shieldcortex 4.13.0 → 4.14.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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/pages/500.html +2 -2
- package/dist/cli/doctor.d.ts +16 -0
- package/dist/cli/doctor.js +329 -8
- package/dist/cli/migrate-legacy.d.ts +30 -0
- package/dist/cli/migrate-legacy.js +199 -0
- package/dist/cloud/config.d.ts +22 -0
- package/dist/cloud/config.js +38 -0
- package/dist/context/derive-project-key.d.ts +36 -0
- package/dist/context/derive-project-key.js +150 -0
- package/dist/context/project-context.d.ts +8 -5
- package/dist/context/project-context.js +16 -32
- package/dist/index.js +16 -1
- package/dist/setup/settings-hooks.d.ts +6 -0
- package/dist/setup/settings-hooks.js +37 -3
- package/dist/worker/brain-worker.d.ts +13 -5
- package/dist/worker/brain-worker.js +80 -40
- package/dist/worker/types.d.ts +19 -0
- package/dist/worker/types.js +7 -0
- package/package.json +1 -1
- package/plugins/openclaw/dist/openclaw.plugin.json +1 -1
- package/scripts/lib/auto-memory-config.mjs +22 -4
- package/scripts/lib/project-key.mjs +6 -0
- package/scripts/pre-compact-hook.mjs +2 -34
- package/scripts/session-end-hook.mjs +2 -24
- package/scripts/stop-hook.mjs +88 -44
- /package/dashboard/.next/standalone/dashboard/.next/static/{kiA_iEHG_1wWOEYFsD0Tj → wrB1TUcOfBtV94V2I9t9N}/_buildManifest.js +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{kiA_iEHG_1wWOEYFsD0Tj → wrB1TUcOfBtV94V2I9t9N}/_clientMiddlewareManifest.json +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{kiA_iEHG_1wWOEYFsD0Tj → wrB1TUcOfBtV94V2I9t9N}/_ssgManifest.js +0 -0
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* This transforms the memory system from reactive to continuously organic.
|
|
11
11
|
*/
|
|
12
|
-
import { DEFAULT_WORKER_CONFIG, } from './types.js';
|
|
12
|
+
import { DEFAULT_WORKER_CONFIG, MCP_LIGHT_TICK_INTERVAL_MS, } from './types.js';
|
|
13
13
|
import { getDatabase } from '../database/init.js';
|
|
14
14
|
import { pruneActivationCache } from '../memory/activation.js';
|
|
15
15
|
import { getMemoryStats } from '../memory/store.js';
|
|
@@ -22,6 +22,21 @@ import { processRetryQueue, purgeOldEntries } from '../cloud/sync-queue.js';
|
|
|
22
22
|
import { sendHeartbeat } from '../cloud/sync.js';
|
|
23
23
|
import { refreshCloudIronDome, applyCachedCloudPatterns } from '../cloud/iron-dome-sync.js';
|
|
24
24
|
import { isFeatureEnabled } from '../license/gate.js';
|
|
25
|
+
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
26
|
+
import { join } from 'path';
|
|
27
|
+
import { homedir } from 'os';
|
|
28
|
+
const WORKER_STATE_DIR = join(homedir(), '.shieldcortex', 'state');
|
|
29
|
+
const WORKER_STATE_FILE = join(WORKER_STATE_DIR, 'worker.json');
|
|
30
|
+
function persistWorkerState(profile, lastLightTick) {
|
|
31
|
+
try {
|
|
32
|
+
if (!existsSync(WORKER_STATE_DIR))
|
|
33
|
+
mkdirSync(WORKER_STATE_DIR, { recursive: true });
|
|
34
|
+
writeFileSync(WORKER_STATE_FILE, JSON.stringify({ pid: process.pid, profile, lastLightTick: lastLightTick.toISOString() }, null, 2), 'utf-8');
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// Best-effort: doctor will warn if the file is stale or missing
|
|
38
|
+
}
|
|
39
|
+
}
|
|
25
40
|
/**
|
|
26
41
|
* Brain Worker Class
|
|
27
42
|
*
|
|
@@ -47,10 +62,17 @@ export class BrainWorker {
|
|
|
47
62
|
/**
|
|
48
63
|
* Create a new BrainWorker
|
|
49
64
|
*
|
|
50
|
-
* @param config - Partial configuration to override defaults
|
|
65
|
+
* @param config - Partial configuration to override defaults. When `profile`
|
|
66
|
+
* is 'mcp' and no explicit `lightTickIntervalMs` is provided,
|
|
67
|
+
* the lite 15-minute cadence is applied so MCP-server-mode
|
|
68
|
+
* workers don't run as often as dashboard-mode ones.
|
|
51
69
|
*/
|
|
52
70
|
constructor(config = {}) {
|
|
53
|
-
|
|
71
|
+
const merged = { ...DEFAULT_WORKER_CONFIG, ...config };
|
|
72
|
+
if (merged.profile === 'mcp' && config.lightTickIntervalMs === undefined) {
|
|
73
|
+
merged.lightTickIntervalMs = MCP_LIGHT_TICK_INTERVAL_MS;
|
|
74
|
+
}
|
|
75
|
+
this.config = merged;
|
|
54
76
|
}
|
|
55
77
|
/**
|
|
56
78
|
* Start the background worker
|
|
@@ -62,17 +84,26 @@ export class BrainWorker {
|
|
|
62
84
|
return;
|
|
63
85
|
}
|
|
64
86
|
this.isRunning = true;
|
|
65
|
-
console.log(
|
|
87
|
+
console.log(`[BrainWorker] Starting background worker (profile=${this.config.profile} pid=${process.pid})`);
|
|
66
88
|
console.log(`[BrainWorker] Light tick interval: ${this.config.lightTickIntervalMs / 1000}s`);
|
|
67
|
-
|
|
68
|
-
|
|
89
|
+
if (this.config.profile === 'full') {
|
|
90
|
+
console.log(`[BrainWorker] Medium tick interval: ${this.config.mediumTickIntervalMs / 1000}s`);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
console.log('[BrainWorker] MCP profile — medium tick + cloud sync disabled');
|
|
94
|
+
}
|
|
95
|
+
// Light tick — every 5 min (full) or every 15 min (mcp)
|
|
69
96
|
this.lightTimer = setInterval(() => this.lightTick(), this.config.lightTickIntervalMs);
|
|
70
97
|
this.lightTimer.unref();
|
|
71
|
-
// Medium tick
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
98
|
+
// Medium tick — full profile only. mcp-mode skips link discovery,
|
|
99
|
+
// contradiction scans, graph maintenance, and sync-queue purging — those
|
|
100
|
+
// are dashboard concerns and shouldn't multiply across N MCP windows.
|
|
101
|
+
if (this.config.profile === 'full') {
|
|
102
|
+
this.mediumTimer = setInterval(() => this.mediumTick(), this.config.mediumTickIntervalMs);
|
|
103
|
+
this.mediumTimer.unref();
|
|
104
|
+
}
|
|
105
|
+
// Apply cached cloud Iron Dome patterns immediately on start (Pro+, full only)
|
|
106
|
+
if (this.config.profile === 'full' && isFeatureEnabled('custom_injection_patterns')) {
|
|
76
107
|
try {
|
|
77
108
|
applyCachedCloudPatterns();
|
|
78
109
|
}
|
|
@@ -150,38 +181,42 @@ export class BrainWorker {
|
|
|
150
181
|
result: result.predictiveConsolidation,
|
|
151
182
|
});
|
|
152
183
|
}
|
|
153
|
-
// 3
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
console.log(`[BrainWorker] Sync retry queue: processed ${retryResult.processed} ` +
|
|
158
|
-
`(${retryResult.succeeded} ok, ${retryResult.failed} retry, ${retryResult.permanentlyFailed} failed)`);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
catch (retryError) {
|
|
162
|
-
console.error('[BrainWorker] Sync retry queue failed:', retryError);
|
|
163
|
-
}
|
|
164
|
-
// 4. Send cloud heartbeat (keeps device status "Online") — Team+ only
|
|
165
|
-
if (isFeatureEnabled('cloud_sync')) {
|
|
184
|
+
// 3-5: cloud sync (retry queue, heartbeat, Iron Dome) — full profile only.
|
|
185
|
+
// Skipped under MCP profile so we don't fan out N concurrent network calls
|
|
186
|
+
// from N open Claude Code windows.
|
|
187
|
+
if (this.config.profile === 'full') {
|
|
166
188
|
try {
|
|
167
|
-
|
|
189
|
+
const retryResult = await processRetryQueue();
|
|
190
|
+
if (retryResult.processed > 0) {
|
|
191
|
+
console.log(`[BrainWorker] Sync retry queue: processed ${retryResult.processed} ` +
|
|
192
|
+
`(${retryResult.succeeded} ok, ${retryResult.failed} retry, ${retryResult.permanentlyFailed} failed)`);
|
|
193
|
+
}
|
|
168
194
|
}
|
|
169
|
-
catch {
|
|
170
|
-
|
|
195
|
+
catch (retryError) {
|
|
196
|
+
console.error('[BrainWorker] Sync retry queue failed:', retryError);
|
|
171
197
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
198
|
+
if (isFeatureEnabled('cloud_sync')) {
|
|
199
|
+
try {
|
|
200
|
+
sendHeartbeat();
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
// Truly silent — heartbeat is best-effort
|
|
204
|
+
}
|
|
177
205
|
}
|
|
178
|
-
|
|
179
|
-
|
|
206
|
+
if (isFeatureEnabled('custom_injection_patterns')) {
|
|
207
|
+
try {
|
|
208
|
+
await refreshCloudIronDome();
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
// Non-critical — cloud Iron Dome sync is best-effort
|
|
212
|
+
}
|
|
180
213
|
}
|
|
181
214
|
}
|
|
182
215
|
// Update stats
|
|
183
216
|
this.lastLightTick = result.timestamp;
|
|
184
217
|
this.stats.lightTicks++;
|
|
218
|
+
// Persist worker freshness for `shieldcortex doctor` to detect stalls.
|
|
219
|
+
persistWorkerState(this.config.profile, result.timestamp);
|
|
185
220
|
// Emit light tick event
|
|
186
221
|
emitWorkerLightTick(result);
|
|
187
222
|
// Log summary
|
|
@@ -314,19 +349,24 @@ export class BrainWorker {
|
|
|
314
349
|
// Default singleton instance (optional - server can create its own)
|
|
315
350
|
let defaultWorker = null;
|
|
316
351
|
/**
|
|
317
|
-
* Get or create the default worker instance
|
|
352
|
+
* Get or create the default worker instance.
|
|
353
|
+
* The first call wins — subsequent calls return the existing singleton even
|
|
354
|
+
* if a different config is passed. That's intentional: it prevents accidental
|
|
355
|
+
* re-instantiation from creating two competing timer sets within one process.
|
|
318
356
|
*/
|
|
319
|
-
export function getDefaultWorker() {
|
|
357
|
+
export function getDefaultWorker(config) {
|
|
320
358
|
if (!defaultWorker) {
|
|
321
|
-
defaultWorker = new BrainWorker();
|
|
359
|
+
defaultWorker = new BrainWorker(config);
|
|
322
360
|
}
|
|
323
361
|
return defaultWorker;
|
|
324
362
|
}
|
|
325
363
|
/**
|
|
326
|
-
* Start the default worker if not already running
|
|
364
|
+
* Start the default worker if not already running. Forwards config to the
|
|
365
|
+
* underlying constructor on first call (used by MCP-server mode to start
|
|
366
|
+
* with `profile: 'mcp'`).
|
|
327
367
|
*/
|
|
328
|
-
export function startDefaultWorker() {
|
|
329
|
-
const worker = getDefaultWorker();
|
|
368
|
+
export function startDefaultWorker(config) {
|
|
369
|
+
const worker = getDefaultWorker(config);
|
|
330
370
|
if (!worker.isActive()) {
|
|
331
371
|
worker.start();
|
|
332
372
|
}
|
package/dist/worker/types.d.ts
CHANGED
|
@@ -7,6 +7,17 @@
|
|
|
7
7
|
* for the background brain worker.
|
|
8
8
|
*/
|
|
9
9
|
import { ConsolidationResult } from '../memory/types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Worker profile.
|
|
12
|
+
* - 'full': dashboard / api / worker modes — runs medium tick, cloud sync,
|
|
13
|
+
* link discovery, the works.
|
|
14
|
+
* - 'mcp': default MCP-server mode (one process per Claude Code window) —
|
|
15
|
+
* keeps consolidation alive but skips heavy/networked work so we don't
|
|
16
|
+
* multiply background load by the number of open windows. Without this,
|
|
17
|
+
* hooks-only installs never run consolidation and STM never graduates
|
|
18
|
+
* to LTM (#45).
|
|
19
|
+
*/
|
|
20
|
+
export type WorkerProfile = 'full' | 'mcp';
|
|
10
21
|
/**
|
|
11
22
|
* Configuration for the brain worker
|
|
12
23
|
*/
|
|
@@ -27,11 +38,19 @@ export interface WorkerConfig {
|
|
|
27
38
|
contradictionScanLimit: number;
|
|
28
39
|
/** High activity threshold - memories created in 30 min (default: 5) */
|
|
29
40
|
highActivityThreshold: number;
|
|
41
|
+
/** Worker profile - 'full' (default) or 'mcp' (lite, see WorkerProfile docs) */
|
|
42
|
+
profile: WorkerProfile;
|
|
30
43
|
}
|
|
31
44
|
/**
|
|
32
45
|
* Default worker configuration
|
|
33
46
|
*/
|
|
34
47
|
export declare const DEFAULT_WORKER_CONFIG: WorkerConfig;
|
|
48
|
+
/**
|
|
49
|
+
* MCP-profile interval override. 15 min vs full's 5 min — one MCP server runs
|
|
50
|
+
* per Claude Code window, so we want lower per-window cadence to keep total
|
|
51
|
+
* background work in check across many windows.
|
|
52
|
+
*/
|
|
53
|
+
export declare const MCP_LIGHT_TICK_INTERVAL_MS: number;
|
|
35
54
|
/**
|
|
36
55
|
* Result of a light tick operation
|
|
37
56
|
*/
|
package/dist/worker/types.js
CHANGED
|
@@ -18,4 +18,11 @@ export const DEFAULT_WORKER_CONFIG = {
|
|
|
18
18
|
maxLinksPerCycle: 10,
|
|
19
19
|
contradictionScanLimit: 50,
|
|
20
20
|
highActivityThreshold: 5,
|
|
21
|
+
profile: 'full',
|
|
21
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* MCP-profile interval override. 15 min vs full's 5 min — one MCP server runs
|
|
25
|
+
* per Claude Code window, so we want lower per-window cadence to keep total
|
|
26
|
+
* background work in check across many windows.
|
|
27
|
+
*/
|
|
28
|
+
export const MCP_LIGHT_TICK_INTERVAL_MS = 15 * 60 * 1000;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shieldcortex",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.14.0",
|
|
4
4
|
"description": "Trustworthy memory and security for AI agents. Recall debugging, review queue, OpenClaw session capture, and memory poisoning defence for Claude Code, Codex, OpenClaw, LangChain, and MCP agents.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "shieldcortex-realtime",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.14.0",
|
|
4
4
|
"name": "ShieldCortex Real-time Scanner",
|
|
5
5
|
"description": "Real-time defence scanning on LLM input, memory extraction on LLM output, and active tool call interception with approval gating.",
|
|
6
6
|
"kind": null,
|
|
@@ -2,13 +2,27 @@ import { existsSync, readFileSync } from 'fs';
|
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { homedir } from 'os';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
function getConfigPath() {
|
|
6
|
+
// Honour the same SHIELDCORTEX_CONFIG_DIR override that src/cloud/config.ts
|
|
7
|
+
// uses, so the runtime gate and the rest of the system always resolve to the
|
|
8
|
+
// same config file (and so tests can isolate via a temp dir).
|
|
9
|
+
const override = process.env.SHIELDCORTEX_CONFIG_DIR?.trim();
|
|
10
|
+
const dir = override || join(homedir(), '.shieldcortex');
|
|
11
|
+
return join(dir, 'config.json');
|
|
12
|
+
}
|
|
6
13
|
|
|
7
14
|
const DEFAULTS = Object.freeze({
|
|
8
15
|
maxTranscriptBytes: 1024 * 1024,
|
|
9
16
|
maxTranscriptLines: 5000,
|
|
10
17
|
keepSlashCommandProse: true,
|
|
11
|
-
|
|
18
|
+
// Lowered 10 → 5 in v4.14.0. At 1-in-10 the realistic capture rate over
|
|
19
|
+
// typical sessions was ~7%, which left LTM near-empty (#44). Salience
|
|
20
|
+
// bypass below catches high-signal turns at any cadence.
|
|
21
|
+
stopHookSamplingTurns: 5,
|
|
22
|
+
// Bypass the modulo gate when the last assistant turn carries a fenced
|
|
23
|
+
// code block or hits multiple keyword categories — those turns are
|
|
24
|
+
// disproportionately what we want to remember.
|
|
25
|
+
stopHookSalienceBypass: true,
|
|
12
26
|
stopHookWindowBytes: 256 * 1024,
|
|
13
27
|
enableSessionEnd: false,
|
|
14
28
|
enableStop: false,
|
|
@@ -17,8 +31,9 @@ const DEFAULTS = Object.freeze({
|
|
|
17
31
|
export function getAutoMemoryConfig() {
|
|
18
32
|
let raw = {};
|
|
19
33
|
try {
|
|
20
|
-
|
|
21
|
-
|
|
34
|
+
const configPath = getConfigPath();
|
|
35
|
+
if (existsSync(configPath)) {
|
|
36
|
+
raw = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
22
37
|
}
|
|
23
38
|
} catch {
|
|
24
39
|
// fall through to defaults
|
|
@@ -31,6 +46,9 @@ export function getAutoMemoryConfig() {
|
|
|
31
46
|
? overrides.keepSlashCommandProse
|
|
32
47
|
: DEFAULTS.keepSlashCommandProse,
|
|
33
48
|
stopHookSamplingTurns: pickPositiveInt(overrides.stopHookSamplingTurns, DEFAULTS.stopHookSamplingTurns),
|
|
49
|
+
stopHookSalienceBypass: typeof overrides.stopHookSalienceBypass === 'boolean'
|
|
50
|
+
? overrides.stopHookSalienceBypass
|
|
51
|
+
: DEFAULTS.stopHookSalienceBypass,
|
|
34
52
|
stopHookWindowBytes: pickPositiveInt(overrides.stopHookWindowBytes, DEFAULTS.stopHookWindowBytes),
|
|
35
53
|
enableSessionEnd: overrides.enableSessionEnd === true,
|
|
36
54
|
enableStop: overrides.enableStop === true,
|
|
@@ -143,6 +143,12 @@ export function deriveProjectKey(cwd) {
|
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
// Hot path post-#42 fix: this branch should only fire outside any git repo
|
|
147
|
+
// or when origin parsing fails. If users see this often after upgrading,
|
|
148
|
+
// the helper itself needs another look.
|
|
149
|
+
if (process.env.SHIELDCORTEX_DEBUG) {
|
|
150
|
+
process.stderr.write(`[shieldcortex deriveProjectKey] basename fallback for cwd=${cwd}\n`);
|
|
151
|
+
}
|
|
146
152
|
return basename;
|
|
147
153
|
}
|
|
148
154
|
|
|
@@ -20,6 +20,7 @@ import { saveAutoExtractedMemory } from './lib/save-memory.mjs';
|
|
|
20
20
|
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
|
+
import { deriveProjectKey } from './lib/project-key.mjs';
|
|
23
24
|
|
|
24
25
|
// Database paths (with legacy fallback)
|
|
25
26
|
const NEW_DB_DIR = join(homedir(), '.shieldcortex');
|
|
@@ -62,39 +63,6 @@ const CATEGORY_EXTRACTION_THRESHOLDS = {
|
|
|
62
63
|
custom: 0.45,
|
|
63
64
|
};
|
|
64
65
|
|
|
65
|
-
// ==================== PROJECT DETECTION (Mirrors src/context/project-context.ts) ====================
|
|
66
|
-
|
|
67
|
-
/** Directories to skip when extracting project name from path */
|
|
68
|
-
const SKIP_DIRECTORIES = [
|
|
69
|
-
'src', 'lib', 'dist', 'build', 'out',
|
|
70
|
-
'node_modules', '.git', '.next', '.cache',
|
|
71
|
-
'test', 'tests', '__tests__', 'spec',
|
|
72
|
-
'bin', 'scripts', 'config', 'public', 'static',
|
|
73
|
-
];
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Extract project name from a file path.
|
|
77
|
-
* Skips common directory names that don't represent projects.
|
|
78
|
-
*/
|
|
79
|
-
function extractProjectFromPath(path) {
|
|
80
|
-
if (!path) return null;
|
|
81
|
-
|
|
82
|
-
const segments = path.split(/[/\\]/).filter(Boolean);
|
|
83
|
-
if (segments.length === 0) return null;
|
|
84
|
-
|
|
85
|
-
// Start from the end and find first non-skipped segment
|
|
86
|
-
for (let i = segments.length - 1; i >= 0; i--) {
|
|
87
|
-
const segment = segments[i];
|
|
88
|
-
if (!SKIP_DIRECTORIES.includes(segment.toLowerCase())) {
|
|
89
|
-
// Skip hidden directories (starting with .)
|
|
90
|
-
if (segment.startsWith('.')) continue;
|
|
91
|
-
return segment;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
66
|
// Maximum memories to auto-create per compaction.
|
|
99
67
|
// Dropped 5 → 2 in v4.11.0 for the same reason thresholds were raised.
|
|
100
68
|
const MAX_AUTO_MEMORIES = 2;
|
|
@@ -520,7 +488,7 @@ process.stdin.on('end', () => {
|
|
|
520
488
|
const hookData = JSON.parse(input || '{}');
|
|
521
489
|
|
|
522
490
|
const trigger = hookData.trigger || 'unknown';
|
|
523
|
-
const project =
|
|
491
|
+
const project = deriveProjectKey(hookData.cwd);
|
|
524
492
|
const autoMemConfig = getAutoMemoryConfig();
|
|
525
493
|
|
|
526
494
|
// Extract conversation text from hook data
|
|
@@ -29,6 +29,7 @@ import { saveAutoExtractedMemory } from './lib/save-memory.mjs';
|
|
|
29
29
|
import { readTranscriptText } from './lib/transcript-reader.mjs';
|
|
30
30
|
import { getAutoMemoryConfig } from './lib/auto-memory-config.mjs';
|
|
31
31
|
import { recordHookInvocation } from './lib/telemetry.mjs';
|
|
32
|
+
import { deriveProjectKey } from './lib/project-key.mjs';
|
|
32
33
|
|
|
33
34
|
// Database paths (with legacy fallback)
|
|
34
35
|
const NEW_DB_DIR = join(homedir(), '.shieldcortex');
|
|
@@ -64,29 +65,6 @@ const CATEGORY_EXTRACTION_THRESHOLDS = {
|
|
|
64
65
|
custom: 0.35,
|
|
65
66
|
};
|
|
66
67
|
|
|
67
|
-
// ==================== PROJECT DETECTION ====================
|
|
68
|
-
|
|
69
|
-
const SKIP_DIRECTORIES = [
|
|
70
|
-
'src', 'lib', 'dist', 'build', 'out',
|
|
71
|
-
'node_modules', '.git', '.next', '.cache',
|
|
72
|
-
'test', 'tests', '__tests__', 'spec',
|
|
73
|
-
'bin', 'scripts', 'config', 'public', 'static',
|
|
74
|
-
];
|
|
75
|
-
|
|
76
|
-
function extractProjectFromPath(path) {
|
|
77
|
-
if (!path) return null;
|
|
78
|
-
const segments = path.split(/[/\\]/).filter(Boolean);
|
|
79
|
-
if (segments.length === 0) return null;
|
|
80
|
-
for (let i = segments.length - 1; i >= 0; i--) {
|
|
81
|
-
const segment = segments[i];
|
|
82
|
-
if (!SKIP_DIRECTORIES.includes(segment.toLowerCase())) {
|
|
83
|
-
if (segment.startsWith('.')) continue;
|
|
84
|
-
return segment;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
68
|
// ==================== DYNAMIC THRESHOLD ====================
|
|
91
69
|
|
|
92
70
|
function getMemoryStats(db) {
|
|
@@ -442,7 +420,7 @@ process.stdin.on('end', () => {
|
|
|
442
420
|
const hookData = JSON.parse(input || '{}');
|
|
443
421
|
|
|
444
422
|
const reason = hookData.reason || 'unknown';
|
|
445
|
-
const project =
|
|
423
|
+
const project = deriveProjectKey(hookData.cwd);
|
|
446
424
|
const autoMemConfig = getAutoMemoryConfig();
|
|
447
425
|
|
|
448
426
|
// Config gate: opt-in (default off). Preserves the historical default
|
package/scripts/stop-hook.mjs
CHANGED
|
@@ -17,13 +17,43 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import Database from 'better-sqlite3';
|
|
20
|
-
import { existsSync, mkdirSync, openSync, readSync, closeSync, statSync } from 'fs';
|
|
20
|
+
import { existsSync, mkdirSync, openSync, readSync, closeSync, statSync, writeFileSync } from 'fs';
|
|
21
21
|
import { join } from 'path';
|
|
22
22
|
import { homedir } from 'os';
|
|
23
23
|
import { saveAutoExtractedMemory } from './lib/save-memory.mjs';
|
|
24
24
|
import { readTranscriptText } from './lib/transcript-reader.mjs';
|
|
25
25
|
import { getAutoMemoryConfig } from './lib/auto-memory-config.mjs';
|
|
26
26
|
import { recordHookInvocation } from './lib/telemetry.mjs';
|
|
27
|
+
import { deriveProjectKey } from './lib/project-key.mjs';
|
|
28
|
+
|
|
29
|
+
// Sentinel directory for once-per-session "disabled" log lines. Without this
|
|
30
|
+
// the stop hook bails silently on every turn when autoMemory.enableStop is
|
|
31
|
+
// false — the user-visible symptom is "ShieldCortex never captured anything"
|
|
32
|
+
// with zero feedback (filed in #41 as silent-amnesia). One sentinel file
|
|
33
|
+
// per session keeps the log to a single line for the lifetime of the session.
|
|
34
|
+
const SC_LOG_DIR = join(homedir(), '.shieldcortex', 'logs');
|
|
35
|
+
const STOP_DISABLED_SENTINEL_DIR = join(SC_LOG_DIR, 'stop-hook-disabled-sessions');
|
|
36
|
+
|
|
37
|
+
function logDisabledOnceForSession(sessionId, reason) {
|
|
38
|
+
// Always print the line — stderr is the existing channel for hook diagnostics
|
|
39
|
+
// (mirrors session-end-hook). Then plant a sentinel so subsequent fires in
|
|
40
|
+
// the same session stay quiet.
|
|
41
|
+
if (!sessionId) {
|
|
42
|
+
console.error(`[shieldcortex stop-hook] ${reason}`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
mkdirSync(STOP_DISABLED_SENTINEL_DIR, { recursive: true });
|
|
47
|
+
const sentinel = join(STOP_DISABLED_SENTINEL_DIR, sessionId.replace(/[^a-zA-Z0-9_.-]/g, '_'));
|
|
48
|
+
if (existsSync(sentinel)) return;
|
|
49
|
+
writeFileSync(sentinel, new Date().toISOString(), { mode: 0o600 });
|
|
50
|
+
console.error(`[shieldcortex stop-hook] ${reason}`);
|
|
51
|
+
} catch {
|
|
52
|
+
// Sentinel write failed — fall back to printing once per fire rather than
|
|
53
|
+
// staying silent. Better noisy-but-discoverable than silent-amnesia.
|
|
54
|
+
console.error(`[shieldcortex stop-hook] ${reason}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
27
57
|
|
|
28
58
|
// ==================== DB ====================
|
|
29
59
|
|
|
@@ -60,28 +90,6 @@ const CATEGORY_EXTRACTION_THRESHOLDS = {
|
|
|
60
90
|
custom: 0.45,
|
|
61
91
|
};
|
|
62
92
|
|
|
63
|
-
// ==================== PROJECT DETECTION ====================
|
|
64
|
-
|
|
65
|
-
const SKIP_DIRECTORIES = [
|
|
66
|
-
'src', 'lib', 'dist', 'build', 'out',
|
|
67
|
-
'node_modules', '.git', '.next', '.cache',
|
|
68
|
-
'test', 'tests', '__tests__', 'spec',
|
|
69
|
-
'bin', 'scripts', 'config', 'public', 'static',
|
|
70
|
-
];
|
|
71
|
-
|
|
72
|
-
function extractProjectFromPath(p) {
|
|
73
|
-
if (!p) return null;
|
|
74
|
-
const segments = p.split(/[/\\]/).filter(Boolean);
|
|
75
|
-
for (let i = segments.length - 1; i >= 0; i--) {
|
|
76
|
-
const segment = segments[i];
|
|
77
|
-
if (!SKIP_DIRECTORIES.includes(segment.toLowerCase())) {
|
|
78
|
-
if (segment.startsWith('.')) continue;
|
|
79
|
-
return segment;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
93
|
// ==================== SALIENCE (mirrors pre-compact) ====================
|
|
86
94
|
|
|
87
95
|
const ARCHITECTURE_KEYWORDS = ['architecture','design','pattern','structure','system','database','api','schema','model','framework','stack','microservice','monolith','serverless','infrastructure'];
|
|
@@ -244,18 +252,17 @@ function getDynamicThreshold(count, max) {
|
|
|
244
252
|
return 0.25;
|
|
245
253
|
}
|
|
246
254
|
|
|
247
|
-
// ====================
|
|
255
|
+
// ==================== TRANSCRIPT PEEK (cheap, partial-read) ====================
|
|
248
256
|
|
|
249
257
|
/**
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
* decisions and an order of magnitude cheaper than full JSON parse.
|
|
258
|
+
* Read the last `windowBytes` of the transcript as raw text and count
|
|
259
|
+
* assistant-role markers. Used for both the modulo sampling gate and the
|
|
260
|
+
* salience-bypass probe — one disk read serves both decisions.
|
|
254
261
|
*/
|
|
255
|
-
function
|
|
256
|
-
if (!transcriptPath) return 0;
|
|
262
|
+
function peekRecentTranscript(transcriptPath, windowBytes) {
|
|
263
|
+
if (!transcriptPath) return { turnCount: 0, raw: '' };
|
|
257
264
|
const resolved = transcriptPath.replace(/^~/, homedir());
|
|
258
|
-
if (!existsSync(resolved)) return 0;
|
|
265
|
+
if (!existsSync(resolved)) return { turnCount: 0, raw: '' };
|
|
259
266
|
try {
|
|
260
267
|
const stat = statSync(resolved);
|
|
261
268
|
const bytes = Math.min(stat.size, windowBytes);
|
|
@@ -268,14 +275,33 @@ function countAssistantTurns(transcriptPath, windowBytes) {
|
|
|
268
275
|
} finally {
|
|
269
276
|
closeSync(fd);
|
|
270
277
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
return (raw.match(/"role":"assistant"|"type":"assistant"/g) || []).length;
|
|
278
|
+
const turnCount = (raw.match(/"role":"assistant"|"type":"assistant"/g) || []).length;
|
|
279
|
+
return { turnCount, raw };
|
|
274
280
|
} catch {
|
|
275
|
-
return 0;
|
|
281
|
+
return { turnCount: 0, raw: '' };
|
|
276
282
|
}
|
|
277
283
|
}
|
|
278
284
|
|
|
285
|
+
/**
|
|
286
|
+
* Cheap salience probe over the recent transcript window. A turn is "salient"
|
|
287
|
+
* (and worth bypassing the modulo gate for) when:
|
|
288
|
+
* - it carries a fenced code block — strong signal of code work / errors / diffs
|
|
289
|
+
* - or ≥2 keyword categories hit (architecture, error, decision, learning,
|
|
290
|
+
* pattern, code-reference)
|
|
291
|
+
*/
|
|
292
|
+
function isSalientWindow(rawText) {
|
|
293
|
+
if (!rawText) return false;
|
|
294
|
+
if (/```/.test(rawText)) return true;
|
|
295
|
+
let hits = 0;
|
|
296
|
+
if (detectKeywords(rawText, ARCHITECTURE_KEYWORDS)) hits++;
|
|
297
|
+
if (detectKeywords(rawText, ERROR_KEYWORDS)) hits++;
|
|
298
|
+
if (detectKeywords(rawText, DECISION_KEYWORDS)) hits++;
|
|
299
|
+
if (detectKeywords(rawText, LEARNING_KEYWORDS)) hits++;
|
|
300
|
+
if (detectKeywords(rawText, PATTERN_KEYWORDS)) hits++;
|
|
301
|
+
if (detectCodeReferences(rawText)) hits++;
|
|
302
|
+
return hits >= 2;
|
|
303
|
+
}
|
|
304
|
+
|
|
279
305
|
// ==================== MAIN ====================
|
|
280
306
|
|
|
281
307
|
let input = '';
|
|
@@ -303,18 +329,35 @@ process.stdin.on('end', () => {
|
|
|
303
329
|
|
|
304
330
|
const autoMemConfig = getAutoMemoryConfig();
|
|
305
331
|
if (!autoMemConfig.enableStop) {
|
|
306
|
-
// Opt-in by config
|
|
307
|
-
//
|
|
332
|
+
// Opt-in by config. As of v4.13.1 the install flag (`--with-stop-hook`)
|
|
333
|
+
// flips this gate at install time so wiring the hook and enabling it are
|
|
334
|
+
// a single user action. If the gate is still false here, the user wired
|
|
335
|
+
// the hook by hand without setting autoMemory.enableStop=true. Log once
|
|
336
|
+
// per session so the failure is visible (was silent-amnesia in #41).
|
|
337
|
+
logDisabledOnceForSession(
|
|
338
|
+
hookData.session_id,
|
|
339
|
+
`disabled — set autoMemory.enableStop=true in ~/.shieldcortex/config.json (or re-run \`shieldcortex setup --with-stop-hook\`)`,
|
|
340
|
+
);
|
|
308
341
|
process.exit(0);
|
|
309
342
|
}
|
|
310
343
|
|
|
311
344
|
const samplingTurns = autoMemConfig.stopHookSamplingTurns;
|
|
312
345
|
const windowBytes = autoMemConfig.stopHookWindowBytes;
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
346
|
+
const salienceBypassEnabled = autoMemConfig.stopHookSalienceBypass;
|
|
347
|
+
|
|
348
|
+
// Use a smaller window for the cheap peek so off-sample turns stay fast.
|
|
349
|
+
// The full extraction below still uses the configured windowBytes.
|
|
350
|
+
const peekBytes = Math.min(32 * 1024, windowBytes);
|
|
351
|
+
const peek = peekRecentTranscript(hookData.transcript_path, peekBytes);
|
|
352
|
+
const turnCount = peek.turnCount;
|
|
353
|
+
const onSample = turnCount > 0 && turnCount % samplingTurns === 0;
|
|
354
|
+
const salientBypass = salienceBypassEnabled && !onSample && isSalientWindow(peek.raw);
|
|
355
|
+
|
|
356
|
+
if (!onSample && !salientBypass) {
|
|
357
|
+
// Off-sample, no salience bypass. Surface the sampling decision to stderr
|
|
358
|
+
// so the "1-in-N turns" behaviour stops being invisible (#41), and still
|
|
359
|
+
// record telemetry so the dashboard shows the hook is wired and active.
|
|
360
|
+
console.error(`[shieldcortex stop-hook] telemetry-only turn=${turnCount}/${samplingTurns}`);
|
|
318
361
|
if (existsSync(DB_PATH)) {
|
|
319
362
|
try {
|
|
320
363
|
const tdb = new Database(DB_PATH, { timeout: 1500 });
|
|
@@ -332,7 +375,7 @@ process.stdin.on('end', () => {
|
|
|
332
375
|
process.exit(0);
|
|
333
376
|
}
|
|
334
377
|
|
|
335
|
-
const project =
|
|
378
|
+
const project = deriveProjectKey(hookData.cwd);
|
|
336
379
|
const transcriptOut = readTranscriptText(hookData.transcript_path, {
|
|
337
380
|
maxBytes: windowBytes,
|
|
338
381
|
maxLines: autoMemConfig.maxTranscriptLines,
|
|
@@ -370,7 +413,8 @@ process.stdin.on('end', () => {
|
|
|
370
413
|
console.error(`[stop] Failed to save "${memory.title}": ${err.message}`);
|
|
371
414
|
}
|
|
372
415
|
}
|
|
373
|
-
|
|
416
|
+
const sampleReason = salientBypass ? `bypass=salience turn=${turnCount}` : `turn=${turnCount}`;
|
|
417
|
+
console.error(`[stop] Sampled ${sampleReason}: ${extractedCount} memories extracted`);
|
|
374
418
|
}
|
|
375
419
|
}
|
|
376
420
|
} catch (err) {
|
|
File without changes
|
|
File without changes
|