shieldcortex 4.24.2 → 4.25.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/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/dist/cli/inspect.d.ts +12 -0
- package/dist/cli/inspect.js +137 -0
- package/dist/cli/memory.d.ts +16 -0
- package/dist/cli/memory.js +228 -0
- package/dist/database/init.js +17 -1
- package/dist/database/schema.sql +2 -0
- package/dist/index.js +14 -0
- package/package.json +1 -1
- package/plugins/openclaw/dist/openclaw.plugin.json +1 -1
- package/scripts/lib/extract-memorable-segments.mjs +139 -47
- package/scripts/lib/precompact-log.mjs +142 -0
- package/scripts/lib/recall-rank.mjs +29 -12
- package/scripts/lib/salience.mjs +83 -0
- package/scripts/lib/save-memory.mjs +17 -5
- package/scripts/pre-compact-hook.mjs +32 -0
- package/scripts/prompt-recall-hook.mjs +93 -5
- /package/dashboard/.next/standalone/dashboard/.next/static/{_aYycB3qp_UNTlAYX3vd2 → 7iaOcy1kc6vGZ8eXyOttR}/_buildManifest.js +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{_aYycB3qp_UNTlAYX3vd2 → 7iaOcy1kc6vGZ8eXyOttR}/_clientMiddlewareManifest.json +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{_aYycB3qp_UNTlAYX3vd2 → 7iaOcy1kc6vGZ8eXyOttR}/_ssgManifest.js +0 -0
|
@@ -23,6 +23,37 @@ export const BASE_THRESHOLD = 0.35;
|
|
|
23
23
|
// trust band (0.5–0.7) used elsewhere in the pipeline.
|
|
24
24
|
export const AUTO_EXTRACT_SALIENCE_CAP = 0.6;
|
|
25
25
|
|
|
26
|
+
// v4.25.0: deterministic taxonomy. The extractor already knows *why* a
|
|
27
|
+
// segment matched (extractorType) — derive memory_purpose and category
|
|
28
|
+
// from that signal instead of re-scanning the captured text. Keyword-
|
|
29
|
+
// based suggestCategory() stays as a fallback for any extractorType not
|
|
30
|
+
// in the map (defensive, not currently used by any in-tree extractor).
|
|
31
|
+
//
|
|
32
|
+
// memory_purpose follows the global taxonomy (src/memory/types.ts):
|
|
33
|
+
// user — who the human is
|
|
34
|
+
// feedback — corrections / instructions the human gave the agent
|
|
35
|
+
// project — facts about the project (decisions, architecture, fixes)
|
|
36
|
+
// reference — reusable knowledge (learnings, external references)
|
|
37
|
+
export const EXTRACTOR_TO_PURPOSE = {
|
|
38
|
+
preference: 'feedback',
|
|
39
|
+
decision: 'project',
|
|
40
|
+
architecture: 'project',
|
|
41
|
+
'error-fix': 'project',
|
|
42
|
+
learning: 'reference',
|
|
43
|
+
'important-note': 'project',
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Pinning category by extractorType eliminates the "important-note tagged
|
|
47
|
+
// as 'error' because the text mentioned a bug" failure mode.
|
|
48
|
+
export const EXTRACTOR_TO_CATEGORY = {
|
|
49
|
+
preference: 'preference',
|
|
50
|
+
decision: 'context',
|
|
51
|
+
architecture: 'architecture',
|
|
52
|
+
'error-fix': 'error',
|
|
53
|
+
learning: 'learning',
|
|
54
|
+
'important-note': 'note',
|
|
55
|
+
};
|
|
56
|
+
|
|
26
57
|
// Default category thresholds (session-end / lighter hooks).
|
|
27
58
|
// Pre-compact hook uses tighter thresholds (raised +0.10 in v4.11.0) and
|
|
28
59
|
// passes them via processSegments({ categoryThresholds: ... }).
|
|
@@ -222,73 +253,82 @@ export function getExtractionThreshold(category, dynamicThreshold, categoryThres
|
|
|
222
253
|
}
|
|
223
254
|
|
|
224
255
|
// ==================== EXTRACTOR DEFINITIONS ====================
|
|
225
|
-
|
|
226
|
-
|
|
256
|
+
//
|
|
257
|
+
// All capture groups use `[^.!?\n]{N,M}[.!?]?` instead of `.{N,M}`. The
|
|
258
|
+
// previous fixed-character-window form (`.{15,200}`) sliced clauses at
|
|
259
|
+
// arbitrary offsets, producing memories like
|
|
260
|
+
// "Decision: python3 /home/ubuntu/clawd/scripts/beautyhair_colo..."
|
|
261
|
+
// where the regex grabbed 150 chars after the keyword regardless of where
|
|
262
|
+
// the sentence ended. The new form stops at the first `.`, `!`, `?`, or
|
|
263
|
+
// newline, capping at 200 chars for safety, and optionally consumes the
|
|
264
|
+
// terminator so the captured group ends cleanly. v4.24.3.
|
|
265
|
+
|
|
266
|
+
export const FULL_EXTRACTORS = [
|
|
227
267
|
{
|
|
228
268
|
name: 'decision',
|
|
229
269
|
titlePrefix: 'Decision: ',
|
|
230
270
|
patterns: [
|
|
231
|
-
/(?:we\s+)?decided\s+(?:to\s+)?(
|
|
232
|
-
/(?:going|went)\s+with\s+(
|
|
233
|
-
/(?:chose|chosen|selected)\s+(
|
|
234
|
-
/the\s+(?:approach|solution|fix)\s+(?:is|was)\s+(
|
|
235
|
-
/(?:using|will\s+use)\s+(
|
|
236
|
-
/(?:opted\s+for|settled\s+on)\s+(
|
|
271
|
+
/(?:we\s+)?decided\s+(?:to\s+)?([^.!?\n]{15,200}[.!?]?)/gi,
|
|
272
|
+
/(?:going|went)\s+with\s+([^.!?\n]{15,150}[.!?]?)/gi,
|
|
273
|
+
/(?:chose|chosen|selected)\s+([^.!?\n]{15,150}[.!?]?)/gi,
|
|
274
|
+
/the\s+(?:approach|solution|fix)\s+(?:is|was)\s+([^.!?\n]{15,200}[.!?]?)/gi,
|
|
275
|
+
/(?:using|will\s+use)\s+([^.!?\n]{15,150}[.!?]?)/gi,
|
|
276
|
+
/(?:opted\s+for|settled\s+on)\s+([^.!?\n]{15,150}[.!?]?)/gi,
|
|
237
277
|
],
|
|
238
278
|
},
|
|
239
279
|
{
|
|
240
280
|
name: 'error-fix',
|
|
241
281
|
titlePrefix: 'Fix: ',
|
|
242
282
|
patterns: [
|
|
243
|
-
/(?:fixed|solved|resolved)\s+(?:by\s+)?(
|
|
244
|
-
/the\s+(?:fix|solution|workaround)\s+(?:is|was)\s+(
|
|
245
|
-
/(?:root\s+cause|issue)\s+(?:is|was)\s+(
|
|
246
|
-
/(?:error|bug)\s+(?:was\s+)?caused\s+by\s+(
|
|
247
|
-
/(?:problem|issue)\s+was\s+(
|
|
248
|
-
/(?:the\s+)?bug\s+(?:is|was)\s+(
|
|
249
|
-
/(?:debugging|debugged)\s+(
|
|
283
|
+
/(?:fixed|solved|resolved)\s+(?:by\s+)?([^.!?\n]{15,200}[.!?]?)/gi,
|
|
284
|
+
/the\s+(?:fix|solution|workaround)\s+(?:is|was)\s+([^.!?\n]{15,200}[.!?]?)/gi,
|
|
285
|
+
/(?:root\s+cause|issue)\s+(?:is|was)\s+([^.!?\n]{15,200}[.!?]?)/gi,
|
|
286
|
+
/(?:error|bug)\s+(?:was\s+)?caused\s+by\s+([^.!?\n]{15,200}[.!?]?)/gi,
|
|
287
|
+
/(?:problem|issue)\s+was\s+([^.!?\n]{15,150}[.!?]?)/gi,
|
|
288
|
+
/(?:the\s+)?bug\s+(?:is|was)\s+([^.!?\n]{15,150}[.!?]?)/gi,
|
|
289
|
+
/(?:debugging|debugged)\s+([^.!?\n]{15,150}[.!?]?)/gi,
|
|
250
290
|
],
|
|
251
291
|
},
|
|
252
292
|
{
|
|
253
293
|
name: 'learning',
|
|
254
294
|
titlePrefix: 'Learned: ',
|
|
255
295
|
patterns: [
|
|
256
|
-
/(?:learned|discovered|realized|found\s+out)\s+(?:that\s+)?(
|
|
257
|
-
/turns\s+out\s+(?:that\s+)?(
|
|
258
|
-
/(?:TIL|today\s+I\s+learned)[:\s]+(
|
|
259
|
-
/(?:now\s+)?(?:understand|know)\s+(?:that\s+)?(
|
|
260
|
-
/(?:figured\s+out|worked\s+out)\s+(
|
|
296
|
+
/(?:learned|discovered|realized|found\s+out)\s+(?:that\s+)?([^.!?\n]{15,200}[.!?]?)/gi,
|
|
297
|
+
/turns\s+out\s+(?:that\s+)?([^.!?\n]{15,200}[.!?]?)/gi,
|
|
298
|
+
/(?:TIL|today\s+I\s+learned)[:\s]+([^.!?\n]{15,200}[.!?]?)/gi,
|
|
299
|
+
/(?:now\s+)?(?:understand|know)\s+(?:that\s+)?([^.!?\n]{15,150}[.!?]?)/gi,
|
|
300
|
+
/(?:figured\s+out|worked\s+out)\s+([^.!?\n]{15,150}[.!?]?)/gi,
|
|
261
301
|
],
|
|
262
302
|
},
|
|
263
303
|
{
|
|
264
304
|
name: 'architecture',
|
|
265
305
|
titlePrefix: 'Architecture: ',
|
|
266
306
|
patterns: [
|
|
267
|
-
/the\s+architecture\s+(?:is|uses|consists\s+of)\s+(
|
|
268
|
-
/(?:design|pattern)\s+(?:is|uses)\s+(
|
|
269
|
-
/(?:system|api|database)\s+(?:structure|design)\s+(?:is|uses)\s+(
|
|
270
|
-
/(?:created|added|implemented|built)\s+(?:a\s+)?(
|
|
271
|
-
/(?:refactored|updated|changed)\s+(?:the\s+)?(
|
|
307
|
+
/the\s+architecture\s+(?:is|uses|consists\s+of)\s+([^.!?\n]{15,200}[.!?]?)/gi,
|
|
308
|
+
/(?:design|pattern)\s+(?:is|uses)\s+([^.!?\n]{15,200}[.!?]?)/gi,
|
|
309
|
+
/(?:system|api|database)\s+(?:structure|design)\s+(?:is|uses)\s+([^.!?\n]{15,200}[.!?]?)/gi,
|
|
310
|
+
/(?:created|added|implemented|built)\s+(?:a\s+)?([^.!?\n]{15,200}[.!?]?)/gi,
|
|
311
|
+
/(?:refactored|updated|changed)\s+(?:the\s+)?([^.!?\n]{15,150}[.!?]?)/gi,
|
|
272
312
|
],
|
|
273
313
|
},
|
|
274
314
|
{
|
|
275
315
|
name: 'preference',
|
|
276
316
|
titlePrefix: 'Preference: ',
|
|
277
317
|
patterns: [
|
|
278
|
-
/(?:always|never)\s+(
|
|
279
|
-
/(?:prefer|want)\s+to\s+(
|
|
280
|
-
/(?:should|must)\s+(?:always\s+)?(
|
|
318
|
+
/(?:always|never)\s+([^.!?\n]{10,150}[.!?]?)/gi,
|
|
319
|
+
/(?:prefer|want)\s+to\s+([^.!?\n]{10,150}[.!?]?)/gi,
|
|
320
|
+
/(?:should|must)\s+(?:always\s+)?([^.!?\n]{10,150}[.!?]?)/gi,
|
|
281
321
|
],
|
|
282
322
|
},
|
|
283
323
|
{
|
|
284
324
|
name: 'important-note',
|
|
285
325
|
titlePrefix: 'Note: ',
|
|
286
326
|
patterns: [
|
|
287
|
-
/important[:\s]+(
|
|
288
|
-
/(?:note|remember)[:\s]+(
|
|
289
|
-
/(?:key|critical)\s+(?:point|thing)[:\s]+(
|
|
290
|
-
/(?:this\s+is\s+)?(?:crucial|essential)[:\s]+(
|
|
291
|
-
/(?:don't\s+forget|keep\s+in\s+mind)[:\s]+(
|
|
327
|
+
/important[:\s]+([^.!?\n]{15,200}[.!?]?)/gi,
|
|
328
|
+
/(?:note|remember)[:\s]+([^.!?\n]{15,200}[.!?]?)/gi,
|
|
329
|
+
/(?:key|critical)\s+(?:point|thing)[:\s]+([^.!?\n]{15,200}[.!?]?)/gi,
|
|
330
|
+
/(?:this\s+is\s+)?(?:crucial|essential)[:\s]+([^.!?\n]{15,150}[.!?]?)/gi,
|
|
331
|
+
/(?:don't\s+forget|keep\s+in\s+mind)[:\s]+([^.!?\n]{15,150}[.!?]?)/gi,
|
|
292
332
|
],
|
|
293
333
|
},
|
|
294
334
|
];
|
|
@@ -296,37 +336,76 @@ const FULL_EXTRACTORS = [
|
|
|
296
336
|
// stop-hook historically used a thinner extractor set (no architecture,
|
|
297
337
|
// no important-note, fewer learning + preference patterns). Preserve the
|
|
298
338
|
// pre-refactor surface so its behaviour does not change with this move.
|
|
299
|
-
|
|
339
|
+
// Same sentence-bounded capture form as FULL_EXTRACTORS (v4.24.3).
|
|
340
|
+
export const STOP_HOOK_EXTRACTORS = [
|
|
300
341
|
FULL_EXTRACTORS[0], // decision
|
|
301
342
|
{
|
|
302
343
|
name: 'error-fix',
|
|
303
344
|
titlePrefix: 'Fix: ',
|
|
304
345
|
patterns: [
|
|
305
|
-
/(?:fixed|solved|resolved)\s+(?:by\s+)?(
|
|
306
|
-
/the\s+(?:fix|solution|workaround)\s+(?:is|was)\s+(
|
|
307
|
-
/(?:root\s+cause|issue)\s+(?:is|was)\s+(
|
|
308
|
-
/(?:error|bug)\s+(?:was\s+)?caused\s+by\s+(
|
|
346
|
+
/(?:fixed|solved|resolved)\s+(?:by\s+)?([^.!?\n]{15,200}[.!?]?)/gi,
|
|
347
|
+
/the\s+(?:fix|solution|workaround)\s+(?:is|was)\s+([^.!?\n]{15,200}[.!?]?)/gi,
|
|
348
|
+
/(?:root\s+cause|issue)\s+(?:is|was)\s+([^.!?\n]{15,200}[.!?]?)/gi,
|
|
349
|
+
/(?:error|bug)\s+(?:was\s+)?caused\s+by\s+([^.!?\n]{15,200}[.!?]?)/gi,
|
|
309
350
|
],
|
|
310
351
|
},
|
|
311
352
|
{
|
|
312
353
|
name: 'learning',
|
|
313
354
|
titlePrefix: 'Learned: ',
|
|
314
355
|
patterns: [
|
|
315
|
-
/(?:learned|discovered|realized|found\s+out)\s+(?:that\s+)?(
|
|
316
|
-
/turns\s+out\s+(?:that\s+)?(
|
|
317
|
-
/(?:figured\s+out|worked\s+out)\s+(
|
|
356
|
+
/(?:learned|discovered|realized|found\s+out)\s+(?:that\s+)?([^.!?\n]{15,200}[.!?]?)/gi,
|
|
357
|
+
/turns\s+out\s+(?:that\s+)?([^.!?\n]{15,200}[.!?]?)/gi,
|
|
358
|
+
/(?:figured\s+out|worked\s+out)\s+([^.!?\n]{15,150}[.!?]?)/gi,
|
|
318
359
|
],
|
|
319
360
|
},
|
|
320
361
|
{
|
|
321
362
|
name: 'preference',
|
|
322
363
|
titlePrefix: 'Preference: ',
|
|
323
364
|
patterns: [
|
|
324
|
-
/(?:always|never)\s+(
|
|
325
|
-
/(?:prefer|want)\s+to\s+(
|
|
365
|
+
/(?:always|never)\s+([^.!?\n]{10,150}[.!?]?)/gi,
|
|
366
|
+
/(?:prefer|want)\s+to\s+([^.!?\n]{10,150}[.!?]?)/gi,
|
|
326
367
|
],
|
|
327
368
|
},
|
|
328
369
|
];
|
|
329
370
|
|
|
371
|
+
/**
|
|
372
|
+
* Defensive JSON-escape unescape. Some upstream paths re-emit
|
|
373
|
+
* conversation text after a stringify/parse round-trip without unescaping
|
|
374
|
+
* the inner string, so literal `\n` / `\t` / `\r` sequences leak through
|
|
375
|
+
* into matched segments. This fixes the most common leaks idempotently —
|
|
376
|
+
* sequences that are already real newlines / tabs / carriage returns are
|
|
377
|
+
* different characters from the literal 2-char `\n` / `\t` / `\r` so the
|
|
378
|
+
* replacement is a no-op on already-unescaped input. The lookbehind keeps
|
|
379
|
+
* `\\n` (genuine literal backslash + n) intact.
|
|
380
|
+
*/
|
|
381
|
+
function defensiveUnescape(text) {
|
|
382
|
+
return text
|
|
383
|
+
.replace(/(?<!\\)\\n/g, '\n')
|
|
384
|
+
.replace(/(?<!\\)\\t/g, '\t')
|
|
385
|
+
.replace(/(?<!\\)\\r/g, '\r');
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Take a captured snippet and return the first sentence (or first
|
|
390
|
+
* word-bounded slice up to `maxLen` if no sentence terminator is nearby).
|
|
391
|
+
* Replaces the old `slice(0, 50)` headline which produced mid-clause
|
|
392
|
+
* garbage like "Decision: any command you must be authenticated. Run x..."
|
|
393
|
+
* where the first 50 chars meant nothing without their context.
|
|
394
|
+
*/
|
|
395
|
+
function extractFirstSentence(text, maxLen = 80) {
|
|
396
|
+
const trimmed = text.trim().replace(/\s+/g, ' ');
|
|
397
|
+
// Find first sentence terminator within reasonable bounds. The terminator
|
|
398
|
+
// must be followed by whitespace OR end-of-string so URLs / decimals /
|
|
399
|
+
// version strings ("v4.24.3") don't fool it.
|
|
400
|
+
const match = trimmed.match(/^([^.!?\n]{15,160}[.!?])(?:\s|$)/);
|
|
401
|
+
if (match) return match[1].slice(0, maxLen);
|
|
402
|
+
// No sentence boundary — trim to maxLen at the nearest word boundary.
|
|
403
|
+
if (trimmed.length <= maxLen) return trimmed;
|
|
404
|
+
const truncated = trimmed.slice(0, maxLen);
|
|
405
|
+
const lastSpace = truncated.lastIndexOf(' ');
|
|
406
|
+
return lastSpace > maxLen * 0.5 ? truncated.slice(0, lastSpace) : truncated;
|
|
407
|
+
}
|
|
408
|
+
|
|
330
409
|
/**
|
|
331
410
|
* Extract memorable segments from conversation text.
|
|
332
411
|
*
|
|
@@ -338,16 +417,23 @@ export function extractMemorableSegments(conversationText, opts = {}) {
|
|
|
338
417
|
const extractors = opts.mode === 'stop' ? STOP_HOOK_EXTRACTORS : FULL_EXTRACTORS;
|
|
339
418
|
const segments = [];
|
|
340
419
|
|
|
420
|
+
// v4.24.3: unescape JSON-encoded escapes before regex matching so
|
|
421
|
+
// captured content doesn't include literal `\n` / `\t` sequences.
|
|
422
|
+
const text = defensiveUnescape(conversationText);
|
|
423
|
+
|
|
341
424
|
for (const extractor of extractors) {
|
|
342
425
|
for (const pattern of extractor.patterns) {
|
|
343
426
|
// Reset lastIndex defensively — patterns are module-level globals.
|
|
344
427
|
pattern.lastIndex = 0;
|
|
345
428
|
let match;
|
|
346
|
-
while ((match = pattern.exec(
|
|
429
|
+
while ((match = pattern.exec(text)) !== null) {
|
|
347
430
|
const content = match[1].trim();
|
|
348
431
|
if (content.length >= 20) {
|
|
349
|
-
|
|
350
|
-
|
|
432
|
+
// v4.24.3: headline = first sentence (sentence-bounded), not
|
|
433
|
+
// the first 50 chars. Eliminates mid-clause garbage in the
|
|
434
|
+
// MEMORY.md index.
|
|
435
|
+
const headline = extractFirstSentence(content, 80);
|
|
436
|
+
const title = extractor.titlePrefix + headline;
|
|
351
437
|
segments.push({
|
|
352
438
|
title,
|
|
353
439
|
content: content.slice(0, 500),
|
|
@@ -543,11 +629,17 @@ export function processSegments(segments, dynamicThreshold = BASE_THRESHOLD, opt
|
|
|
543
629
|
if (!isDupe) {
|
|
544
630
|
const text = seg.title + ' ' + seg.content;
|
|
545
631
|
const baseSalience = calculateSalience(text);
|
|
546
|
-
|
|
632
|
+
// v4.25.0: extractorType drives category and memory_purpose. Fall
|
|
633
|
+
// back to keyword-based suggestCategory only when extractorType is
|
|
634
|
+
// unknown (defensive; no in-tree extractor produces a name outside
|
|
635
|
+
// EXTRACTOR_TO_CATEGORY).
|
|
636
|
+
const category = EXTRACTOR_TO_CATEGORY[seg.extractorType] ?? suggestCategory(text);
|
|
637
|
+
const memoryPurpose = EXTRACTOR_TO_PURPOSE[seg.extractorType] ?? 'project';
|
|
547
638
|
unique.push({
|
|
548
639
|
...seg,
|
|
549
640
|
baseSalience,
|
|
550
641
|
category,
|
|
642
|
+
memoryPurpose,
|
|
551
643
|
tags: extractTags(text, hookTag, seg.extractorType),
|
|
552
644
|
});
|
|
553
645
|
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Precompact ring buffer (v4.25.0).
|
|
3
|
+
*
|
|
4
|
+
* Each precompact hook run writes a debug log of "what did the extractor
|
|
5
|
+
* propose this time, and which proposals actually landed in `memories`?"
|
|
6
|
+
* Operators can read it via `shieldcortex inspect last-precompact` when
|
|
7
|
+
* tuning thresholds or chasing weird auto-extract behaviour.
|
|
8
|
+
*
|
|
9
|
+
* Ring buffer at `~/.shieldcortex/precompact-log/{0..9}.json` — index 0 is
|
|
10
|
+
* the most recent. On every write we rotate (delete 9, rename 8→9, ..., 0→1)
|
|
11
|
+
* and atomically write the new run to index 0 via a temp-file + rename so a
|
|
12
|
+
* crash mid-rotation never leaves a torn JSON file.
|
|
13
|
+
*
|
|
14
|
+
* Size cap: 10 files × ~5KB each = ~50KB. Negligible disk impact.
|
|
15
|
+
*
|
|
16
|
+
* Designed to be best-effort — never throws into the caller. The hook
|
|
17
|
+
* absolutely must not block compaction on a missing ~/.shieldcortex
|
|
18
|
+
* directory or a transient EBUSY.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'fs';
|
|
22
|
+
import { homedir } from 'os';
|
|
23
|
+
import { join } from 'path';
|
|
24
|
+
|
|
25
|
+
const RING_SIZE = 10;
|
|
26
|
+
|
|
27
|
+
// Resolved per-call so tests can swap HOME between cases. Read
|
|
28
|
+
// `process.env.HOME` directly rather than going through `os.homedir()`
|
|
29
|
+
// because jest's ESM VM loader doesn't reliably reflect HOME mutations
|
|
30
|
+
// through homedir(), causing test-suite cross-contamination.
|
|
31
|
+
function logDir() {
|
|
32
|
+
return join(process.env.HOME || homedir(), '.shieldcortex', 'precompact-log');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function logPath(index) {
|
|
36
|
+
return join(logDir(), `${index}.json`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function ensureDir() {
|
|
40
|
+
const dir = logDir();
|
|
41
|
+
if (!existsSync(dir)) {
|
|
42
|
+
mkdirSync(dir, { recursive: true });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Rotate the ring buffer one slot. Oldest entry (index 9) is unlinked,
|
|
48
|
+
* remaining entries shift up by one. Safe to call when slots are missing.
|
|
49
|
+
*/
|
|
50
|
+
function rotate() {
|
|
51
|
+
try {
|
|
52
|
+
unlinkSync(logPath(RING_SIZE - 1));
|
|
53
|
+
} catch {
|
|
54
|
+
// No file at the oldest slot — fine.
|
|
55
|
+
}
|
|
56
|
+
for (let i = RING_SIZE - 2; i >= 0; i--) {
|
|
57
|
+
const from = logPath(i);
|
|
58
|
+
const to = logPath(i + 1);
|
|
59
|
+
if (existsSync(from)) {
|
|
60
|
+
try {
|
|
61
|
+
renameSync(from, to);
|
|
62
|
+
} catch {
|
|
63
|
+
// Best-effort — skip if EBUSY/EACCES.
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Atomically write a precompact run entry to slot 0 (the newest slot).
|
|
71
|
+
* Rotates the ring beforehand.
|
|
72
|
+
*
|
|
73
|
+
* @param {{
|
|
74
|
+
* ranAt?: string,
|
|
75
|
+
* thresholdUsed?: number,
|
|
76
|
+
* contextFullnessPct?: number,
|
|
77
|
+
* totalMemories?: number,
|
|
78
|
+
* candidates: Array<{
|
|
79
|
+
* extractorType?: string,
|
|
80
|
+
* category?: string,
|
|
81
|
+
* memoryPurpose?: string,
|
|
82
|
+
* title?: string,
|
|
83
|
+
* salience?: number,
|
|
84
|
+
* saved?: boolean,
|
|
85
|
+
* memoryId?: number | null,
|
|
86
|
+
* dropReason?: string | null,
|
|
87
|
+
* }>,
|
|
88
|
+
* }} entry
|
|
89
|
+
*/
|
|
90
|
+
export function writePrecompactLog(entry) {
|
|
91
|
+
try {
|
|
92
|
+
ensureDir();
|
|
93
|
+
rotate();
|
|
94
|
+
const payload = {
|
|
95
|
+
ranAt: entry.ranAt ?? new Date().toISOString(),
|
|
96
|
+
thresholdUsed: entry.thresholdUsed ?? null,
|
|
97
|
+
contextFullnessPct: entry.contextFullnessPct ?? null,
|
|
98
|
+
totalMemories: entry.totalMemories ?? null,
|
|
99
|
+
candidates: Array.isArray(entry.candidates) ? entry.candidates : [],
|
|
100
|
+
};
|
|
101
|
+
const target = logPath(0);
|
|
102
|
+
const tmp = `${target}.tmp`;
|
|
103
|
+
writeFileSync(tmp, JSON.stringify(payload, null, 2), 'utf8');
|
|
104
|
+
renameSync(tmp, target);
|
|
105
|
+
} catch {
|
|
106
|
+
// Best-effort. The hook continues without a log entry rather than
|
|
107
|
+
// blocking compaction on a disk error.
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Read a precompact log entry by ring index.
|
|
113
|
+
*
|
|
114
|
+
* @param {number} index — 0 = newest, RING_SIZE-1 = oldest
|
|
115
|
+
* @returns {object | null} parsed entry, or null if missing/corrupt
|
|
116
|
+
*/
|
|
117
|
+
export function readPrecompactLog(index = 0) {
|
|
118
|
+
try {
|
|
119
|
+
const raw = readFileSync(logPath(index), 'utf8');
|
|
120
|
+
return JSON.parse(raw);
|
|
121
|
+
} catch {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Read all present precompact log entries, newest first. Missing slots are
|
|
128
|
+
* skipped (no nulls in the returned array).
|
|
129
|
+
*
|
|
130
|
+
* @returns {Array<{ index: number, entry: object }>}
|
|
131
|
+
*/
|
|
132
|
+
export function listPrecompactLogs() {
|
|
133
|
+
const out = [];
|
|
134
|
+
for (let i = 0; i < RING_SIZE; i++) {
|
|
135
|
+
const entry = readPrecompactLog(i);
|
|
136
|
+
if (entry) out.push({ index: i, entry });
|
|
137
|
+
}
|
|
138
|
+
return out;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export const PRECOMPACT_RING_SIZE = RING_SIZE;
|
|
142
|
+
export { logDir as getPrecompactLogDir };
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Recall result ranking helpers
|
|
2
|
+
* Recall result ranking helpers.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* by RAW salience, discarding the relevance signal. Result: high-salience-
|
|
7
|
-
* but-off-topic memories bubbled to the top of the per-prompt recall preamble
|
|
8
|
-
* ("Decision: that path for the rest of this conversation"-style fragments).
|
|
4
|
+
* v4.23.0 — FTS rank primary, raw salience tiebreaker (fixed: high-salience-
|
|
5
|
+
* but-off-topic memories bubbling to the top of the per-prompt recall preamble).
|
|
9
6
|
*
|
|
10
|
-
* v4.
|
|
11
|
-
*
|
|
7
|
+
* v4.25.0 — tiebreaker now uses *effective* salience instead of raw:
|
|
8
|
+
* recency × access × pin × downvote_penalty. See scripts/lib/salience.mjs.
|
|
9
|
+
* The DB column stays untouched — this is a read-time computation only.
|
|
12
10
|
*
|
|
13
11
|
* SQLite FTS5 BM25 ranks are negative numbers — more negative = more
|
|
14
12
|
* relevant. So `a.rank - b.rank` (ascending) puts the most-relevant result
|
|
@@ -16,21 +14,36 @@
|
|
|
16
14
|
* field; they sort below all FTS results.
|
|
17
15
|
*/
|
|
18
16
|
|
|
17
|
+
import { computeEffectiveSalience } from './salience.mjs';
|
|
18
|
+
|
|
19
19
|
/**
|
|
20
20
|
* Sort comparator for memory recall results.
|
|
21
21
|
*
|
|
22
22
|
* Behaviour:
|
|
23
23
|
* - Both rows have `rank` (FTS results): lower rank wins (more relevant)
|
|
24
24
|
* - Only one has `rank`: that one wins (FTS beats category-only fallback)
|
|
25
|
-
* - Neither has `rank` (or tied): higher salience wins
|
|
25
|
+
* - Neither has `rank` (or tied): higher *effective* salience wins
|
|
26
26
|
*
|
|
27
27
|
* Stable behaviour for equal-rank-equal-salience: original order preserved
|
|
28
28
|
* (Array.prototype.sort in modern engines is stable).
|
|
29
29
|
*
|
|
30
|
-
* @param {{ rank?: number, salience?: number }} a
|
|
31
|
-
* @param {{ rank?: number, salience?: number }} b
|
|
30
|
+
* @param {{ rank?: number, salience?: number, last_accessed?: string, access_count?: number, pinned?: number, downvote_count?: number }} a
|
|
31
|
+
* @param {{ rank?: number, salience?: number, last_accessed?: string, access_count?: number, pinned?: number, downvote_count?: number }} b
|
|
32
32
|
* @returns {number} negative if a comes first, positive if b comes first
|
|
33
33
|
*/
|
|
34
|
+
// A row carries the v4.25 salience-formula inputs only when the SELECT
|
|
35
|
+
// projected pinned/access_count/last_accessed/downvote_count. Older call
|
|
36
|
+
// sites and recall-rank tests pass rows with just {id, rank, salience} —
|
|
37
|
+
// for those, fall back to raw salience comparison (v4.23 behaviour).
|
|
38
|
+
function hasSalienceFormulaInputs(row) {
|
|
39
|
+
return (
|
|
40
|
+
row.access_count !== undefined ||
|
|
41
|
+
row.last_accessed !== undefined ||
|
|
42
|
+
row.pinned !== undefined ||
|
|
43
|
+
row.downvote_count !== undefined
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
34
47
|
export function compareRecallResults(a, b) {
|
|
35
48
|
const aHasRank = typeof a.rank === 'number' && Number.isFinite(a.rank);
|
|
36
49
|
const bHasRank = typeof b.rank === 'number' && Number.isFinite(b.rank);
|
|
@@ -41,6 +54,10 @@ export function compareRecallResults(a, b) {
|
|
|
41
54
|
} else if (aHasRank !== bHasRank) {
|
|
42
55
|
return aHasRank ? -1 : 1;
|
|
43
56
|
}
|
|
44
|
-
//
|
|
57
|
+
// v4.25.0: effective salience if both rows carry the formula inputs.
|
|
58
|
+
// Otherwise (legacy or test rows) preserve v4.23 raw-salience behaviour.
|
|
59
|
+
if (hasSalienceFormulaInputs(a) && hasSalienceFormulaInputs(b)) {
|
|
60
|
+
return computeEffectiveSalience(b) - computeEffectiveSalience(a);
|
|
61
|
+
}
|
|
45
62
|
return (b.salience ?? 0) - (a.salience ?? 0);
|
|
46
63
|
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effective salience computation (v4.25.0).
|
|
3
|
+
*
|
|
4
|
+
* Pre-4.25 the recall hook ranked tied FTS results by raw `salience` only.
|
|
5
|
+
* That ignored real signal: a memory that was last accessed 3 months ago
|
|
6
|
+
* carries less weight than a memory accessed yesterday; a pinned memory
|
|
7
|
+
* deserves more weight than an identical unpinned one; a memory the user
|
|
8
|
+
* downvoted via `shieldcortex memory downvote <id>` should be demoted.
|
|
9
|
+
*
|
|
10
|
+
* Formula:
|
|
11
|
+
* effective = base × recency × access × pin × downvote_penalty
|
|
12
|
+
*
|
|
13
|
+
* recency = exp(-Δt_days / halfLifeDays) // decay
|
|
14
|
+
* access = log(1 + access_count) / log(1 + accessNorm)
|
|
15
|
+
* pin = pinned ? pinBoost : 1
|
|
16
|
+
* downvote_penalty = max(0.1, 1 - downvoteDecay × downvote_count)
|
|
17
|
+
*
|
|
18
|
+
* All constants are env-var-tunable (no recompile needed for field tuning).
|
|
19
|
+
*
|
|
20
|
+
* The function returns the *multiplier-adjusted* salience. The base salience
|
|
21
|
+
* column in SQLite stays untouched — this is a read-time computation.
|
|
22
|
+
*
|
|
23
|
+
* @param {{
|
|
24
|
+
* salience?: number,
|
|
25
|
+
* last_accessed?: string | null,
|
|
26
|
+
* access_count?: number | null,
|
|
27
|
+
* pinned?: number | boolean | null,
|
|
28
|
+
* downvote_count?: number | null
|
|
29
|
+
* }} memory
|
|
30
|
+
* @param {{
|
|
31
|
+
* halfLifeDays?: number,
|
|
32
|
+
* accessNorm?: number,
|
|
33
|
+
* pinBoost?: number,
|
|
34
|
+
* downvoteDecay?: number,
|
|
35
|
+
* now?: number,
|
|
36
|
+
* }} [opts]
|
|
37
|
+
* @returns {number}
|
|
38
|
+
*/
|
|
39
|
+
// Resolve a numeric tuning constant from opts (explicit override), then
|
|
40
|
+
// SHIELDCORTEX_* env var, then the documented default. Returns the default
|
|
41
|
+
// if either of the first two is NaN — we never want a typo'd env var to
|
|
42
|
+
// silently zero out a multiplier.
|
|
43
|
+
function pickNumber(override, envName, fallback) {
|
|
44
|
+
if (typeof override === 'number' && Number.isFinite(override)) return override;
|
|
45
|
+
const fromEnv = Number(process.env[envName]);
|
|
46
|
+
if (Number.isFinite(fromEnv) && fromEnv !== 0) return fromEnv;
|
|
47
|
+
return fallback;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function computeEffectiveSalience(memory, opts = {}) {
|
|
51
|
+
const halfLifeDays = pickNumber(opts.halfLifeDays, 'SHIELDCORTEX_SALIENCE_HALF_LIFE_DAYS', 14);
|
|
52
|
+
const accessNorm = pickNumber(opts.accessNorm, 'SHIELDCORTEX_SALIENCE_ACCESS_NORM', 10);
|
|
53
|
+
const pinBoost = pickNumber(opts.pinBoost, 'SHIELDCORTEX_SALIENCE_PIN_BOOST', 1.5);
|
|
54
|
+
const downvoteDecay = pickNumber(opts.downvoteDecay, 'SHIELDCORTEX_SALIENCE_DOWNVOTE_DECAY', 0.3);
|
|
55
|
+
const now = opts.now ?? Date.now();
|
|
56
|
+
|
|
57
|
+
const base = typeof memory.salience === 'number' ? memory.salience : 0;
|
|
58
|
+
|
|
59
|
+
// Recency: exp(-Δt_days / halfLife). last_accessed missing → assume "now"
|
|
60
|
+
// (a brand-new memory should not be penalised for never having been read).
|
|
61
|
+
let recency = 1;
|
|
62
|
+
if (memory.last_accessed) {
|
|
63
|
+
const lastMs = Date.parse(memory.last_accessed);
|
|
64
|
+
if (Number.isFinite(lastMs)) {
|
|
65
|
+
const deltaDays = Math.max(0, (now - lastMs) / 86_400_000);
|
|
66
|
+
recency = Math.exp(-deltaDays / halfLifeDays);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Access: log-scaled, normalised so access_count=accessNorm produces ~1.0.
|
|
71
|
+
const accessCount = Math.max(0, Number(memory.access_count) || 0);
|
|
72
|
+
const access = Math.log1p(accessCount) / Math.log1p(accessNorm);
|
|
73
|
+
|
|
74
|
+
// Pin: SQLite stores boolean as 0/1.
|
|
75
|
+
const pin = memory.pinned ? pinBoost : 1;
|
|
76
|
+
|
|
77
|
+
// Downvote: each downvote lops downvoteDecay off the multiplier, floored
|
|
78
|
+
// at 0.1 so a 4×-downvoted memory can still surface when truly relevant.
|
|
79
|
+
const downvotes = Math.max(0, Number(memory.downvote_count) || 0);
|
|
80
|
+
const downvotePenalty = Math.max(0.1, 1 - downvoteDecay * downvotes);
|
|
81
|
+
|
|
82
|
+
return base * recency * access * pin * downvotePenalty;
|
|
83
|
+
}
|
|
@@ -20,7 +20,7 @@ import { fileURLToPath, pathToFileURL } from 'url';
|
|
|
20
20
|
* Async: the pipeline lives in dist/ as ESM and is loaded via dynamic import.
|
|
21
21
|
*
|
|
22
22
|
* @param {import('better-sqlite3').Database} db
|
|
23
|
-
* @param {{ title: string, content: string, category: string, salience: number, tags: string[] }} memory
|
|
23
|
+
* @param {{ title: string, content: string, category: string, salience: number, tags: string[], memoryPurpose?: string }} memory
|
|
24
24
|
* @param {string|null} [project]
|
|
25
25
|
* @param {{ source?: string }} [opts] — `source` identifies the calling hook
|
|
26
26
|
* ('session-end-hook' | 'pre-compact-hook' | 'stop-hook' | 'hook').
|
|
@@ -50,7 +50,7 @@ export async function saveAutoExtractedMemory(db, memory, project, opts = {}) {
|
|
|
50
50
|
const decision = result.firewall.result;
|
|
51
51
|
|
|
52
52
|
if (decision === 'ALLOW') {
|
|
53
|
-
insertMemoryRow(db, memory, project);
|
|
53
|
+
insertMemoryRow(db, memory, project, sourceIdentifier);
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -73,11 +73,21 @@ export async function saveAutoExtractedMemory(db, memory, project, opts = {}) {
|
|
|
73
73
|
|
|
74
74
|
// ==================== Internal: writes ====================
|
|
75
75
|
|
|
76
|
-
function insertMemoryRow(db, memory, project) {
|
|
76
|
+
function insertMemoryRow(db, memory, project, sourceIdentifier) {
|
|
77
77
|
const timestamp = new Date().toISOString();
|
|
78
|
+
// v4.25.0: pre-4.25 the INSERT omitted memory_purpose / source / source_kind
|
|
79
|
+
// / capture_method, so every hook write looked identical to a user-typed
|
|
80
|
+
// memory at the SQL level. The hook already knows which hook is calling
|
|
81
|
+
// (sourceIdentifier) and the extractor already computed memoryPurpose —
|
|
82
|
+
// thread both through so `shieldcortex inspect last-precompact` and any
|
|
83
|
+
// memory-source SQL query can distinguish hook writes from user writes.
|
|
78
84
|
db.prepare(`
|
|
79
|
-
INSERT INTO memories (
|
|
80
|
-
|
|
85
|
+
INSERT INTO memories (
|
|
86
|
+
uuid, title, content, type, category, salience, tags, project,
|
|
87
|
+
memory_purpose, source, source_kind, capture_method,
|
|
88
|
+
created_at, last_accessed
|
|
89
|
+
)
|
|
90
|
+
VALUES (?, ?, ?, 'short_term', ?, ?, ?, ?, ?, ?, 'hook', 'auto', ?, ?)
|
|
81
91
|
`).run(
|
|
82
92
|
randomUUID(),
|
|
83
93
|
memory.title,
|
|
@@ -86,6 +96,8 @@ function insertMemoryRow(db, memory, project) {
|
|
|
86
96
|
memory.salience,
|
|
87
97
|
JSON.stringify(memory.tags),
|
|
88
98
|
project || null,
|
|
99
|
+
memory.memoryPurpose ?? 'project',
|
|
100
|
+
`hook:${sourceIdentifier}`,
|
|
89
101
|
timestamp,
|
|
90
102
|
timestamp,
|
|
91
103
|
);
|