chainlesschain 0.162.31 → 0.162.33

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 (170) hide show
  1. package/package.json +2 -2
  2. package/src/assets/web-panel/assets/{AIOps-BqWP6FKu.js → AIOps-3TazCYWE.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-CXwMgOvX.js → ActionButton-DUPN0PST.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-DAebZ4IY.js → Analytics-CemvhkzD.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-CYsqYoME.js → AppLayout-BL_tAU3M.js} +5 -5
  6. package/src/assets/web-panel/assets/{Audit-BbTtX1Nf.js → Audit-Dl9l-cxF.js} +1 -1
  7. package/src/assets/web-panel/assets/{Backup-DgqY2Eb-.js → Backup-BKDDX75m.js} +1 -1
  8. package/src/assets/web-panel/assets/{BaseInput-Cq2ZuSoO.js → BaseInput-CDYePvMI.js} +1 -1
  9. package/src/assets/web-panel/assets/{Chat-D2kqpUyO.js → Chat-CGtR0sg3.js} +5 -5
  10. package/src/assets/web-panel/assets/ChatBubbleRenderer-DZjc9uKn.js +1 -0
  11. package/src/assets/web-panel/assets/{Checkbox-_9swHpyc.js → Checkbox-CwYIHOOo.js} +1 -1
  12. package/src/assets/web-panel/assets/{Codegen-Cr9YbCPl.js → Codegen-CIF5tbtd.js} +1 -1
  13. package/src/assets/web-panel/assets/{Col--wdpCMxx.js → Col-z7d4kxeP.js} +1 -1
  14. package/src/assets/web-panel/assets/{Community-DuFcVnLu.js → Community-DUlDrqF7.js} +1 -1
  15. package/src/assets/web-panel/assets/{Compact-1yzYeT04.js → Compact-CJ1o8QQR.js} +1 -1
  16. package/src/assets/web-panel/assets/{Compliance-Dq3aU9Df.js → Compliance-D3i9d_uO.js} +1 -1
  17. package/src/assets/web-panel/assets/{Cowork-CrWcnIg8.js → Cowork-Wm7JTkfB.js} +2 -2
  18. package/src/assets/web-panel/assets/{Cron-Bh6fKZ0h.js → Cron-B0QnHhZx.js} +2 -2
  19. package/src/assets/web-panel/assets/{Crosschain-8ofPaWVW.js → Crosschain-3yPrnNgd.js} +1 -1
  20. package/src/assets/web-panel/assets/{DID-D3EiYm3w.js → DID-cfdkiDWF.js} +2 -2
  21. package/src/assets/web-panel/assets/{Dashboard-BFjEdFne.js → Dashboard-DFkgM4gT.js} +2 -2
  22. package/src/assets/web-panel/assets/{Dropdown-pYVPcP6O.js → Dropdown-YYWE81DL.js} +1 -1
  23. package/src/assets/web-panel/assets/{EmailListRenderer-zBPodwJ1.js → EmailListRenderer-BXfHK1Bn.js} +1 -1
  24. package/src/assets/web-panel/assets/{FamilyGuardDashboard-CyQTW6PW.js → FamilyGuardDashboard-DInUxJ2G.js} +1 -1
  25. package/src/assets/web-panel/assets/{Federation-Ctaq3zYq.js → Federation-DNUYeFsv.js} +1 -1
  26. package/src/assets/web-panel/assets/{FormItemContext-CWYJCLq1.js → FormItemContext-Cr7eVEBB.js} +1 -1
  27. package/src/assets/web-panel/assets/{GenericCardRenderer-B1g6t9R9.js → GenericCardRenderer-_gF4cmDa.js} +1 -1
  28. package/src/assets/web-panel/assets/{Git-DH-v8iwd.js → Git-BqldmUbO.js} +2 -2
  29. package/src/assets/web-panel/assets/{Governance-jZxXvOs5.js → Governance-BF59ZiQ8.js} +1 -1
  30. package/src/assets/web-panel/assets/{Inference-D07LRghn.js → Inference-Cy7y1eb9.js} +1 -1
  31. package/src/assets/web-panel/assets/{KnowledgeGraph-DnGtRZhx.js → KnowledgeGraph-B3fVocTO.js} +1 -1
  32. package/src/assets/web-panel/assets/{Logs-D2pM9C4W.js → Logs-BDirsUVk.js} +2 -2
  33. package/src/assets/web-panel/assets/{Marketplace-UyIO7C7r.js → Marketplace-GhXpZgp2.js} +1 -1
  34. package/src/assets/web-panel/assets/{McpTools-Bf1gvZPf.js → McpTools-0VvfIhKx.js} +3 -3
  35. package/src/assets/web-panel/assets/{Memory-C1bWj4RN.js → Memory-CJLBgAUT.js} +2 -2
  36. package/src/assets/web-panel/assets/{MobileBridge-C_Ot1H_a.js → MobileBridge-BMedY9Yg.js} +2 -2
  37. package/src/assets/web-panel/assets/MobileProjects-mdohgRlL.js +1 -0
  38. package/src/assets/web-panel/assets/{Mtc-CnzFUz5J.js → Mtc-CgEuUg0g.js} +5 -5
  39. package/src/assets/web-panel/assets/{MtcAudit-CAAh99wz.js → MtcAudit-1pWNe_xi.js} +2 -2
  40. package/src/assets/web-panel/assets/{Multisig-D6IAg6HE.js → Multisig-DPIQ7oZL.js} +3 -3
  41. package/src/assets/web-panel/assets/{NLProgramming-BFMarxb0.js → NLProgramming-W__P_P4Z.js} +1 -1
  42. package/src/assets/web-panel/assets/{Notes-BRp9ro3t.js → Notes-C_MCDhFk.js} +3 -3
  43. package/src/assets/web-panel/assets/{NotificationSettings-C0Au3Cxb.js → NotificationSettings-CDFotapL.js} +1 -1
  44. package/src/assets/web-panel/assets/OrderTableRenderer-Dtht0cEs.js +1 -0
  45. package/src/assets/web-panel/assets/{Organization-DYoxLBRX.js → Organization-D6lMumhD.js} +2 -2
  46. package/src/assets/web-panel/assets/{Overflow-rO8JJWGJ.js → Overflow-BMOvUMW6.js} +1 -1
  47. package/src/assets/web-panel/assets/{P2P-DJleeXIK.js → P2P-DsQTEw1t.js} +2 -2
  48. package/src/assets/web-panel/assets/{PdhVaultBrowser-DM5qghFp.js → PdhVaultBrowser-CncRtN1Z.js} +3 -3
  49. package/src/assets/web-panel/assets/{Permissions-D5v4Beya.js → Permissions-DDC-DkUl.js} +4 -4
  50. package/src/assets/web-panel/assets/{PersonalDataHub-c2ZTX0Pv.js → PersonalDataHub-DVKY_NnT.js} +4 -4
  51. package/src/assets/web-panel/assets/{Pipeline-Crrkyhpz.js → Pipeline-C7oDVTl-.js} +1 -1
  52. package/src/assets/web-panel/assets/{Privacy-DZVyrJKa.js → Privacy-DReGvTEJ.js} +1 -1
  53. package/src/assets/web-panel/assets/{ProjectInit-DKg7J0gz.js → ProjectInit-C-j2dzxJ.js} +2 -2
  54. package/src/assets/web-panel/assets/{ProjectSettings-3ndmTvVH.js → ProjectSettings-DcUsvFnc.js} +2 -2
  55. package/src/assets/web-panel/assets/Projects-jSjWnmr6.js +1 -0
  56. package/src/assets/web-panel/assets/{Providers-BeqBVMhB.js → Providers-DIpohWG5.js} +1 -1
  57. package/src/assets/web-panel/assets/{QuickAsk-DKAAxzuA.js → QuickAsk-DdvLtpEU.js} +1 -1
  58. package/src/assets/web-panel/assets/{Recommend-Byu7IGei.js → Recommend-DPAi2zo3.js} +1 -1
  59. package/src/assets/web-panel/assets/{Reputation-BKhWAmCu.js → Reputation-DJD7qXSI.js} +1 -1
  60. package/src/assets/web-panel/assets/{Row-BFtn11O6.js → Row-XERdPDHk.js} +1 -1
  61. package/src/assets/web-panel/assets/{RssFeed-D5a0PT0k.js → RssFeed-Cl_VlCLg.js} +3 -3
  62. package/src/assets/web-panel/assets/{Search-DAkuaZNe.js → Search-C-poG9P5.js} +1 -1
  63. package/src/assets/web-panel/assets/{Security-C79Ml2Ms.js → Security-DjjCrw8v.js} +2 -2
  64. package/src/assets/web-panel/assets/{Services-BBk_jH6-.js → Services-BuWeB4YJ.js} +2 -2
  65. package/src/assets/web-panel/assets/{Skeleton-Cy0VvL0M.js → Skeleton-VZXOKwC_.js} +1 -1
  66. package/src/assets/web-panel/assets/Skills-B76ONTfP.js +1 -0
  67. package/src/assets/web-panel/assets/{Sla-CbX1f8xN.js → Sla-DIj1KREq.js} +1 -1
  68. package/src/assets/web-panel/assets/{SpeechSettings-BIkoUjws.js → SpeechSettings-BrAp3Yk3.js} +1 -1
  69. package/src/assets/web-panel/assets/{SyncSettings-DG6Swk7G.js → SyncSettings--mJcpccF.js} +2 -2
  70. package/src/assets/web-panel/assets/Tasks-DM8cMr83.js +1 -0
  71. package/src/assets/web-panel/assets/{Templates-AaJPeCIz.js → Templates-kOBK6m1Z.js} +1 -1
  72. package/src/assets/web-panel/assets/{Tenant-jVFRofww.js → Tenant-BjSzYPzn.js} +1 -1
  73. package/src/assets/web-panel/assets/{Terminal-DHBMzfK6.js → Terminal-DwpY-Ay7.js} +2 -2
  74. package/src/assets/web-panel/assets/{TimelineRenderer-9RFfOHSI.js → TimelineRenderer-aoI0DazM.js} +1 -1
  75. package/src/assets/web-panel/assets/{Tokens-ZTfwuABF.js → Tokens-YwE0LqSZ.js} +1 -1
  76. package/src/assets/web-panel/assets/{Trigger-Xo7uZNQs.js → Trigger-CwSKzvlX.js} +1 -1
  77. package/src/assets/web-panel/assets/{Trust-C0cTPYvn.js → Trust-B__Jqdzn.js} +1 -1
  78. package/src/assets/web-panel/assets/{UkeySign-DmMKio71.js → UkeySign-mty0jwmx.js} +1 -1
  79. package/src/assets/web-panel/assets/{VideoEditing-DP7B-oGT.js → VideoEditing-Ddsx_OQ6.js} +1 -1
  80. package/src/assets/web-panel/assets/{Wallet-B1kZDARo.js → Wallet-D4Q8yXZm.js} +4 -4
  81. package/src/assets/web-panel/assets/{WebAuthn-Bo5kBx27.js → WebAuthn-CLUaKUr5.js} +5 -5
  82. package/src/assets/web-panel/assets/{WorkflowEditor-DGI9SNHH.js → WorkflowEditor-Di5pOaeC.js} +1 -1
  83. package/src/assets/web-panel/assets/{chat-y97W1CIG.js → chat-CELatHkT.js} +1 -1
  84. package/src/assets/web-panel/assets/{colors-DtTNo0sH.js → colors-CawDLjXV.js} +1 -1
  85. package/src/assets/web-panel/assets/{compact-item-D0q0exuS.js → compact-item-DeMp-K0j.js} +1 -1
  86. package/src/assets/web-panel/assets/{createContext-D7pLFs2I.js → createContext-zY9kXivd.js} +1 -1
  87. package/src/assets/web-panel/assets/devWarning-zLjV7g6r.js +1 -0
  88. package/src/assets/web-panel/assets/{hasIn-CXjG5B2j.js → hasIn-VEBMW8E4.js} +1 -1
  89. package/src/assets/web-panel/assets/{index-TrBGgrwG.js → index-8kqE_cVD.js} +1 -1
  90. package/src/assets/web-panel/assets/{index-D_4WcI1V.js → index-B8AZpx7d.js} +1 -1
  91. package/src/assets/web-panel/assets/{index-YWOEx3rP.js → index-BFc0vBN9.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-BqVjUN8b.js → index-BVkrfyuk.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-BnLrbXDA.js → index-BfGGKoo8.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-CKrbutAQ.js → index-BjctklSd.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-CFsPe2N7.js → index-BqJ2r12F.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-CSdhC7Qo.js → index-C0GhuYLk.js} +1 -1
  97. package/src/assets/web-panel/assets/index-CDtUWCtX.js +1 -0
  98. package/src/assets/web-panel/assets/{index-BO644Q4S.js → index-CHqvj9uz.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-gFLQe31v.js → index-CHxHLv2b.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BgyrM0UN.js → index-CWbbB1MI.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-1dwtkcJv.js → index-CbJZzK9B.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-B3y_4OdG.js → index-CfZV3FXN.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-Dr45Nm9V.js → index-Cr7lnIeI.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CkGFqlYX.js → index-CtLZammH.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-6np5ESBM.js → index-CtoauqWt.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-BU944DeT.js → index-CyeYs7SG.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-POaFzYGS.js → index-DALuVdhu.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DjCawXk1.js → index-DClGYjBM.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-8jxbZupG.js → index-DPHe9NYG.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-_3wPBMKt.js → index-DSiL_W2n.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Cbqu804A.js → index-DXNe_zIP.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-EaIfumgW.js → index-DhsfyHcg.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-BzCPx1cq.js → index-Dna2psGz.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-kvV0f4tV.js → index-GRNVdvoA.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-BdhEYW2a.js → index-JseP3-5X.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-aarO4HT9.js → index-KcOEkUCM.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BgmvrPJH.js → index-S9JZDSaa.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DY6KLlgG.js → index-SrQIPYq8.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-Ct6xtKkc.js → index-TfXODan7.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-B_hjkMtX.js → index-V3K9gvKR.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-4mWZhCzz.js → index-VJnHvkv2.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-BJUf19Wd.js → index-XFyv3Sg_.js} +3 -3
  123. package/src/assets/web-panel/assets/{index-B4dPdrvC.js → index-b3ZuAreb.js} +1 -1
  124. package/src/assets/web-panel/assets/index-d_RPqH7u.js +1 -0
  125. package/src/assets/web-panel/assets/{index-BPXhU-jp.js → index-fBNVDEf2.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-bVJvqDAz.js → index-u_1aiNTA.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-qoB3whR9.js → index-vaD1iHg5.js} +1 -1
  128. package/src/assets/web-panel/assets/{initDefaultProps-BnXISaAa.js → initDefaultProps-Sd7Eayz4.js} +1 -1
  129. package/src/assets/web-panel/assets/{motion-ChY7C0zJ.js → motion-DlToY72q.js} +1 -1
  130. package/src/assets/web-panel/assets/{move-ByFZMFM5.js → move-DvS7EmAP.js} +1 -1
  131. package/src/assets/web-panel/assets/{omit-BYeliY1H.js → omit-CzLq4QKW.js} +1 -1
  132. package/src/assets/web-panel/assets/{pickAttrs-B9dcAKnu.js → pickAttrs-BcM75Jx_.js} +1 -1
  133. package/src/assets/web-panel/assets/{placementArrow-D3F_txz7.js → placementArrow-B7xXXiwd.js} +1 -1
  134. package/src/assets/web-panel/assets/{responsiveObserve-ClkwY7wS.js → responsiveObserve-CrYPRB-g.js} +1 -1
  135. package/src/assets/web-panel/assets/{slide-BNgy2Eea.js → slide-CSYTtsRt.js} +1 -1
  136. package/src/assets/web-panel/assets/{statusUtils-Bv3heMCD.js → statusUtils-CeSuOVT_.js} +1 -1
  137. package/src/assets/web-panel/assets/{styleChecker-DVdlHbQm.js → styleChecker-KiQethca.js} +1 -1
  138. package/src/assets/web-panel/assets/{useFlexGapSupport-alrRY5BK.js → useFlexGapSupport-CSQnQdiv.js} +1 -1
  139. package/src/assets/web-panel/assets/{useFs-CcVh0-Vu.js → useFs-Br8Kr1pr.js} +1 -1
  140. package/src/assets/web-panel/assets/{usePersonalDataHub-CkkHPhyq.js → usePersonalDataHub-DGJtDcMm.js} +1 -1
  141. package/src/assets/web-panel/assets/{vnode-DWi0X9WN.js → vnode-C-jVtGka.js} +1 -1
  142. package/src/assets/web-panel/assets/{zoom-DCbqxxLH.js → zoom-CeWySTPF.js} +1 -1
  143. package/src/assets/web-panel/index.html +1 -1
  144. package/src/commands/agent.js +47 -0
  145. package/src/commands/checkpoint.js +253 -53
  146. package/src/commands/compact.js +150 -0
  147. package/src/commands/goal.js +417 -0
  148. package/src/commands/hub.js +7 -0
  149. package/src/harness/prompt-compressor.js +71 -1
  150. package/src/index.js +4 -0
  151. package/src/lib/agent-core.js +1 -0
  152. package/src/lib/checkpoint-store.js +523 -0
  153. package/src/lib/goal-assess.js +228 -0
  154. package/src/lib/goal-context.js +87 -0
  155. package/src/lib/goal-store.js +341 -0
  156. package/src/repl/agent-repl.js +43 -7
  157. package/src/runtime/agent-core.js +267 -1
  158. package/src/runtime/headless-runner.js +147 -0
  159. package/src/runtime/headless-stream.js +34 -0
  160. package/src/runtime/mcp-config.js +139 -0
  161. package/src/runtime/policies/agent-policy.js +1 -0
  162. package/src/assets/web-panel/assets/ChatBubbleRenderer-C-svYkrC.js +0 -1
  163. package/src/assets/web-panel/assets/MobileProjects-zr-PpsT_.js +0 -1
  164. package/src/assets/web-panel/assets/OrderTableRenderer-ISp6btRY.js +0 -1
  165. package/src/assets/web-panel/assets/Projects-ll5wnj2L.js +0 -1
  166. package/src/assets/web-panel/assets/Skills-OQNky3uI.js +0 -1
  167. package/src/assets/web-panel/assets/Tasks-C9R8sgyi.js +0 -1
  168. package/src/assets/web-panel/assets/devWarning-BDK34w0I.js +0 -1
  169. package/src/assets/web-panel/assets/index-B6SaRuCI.js +0 -1
  170. package/src/assets/web-panel/assets/index-B9ekWb3I.js +0 -1
