shieldcortex 4.28.0 → 4.29.0
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/dashboard/.next/standalone/dashboard/.next/BUILD_ID +1 -1
- package/dashboard/.next/standalone/dashboard/.next/build-manifest.json +2 -2
- package/dashboard/.next/standalone/dashboard/.next/prerender-manifest.json +3 -3
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk/admin/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk/admin.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk/cloud/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk/cloud.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory/capture/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory/capture.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory/graph/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory/graph.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory/recall/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory/recall.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory/replay/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory/replay.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory/review/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory/review.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory/timeline/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory/timeline.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk/overview/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk/overview.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection/audit/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection/audit.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection/intercepts/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection/intercepts.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection/iron-dome/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection/iron-dome.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection/policies/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection/policies.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection/quarantine/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection/quarantine.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk/protection/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain/xray/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain/xray.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk/supply-chain/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk/supply-chain.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/pages/404.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/pages/500.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/server-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/server-reference-manifest.json +1 -1
- package/dist/cli/doctor.d.ts +17 -0
- package/dist/cli/doctor.js +44 -0
- package/dist/cli/memory.d.ts +23 -0
- package/dist/cli/memory.js +101 -0
- package/dist/database/init.d.ts +9 -0
- package/dist/database/init.js +32 -4
- package/dist/database/migrations.js +126 -0
- package/dist/license/store.js +42 -2
- package/dist/memory/consolidate.d.ts +82 -6
- package/dist/memory/consolidate.js +287 -117
- package/dist/setup/openclaw.d.ts +26 -0
- package/dist/setup/openclaw.js +61 -0
- package/dist/tools/remember.js +24 -3
- package/hooks/openclaw/cortex-memory/handler.ts +223 -171
- package/hooks/openclaw/cortex-memory/runtime.mjs +64 -0
- package/package.json +1 -1
- package/scripts/lib/dedup.mjs +99 -0
- package/scripts/lib/openclaw-extract.mjs +129 -0
- package/scripts/lib/recall-log.mjs +16 -1
- package/scripts/lib/recall-relevance.mjs +191 -0
- package/scripts/lib/salience.mjs +8 -3
- package/scripts/lib/save-memory.mjs +62 -6
- package/scripts/lib/session-context.mjs +30 -0
- package/scripts/postinstall.mjs +29 -10
- package/scripts/prompt-recall-hook.mjs +118 -15
- package/scripts/session-start-hook.mjs +17 -6
- /package/dashboard/.next/standalone/dashboard/.next/static/{3HiFjAMoQUDn05ZMNC0Ae → 0HpUm8SRvm9fnWVO0OBB2}/_buildManifest.js +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{3HiFjAMoQUDn05ZMNC0Ae → 0HpUm8SRvm9fnWVO0OBB2}/_clientMiddlewareManifest.json +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{3HiFjAMoQUDn05ZMNC0Ae → 0HpUm8SRvm9fnWVO0OBB2}/_ssgManifest.js +0 -0
|
@@ -10,11 +10,21 @@
|
|
|
10
10
|
import { getDatabase, withTransaction } from '../database/init.js';
|
|
11
11
|
import { DEFAULT_CONFIG, } from './types.js';
|
|
12
12
|
import { getMemoriesByType, getRecentMemories, promoteMemory, deleteMemory, searchMemories, getMemoryStats, updateDecayScores, addMemory, rowToMemory, } from './store.js';
|
|
13
|
-
import { runDefencePipeline } from '../defence/index.js';
|
|
14
13
|
import { processDecay, } from './decay.js';
|
|
15
14
|
import { detectContradictions, linkContradictions, } from './contradiction.js';
|
|
16
15
|
import { jaccardSimilarity } from './similarity.js';
|
|
17
16
|
import { pruneActivationCache } from './activation.js';
|
|
17
|
+
// Static import of the shared effective-salience helper. Every other src/ file
|
|
18
|
+
// (cli/memory.ts, the recall hook) reaches salience.mjs via a relative path
|
|
19
|
+
// because `scripts/` lives outside tsconfig's rootDir; a static top-level
|
|
20
|
+
// import compiles clean (tsc keeps the dist layout intact and emits the same
|
|
21
|
+
// '../../scripts/lib/salience.mjs' specifier the dynamic import did) and lets
|
|
22
|
+
// these consolidation functions stay SYNCHRONOUS — better-sqlite3 transactions
|
|
23
|
+
// cannot await, and consolidate()/deduplicateMemories() have several sync
|
|
24
|
+
// callers. One source of truth: this is the same computeEffectiveSalience the
|
|
25
|
+
// recall hook and `shieldcortex memory downvote` use.
|
|
26
|
+
// @ts-expect-error — importing a .mjs hook util that has no .d.ts
|
|
27
|
+
import { computeEffectiveSalience } from '../../scripts/lib/salience.mjs';
|
|
18
28
|
/**
|
|
19
29
|
* Run full consolidation process
|
|
20
30
|
* This is like the brain's sleep consolidation - should be run periodically
|
|
@@ -254,49 +264,80 @@ export function findDuplicateMemoryPairs(options) {
|
|
|
254
264
|
return pairs;
|
|
255
265
|
}
|
|
256
266
|
/**
|
|
257
|
-
*
|
|
258
|
-
*
|
|
267
|
+
* De-duplicate long-term memories found as duplicate PAIRS by
|
|
268
|
+
* findDuplicateMemoryPairs (same project|category, similar title + >0.5 content
|
|
269
|
+
* overlap). Runs every ~4h on the auto path: server.ts setInterval → fullCleanup
|
|
270
|
+
* → consolidate → deduplicateMemories.
|
|
271
|
+
*
|
|
272
|
+
* B11 (memory-quality fix): the previous implementation built
|
|
273
|
+
* `kept.content + "\n\nMerged from duplicate:\n" + uniqueSentences` and wrote it
|
|
274
|
+
* back with `UPDATE memories SET content = ?`. That was the SECOND lossy-append
|
|
275
|
+
* site (mergeSimilarMemories was the first) and kept generating ever-growing
|
|
276
|
+
* "frankenmemories" on this path even after the first site was fixed. The kept
|
|
277
|
+
* memory's `content` is now NEVER modified.
|
|
278
|
+
*
|
|
279
|
+
* New policy (identical to mergeSimilarMemories — one source of truth):
|
|
280
|
+
* - KEEP the higher-EFFECTIVE-salience member of the pair (computeEffectiveSalience
|
|
281
|
+
* via the shared salience.mjs — recency/access/pin/downvote, same ranking as
|
|
282
|
+
* recall and the downvote CLI). NOTE: this can differ from the pair's raw
|
|
283
|
+
* `recommendedKeepId`, which only considered raw salience + recency.
|
|
284
|
+
* - Dispose the loser via the shared disposeLoser: combined similarity
|
|
285
|
+
* (re-measured vs the kept row) ≥ 0.85 → DELETE; below → DOWNVOTE (reversible).
|
|
286
|
+
* - Tags are unioned onto the kept row (metadata only, non-lossy). The kept
|
|
287
|
+
* content and salience are untouched.
|
|
288
|
+
*
|
|
289
|
+
* Defence re-scan removed (B11): the old re-scan existed ONLY to validate the
|
|
290
|
+
* SYNTHESIZED concatenated merged body before persisting it (two individually-
|
|
291
|
+
* clean rows could straddle a credential pattern across the join). Now that no
|
|
292
|
+
* concatenation happens here, there is no synthesized content to scan — the kept
|
|
293
|
+
* row's bytes are written verbatim and unchanged, exactly as they already exist
|
|
294
|
+
* in `memories`. So this pass introduces no new bytes to validate. (This is a
|
|
295
|
+
* narrow claim about THIS path: it does not assume every row was scanned at write
|
|
296
|
+
* time — e.g. importMemories inserts rows with no scan — only that the dedup no
|
|
297
|
+
* longer fabricates a new body that would need scanning.) Dropping the re-scan
|
|
298
|
+
* also avoids re-auditing unchanged content on every 4h pass.
|
|
299
|
+
*
|
|
300
|
+
* Only rows clustered in THIS pass are acted on; historical merged rows are not
|
|
301
|
+
* rewritten (effective salience demotes them over time). STM→LTM promotion is
|
|
302
|
+
* handled separately by processDecay/promoteMemory in consolidate().
|
|
259
303
|
*/
|
|
260
304
|
export function deduplicateMemories(options) {
|
|
261
305
|
const dryRun = options?.dryRun ?? false;
|
|
262
306
|
return withTransaction(() => {
|
|
263
307
|
const db = getDatabase();
|
|
264
308
|
const pairs = [];
|
|
265
|
-
const
|
|
309
|
+
const disposed = new Set();
|
|
310
|
+
const nowIso = new Date().toISOString();
|
|
311
|
+
const downvoteStmt = db.prepare(DOWNVOTE_SQL);
|
|
312
|
+
// findDuplicateMemoryPairs returns rowToMemory-converted objects, which omit
|
|
313
|
+
// downvote_count. Fetch raw rows on demand so effective-salience ranking and
|
|
314
|
+
// the loser disposal see the full signal.
|
|
315
|
+
const rawRowStmt = db.prepare('SELECT * FROM memories WHERE id = ?');
|
|
316
|
+
const rawRow = (id) => rawRowStmt.get(id);
|
|
266
317
|
for (const pair of findDuplicateMemoryPairs()) {
|
|
267
|
-
if (
|
|
318
|
+
if (disposed.has(pair.memoryA.id) || disposed.has(pair.memoryB.id))
|
|
268
319
|
continue;
|
|
269
|
-
const
|
|
320
|
+
const rowA = rawRow(pair.memoryA.id);
|
|
321
|
+
const rowB = rawRow(pair.memoryB.id);
|
|
322
|
+
if (!rowA || !rowB)
|
|
323
|
+
continue; // already gone (e.g. deleted earlier this pass)
|
|
324
|
+
// KEEP the higher-effective-salience member (tie → keep A, the older row
|
|
325
|
+
// by findDuplicateMemoryPairs' created_at ASC ordering).
|
|
326
|
+
const keepA = effectiveSalienceOfRow(rowA) >= effectiveSalienceOfRow(rowB);
|
|
327
|
+
const kept = keepA ? pair.memoryA : pair.memoryB;
|
|
328
|
+
const loser = keepA ? pair.memoryB : pair.memoryA;
|
|
270
329
|
if (!dryRun) {
|
|
271
|
-
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
.filter(s => s.length > 0 && !keptSentences.has(s.toLowerCase()));
|
|
278
|
-
if (uniqueSentences.length > 0) {
|
|
279
|
-
const mergedContent = kept.content + '\n\nMerged from duplicate:\n' + uniqueSentences.join('. ') + '.';
|
|
280
|
-
// DEFENCE PIPELINE: re-scan the merged content. Two individually-clean
|
|
281
|
-
// memories can produce content that straddles a credential pattern
|
|
282
|
-
// across the join. Without this re-scan the "every byte in `memories`
|
|
283
|
-
// has been scanned" invariant is broken. If the merge is blocked, skip
|
|
284
|
-
// both the content update AND the delete so the source rows survive.
|
|
285
|
-
const dedupSource = { type: 'hook', identifier: 'hook:consolidation' };
|
|
286
|
-
const defenceResult = runDefencePipeline(mergedContent, kept.title, dedupSource, undefined, kept.project ?? discarded.project ?? undefined);
|
|
287
|
-
if (defenceResult.firewall.result !== 'ALLOW') {
|
|
288
|
-
// Surface in audit (already written by the pipeline) and skip this pair.
|
|
289
|
-
console.warn(`[shieldcortex] Dedup merge blocked for memory ${kept.id} + ${removedId}: ${defenceResult.firewall.reason}`);
|
|
290
|
-
continue;
|
|
291
|
-
}
|
|
292
|
-
db.prepare('UPDATE memories SET content = ? WHERE id = ?').run(mergedContent, kept.id);
|
|
293
|
-
}
|
|
294
|
-
deleteMemory(removedId);
|
|
330
|
+
// Union the loser's tags onto the kept row (metadata only, non-lossy).
|
|
331
|
+
const mergedTags = [...new Set([...kept.tags, ...loser.tags])];
|
|
332
|
+
db.prepare('UPDATE memories SET tags = ? WHERE id = ?')
|
|
333
|
+
.run(JSON.stringify(mergedTags), kept.id);
|
|
334
|
+
// Shared disposal policy — identical to mergeSimilarMemories.
|
|
335
|
+
disposeLoser({ content: kept.content, title: kept.title }, { id: loser.id, content: loser.content, title: loser.title }, downvoteStmt, nowIso);
|
|
295
336
|
}
|
|
296
|
-
|
|
337
|
+
disposed.add(loser.id);
|
|
297
338
|
pairs.push({
|
|
298
|
-
kept:
|
|
299
|
-
removed:
|
|
339
|
+
kept: kept.id,
|
|
340
|
+
removed: loser.id,
|
|
300
341
|
similarity: pair.similarity,
|
|
301
342
|
});
|
|
302
343
|
}
|
|
@@ -422,10 +463,79 @@ export function enforceMemoryLimits(config = DEFAULT_CONFIG) {
|
|
|
422
463
|
return deleted;
|
|
423
464
|
}
|
|
424
465
|
/**
|
|
425
|
-
*
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
466
|
+
* Combined-similarity bar at/above which a clustered loser is considered a
|
|
467
|
+
* NEAR-IDENTICAL duplicate of the kept memory. Such a loser's content is, by
|
|
468
|
+
* construction, almost entirely contained in the kept memory, so deleting it
|
|
469
|
+
* loses no real information — this is the non-lossy successor to the old
|
|
470
|
+
* concatenate-then-delete behaviour, minus the concatenation. Moderate
|
|
471
|
+
* near-dups (similarityThreshold ≤ combined < this) keep some distinct content,
|
|
472
|
+
* so we DOWNVOTE rather than delete them (reversible, non-lossy).
|
|
473
|
+
*/
|
|
474
|
+
const NEAR_IDENTICAL_DELETE_THRESHOLD = 0.85;
|
|
475
|
+
/**
|
|
476
|
+
* Effective salience of a raw `memories` row, via the shared
|
|
477
|
+
* scripts/lib/salience.mjs helper (recency × access × pin × downvote_penalty).
|
|
478
|
+
* One source of truth with recall ranking and the `shieldcortex memory
|
|
479
|
+
* downvote` CLI, so "highest-salience to keep" and "downvoted to demote" agree.
|
|
480
|
+
*/
|
|
481
|
+
function effectiveSalienceOfRow(m) {
|
|
482
|
+
return computeEffectiveSalience({
|
|
483
|
+
salience: m.salience ?? 0,
|
|
484
|
+
last_accessed: m.last_accessed ?? null,
|
|
485
|
+
access_count: m.access_count ?? 0,
|
|
486
|
+
pinned: m.pinned ?? 0,
|
|
487
|
+
downvote_count: m.downvote_count ?? 0,
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
function disposeLoser(kept, loser, downvoteStmt, nowIso) {
|
|
491
|
+
const cSim = jaccardSimilarity(kept.content, loser.content);
|
|
492
|
+
const tSim = jaccardSimilarity(kept.title, loser.title);
|
|
493
|
+
const combinedToKept = cSim * 0.6 + tSim * 0.4;
|
|
494
|
+
if (combinedToKept >= NEAR_IDENTICAL_DELETE_THRESHOLD) {
|
|
495
|
+
deleteMemory(loser.id);
|
|
496
|
+
return 'deleted';
|
|
497
|
+
}
|
|
498
|
+
downvoteStmt.run(nowIso, loser.id);
|
|
499
|
+
return 'downvoted';
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* The shared downvote SQL — prepared once per pass by each caller and handed to
|
|
503
|
+
* disposeLoser. Reversible soft demotion: bumps downvote_count (effective
|
|
504
|
+
* salience reads it) and stamps last_downvoted_at.
|
|
505
|
+
*/
|
|
506
|
+
const DOWNVOTE_SQL = `
|
|
507
|
+
UPDATE memories
|
|
508
|
+
SET downvote_count = COALESCE(downvote_count, 0) + 1,
|
|
509
|
+
last_downvoted_at = ?
|
|
510
|
+
WHERE id = ?
|
|
511
|
+
`;
|
|
512
|
+
/**
|
|
513
|
+
* Find clusters of similar short-term memories within each project|category,
|
|
514
|
+
* KEEP the single highest-effective-salience member, and demote the rest
|
|
515
|
+
* WITHOUT destroying or concatenating their content.
|
|
516
|
+
*
|
|
517
|
+
* B11 (memory-quality fix): the previous implementation appended every loser's
|
|
518
|
+
* body into the kept memory ("Consolidated context:" bullets) and deleted the
|
|
519
|
+
* losers. Over ~417 live rows this produced 188 ever-growing "frankenmemories"
|
|
520
|
+
* — exactly the garbled content users complained about. The kept memory's
|
|
521
|
+
* `content` is now NEVER modified.
|
|
522
|
+
*
|
|
523
|
+
* Disposition per loser (see NEAR_IDENTICAL_DELETE_THRESHOLD):
|
|
524
|
+
* - combined ≥ 0.85 → DELETE (near-identical; content already in the kept row)
|
|
525
|
+
* - combined < 0.85 → DOWNVOTE (reversible; sinks via effective salience)
|
|
526
|
+
*
|
|
527
|
+
* Why the split exists at all: NO reaping path (decay.ts shouldDelete,
|
|
528
|
+
* prune.ts, expiry.ts, enforceMemoryLimits) reads `downvote_count` or effective
|
|
529
|
+
* salience — they all order by raw `salience`. So downvote-ONLY would leave the
|
|
530
|
+
* store unbounded (the dups sink in recall but never get pruned). Deleting the
|
|
531
|
+
* near-identical losers keeps the store bounded with zero information loss; the
|
|
532
|
+
* moderate near-dups are preserved and merely demoted.
|
|
533
|
+
*
|
|
534
|
+
* Tags are unioned onto the kept row and access counts summed (metadata only,
|
|
535
|
+
* non-lossy). STM→LTM promotion is handled separately by processDecay/
|
|
536
|
+
* promoteMemory in consolidate(); this function only de-duplicates.
|
|
537
|
+
*
|
|
538
|
+
* Returns the count of deleted (near-identical) losers.
|
|
429
539
|
*/
|
|
430
540
|
export function mergeSimilarMemories(project, similarityThreshold = 0.25) {
|
|
431
541
|
return withTransaction(() => {
|
|
@@ -466,6 +576,21 @@ export function mergeSimilarMemories(project, similarityThreshold = 0.25) {
|
|
|
466
576
|
const contentSim = jaccardSimilarity(memA.content, memB.content);
|
|
467
577
|
const titleSim = jaccardSimilarity(memA.title, memB.title);
|
|
468
578
|
const combinedSim = contentSim * 0.6 + titleSim * 0.4;
|
|
579
|
+
// THRESHOLD RECONCILIATION (B11, reconciled with Task 8's write-path
|
|
580
|
+
// dedup):
|
|
581
|
+
// - Task 8's write-path SKIP fires at combined ≥ 0.5 and is STRICT
|
|
582
|
+
// because skipping a write is IRREVERSIBLE data loss — the memory
|
|
583
|
+
// is never stored.
|
|
584
|
+
// - Consolidate stays AGGRESSIVE at 0.25 because its action is now
|
|
585
|
+
// REVERSIBLE: moderate near-dups are DOWNVOTED — a soft demotion
|
|
586
|
+
// that leaves the row + its content intact (clearing
|
|
587
|
+
// downvote_count restores the prior ranking), not the old
|
|
588
|
+
// concatenate-into-kept + delete, which destroyed data.
|
|
589
|
+
// The two thresholds no longer conflict: a pair at combined ~0.3
|
|
590
|
+
// (below the 0.5 write-skip, above this 0.25 bar) survives the
|
|
591
|
+
// write but is demoted here via reversible downvote. Only
|
|
592
|
+
// near-IDENTICAL losers (≥ 0.85, content already in the kept row)
|
|
593
|
+
// are deleted — see NEAR_IDENTICAL_DELETE_THRESHOLD.
|
|
469
594
|
if (combinedSim >= similarityThreshold) {
|
|
470
595
|
cluster.push(j);
|
|
471
596
|
}
|
|
@@ -475,18 +600,17 @@ export function mergeSimilarMemories(project, similarityThreshold = 0.25) {
|
|
|
475
600
|
// Mark all as clustered
|
|
476
601
|
for (const idx of cluster)
|
|
477
602
|
clustered.add(idx);
|
|
478
|
-
// Step 4:
|
|
479
|
-
//
|
|
603
|
+
// Step 4: Resolve the cluster WITHOUT lossy concatenation.
|
|
604
|
+
// KEEP the single highest-EFFECTIVE-salience member (downvotes,
|
|
605
|
+
// recency, pins and access all factor in — same ranking the recall
|
|
606
|
+
// hook uses). The kept row's `content` is NEVER touched.
|
|
480
607
|
const clusterMems = cluster.map(idx => group[idx]);
|
|
481
|
-
clusterMems.sort((a, b) => b
|
|
482
|
-
const
|
|
483
|
-
const
|
|
484
|
-
// Merge
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
.join('\n');
|
|
488
|
-
const mergedContent = `${base.content}\n\nConsolidated context:\n${bulletPoints}`;
|
|
489
|
-
// Merge tags (union)
|
|
608
|
+
clusterMems.sort((a, b) => effectiveSalienceOfRow(b) - effectiveSalienceOfRow(a));
|
|
609
|
+
const kept = clusterMems[0];
|
|
610
|
+
const losers = clusterMems.slice(1);
|
|
611
|
+
// Merge tags onto the kept row (union — metadata only, non-lossy) and
|
|
612
|
+
// accumulate the losers' access counts so reinforcement history isn't
|
|
613
|
+
// lost. The kept content and salience stay exactly as they were.
|
|
490
614
|
const allTags = new Set();
|
|
491
615
|
for (const m of clusterMems) {
|
|
492
616
|
try {
|
|
@@ -498,24 +622,31 @@ export function mergeSimilarMemories(project, similarityThreshold = 0.25) {
|
|
|
498
622
|
// skip invalid tags
|
|
499
623
|
}
|
|
500
624
|
}
|
|
501
|
-
// Sum access counts
|
|
502
625
|
const totalAccessCount = clusterMems.reduce((sum, m) => sum + (m.access_count || 0), 0);
|
|
503
|
-
//
|
|
504
|
-
|
|
505
|
-
//
|
|
626
|
+
// Promote the kept memory to long-term and absorb the union'd tags +
|
|
627
|
+
// summed access count. NOTE: content is deliberately omitted from this
|
|
628
|
+
// UPDATE — no frankenmerge.
|
|
506
629
|
db.prepare(`
|
|
507
630
|
UPDATE memories
|
|
508
631
|
SET type = 'long_term',
|
|
509
|
-
content = ?,
|
|
510
632
|
tags = ?,
|
|
511
|
-
salience = ?,
|
|
512
633
|
access_count = ?
|
|
513
634
|
WHERE id = ?
|
|
514
|
-
`).run(
|
|
515
|
-
//
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
635
|
+
`).run(JSON.stringify([...allTags]), totalAccessCount, kept.id);
|
|
636
|
+
// Dispose of each loser via the SHARED disposal policy (disposeLoser):
|
|
637
|
+
// near-identical (≥ 0.85 vs the kept row) → DELETE; moderate → DOWNVOTE.
|
|
638
|
+
// Identical policy to deduplicateMemories — one source of truth.
|
|
639
|
+
const nowIso = new Date().toISOString();
|
|
640
|
+
const downvoteStmt = db.prepare(DOWNVOTE_SQL);
|
|
641
|
+
const keptText = { content: kept.content, title: kept.title };
|
|
642
|
+
for (const loser of losers) {
|
|
643
|
+
const disposition = disposeLoser(keptText, {
|
|
644
|
+
id: loser.id,
|
|
645
|
+
content: loser.content,
|
|
646
|
+
title: loser.title,
|
|
647
|
+
}, downvoteStmt, nowIso);
|
|
648
|
+
if (disposition === 'deleted')
|
|
649
|
+
deleted++;
|
|
519
650
|
}
|
|
520
651
|
}
|
|
521
652
|
}
|
|
@@ -782,70 +913,109 @@ export function fullCleanup(config = DEFAULT_CONFIG) {
|
|
|
782
913
|
* 1. Find near-duplicates by embedding similarity >0.9, merge them
|
|
783
914
|
* 2. Flag memories >30 days old with no access as archival candidates
|
|
784
915
|
* 3. Detect and flag contradictions
|
|
916
|
+
*
|
|
917
|
+
* DISPOSAL POLICY — deliberately DIVERGES from the auto path:
|
|
918
|
+
* This is the EXPLICIT, user-invoked `shieldcortex consolidate` command (and the
|
|
919
|
+
* public `consolidateMemories` export). Because the user has actively asked for a
|
|
920
|
+
* consolidation, aggressive cleanup is the intended behaviour: the loser of every
|
|
921
|
+
* duplicate pair is HARD-DELETED. This is on purpose and must NOT be replaced with
|
|
922
|
+
* the gentle `disposeLoser` policy.
|
|
923
|
+
*
|
|
924
|
+
* Contrast with the 4-hourly AUTO path (deduplicateMemories / mergeSimilarMemories),
|
|
925
|
+
* which runs UNATTENDED and therefore uses the conservative `disposeLoser`: it only
|
|
926
|
+
* deletes near-identical losers (combined ≥ 0.85, content already contained in the
|
|
927
|
+
* kept row) and merely DOWNVOTES (reversible) the moderate near-dups. That caution
|
|
928
|
+
* is right for an unsupervised background job, but wrong for a deliberate manual
|
|
929
|
+
* cleanup the user explicitly triggered.
|
|
930
|
+
*
|
|
931
|
+
* The two paths DO share keep-selection: both pick the kept row by EFFECTIVE
|
|
932
|
+
* salience (effectiveSalienceOfRow — recency/access/pin/downvote), so the row that
|
|
933
|
+
* survives is consistent across all three dedup sites. Effective salience also
|
|
934
|
+
* discriminates where the pair's raw `recommendedKeepId` (raw salience + recency)
|
|
935
|
+
* ties at 1.0.
|
|
785
936
|
*/
|
|
786
937
|
export function consolidateMemories() {
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
938
|
+
// Wrap the dedup delete loop in a transaction for atomicity: previously each
|
|
939
|
+
// pair was deleted on a bare getDatabase() with no transaction, so a mid-loop
|
|
940
|
+
// failure left partial deletes (some losers gone, tag-merges half-applied).
|
|
941
|
+
return withTransaction(() => {
|
|
942
|
+
const db = getDatabase();
|
|
943
|
+
let nearDuplicatesMerged = 0;
|
|
944
|
+
let archivalCandidates = 0;
|
|
945
|
+
let contradictionsDetected = 0;
|
|
946
|
+
// findDuplicateMemoryPairs returns rowToMemory-converted objects, which omit
|
|
947
|
+
// downvote_count. Fetch raw rows on demand so effective-salience keep-selection
|
|
948
|
+
// sees the full signal (same pattern as deduplicateMemories).
|
|
949
|
+
const rawRowStmt = db.prepare('SELECT * FROM memories WHERE id = ?');
|
|
950
|
+
const rawRow = (id) => rawRowStmt.get(id);
|
|
951
|
+
// Step 1: Find and merge near-duplicates
|
|
952
|
+
const duplicatePairs = findDuplicateMemoryPairs({ limit: 100 });
|
|
953
|
+
for (const pair of duplicatePairs) {
|
|
954
|
+
try {
|
|
955
|
+
const memA = pair.memoryA;
|
|
956
|
+
const memB = pair.memoryB;
|
|
957
|
+
if (!memA || !memB)
|
|
958
|
+
continue;
|
|
959
|
+
// KEEP the higher-EFFECTIVE-salience member (recency/access/pin/downvote),
|
|
960
|
+
// consistent with deduplicateMemories and mergeSimilarMemories — one source
|
|
961
|
+
// of truth via effectiveSalienceOfRow. This can differ from the pair's raw
|
|
962
|
+
// `recommendedKeepId` (raw salience + recency), which can't break a 1.0 tie.
|
|
963
|
+
const rowA = rawRow(memA.id);
|
|
964
|
+
const rowB = rawRow(memB.id);
|
|
965
|
+
if (!rowA || !rowB)
|
|
966
|
+
continue; // already gone (deleted earlier this pass)
|
|
967
|
+
// Tie → keep A (the older row by findDuplicateMemoryPairs' created_at ASC).
|
|
968
|
+
const keepA = effectiveSalienceOfRow(rowA) >= effectiveSalienceOfRow(rowB);
|
|
969
|
+
const kept = keepA ? memA : memB;
|
|
970
|
+
const removed = keepA ? memB : memA;
|
|
971
|
+
// Merge tags from both onto the kept row (metadata only, non-lossy).
|
|
972
|
+
const mergedTags = [...new Set([...kept.tags, ...removed.tags])];
|
|
973
|
+
db.prepare('UPDATE memories SET tags = ? WHERE id = ?')
|
|
974
|
+
.run(JSON.stringify(mergedTags), kept.id);
|
|
975
|
+
// Aggressive hard-DELETE of the loser — intended for this manual command
|
|
976
|
+
// (see the disposal-policy note in the function header).
|
|
977
|
+
deleteMemory(removed.id);
|
|
978
|
+
nearDuplicatesMerged++;
|
|
979
|
+
}
|
|
980
|
+
catch {
|
|
981
|
+
// Skip problematic pairs
|
|
982
|
+
}
|
|
810
983
|
}
|
|
811
|
-
|
|
812
|
-
|
|
984
|
+
// Step 2: Flag stale memories for archival (>30 days, no access)
|
|
985
|
+
const thirtyDaysAgo = new Date(Date.now() - 30 * 86_400_000).toISOString();
|
|
986
|
+
const staleRows = db.prepare(`
|
|
987
|
+
SELECT id FROM memories
|
|
988
|
+
WHERE status = 'active'
|
|
989
|
+
AND last_accessed < ?
|
|
990
|
+
AND access_count <= 1
|
|
991
|
+
AND pinned = 0
|
|
992
|
+
`).all(thirtyDaysAgo);
|
|
993
|
+
for (const row of staleRows) {
|
|
994
|
+
try {
|
|
995
|
+
db.prepare("UPDATE memories SET status = 'archived', updated_at = CURRENT_TIMESTAMP WHERE id = ?")
|
|
996
|
+
.run(row.id);
|
|
997
|
+
archivalCandidates++;
|
|
998
|
+
}
|
|
999
|
+
catch {
|
|
1000
|
+
// Skip
|
|
1001
|
+
}
|
|
813
1002
|
}
|
|
814
|
-
|
|
815
|
-
// Step 2: Flag stale memories for archival (>30 days, no access)
|
|
816
|
-
const thirtyDaysAgo = new Date(Date.now() - 30 * 86_400_000).toISOString();
|
|
817
|
-
const staleRows = db.prepare(`
|
|
818
|
-
SELECT id FROM memories
|
|
819
|
-
WHERE status = 'active'
|
|
820
|
-
AND last_accessed < ?
|
|
821
|
-
AND access_count <= 1
|
|
822
|
-
AND pinned = 0
|
|
823
|
-
`).all(thirtyDaysAgo);
|
|
824
|
-
for (const row of staleRows) {
|
|
1003
|
+
// Step 3: Detect contradictions
|
|
825
1004
|
try {
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
1005
|
+
const contradictions = detectContradictions();
|
|
1006
|
+
if (contradictions.length > 0) {
|
|
1007
|
+
contradictionsDetected = linkContradictions(contradictions);
|
|
1008
|
+
}
|
|
829
1009
|
}
|
|
830
1010
|
catch {
|
|
831
|
-
//
|
|
1011
|
+
// Contradiction detection may fail on empty/small DBs
|
|
832
1012
|
}
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
catch {
|
|
842
|
-
// Contradiction detection may fail on empty/small DBs
|
|
843
|
-
}
|
|
844
|
-
const totalProcessed = duplicatePairs.length + staleRows.length;
|
|
845
|
-
return {
|
|
846
|
-
nearDuplicatesMerged,
|
|
847
|
-
archivalCandidates,
|
|
848
|
-
contradictionsDetected,
|
|
849
|
-
totalProcessed,
|
|
850
|
-
};
|
|
1013
|
+
const totalProcessed = duplicatePairs.length + staleRows.length;
|
|
1014
|
+
return {
|
|
1015
|
+
nearDuplicatesMerged,
|
|
1016
|
+
archivalCandidates,
|
|
1017
|
+
contradictionsDetected,
|
|
1018
|
+
totalProcessed,
|
|
1019
|
+
};
|
|
1020
|
+
});
|
|
851
1021
|
}
|
package/dist/setup/openclaw.d.ts
CHANGED
|
@@ -20,6 +20,32 @@ export declare function isDockerEnvironment(): boolean;
|
|
|
20
20
|
* Creates the hooks/ subdirectory if the parent config dir exists.
|
|
21
21
|
*/
|
|
22
22
|
export declare function findAllHooksDirs(): string[];
|
|
23
|
+
/**
|
|
24
|
+
* The standard installed-hook destination: `~/.openclaw/hooks/cortex-memory`.
|
|
25
|
+
* Resolves the real user's home (sudo-aware) so doctor/postinstall agree with
|
|
26
|
+
* the install path.
|
|
27
|
+
*/
|
|
28
|
+
export declare function defaultHookDestDir(): string;
|
|
29
|
+
/**
|
|
30
|
+
* Single source of truth for "the installed hook copy is out of date".
|
|
31
|
+
*
|
|
32
|
+
* The cortex-memory hook is installed by FILE COPY (see `copyHookFiles`) into
|
|
33
|
+
* `~/.openclaw/hooks/cortex-memory/`. A package update does NOT automatically
|
|
34
|
+
* re-copy it, so the installed `handler.ts` / `runtime.mjs` can drift behind
|
|
35
|
+
* the package's `HOOK_SOURCE` version. This compares every HOOK_FILE in
|
|
36
|
+
* `destDir` against the packaged source by content.
|
|
37
|
+
*
|
|
38
|
+
* Pure + synchronous (fs reads only, no writes, no side effects). Returns
|
|
39
|
+
* `true` if any required file is missing from `destDir` OR differs byte-for-byte
|
|
40
|
+
* from the packaged source. Returns `false` only when every file is present and
|
|
41
|
+
* identical. On any unexpected read error it returns `true` (fail toward
|
|
42
|
+
* "refresh needed") so a half-readable install is never reported as current.
|
|
43
|
+
*
|
|
44
|
+
* If the package's own `HOOK_SOURCE` is missing (corrupt/partial package), the
|
|
45
|
+
* comparison is impossible, so this returns `false` — we can't claim the
|
|
46
|
+
* install is stale relative to a source we can't read.
|
|
47
|
+
*/
|
|
48
|
+
export declare function hookFilesStale(destDir?: string): boolean;
|
|
23
49
|
/**
|
|
24
50
|
* Pure idempotency check for the openclaw.json plugin registration.
|
|
25
51
|
*
|
package/dist/setup/openclaw.js
CHANGED
|
@@ -209,6 +209,67 @@ function legacyHookDirs(hooksDir) {
|
|
|
209
209
|
function hasRequiredHookFiles(dir) {
|
|
210
210
|
return HOOK_FILES.every(file => fs.existsSync(path.join(dir, file)));
|
|
211
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* The standard installed-hook destination: `~/.openclaw/hooks/cortex-memory`.
|
|
214
|
+
* Resolves the real user's home (sudo-aware) so doctor/postinstall agree with
|
|
215
|
+
* the install path.
|
|
216
|
+
*/
|
|
217
|
+
export function defaultHookDestDir() {
|
|
218
|
+
return path.join(resolveUserHome(), '.openclaw', 'hooks', HOOK_NAME);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Single source of truth for "the installed hook copy is out of date".
|
|
222
|
+
*
|
|
223
|
+
* The cortex-memory hook is installed by FILE COPY (see `copyHookFiles`) into
|
|
224
|
+
* `~/.openclaw/hooks/cortex-memory/`. A package update does NOT automatically
|
|
225
|
+
* re-copy it, so the installed `handler.ts` / `runtime.mjs` can drift behind
|
|
226
|
+
* the package's `HOOK_SOURCE` version. This compares every HOOK_FILE in
|
|
227
|
+
* `destDir` against the packaged source by content.
|
|
228
|
+
*
|
|
229
|
+
* Pure + synchronous (fs reads only, no writes, no side effects). Returns
|
|
230
|
+
* `true` if any required file is missing from `destDir` OR differs byte-for-byte
|
|
231
|
+
* from the packaged source. Returns `false` only when every file is present and
|
|
232
|
+
* identical. On any unexpected read error it returns `true` (fail toward
|
|
233
|
+
* "refresh needed") so a half-readable install is never reported as current.
|
|
234
|
+
*
|
|
235
|
+
* If the package's own `HOOK_SOURCE` is missing (corrupt/partial package), the
|
|
236
|
+
* comparison is impossible, so this returns `false` — we can't claim the
|
|
237
|
+
* install is stale relative to a source we can't read.
|
|
238
|
+
*/
|
|
239
|
+
export function hookFilesStale(destDir = defaultHookDestDir()) {
|
|
240
|
+
// No installed copy at all → definitely needs (re)install.
|
|
241
|
+
if (!fs.existsSync(destDir))
|
|
242
|
+
return true;
|
|
243
|
+
// No packaged source to compare against → can't prove staleness.
|
|
244
|
+
if (!fs.existsSync(HOOK_SOURCE))
|
|
245
|
+
return false;
|
|
246
|
+
for (const file of HOOK_FILES) {
|
|
247
|
+
const srcPath = path.join(HOOK_SOURCE, file);
|
|
248
|
+
const destPath = path.join(destDir, file);
|
|
249
|
+
try {
|
|
250
|
+
if (!fs.existsSync(srcPath)) {
|
|
251
|
+
// Packaged source is missing this file — can't compare it; skip.
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
if (!fs.existsSync(destPath))
|
|
255
|
+
return true; // installed copy missing a file
|
|
256
|
+
const srcBuf = fs.readFileSync(srcPath);
|
|
257
|
+
const destBuf = fs.readFileSync(destPath);
|
|
258
|
+
if (!srcBuf.equals(destBuf))
|
|
259
|
+
return true; // content differs → stale
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
// Unreadable file on either side — treat as stale so the user re-copies.
|
|
263
|
+
// DELIBERATE ASYMMETRY with the inline staleness loop in
|
|
264
|
+
// hooks/openclaw/cortex-memory/handler.ts (selfCheckAndHeal), which does
|
|
265
|
+
// NOT flip `stale` on a read error: that runs in the long-lived gateway
|
|
266
|
+
// and must stay quiet on transient errors. This path backs `doctor`, which
|
|
267
|
+
// SHOULD nag on a half-readable install. Keep them divergent.
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
212
273
|
function copyHookFiles(sourceDir, destDir) {
|
|
213
274
|
fs.mkdirSync(destDir, { recursive: true });
|
|
214
275
|
for (const file of HOOK_FILES) {
|
package/dist/tools/remember.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import { addMemory, searchMemories, detectRelationships, createMemoryLink, getLastTruncationInfo } from '../memory/store.js';
|
|
8
|
-
import { analyzeSalienceFactors, explainSalience } from '../memory/salience.js';
|
|
8
|
+
import { calculateSalience, analyzeSalienceFactors, explainSalience } from '../memory/salience.js';
|
|
9
9
|
import { formatErrorForMcp } from '../errors.js';
|
|
10
10
|
import { resolveProject } from '../context/project-context.js';
|
|
11
11
|
import { shouldFilterMemory } from '../memory/save-filter.js';
|
|
@@ -116,7 +116,7 @@ export async function executeRemember(input) {
|
|
|
116
116
|
error: `Memory filtered: ${filterResult.reason}${filterResult.warning ? ' — ' + filterResult.warning : ''}`,
|
|
117
117
|
};
|
|
118
118
|
}
|
|
119
|
-
const
|
|
119
|
+
const memoryInput = {
|
|
120
120
|
title,
|
|
121
121
|
content,
|
|
122
122
|
category: input.category,
|
|
@@ -129,7 +129,28 @@ export async function executeRemember(input) {
|
|
|
129
129
|
metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
|
|
130
130
|
memoryPurpose: input.memoryPurpose,
|
|
131
131
|
memoryScope: input.memoryScope,
|
|
132
|
-
}
|
|
132
|
+
};
|
|
133
|
+
// Defence-in-depth against the "salience wall": automated/hook callers
|
|
134
|
+
// (e.g. the OpenClaw hook, which shells out `remember` with importance:"high"
|
|
135
|
+
// /"critical" and sourceType:"hook") must not mint 0.8/1.0-salience memories
|
|
136
|
+
// the way a human deliberately saving something can. Cap the FINAL resolved
|
|
137
|
+
// salience — covering BOTH the importance-derived override and the
|
|
138
|
+
// calculateSalience fall-through — at the same 0.6 the dedicated auto-extract
|
|
139
|
+
// writer enforces, so even a stale/un-refactored hook can't exceed it by ANY
|
|
140
|
+
// path. Interactive remembers (no source, or a user/cli/agent source) stay
|
|
141
|
+
// uncapped — deliberate intent is honoured. Resolve salience exactly as
|
|
142
|
+
// addMemory does, from the SAME memoryInput object, so there is no input-shape
|
|
143
|
+
// drift, then clamp and pass it verbatim.
|
|
144
|
+
//
|
|
145
|
+
// Canonical constant: scripts/lib/extract-memorable-segments.mjs:24
|
|
146
|
+
// (AUTO_EXTRACT_SALIENCE_CAP = 0.6). It lives in a build-script .mjs outside
|
|
147
|
+
// the compiled src/ surface, so the value is mirrored here.
|
|
148
|
+
if (derivedSource?.type === 'hook') {
|
|
149
|
+
const AUTO_EXTRACT_SALIENCE_CAP = 0.6;
|
|
150
|
+
const effective = memoryInput.salience ?? calculateSalience(memoryInput);
|
|
151
|
+
memoryInput.salience = Math.min(effective, AUTO_EXTRACT_SALIENCE_CAP);
|
|
152
|
+
}
|
|
153
|
+
const memory = addMemory(memoryInput, undefined, derivedSource ?? { type: 'cli', identifier: 'mcp' });
|
|
133
154
|
// Auto-detect and create relationships with existing memories
|
|
134
155
|
let linksCreated = 0;
|
|
135
156
|
try {
|