@cleocode/cleo 2026.10.4 → 2026.10.5
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.
- package/README.md +7 -0
- package/dist/cli/{adapter-LVXHFBC4.js → adapter-OUQRSFZL.js} +10 -9
- package/dist/cli/{add-WUAV7LDT.js → add-4SRRJL4U.js} +18 -18
- package/dist/cli/{add-batch-U2DLKAQC.js → add-batch-TSWICA5J.js} +12 -11
- package/dist/cli/admin-L3F6CDYH.js +1428 -0
- package/dist/cli/{admin-I7BQYVZD.js → admin-YMU55YCU.js} +10 -9
- package/dist/cli/{adr-K2THMQBS.js → adr-XESRMFMP.js} +10 -9
- package/dist/cli/{agent-WQ6XY2DW.js → agent-TAFPIYUU.js} +66 -28
- package/dist/cli/{agent-outputs-BJIYLVTU.js → agent-outputs-HVJJIPS4.js} +3 -3
- package/dist/cli/{analyze-PGQZWGOC.js → analyze-YQ22QVGW.js} +10 -9
- package/dist/cli/{archive-5LZPF7C3.js → archive-W5XX6AH7.js} +10 -9
- package/dist/cli/{archive-stats-U6CYC6JM.js → archive-stats-HP2KPAJU.js} +10 -9
- package/dist/cli/attention-7JBDCRZX.js +124 -0
- package/dist/cli/{attention-SOURWCNI.js → attention-ZXZANHKC.js} +13 -12
- package/dist/cli/{audit-FO2Y4LH2.js → audit-ICA2SEFN.js} +2 -2
- package/dist/cli/{auth-ED7TAIXI.js → auth-DXIG5OG7.js} +5 -5
- package/dist/cli/{backfill-32TRAYRD.js → backfill-LBSYBWLR.js} +2 -2
- package/dist/cli/{backup-LEJMZJKL.js → backup-NUGBZ7NA.js} +17 -16
- package/dist/cli/{backup-inspect-6HPLUEI2.js → backup-inspect-PDRXI45A.js} +3 -3
- package/dist/cli/{backup-recover-2BTYBZU2.js → backup-recover-TVKAPERB.js} +3 -3
- package/dist/cli/{blockers-5JULUJTV.js → blockers-ZOPCGHDW.js} +10 -9
- package/dist/cli/{brain-273N3FW4.js → brain-EJOBKL4A.js} +9 -12
- package/dist/cli/{briefing-7H6OLECX.js → briefing-RDQJ6WHS.js} +11 -10
- package/dist/cli/{caamp-MFQVN6VU.js → caamp-Z3XPKEHB.js} +2 -2
- package/dist/cli/{cancel-SCMJTXZB.js → cancel-S7EHLCJN.js} +10 -9
- package/dist/cli/{cant-46XCUP4P.js → cant-CHNN6O57.js} +2 -2
- package/dist/cli/{changeset-32NMBGG2.js → changeset-RYPHPN2B.js} +4 -6
- package/dist/cli/check-C67YAU7W.js +759 -0
- package/dist/cli/{check-RWJLBCI2.js → check-DHMURGHC.js} +30 -13
- package/dist/cli/{checkpoint-37HMMKD7.js → checkpoint-UWDFOGYQ.js} +3 -3
- package/dist/cli/{chunk-NRKWJLMS.js → chunk-22YPFZYB.js} +2 -2
- package/dist/cli/{chunk-I3CRQQAD.js → chunk-2MGFDMDF.js} +84 -37
- package/dist/cli/{chunk-BCEXRFA2.js → chunk-4JYHPP4C.js} +2 -2
- package/dist/cli/{chunk-A2IUEIM5.js → chunk-4PEODTHY.js} +2 -2
- package/dist/cli/{chunk-3ZO3M37V.js → chunk-4RGSNUUP.js} +118 -170
- package/dist/cli/{chunk-AWCQH2W5.js → chunk-4VASFLUW.js} +2 -2
- package/dist/cli/{chunk-BPEVD37G.js → chunk-5PNI276X.js} +2 -2
- package/dist/cli/{chunk-OGV57L4J.js → chunk-6N6WGLXE.js} +6 -2
- package/dist/cli/{chunk-KHB52JNB.js → chunk-75UH3BLS.js} +4 -3
- package/dist/cli/{chunk-5ZFFUFH7.js → chunk-7ACK4EIN.js} +2 -2
- package/dist/cli/{chunk-MNJRLSEQ.js → chunk-7NMKLVMI.js} +2 -2
- package/dist/cli/{chunk-GFGLLDXX.js → chunk-7SINJXB6.js} +2 -2
- package/dist/cli/{chunk-KJDWWQFY.js → chunk-7UARFJYS.js} +3 -3
- package/dist/cli/{chunk-JNZJPIPJ.js → chunk-7ZYPQV4N.js} +3 -3
- package/dist/cli/{chunk-DVTPIZJM.js → chunk-AQCYT3L4.js} +2 -2
- package/dist/cli/{chunk-EGOTK2HA.js → chunk-BQK6XTOH.js} +2 -2
- package/dist/cli/{chunk-DYABOIHB.js → chunk-CAPAGD5E.js} +6 -4
- package/dist/cli/{chunk-ZZTHTMQP.js → chunk-CHGEDCKG.js} +3 -3
- package/dist/cli/{chunk-QPUY2HQZ.js → chunk-COXFJ3PT.js} +2 -2
- package/dist/cli/chunk-D7BAQNV2.js +55 -0
- package/dist/cli/{chunk-OPTEQKBB.js → chunk-EIUXVHNF.js} +3 -3
- package/dist/cli/{chunk-3PGH67MT.js → chunk-EUGB6P5V.js} +4 -6
- package/dist/cli/chunk-EW2CKNNZ.js +304 -0
- package/dist/cli/{chunk-2JIJD2I7.js → chunk-FSKN4DWC.js} +2 -2
- package/dist/cli/{chunk-NSHV2JNM.js → chunk-FVKLULL7.js} +2 -2
- package/dist/cli/{chunk-GH37QXW5.js → chunk-GAGUBU4Z.js} +2 -2
- package/dist/cli/{chunk-37NU2XDP.js → chunk-GKRFH2YG.js} +2 -2
- package/dist/cli/{chunk-ULN4OKQQ.js → chunk-GRU74UE4.js} +21 -10
- package/dist/cli/{chunk-LKNUA3SB.js → chunk-HFLLZE6A.js} +2 -2
- package/dist/cli/{chunk-YGKEECTI.js → chunk-HXRXT3XU.js} +2 -2
- package/dist/cli/{chunk-REUTEW3O.js → chunk-IIOGUY3B.js} +6 -6
- package/dist/cli/chunk-ILWWL462.js +60 -0
- package/dist/cli/{chunk-XRAX6XFP.js → chunk-J5USPJKZ.js} +2 -2
- package/dist/cli/{chunk-S24YI723.js → chunk-KEQS36GD.js} +4 -4
- package/dist/cli/chunk-L7ONYSV6.js +2497 -0
- package/dist/cli/chunk-NEFMQYLE.js +656 -0
- package/dist/cli/{chunk-QFFQSKRC.js → chunk-NU6CQQVB.js} +6 -2
- package/dist/cli/{chunk-5J2VH3BC.js → chunk-PN4WW5VX.js} +3 -3
- package/dist/cli/{chunk-AYA6F4ZT.js → chunk-PSJ33WVO.js} +3 -3
- package/dist/cli/{chunk-FORFDPP5.js → chunk-QJJWWCIC.js} +3 -3
- package/dist/cli/{chunk-ZBISIPCK.js → chunk-QKMBWYAS.js} +16 -1
- package/dist/cli/chunk-QWNKLLLG.js +84 -0
- package/dist/cli/{chunk-7INMKEAD.js → chunk-QWUFFDL3.js} +2 -2
- package/dist/cli/chunk-QY76BRUZ.js +35 -0
- package/dist/cli/chunk-R45KVF5Y.js +117 -0
- package/dist/cli/{chunk-W33Q3FBH.js → chunk-RRKP7HLU.js} +3 -3
- package/dist/cli/{chunk-YUZJI67I.js → chunk-T6GZJYL3.js} +2 -2
- package/dist/cli/{chunk-LWQBJQSE.js → chunk-TLQ37HRE.js} +3 -3
- package/dist/cli/chunk-TPTNEJZJ.js +52 -0
- package/dist/cli/chunk-TYC7G5LF.js +100 -0
- package/dist/cli/{chunk-J3ZFM3UQ.js → chunk-UWCZY52R.js} +25 -13
- package/dist/cli/{chunk-V5GBGOGM.js → chunk-VB3LDPL5.js} +2 -2
- package/dist/cli/chunk-WWCYZYSN.js +56 -0
- package/dist/cli/{chunk-EBRZ76HS.js → chunk-XA5WISNV.js} +4 -3
- package/dist/cli/chunk-XHRZ7OYZ.js +132 -0
- package/dist/cli/{chunk-EOPQFCSR.js → chunk-XLPMIGJJ.js} +6 -6
- package/dist/cli/{chunk-NWTATTEQ.js → chunk-ZMGDZMSJ.js} +2 -2
- package/dist/cli/{claim-KPENYHIQ.js → claim-IGOG2QOC.js} +10 -9
- package/dist/cli/{classify-DRVMCFQU.js → classify-MG4N7GMQ.js} +2 -2
- package/dist/cli/{cli-T3CR7J57.js → cli-A23Q335V.js} +10 -7
- package/dist/cli/{cloud-PPQ4O5TX.js → cloud-SILYJVKO.js} +194 -28
- package/dist/cli/{code-Z5CTMVTD.js → code-H2FQCVMW.js} +2 -2
- package/dist/cli/{complete-UBOCOBRB.js → complete-JLX7NBI4.js} +9 -8
- package/dist/cli/{complexity-BV2AGQRZ.js → complexity-OKV7PVZH.js} +10 -9
- package/dist/cli/{compliance-32PD5Y47.js → compliance-QMGZHJNQ.js} +10 -9
- package/dist/cli/{conduit-VDKCH33F.js → conduit-4H32UYEA.js} +10 -9
- package/dist/cli/conduit-EY54WTZA.js +535 -0
- package/dist/cli/{config-I72JAXK4.js → config-TDYOC7XO.js} +21 -18
- package/dist/cli/{consensus-LFILLSTK.js → consensus-4XCOFPPT.js} +10 -9
- package/dist/cli/{context-XUUVFVTP.js → context-FN4YTGHD.js} +12 -11
- package/dist/cli/{contribution-37NQ4N5R.js → contribution-7RWFBJLC.js} +10 -9
- package/dist/cli/{curator-TFDXU2EX.js → curator-HKZJCVRL.js} +2 -2
- package/dist/cli/{current-C4SN5BWV.js → current-B2NU7V3G.js} +10 -9
- package/dist/cli/{daemon-DV25JQ62.js → daemon-GBD4TVCD.js} +11 -10
- package/dist/cli/{dash-TFU4RLQW.js → dash-IGDANIE5.js} +10 -9
- package/dist/cli/{decide-5VPMNTSI.js → decide-26SXC2V6.js} +5 -8
- package/dist/cli/{decompose-KOYEZNJL.js → decompose-LQ76TEZG.js} +11 -10
- package/dist/cli/{decomposition-7OHUFIQN.js → decomposition-WFRWNUSJ.js} +10 -9
- package/dist/cli/{delete-Q7YCAFY5.js → delete-T5DUQHOX.js} +11 -10
- package/dist/cli/{deps-6UZKLDGJ.js → deps-UTPZJBXL.js} +17 -18
- package/dist/cli/{detect-FERY35UL.js → detect-FFZSMVDT.js} +10 -9
- package/dist/cli/{detect-drift-UL2JTPUK.js → detect-drift-TVCJOFYJ.js} +7 -7
- package/dist/cli/diagnostics-GN5CVD3N.js +93 -0
- package/dist/cli/{diagnostics-TI5QAZXR.js → diagnostics-ZNBKH6GX.js} +10 -9
- package/dist/cli/docs-CLQKEEUK.js +1710 -0
- package/dist/cli/{docs-QI2PRN3T.js → docs-DPPDFTWR.js} +45 -42
- package/dist/cli/{doctor-AX5TICQO.js → doctor-GPENOP4N.js} +79 -62
- package/dist/cli/{doctor-ac-bindings-YPMYHU2G.js → doctor-ac-bindings-S3IOEFP4.js} +3 -3
- package/dist/cli/{doctor-acceptance-drift-PYNFGMKB.js → doctor-acceptance-drift-VNFKPBSQ.js} +3 -3
- package/dist/cli/{doctor-credentials-UZRIADKM.js → doctor-credentials-A5H4JMTF.js} +3 -3
- package/dist/cli/{doctor-db-substrate-Q2TOYM2S.js → doctor-db-substrate-FGCISE4Z.js} +3 -3
- package/dist/cli/{doctor-dep-cycles-GCVYZY6F.js → doctor-dep-cycles-BKKKHHYG.js} +3 -3
- package/dist/cli/{doctor-exodus-RO5SUTC2.js → doctor-exodus-ND2DH2KP.js} +3 -3
- package/dist/cli/{doctor-exodus-residue-EM2AWQXP.js → doctor-exodus-residue-4EMRYMEQ.js} +3 -3
- package/dist/cli/{doctor-fk-check-Q3FOLECE.js → doctor-fk-check-VY3RIQV3.js} +3 -3
- package/dist/cli/{doctor-global-delivery-TNOAQ3NP.js → doctor-global-delivery-JN6IGHUL.js} +3 -3
- package/dist/cli/{doctor-heavy-command-hook-IO3QAQLG.js → doctor-heavy-command-hook-XSN44WXU.js} +3 -3
- package/dist/cli/{doctor-legacy-backups-O2YH5VLS.js → doctor-legacy-backups-QAG5NHYP.js} +3 -3
- package/dist/cli/{doctor-legacy-reaper-VSEJEIFA.js → doctor-legacy-reaper-CIRGFE6R.js} +3 -3
- package/dist/cli/{doctor-malformed-ids-LQ766V5K.js → doctor-malformed-ids-WL7HT4TB.js} +3 -3
- package/dist/cli/{doctor-manifest-rows-6FQDNHLH.js → doctor-manifest-rows-SMQCKJ2T.js} +3 -3
- package/dist/cli/{doctor-memory-guard-J4PSEKB5.js → doctor-memory-guard-LJDOJG76.js} +3 -3
- package/dist/cli/{doctor-migrations-ONOH56YM.js → doctor-migrations-ETQPFNUP.js} +3 -3
- package/dist/cli/{doctor-nexus-residency-FUQAX7PV.js → doctor-nexus-residency-A4JMKBEJ.js} +3 -3
- package/dist/cli/{doctor-project-identity-GUDK3HYX.js → doctor-project-identity-FFQJ5LNX.js} +3 -3
- package/dist/cli/{doctor-projects-7L3BNL4O.js → doctor-projects-MFUTKRHP.js} +3 -3
- package/dist/cli/{doctor-projects-registry-TEAVHFQU.js → doctor-projects-registry-76X6VTGM.js} +3 -3
- package/dist/cli/{doctor-release-readiness-IEGHX6SL.js → doctor-release-readiness-QJCOPFTK.js} +3 -3
- package/dist/cli/{doctor-repair-NBONOSZU.js → doctor-repair-AU76FIKY.js} +3 -3
- package/dist/cli/doctor-row-identity-KW6JYZQE.js +26 -0
- package/dist/cli/{doctor-skill-fixtures-7Y6L34A3.js → doctor-skill-fixtures-G3T7JUHS.js} +3 -3
- package/dist/cli/{doctor-split-brain-TUKIGVHF.js → doctor-split-brain-FUW6L7FS.js} +3 -3
- package/dist/cli/{doctor-superseded-store-BHZY2B2L.js → doctor-superseded-store-DUHGSBLC.js} +3 -3
- package/dist/cli/doctor-sync-journal-SXMUIKF7.js +26 -0
- package/dist/cli/doctor-sync-triggers-6WNJZFRM.js +26 -0
- package/dist/cli/{doctor-tool-locks-REQMIVYK.js → doctor-tool-locks-66LSLUBN.js} +3 -3
- package/dist/cli/{doctor-twin-collapse-222GOSPE.js → doctor-twin-collapse-AYBYBFC4.js} +3 -3
- package/dist/cli/{doctor-worktree-stores-J7TCRVJ3.js → doctor-worktree-stores-C5XEH5OG.js} +3 -3
- package/dist/cli/{done-V3AOO65B.js → done-R64XRZ32.js} +11 -10
- package/dist/cli/entities-3JIHDIOK.js +361 -0
- package/dist/cli/{event-EGNPGE5A.js → event-45KEWV5H.js} +2 -2
- package/dist/cli/{exists-H4SDCBPL.js → exists-BEDZS5RI.js} +3 -3
- package/dist/cli/{exodus-KALO3B3X.js → exodus-DUX62344.js} +3 -3
- package/dist/cli/{export-ROFOCG4M.js → export-C5PQIQ5O.js} +11 -10
- package/dist/cli/{export-tasks-US3WBIEQ.js → export-tasks-CUXDZPJB.js} +11 -10
- package/dist/cli/{federation-SUIB5QWT.js → federation-ESM35EGG.js} +3 -3
- package/dist/cli/{find-YICG4BG6.js → find-5EUZHHQJ.js} +13 -12
- package/dist/cli/focus-6AH4KLRO.js +368 -0
- package/dist/cli/{focus-TKCZPKOM.js → focus-ANKAIRO5.js} +10 -9
- package/dist/cli/{gateway-H4HFDC3E.js → gateway-2GW2KTK3.js} +2 -2
- package/dist/cli/{gc-5R2TUY5T.js → gc-CTOQLUSA.js} +2 -2
- package/dist/cli/{go-PRQFK5YG.js → go-YJPNHHYT.js} +6 -6
- package/dist/cli/{goal-7CZRMLHC.js → goal-4GW4G77D.js} +4 -3
- package/dist/cli/{grade-PY2YRPUS.js → grade-25WSZH4X.js} +10 -9
- package/dist/cli/{graph-XIXMCFKG.js → graph-JUO3TMF3.js} +11 -10
- package/dist/cli/{history-EIXADPAD.js → history-NACNUQTC.js} +10 -9
- package/dist/cli/{import-R73SO444.js → import-7ESGL5SS.js} +10 -9
- package/dist/cli/{import-tasks-O22FZJ4U.js → import-tasks-FLE2RPBR.js} +10 -9
- package/dist/cli/index.js +395 -238
- package/dist/cli/{init-IHEJDQWU.js → init-AN4DZ2XO.js} +5 -5
- package/dist/cli/{inject-LSRVWNCP.js → inject-HQWA5GWY.js} +10 -9
- package/dist/cli/{install-global-4AZUCH6U.js → install-global-YQV4W5OG.js} +2 -2
- package/dist/cli/intelligence-OFFNQGHE.js +238 -0
- package/dist/cli/{intelligence-2OSFOGD2.js → intelligence-QIC4SN4X.js} +10 -9
- package/dist/cli/{issue-IIWEDNFC.js → issue-P5RNMRDG.js} +10 -9
- package/dist/cli/{janitor-GPMC7VOR.js → janitor-ZNCFQ7E3.js} +2 -2
- package/dist/cli/{labels-5NPOIQXN.js → labels-ORBM3T57.js} +10 -9
- package/dist/cli/{lifecycle-4FFS2K2T.js → lifecycle-MHR22TVI.js} +13 -12
- package/dist/cli/{list-47KEUGPQ.js → list-LB6GCYYU.js} +14 -13
- package/dist/cli/llm-H7LZWQKX.js +130 -0
- package/dist/cli/{llm-G5B3I6GD.js → llm-OTJWPMGI.js} +14 -13
- package/dist/cli/{llm-cost-S7RS6BVA.js → llm-cost-MLMXEAR4.js} +3 -3
- package/dist/cli/{llm-stream-24A45NTS.js → llm-stream-AAEUNKRP.js} +3 -3
- package/dist/cli/{log-XF6H2XSD.js → log-W2A5M2NA.js} +10 -9
- package/dist/cli/{login-LBPLGHYG.js → login-SIXFFZSP.js} +6 -4
- package/dist/cli/{logout-SX4JSJIV.js → logout-G3KVLQQM.js} +5 -5
- package/dist/cli/{manifest-NMCW4PIW.js → manifest-G4T6EBSI.js} +10 -9
- package/dist/cli/{map-BU72KMGF.js → map-VU5M72TK.js} +10 -9
- package/dist/cli/{memory-UHYIVGVM.js → memory-2E27G2G5.js} +17 -21
- package/dist/cli/memory-IAEYKXG6.js +1895 -0
- package/dist/cli/{migrate-agents-v2-OO7OILZK.js → migrate-agents-v2-A52QIYNJ.js} +3 -3
- package/dist/cli/{migrate-claude-mem-EDNYUY3K.js → migrate-claude-mem-TPDW3R4Z.js} +17 -12
- package/dist/cli/{next-RZFRG5X7.js → next-SVH4LIDY.js} +10 -9
- package/dist/cli/nexus-FPQV2EAF.js +1059 -0
- package/dist/cli/{nexus-4S4Z5EVU.js → nexus-XSFXN5E6.js} +14 -13
- package/dist/cli/{ops-KR7AWCG3.js → ops-K6LHY5J6.js} +10 -9
- package/dist/cli/orchestrate-CZ2J6W3L.js +1650 -0
- package/dist/cli/{orchestrate-HOYZY3VX.js → orchestrate-HURUCQFT.js} +13 -11
- package/dist/cli/{otel-U7IIRBCT.js → otel-JCNPVJLZ.js} +2 -2
- package/dist/cli/{phase-NYZFHUE5.js → phase-VDFRASSO.js} +10 -9
- package/dist/cli/pipeline-TCZPOEDR.js +697 -0
- package/dist/cli/{pivot-FF2CVUZL.js → pivot-V5MSQZ7L.js} +10 -9
- package/dist/cli/{plan-3SL2NTRV.js → plan-SQUGCKSM.js} +10 -9
- package/dist/cli/{playbook-2FCBV7N3.js → playbook-L47GLDQD.js} +10 -9
- package/dist/cli/playbook-NJVO4R6P.js +33 -0
- package/dist/cli/{project-WDX2TGMC.js → project-YZEC7GYF.js} +6 -5
- package/dist/cli/{promote-YINYFBZY.js → promote-FINF4HVK.js} +10 -9
- package/dist/cli/provenance-3TUWVBFR.js +141 -0
- package/dist/cli/{provenance-C7AYD7WG.js → provenance-YZG33JGM.js} +10 -9
- package/dist/cli/{provider-QLJEDQBR.js → provider-23JVLLG3.js} +10 -9
- package/dist/cli/{reason-JF5BHBM5.js → reason-FHN54O7O.js} +10 -9
- package/dist/cli/{reconcile-NMISHDGX.js → reconcile-MOM5T4AX.js} +11 -10
- package/dist/cli/{refresh-memory-EY5YNICV.js → refresh-memory-3OSTRAVK.js} +2 -2
- package/dist/cli/{relates-R3ZPICAY.js → relates-6FWUFUS2.js} +10 -9
- package/dist/cli/release-G2DPSG5M.js +347 -0
- package/dist/cli/{release-4ZJTMUUT.js → release-URX6JHZ2.js} +10 -9
- package/dist/cli/{remote-QSONJDIK.js → remote-VIULU2T5.js} +3 -3
- package/dist/cli/{renderers-64OR3IWX.js → renderers-TGSW77J4.js} +2 -2
- package/dist/cli/{reorder-J3DOE7ST.js → reorder-UIPN6TQY.js} +10 -9
- package/dist/cli/{reparent-2OUMKEZX.js → reparent-ALOWWUIU.js} +10 -9
- package/dist/cli/{req-TZB7OFKO.js → req-RH2Y3H7A.js} +10 -9
- package/dist/cli/{research-MTD7EX45.js → research-G2Y72HRC.js} +10 -9
- package/dist/cli/{restore-VEUOX7NF.js → restore-VBR5XNML.js} +62 -15
- package/dist/cli/{revert-3YF2IL5G.js → revert-32LDNSGP.js} +2 -2
- package/dist/cli/{roadmap-7OOQLXKG.js → roadmap-LFU3AG7D.js} +10 -9
- package/dist/cli/{run-2U5NZV5Z.js → run-HXRILSR7.js} +40 -6
- package/dist/cli/{safestop-VR4VK56D.js → safestop-Z5UC7NGQ.js} +10 -9
- package/dist/cli/{saga-SEWPIOX2.js → saga-Y6FZS6AM.js} +12 -11
- package/dist/cli/{schema-C52WZ35V.js → schema-OOOKLWUE.js} +5 -5
- package/dist/cli/{self-update-GQIGUDPS.js → self-update-26SOTJMH.js} +3 -3
- package/dist/cli/{selfimprove-3Y5L4ECT.js → selfimprove-4SMOCLUV.js} +10 -9
- package/dist/cli/selfimprove-EB4RQLP4.js +139 -0
- package/dist/cli/sentient-QPETVE53.js +254 -0
- package/dist/cli/{sentient-M4YMAVGV.js → sentient-RGMWR4XJ.js} +2 -2
- package/dist/cli/{sequence-6UBMA4IF.js → sequence-H7DSAJPF.js} +10 -9
- package/dist/cli/{service-5R7SILZ7.js → service-EK5MGB2D.js} +10 -9
- package/dist/cli/service-GLOMZWPQ.js +437 -0
- package/dist/cli/{session-3C6AAC4Y.js → session-HYUXAQGC.js} +12 -11
- package/dist/cli/session-N5ISU56W.js +568 -0
- package/dist/cli/{setup-BTUBW5PU.js → setup-L3YYV53D.js} +4 -4
- package/dist/cli/{show-MXT2V7TF.js → show-364V3KY2.js} +12 -11
- package/dist/cli/{skill-GFUZOU2C.js → skill-F2KR6HW5.js} +2 -2
- package/dist/cli/{skills-EDWLKAF3.js → skills-FS3DCP6E.js} +13 -12
- package/dist/cli/{snapshot-GUWMURCM.js → snapshot-EGXEQ5PR.js} +12 -11
- package/dist/cli/{src-66GAKPXR.js → src-LYLXHXHH.js} +2 -2
- package/dist/cli/{start-QFG56RGN.js → start-6DXOCCKL.js} +10 -9
- package/dist/cli/{stats-GW55P7RR.js → stats-UVUQEGYC.js} +10 -9
- package/dist/cli/{status-46HTKNRR.js → status-XLKYLN42.js} +3 -3
- package/dist/cli/sticky-VSTQ2I2O.js +264 -0
- package/dist/cli/{sticky-2DUZOUGI.js → sticky-XZXZDCFW.js} +12 -11
- package/dist/cli/{stop-J2QEUKHX.js → stop-VNOAFWNB.js} +10 -9
- package/dist/cli/{sync-GJP2QYT5.js → sync-YYPARW3A.js} +11 -10
- package/dist/cli/tasks-C24KHTFF.js +1118 -0
- package/dist/cli/{tasks-BNXTM7PB.js → tasks-LBJC7CZV.js} +10 -9
- package/dist/cli/{telemetry-55Z2XJWL.js → telemetry-CU7W5WAY.js} +2 -2
- package/dist/cli/{templates-7O77TKPV.js → templates-G42JBUY4.js} +9 -11
- package/dist/cli/{testing-37YTBNKP.js → testing-HSRITHEY.js} +10 -9
- package/dist/cli/{token-UAVJMNUI.js → token-J74E7TSU.js} +10 -9
- package/dist/cli/tools-BI74W7VE.js +652 -0
- package/dist/cli/{transcript-LORQTV5Z.js → transcript-RGK7RSGQ.js} +2 -2
- package/dist/cli/{update-NVCYV2FT.js → update-2KQWA27S.js} +19 -17
- package/dist/cli/update-check-entry.js +124 -0
- package/dist/cli/update-notice-6SQ6WPQG.js +68 -0
- package/dist/cli/upgrade-E2MJAPC7.js +136 -0
- package/dist/cli/{upgrade-OXJXOGEF.js → upgrade-XRSQ4RWH.js} +5 -5
- package/dist/cli/{verify-LYLDHPT2.js → verify-WASRGDBA.js} +10 -9
- package/dist/cli/{web-QP2RP266.js → web-NJ3P67EU.js} +4 -4
- package/dist/cli/{workgraph-FXBSZDQE.js → workgraph-OHJ2VKJD.js} +6 -6
- package/dist/cli/{worktree-6RXAJIST.js → worktree-FVQLORFY.js} +10 -9
- package/dist/cli/worktree-ZJ6JTQNG.js +287 -0
- package/package.json +13 -13
- package/studio-dist/client/_app/immutable/chunks/{Btgeq_wq.js → AH7dIemv.js} +1 -1
- package/studio-dist/client/_app/immutable/chunks/{DgEKqO6r.js → BDgH40i3.js} +1 -1
- package/studio-dist/client/_app/immutable/chunks/BXDCSJ7U.js +1 -0
- package/studio-dist/client/_app/immutable/chunks/{CgBjxmu6.js → Gg4iYl59.js} +1 -1
- package/studio-dist/client/_app/immutable/entry/{app.a02HWaRB.js → app.DUDNK-37.js} +2 -2
- package/studio-dist/client/_app/immutable/entry/start.DNmZ0pA4.js +1 -0
- package/studio-dist/client/_app/immutable/nodes/{0.nTXyRfc-.js → 0.DWqP3ail.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{1.4zrWeHtl.js → 1.CZGVUP5B.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{15.D9mk4JyY.js → 15.DGaflZRS.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{16._-wt-sQf.js → 16.uYlarGXl.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{17.CUu6LQDj.js → 17.CZMR0E47.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{18.Dz4QRTkX.js → 18.CBC-AKH_.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{20.CJ2_EB0U.js → 20.BGi43MvQ.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{24.Igj2FS7k.js → 24.Dv8ftCyR.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/25.DQPVlTDQ.js +39 -0
- package/studio-dist/client/_app/immutable/nodes/{26.6iPyjT44.js → 26.Cl800304.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{3.AA5GwNgP.js → 3.D_fQKj9f.js} +1 -1
- package/studio-dist/client/_app/version.json +1 -1
- package/studio-dist/server/chunks/{0-DGmsoBYm.js → 0-BpOagOst.js} +3 -3
- package/studio-dist/server/chunks/1-D0oRGR-C.js +9 -0
- package/studio-dist/server/chunks/{15-Bg6YTndh.js → 15-BcjHz7Tv.js} +3 -3
- package/studio-dist/server/chunks/{16-BObLwgyD.js → 16-CXm8TUk7.js} +3 -3
- package/studio-dist/server/chunks/{17-BNXGyAHX.js → 17-mSgUK-cp.js} +3 -3
- package/studio-dist/server/chunks/{18-UqQFRIID.js → 18-BtfnIw1d.js} +3 -3
- package/studio-dist/server/chunks/{20-CMn8a_yP.js → 20-By1e4QDS.js} +3 -3
- package/studio-dist/server/chunks/{24-BuOTDzib.js → 24-0i2YLVxG.js} +3 -3
- package/studio-dist/server/chunks/{dist-B8xbIrdB.js → 25-DPsrqbrh.js} +795 -10736
- package/studio-dist/server/chunks/{26-DWGObn2T.js → 26-P0XkOibm.js} +3 -3
- package/studio-dist/server/chunks/{3-CyiffdJZ.js → 3-WudjUK7e.js} +3 -3
- package/studio-dist/server/chunks/{_layout.svelte-DYtClaIk.js → _layout.svelte-D9m81Rle.js} +4 -4
- package/studio-dist/server/chunks/{_page.svelte-CEATWp_5.js → _page.svelte-2PDLOF83.js} +3 -3
- package/studio-dist/server/chunks/{_page.svelte-Bip079LT.js → _page.svelte-BjE3jm2K.js} +3 -3
- package/studio-dist/server/chunks/{_page.svelte-CV3xiD1y.js → _page.svelte-Clc0vmiZ.js} +4 -4
- package/studio-dist/server/chunks/{_page.svelte-DSSy6LuK.js → _page.svelte-DABdRT3h.js} +3 -3
- package/studio-dist/server/chunks/{_page.svelte-1h9E6s_f.js → _page.svelte-DG3PjiHj.js} +3 -3
- package/studio-dist/server/chunks/{_page.svelte-BT1EUadj.js → _page.svelte-Edy9CaE8.js} +20 -7
- package/studio-dist/server/chunks/{_page.svelte-BNNF62Nm.js → _page.svelte-Hrf3-ZR8.js} +3 -3
- package/studio-dist/server/chunks/{_page.svelte-TF795TAS.js → _page.svelte-VB4O4Nl5.js} +3 -3
- package/studio-dist/server/chunks/{_page.svelte-Cv_KVJDV.js → _page.svelte-d3jEgjsI.js} +3 -3
- package/studio-dist/server/chunks/{_server.ts-CzrwbhkQ.js → _server.ts-BcRFsyo3.js} +4 -5
- package/studio-dist/server/chunks/{_server.ts-C4w6UdU0.js → _server.ts-CEWpIFrj.js} +6 -5
- package/studio-dist/server/chunks/{_server.ts-BlhRFLY3.js → _server.ts-CLVdVIF9.js} +2 -2
- package/studio-dist/server/chunks/{_server.ts-Db6mEile.js → _server.ts-D_j7aSy5.js} +6 -5
- package/studio-dist/server/chunks/{_server.ts-DWt8Dziu.js → _server.ts-QEZF8h2q.js} +4 -5
- package/studio-dist/server/chunks/{client-D8f2k-H_.js → client-Kp1dP1od.js} +2 -2
- package/studio-dist/server/chunks/{error.svelte-DbbOwIme.js → error.svelte-WOCioJVX.js} +3 -3
- package/studio-dist/server/chunks/{hooks.server-D2qbf3Zp.js → hooks.server-DH9zkIrJ.js} +3 -1
- package/studio-dist/server/chunks/{http-1ftNGTs5.js → http-DT5kxaWk.js} +5 -4
- package/studio-dist/server/chunks/{internal-CTULuLPB.js → internal-z0vqd5_u.js} +3 -3
- package/studio-dist/server/chunks/operations-registry-DdzmYzqX.js +10584 -0
- package/studio-dist/server/chunks/{stores-CS5XOReX.js → stores-s2kaL315.js} +2 -2
- package/studio-dist/server/index.js +1 -1
- package/studio-dist/server/manifest.js +17 -17
- package/dist/cli/chunk-3IOQVUO7.js +0 -17308
- package/dist/cli/chunk-OAPN46TC.js +0 -89
- package/studio-dist/client/_app/immutable/chunks/t81h7afa.js +0 -1
- package/studio-dist/client/_app/immutable/entry/start.BreMSngo.js +0 -1
- package/studio-dist/client/_app/immutable/nodes/25.BnATjVGN.js +0 -39
- package/studio-dist/server/chunks/1-8PfxPvlK.js +0 -9
- package/studio-dist/server/chunks/25-CIMSmjVx.js +0 -366
|
@@ -0,0 +1,1895 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
const _installed = Symbol.for('cleocode.cli.sqliteWarningFilter');
|
|
3
|
+
if (globalThis[_installed]) return;
|
|
4
|
+
globalThis[_installed] = true;
|
|
5
|
+
const _origEmitWarning = process.emitWarning;
|
|
6
|
+
process.emitWarning = function(warning, type, code, ctor) {
|
|
7
|
+
if (typeof warning === 'object' && warning.name === 'ExperimentalWarning' && typeof warning.message === 'string' && /SQLite is an experimental feature/i.test(warning.message)) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (typeof warning === 'string' && /SQLite is an experimental feature/i.test(warning)) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
return _origEmitWarning.call(process, warning, type, code, ctor);
|
|
14
|
+
};
|
|
15
|
+
})();
|
|
16
|
+
import {
|
|
17
|
+
lazyOperation
|
|
18
|
+
} from "./chunk-TYC7G5LF.js";
|
|
19
|
+
import {
|
|
20
|
+
errorResult,
|
|
21
|
+
handleErrorResult,
|
|
22
|
+
paramBool,
|
|
23
|
+
paramNumber,
|
|
24
|
+
paramString,
|
|
25
|
+
paramStringArray,
|
|
26
|
+
paramStringRequired,
|
|
27
|
+
unsupportedOp,
|
|
28
|
+
wrapResult
|
|
29
|
+
} from "./chunk-XHRZ7OYZ.js";
|
|
30
|
+
|
|
31
|
+
// packages/cleo/src/dispatch/domains/memory.ts
|
|
32
|
+
import {
|
|
33
|
+
OAUTH_STATUS_PROVIDERS,
|
|
34
|
+
resolveCredentials,
|
|
35
|
+
resolveProviderStatus
|
|
36
|
+
} from "@cleocode/core/llm/credentials";
|
|
37
|
+
import { getLogger } from "@cleocode/core/logger";
|
|
38
|
+
import {
|
|
39
|
+
approveBackfillRun,
|
|
40
|
+
listBackfillRuns,
|
|
41
|
+
rollbackBackfillRun,
|
|
42
|
+
stagedBackfillRun
|
|
43
|
+
} from "@cleocode/core/memory/brain-backfill.js";
|
|
44
|
+
import { precompactFlush } from "@cleocode/core/memory/precompact-flush.js";
|
|
45
|
+
import { getProjectRoot } from "@cleocode/core/project-scope";
|
|
46
|
+
import { createAttachmentStore } from "@cleocode/core/store/attachment-store";
|
|
47
|
+
import { getBrainNativeDb } from "@cleocode/core/store/memory-sqlite";
|
|
48
|
+
import { typedAll } from "@cleocode/core/store/typed-query";
|
|
49
|
+
var generateMemoryBridgeContent = lazyOperation(
|
|
50
|
+
async () => (await import("@cleocode/core/memory/memory-bridge")).generateMemoryBridgeContent
|
|
51
|
+
);
|
|
52
|
+
var getBrainDb = lazyOperation(
|
|
53
|
+
async () => (await import("@cleocode/core/store/memory-sqlite")).getBrainDb
|
|
54
|
+
);
|
|
55
|
+
var memoryDecisionFind = lazyOperation(
|
|
56
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryDecisionFind
|
|
57
|
+
);
|
|
58
|
+
var memoryDecisionStore = lazyOperation(
|
|
59
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryDecisionStore
|
|
60
|
+
);
|
|
61
|
+
var memoryFetch = lazyOperation(
|
|
62
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryFetch
|
|
63
|
+
);
|
|
64
|
+
var memoryFind = lazyOperation(
|
|
65
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryFind
|
|
66
|
+
);
|
|
67
|
+
var memoryGraphAdd = lazyOperation(
|
|
68
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryGraphAdd
|
|
69
|
+
);
|
|
70
|
+
var memoryGraphContext = lazyOperation(
|
|
71
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryGraphContext
|
|
72
|
+
);
|
|
73
|
+
var memoryGraphNeighbors = lazyOperation(
|
|
74
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryGraphNeighbors
|
|
75
|
+
);
|
|
76
|
+
var memoryGraphRelated = lazyOperation(
|
|
77
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryGraphRelated
|
|
78
|
+
);
|
|
79
|
+
var memoryGraphRemove = lazyOperation(
|
|
80
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryGraphRemove
|
|
81
|
+
);
|
|
82
|
+
var memoryGraphShow = lazyOperation(
|
|
83
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryGraphShow
|
|
84
|
+
);
|
|
85
|
+
var memoryGraphStatsFull = lazyOperation(
|
|
86
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryGraphStatsFull
|
|
87
|
+
);
|
|
88
|
+
var memoryGraphTrace = lazyOperation(
|
|
89
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryGraphTrace
|
|
90
|
+
);
|
|
91
|
+
var memoryLearningFind = lazyOperation(
|
|
92
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryLearningFind
|
|
93
|
+
);
|
|
94
|
+
var memoryLearningStore = lazyOperation(
|
|
95
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryLearningStore
|
|
96
|
+
);
|
|
97
|
+
var memoryLink = lazyOperation(
|
|
98
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryLink
|
|
99
|
+
);
|
|
100
|
+
var memoryObserve = lazyOperation(
|
|
101
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryObserve
|
|
102
|
+
);
|
|
103
|
+
var memoryPatternFind = lazyOperation(
|
|
104
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryPatternFind
|
|
105
|
+
);
|
|
106
|
+
var memoryPatternStore = lazyOperation(
|
|
107
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryPatternStore
|
|
108
|
+
);
|
|
109
|
+
var memoryQualityReport = lazyOperation(
|
|
110
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryQualityReport
|
|
111
|
+
);
|
|
112
|
+
var memoryReasonSimilar = lazyOperation(
|
|
113
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryReasonSimilar
|
|
114
|
+
);
|
|
115
|
+
var memoryReasonWhy = lazyOperation(
|
|
116
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryReasonWhy
|
|
117
|
+
);
|
|
118
|
+
var memorySearchHybrid = lazyOperation(
|
|
119
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memorySearchHybrid
|
|
120
|
+
);
|
|
121
|
+
var memoryTimeline = lazyOperation(
|
|
122
|
+
async () => (await import("@cleocode/core/memory/engine-compat")).memoryTimeline
|
|
123
|
+
);
|
|
124
|
+
var MemoryHandler = class {
|
|
125
|
+
// -----------------------------------------------------------------------
|
|
126
|
+
// Query
|
|
127
|
+
// -----------------------------------------------------------------------
|
|
128
|
+
async query(operation, params) {
|
|
129
|
+
const projectRoot = getProjectRoot();
|
|
130
|
+
const startTime = Date.now();
|
|
131
|
+
try {
|
|
132
|
+
switch (operation) {
|
|
133
|
+
case "find": {
|
|
134
|
+
const query = paramStringRequired(params, "query");
|
|
135
|
+
if (!query)
|
|
136
|
+
return errorResult(
|
|
137
|
+
"query",
|
|
138
|
+
"memory",
|
|
139
|
+
operation,
|
|
140
|
+
"E_INVALID_INPUT",
|
|
141
|
+
"query is required",
|
|
142
|
+
startTime
|
|
143
|
+
);
|
|
144
|
+
return wrapResult(
|
|
145
|
+
await memoryFind(
|
|
146
|
+
{
|
|
147
|
+
query,
|
|
148
|
+
limit: paramNumber(params, "limit"),
|
|
149
|
+
tables: paramStringArray(params, "tables"),
|
|
150
|
+
includeHistory: paramBool(params, "includeHistory"),
|
|
151
|
+
dateStart: paramString(params, "dateStart"),
|
|
152
|
+
dateEnd: paramString(params, "dateEnd"),
|
|
153
|
+
agent: paramString(params, "agent")
|
|
154
|
+
},
|
|
155
|
+
projectRoot
|
|
156
|
+
),
|
|
157
|
+
"query",
|
|
158
|
+
"memory",
|
|
159
|
+
operation,
|
|
160
|
+
startTime
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
case "timeline": {
|
|
164
|
+
const anchor = paramStringRequired(params, "anchor");
|
|
165
|
+
if (!anchor)
|
|
166
|
+
return errorResult(
|
|
167
|
+
"query",
|
|
168
|
+
"memory",
|
|
169
|
+
operation,
|
|
170
|
+
"E_INVALID_INPUT",
|
|
171
|
+
"anchor is required",
|
|
172
|
+
startTime
|
|
173
|
+
);
|
|
174
|
+
return wrapResult(
|
|
175
|
+
await memoryTimeline(
|
|
176
|
+
{
|
|
177
|
+
anchor,
|
|
178
|
+
depthBefore: paramNumber(params, "depthBefore"),
|
|
179
|
+
depthAfter: paramNumber(params, "depthAfter")
|
|
180
|
+
},
|
|
181
|
+
projectRoot
|
|
182
|
+
),
|
|
183
|
+
"query",
|
|
184
|
+
"memory",
|
|
185
|
+
operation,
|
|
186
|
+
startTime
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
case "fetch": {
|
|
190
|
+
const ids = paramStringArray(params, "ids");
|
|
191
|
+
if (!ids || ids.length === 0)
|
|
192
|
+
return errorResult(
|
|
193
|
+
"query",
|
|
194
|
+
"memory",
|
|
195
|
+
operation,
|
|
196
|
+
"E_INVALID_INPUT",
|
|
197
|
+
"ids is required (non-empty array)",
|
|
198
|
+
startTime
|
|
199
|
+
);
|
|
200
|
+
return wrapResult(
|
|
201
|
+
await memoryFetch({ ids }, projectRoot),
|
|
202
|
+
"query",
|
|
203
|
+
"memory",
|
|
204
|
+
operation,
|
|
205
|
+
startTime
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
case "decision.find": {
|
|
209
|
+
const result = await memoryDecisionFind(
|
|
210
|
+
{
|
|
211
|
+
query: paramString(params, "query"),
|
|
212
|
+
taskId: paramString(params, "taskId"),
|
|
213
|
+
limit: paramNumber(params, "limit"),
|
|
214
|
+
// T1830: opt-in to AGT-* dispatch rows; excluded by default
|
|
215
|
+
includeAgentDispatch: paramBool(params, "includeAgentDispatch") ?? false
|
|
216
|
+
},
|
|
217
|
+
projectRoot
|
|
218
|
+
);
|
|
219
|
+
return wrapResult(result, "query", "memory", operation, startTime);
|
|
220
|
+
}
|
|
221
|
+
case "pattern.find": {
|
|
222
|
+
const patternType = paramString(params, "type");
|
|
223
|
+
const patternImpact = paramString(params, "impact");
|
|
224
|
+
const result = await memoryPatternFind(
|
|
225
|
+
{
|
|
226
|
+
type: patternType,
|
|
227
|
+
impact: patternImpact,
|
|
228
|
+
query: paramString(params, "query"),
|
|
229
|
+
minFrequency: paramNumber(params, "minFrequency"),
|
|
230
|
+
limit: paramNumber(params, "limit")
|
|
231
|
+
},
|
|
232
|
+
projectRoot
|
|
233
|
+
);
|
|
234
|
+
return wrapResult(result, "query", "memory", operation, startTime);
|
|
235
|
+
}
|
|
236
|
+
case "learning.find": {
|
|
237
|
+
const result = await memoryLearningFind(
|
|
238
|
+
{
|
|
239
|
+
query: paramString(params, "query"),
|
|
240
|
+
minConfidence: paramNumber(params, "minConfidence"),
|
|
241
|
+
actionableOnly: paramBool(params, "actionableOnly"),
|
|
242
|
+
applicableType: paramString(params, "applicableType"),
|
|
243
|
+
limit: paramNumber(params, "limit")
|
|
244
|
+
},
|
|
245
|
+
projectRoot
|
|
246
|
+
);
|
|
247
|
+
return wrapResult(result, "query", "memory", operation, startTime);
|
|
248
|
+
}
|
|
249
|
+
case "graph.show": {
|
|
250
|
+
const nodeId = paramStringRequired(params, "nodeId");
|
|
251
|
+
if (!nodeId) {
|
|
252
|
+
return errorResult(
|
|
253
|
+
"query",
|
|
254
|
+
"memory",
|
|
255
|
+
operation,
|
|
256
|
+
"E_INVALID_INPUT",
|
|
257
|
+
"nodeId is required",
|
|
258
|
+
startTime
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
const result = await memoryGraphShow({ nodeId }, projectRoot);
|
|
262
|
+
return wrapResult(result, "query", "memory", operation, startTime);
|
|
263
|
+
}
|
|
264
|
+
case "graph.neighbors": {
|
|
265
|
+
const nodeId = paramStringRequired(params, "nodeId");
|
|
266
|
+
if (!nodeId) {
|
|
267
|
+
return errorResult(
|
|
268
|
+
"query",
|
|
269
|
+
"memory",
|
|
270
|
+
operation,
|
|
271
|
+
"E_INVALID_INPUT",
|
|
272
|
+
"nodeId is required",
|
|
273
|
+
startTime
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
const result = await memoryGraphNeighbors(
|
|
277
|
+
{ nodeId, edgeType: paramString(params, "edgeType") },
|
|
278
|
+
projectRoot
|
|
279
|
+
);
|
|
280
|
+
return wrapResult(result, "query", "memory", operation, startTime);
|
|
281
|
+
}
|
|
282
|
+
case "graph.trace": {
|
|
283
|
+
const nodeId = paramStringRequired(params, "nodeId");
|
|
284
|
+
if (!nodeId) {
|
|
285
|
+
return errorResult(
|
|
286
|
+
"query",
|
|
287
|
+
"memory",
|
|
288
|
+
operation,
|
|
289
|
+
"E_INVALID_INPUT",
|
|
290
|
+
"nodeId is required",
|
|
291
|
+
startTime
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
const result = await memoryGraphTrace(
|
|
295
|
+
{ nodeId, maxDepth: paramNumber(params, "maxDepth") },
|
|
296
|
+
projectRoot
|
|
297
|
+
);
|
|
298
|
+
return wrapResult(result, "query", "memory", operation, startTime);
|
|
299
|
+
}
|
|
300
|
+
case "graph.related": {
|
|
301
|
+
const nodeId = paramStringRequired(params, "nodeId");
|
|
302
|
+
if (!nodeId) {
|
|
303
|
+
return errorResult(
|
|
304
|
+
"query",
|
|
305
|
+
"memory",
|
|
306
|
+
operation,
|
|
307
|
+
"E_INVALID_INPUT",
|
|
308
|
+
"nodeId is required",
|
|
309
|
+
startTime
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
const result = await memoryGraphRelated(
|
|
313
|
+
{ nodeId, edgeType: paramString(params, "edgeType") },
|
|
314
|
+
projectRoot
|
|
315
|
+
);
|
|
316
|
+
return wrapResult(result, "query", "memory", operation, startTime);
|
|
317
|
+
}
|
|
318
|
+
case "graph.context": {
|
|
319
|
+
const nodeId = paramStringRequired(params, "nodeId");
|
|
320
|
+
if (!nodeId) {
|
|
321
|
+
return errorResult(
|
|
322
|
+
"query",
|
|
323
|
+
"memory",
|
|
324
|
+
operation,
|
|
325
|
+
"E_INVALID_INPUT",
|
|
326
|
+
"nodeId is required",
|
|
327
|
+
startTime
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
const result = await memoryGraphContext({ nodeId }, projectRoot);
|
|
331
|
+
return wrapResult(result, "query", "memory", operation, startTime);
|
|
332
|
+
}
|
|
333
|
+
case "graph.stats": {
|
|
334
|
+
const result = await memoryGraphStatsFull(projectRoot);
|
|
335
|
+
return wrapResult(result, "query", "memory", operation, startTime);
|
|
336
|
+
}
|
|
337
|
+
case "reason.why": {
|
|
338
|
+
const taskId = paramStringRequired(params, "taskId");
|
|
339
|
+
if (!taskId) {
|
|
340
|
+
return errorResult(
|
|
341
|
+
"query",
|
|
342
|
+
"memory",
|
|
343
|
+
operation,
|
|
344
|
+
"E_INVALID_INPUT",
|
|
345
|
+
"taskId is required",
|
|
346
|
+
startTime
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
const result = await memoryReasonWhy({ taskId }, projectRoot);
|
|
350
|
+
return wrapResult(result, "query", "memory", operation, startTime);
|
|
351
|
+
}
|
|
352
|
+
case "reason.similar": {
|
|
353
|
+
const entryId = paramStringRequired(params, "entryId");
|
|
354
|
+
if (!entryId) {
|
|
355
|
+
return errorResult(
|
|
356
|
+
"query",
|
|
357
|
+
"memory",
|
|
358
|
+
operation,
|
|
359
|
+
"E_INVALID_INPUT",
|
|
360
|
+
"entryId is required",
|
|
361
|
+
startTime
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
const result = await memoryReasonSimilar(
|
|
365
|
+
{ entryId, limit: paramNumber(params, "limit") },
|
|
366
|
+
projectRoot
|
|
367
|
+
);
|
|
368
|
+
return wrapResult(result, "query", "memory", operation, startTime);
|
|
369
|
+
}
|
|
370
|
+
case "search.hybrid": {
|
|
371
|
+
const query = paramStringRequired(params, "query");
|
|
372
|
+
if (!query) {
|
|
373
|
+
return errorResult(
|
|
374
|
+
"query",
|
|
375
|
+
"memory",
|
|
376
|
+
operation,
|
|
377
|
+
"E_INVALID_INPUT",
|
|
378
|
+
"query is required",
|
|
379
|
+
startTime
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
const result = await memorySearchHybrid(
|
|
383
|
+
{
|
|
384
|
+
query,
|
|
385
|
+
ftsWeight: paramNumber(params, "ftsWeight"),
|
|
386
|
+
vecWeight: paramNumber(params, "vecWeight"),
|
|
387
|
+
graphWeight: paramNumber(params, "graphWeight"),
|
|
388
|
+
limit: paramNumber(params, "limit")
|
|
389
|
+
},
|
|
390
|
+
projectRoot
|
|
391
|
+
);
|
|
392
|
+
return wrapResult(result, "query", "memory", operation, startTime);
|
|
393
|
+
}
|
|
394
|
+
case "quality": {
|
|
395
|
+
const result = await memoryQualityReport(projectRoot);
|
|
396
|
+
return wrapResult(result, "query", "memory", operation, startTime);
|
|
397
|
+
}
|
|
398
|
+
case "code.links": {
|
|
399
|
+
const { listCodeLinks } = await import("@cleocode/core/memory/graph-memory-bridge");
|
|
400
|
+
const links = await listCodeLinks(projectRoot);
|
|
401
|
+
return wrapResult(
|
|
402
|
+
{ success: true, data: links },
|
|
403
|
+
"query",
|
|
404
|
+
"memory",
|
|
405
|
+
operation,
|
|
406
|
+
startTime
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
case "code.memories-for-code": {
|
|
410
|
+
const symbol = paramStringRequired(params, "symbol");
|
|
411
|
+
if (!symbol) {
|
|
412
|
+
return errorResult(
|
|
413
|
+
"query",
|
|
414
|
+
"memory",
|
|
415
|
+
operation,
|
|
416
|
+
"E_INVALID_INPUT",
|
|
417
|
+
"symbol is required",
|
|
418
|
+
startTime
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
const { queryMemoriesForCode } = await import("@cleocode/core/memory/graph-memory-bridge");
|
|
422
|
+
const result = await queryMemoriesForCode(projectRoot, symbol);
|
|
423
|
+
return wrapResult(
|
|
424
|
+
{ success: true, data: result },
|
|
425
|
+
"query",
|
|
426
|
+
"memory",
|
|
427
|
+
operation,
|
|
428
|
+
startTime
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
case "code.for-memory": {
|
|
432
|
+
const memoryId = paramStringRequired(params, "memoryId");
|
|
433
|
+
if (!memoryId) {
|
|
434
|
+
return errorResult(
|
|
435
|
+
"query",
|
|
436
|
+
"memory",
|
|
437
|
+
operation,
|
|
438
|
+
"E_INVALID_INPUT",
|
|
439
|
+
"memoryId is required",
|
|
440
|
+
startTime
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
const { queryCodeForMemory } = await import("@cleocode/core/memory/graph-memory-bridge");
|
|
444
|
+
const result = await queryCodeForMemory(projectRoot, memoryId);
|
|
445
|
+
return wrapResult(
|
|
446
|
+
{ success: true, data: result },
|
|
447
|
+
"query",
|
|
448
|
+
"memory",
|
|
449
|
+
operation,
|
|
450
|
+
startTime
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
// T1262 — brain noise detector (read-only, E1-parallel per council verdict)
|
|
454
|
+
case "doctor": {
|
|
455
|
+
const { scanBrainNoise } = await import("@cleocode/core/memory/brain-doctor.js");
|
|
456
|
+
const result = await scanBrainNoise(projectRoot);
|
|
457
|
+
const assertClean = paramBool(params, "assert-clean");
|
|
458
|
+
if (assertClean) {
|
|
459
|
+
let pendingCandidates = 0;
|
|
460
|
+
try {
|
|
461
|
+
const { getBrainNativeDb: _getDoctorNativeDb } = await import("@cleocode/core/store/memory-sqlite.js");
|
|
462
|
+
const doctorNativeDb = _getDoctorNativeDb();
|
|
463
|
+
if (doctorNativeDb) {
|
|
464
|
+
const stagingTableRow = doctorNativeDb.prepare(
|
|
465
|
+
`SELECT name FROM sqlite_master WHERE type='table' AND name IN ('brain_observations_staging', 'brain_v2_candidate') ORDER BY CASE name WHEN 'brain_observations_staging' THEN 0 ELSE 1 END LIMIT 1`
|
|
466
|
+
).get();
|
|
467
|
+
if (stagingTableRow?.name) {
|
|
468
|
+
const countRow = doctorNativeDb.prepare(
|
|
469
|
+
`SELECT COUNT(*) AS cnt FROM ${stagingTableRow.name} WHERE validation_status = 'pending'`
|
|
470
|
+
).get();
|
|
471
|
+
pendingCandidates = countRow?.cnt ?? 0;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
} catch {
|
|
475
|
+
}
|
|
476
|
+
if (!result.isClean) {
|
|
477
|
+
return errorResult(
|
|
478
|
+
"query",
|
|
479
|
+
"memory",
|
|
480
|
+
operation,
|
|
481
|
+
"E_BRAIN_NOISE_DETECTED",
|
|
482
|
+
`Brain noise detected: ${result.findings.length} pattern(s) across ${result.totalScanned} entries. ` + result.findings.map((f) => `${f.pattern}(${f.count})`).join(", ") + ". Run `cleo memory doctor` for details. Fix noise before enabling Sentient v1 (M7 gate).",
|
|
483
|
+
startTime
|
|
484
|
+
);
|
|
485
|
+
}
|
|
486
|
+
if (pendingCandidates > 0) {
|
|
487
|
+
return errorResult(
|
|
488
|
+
"query",
|
|
489
|
+
"memory",
|
|
490
|
+
operation,
|
|
491
|
+
"E_SWEEP_PENDING",
|
|
492
|
+
`Staged sweep has ${pendingCandidates} pending brain_observations_staging rows. Run \`cleo memory sweep --status\` to review, then \`cleo memory sweep --approve <runId>\` to apply.`,
|
|
493
|
+
startTime
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
} else if (!result.isClean) {
|
|
497
|
+
}
|
|
498
|
+
return wrapResult(
|
|
499
|
+
{ success: true, data: { ...result, pendingCandidates: 0 } },
|
|
500
|
+
"query",
|
|
501
|
+
"memory",
|
|
502
|
+
operation,
|
|
503
|
+
startTime
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
// T1147 W7 — BRAIN noise sweep (shadow-write envelope, self-healing gate)
|
|
507
|
+
case "sweep": {
|
|
508
|
+
const dryRun = params?.["dry-run"] === true || params?.dryRun === true;
|
|
509
|
+
const approveRunId = paramString(params, "approve");
|
|
510
|
+
const statusQuery = params?.status === true;
|
|
511
|
+
const rollbackRunId = paramString(params, "rollback");
|
|
512
|
+
if (statusQuery) {
|
|
513
|
+
const { getBrainDb: _getBrainDb2, getBrainNativeDb: _getNativeDb2 } = await import("@cleocode/core/store/memory-sqlite.js");
|
|
514
|
+
const sweepDb = await _getBrainDb2(projectRoot);
|
|
515
|
+
const nativeDb2 = _getNativeDb2();
|
|
516
|
+
if (!nativeDb2) {
|
|
517
|
+
return errorResult(
|
|
518
|
+
"query",
|
|
519
|
+
"memory",
|
|
520
|
+
operation,
|
|
521
|
+
"E_DB_UNAVAILABLE",
|
|
522
|
+
"brain.db not available",
|
|
523
|
+
startTime
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
const rows = nativeDb2.prepare(
|
|
527
|
+
`SELECT id, status, rows_affected, created_at, approved_at, approved_by
|
|
528
|
+
FROM brain_backfill_runs
|
|
529
|
+
WHERE kind = 'noise-sweep-2440'
|
|
530
|
+
ORDER BY created_at DESC
|
|
531
|
+
LIMIT 20`
|
|
532
|
+
).all();
|
|
533
|
+
void sweepDb;
|
|
534
|
+
return wrapResult(
|
|
535
|
+
{ success: true, data: { runs: rows } },
|
|
536
|
+
"query",
|
|
537
|
+
"memory",
|
|
538
|
+
operation,
|
|
539
|
+
startTime
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
if (approveRunId) {
|
|
543
|
+
const { executeSweep } = await import("@cleocode/core/memory/brain-sweep-executor.js");
|
|
544
|
+
const result = await executeSweep({
|
|
545
|
+
projectRoot,
|
|
546
|
+
runId: approveRunId,
|
|
547
|
+
approvedBy: "cleo-cli"
|
|
548
|
+
});
|
|
549
|
+
if (!result.success) {
|
|
550
|
+
return errorResult(
|
|
551
|
+
"mutate",
|
|
552
|
+
"memory",
|
|
553
|
+
operation,
|
|
554
|
+
"E_SWEEP_FAILED",
|
|
555
|
+
result.errorMessage ?? "Sweep failed",
|
|
556
|
+
startTime
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
return wrapResult(
|
|
560
|
+
{ success: true, data: result },
|
|
561
|
+
"mutate",
|
|
562
|
+
"memory",
|
|
563
|
+
operation,
|
|
564
|
+
startTime
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
if (rollbackRunId) {
|
|
568
|
+
const { rollbackSweep } = await import("@cleocode/core/memory/brain-sweep-executor.js");
|
|
569
|
+
const rolled = await rollbackSweep(projectRoot, rollbackRunId);
|
|
570
|
+
if (!rolled) {
|
|
571
|
+
return errorResult(
|
|
572
|
+
"mutate",
|
|
573
|
+
"memory",
|
|
574
|
+
operation,
|
|
575
|
+
"E_SWEEP_ROLLBACK_FAILED",
|
|
576
|
+
`Run '${rollbackRunId}' not found or not in staged status`,
|
|
577
|
+
startTime
|
|
578
|
+
);
|
|
579
|
+
}
|
|
580
|
+
return wrapResult(
|
|
581
|
+
{ success: true, data: { rolledBack: rollbackRunId } },
|
|
582
|
+
"mutate",
|
|
583
|
+
"memory",
|
|
584
|
+
operation,
|
|
585
|
+
startTime
|
|
586
|
+
);
|
|
587
|
+
}
|
|
588
|
+
const { detectNoiseCandidates } = await import("@cleocode/core/memory/brain-noise-detector.js");
|
|
589
|
+
const detectResult = await detectNoiseCandidates(projectRoot, { dryRun });
|
|
590
|
+
return wrapResult(
|
|
591
|
+
{ success: true, data: detectResult },
|
|
592
|
+
dryRun ? "query" : "mutate",
|
|
593
|
+
"memory",
|
|
594
|
+
operation,
|
|
595
|
+
startTime
|
|
596
|
+
);
|
|
597
|
+
}
|
|
598
|
+
// T791 — LLM extraction backend status
|
|
599
|
+
case "llm-status": {
|
|
600
|
+
const _anthropicCred = resolveCredentials("anthropic");
|
|
601
|
+
const extractionEnabled = _anthropicCred.apiKey !== null;
|
|
602
|
+
const resolvedSource = (() => {
|
|
603
|
+
switch (_anthropicCred.source) {
|
|
604
|
+
case "env":
|
|
605
|
+
return "env";
|
|
606
|
+
case "claude-creds":
|
|
607
|
+
return "oauth";
|
|
608
|
+
case "global-config":
|
|
609
|
+
case "project-config":
|
|
610
|
+
return "config";
|
|
611
|
+
default:
|
|
612
|
+
return "none";
|
|
613
|
+
}
|
|
614
|
+
})();
|
|
615
|
+
const providers = OAUTH_STATUS_PROVIDERS.map(resolveProviderStatus);
|
|
616
|
+
let lastExtractionRun = null;
|
|
617
|
+
try {
|
|
618
|
+
await getBrainDb(projectRoot);
|
|
619
|
+
const nativeDb = getBrainNativeDb(projectRoot);
|
|
620
|
+
if (nativeDb) {
|
|
621
|
+
const row = nativeDb.prepare(
|
|
622
|
+
`SELECT created_at FROM brain_observations
|
|
623
|
+
WHERE source_type IN ('observer', 'reflector', 'transcript')
|
|
624
|
+
ORDER BY created_at DESC LIMIT 1`
|
|
625
|
+
).get();
|
|
626
|
+
if (row?.created_at) {
|
|
627
|
+
lastExtractionRun = row.created_at.replace(" ", "T");
|
|
628
|
+
if (!lastExtractionRun.includes("Z")) lastExtractionRun += "Z";
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
} catch {
|
|
632
|
+
}
|
|
633
|
+
return wrapResult(
|
|
634
|
+
{
|
|
635
|
+
success: true,
|
|
636
|
+
data: {
|
|
637
|
+
resolvedSource,
|
|
638
|
+
extractionEnabled,
|
|
639
|
+
lastExtractionRun,
|
|
640
|
+
testCommand: "cleo memory reflect --json",
|
|
641
|
+
providers
|
|
642
|
+
}
|
|
643
|
+
},
|
|
644
|
+
"query",
|
|
645
|
+
"memory",
|
|
646
|
+
operation,
|
|
647
|
+
startTime
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
// T792 — surface unverified-but-highly-cited entries as verification queue
|
|
651
|
+
case "pending-verify": {
|
|
652
|
+
const minCitations = paramNumber(params, "minCitations") ?? 5;
|
|
653
|
+
const limitVal = paramNumber(params, "limit") ?? 50;
|
|
654
|
+
try {
|
|
655
|
+
await getBrainDb(projectRoot);
|
|
656
|
+
const nativeDb = getBrainNativeDb(projectRoot);
|
|
657
|
+
if (!nativeDb) {
|
|
658
|
+
return errorResult(
|
|
659
|
+
"query",
|
|
660
|
+
"memory",
|
|
661
|
+
operation,
|
|
662
|
+
"E_DB_UNAVAILABLE",
|
|
663
|
+
"brain.db is unavailable",
|
|
664
|
+
startTime
|
|
665
|
+
);
|
|
666
|
+
}
|
|
667
|
+
const tables = [
|
|
668
|
+
{ name: "brain_observations", labelCol: "title" },
|
|
669
|
+
{ name: "brain_decisions", labelCol: "decision" },
|
|
670
|
+
{ name: "brain_patterns", labelCol: "pattern" },
|
|
671
|
+
{ name: "brain_learnings", labelCol: "insight" }
|
|
672
|
+
];
|
|
673
|
+
const allPending = [];
|
|
674
|
+
for (const t of tables) {
|
|
675
|
+
try {
|
|
676
|
+
const rawRows = nativeDb.prepare(
|
|
677
|
+
`SELECT id,
|
|
678
|
+
COALESCE(${t.labelCol}, id) AS title,
|
|
679
|
+
source_confidence,
|
|
680
|
+
citation_count,
|
|
681
|
+
memory_tier,
|
|
682
|
+
created_at
|
|
683
|
+
FROM ${t.name}
|
|
684
|
+
WHERE verified = 0
|
|
685
|
+
AND citation_count >= ?
|
|
686
|
+
AND invalid_at IS NULL
|
|
687
|
+
ORDER BY citation_count DESC
|
|
688
|
+
LIMIT ?`
|
|
689
|
+
).all(minCitations, limitVal);
|
|
690
|
+
const rows = rawRows.map((raw) => {
|
|
691
|
+
const r = raw;
|
|
692
|
+
return {
|
|
693
|
+
id: String(r["id"] ?? ""),
|
|
694
|
+
title: r["title"] != null ? String(r["title"]) : null,
|
|
695
|
+
source_confidence: r["source_confidence"] != null ? String(r["source_confidence"]) : null,
|
|
696
|
+
citation_count: Number(r["citation_count"] ?? 0),
|
|
697
|
+
memory_tier: r["memory_tier"] != null ? String(r["memory_tier"]) : null,
|
|
698
|
+
created_at: String(r["created_at"] ?? "")
|
|
699
|
+
};
|
|
700
|
+
});
|
|
701
|
+
for (const row of rows) {
|
|
702
|
+
allPending.push({ ...row, table: t.name.replace("brain_", "") });
|
|
703
|
+
}
|
|
704
|
+
} catch {
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
allPending.sort((a, b) => b.citation_count - a.citation_count);
|
|
708
|
+
const items = allPending.slice(0, limitVal);
|
|
709
|
+
return wrapResult(
|
|
710
|
+
{
|
|
711
|
+
success: true,
|
|
712
|
+
data: {
|
|
713
|
+
count: items.length,
|
|
714
|
+
minCitations,
|
|
715
|
+
items,
|
|
716
|
+
hint: `Run 'cleo memory verify <id>' to promote an entry to verified=true`
|
|
717
|
+
}
|
|
718
|
+
},
|
|
719
|
+
"query",
|
|
720
|
+
"memory",
|
|
721
|
+
operation,
|
|
722
|
+
startTime
|
|
723
|
+
);
|
|
724
|
+
} catch (dbErr) {
|
|
725
|
+
return handleErrorResult("query", "memory", operation, dbErr, startTime);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
// T1006 — summarized top-N observations as session briefing digest
|
|
729
|
+
case "digest": {
|
|
730
|
+
const limitVal = paramNumber(params, "limit") ?? 10;
|
|
731
|
+
try {
|
|
732
|
+
await getBrainDb(projectRoot);
|
|
733
|
+
const nativeDb = getBrainNativeDb(projectRoot);
|
|
734
|
+
if (!nativeDb) {
|
|
735
|
+
return errorResult(
|
|
736
|
+
"query",
|
|
737
|
+
"memory",
|
|
738
|
+
operation,
|
|
739
|
+
"E_DB_UNAVAILABLE",
|
|
740
|
+
"brain.db is unavailable",
|
|
741
|
+
startTime
|
|
742
|
+
);
|
|
743
|
+
}
|
|
744
|
+
let rows = [];
|
|
745
|
+
try {
|
|
746
|
+
const rawRows = nativeDb.prepare(
|
|
747
|
+
`SELECT id,
|
|
748
|
+
title,
|
|
749
|
+
text,
|
|
750
|
+
citation_count,
|
|
751
|
+
quality_score,
|
|
752
|
+
memory_tier,
|
|
753
|
+
created_at
|
|
754
|
+
FROM brain_observations
|
|
755
|
+
WHERE invalid_at IS NULL
|
|
756
|
+
ORDER BY citation_count DESC, quality_score DESC
|
|
757
|
+
LIMIT ?`
|
|
758
|
+
).all(limitVal);
|
|
759
|
+
rows = rawRows.map((raw) => {
|
|
760
|
+
const r = raw;
|
|
761
|
+
return {
|
|
762
|
+
id: String(r["id"] ?? ""),
|
|
763
|
+
title: r["title"] != null ? String(r["title"]) : null,
|
|
764
|
+
text: String(r["text"] ?? ""),
|
|
765
|
+
citation_count: Number(r["citation_count"] ?? 0),
|
|
766
|
+
quality_score: r["quality_score"] != null ? Number(r["quality_score"]) : null,
|
|
767
|
+
memory_tier: r["memory_tier"] != null ? String(r["memory_tier"]) : null,
|
|
768
|
+
created_at: String(r["created_at"] ?? "")
|
|
769
|
+
};
|
|
770
|
+
});
|
|
771
|
+
} catch {
|
|
772
|
+
}
|
|
773
|
+
const summaryLines = rows.map((r, i) => {
|
|
774
|
+
const label = r.title ?? r.id;
|
|
775
|
+
const snippet = r.text.slice(0, 80).replace(/\n/g, " ");
|
|
776
|
+
return `${i + 1}. [${r.id}] ${label} \u2014 ${snippet}${r.text.length > 80 ? "\u2026" : ""}`;
|
|
777
|
+
});
|
|
778
|
+
return wrapResult(
|
|
779
|
+
{
|
|
780
|
+
success: true,
|
|
781
|
+
data: {
|
|
782
|
+
count: rows.length,
|
|
783
|
+
limit: limitVal,
|
|
784
|
+
summary: summaryLines.join("\n"),
|
|
785
|
+
observations: rows
|
|
786
|
+
}
|
|
787
|
+
},
|
|
788
|
+
"query",
|
|
789
|
+
"memory",
|
|
790
|
+
operation,
|
|
791
|
+
startTime
|
|
792
|
+
);
|
|
793
|
+
} catch (dbErr) {
|
|
794
|
+
return handleErrorResult("query", "memory", operation, dbErr, startTime);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
// T1006 — tail recent observations with optional filters
|
|
798
|
+
case "recent": {
|
|
799
|
+
const limitVal = paramNumber(params, "limit") ?? 20;
|
|
800
|
+
const sinceParam = paramString(params, "since");
|
|
801
|
+
const typeFilter = paramString(params, "type");
|
|
802
|
+
const sessionFilter = paramString(params, "session");
|
|
803
|
+
const tierFilter = paramString(params, "tier");
|
|
804
|
+
try {
|
|
805
|
+
await getBrainDb(projectRoot);
|
|
806
|
+
const nativeDb = getBrainNativeDb(projectRoot);
|
|
807
|
+
if (!nativeDb) {
|
|
808
|
+
return errorResult(
|
|
809
|
+
"query",
|
|
810
|
+
"memory",
|
|
811
|
+
operation,
|
|
812
|
+
"E_DB_UNAVAILABLE",
|
|
813
|
+
"brain.db is unavailable",
|
|
814
|
+
startTime
|
|
815
|
+
);
|
|
816
|
+
}
|
|
817
|
+
let sinceIso;
|
|
818
|
+
if (sinceParam) {
|
|
819
|
+
const durationMatch = /^(\d+)(m|h|d|w)$/i.exec(sinceParam);
|
|
820
|
+
if (durationMatch) {
|
|
821
|
+
const amount = Number(durationMatch[1]);
|
|
822
|
+
const unit = durationMatch[2].toLowerCase();
|
|
823
|
+
const ms = unit === "m" ? amount * 6e4 : unit === "h" ? amount * 36e5 : unit === "d" ? amount * 864e5 : amount * 7 * 864e5;
|
|
824
|
+
sinceIso = new Date(Date.now() - ms).toISOString().replace("T", " ").slice(0, 19);
|
|
825
|
+
} else {
|
|
826
|
+
sinceIso = sinceParam;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
const clauses = ["invalid_at IS NULL"];
|
|
830
|
+
const bindArgs = [];
|
|
831
|
+
if (sinceIso) {
|
|
832
|
+
clauses.push("created_at >= ?");
|
|
833
|
+
bindArgs.push(sinceIso);
|
|
834
|
+
}
|
|
835
|
+
if (typeFilter) {
|
|
836
|
+
clauses.push("type = ?");
|
|
837
|
+
bindArgs.push(typeFilter);
|
|
838
|
+
}
|
|
839
|
+
if (sessionFilter) {
|
|
840
|
+
clauses.push("source_session_id = ?");
|
|
841
|
+
bindArgs.push(sessionFilter);
|
|
842
|
+
}
|
|
843
|
+
if (tierFilter) {
|
|
844
|
+
clauses.push("memory_tier = ?");
|
|
845
|
+
bindArgs.push(tierFilter);
|
|
846
|
+
}
|
|
847
|
+
bindArgs.push(limitVal);
|
|
848
|
+
const whereClause = clauses.join(" AND ");
|
|
849
|
+
const rawRows = nativeDb.prepare(
|
|
850
|
+
`SELECT id, title, narrative AS text, type, source_session_id, memory_tier, created_at
|
|
851
|
+
FROM brain_observations
|
|
852
|
+
WHERE ${whereClause}
|
|
853
|
+
ORDER BY created_at DESC
|
|
854
|
+
LIMIT ?`
|
|
855
|
+
).all(...bindArgs);
|
|
856
|
+
const rows = rawRows.map((raw) => {
|
|
857
|
+
const r = raw;
|
|
858
|
+
return {
|
|
859
|
+
id: String(r["id"] ?? ""),
|
|
860
|
+
title: r["title"] != null ? String(r["title"]) : null,
|
|
861
|
+
text: String(r["text"] ?? ""),
|
|
862
|
+
type: r["type"] != null ? String(r["type"]) : null,
|
|
863
|
+
source_session_id: r["source_session_id"] != null ? String(r["source_session_id"]) : null,
|
|
864
|
+
memory_tier: r["memory_tier"] != null ? String(r["memory_tier"]) : null,
|
|
865
|
+
created_at: String(r["created_at"] ?? "")
|
|
866
|
+
};
|
|
867
|
+
});
|
|
868
|
+
return wrapResult(
|
|
869
|
+
{
|
|
870
|
+
success: true,
|
|
871
|
+
data: {
|
|
872
|
+
count: rows.length,
|
|
873
|
+
limit: limitVal,
|
|
874
|
+
since: sinceIso ?? null,
|
|
875
|
+
observations: rows
|
|
876
|
+
}
|
|
877
|
+
},
|
|
878
|
+
"query",
|
|
879
|
+
"memory",
|
|
880
|
+
operation,
|
|
881
|
+
startTime
|
|
882
|
+
);
|
|
883
|
+
} catch (dbErr) {
|
|
884
|
+
return handleErrorResult("query", "memory", operation, dbErr, startTime);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
// T1006 — read diary-typed observations
|
|
888
|
+
case "diary": {
|
|
889
|
+
const limitVal = paramNumber(params, "limit") ?? 20;
|
|
890
|
+
try {
|
|
891
|
+
await getBrainDb(projectRoot);
|
|
892
|
+
const nativeDb = getBrainNativeDb(projectRoot);
|
|
893
|
+
if (!nativeDb) {
|
|
894
|
+
return errorResult(
|
|
895
|
+
"query",
|
|
896
|
+
"memory",
|
|
897
|
+
operation,
|
|
898
|
+
"E_DB_UNAVAILABLE",
|
|
899
|
+
"brain.db is unavailable",
|
|
900
|
+
startTime
|
|
901
|
+
);
|
|
902
|
+
}
|
|
903
|
+
const rawRows = nativeDb.prepare(
|
|
904
|
+
`SELECT id, title, narrative AS text, source_session_id, memory_tier, created_at
|
|
905
|
+
FROM brain_observations
|
|
906
|
+
WHERE type = 'diary'
|
|
907
|
+
AND invalid_at IS NULL
|
|
908
|
+
ORDER BY created_at DESC
|
|
909
|
+
LIMIT ?`
|
|
910
|
+
).all(limitVal);
|
|
911
|
+
const rows = rawRows.map((raw) => {
|
|
912
|
+
const r = raw;
|
|
913
|
+
return {
|
|
914
|
+
id: String(r["id"] ?? ""),
|
|
915
|
+
title: r["title"] != null ? String(r["title"]) : null,
|
|
916
|
+
text: String(r["text"] ?? ""),
|
|
917
|
+
source_session_id: r["source_session_id"] != null ? String(r["source_session_id"]) : null,
|
|
918
|
+
memory_tier: r["memory_tier"] != null ? String(r["memory_tier"]) : null,
|
|
919
|
+
created_at: String(r["created_at"] ?? "")
|
|
920
|
+
};
|
|
921
|
+
});
|
|
922
|
+
return wrapResult(
|
|
923
|
+
{
|
|
924
|
+
success: true,
|
|
925
|
+
data: {
|
|
926
|
+
count: rows.length,
|
|
927
|
+
limit: limitVal,
|
|
928
|
+
type: "diary",
|
|
929
|
+
entries: rows
|
|
930
|
+
}
|
|
931
|
+
},
|
|
932
|
+
"query",
|
|
933
|
+
"memory",
|
|
934
|
+
operation,
|
|
935
|
+
startTime
|
|
936
|
+
);
|
|
937
|
+
} catch (dbErr) {
|
|
938
|
+
return handleErrorResult("query", "memory", operation, dbErr, startTime);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
// T1006 — long-poll stream of recent brain writes (SSE-style polling stub)
|
|
942
|
+
// Returns the latest N observations created after an optional cursor.
|
|
943
|
+
// Clients call this in a loop, advancing the cursor with the returned `nextCursor`.
|
|
944
|
+
case "watch": {
|
|
945
|
+
const cursorParam = paramString(params, "cursor");
|
|
946
|
+
const limitVal = paramNumber(params, "limit") ?? 10;
|
|
947
|
+
try {
|
|
948
|
+
await getBrainDb(projectRoot);
|
|
949
|
+
const nativeDb = getBrainNativeDb(projectRoot);
|
|
950
|
+
if (!nativeDb) {
|
|
951
|
+
return errorResult(
|
|
952
|
+
"query",
|
|
953
|
+
"memory",
|
|
954
|
+
operation,
|
|
955
|
+
"E_DB_UNAVAILABLE",
|
|
956
|
+
"brain.db is unavailable",
|
|
957
|
+
startTime
|
|
958
|
+
);
|
|
959
|
+
}
|
|
960
|
+
const clauses = ["invalid_at IS NULL"];
|
|
961
|
+
const bindArgs = [];
|
|
962
|
+
if (cursorParam) {
|
|
963
|
+
clauses.push("created_at > ?");
|
|
964
|
+
bindArgs.push(cursorParam);
|
|
965
|
+
}
|
|
966
|
+
bindArgs.push(limitVal);
|
|
967
|
+
const rawRows = nativeDb.prepare(
|
|
968
|
+
`SELECT id, title, narrative AS text, type, memory_tier, created_at
|
|
969
|
+
FROM brain_observations
|
|
970
|
+
WHERE ${clauses.join(" AND ")}
|
|
971
|
+
ORDER BY created_at ASC
|
|
972
|
+
LIMIT ?`
|
|
973
|
+
).all(...bindArgs);
|
|
974
|
+
const rows = rawRows.map((raw) => {
|
|
975
|
+
const r = raw;
|
|
976
|
+
return {
|
|
977
|
+
id: String(r["id"] ?? ""),
|
|
978
|
+
title: r["title"] != null ? String(r["title"]) : null,
|
|
979
|
+
text: String(r["text"] ?? ""),
|
|
980
|
+
type: r["type"] != null ? String(r["type"]) : null,
|
|
981
|
+
memory_tier: r["memory_tier"] != null ? String(r["memory_tier"]) : null,
|
|
982
|
+
created_at: String(r["created_at"] ?? "")
|
|
983
|
+
};
|
|
984
|
+
});
|
|
985
|
+
const nextCursor = rows.length > 0 ? rows[rows.length - 1].created_at : cursorParam ?? null;
|
|
986
|
+
return wrapResult(
|
|
987
|
+
{
|
|
988
|
+
success: true,
|
|
989
|
+
data: {
|
|
990
|
+
count: rows.length,
|
|
991
|
+
cursor: cursorParam ?? null,
|
|
992
|
+
nextCursor,
|
|
993
|
+
events: rows,
|
|
994
|
+
hint: "Poll again with cursor=nextCursor to stream new writes"
|
|
995
|
+
}
|
|
996
|
+
},
|
|
997
|
+
"query",
|
|
998
|
+
"memory",
|
|
999
|
+
operation,
|
|
1000
|
+
startTime
|
|
1001
|
+
);
|
|
1002
|
+
} catch (dbErr) {
|
|
1003
|
+
return handleErrorResult("query", "memory", operation, dbErr, startTime);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
// T1003 — list staged backfill runs (pending/approved/rolled-back)
|
|
1007
|
+
case "backfill.list": {
|
|
1008
|
+
try {
|
|
1009
|
+
const status = paramString(params, "status");
|
|
1010
|
+
const limit = paramNumber(params, "limit");
|
|
1011
|
+
const runs = await listBackfillRuns(projectRoot, { status, limit });
|
|
1012
|
+
return wrapResult(
|
|
1013
|
+
{
|
|
1014
|
+
success: true,
|
|
1015
|
+
data: {
|
|
1016
|
+
count: runs.length,
|
|
1017
|
+
runs,
|
|
1018
|
+
hint: `Use 'cleo memory backfill.approve <runId>' or 'cleo memory backfill.rollback <runId>'`
|
|
1019
|
+
}
|
|
1020
|
+
},
|
|
1021
|
+
"query",
|
|
1022
|
+
"memory",
|
|
1023
|
+
operation,
|
|
1024
|
+
startTime
|
|
1025
|
+
);
|
|
1026
|
+
} catch (listErr) {
|
|
1027
|
+
return handleErrorResult("query", "memory", operation, listErr, startTime);
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
// T999 — stream brain.db memory-bridge content directly (cli mode default)
|
|
1031
|
+
case "bridge": {
|
|
1032
|
+
const content = await generateMemoryBridgeContent(projectRoot);
|
|
1033
|
+
return wrapResult(
|
|
1034
|
+
{ success: true, data: { content } },
|
|
1035
|
+
"query",
|
|
1036
|
+
"memory",
|
|
1037
|
+
operation,
|
|
1038
|
+
startTime
|
|
1039
|
+
);
|
|
1040
|
+
}
|
|
1041
|
+
// T997 — read-only view over STDP weights + retrieval log + citation data
|
|
1042
|
+
case "promote-explain": {
|
|
1043
|
+
const entryId = paramStringRequired(params, "id");
|
|
1044
|
+
if (!entryId) {
|
|
1045
|
+
return errorResult(
|
|
1046
|
+
"query",
|
|
1047
|
+
"memory",
|
|
1048
|
+
operation,
|
|
1049
|
+
"E_INVALID_INPUT",
|
|
1050
|
+
"id is required",
|
|
1051
|
+
startTime
|
|
1052
|
+
);
|
|
1053
|
+
}
|
|
1054
|
+
try {
|
|
1055
|
+
await getBrainDb(projectRoot);
|
|
1056
|
+
const nativeDb = getBrainNativeDb(projectRoot);
|
|
1057
|
+
if (!nativeDb) {
|
|
1058
|
+
return errorResult(
|
|
1059
|
+
"query",
|
|
1060
|
+
"memory",
|
|
1061
|
+
operation,
|
|
1062
|
+
"E_DB_UNAVAILABLE",
|
|
1063
|
+
"brain.db is unavailable",
|
|
1064
|
+
startTime
|
|
1065
|
+
);
|
|
1066
|
+
}
|
|
1067
|
+
const typedTables = [
|
|
1068
|
+
{ name: "brain_observations", labelCol: "title" },
|
|
1069
|
+
{ name: "brain_decisions", labelCol: "decision" },
|
|
1070
|
+
{ name: "brain_patterns", labelCol: "pattern" },
|
|
1071
|
+
{ name: "brain_learnings", labelCol: "insight" }
|
|
1072
|
+
];
|
|
1073
|
+
let foundTable = "";
|
|
1074
|
+
let typedRow;
|
|
1075
|
+
for (const t of typedTables) {
|
|
1076
|
+
try {
|
|
1077
|
+
const row = nativeDb.prepare(
|
|
1078
|
+
`SELECT id, citation_count, quality_score, memory_tier, tier_promoted_at, verified
|
|
1079
|
+
FROM ${t.name}
|
|
1080
|
+
WHERE id = ? AND invalid_at IS NULL
|
|
1081
|
+
LIMIT 1`
|
|
1082
|
+
).get(entryId);
|
|
1083
|
+
if (row) {
|
|
1084
|
+
typedRow = row;
|
|
1085
|
+
foundTable = t.name.replace("brain_", "");
|
|
1086
|
+
break;
|
|
1087
|
+
}
|
|
1088
|
+
} catch {
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
if (!typedRow) {
|
|
1092
|
+
return errorResult(
|
|
1093
|
+
"query",
|
|
1094
|
+
"memory",
|
|
1095
|
+
operation,
|
|
1096
|
+
"E_NOT_FOUND",
|
|
1097
|
+
`Entry '${entryId}' not found in any brain table (or is invalidated)`,
|
|
1098
|
+
startTime
|
|
1099
|
+
);
|
|
1100
|
+
}
|
|
1101
|
+
let pruneCandidate = false;
|
|
1102
|
+
try {
|
|
1103
|
+
const pruneRow = nativeDb.prepare(`SELECT prune_candidate FROM brain_${foundTable} WHERE id = ? LIMIT 1`).get(entryId);
|
|
1104
|
+
pruneCandidate = (pruneRow?.prune_candidate ?? 0) === 1;
|
|
1105
|
+
} catch {
|
|
1106
|
+
}
|
|
1107
|
+
let stdpWeights = [];
|
|
1108
|
+
try {
|
|
1109
|
+
const stmt = nativeDb.prepare(
|
|
1110
|
+
`SELECT from_id, to_id, edge_type, weight,
|
|
1111
|
+
COALESCE(reinforcement_count, 0) AS reinforcement_count,
|
|
1112
|
+
last_reinforced_at
|
|
1113
|
+
FROM brain_page_edges
|
|
1114
|
+
WHERE (from_id = ? OR to_id = ?)
|
|
1115
|
+
AND plasticity_class IN ('hebbian', 'stdp')
|
|
1116
|
+
ORDER BY weight DESC
|
|
1117
|
+
LIMIT 20`
|
|
1118
|
+
);
|
|
1119
|
+
stdpWeights = typedAll(stmt, entryId, entryId);
|
|
1120
|
+
} catch {
|
|
1121
|
+
try {
|
|
1122
|
+
const stmt = nativeDb.prepare(
|
|
1123
|
+
`SELECT from_id, to_id, edge_type, weight,
|
|
1124
|
+
COALESCE(reinforcement_count, 0) AS reinforcement_count,
|
|
1125
|
+
last_reinforced_at
|
|
1126
|
+
FROM brain_page_edges
|
|
1127
|
+
WHERE from_id = ? OR to_id = ?
|
|
1128
|
+
ORDER BY weight DESC
|
|
1129
|
+
LIMIT 20`
|
|
1130
|
+
);
|
|
1131
|
+
stdpWeights = typedAll(stmt, entryId, entryId);
|
|
1132
|
+
} catch {
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
let retrievalCount = 0;
|
|
1136
|
+
let lastAccessedAt = null;
|
|
1137
|
+
try {
|
|
1138
|
+
const logRow = nativeDb.prepare(
|
|
1139
|
+
`SELECT COUNT(*) AS retrieval_count,
|
|
1140
|
+
MAX(created_at) AS last_accessed_at
|
|
1141
|
+
FROM brain_retrieval_log
|
|
1142
|
+
WHERE entry_ids LIKE ?`
|
|
1143
|
+
).get(`%${entryId}%`);
|
|
1144
|
+
retrievalCount = logRow?.retrieval_count ?? 0;
|
|
1145
|
+
lastAccessedAt = logRow?.last_accessed_at ?? null;
|
|
1146
|
+
if (lastAccessedAt && !lastAccessedAt.includes("T")) {
|
|
1147
|
+
lastAccessedAt = lastAccessedAt.replace(" ", "T");
|
|
1148
|
+
if (!lastAccessedAt.endsWith("Z")) lastAccessedAt += "Z";
|
|
1149
|
+
}
|
|
1150
|
+
} catch {
|
|
1151
|
+
}
|
|
1152
|
+
const citationCount = typedRow.citation_count ?? 0;
|
|
1153
|
+
const qualityScore = typedRow.quality_score ?? null;
|
|
1154
|
+
const memoryTier = typedRow.memory_tier ?? null;
|
|
1155
|
+
const promotedAt = typedRow.tier_promoted_at ?? null;
|
|
1156
|
+
const verified = typedRow.verified === 1;
|
|
1157
|
+
const stdpWeightMax = stdpWeights.length > 0 ? Math.max(...stdpWeights.map((e) => e.weight)) : 0;
|
|
1158
|
+
let tier;
|
|
1159
|
+
let explanation;
|
|
1160
|
+
if (pruneCandidate) {
|
|
1161
|
+
tier = "rejected";
|
|
1162
|
+
explanation = `Entry flagged as prune candidate. quality_score=${qualityScore ?? "null"}, citation_count=${citationCount}, retrieval_count=${retrievalCount}. Meets pruning criteria: low quality and/or zero citations over time.`;
|
|
1163
|
+
} else if (memoryTier === "long" || memoryTier === "medium" || verified || promotedAt !== null) {
|
|
1164
|
+
tier = "promoted";
|
|
1165
|
+
explanation = `Entry promoted to memory tier '${memoryTier ?? "promoted"}'. citation_count=${citationCount}, retrieval_count=${retrievalCount}, stdp_weight_max=${stdpWeightMax.toFixed(3)}, verified=${verified}. ` + (promotedAt ? `Tier promotion recorded at ${promotedAt}.` : "Verified by owner.");
|
|
1166
|
+
} else {
|
|
1167
|
+
tier = "pending";
|
|
1168
|
+
explanation = `Entry has not yet been promoted or flagged for pruning. memory_tier='${memoryTier ?? "short"}', citation_count=${citationCount}, retrieval_count=${retrievalCount}, stdp_weight_max=${stdpWeightMax.toFixed(3)}. Increase retrieval frequency or citation count to qualify for promotion.`;
|
|
1169
|
+
}
|
|
1170
|
+
const scoreBreakdown = {
|
|
1171
|
+
stdpWeightMax,
|
|
1172
|
+
retrievalCount,
|
|
1173
|
+
lastAccessedAt,
|
|
1174
|
+
citationCount,
|
|
1175
|
+
qualityScore,
|
|
1176
|
+
pruneCandidate,
|
|
1177
|
+
verified
|
|
1178
|
+
};
|
|
1179
|
+
const weights = stdpWeights.map((e) => ({
|
|
1180
|
+
fromId: e.from_id,
|
|
1181
|
+
toId: e.to_id,
|
|
1182
|
+
edgeType: e.edge_type,
|
|
1183
|
+
weight: e.weight,
|
|
1184
|
+
reinforcementCount: e.reinforcement_count,
|
|
1185
|
+
lastReinforcedAt: e.last_reinforced_at
|
|
1186
|
+
}));
|
|
1187
|
+
return wrapResult(
|
|
1188
|
+
{
|
|
1189
|
+
success: true,
|
|
1190
|
+
data: {
|
|
1191
|
+
id: entryId,
|
|
1192
|
+
table: foundTable,
|
|
1193
|
+
tier,
|
|
1194
|
+
explanation,
|
|
1195
|
+
promotedAt: promotedAt ?? null,
|
|
1196
|
+
stdpWeights: weights,
|
|
1197
|
+
scoreBreakdown
|
|
1198
|
+
}
|
|
1199
|
+
},
|
|
1200
|
+
"query",
|
|
1201
|
+
"memory",
|
|
1202
|
+
operation,
|
|
1203
|
+
startTime
|
|
1204
|
+
);
|
|
1205
|
+
} catch (dbErr) {
|
|
1206
|
+
return handleErrorResult("query", "memory", operation, dbErr, startTime);
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
default:
|
|
1210
|
+
return unsupportedOp("query", "memory", operation, startTime);
|
|
1211
|
+
}
|
|
1212
|
+
} catch (error) {
|
|
1213
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1214
|
+
getLogger("domain:memory").error(
|
|
1215
|
+
{ gateway: "query", domain: "memory", operation, err: error },
|
|
1216
|
+
message
|
|
1217
|
+
);
|
|
1218
|
+
return handleErrorResult("query", "memory", operation, error, startTime);
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
// -----------------------------------------------------------------------
|
|
1222
|
+
// Mutate
|
|
1223
|
+
// -----------------------------------------------------------------------
|
|
1224
|
+
async mutate(operation, params) {
|
|
1225
|
+
const projectRoot = getProjectRoot();
|
|
1226
|
+
const startTime = Date.now();
|
|
1227
|
+
try {
|
|
1228
|
+
switch (operation) {
|
|
1229
|
+
case "observe": {
|
|
1230
|
+
const text = paramStringRequired(params, "text");
|
|
1231
|
+
if (!text) {
|
|
1232
|
+
return errorResult(
|
|
1233
|
+
"mutate",
|
|
1234
|
+
"memory",
|
|
1235
|
+
operation,
|
|
1236
|
+
"E_INVALID_INPUT",
|
|
1237
|
+
"text is required",
|
|
1238
|
+
startTime
|
|
1239
|
+
);
|
|
1240
|
+
}
|
|
1241
|
+
let attachmentRefs;
|
|
1242
|
+
const attachArr = paramStringArray(params, "attach");
|
|
1243
|
+
const attachStr = paramString(params, "attach");
|
|
1244
|
+
if (attachArr !== void 0) {
|
|
1245
|
+
attachmentRefs = attachArr.filter((r) => r.length > 0);
|
|
1246
|
+
} else if (attachStr?.trim()) {
|
|
1247
|
+
attachmentRefs = attachStr.split(",").map((r) => r.trim()).filter(Boolean);
|
|
1248
|
+
}
|
|
1249
|
+
const result = await memoryObserve(
|
|
1250
|
+
{
|
|
1251
|
+
text,
|
|
1252
|
+
title: paramString(params, "title"),
|
|
1253
|
+
type: paramString(params, "type"),
|
|
1254
|
+
project: paramString(params, "project"),
|
|
1255
|
+
sourceSessionId: paramString(params, "sourceSessionId"),
|
|
1256
|
+
sourceType: paramString(params, "sourceType"),
|
|
1257
|
+
// T417: optional agent provenance for mental model observations
|
|
1258
|
+
agent: paramString(params, "agent"),
|
|
1259
|
+
// T799: optional attachment refs
|
|
1260
|
+
attachmentRefs,
|
|
1261
|
+
// T12494: interactive observe opts in to the System One type choice.
|
|
1262
|
+
askTypeDecision: true
|
|
1263
|
+
},
|
|
1264
|
+
projectRoot
|
|
1265
|
+
);
|
|
1266
|
+
return wrapResult(result, "mutate", "memory", operation, startTime);
|
|
1267
|
+
}
|
|
1268
|
+
case "decision.store": {
|
|
1269
|
+
const decision = paramStringRequired(params, "decision");
|
|
1270
|
+
const rationale = paramStringRequired(params, "rationale");
|
|
1271
|
+
if (!decision || !rationale) {
|
|
1272
|
+
return errorResult(
|
|
1273
|
+
"mutate",
|
|
1274
|
+
"memory",
|
|
1275
|
+
operation,
|
|
1276
|
+
"E_INVALID_INPUT",
|
|
1277
|
+
"decision and rationale are required",
|
|
1278
|
+
startTime
|
|
1279
|
+
);
|
|
1280
|
+
}
|
|
1281
|
+
const confirmationStateRaw = paramString(params, "confirmationState");
|
|
1282
|
+
const decidedByRaw = paramString(params, "decidedBy");
|
|
1283
|
+
const result = await memoryDecisionStore(
|
|
1284
|
+
{
|
|
1285
|
+
decision,
|
|
1286
|
+
rationale,
|
|
1287
|
+
alternatives: paramStringArray(params, "alternatives"),
|
|
1288
|
+
taskId: paramString(params, "taskId"),
|
|
1289
|
+
sessionId: paramString(params, "sessionId"),
|
|
1290
|
+
adrPath: paramString(params, "adrPath"),
|
|
1291
|
+
supersedes: paramString(params, "supersedes"),
|
|
1292
|
+
confirmationState: confirmationStateRaw === "proposed" || confirmationStateRaw === "accepted" || confirmationStateRaw === "superseded" ? confirmationStateRaw : void 0,
|
|
1293
|
+
decidedBy: decidedByRaw === "owner" || decidedByRaw === "council" || decidedByRaw === "agent" ? decidedByRaw : void 0
|
|
1294
|
+
},
|
|
1295
|
+
projectRoot
|
|
1296
|
+
);
|
|
1297
|
+
return wrapResult(result, "mutate", "memory", operation, startTime);
|
|
1298
|
+
}
|
|
1299
|
+
case "pattern.store": {
|
|
1300
|
+
const patternText = paramStringRequired(params, "pattern");
|
|
1301
|
+
const context = paramStringRequired(params, "context");
|
|
1302
|
+
if (!patternText || !context) {
|
|
1303
|
+
return errorResult(
|
|
1304
|
+
"mutate",
|
|
1305
|
+
"memory",
|
|
1306
|
+
operation,
|
|
1307
|
+
"E_INVALID_INPUT",
|
|
1308
|
+
"pattern and context are required",
|
|
1309
|
+
startTime
|
|
1310
|
+
);
|
|
1311
|
+
}
|
|
1312
|
+
const storePatternType = paramString(params, "type");
|
|
1313
|
+
const storePatternImpact = paramString(params, "impact");
|
|
1314
|
+
const result = await memoryPatternStore(
|
|
1315
|
+
{
|
|
1316
|
+
type: storePatternType || "workflow",
|
|
1317
|
+
pattern: patternText,
|
|
1318
|
+
context,
|
|
1319
|
+
impact: storePatternImpact,
|
|
1320
|
+
antiPattern: paramString(params, "antiPattern"),
|
|
1321
|
+
mitigation: paramString(params, "mitigation"),
|
|
1322
|
+
examples: paramStringArray(params, "examples"),
|
|
1323
|
+
successRate: paramNumber(params, "successRate")
|
|
1324
|
+
},
|
|
1325
|
+
projectRoot
|
|
1326
|
+
);
|
|
1327
|
+
return wrapResult(result, "mutate", "memory", operation, startTime);
|
|
1328
|
+
}
|
|
1329
|
+
case "learning.store": {
|
|
1330
|
+
const insight = paramStringRequired(params, "insight");
|
|
1331
|
+
const source = paramStringRequired(params, "source");
|
|
1332
|
+
if (!insight || !source) {
|
|
1333
|
+
return errorResult(
|
|
1334
|
+
"mutate",
|
|
1335
|
+
"memory",
|
|
1336
|
+
operation,
|
|
1337
|
+
"E_INVALID_INPUT",
|
|
1338
|
+
"insight and source are required",
|
|
1339
|
+
startTime
|
|
1340
|
+
);
|
|
1341
|
+
}
|
|
1342
|
+
const result = await memoryLearningStore(
|
|
1343
|
+
{
|
|
1344
|
+
insight,
|
|
1345
|
+
source,
|
|
1346
|
+
confidence: paramNumber(params, "confidence") ?? 0.5,
|
|
1347
|
+
actionable: paramBool(params, "actionable"),
|
|
1348
|
+
application: paramString(params, "application"),
|
|
1349
|
+
applicableTypes: paramStringArray(params, "applicableTypes")
|
|
1350
|
+
},
|
|
1351
|
+
projectRoot
|
|
1352
|
+
);
|
|
1353
|
+
return wrapResult(result, "mutate", "memory", operation, startTime);
|
|
1354
|
+
}
|
|
1355
|
+
case "link": {
|
|
1356
|
+
const taskId = paramStringRequired(params, "taskId");
|
|
1357
|
+
const entryId = paramStringRequired(params, "entryId");
|
|
1358
|
+
if (!taskId || !entryId) {
|
|
1359
|
+
return errorResult(
|
|
1360
|
+
"mutate",
|
|
1361
|
+
"memory",
|
|
1362
|
+
operation,
|
|
1363
|
+
"E_INVALID_INPUT",
|
|
1364
|
+
"taskId and entryId are required",
|
|
1365
|
+
startTime
|
|
1366
|
+
);
|
|
1367
|
+
}
|
|
1368
|
+
const result = await memoryLink({ taskId, entryId }, projectRoot);
|
|
1369
|
+
return wrapResult(result, "mutate", "memory", operation, startTime);
|
|
1370
|
+
}
|
|
1371
|
+
case "graph.add": {
|
|
1372
|
+
const result = await memoryGraphAdd(
|
|
1373
|
+
{
|
|
1374
|
+
nodeId: paramString(params, "nodeId"),
|
|
1375
|
+
nodeType: paramString(params, "nodeType"),
|
|
1376
|
+
label: paramString(params, "label"),
|
|
1377
|
+
metadataJson: paramString(params, "metadataJson"),
|
|
1378
|
+
fromId: paramString(params, "fromId"),
|
|
1379
|
+
toId: paramString(params, "toId"),
|
|
1380
|
+
edgeType: paramString(params, "edgeType"),
|
|
1381
|
+
weight: paramNumber(params, "weight")
|
|
1382
|
+
},
|
|
1383
|
+
projectRoot
|
|
1384
|
+
);
|
|
1385
|
+
return wrapResult(result, "mutate", "memory", operation, startTime);
|
|
1386
|
+
}
|
|
1387
|
+
case "graph.remove": {
|
|
1388
|
+
const result = await memoryGraphRemove(
|
|
1389
|
+
{
|
|
1390
|
+
nodeId: paramString(params, "nodeId"),
|
|
1391
|
+
fromId: paramString(params, "fromId"),
|
|
1392
|
+
toId: paramString(params, "toId"),
|
|
1393
|
+
edgeType: paramString(params, "edgeType")
|
|
1394
|
+
},
|
|
1395
|
+
projectRoot
|
|
1396
|
+
);
|
|
1397
|
+
return wrapResult(result, "mutate", "memory", operation, startTime);
|
|
1398
|
+
}
|
|
1399
|
+
case "code.link": {
|
|
1400
|
+
const memoryId = paramStringRequired(params, "memoryId");
|
|
1401
|
+
const codeSymbol = paramStringRequired(params, "codeSymbol");
|
|
1402
|
+
if (!memoryId || !codeSymbol) {
|
|
1403
|
+
return errorResult(
|
|
1404
|
+
"mutate",
|
|
1405
|
+
"memory",
|
|
1406
|
+
operation,
|
|
1407
|
+
"E_INVALID_INPUT",
|
|
1408
|
+
"memoryId and codeSymbol are required",
|
|
1409
|
+
startTime
|
|
1410
|
+
);
|
|
1411
|
+
}
|
|
1412
|
+
const { linkMemoryToCode } = await import("@cleocode/core/memory/graph-memory-bridge");
|
|
1413
|
+
const linked = await linkMemoryToCode(projectRoot, memoryId, codeSymbol);
|
|
1414
|
+
return wrapResult(
|
|
1415
|
+
{ success: true, data: { linked } },
|
|
1416
|
+
"mutate",
|
|
1417
|
+
"memory",
|
|
1418
|
+
operation,
|
|
1419
|
+
startTime
|
|
1420
|
+
);
|
|
1421
|
+
}
|
|
1422
|
+
case "code.auto-link": {
|
|
1423
|
+
const { autoLinkMemories } = await import("@cleocode/core/memory/graph-memory-bridge");
|
|
1424
|
+
const result = await autoLinkMemories(projectRoot);
|
|
1425
|
+
return wrapResult(
|
|
1426
|
+
{ success: true, data: result },
|
|
1427
|
+
"mutate",
|
|
1428
|
+
"memory",
|
|
1429
|
+
operation,
|
|
1430
|
+
startTime
|
|
1431
|
+
);
|
|
1432
|
+
}
|
|
1433
|
+
// T792 — promote an agent observation to verified=true (owner/cleo-prime only)
|
|
1434
|
+
case "verify": {
|
|
1435
|
+
const entryId = paramStringRequired(params, "id");
|
|
1436
|
+
if (!entryId) {
|
|
1437
|
+
return errorResult(
|
|
1438
|
+
"mutate",
|
|
1439
|
+
"memory",
|
|
1440
|
+
operation,
|
|
1441
|
+
"E_INVALID_INPUT",
|
|
1442
|
+
"id is required (the observation/decision/pattern/learning ID to verify)",
|
|
1443
|
+
startTime
|
|
1444
|
+
);
|
|
1445
|
+
}
|
|
1446
|
+
const VERIFY_PERMITTED_IDENTITIES = /* @__PURE__ */ new Set([
|
|
1447
|
+
"owner",
|
|
1448
|
+
"project-orchestrator",
|
|
1449
|
+
"cleo-prime"
|
|
1450
|
+
// legacy alias — see migration shim note above
|
|
1451
|
+
]);
|
|
1452
|
+
const callerAgent = paramString(params, "agent");
|
|
1453
|
+
if (callerAgent && !VERIFY_PERMITTED_IDENTITIES.has(callerAgent)) {
|
|
1454
|
+
return errorResult(
|
|
1455
|
+
"mutate",
|
|
1456
|
+
"memory",
|
|
1457
|
+
operation,
|
|
1458
|
+
"E_FORBIDDEN",
|
|
1459
|
+
`verify requires agent identity 'project-orchestrator' or 'owner'; got '${callerAgent}'`,
|
|
1460
|
+
startTime
|
|
1461
|
+
);
|
|
1462
|
+
}
|
|
1463
|
+
try {
|
|
1464
|
+
await getBrainDb(projectRoot);
|
|
1465
|
+
const nativeDb = getBrainNativeDb(projectRoot);
|
|
1466
|
+
if (!nativeDb) {
|
|
1467
|
+
return errorResult(
|
|
1468
|
+
"mutate",
|
|
1469
|
+
"memory",
|
|
1470
|
+
operation,
|
|
1471
|
+
"E_DB_UNAVAILABLE",
|
|
1472
|
+
"brain.db is unavailable",
|
|
1473
|
+
startTime
|
|
1474
|
+
);
|
|
1475
|
+
}
|
|
1476
|
+
const tables = [
|
|
1477
|
+
"brain_observations",
|
|
1478
|
+
"brain_decisions",
|
|
1479
|
+
"brain_patterns",
|
|
1480
|
+
"brain_learnings"
|
|
1481
|
+
];
|
|
1482
|
+
const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
1483
|
+
let found = false;
|
|
1484
|
+
let foundTable = "";
|
|
1485
|
+
let alreadyVerified = false;
|
|
1486
|
+
let foundNarrative = null;
|
|
1487
|
+
for (const tbl of tables) {
|
|
1488
|
+
try {
|
|
1489
|
+
const selectSql = tbl === "brain_observations" ? `SELECT id, verified, narrative FROM ${tbl} WHERE id = ? AND invalid_at IS NULL LIMIT 1` : `SELECT id, verified FROM ${tbl} WHERE id = ? AND invalid_at IS NULL LIMIT 1`;
|
|
1490
|
+
const row = nativeDb.prepare(selectSql).get(entryId);
|
|
1491
|
+
if (row) {
|
|
1492
|
+
found = true;
|
|
1493
|
+
foundTable = tbl;
|
|
1494
|
+
alreadyVerified = row.verified === 1;
|
|
1495
|
+
foundNarrative = row.narrative ?? null;
|
|
1496
|
+
if (!alreadyVerified) {
|
|
1497
|
+
if (tbl === "brain_observations") {
|
|
1498
|
+
try {
|
|
1499
|
+
nativeDb.prepare(
|
|
1500
|
+
`UPDATE ${tbl} SET verified = 1, updated_at = ?, validated_at = ? WHERE id = ?`
|
|
1501
|
+
).run(now, now, entryId);
|
|
1502
|
+
} catch {
|
|
1503
|
+
nativeDb.prepare(`UPDATE ${tbl} SET verified = 1, updated_at = ? WHERE id = ?`).run(now, entryId);
|
|
1504
|
+
}
|
|
1505
|
+
} else {
|
|
1506
|
+
nativeDb.prepare(`UPDATE ${tbl} SET verified = 1, updated_at = ? WHERE id = ?`).run(now, entryId);
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
break;
|
|
1510
|
+
}
|
|
1511
|
+
} catch {
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
if (!found) {
|
|
1515
|
+
return errorResult(
|
|
1516
|
+
"mutate",
|
|
1517
|
+
"memory",
|
|
1518
|
+
operation,
|
|
1519
|
+
"E_NOT_FOUND",
|
|
1520
|
+
`Entry '${entryId}' not found in any brain table (or is invalidated)`,
|
|
1521
|
+
startTime
|
|
1522
|
+
);
|
|
1523
|
+
}
|
|
1524
|
+
let attachmentMissing;
|
|
1525
|
+
let attachmentId;
|
|
1526
|
+
if (foundTable === "brain_observations" && foundNarrative) {
|
|
1527
|
+
try {
|
|
1528
|
+
const payload = JSON.parse(
|
|
1529
|
+
foundNarrative
|
|
1530
|
+
);
|
|
1531
|
+
if (payload.kind === "doc-attachment" && typeof payload.attachmentId === "string") {
|
|
1532
|
+
attachmentId = payload.attachmentId;
|
|
1533
|
+
const store = createAttachmentStore();
|
|
1534
|
+
const meta = await store.getMetadata(payload.attachmentId);
|
|
1535
|
+
attachmentMissing = meta === null;
|
|
1536
|
+
}
|
|
1537
|
+
} catch {
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
return wrapResult(
|
|
1541
|
+
{
|
|
1542
|
+
success: true,
|
|
1543
|
+
data: {
|
|
1544
|
+
id: entryId,
|
|
1545
|
+
table: foundTable.replace("brain_", ""),
|
|
1546
|
+
verified: true,
|
|
1547
|
+
alreadyVerified,
|
|
1548
|
+
verifiedAt: alreadyVerified ? null : now,
|
|
1549
|
+
// T9976 — doc-attachment round-trip fields (only present when applicable).
|
|
1550
|
+
...attachmentId !== void 0 ? { attachmentId } : {},
|
|
1551
|
+
...attachmentMissing !== void 0 ? { attachmentMissing } : {},
|
|
1552
|
+
...attachmentMissing === true ? {
|
|
1553
|
+
warning: `Attachment '${attachmentId}' referenced by this observation no longer exists in the docs store. The doc may have been removed.`
|
|
1554
|
+
} : {}
|
|
1555
|
+
}
|
|
1556
|
+
},
|
|
1557
|
+
"mutate",
|
|
1558
|
+
"memory",
|
|
1559
|
+
operation,
|
|
1560
|
+
startTime
|
|
1561
|
+
);
|
|
1562
|
+
} catch (dbErr) {
|
|
1563
|
+
return handleErrorResult("mutate", "memory", operation, dbErr, startTime);
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
// T1006 — write a diary-typed observation (thin wrapper over observe)
|
|
1567
|
+
case "diary.write": {
|
|
1568
|
+
const text = paramStringRequired(params, "text");
|
|
1569
|
+
if (!text) {
|
|
1570
|
+
return errorResult(
|
|
1571
|
+
"mutate",
|
|
1572
|
+
"memory",
|
|
1573
|
+
operation,
|
|
1574
|
+
"E_INVALID_INPUT",
|
|
1575
|
+
"text is required",
|
|
1576
|
+
startTime
|
|
1577
|
+
);
|
|
1578
|
+
}
|
|
1579
|
+
const result = await memoryObserve(
|
|
1580
|
+
{
|
|
1581
|
+
text,
|
|
1582
|
+
title: paramString(params, "title"),
|
|
1583
|
+
type: "diary",
|
|
1584
|
+
sourceSessionId: paramString(params, "sourceSessionId"),
|
|
1585
|
+
agent: paramString(params, "agent")
|
|
1586
|
+
},
|
|
1587
|
+
projectRoot
|
|
1588
|
+
);
|
|
1589
|
+
return wrapResult(result, "mutate", "memory", operation, startTime);
|
|
1590
|
+
}
|
|
1591
|
+
// T1004 — flush in-flight observations + WAL checkpoint before context compaction
|
|
1592
|
+
case "precompact-flush": {
|
|
1593
|
+
try {
|
|
1594
|
+
const flushResult = await precompactFlush(projectRoot);
|
|
1595
|
+
return wrapResult(
|
|
1596
|
+
{
|
|
1597
|
+
success: true,
|
|
1598
|
+
data: flushResult
|
|
1599
|
+
},
|
|
1600
|
+
"mutate",
|
|
1601
|
+
"memory",
|
|
1602
|
+
operation,
|
|
1603
|
+
startTime
|
|
1604
|
+
);
|
|
1605
|
+
} catch (flushErr) {
|
|
1606
|
+
return handleErrorResult("mutate", "memory", operation, flushErr, startTime);
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
// T1003 — stage a new graph backfill run (rows held pending approval)
|
|
1610
|
+
case "backfill.run": {
|
|
1611
|
+
try {
|
|
1612
|
+
const source = paramString(params, "source");
|
|
1613
|
+
const kind = paramString(params, "kind");
|
|
1614
|
+
const targetTable = paramString(params, "targetTable");
|
|
1615
|
+
const nodeIds = paramStringArray(params, "nodeIds");
|
|
1616
|
+
if (params?.["nodeIds"] !== void 0 && !nodeIds)
|
|
1617
|
+
throw new Error("nodeIds must be an array of qualified graph IDs.");
|
|
1618
|
+
const result = await stagedBackfillRun(projectRoot, {
|
|
1619
|
+
source,
|
|
1620
|
+
kind,
|
|
1621
|
+
targetTable,
|
|
1622
|
+
nodeIds
|
|
1623
|
+
});
|
|
1624
|
+
return wrapResult(
|
|
1625
|
+
{
|
|
1626
|
+
success: true,
|
|
1627
|
+
data: {
|
|
1628
|
+
runId: result.run.id,
|
|
1629
|
+
run: result.run,
|
|
1630
|
+
empty: result.empty,
|
|
1631
|
+
hint: result.empty ? "All candidate nodes already present \u2014 nothing to backfill" : `Run staged with ${result.run.rowsAffected} rows. Approve with 'cleo memory backfill.approve ${result.run.id}'`
|
|
1632
|
+
}
|
|
1633
|
+
},
|
|
1634
|
+
"mutate",
|
|
1635
|
+
"memory",
|
|
1636
|
+
operation,
|
|
1637
|
+
startTime
|
|
1638
|
+
);
|
|
1639
|
+
} catch (runErr) {
|
|
1640
|
+
return handleErrorResult("mutate", "memory", operation, runErr, startTime);
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
// T1003 — approve a staged backfill run (commits rows to live tables)
|
|
1644
|
+
case "backfill.approve": {
|
|
1645
|
+
const runId = paramString(params, "runId");
|
|
1646
|
+
if (!runId) {
|
|
1647
|
+
return errorResult(
|
|
1648
|
+
"mutate",
|
|
1649
|
+
"memory",
|
|
1650
|
+
operation,
|
|
1651
|
+
"E_INVALID_INPUT",
|
|
1652
|
+
"runId is required",
|
|
1653
|
+
startTime
|
|
1654
|
+
);
|
|
1655
|
+
}
|
|
1656
|
+
try {
|
|
1657
|
+
const approvedBy = paramString(params, "approvedBy");
|
|
1658
|
+
const result = await approveBackfillRun(projectRoot, runId, approvedBy);
|
|
1659
|
+
return wrapResult(
|
|
1660
|
+
{
|
|
1661
|
+
success: true,
|
|
1662
|
+
data: {
|
|
1663
|
+
runId: result.run.id,
|
|
1664
|
+
run: result.run,
|
|
1665
|
+
alreadySettled: result.alreadySettled,
|
|
1666
|
+
backfillResult: result.backfillResult ?? null,
|
|
1667
|
+
hint: result.alreadySettled ? `Run '${runId}' was already settled (status: ${result.run.status})` : `Backfill committed: ${result.backfillResult?.nodesInserted ?? 0} nodes inserted`
|
|
1668
|
+
}
|
|
1669
|
+
},
|
|
1670
|
+
"mutate",
|
|
1671
|
+
"memory",
|
|
1672
|
+
operation,
|
|
1673
|
+
startTime
|
|
1674
|
+
);
|
|
1675
|
+
} catch (approveErr) {
|
|
1676
|
+
return handleErrorResult("mutate", "memory", operation, approveErr, startTime);
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
// T1003 — rollback a backfill run (removes staged/committed rows)
|
|
1680
|
+
case "backfill.rollback": {
|
|
1681
|
+
const runId = paramString(params, "runId");
|
|
1682
|
+
if (!runId) {
|
|
1683
|
+
return errorResult(
|
|
1684
|
+
"mutate",
|
|
1685
|
+
"memory",
|
|
1686
|
+
operation,
|
|
1687
|
+
"E_INVALID_INPUT",
|
|
1688
|
+
"runId is required",
|
|
1689
|
+
startTime
|
|
1690
|
+
);
|
|
1691
|
+
}
|
|
1692
|
+
try {
|
|
1693
|
+
const result = await rollbackBackfillRun(projectRoot, runId);
|
|
1694
|
+
return wrapResult(
|
|
1695
|
+
{
|
|
1696
|
+
success: true,
|
|
1697
|
+
data: {
|
|
1698
|
+
runId: result.run.id,
|
|
1699
|
+
run: result.run,
|
|
1700
|
+
alreadySettled: result.alreadySettled,
|
|
1701
|
+
deletedRows: result.deletedRows,
|
|
1702
|
+
hint: result.alreadySettled ? `Run '${runId}' was already rolled back` : result.deletedRows > 0 ? `Rolled back: deleted ${result.deletedRows} committed rows` : "Run was still staged \u2014 no committed rows to delete"
|
|
1703
|
+
}
|
|
1704
|
+
},
|
|
1705
|
+
"mutate",
|
|
1706
|
+
"memory",
|
|
1707
|
+
operation,
|
|
1708
|
+
startTime
|
|
1709
|
+
);
|
|
1710
|
+
} catch (rollbackErr) {
|
|
1711
|
+
return handleErrorResult("mutate", "memory", operation, rollbackErr, startTime);
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
// T1147 W7 — sweep mutate operations (approve, rollback) delegate to query handler
|
|
1715
|
+
// which already handles all sweep sub-commands via a unified case block.
|
|
1716
|
+
case "sweep":
|
|
1717
|
+
return this.query(operation, params);
|
|
1718
|
+
// T9976 — backfill: emit memory observations for existing doc attachments
|
|
1719
|
+
// that do not yet have a corresponding brain observation.
|
|
1720
|
+
case "backfill-docs": {
|
|
1721
|
+
try {
|
|
1722
|
+
const store = createAttachmentStore();
|
|
1723
|
+
const allAttachments = await store.listAllInProject();
|
|
1724
|
+
await getBrainDb(projectRoot);
|
|
1725
|
+
const nativeDb = getBrainNativeDb(projectRoot);
|
|
1726
|
+
const existingAttachmentIds = /* @__PURE__ */ new Set();
|
|
1727
|
+
if (nativeDb) {
|
|
1728
|
+
try {
|
|
1729
|
+
const existing = nativeDb.prepare(
|
|
1730
|
+
`SELECT narrative FROM brain_observations
|
|
1731
|
+
WHERE narrative LIKE '%"kind":"doc-attachment"%'
|
|
1732
|
+
AND invalid_at IS NULL`
|
|
1733
|
+
).all();
|
|
1734
|
+
for (const row of existing) {
|
|
1735
|
+
if (!row.narrative) continue;
|
|
1736
|
+
try {
|
|
1737
|
+
const p = JSON.parse(row.narrative);
|
|
1738
|
+
if (p.kind === "doc-attachment" && typeof p.attachmentId === "string") {
|
|
1739
|
+
existingAttachmentIds.add(p.attachmentId);
|
|
1740
|
+
}
|
|
1741
|
+
} catch {
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
} catch {
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
let emitted = 0;
|
|
1748
|
+
let skipped = 0;
|
|
1749
|
+
const emittedIds = [];
|
|
1750
|
+
for (const item of allAttachments) {
|
|
1751
|
+
const attId = item.metadata.id;
|
|
1752
|
+
if (existingAttachmentIds.has(attId)) {
|
|
1753
|
+
skipped++;
|
|
1754
|
+
continue;
|
|
1755
|
+
}
|
|
1756
|
+
const extras = await store.getExtras(attId);
|
|
1757
|
+
const slug = extras?.slug ?? void 0;
|
|
1758
|
+
const type = extras?.type ?? void 0;
|
|
1759
|
+
const payload = {
|
|
1760
|
+
kind: "doc-attachment",
|
|
1761
|
+
attachmentId: attId,
|
|
1762
|
+
ownerId: item.ownerId,
|
|
1763
|
+
addedAt: item.metadata.createdAt,
|
|
1764
|
+
...slug !== void 0 ? { slug } : {},
|
|
1765
|
+
...type !== void 0 ? { type } : {}
|
|
1766
|
+
};
|
|
1767
|
+
const { memoryObserve: brainObserve } = await import("@cleocode/core/memory/engine-compat");
|
|
1768
|
+
await brainObserve(
|
|
1769
|
+
{
|
|
1770
|
+
text: JSON.stringify(payload),
|
|
1771
|
+
title: `Doc attached: ${slug ?? attId}`,
|
|
1772
|
+
type: "feature",
|
|
1773
|
+
// sourceType: 'manual' avoids the mental-model queue (5s flush interval).
|
|
1774
|
+
// The mental-model queue is only entered when `agent` is set + type is in
|
|
1775
|
+
// MENTAL_MODEL_TYPES. Using 'manual' bypasses this path entirely.
|
|
1776
|
+
sourceType: "manual"
|
|
1777
|
+
},
|
|
1778
|
+
projectRoot
|
|
1779
|
+
).catch(() => {
|
|
1780
|
+
});
|
|
1781
|
+
emittedIds.push(attId);
|
|
1782
|
+
emitted++;
|
|
1783
|
+
}
|
|
1784
|
+
return wrapResult(
|
|
1785
|
+
{
|
|
1786
|
+
success: true,
|
|
1787
|
+
data: {
|
|
1788
|
+
total: allAttachments.length,
|
|
1789
|
+
emitted,
|
|
1790
|
+
skipped,
|
|
1791
|
+
emittedAttachmentIds: emittedIds,
|
|
1792
|
+
hint: emitted === 0 ? "All existing attachments already have memory observations \u2014 nothing to backfill." : `Emitted ${emitted} new doc-attachment observations. Use 'cleo memory find <slug>' to verify.`
|
|
1793
|
+
}
|
|
1794
|
+
},
|
|
1795
|
+
"mutate",
|
|
1796
|
+
"memory",
|
|
1797
|
+
operation,
|
|
1798
|
+
startTime
|
|
1799
|
+
);
|
|
1800
|
+
} catch (backfillErr) {
|
|
1801
|
+
return handleErrorResult("mutate", "memory", operation, backfillErr, startTime);
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
default:
|
|
1805
|
+
return unsupportedOp("mutate", "memory", operation, startTime);
|
|
1806
|
+
}
|
|
1807
|
+
} catch (error) {
|
|
1808
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1809
|
+
getLogger("domain:memory").error(
|
|
1810
|
+
{ gateway: "mutate", domain: "memory", operation, err: error },
|
|
1811
|
+
message
|
|
1812
|
+
);
|
|
1813
|
+
return handleErrorResult("mutate", "memory", operation, error, startTime);
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
// -----------------------------------------------------------------------
|
|
1817
|
+
// Supported operations
|
|
1818
|
+
// -----------------------------------------------------------------------
|
|
1819
|
+
getSupportedOperations() {
|
|
1820
|
+
return {
|
|
1821
|
+
query: [
|
|
1822
|
+
"find",
|
|
1823
|
+
"timeline",
|
|
1824
|
+
"fetch",
|
|
1825
|
+
"decision.find",
|
|
1826
|
+
"pattern.find",
|
|
1827
|
+
"learning.find",
|
|
1828
|
+
"graph.show",
|
|
1829
|
+
"graph.neighbors",
|
|
1830
|
+
"graph.trace",
|
|
1831
|
+
"graph.related",
|
|
1832
|
+
"graph.context",
|
|
1833
|
+
"graph.stats",
|
|
1834
|
+
"reason.why",
|
|
1835
|
+
"reason.similar",
|
|
1836
|
+
"search.hybrid",
|
|
1837
|
+
"quality",
|
|
1838
|
+
"code.links",
|
|
1839
|
+
"code.memories-for-code",
|
|
1840
|
+
"code.for-memory",
|
|
1841
|
+
// T1262 — brain noise detector (E1-parallel, read-only) + assert-clean gate
|
|
1842
|
+
"doctor",
|
|
1843
|
+
// T1147 W7 — sweep status query (dry-run mode)
|
|
1844
|
+
"sweep",
|
|
1845
|
+
// T791 — LLM extraction backend status
|
|
1846
|
+
"llm-status",
|
|
1847
|
+
// T792 — pending verification queue
|
|
1848
|
+
"pending-verify",
|
|
1849
|
+
// T999 — live memory-bridge content from brain.db (cli mode)
|
|
1850
|
+
"bridge",
|
|
1851
|
+
// T997 — read-only explainability view for promotion decisions
|
|
1852
|
+
"promote-explain",
|
|
1853
|
+
// T1006 — summarized top-N observations as session briefing digest
|
|
1854
|
+
"digest",
|
|
1855
|
+
// T1006 — tail recent observations with optional filters
|
|
1856
|
+
"recent",
|
|
1857
|
+
// T1006 — diary-typed observations (requires diary enum from T1005)
|
|
1858
|
+
"diary",
|
|
1859
|
+
// T1006 — long-poll stream of recent brain writes (SSE-style polling stub)
|
|
1860
|
+
"watch",
|
|
1861
|
+
// T1003 — list staged backfill runs
|
|
1862
|
+
"backfill.list"
|
|
1863
|
+
],
|
|
1864
|
+
mutate: [
|
|
1865
|
+
"observe",
|
|
1866
|
+
"decision.store",
|
|
1867
|
+
"pattern.store",
|
|
1868
|
+
"learning.store",
|
|
1869
|
+
"link",
|
|
1870
|
+
"graph.add",
|
|
1871
|
+
"graph.remove",
|
|
1872
|
+
"code.link",
|
|
1873
|
+
"code.auto-link",
|
|
1874
|
+
// T792 — promote entry to verified=true
|
|
1875
|
+
"verify",
|
|
1876
|
+
// T1004 — flush in-flight observations + WAL checkpoint before context compaction
|
|
1877
|
+
"precompact-flush",
|
|
1878
|
+
// T1006 — write a diary-typed observation
|
|
1879
|
+
"diary.write",
|
|
1880
|
+
// T1147 W7 — sweep mutate operations (approve, rollback)
|
|
1881
|
+
"sweep",
|
|
1882
|
+
// T1003 — staged backfill operations
|
|
1883
|
+
"backfill.run",
|
|
1884
|
+
"backfill.approve",
|
|
1885
|
+
"backfill.rollback",
|
|
1886
|
+
// T9976 — emit memory observations for existing doc attachments
|
|
1887
|
+
"backfill-docs"
|
|
1888
|
+
]
|
|
1889
|
+
};
|
|
1890
|
+
}
|
|
1891
|
+
};
|
|
1892
|
+
export {
|
|
1893
|
+
MemoryHandler
|
|
1894
|
+
};
|
|
1895
|
+
//# sourceMappingURL=memory-IAEYKXG6.js.map
|