@@ -0,0 +1,417 @@
1
+ /**
2
+ * cc goal — cross-session persistent goals / OKRs.
3
+ *
4
+ * cc goal set <objective> [--title <t>] [--kr <text>...] create a goal
5
+ * cc goal list [--status active] [--json] list goals
6
+ * cc goal show <id> [--json] show one goal
7
+ * cc goal kr add <id> <text> [--target <n>] add a key result
8
+ * cc goal kr set <id> <krId> [--current <n>] [--done] update a key result
9
+ * cc goal progress <id> [--pct <n>] [--note <text>] record progress
10
+ * cc goal link <id> [sessionId] / unlink <id> [sessionId]
11
+ * cc goal pause|resume|close|abandon|rm <id> lifecycle
12
+ * cc goal active [--session <id>] [--json] the bound goal
13
+ *
14
+ * A goal is a long-lived objective the agent advances toward across sessions —
15
+ * distinct from `cc session` (short context), `cc memory` (facts),
16
+ * `cc planmode` (one run's plan) and `cc workflow` (execution state). When a
17
+ * goal is active it is injected into the agent loop each turn (goal-context.js).
18
+ */
19
+
20
+ import chalk from "chalk";
21
+ import { logger } from "../lib/logger.js";
22
+
23
+ const STATUS_COLOR = {
24
+ active: chalk.green,
25
+ paused: chalk.yellow,
26
+ done: chalk.cyan,
27
+ abandoned: chalk.gray,
28
+ };
29
+
30
+ function fmtStatus(s) {
31
+ return (STATUS_COLOR[s] || chalk.white)(s);
32
+ }
33
+
34
+ function printGoal(g, { verbose } = {}) {
35
+ logger.log(
36
+ `${chalk.bold(g.id)} ${fmtStatus(g.status)} ${chalk.gray(`${g.progress}%`)}`,
37
+ );
38
+ logger.log(` ${g.objective}`);
39
+ if (g.title && g.title !== g.objective) {
40
+ logger.log(chalk.gray(` title: ${g.title}`));
41
+ }
42
+ const open = (g.keyResults || []).filter((k) => !k.done).length;
43
+ const total = (g.keyResults || []).length;
44
+ if (total > 0) {
45
+ logger.log(chalk.gray(` key results: ${total - open}/${total} done`));
46
+ if (verbose) {
47
+ for (const kr of g.keyResults) {
48
+ const mark = kr.done ? chalk.green("✓") : chalk.gray("○");
49
+ const target = kr.target != null ? ` [${kr.current}/${kr.target}]` : "";
50
+ logger.log(` ${mark} ${chalk.dim(kr.id)} ${kr.text}${target}`);
51
+ }
52
+ }
53
+ }
54
+ if (verbose) {
55
+ if (g.linkedSessions?.length) {
56
+ logger.log(chalk.gray(` sessions: ${g.linkedSessions.join(", ")}`));
57
+ }
58
+ if (g.notes?.length) {
59
+ logger.log(chalk.gray(` notes:`));
60
+ for (const n of g.notes.slice(-5)) {
61
+ logger.log(
62
+ chalk.gray(` [${n.at.slice(0, 16)}] (${n.by}) ${n.text}`),
63
+ );
64
+ }
65
+ }
66
+ logger.log(
67
+ chalk.gray(` created: ${g.createdAt} updated: ${g.updatedAt}`),
68
+ );
69
+ }
70
+ }
71
+
72
+ function fail(action, err) {
73
+ logger.error(chalk.red(`goal ${action} failed: ${err.message}`));
74
+ process.exitCode = 1;
75
+ }
76
+
77
+ export function registerGoalCommand(program) {
78
+ const goal = program
79
+ .command("goal")
80
+ .description("Cross-session persistent goals / OKRs");
81
+
82
+ // ── set (create) ──────────────────────────────────────────────────────
83
+ goal
84
+ .command("set <objective>")
85
+ .alias("add")
86
+ .description("Create a goal with an objective (and optional key results)")
87
+ .option("--title <title>", "Short title (defaults to the objective)")
88
+ .option(
89
+ "--kr <text>",
90
+ "Key result (repeatable)",
91
+ (v, acc) => (acc.push(v), acc),
92
+ [],
93
+ )
94
+ .option("--json", "Output as JSON")
95
+ .action(async (objective, options) => {
96
+ try {
97
+ const { createGoal } = await import("../lib/goal-store.js");
98
+ const g = createGoal({
99
+ objective,
100
+ title: options.title,
101
+ keyResults: options.kr || [],
102
+ });
103
+ if (options.json) {
104
+ console.log(JSON.stringify(g, null, 2));
105
+ return;
106
+ }
107
+ logger.log(chalk.green(`✓ goal ${chalk.bold(g.id)} created`));
108
+ printGoal(g, { verbose: true });
109
+ logger.log(
110
+ chalk.gray(
111
+ ` bind to a run with: cc agent --goal ${g.id} (or it auto-binds when it is the only active goal)`,
112
+ ),
113
+ );
114
+ } catch (err) {
115
+ fail("set", err);
116
+ }
117
+ });
118
+
119
+ // ── list ──────────────────────────────────────────────────────────────
120
+ goal
121
+ .command("list")
122
+ .alias("ls")
123
+ .description("List goals (newest first)")
124
+ .option("--status <status>", "Filter: active|paused|done|abandoned")
125
+ .option("--json", "Output as JSON")
126
+ .action(async (options) => {
127
+ try {
128
+ const { listGoals } = await import("../lib/goal-store.js");
129
+ const all = listGoals({ status: options.status });
130
+ if (options.json) {
131
+ console.log(JSON.stringify(all, null, 2));
132
+ return;
133
+ }
134
+ if (all.length === 0) {
135
+ logger.log(
136
+ chalk.gray("No goals. Create one: cc goal set <objective>"),
137
+ );
138
+ return;
139
+ }
140
+ for (const g of all) {
141
+ const open = (g.keyResults || []).filter((k) => !k.done).length;
142
+ const total = (g.keyResults || []).length;
143
+ const krInfo = total
144
+ ? chalk.gray(` ${total - open}/${total} KR`)
145
+ : "";
146
+ // Soft drift hint: active goal with no progress recorded in 14+ days.
147
+ const stale = isStale(g);
148
+ logger.log(
149
+ `${chalk.cyan(g.id.padEnd(24))} ${fmtStatus(g.status).padEnd(18)} ${chalk.gray(`${String(g.progress).padStart(3)}%`)}${krInfo}` +
150
+ (stale ? chalk.yellow(" ⚠ stale") : "") +
151
+ `\n ${chalk.gray(truncate(g.objective, 80))}`,
152
+ );
153
+ }
154
+ } catch (err) {
155
+ fail("list", err);
156
+ }
157
+ });
158
+
159
+ // ── show ──────────────────────────────────────────────────────────────
160
+ goal
161
+ .command("show <id>")
162
+ .description("Show a goal in full")
163
+ .option("--json", "Output as JSON")
164
+ .action(async (id, options) => {
165
+ try {
166
+ const { getGoal } = await import("../lib/goal-store.js");
167
+ const g = getGoal(id);
168
+ if (!g) {
169
+ logger.error(chalk.red(`no such goal: ${id}`));
170
+ process.exitCode = 1;
171
+ return;
172
+ }
173
+ if (options.json) {
174
+ console.log(JSON.stringify(g, null, 2));
175
+ return;
176
+ }
177
+ printGoal(g, { verbose: true });
178
+ } catch (err) {
179
+ fail("show", err);
180
+ }
181
+ });
182
+
183
+ // ── kr (key results) ──────────────────────────────────────────────────
184
+ const kr = goal.command("kr").description("Manage key results");
185
+
186
+ kr.command("add <id> <text>")
187
+ .description("Add a key result to a goal")
188
+ .option("--target <n>", "Numeric target for this key result")
189
+ .option("--json", "Output as JSON")
190
+ .action(async (id, text, options) => {
191
+ try {
192
+ const { addKeyResult } = await import("../lib/goal-store.js");
193
+ const g = addKeyResult(id, text, {
194
+ target: options.target != null ? Number(options.target) : null,
195
+ });
196
+ if (options.json) return void console.log(JSON.stringify(g, null, 2));
197
+ logger.log(chalk.green(`✓ key result added to ${id}`));
198
+ printGoal(g, { verbose: true });
199
+ } catch (err) {
200
+ fail("kr add", err);
201
+ }
202
+ });
203
+
204
+ kr.command("set <id> <krId>")
205
+ .description("Update a key result's current value and/or mark it done")
206
+ .option("--current <n>", "Set the current value")
207
+ .option("--done", "Mark this key result done")
208
+ .option("--json", "Output as JSON")
209
+ .action(async (id, krId, options) => {
210
+ try {
211
+ const { setKeyResult } = await import("../lib/goal-store.js");
212
+ const g = setKeyResult(id, krId, {
213
+ current: options.current != null ? Number(options.current) : null,
214
+ done: options.done ? true : null,
215
+ });
216
+ if (options.json) return void console.log(JSON.stringify(g, null, 2));
217
+ logger.log(chalk.green(`✓ key result ${krId} updated`));
218
+ printGoal(g, { verbose: true });
219
+ } catch (err) {
220
+ fail("kr set", err);
221
+ }
222
+ });
223
+
224
+ // ── progress ──────────────────────────────────────────────────────────
225
+ goal
226
+ .command("progress <id>")
227
+ .description("Record progress: set a percentage and/or append a note")
228
+ .option("--pct <n>", "Progress percentage (0–100)")
229
+ .option("--note <text>", "Progress note")
230
+ .option("--json", "Output as JSON")
231
+ .action(async (id, options) => {
232
+ try {
233
+ const { recordProgress } = await import("../lib/goal-store.js");
234
+ if (options.pct == null && !options.note) {
235
+ logger.error(
236
+ chalk.red(
237
+ "nothing to record — pass --pct <n> and/or --note <text>",
238
+ ),
239
+ );
240
+ process.exitCode = 1;
241
+ return;
242
+ }
243
+ const g = recordProgress(id, {
244
+ pct: options.pct,
245
+ note: options.note,
246
+ by: "user",
247
+ });
248
+ if (options.json) return void console.log(JSON.stringify(g, null, 2));
249
+ logger.log(
250
+ chalk.green(`✓ progress recorded for ${id} (${g.progress}%)`),
251
+ );
252
+ } catch (err) {
253
+ fail("progress", err);
254
+ }
255
+ });
256
+
257
+ // ── link / unlink ─────────────────────────────────────────────────────
258
+ goal
259
+ .command("link <id> [sessionId]")
260
+ .description("Attach a session to a goal (defaults to the latest session)")
261
+ .option("--json", "Output as JSON")
262
+ .action(async (id, sessionId, options) => {
263
+ try {
264
+ const { linkSession } = await import("../lib/goal-store.js");
265
+ const sid = sessionId || (await latestSessionId());
266
+ if (!sid) {
267
+ logger.error(
268
+ chalk.red("no session id given and none could be inferred"),
269
+ );
270
+ process.exitCode = 1;
271
+ return;
272
+ }
273
+ const g = linkSession(id, sid);
274
+ if (options.json) return void console.log(JSON.stringify(g, null, 2));
275
+ logger.log(chalk.green(`✓ linked session ${sid} to ${id}`));
276
+ } catch (err) {
277
+ fail("link", err);
278
+ }
279
+ });
280
+
281
+ goal
282
+ .command("unlink <id> [sessionId]")
283
+ .description("Detach a session from a goal")
284
+ .option("--json", "Output as JSON")
285
+ .action(async (id, sessionId, options) => {
286
+ try {
287
+ const { unlinkSession } = await import("../lib/goal-store.js");
288
+ const sid = sessionId || (await latestSessionId());
289
+ const g = unlinkSession(id, sid);
290
+ if (options.json) return void console.log(JSON.stringify(g, null, 2));
291
+ logger.log(chalk.green(`✓ unlinked session ${sid} from ${id}`));
292
+ } catch (err) {
293
+ fail("unlink", err);
294
+ }
295
+ });
296
+
297
+ // ── lifecycle ─────────────────────────────────────────────────────────
298
+ const lifecycle = [
299
+ ["pause", "paused", "paused"],
300
+ ["resume", "active", "resumed"],
301
+ ["close", "done", "closed (done)"],
302
+ ["abandon", "abandoned", "abandoned"],
303
+ ];
304
+ for (const [cmd, status, verb] of lifecycle) {
305
+ goal
306
+ .command(`${cmd} <id>`)
307
+ .description(`Mark a goal ${verb}`)
308
+ .option("--json", "Output as JSON")
309
+ .action(async (id, options) => {
310
+ try {
311
+ const { setStatus } = await import("../lib/goal-store.js");
312
+ const g = setStatus(id, status);
313
+ if (options.json) return void console.log(JSON.stringify(g, null, 2));
314
+ logger.log(chalk.green(`✓ goal ${id} ${verb}`));
315
+ } catch (err) {
316
+ fail(cmd, err);
317
+ }
318
+ });
319
+ }
320
+
321
+ goal
322
+ .command("rm <id>")
323
+ .alias("delete")
324
+ .description("Delete a goal")
325
+ .option("--force", "Skip confirmation")
326
+ .action(async (id, options) => {
327
+ try {
328
+ const { deleteGoal } = await import("../lib/goal-store.js");
329
+ if (!options.force && process.stdin.isTTY) {
330
+ const { confirm } = await import("@inquirer/prompts");
331
+ const ok = await confirm({
332
+ message: `Delete goal ${id}?`,
333
+ default: false,
334
+ }).catch(() => false);
335
+ if (!ok) {
336
+ logger.log(chalk.gray("Aborted."));
337
+ return;
338
+ }
339
+ }
340
+ const existed = deleteGoal(id);
341
+ if (!existed) {
342
+ logger.error(chalk.red(`no such goal: ${id}`));
343
+ process.exitCode = 1;
344
+ return;
345
+ }
346
+ logger.log(chalk.green(`✓ deleted ${id}`));
347
+ } catch (err) {
348
+ fail("rm", err);
349
+ }
350
+ });
351
+
352
+ // ── active (what's bound to a run) ────────────────────────────────────
353
+ goal
354
+ .command("active")
355
+ .description("Show the goal that would bind to a run (resolution order)")
356
+ .option("--session <id>", "Resolve as if this session were running")
357
+ .option("--json", "Output as JSON")
358
+ .action(async (options) => {
359
+ try {
360
+ const { resolveActiveGoal } = await import("../lib/goal-store.js");
361
+ const g = resolveActiveGoal({ sessionId: options.session });
362
+ if (options.json) {
363
+ console.log(JSON.stringify(g || null, null, 2));
364
+ return;
365
+ }
366
+ if (!g) {
367
+ logger.log(
368
+ chalk.gray(
369
+ "No goal would auto-bind (0 active goals, or several active and none linked — pass --goal <id> explicitly).",
370
+ ),
371
+ );
372
+ return;
373
+ }
374
+ logger.log(chalk.bold("Bound goal:"));
375
+ printGoal(g, { verbose: true });
376
+ } catch (err) {
377
+ fail("active", err);
378
+ }
379
+ });
380
+ }
381
+
382
+ function truncate(s, n) {
383
+ s = String(s || "");
384
+ return s.length > n ? `${s.slice(0, n - 1)}…` : s;
385
+ }
386
+
387
+ /** Active goal with no progress recorded in 14+ days = soft drift hint. */
388
+ function isStale(g) {
389
+ if (g.status !== "active") return false;
390
+ const last = g.drift?.lastProgressAt || g.createdAt;
391
+ if (!last) return false;
392
+ const ageMs = Date.now() - new Date(last).getTime();
393
+ return ageMs > 14 * 24 * 60 * 60 * 1000;
394
+ }
395
+
396
+ /** Best-effort: the most recent session id, for `link` without an explicit id. */
397
+ async function latestSessionId() {
398
+ try {
399
+ const fs = await import("node:fs");
400
+ const path = await import("node:path");
401
+ const { sessionPath } = await import("../harness/jsonl-session-store.js");
402
+ // sessionPath("x") → <home>/sessions/x.jsonl — derive the dir from it.
403
+ const dir = path.dirname(sessionPath("x"));
404
+ if (!fs.existsSync(dir)) return null;
405
+ const files = fs
406
+ .readdirSync(dir)
407
+ .filter((f) => f.endsWith(".jsonl"))
408
+ .map((f) => ({
409
+ id: f.slice(0, -6),
410
+ mtime: fs.statSync(path.join(dir, f)).mtimeMs,
411
+ }))
412
+ .sort((a, b) => b.mtime - a.mtime);
413
+ return files[0]?.id || null;
414
+ } catch {
415
+ return null;
416
+ }
417
+ }
@@ -351,6 +351,9 @@ async function cmdSyncAdapter(name, options) {
351
351
  // sources (wechat-pc), --db-path as an explicit alias for the DB file.
352
352
  if (options.key) opts.key = String(options.key);
353
353
  if (options.dbPath) opts.dbPath = String(options.dbPath);
354
+ // QQ NT (qq-pc): the SQLCipher passphrase from qq-win-db-key (ASCII, e.g.
355
+ // "5{sww#,6aq=)8=A@"). Routes qq-pc through the decrypt+parse sidecar.
356
+ if (options.passphrase) opts.passphrase = String(options.passphrase);
354
357
  // Cookie-mode sources (weread): pass the login cookie through to the adapter.
355
358
  if (options.cookie) opts.cookie = String(options.cookie);
356
359
  const report = await hub.registry.syncAdapter(name, opts);
@@ -2137,6 +2140,10 @@ export function registerHubCommand(program) {
2137
2140
  "--key <hex>",
2138
2141
  "SQLCipher key (64-hex) for encrypted local DBs (e.g. wechat-pc)",
2139
2142
  )
2143
+ .option(
2144
+ "--passphrase <key>",
2145
+ 'QQ NT SQLCipher passphrase from qq-win-db-key (ASCII, e.g. "5{sww#,6aq=)8=A@") — decrypts + parses qq-pc',
2146
+ )
2140
2147
  .option(
2141
2148
  "--cookie <cookie>",
2142
2149
  "Login cookie for cookie-mode sources (e.g. weread)",
@@ -140,6 +140,70 @@ export function adaptiveThresholds(contextWindow) {
140
140
  return result;
141
141
  }
142
142
 
143
+ /**
144
+ * Repair tool-call/tool-result pairing after lossy compaction.
145
+ *
146
+ * Strict chat APIs reject a `tool` message whose `tool_call_id` has no
147
+ * preceding assistant `tool_calls`, and (for Anthropic) an assistant
148
+ * `tool_calls` with no following result. Count-based truncation / per-message
149
+ * snipping can orphan either side. This pass drops assistant tool_calls that
150
+ * lost their result, then drops tool results whose call was removed — leaving a
151
+ * sequence every provider will accept. Assistant messages whose calls are all
152
+ * orphaned are kept as plain text (if any) or dropped.
153
+ *
154
+ * @param {Array<object>} messages
155
+ * @returns {Array<object>} a new, balanced array
156
+ */
157
+ export function sanitizeToolPairs(messages) {
158
+ if (!Array.isArray(messages)) return messages;
159
+
160
+ const resultIds = new Set(
161
+ messages
162
+ .filter((m) => m && m.role === "tool" && m.tool_call_id)
163
+ .map((m) => m.tool_call_id),
164
+ );
165
+
166
+ // Pass 1 — drop assistant tool_calls that have no matching tool result.
167
+ const stage1 = [];
168
+ for (const m of messages) {
169
+ if (
170
+ m &&
171
+ m.role === "assistant" &&
172
+ Array.isArray(m.tool_calls) &&
173
+ m.tool_calls.length
174
+ ) {
175
+ const kept = m.tool_calls.filter((tc) => tc && resultIds.has(tc.id));
176
+ if (kept.length === m.tool_calls.length) {
177
+ stage1.push(m);
178
+ } else if (kept.length > 0) {
179
+ stage1.push({ ...m, tool_calls: kept });
180
+ } else {
181
+ // No surviving calls: keep the assistant text if any, else drop it.
182
+ const { tool_calls: _drop, ...rest } = m;
183
+ if (rest.content && String(rest.content).trim()) stage1.push(rest);
184
+ }
185
+ } else {
186
+ stage1.push(m);
187
+ }
188
+ }
189
+
190
+ // Pass 2 — drop tool results whose call was removed in pass 1.
191
+ const survivingCallIds = new Set(
192
+ stage1
193
+ .filter((m) => m && m.role === "assistant" && Array.isArray(m.tool_calls))
194
+ .flatMap((m) => m.tool_calls.map((tc) => tc.id)),
195
+ );
196
+ return stage1.filter(
197
+ (m) =>
198
+ !(
199
+ m &&
200
+ m.role === "tool" &&
201
+ m.tool_call_id &&
202
+ !survivingCallIds.has(m.tool_call_id)
203
+ ),
204
+ );
205
+ }
206
+
143
207
  export class PromptCompressor {
144
208
  constructor(options = {}) {
145
209
  if (
@@ -217,6 +281,13 @@ export class PromptCompressor {
217
281
  }
218
282
  }
219
283
 
284
+ // Tool-pair repair (opt-in) — callers compacting tool-laden histories
285
+ // (e.g. the headless agent loop) pass this so truncation/snip never leaves
286
+ // an orphaned tool result or unanswered tool_call for a strict API.
287
+ if (options.preserveToolPairs) {
288
+ result = sanitizeToolPairs(result);
289
+ }
290
+
220
291
  const compressedTokens = estimateMessagesTokens(result);
221
292
  const stats = {
222
293
  strategy: applied.join("+") || "none",
@@ -415,7 +486,6 @@ export class PromptCompressor {
415
486
  }
416
487
  }
417
488
 
418
-
419
489
  // =====================================================================
420
490
  // Prompt Compressor V2 governance overlay
421
491
  // =====================================================================
package/src/index.js CHANGED
@@ -58,6 +58,8 @@ import { registerRCacheCommand } from "./commands/rcache.js";
58
58
  import { registerSessionCommand } from "./commands/session.js";
59
59
  import { registerCostCommand } from "./commands/cost.js";
60
60
  import { registerCheckpointCommand } from "./commands/checkpoint.js";
61
+ import { registerGoalCommand } from "./commands/goal.js";
62
+ import { registerCompactCommand } from "./commands/compact.js";
61
63
  import { registerConsolCommand } from "./commands/consol.js";
62
64
  import { registerImportCommand } from "./commands/import.js";
63
65
  import { registerExportCommand } from "./commands/export.js";
@@ -452,6 +454,8 @@ export function createProgram(opts = {}) {
452
454
  registerSessionCommand(program);
453
455
  registerCostCommand(program);
454
456
  registerCheckpointCommand(program);
457
+ registerGoalCommand(program);
458
+ registerCompactCommand(program);
455
459
  registerConsolCommand(program);
456
460
 
457
461
  // Phase 2: Knowledge & content management
@@ -24,4 +24,5 @@ export {
24
24
  agentLoop,
25
25
  formatToolArgs,
26
26
  getActiveMcpServers,
27
+ _accumulateOllamaStream,
27
28
  } from "../runtime/agent-core.js";