shieldcortex 4.15.0 → 4.16.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/README.md +4 -0
- 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/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/migrate-legacy.d.ts +18 -0
- package/dist/cli/migrate-legacy.js +96 -0
- package/dist/database/init.js +21 -0
- package/dist/database/schema.sql +1 -0
- package/dist/database/seed-firewall-rules.d.ts +21 -0
- package/dist/database/seed-firewall-rules.js +105 -0
- package/dist/defence/custom-rules/store.d.ts +4 -1
- package/dist/defence/custom-rules/store.js +7 -3
- package/dist/defence/firewall/instruction-detector.js +15 -0
- package/dist/defence/pipeline.js +19 -13
- package/dist/defence/types.d.ts +1 -1
- package/hooks/openclaw/cortex-memory/HOOK.md +37 -0
- package/package.json +1 -1
- package/plugins/openclaw/dist/openclaw.plugin.json +1 -1
- package/scripts/lib/extract-memorable-segments.mjs +555 -0
- package/scripts/lib/save-memory.mjs +198 -13
- package/scripts/pre-compact-hook.mjs +19 -375
- package/scripts/session-end-hook.mjs +16 -307
- package/scripts/stop-hook.mjs +28 -159
- /package/dashboard/.next/standalone/dashboard/.next/static/{10a_MRwbHFUuDdfr86RUu → 6WjF0Utj3STrFgg7vZVPK}/_buildManifest.js +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{10a_MRwbHFUuDdfr86RUu → 6WjF0Utj3STrFgg7vZVPK}/_clientMiddlewareManifest.json +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{10a_MRwbHFUuDdfr86RUu → 6WjF0Utj3STrFgg7vZVPK}/_ssgManifest.js +0 -0
|
@@ -1,27 +1,84 @@
|
|
|
1
1
|
import { randomUUID } from 'crypto';
|
|
2
|
+
import { dirname, resolve } from 'path';
|
|
3
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
|
-
* Insert an auto-extracted memory into the SC database
|
|
6
|
+
* Insert an auto-extracted memory into the SC database, routed through the
|
|
7
|
+
* full defence pipeline.
|
|
5
8
|
*
|
|
6
|
-
* Single source of truth for hook-side memory writes
|
|
7
|
-
* and
|
|
8
|
-
*
|
|
9
|
-
*
|
|
9
|
+
* Single source of truth for hook-side memory writes (session-end,
|
|
10
|
+
* pre-compact, and stop hooks all converge here). Every byte that lands in
|
|
11
|
+
* `memories` must have passed `runDefencePipeline()` first — that guarantees:
|
|
12
|
+
* - a defence_audit row exists for every capture (good or bad)
|
|
13
|
+
* - injection-shaped content lands in `quarantine`, not in `memories`
|
|
14
|
+
* - a hard BLOCK is dropped with an audit trail (no silent loss)
|
|
10
15
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
16
|
+
* If the pipeline cannot be loaded (no dist build, e.g. dev workspace before
|
|
17
|
+
* `npm run build`) the call is fail-closed: nothing is written to memories
|
|
18
|
+
* and a stderr warning is printed. A fallback defence_audit row is logged.
|
|
13
19
|
*
|
|
14
|
-
*
|
|
20
|
+
* Async: the pipeline lives in dist/ as ESM and is loaded via dynamic import.
|
|
21
|
+
*
|
|
22
|
+
* @param {import('better-sqlite3').Database} db
|
|
15
23
|
* @param {{ title: string, content: string, category: string, salience: number, tags: string[] }} memory
|
|
16
|
-
* @param {string|null} [project]
|
|
24
|
+
* @param {string|null} [project]
|
|
25
|
+
* @param {{ source?: string }} [opts] — `source` identifies the calling hook
|
|
26
|
+
* ('session-end-hook' | 'pre-compact-hook' | 'stop-hook' | 'hook').
|
|
17
27
|
*/
|
|
18
|
-
export function saveAutoExtractedMemory(db, memory, project) {
|
|
28
|
+
export async function saveAutoExtractedMemory(db, memory, project, opts = {}) {
|
|
29
|
+
const sourceIdentifier = opts.source ?? 'hook';
|
|
30
|
+
const source = { type: 'hook', identifier: sourceIdentifier };
|
|
31
|
+
|
|
32
|
+
const defence = await loadDefenceModules(db);
|
|
33
|
+
|
|
34
|
+
if (!defence) {
|
|
35
|
+
writeFallbackAudit(db, memory, project, sourceIdentifier, 'defence_pipeline_unavailable: dist build missing');
|
|
36
|
+
process.stderr.write(`[shieldcortex save-memory] dropped (defence pipeline unavailable): ${memory.title}\n`);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let result;
|
|
41
|
+
try {
|
|
42
|
+
result = defence.runDefencePipeline(memory.content, memory.title, source, undefined, project ?? undefined);
|
|
43
|
+
} catch (err) {
|
|
44
|
+
const msg = err && typeof err === 'object' && 'message' in err ? String(err.message) : String(err);
|
|
45
|
+
writeFallbackAudit(db, memory, project, sourceIdentifier, `pipeline_error: ${msg}`);
|
|
46
|
+
process.stderr.write(`[shieldcortex save-memory] dropped (pipeline error): ${memory.title} — ${msg}\n`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const decision = result.firewall.result;
|
|
51
|
+
|
|
52
|
+
if (decision === 'ALLOW') {
|
|
53
|
+
insertMemoryRow(db, memory, project);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (decision === 'QUARANTINE') {
|
|
58
|
+
// Route quarantine writes through the singleton's connection so the
|
|
59
|
+
// audit_id FK reference resolves against the same connection that
|
|
60
|
+
// wrote the audit row a few lines up in pipeline.ts.
|
|
61
|
+
const quarantineDb = (typeof _getDatabase === 'function' && defence.isDatabaseInitialized && defence.isDatabaseInitialized())
|
|
62
|
+
? _getDatabase()
|
|
63
|
+
: db;
|
|
64
|
+
insertQuarantineRow(quarantineDb, memory, project, source, result);
|
|
65
|
+
process.stderr.write(`[shieldcortex save-memory] quarantined: ${memory.title} — ${result.firewall.reason}\n`);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// BLOCK — defence_audit row already written by the pipeline. Drop with
|
|
70
|
+
// a single stderr line for operator visibility.
|
|
71
|
+
process.stderr.write(`[shieldcortex save-memory] blocked: ${memory.title} — ${result.firewall.reason}\n`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ==================== Internal: writes ====================
|
|
75
|
+
|
|
76
|
+
function insertMemoryRow(db, memory, project) {
|
|
19
77
|
const timestamp = new Date().toISOString();
|
|
20
|
-
|
|
78
|
+
db.prepare(`
|
|
21
79
|
INSERT INTO memories (uuid, title, content, type, category, salience, tags, project, created_at, last_accessed)
|
|
22
80
|
VALUES (?, ?, ?, 'short_term', ?, ?, ?, ?, ?, ?)
|
|
23
|
-
`)
|
|
24
|
-
stmt.run(
|
|
81
|
+
`).run(
|
|
25
82
|
randomUUID(),
|
|
26
83
|
memory.title,
|
|
27
84
|
memory.content,
|
|
@@ -33,3 +90,131 @@ export function saveAutoExtractedMemory(db, memory, project) {
|
|
|
33
90
|
timestamp,
|
|
34
91
|
);
|
|
35
92
|
}
|
|
93
|
+
|
|
94
|
+
function insertQuarantineRow(db, memory, project, source, result) {
|
|
95
|
+
// Mirrors the canonical SQL used by src/memory/store.ts:quarantineMemory
|
|
96
|
+
// so QUARANTINE decisions from any path produce schema-identical rows.
|
|
97
|
+
const firewallResult = result.firewall.result === 'ALLOW' ? 'BLOCK' : result.firewall.result;
|
|
98
|
+
db.prepare(`
|
|
99
|
+
INSERT INTO quarantine (
|
|
100
|
+
original_title, original_content, project,
|
|
101
|
+
source_type, source_identifier, reason,
|
|
102
|
+
threat_indicators, anomaly_score, firewall_result, audit_id, status
|
|
103
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending')
|
|
104
|
+
`).run(
|
|
105
|
+
memory.title,
|
|
106
|
+
memory.content,
|
|
107
|
+
project || null,
|
|
108
|
+
source.type,
|
|
109
|
+
source.identifier,
|
|
110
|
+
result.firewall.reason,
|
|
111
|
+
JSON.stringify(result.firewall.threatIndicators),
|
|
112
|
+
result.firewall.anomalyScore,
|
|
113
|
+
firewallResult,
|
|
114
|
+
result.auditId ?? null,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function writeFallbackAudit(db, memory, project, sourceIdentifier, reason) {
|
|
119
|
+
// Synthetic audit row for cases where the pipeline could not run.
|
|
120
|
+
try {
|
|
121
|
+
db.prepare(`
|
|
122
|
+
INSERT INTO defence_audit (
|
|
123
|
+
memory_id, project, timestamp,
|
|
124
|
+
source_type, source_identifier,
|
|
125
|
+
trust_score, sensitivity_level, firewall_result,
|
|
126
|
+
anomaly_score, threat_indicators, blocked_patterns,
|
|
127
|
+
reason, fragmentation_score, pipeline_duration_ms
|
|
128
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, 'BLOCK', ?, ?, ?, ?, ?, ?)
|
|
129
|
+
`).run(
|
|
130
|
+
null,
|
|
131
|
+
project || null,
|
|
132
|
+
new Date().toISOString(),
|
|
133
|
+
'hook',
|
|
134
|
+
sourceIdentifier,
|
|
135
|
+
0,
|
|
136
|
+
'INTERNAL',
|
|
137
|
+
0,
|
|
138
|
+
'[]',
|
|
139
|
+
'[]',
|
|
140
|
+
reason,
|
|
141
|
+
null,
|
|
142
|
+
0,
|
|
143
|
+
);
|
|
144
|
+
} catch {
|
|
145
|
+
// Schema may be older than the audit columns. Better silent here than
|
|
146
|
+
// raising into the hook — the stderr line above carries the signal.
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ==================== Internal: lazy dist loader ====================
|
|
151
|
+
|
|
152
|
+
let _defenceCache = null;
|
|
153
|
+
let _defenceCacheKey = null;
|
|
154
|
+
let _getDatabase = null;
|
|
155
|
+
|
|
156
|
+
async function loadDefenceModules(db) {
|
|
157
|
+
// Resolve the dist build relative to this file's location. save-memory.mjs
|
|
158
|
+
// lives at scripts/lib/, so dist is two directories up.
|
|
159
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
160
|
+
const distRoot = resolve(here, '..', '..', 'dist');
|
|
161
|
+
|
|
162
|
+
if (_defenceCache && _defenceCacheKey === distRoot) {
|
|
163
|
+
ensureDatabaseSingleton(db, _defenceCache);
|
|
164
|
+
return _defenceCache;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
const pipelineUrl = pathToFileURL(resolve(distRoot, 'defence', 'pipeline.js')).href;
|
|
169
|
+
const initUrl = pathToFileURL(resolve(distRoot, 'database', 'init.js')).href;
|
|
170
|
+
|
|
171
|
+
const [pipelineMod, initMod] = await Promise.all([
|
|
172
|
+
import(pipelineUrl),
|
|
173
|
+
import(initUrl),
|
|
174
|
+
]);
|
|
175
|
+
|
|
176
|
+
if (typeof pipelineMod.runDefencePipeline !== 'function') return null;
|
|
177
|
+
if (typeof initMod.initDatabase !== 'function') return null;
|
|
178
|
+
|
|
179
|
+
_defenceCache = {
|
|
180
|
+
runDefencePipeline: pipelineMod.runDefencePipeline,
|
|
181
|
+
initDatabase: initMod.initDatabase,
|
|
182
|
+
isDatabaseInitialized: initMod.isDatabaseInitialized,
|
|
183
|
+
getDatabase: initMod.getDatabase,
|
|
184
|
+
closeDatabase: initMod.closeDatabase,
|
|
185
|
+
};
|
|
186
|
+
_defenceCacheKey = distRoot;
|
|
187
|
+
_getDatabase = initMod.getDatabase;
|
|
188
|
+
|
|
189
|
+
ensureDatabaseSingleton(db, _defenceCache);
|
|
190
|
+
return _defenceCache;
|
|
191
|
+
} catch {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function ensureDatabaseSingleton(db, defence) {
|
|
197
|
+
// The pipeline's audit + custom-rules layers use getDatabase() (singleton).
|
|
198
|
+
// Initialise it against the same path the hook is writing to so audit
|
|
199
|
+
// rows are visible across connections (and to the dashboard).
|
|
200
|
+
const targetPath = db && db.name ? db.name : null;
|
|
201
|
+
if (!targetPath || targetPath === ':memory:') return;
|
|
202
|
+
|
|
203
|
+
if (defence.isDatabaseInitialized && defence.isDatabaseInitialized()) {
|
|
204
|
+
try {
|
|
205
|
+
const current = defence.getDatabase();
|
|
206
|
+
if (current && current.name === targetPath) return; // already pointed here
|
|
207
|
+
// Path mismatch (typical in tests using per-case temp DBs) — re-init.
|
|
208
|
+
if (defence.closeDatabase) defence.closeDatabase();
|
|
209
|
+
} catch {
|
|
210
|
+
// If anything throws, fall through and try to (re-)init.
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
try {
|
|
215
|
+
defence.initDatabase(targetPath);
|
|
216
|
+
} catch {
|
|
217
|
+
// Recoverable: pipeline.ts skips audit + custom-rules gracefully when
|
|
218
|
+
// the singleton isn't initialised.
|
|
219
|
+
}
|
|
220
|
+
}
|
|
@@ -21,6 +21,11 @@ import { readTranscriptText } from './lib/transcript-reader.mjs';
|
|
|
21
21
|
import { getAutoMemoryConfig } from './lib/auto-memory-config.mjs';
|
|
22
22
|
import { recordHookInvocation } from './lib/telemetry.mjs';
|
|
23
23
|
import { deriveProjectKey } from './lib/project-key.mjs';
|
|
24
|
+
import {
|
|
25
|
+
extractMemorableSegments,
|
|
26
|
+
processSegments,
|
|
27
|
+
PRE_COMPACT_CATEGORY_THRESHOLDS,
|
|
28
|
+
} from './lib/extract-memorable-segments.mjs';
|
|
24
29
|
|
|
25
30
|
// Database paths (with legacy fallback)
|
|
26
31
|
const NEW_DB_DIR = join(homedir(), '.shieldcortex');
|
|
@@ -42,31 +47,13 @@ const { dir: DB_DIR, path: DB_PATH } = getDbPath();
|
|
|
42
47
|
const MAX_SHORT_TERM_MEMORIES = 100;
|
|
43
48
|
const MAX_LONG_TERM_MEMORIES = 1000;
|
|
44
49
|
|
|
45
|
-
// Base salience threshold (will be adjusted dynamically)
|
|
46
|
-
// Lowered from 0.45 to capture more content
|
|
47
|
-
const BASE_THRESHOLD = 0.35;
|
|
48
|
-
|
|
49
|
-
// Category-specific extraction thresholds (lower = easier to extract).
|
|
50
|
-
// Raised +0.1 across the board in v4.11.0 after fleet evidence showed the
|
|
51
|
-
// previous permissive thresholds produced ~5% signal and flooded recall with
|
|
52
|
-
// noise. Prefer missing a marginal memory to saving a noisy one.
|
|
53
|
-
const CATEGORY_EXTRACTION_THRESHOLDS = {
|
|
54
|
-
architecture: 0.38,
|
|
55
|
-
error: 0.40,
|
|
56
|
-
context: 0.42,
|
|
57
|
-
learning: 0.42,
|
|
58
|
-
pattern: 0.45,
|
|
59
|
-
preference: 0.48,
|
|
60
|
-
note: 0.52,
|
|
61
|
-
todo: 0.50,
|
|
62
|
-
relationship: 0.45,
|
|
63
|
-
custom: 0.45,
|
|
64
|
-
};
|
|
65
|
-
|
|
66
50
|
// Maximum memories to auto-create per compaction.
|
|
67
51
|
// Dropped 5 → 2 in v4.11.0 for the same reason thresholds were raised.
|
|
68
52
|
const MAX_AUTO_MEMORIES = 2;
|
|
69
53
|
|
|
54
|
+
// Pre-compact uses tighter category thresholds (raised +0.10 in v4.11.0)
|
|
55
|
+
// — see PRE_COMPACT_CATEGORY_THRESHOLDS in scripts/lib/extract-memorable-segments.mjs.
|
|
56
|
+
|
|
70
57
|
// ==================== DYNAMIC THRESHOLD CALCULATION ====================
|
|
71
58
|
|
|
72
59
|
/**
|
|
@@ -103,357 +90,10 @@ function getDynamicThreshold(memoryCount, maxMemories) {
|
|
|
103
90
|
return 0.25; // Very sparse - accept most valuable items
|
|
104
91
|
}
|
|
105
92
|
|
|
106
|
-
|
|
107
|
-
* Get extraction threshold for a specific category
|
|
108
|
-
* Combines dynamic threshold with category-specific adjustments
|
|
109
|
-
*/
|
|
110
|
-
function getExtractionThreshold(category, dynamicThreshold) {
|
|
111
|
-
const categoryThreshold = CATEGORY_EXTRACTION_THRESHOLDS[category] || BASE_THRESHOLD;
|
|
112
|
-
// Use whichever is lower (more permissive for valuable categories when memory is sparse)
|
|
113
|
-
return Math.min(categoryThreshold, dynamicThreshold);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// ==================== SALIENCE DETECTION (Mirrors src/memory/salience.ts) ====================
|
|
117
|
-
|
|
118
|
-
const ARCHITECTURE_KEYWORDS = [
|
|
119
|
-
'architecture', 'design', 'pattern', 'structure', 'system',
|
|
120
|
-
'database', 'api', 'schema', 'model', 'framework', 'stack',
|
|
121
|
-
'microservice', 'monolith', 'serverless', 'infrastructure'
|
|
122
|
-
];
|
|
123
|
-
|
|
124
|
-
const ERROR_KEYWORDS = [
|
|
125
|
-
'error', 'bug', 'fix', 'issue', 'problem', 'crash', 'fail',
|
|
126
|
-
'exception', 'debug', 'resolve', 'solution', 'workaround'
|
|
127
|
-
];
|
|
128
|
-
|
|
129
|
-
const PREFERENCE_KEYWORDS = [
|
|
130
|
-
'prefer', 'always', 'never', 'style', 'convention', 'standard',
|
|
131
|
-
'like', 'want', 'should', 'must', 'require'
|
|
132
|
-
];
|
|
133
|
-
|
|
134
|
-
const PATTERN_KEYWORDS = [
|
|
135
|
-
'pattern', 'practice', 'approach', 'method', 'technique',
|
|
136
|
-
'implementation', 'strategy', 'algorithm', 'workflow'
|
|
137
|
-
];
|
|
138
|
-
|
|
139
|
-
const DECISION_KEYWORDS = [
|
|
140
|
-
'decided', 'decision', 'chose', 'chosen', 'selected', 'going with',
|
|
141
|
-
'will use', 'opted for', 'settled on', 'agreed'
|
|
142
|
-
];
|
|
143
|
-
|
|
144
|
-
const LEARNING_KEYWORDS = [
|
|
145
|
-
'learned', 'discovered', 'realized', 'found out', 'turns out',
|
|
146
|
-
'TIL', 'now know', 'understand now', 'figured out'
|
|
147
|
-
];
|
|
148
|
-
|
|
149
|
-
const EMOTIONAL_MARKERS = [
|
|
150
|
-
'important', 'critical', 'crucial', 'essential', 'key',
|
|
151
|
-
'finally', 'breakthrough', 'eureka', 'aha', 'got it',
|
|
152
|
-
'frustrating', 'annoying', 'tricky', 'remember'
|
|
153
|
-
];
|
|
154
|
-
|
|
155
|
-
const CODE_REFERENCE_PATTERNS = [
|
|
156
|
-
/\b[A-Z][a-zA-Z]*\.[a-zA-Z]+\b/,
|
|
157
|
-
/\b[a-z_][a-zA-Z0-9_]*\.(ts|js|py|go|rs)\b/,
|
|
158
|
-
/`[^`]+`/,
|
|
159
|
-
/\b(function|class|interface|type|const|let|var)\s+\w+/i,
|
|
160
|
-
/\bline\s*\d+\b/i,
|
|
161
|
-
/\b(src|lib|app|components?)\/\S+/,
|
|
162
|
-
];
|
|
163
|
-
|
|
164
|
-
function detectKeywords(text, keywords) {
|
|
165
|
-
const lower = text.toLowerCase();
|
|
166
|
-
return keywords.some(keyword => lower.includes(keyword.toLowerCase()));
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function detectCodeReferences(content) {
|
|
170
|
-
return CODE_REFERENCE_PATTERNS.some(pattern => pattern.test(content));
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function detectExplicitRequest(text) {
|
|
174
|
-
const patterns = [
|
|
175
|
-
/\bremember\s+(this|that)\b/i,
|
|
176
|
-
/\bdon'?t\s+forget\b/i,
|
|
177
|
-
/\bkeep\s+(in\s+)?mind\b/i,
|
|
178
|
-
/\bnote\s+(this|that)\b/i,
|
|
179
|
-
/\bsave\s+(this|that)\b/i,
|
|
180
|
-
/\bimportant[:\s]/i,
|
|
181
|
-
/\bfor\s+future\s+reference\b/i,
|
|
182
|
-
];
|
|
183
|
-
return patterns.some(pattern => pattern.test(text));
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function calculateSalience(text) {
|
|
187
|
-
let score = 0.25; // Base score
|
|
188
|
-
|
|
189
|
-
if (detectExplicitRequest(text)) score += 0.5;
|
|
190
|
-
if (detectKeywords(text, ARCHITECTURE_KEYWORDS)) score += 0.4;
|
|
191
|
-
if (detectKeywords(text, ERROR_KEYWORDS)) score += 0.35;
|
|
192
|
-
if (detectKeywords(text, DECISION_KEYWORDS)) score += 0.35;
|
|
193
|
-
if (detectKeywords(text, LEARNING_KEYWORDS)) score += 0.3;
|
|
194
|
-
if (detectKeywords(text, PATTERN_KEYWORDS)) score += 0.25;
|
|
195
|
-
if (detectKeywords(text, PREFERENCE_KEYWORDS)) score += 0.25;
|
|
196
|
-
if (detectCodeReferences(text)) score += 0.15;
|
|
197
|
-
if (detectKeywords(text, EMOTIONAL_MARKERS)) score += 0.2;
|
|
198
|
-
|
|
199
|
-
return Math.min(1.0, score);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
function suggestCategory(text) {
|
|
203
|
-
const lower = text.toLowerCase();
|
|
204
|
-
|
|
205
|
-
if (detectKeywords(lower, ARCHITECTURE_KEYWORDS)) return 'architecture';
|
|
206
|
-
if (detectKeywords(lower, ERROR_KEYWORDS)) return 'error';
|
|
207
|
-
if (detectKeywords(lower, DECISION_KEYWORDS)) return 'context';
|
|
208
|
-
if (detectKeywords(lower, LEARNING_KEYWORDS)) return 'learning';
|
|
209
|
-
if (detectKeywords(lower, PREFERENCE_KEYWORDS)) return 'preference';
|
|
210
|
-
if (detectKeywords(lower, PATTERN_KEYWORDS)) return 'pattern';
|
|
211
|
-
if (/\b(todo|fixme|hack|xxx)\b/i.test(lower)) return 'todo';
|
|
212
|
-
|
|
213
|
-
return 'note';
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function extractTags(text, extractorName = null) {
|
|
217
|
-
const tags = new Set();
|
|
218
|
-
|
|
219
|
-
// Extract hashtags
|
|
220
|
-
const hashtagMatches = text.match(/#[a-zA-Z][a-zA-Z0-9_-]*/g);
|
|
221
|
-
if (hashtagMatches) {
|
|
222
|
-
hashtagMatches.forEach(tag => tags.add(tag.slice(1).toLowerCase()));
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Extract common tech terms
|
|
226
|
-
const techTerms = [
|
|
227
|
-
'react', 'vue', 'angular', 'node', 'python', 'typescript', 'javascript',
|
|
228
|
-
'api', 'database', 'sql', 'mongodb', 'postgresql', 'mysql',
|
|
229
|
-
'docker', 'kubernetes', 'aws', 'git', 'testing', 'auth', 'security'
|
|
230
|
-
];
|
|
231
|
-
|
|
232
|
-
const lowerText = text.toLowerCase();
|
|
233
|
-
techTerms.forEach(term => {
|
|
234
|
-
if (lowerText.includes(term)) tags.add(term);
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
// Add auto-extracted tag
|
|
238
|
-
tags.add('auto-extracted');
|
|
239
|
-
|
|
240
|
-
// Add source extractor tag for tracking
|
|
241
|
-
if (extractorName) {
|
|
242
|
-
tags.add(`source:${extractorName}`);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
return Array.from(tags).slice(0, 12);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Calculate frequency boost based on how often key terms appear
|
|
250
|
-
* across all extracted segments. Repeated topics are more important.
|
|
251
|
-
*/
|
|
252
|
-
function calculateFrequencyBoost(segment, allSegments) {
|
|
253
|
-
// Extract key terms (words > 5 chars that aren't common)
|
|
254
|
-
const commonWords = new Set([
|
|
255
|
-
'about', 'after', 'before', 'being', 'between', 'could', 'during',
|
|
256
|
-
'every', 'found', 'through', 'would', 'should', 'which', 'where',
|
|
257
|
-
'there', 'these', 'their', 'other', 'using', 'because', 'without'
|
|
258
|
-
]);
|
|
259
|
-
|
|
260
|
-
const words = segment.content.toLowerCase().split(/\s+/);
|
|
261
|
-
const keyTerms = words.filter(w =>
|
|
262
|
-
w.length > 5 &&
|
|
263
|
-
!commonWords.has(w) &&
|
|
264
|
-
/^[a-z]+$/.test(w)
|
|
265
|
-
);
|
|
266
|
-
|
|
267
|
-
let boost = 0;
|
|
268
|
-
const seenTerms = new Set();
|
|
269
|
-
|
|
270
|
-
for (const term of keyTerms) {
|
|
271
|
-
if (seenTerms.has(term)) continue;
|
|
272
|
-
seenTerms.add(term);
|
|
273
|
-
|
|
274
|
-
// Count how many other segments mention this term
|
|
275
|
-
const mentions = allSegments.filter(s =>
|
|
276
|
-
s !== segment &&
|
|
277
|
-
s.content.toLowerCase().includes(term)
|
|
278
|
-
).length;
|
|
279
|
-
|
|
280
|
-
// Boost for repeated topics (cap at 5 mentions)
|
|
281
|
-
if (mentions > 1) {
|
|
282
|
-
boost += 0.03 * Math.min(mentions, 5);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// Cap total frequency boost at 0.15
|
|
287
|
-
return Math.min(0.15, boost);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// ==================== CONTENT EXTRACTION ====================
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* Extract meaningful segments from conversation text
|
|
294
|
-
* Looks for decisions, learnings, fixes, patterns, etc.
|
|
295
|
-
*/
|
|
296
|
-
function extractMemorableSegments(conversationText) {
|
|
297
|
-
const segments = [];
|
|
298
|
-
|
|
299
|
-
// Pattern matchers for different types of important content
|
|
300
|
-
// Expanded patterns with lower minimum lengths for better capture
|
|
301
|
-
const extractors = [
|
|
302
|
-
{
|
|
303
|
-
name: 'decision',
|
|
304
|
-
patterns: [
|
|
305
|
-
/(?:we\s+)?decided\s+(?:to\s+)?(.{15,200})/gi,
|
|
306
|
-
/(?:going|went)\s+with\s+(.{15,150})/gi,
|
|
307
|
-
/(?:chose|chosen|selected)\s+(.{15,150})/gi,
|
|
308
|
-
/the\s+(?:approach|solution|fix)\s+(?:is|was)\s+(.{15,200})/gi,
|
|
309
|
-
// New patterns
|
|
310
|
-
/(?:using|will\s+use)\s+(.{15,150})/gi,
|
|
311
|
-
/(?:opted\s+for|settled\s+on)\s+(.{15,150})/gi,
|
|
312
|
-
],
|
|
313
|
-
titlePrefix: 'Decision: ',
|
|
314
|
-
},
|
|
315
|
-
{
|
|
316
|
-
name: 'error-fix',
|
|
317
|
-
patterns: [
|
|
318
|
-
/(?:fixed|solved|resolved)\s+(?:by\s+)?(.{15,200})/gi,
|
|
319
|
-
/the\s+(?:fix|solution|workaround)\s+(?:is|was)\s+(.{15,200})/gi,
|
|
320
|
-
/(?:root\s+cause|issue)\s+(?:is|was)\s+(.{15,200})/gi,
|
|
321
|
-
/(?:error|bug)\s+(?:was\s+)?caused\s+by\s+(.{15,200})/gi,
|
|
322
|
-
// New patterns
|
|
323
|
-
/(?:problem|issue)\s+was\s+(.{15,150})/gi,
|
|
324
|
-
/(?:the\s+)?bug\s+(?:is|was)\s+(.{15,150})/gi,
|
|
325
|
-
/(?:debugging|debugged)\s+(.{15,150})/gi,
|
|
326
|
-
],
|
|
327
|
-
titlePrefix: 'Fix: ',
|
|
328
|
-
},
|
|
329
|
-
{
|
|
330
|
-
name: 'learning',
|
|
331
|
-
patterns: [
|
|
332
|
-
/(?:learned|discovered|realized|found\s+out)\s+(?:that\s+)?(.{15,200})/gi,
|
|
333
|
-
/turns\s+out\s+(?:that\s+)?(.{15,200})/gi,
|
|
334
|
-
/(?:TIL|today\s+I\s+learned)[:\s]+(.{15,200})/gi,
|
|
335
|
-
// New patterns
|
|
336
|
-
/(?:now\s+)?(?:understand|know)\s+(?:that\s+)?(.{15,150})/gi,
|
|
337
|
-
/(?:figured\s+out|worked\s+out)\s+(.{15,150})/gi,
|
|
338
|
-
],
|
|
339
|
-
titlePrefix: 'Learned: ',
|
|
340
|
-
},
|
|
341
|
-
{
|
|
342
|
-
name: 'architecture',
|
|
343
|
-
patterns: [
|
|
344
|
-
/the\s+architecture\s+(?:is|uses|consists\s+of)\s+(.{15,200})/gi,
|
|
345
|
-
/(?:design|pattern)\s+(?:is|uses)\s+(.{15,200})/gi,
|
|
346
|
-
/(?:system|api|database)\s+(?:structure|design)\s+(?:is|uses)\s+(.{15,200})/gi,
|
|
347
|
-
// New patterns
|
|
348
|
-
/(?:created|added|implemented|built)\s+(?:a\s+)?(.{15,200})/gi,
|
|
349
|
-
/(?:refactored|updated|changed)\s+(?:the\s+)?(.{15,150})/gi,
|
|
350
|
-
],
|
|
351
|
-
titlePrefix: 'Architecture: ',
|
|
352
|
-
},
|
|
353
|
-
{
|
|
354
|
-
name: 'preference',
|
|
355
|
-
patterns: [
|
|
356
|
-
/(?:always|never)\s+(.{10,150})/gi,
|
|
357
|
-
/(?:prefer|want)\s+to\s+(.{10,150})/gi,
|
|
358
|
-
/(?:should|must)\s+(?:always\s+)?(.{10,150})/gi,
|
|
359
|
-
],
|
|
360
|
-
titlePrefix: 'Preference: ',
|
|
361
|
-
},
|
|
362
|
-
{
|
|
363
|
-
name: 'important-note',
|
|
364
|
-
patterns: [
|
|
365
|
-
/important[:\s]+(.{15,200})/gi,
|
|
366
|
-
/(?:note|remember)[:\s]+(.{15,200})/gi,
|
|
367
|
-
/(?:key|critical)\s+(?:point|thing)[:\s]+(.{15,200})/gi,
|
|
368
|
-
// New patterns
|
|
369
|
-
/(?:this\s+is\s+)?(?:crucial|essential)[:\s]+(.{15,150})/gi,
|
|
370
|
-
/(?:don't\s+forget|keep\s+in\s+mind)[:\s]+(.{15,150})/gi,
|
|
371
|
-
],
|
|
372
|
-
titlePrefix: 'Note: ',
|
|
373
|
-
},
|
|
374
|
-
];
|
|
375
|
-
|
|
376
|
-
for (const extractor of extractors) {
|
|
377
|
-
for (const pattern of extractor.patterns) {
|
|
378
|
-
let match;
|
|
379
|
-
while ((match = pattern.exec(conversationText)) !== null) {
|
|
380
|
-
const content = match[1].trim();
|
|
381
|
-
if (content.length >= 20) {
|
|
382
|
-
// Generate a title from first ~50 chars
|
|
383
|
-
const titleContent = content.slice(0, 50).replace(/\s+/g, ' ').trim();
|
|
384
|
-
const title = extractor.titlePrefix + (titleContent.length < 50 ? titleContent : titleContent + '...');
|
|
385
|
-
|
|
386
|
-
segments.push({
|
|
387
|
-
title,
|
|
388
|
-
content: content.slice(0, 500), // Cap content length
|
|
389
|
-
extractorType: extractor.name,
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
return segments;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
/**
|
|
400
|
-
* Deduplicate and score segments
|
|
401
|
-
* @param {Array} segments - Raw extracted segments
|
|
402
|
-
* @param {number} dynamicThreshold - Dynamic threshold based on memory fullness
|
|
403
|
-
*/
|
|
404
|
-
function processSegments(segments, dynamicThreshold = BASE_THRESHOLD) {
|
|
405
|
-
// Remove near-duplicates (segments with >80% overlap)
|
|
406
|
-
const unique = [];
|
|
407
|
-
for (const seg of segments) {
|
|
408
|
-
const isDupe = unique.some(existing => {
|
|
409
|
-
const overlap = calculateOverlap(existing.content, seg.content);
|
|
410
|
-
return overlap > 0.8;
|
|
411
|
-
});
|
|
412
|
-
if (!isDupe) {
|
|
413
|
-
const text = seg.title + ' ' + seg.content;
|
|
414
|
-
const baseSalience = calculateSalience(text);
|
|
415
|
-
const category = suggestCategory(text);
|
|
416
|
-
|
|
417
|
-
unique.push({
|
|
418
|
-
...seg,
|
|
419
|
-
baseSalience,
|
|
420
|
-
category,
|
|
421
|
-
tags: extractTags(text, seg.extractorType),
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
}
|
|
93
|
+
// getExtractionThreshold lives in the shared chunker module.
|
|
425
94
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
const frequencyBoost = calculateFrequencyBoost(seg, unique);
|
|
429
|
-
seg.salience = Math.min(1.0, seg.baseSalience + frequencyBoost);
|
|
430
|
-
seg.frequencyBoost = frequencyBoost;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
// Sort by salience (highest first)
|
|
434
|
-
unique.sort((a, b) => b.salience - a.salience);
|
|
435
|
-
|
|
436
|
-
// Filter by category-specific threshold (combined with dynamic threshold)
|
|
437
|
-
const filtered = unique.filter(seg => {
|
|
438
|
-
const threshold = getExtractionThreshold(seg.category, dynamicThreshold);
|
|
439
|
-
return seg.salience >= threshold;
|
|
440
|
-
});
|
|
441
|
-
|
|
442
|
-
return filtered.slice(0, MAX_AUTO_MEMORIES);
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
/**
|
|
446
|
-
* Simple overlap calculation (Jaccard similarity on words)
|
|
447
|
-
*/
|
|
448
|
-
function calculateOverlap(text1, text2) {
|
|
449
|
-
const words1 = new Set(text1.toLowerCase().split(/\s+/));
|
|
450
|
-
const words2 = new Set(text2.toLowerCase().split(/\s+/));
|
|
451
|
-
|
|
452
|
-
const intersection = new Set([...words1].filter(w => words2.has(w)));
|
|
453
|
-
const union = new Set([...words1, ...words2]);
|
|
454
|
-
|
|
455
|
-
return intersection.size / union.size;
|
|
456
|
-
}
|
|
95
|
+
// Salience detection, content extraction, and segment processing now
|
|
96
|
+
// live in scripts/lib/extract-memorable-segments.mjs (imported above).
|
|
457
97
|
|
|
458
98
|
// ==================== DATABASE OPERATIONS ====================
|
|
459
99
|
|
|
@@ -461,7 +101,7 @@ function calculateOverlap(text1, text2) {
|
|
|
461
101
|
// write lives in scripts/lib/save-memory.mjs so pre-compact and
|
|
462
102
|
// session-end share one code path (and one regression test).
|
|
463
103
|
function saveMemory(db, memory, project) {
|
|
464
|
-
saveAutoExtractedMemory(db, memory, project);
|
|
104
|
+
return saveAutoExtractedMemory(db, memory, project, { source: 'pre-compact-hook' });
|
|
465
105
|
}
|
|
466
106
|
|
|
467
107
|
|
|
@@ -477,7 +117,7 @@ process.stdin.on('readable', () => {
|
|
|
477
117
|
}
|
|
478
118
|
});
|
|
479
119
|
|
|
480
|
-
process.stdin.on('end', () => {
|
|
120
|
+
process.stdin.on('end', async () => {
|
|
481
121
|
const startedAt = Date.now();
|
|
482
122
|
let db = null;
|
|
483
123
|
let autoExtractedCount = 0;
|
|
@@ -527,12 +167,16 @@ process.stdin.on('end', () => {
|
|
|
527
167
|
if (conversationText && conversationText.length > 100) {
|
|
528
168
|
// Extract memorable segments
|
|
529
169
|
const segments = extractMemorableSegments(conversationText);
|
|
530
|
-
const processedSegments = processSegments(segments, dynamicThreshold
|
|
170
|
+
const processedSegments = processSegments(segments, dynamicThreshold, {
|
|
171
|
+
maxMemories: MAX_AUTO_MEMORIES,
|
|
172
|
+
categoryThresholds: PRE_COMPACT_CATEGORY_THRESHOLDS,
|
|
173
|
+
conversationText,
|
|
174
|
+
});
|
|
531
175
|
|
|
532
176
|
// Save auto-extracted memories
|
|
533
177
|
for (const memory of processedSegments) {
|
|
534
178
|
try {
|
|
535
|
-
saveMemory(db, memory, project);
|
|
179
|
+
await saveMemory(db, memory, project);
|
|
536
180
|
autoExtractedCount++;
|
|
537
181
|
const boostInfo = memory.frequencyBoost > 0 ? ` +${memory.frequencyBoost.toFixed(2)} boost` : '';
|
|
538
182
|
console.error(`[auto-extract] Saved: ${memory.title} (salience: ${memory.salience.toFixed(2)}${boostInfo}, category: ${memory.category})`);
|