@remnic/core 9.15.3 → 9.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/dist/access-admin-ops-surface.d.ts +8 -8
- package/dist/access-admin-ops-surface.js +7 -7
- package/dist/access-boundary.d.ts +8 -8
- package/dist/access-boundary.js +7 -7
- package/dist/access-cli.js +31 -30
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +8 -8
- package/dist/access-http.js +11 -11
- package/dist/access-identity-continuity-surface.d.ts +6 -6
- package/dist/access-identity-continuity-surface.js +7 -7
- package/dist/access-lcm-surface.d.ts +8 -8
- package/dist/access-lcm-surface.js +7 -7
- package/dist/access-mcp.d.ts +8 -8
- package/dist/access-mcp.js +10 -10
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-B9e5GnyZ.d.ts → access-namespace-preflight-DwhEFYy3.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +7 -7
- package/dist/access-observe-write-surface.d.ts +8 -8
- package/dist/access-observe-write-surface.js +7 -7
- package/dist/access-operations-batch.js +8 -8
- package/dist/access-operations.d.ts +8 -8
- package/dist/access-operations.js +9 -9
- package/dist/access-recall-concurrency.d.ts +8 -8
- package/dist/access-recall-concurrency.js +7 -7
- package/dist/access-recall-response.d.ts +8 -8
- package/dist/access-recall-response.js +7 -7
- package/dist/access-recall-surface.d.ts +8 -8
- package/dist/access-recall-surface.js +7 -7
- package/dist/{access-service-DgmJd_A-.d.ts → access-service-CSq1Wp2Z.d.ts} +6 -6
- package/dist/access-service.d.ts +8 -8
- package/dist/access-service.js +7 -7
- package/dist/access-surface-catalog.d.ts +8 -8
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +2 -1
- package/dist/active-recall.js.map +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +6 -6
- package/dist/briefing.d.ts +2 -2
- package/dist/briefing.js +3 -3
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +2 -2
- package/dist/bulk-import/index.d.ts +3 -3
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{catalog-g_dfT6oL.d.ts → catalog-B9uga4sG.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +4 -4
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-IRX5UCGN.js → chunk-2OH3ZRYH.js} +3 -3
- package/dist/{chunk-YXTSUIXC.js → chunk-5EKOBRCA.js} +6 -1
- package/dist/chunk-5EKOBRCA.js.map +1 -0
- package/dist/{chunk-42DJZZUB.js → chunk-7LXSPIVG.js} +2 -2
- package/dist/{chunk-47WFEKT7.js → chunk-7PK4W4RN.js} +2 -2
- package/dist/{chunk-O7ACJAHR.js → chunk-7YJLCNPF.js} +2 -2
- package/dist/{chunk-6EJL2O3G.js → chunk-AFH7PIFU.js} +2 -2
- package/dist/{chunk-JN4N2TMQ.js → chunk-ANGUOE2N.js} +7 -7
- package/dist/{chunk-GQOKO77V.js → chunk-AWT7SCWQ.js} +2 -2
- package/dist/{chunk-PXJEL55X.js → chunk-BIRPR5N7.js} +2 -2
- package/dist/{chunk-NAY25BGS.js → chunk-BTK2PIFL.js} +6 -6
- package/dist/{chunk-SYCVU556.js → chunk-C2RMQRPN.js} +3 -3
- package/dist/{chunk-T4EAQPQQ.js → chunk-G2WCVFDC.js} +2 -2
- package/dist/{chunk-UJIBXOJA.js → chunk-GEDBTSYU.js} +5 -5
- package/dist/{chunk-CXFVZ3PK.js → chunk-GRJ5UOFO.js} +84 -658
- package/dist/chunk-GRJ5UOFO.js.map +1 -0
- package/dist/chunk-GSQASASV.js +429 -0
- package/dist/chunk-GSQASASV.js.map +1 -0
- package/dist/{chunk-WIKOHCQZ.js → chunk-I6ODVWQB.js} +2 -2
- package/dist/{chunk-H4MDUPER.js → chunk-IZHXSLO7.js} +2 -2
- package/dist/{chunk-RRS5CDB6.js → chunk-JOCXI2O5.js} +2 -2
- package/dist/{chunk-EEUZQQRJ.js → chunk-KGKYTCDO.js} +2 -2
- package/dist/{chunk-JTW4TGPV.js → chunk-L3HAUO7K.js} +2 -2
- package/dist/{chunk-P53HGVJS.js → chunk-LMVAIZR5.js} +2 -2
- package/dist/{chunk-KLXG4BBO.js → chunk-M6TZQDTX.js} +2 -2
- package/dist/{chunk-FJ5IQ3SI.js → chunk-N7DK67GZ.js} +1 -1
- package/dist/chunk-N7DK67GZ.js.map +1 -0
- package/dist/{chunk-U6QWUFSM.js → chunk-OXT5TQDS.js} +2 -2
- package/dist/{chunk-T4OTDMX4.js → chunk-QDTEH6BS.js} +2 -2
- package/dist/{chunk-5MDE5MIC.js → chunk-SESF64QR.js} +2 -2
- package/dist/{chunk-4E5H4FPC.js → chunk-TUNI4GB3.js} +3 -3
- package/dist/{chunk-XJT6LNLY.js → chunk-V6LYAXGW.js} +834 -25
- package/dist/chunk-V6LYAXGW.js.map +1 -0
- package/dist/{chunk-5HFIHWOF.js → chunk-VLIY55Q5.js} +17 -17
- package/dist/{chunk-BNH2VVWP.js → chunk-WIS5JTJR.js} +2 -2
- package/dist/{chunk-OOGGUXAG.js → chunk-WQ2I6ODB.js} +2 -2
- package/dist/{cli-BXCd2cgK.d.ts → cli-DYLGXxuu.d.ts} +5 -5
- package/dist/cli.d.ts +10 -10
- package/dist/cli.js +25 -24
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +3 -3
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +2 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +3 -3
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +3 -3
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/contradiction/index.d.ts +2 -2
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +2 -2
- package/dist/entity-retrieval.js +3 -3
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +6 -6
- package/dist/extraction-faithfulness.d.ts +1 -1
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/graph-dashboard-diff.d.ts +1 -1
- package/dist/graph-dashboard-key.d.ts +1 -1
- package/dist/graph-dashboard-parser.d.ts +1 -1
- package/dist/graph-edge-reinforcement.d.ts +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/importers/index.d.ts +1 -1
- package/dist/in-flight-reads.d.ts +1 -1
- package/dist/index.d.ts +289 -99
- package/dist/index.js +70 -45
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +3 -3
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
- package/dist/maintenance/rebuild-memory-projection.js +4 -4
- package/dist/mcp-memory-inspector-app.d.ts +8 -8
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +2 -2
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +3 -3
- package/dist/namespaces/migrate.js +4 -4
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +3 -3
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/offline-sync-impression-drain.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +2 -2
- package/dist/operator-toolkit.js +9 -8
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +10 -7
- package/dist/orchestration/maintenance.js +7 -6
- package/dist/{orchestrator-BHfWtvEJ.d.ts → orchestrator-BHx-DWCa.d.ts} +7 -5
- package/dist/orchestrator.d.ts +6 -6
- package/dist/orchestrator.js +31 -30
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-CBYcnmDC.d.ts → pipeline-DDHSE876.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/proactive-contention.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/{qmd-BIq-jrV4.d.ts → qmd-C4WVh6BM.d.ts} +1 -1
- package/dist/qmd-preflight.d.ts +2 -2
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +2 -2
- package/dist/recall-concurrency-config.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-memory-map.d.ts +1 -1
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-timings.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- package/dist/replay/normalizers/chatgpt.d.ts +1 -1
- package/dist/replay/normalizers/claude.d.ts +1 -1
- package/dist/replay/normalizers/openclaw.d.ts +1 -1
- package/dist/replay/normalizers/shared.d.ts +1 -1
- package/dist/replay/runner.d.ts +1 -1
- package/dist/replay/types.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +3 -2
- package/dist/retrieval-agents.d.ts +2 -2
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/salvage-envelope.d.ts +1 -1
- package/dist/{scope-profiles-DDno-uvy.d.ts → scope-profiles-EqMXwzCz.d.ts} +1 -1
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/index.d.ts +1 -1
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-7RIJFDwY.d.ts → semantic-consolidation-CYpvwmQc.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +4 -4
- package/dist/semantic-rule-promotion.js +3 -3
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +3 -3
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/{storage-DkphZiOJ.d.ts → storage-Dxd7zVZH.d.ts} +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +2 -2
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +2 -2
- package/dist/temporal-timeline-recall.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +2 -2
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-2q_MRFcM.d.ts → types-OUCJALBK.d.ts} +98 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +3 -3
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +2 -2
- package/src/activity/config.test.ts +113 -0
- package/src/activity/config.ts +111 -0
- package/src/activity/digest.ts +2 -2
- package/src/activity/index.ts +6 -0
- package/src/activity/pipeline.test.ts +379 -0
- package/src/activity/pipeline.ts +223 -0
- package/src/activity/reindex.test.ts +97 -0
- package/src/activity/reindex.ts +40 -0
- package/src/activity/runner.test.ts +452 -0
- package/src/activity/runner.ts +237 -0
- package/src/activity/scheduler.test.ts +303 -0
- package/src/activity/scheduler.ts +147 -0
- package/src/activity/source-client.test.ts +208 -0
- package/src/activity/source-client.ts +159 -0
- package/src/activity/sync-registration.test.ts +134 -0
- package/src/activity/sync-registration.ts +139 -0
- package/src/activity/types.ts +17 -0
- package/src/config.test.ts +19 -0
- package/src/config.ts +3 -0
- package/src/orchestration/maintenance.test.ts +42 -42
- package/src/orchestration/maintenance.ts +37 -5
- package/src/orchestration/orchestrator-helpers.ts +36 -1
- package/src/orchestration/recall-internal.ts +6 -6
- package/src/orchestration/recall-search-pipeline.ts +15 -7
- package/src/orchestrator-background-writes.test.ts +2 -2
- package/src/orchestrator.ts +3 -3
- package/src/types.ts +4 -1
- package/dist/chunk-CXFVZ3PK.js.map +0 -1
- package/dist/chunk-FJ5IQ3SI.js.map +0 -1
- package/dist/chunk-XJT6LNLY.js.map +0 -1
- package/dist/chunk-YXTSUIXC.js.map +0 -1
- /package/dist/{chunk-IRX5UCGN.js.map → chunk-2OH3ZRYH.js.map} +0 -0
- /package/dist/{chunk-42DJZZUB.js.map → chunk-7LXSPIVG.js.map} +0 -0
- /package/dist/{chunk-47WFEKT7.js.map → chunk-7PK4W4RN.js.map} +0 -0
- /package/dist/{chunk-O7ACJAHR.js.map → chunk-7YJLCNPF.js.map} +0 -0
- /package/dist/{chunk-6EJL2O3G.js.map → chunk-AFH7PIFU.js.map} +0 -0
- /package/dist/{chunk-JN4N2TMQ.js.map → chunk-ANGUOE2N.js.map} +0 -0
- /package/dist/{chunk-GQOKO77V.js.map → chunk-AWT7SCWQ.js.map} +0 -0
- /package/dist/{chunk-PXJEL55X.js.map → chunk-BIRPR5N7.js.map} +0 -0
- /package/dist/{chunk-NAY25BGS.js.map → chunk-BTK2PIFL.js.map} +0 -0
- /package/dist/{chunk-SYCVU556.js.map → chunk-C2RMQRPN.js.map} +0 -0
- /package/dist/{chunk-T4EAQPQQ.js.map → chunk-G2WCVFDC.js.map} +0 -0
- /package/dist/{chunk-UJIBXOJA.js.map → chunk-GEDBTSYU.js.map} +0 -0
- /package/dist/{chunk-WIKOHCQZ.js.map → chunk-I6ODVWQB.js.map} +0 -0
- /package/dist/{chunk-H4MDUPER.js.map → chunk-IZHXSLO7.js.map} +0 -0
- /package/dist/{chunk-RRS5CDB6.js.map → chunk-JOCXI2O5.js.map} +0 -0
- /package/dist/{chunk-EEUZQQRJ.js.map → chunk-KGKYTCDO.js.map} +0 -0
- /package/dist/{chunk-JTW4TGPV.js.map → chunk-L3HAUO7K.js.map} +0 -0
- /package/dist/{chunk-P53HGVJS.js.map → chunk-LMVAIZR5.js.map} +0 -0
- /package/dist/{chunk-KLXG4BBO.js.map → chunk-M6TZQDTX.js.map} +0 -0
- /package/dist/{chunk-U6QWUFSM.js.map → chunk-OXT5TQDS.js.map} +0 -0
- /package/dist/{chunk-T4OTDMX4.js.map → chunk-QDTEH6BS.js.map} +0 -0
- /package/dist/{chunk-5MDE5MIC.js.map → chunk-SESF64QR.js.map} +0 -0
- /package/dist/{chunk-4E5H4FPC.js.map → chunk-TUNI4GB3.js.map} +0 -0
- /package/dist/{chunk-5HFIHWOF.js.map → chunk-VLIY55Q5.js.map} +0 -0
- /package/dist/{chunk-BNH2VVWP.js.map → chunk-WIS5JTJR.js.map} +0 -0
- /package/dist/{chunk-OOGGUXAG.js.map → chunk-WQ2I6ODB.js.map} +0 -0
package/src/config.ts
CHANGED
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
resolveNamespaceCatalogEnabled,
|
|
52
52
|
} from "./emit-legacy-tools.js";
|
|
53
53
|
import { parseWearablesConfig } from "./wearables/config.js";
|
|
54
|
+
import { parseActivityConfig } from "./activity/config.js";
|
|
54
55
|
import { parseProvenanceConfig } from "./provenance.js";
|
|
55
56
|
import { parseBoundedJsonlStateConfig } from "./bounded-jsonl-state.js";
|
|
56
57
|
import { parseCodingKnowledgeConfig } from "./coding/coding-knowledge-config.js";
|
|
@@ -1172,6 +1173,7 @@ export function parseConfig(
|
|
|
1172
1173
|
|
|
1173
1174
|
// Wearable transcript ingestion (Limitless / Bee / Omi) — delegated to the wearables module.
|
|
1174
1175
|
const wearables = parseWearablesConfig(cfg.wearables);
|
|
1176
|
+
const activity = parseActivityConfig(cfg.activity);
|
|
1175
1177
|
|
|
1176
1178
|
const provenance = parseProvenanceConfig(cfg.provenance);
|
|
1177
1179
|
// Coding-agent project/branch scoping (issue #569)
|
|
@@ -2335,6 +2337,7 @@ export function parseConfig(
|
|
|
2335
2337
|
dreamsPhases,
|
|
2336
2338
|
procedural,
|
|
2337
2339
|
wearables,
|
|
2340
|
+
activity,
|
|
2338
2341
|
provenance,
|
|
2339
2342
|
// At-rest encryption (issue #690 PR 3/4)
|
|
2340
2343
|
// coerceBool handles CLI string inputs: `--config secureStoreEnabled=true`
|
|
@@ -162,7 +162,7 @@ test("runQmdMaintenance updates and embeds cataloged dynamic namespaces (NGnei)"
|
|
|
162
162
|
assert.equal(embedCalls.length, 1, "QMD embed must batch all selected namespaces into one router call");
|
|
163
163
|
assert.deepEqual(new Set(embedCalls[0]), new Set(["default", "shared", dynamicNamespace]));
|
|
164
164
|
} finally {
|
|
165
|
-
scheduler.dispose();
|
|
165
|
+
await scheduler.dispose();
|
|
166
166
|
await rm(memoryDir, { recursive: true, force: true });
|
|
167
167
|
}
|
|
168
168
|
});
|
|
@@ -218,7 +218,7 @@ test("runQmdMaintenance tracks namespace embed cadence across budget rotation",
|
|
|
218
218
|
"a global embed timestamp must not suppress embeddings for newly budgeted namespaces",
|
|
219
219
|
);
|
|
220
220
|
} finally {
|
|
221
|
-
scheduler.dispose();
|
|
221
|
+
await scheduler.dispose();
|
|
222
222
|
await rm(memoryDir, { recursive: true, force: true });
|
|
223
223
|
}
|
|
224
224
|
});
|
|
@@ -285,7 +285,7 @@ test("runQmdMaintenance skips cataloged dynamic namespaces whose live root is un
|
|
|
285
285
|
"cataloged dynamic namespaces are skipped when the live router root differs from the catalog-sanitized root",
|
|
286
286
|
);
|
|
287
287
|
} finally {
|
|
288
|
-
scheduler.dispose();
|
|
288
|
+
await scheduler.dispose();
|
|
289
289
|
await rm(memoryDir, { recursive: true, force: true });
|
|
290
290
|
await rm(outsideDir, { recursive: true, force: true });
|
|
291
291
|
}
|
|
@@ -337,7 +337,7 @@ test("runQmdMaintenance treats zero namespace updates as failed maintenance", as
|
|
|
337
337
|
assert.equal(markMaintenanceCalls, 0);
|
|
338
338
|
assert.equal(embedCalls, 0);
|
|
339
339
|
} finally {
|
|
340
|
-
scheduler.dispose();
|
|
340
|
+
await scheduler.dispose();
|
|
341
341
|
await rm(memoryDir, { recursive: true, force: true });
|
|
342
342
|
}
|
|
343
343
|
});
|
|
@@ -393,7 +393,7 @@ test("runQmdMaintenance treats partial namespace update eligibility as failed ma
|
|
|
393
393
|
assert.equal(markMaintenanceCalls, 0);
|
|
394
394
|
assert.equal(embedCalls, 0);
|
|
395
395
|
} finally {
|
|
396
|
-
scheduler.dispose();
|
|
396
|
+
await scheduler.dispose();
|
|
397
397
|
await rm(memoryDir, { recursive: true, force: true });
|
|
398
398
|
}
|
|
399
399
|
});
|
|
@@ -442,7 +442,7 @@ test("runQmdMaintenance treats namespace embed errors as failed maintenance", as
|
|
|
442
442
|
);
|
|
443
443
|
assert.equal(markMaintenanceCalls, 0);
|
|
444
444
|
} finally {
|
|
445
|
-
scheduler.dispose();
|
|
445
|
+
await scheduler.dispose();
|
|
446
446
|
await rm(memoryDir, { recursive: true, force: true });
|
|
447
447
|
}
|
|
448
448
|
});
|
|
@@ -515,7 +515,7 @@ test("runQmdMaintenance records QMD min-interval throttles as skipped maintenanc
|
|
|
515
515
|
assert.equal(markMaintenanceCalls, 0);
|
|
516
516
|
assert.equal(embedCalls, 0);
|
|
517
517
|
} finally {
|
|
518
|
-
scheduler.dispose();
|
|
518
|
+
await scheduler.dispose();
|
|
519
519
|
await rm(memoryDir, { recursive: true, force: true });
|
|
520
520
|
}
|
|
521
521
|
});
|
|
@@ -578,7 +578,7 @@ test("runQmdMaintenance still embeds when due update is throttled", async () =>
|
|
|
578
578
|
);
|
|
579
579
|
assert.equal(markMaintenanceCalls, 0);
|
|
580
580
|
} finally {
|
|
581
|
-
scheduler.dispose();
|
|
581
|
+
await scheduler.dispose();
|
|
582
582
|
await rm(memoryDir, { recursive: true, force: true });
|
|
583
583
|
}
|
|
584
584
|
});
|
|
@@ -637,7 +637,7 @@ test("runQmdMaintenance treats strict namespace update errors as failed maintena
|
|
|
637
637
|
assert.equal(markMaintenanceCalls, 0);
|
|
638
638
|
assert.equal(embedCalls, 0);
|
|
639
639
|
} finally {
|
|
640
|
-
scheduler.dispose();
|
|
640
|
+
await scheduler.dispose();
|
|
641
641
|
await rm(memoryDir, { recursive: true, force: true });
|
|
642
642
|
}
|
|
643
643
|
});
|
|
@@ -682,7 +682,7 @@ test("runQmdMaintenance falls back to configured namespaces when the catalog is
|
|
|
682
682
|
"a disabled catalog covers exactly the configured set",
|
|
683
683
|
);
|
|
684
684
|
} finally {
|
|
685
|
-
scheduler.dispose();
|
|
685
|
+
await scheduler.dispose();
|
|
686
686
|
await rm(memoryDir, { recursive: true, force: true });
|
|
687
687
|
}
|
|
688
688
|
});
|
|
@@ -747,7 +747,7 @@ test("MaintenanceScheduler reads a runtime-swapped qmd backend via getQmd (regre
|
|
|
747
747
|
"after the swap to NoopSearchBackend, requestQmdMaintenance must short-circuit (isAvailable===false) and never touch the disposed backend",
|
|
748
748
|
);
|
|
749
749
|
} finally {
|
|
750
|
-
scheduler.dispose();
|
|
750
|
+
await scheduler.dispose();
|
|
751
751
|
}
|
|
752
752
|
});
|
|
753
753
|
|
|
@@ -825,7 +825,7 @@ test("auto-compaction shrinks an oversized ledger and writes a verbatim backup",
|
|
|
825
825
|
try {
|
|
826
826
|
await scheduler.maybeCompactMemoryLifecycleLedger();
|
|
827
827
|
} finally {
|
|
828
|
-
scheduler.dispose();
|
|
828
|
+
await scheduler.dispose();
|
|
829
829
|
}
|
|
830
830
|
|
|
831
831
|
const afterSize = (await stat(ledgerPath)).size;
|
|
@@ -897,7 +897,7 @@ alpha
|
|
|
897
897
|
try {
|
|
898
898
|
await scheduler.maybeCompactMemoryLifecycleLedger();
|
|
899
899
|
} finally {
|
|
900
|
-
scheduler.dispose();
|
|
900
|
+
await scheduler.dispose();
|
|
901
901
|
}
|
|
902
902
|
|
|
903
903
|
const rebuilt = (await readFile(ledgerPath, "utf-8"))
|
|
@@ -934,7 +934,7 @@ test("auto-compaction is disabled when memoryLifecycleLedgerCompactBytes is 0",
|
|
|
934
934
|
try {
|
|
935
935
|
await scheduler.maybeCompactMemoryLifecycleLedger();
|
|
936
936
|
} finally {
|
|
937
|
-
scheduler.dispose();
|
|
937
|
+
await scheduler.dispose();
|
|
938
938
|
}
|
|
939
939
|
assert.equal(await readFile(ledgerPath, "utf-8"), before, "disabled: ledger untouched");
|
|
940
940
|
await assert.rejects(() => readdir(path.join(memoryDir, "archive", "memory-lifecycle-ledger")));
|
|
@@ -967,7 +967,7 @@ test("auto-compaction min-interval throttle prevents a second run within the win
|
|
|
967
967
|
assert.equal((await stat(ledgerPath)).size, regrownSize, "throttled: ledger not recompacted");
|
|
968
968
|
assert.ok(regrownSize > compactedSize);
|
|
969
969
|
} finally {
|
|
970
|
-
scheduler.dispose();
|
|
970
|
+
await scheduler.dispose();
|
|
971
971
|
}
|
|
972
972
|
} finally {
|
|
973
973
|
await rm(memoryDir, { recursive: true, force: true });
|
|
@@ -988,7 +988,7 @@ test("auto-compaction is a no-op when the ledger is below the threshold", async
|
|
|
988
988
|
try {
|
|
989
989
|
await scheduler.maybeCompactMemoryLifecycleLedger();
|
|
990
990
|
} finally {
|
|
991
|
-
scheduler.dispose();
|
|
991
|
+
await scheduler.dispose();
|
|
992
992
|
}
|
|
993
993
|
assert.equal(await readFile(ledgerPath, "utf-8"), before, "under threshold: ledger untouched");
|
|
994
994
|
} finally {
|
|
@@ -1064,7 +1064,7 @@ test("auto-compaction singleflight: two requests racing through the over-cap pro
|
|
|
1064
1064
|
assert.equal(stamps.length, 1, "only one compaction backup exists");
|
|
1065
1065
|
assert.ok((await stat(ledgerPath)).size < 4096, "ledger was compacted once");
|
|
1066
1066
|
} finally {
|
|
1067
|
-
scheduler.dispose();
|
|
1067
|
+
await scheduler.dispose();
|
|
1068
1068
|
}
|
|
1069
1069
|
} finally {
|
|
1070
1070
|
await rm(memoryDir, { recursive: true, force: true });
|
|
@@ -1120,7 +1120,7 @@ test("auto-compaction leaves the throttle un-advanced after a failed run so it r
|
|
|
1120
1120
|
"still-eligible retry compacts once the failure clears",
|
|
1121
1121
|
);
|
|
1122
1122
|
} finally {
|
|
1123
|
-
scheduler.dispose();
|
|
1123
|
+
await scheduler.dispose();
|
|
1124
1124
|
}
|
|
1125
1125
|
} finally {
|
|
1126
1126
|
await rm(memoryDir, { recursive: true, force: true });
|
|
@@ -1147,7 +1147,7 @@ test("auto-compaction rewrites the ledger encrypted at rest under a secure store
|
|
|
1147
1147
|
try {
|
|
1148
1148
|
await scheduler.maybeCompactMemoryLifecycleLedger();
|
|
1149
1149
|
} finally {
|
|
1150
|
-
scheduler.dispose();
|
|
1150
|
+
await scheduler.dispose();
|
|
1151
1151
|
}
|
|
1152
1152
|
// The rewritten ledger is encrypted at rest and smaller than the plaintext
|
|
1153
1153
|
// original, and decrypts back to the rebuilt events via the same key.
|
|
@@ -1215,7 +1215,7 @@ test("auto-compaction re-encrypts an ENCRYPTED ledger's backup for the archive p
|
|
|
1215
1215
|
try {
|
|
1216
1216
|
await scheduler.maybeCompactMemoryLifecycleLedger();
|
|
1217
1217
|
} finally {
|
|
1218
|
-
scheduler.dispose();
|
|
1218
|
+
await scheduler.dispose();
|
|
1219
1219
|
}
|
|
1220
1220
|
|
|
1221
1221
|
assert.ok(isEncryptedFile(await readFile(ledgerPath)), "compacted ledger stays encrypted at rest");
|
|
@@ -1314,7 +1314,7 @@ test("mixed pass: a deferred encrypted target keeps the throttle un-armed so unt
|
|
|
1314
1314
|
"deferred target left the throttle un-armed: the second in-window pass recompacts",
|
|
1315
1315
|
);
|
|
1316
1316
|
} finally {
|
|
1317
|
-
scheduler.dispose();
|
|
1317
|
+
await scheduler.dispose();
|
|
1318
1318
|
}
|
|
1319
1319
|
} finally {
|
|
1320
1320
|
await rm(root, { recursive: true, force: true });
|
|
@@ -1351,7 +1351,7 @@ test("maintenance drains a pending lifecycle-append spill even when compaction i
|
|
|
1351
1351
|
try {
|
|
1352
1352
|
await scheduler.maybeCompactMemoryLifecycleLedger();
|
|
1353
1353
|
} finally {
|
|
1354
|
-
scheduler.dispose();
|
|
1354
|
+
await scheduler.dispose();
|
|
1355
1355
|
}
|
|
1356
1356
|
|
|
1357
1357
|
const ids = (await storage.readAllMemoryLifecycleEvents()).map((e) => e.eventId);
|
|
@@ -1433,7 +1433,7 @@ test("maintenance drains a namespace pending spill created after the throttle ar
|
|
|
1433
1433
|
);
|
|
1434
1434
|
await assert.rejects(() => stat(spillPath), /ENOENT/, "namespace spill file removed after drain");
|
|
1435
1435
|
} finally {
|
|
1436
|
-
scheduler.dispose();
|
|
1436
|
+
await scheduler.dispose();
|
|
1437
1437
|
}
|
|
1438
1438
|
} finally {
|
|
1439
1439
|
await rm(root, { recursive: true, force: true });
|
|
@@ -1487,7 +1487,7 @@ test("auto-compaction bounds per-namespace ledgers, not just the root state path
|
|
|
1487
1487
|
try {
|
|
1488
1488
|
await scheduler.maybeCompactMemoryLifecycleLedger();
|
|
1489
1489
|
} finally {
|
|
1490
|
-
scheduler.dispose();
|
|
1490
|
+
await scheduler.dispose();
|
|
1491
1491
|
}
|
|
1492
1492
|
assert.ok((await stat(nsLedger)).size < beforeSize, "namespace ledger must be compacted");
|
|
1493
1493
|
const rebuilt = (await readFile(nsLedger, "utf-8")).trim().split("\n").map((l) => JSON.parse(l));
|
|
@@ -1529,7 +1529,7 @@ test("catalog-disabled fallback never downgrades an encrypted namespace ledger t
|
|
|
1529
1529
|
try {
|
|
1530
1530
|
await scheduler.maybeCompactMemoryLifecycleLedger();
|
|
1531
1531
|
} finally {
|
|
1532
|
-
scheduler.dispose();
|
|
1532
|
+
await scheduler.dispose();
|
|
1533
1533
|
}
|
|
1534
1534
|
// Skipped, not rewritten: the encrypted ledger must be byte-for-byte intact.
|
|
1535
1535
|
assert.deepEqual(
|
|
@@ -1635,7 +1635,7 @@ test("catalog-disabled fallback compacts an encrypted over-cap namespace ledger
|
|
|
1635
1635
|
"encrypted fallback ledger compacts through the keyed store, never deferred forever",
|
|
1636
1636
|
);
|
|
1637
1637
|
} finally {
|
|
1638
|
-
scheduler.dispose();
|
|
1638
|
+
await scheduler.dispose();
|
|
1639
1639
|
}
|
|
1640
1640
|
|
|
1641
1641
|
// On disk: rewritten, still encrypted at rest (no plaintext downgrade), and
|
|
@@ -1755,7 +1755,7 @@ test("catalog-disabled fallback decodes a long tokenized namespace dir so an enc
|
|
|
1755
1755
|
"encrypted over-cap ledger for a long namespace compacts through the keyed store, never deferred forever",
|
|
1756
1756
|
);
|
|
1757
1757
|
} finally {
|
|
1758
|
-
scheduler.dispose();
|
|
1758
|
+
await scheduler.dispose();
|
|
1759
1759
|
}
|
|
1760
1760
|
|
|
1761
1761
|
assert.notDeepEqual(
|
|
@@ -1867,7 +1867,7 @@ test("catalog-disabled fallback resolves a LEGACY RAW namespace dir (not a ns- t
|
|
|
1867
1867
|
"encrypted over-cap ledger under a legacy raw namespace dir compacts through the keyed store, never deferred forever",
|
|
1868
1868
|
);
|
|
1869
1869
|
} finally {
|
|
1870
|
-
scheduler.dispose();
|
|
1870
|
+
await scheduler.dispose();
|
|
1871
1871
|
}
|
|
1872
1872
|
|
|
1873
1873
|
assert.notDeepEqual(await readFile(nsLedger), encrypted, "ledger was rewritten (not deferred)");
|
|
@@ -1996,7 +1996,7 @@ test("catalog-disabled fallback routes a LEGACY RAW namespace dir through the PR
|
|
|
1996
1996
|
"encrypted over-cap ledger under a legacy raw namespace dir compacts through the production-resolved keyed store, never deferred forever",
|
|
1997
1997
|
);
|
|
1998
1998
|
} finally {
|
|
1999
|
-
scheduler.dispose();
|
|
1999
|
+
await scheduler.dispose();
|
|
2000
2000
|
}
|
|
2001
2001
|
|
|
2002
2002
|
assert.notDeepEqual(await readFile(nsLedger), encrypted, "ledger was rewritten (not deferred)");
|
|
@@ -2128,7 +2128,7 @@ test("catalog-disabled fallback refuses a symlinked namespaces scan root (#2033)
|
|
|
2128
2128
|
try {
|
|
2129
2129
|
await scheduler.maybeCompactMemoryLifecycleLedger();
|
|
2130
2130
|
} finally {
|
|
2131
|
-
scheduler.dispose();
|
|
2131
|
+
await scheduler.dispose();
|
|
2132
2132
|
}
|
|
2133
2133
|
assert.equal(
|
|
2134
2134
|
await readFile(nsLedger, "utf-8"),
|
|
@@ -2175,7 +2175,7 @@ test("maintenance request triggers lifecycle compaction even when QMD is unavail
|
|
|
2175
2175
|
"lifecycle compaction must be triggered from the maintenance request when QMD is unavailable",
|
|
2176
2176
|
);
|
|
2177
2177
|
} finally {
|
|
2178
|
-
scheduler.dispose();
|
|
2178
|
+
await scheduler.dispose();
|
|
2179
2179
|
}
|
|
2180
2180
|
} finally {
|
|
2181
2181
|
await rm(memoryDir, { recursive: true, force: true });
|
|
@@ -2215,7 +2215,7 @@ test("auto-compaction bounds per-namespace ledgers via filesystem fallback when
|
|
|
2215
2215
|
try {
|
|
2216
2216
|
await scheduler.maybeCompactMemoryLifecycleLedger();
|
|
2217
2217
|
} finally {
|
|
2218
|
-
scheduler.dispose();
|
|
2218
|
+
await scheduler.dispose();
|
|
2219
2219
|
}
|
|
2220
2220
|
assert.ok(
|
|
2221
2221
|
(await stat(nsLedger)).size < beforeSize,
|
|
@@ -2286,7 +2286,7 @@ test("auto-compaction bounds a large append-only history under the read/decrypt
|
|
|
2286
2286
|
"throttle armed after an effective bounded compaction: second in-window pass is a no-op",
|
|
2287
2287
|
);
|
|
2288
2288
|
} finally {
|
|
2289
|
-
scheduler.dispose();
|
|
2289
|
+
await scheduler.dispose();
|
|
2290
2290
|
}
|
|
2291
2291
|
} finally {
|
|
2292
2292
|
await rm(memoryDir, { recursive: true, force: true });
|
|
@@ -2328,7 +2328,7 @@ test("filesystem-fallback compaction drains a pending lifecycle append even when
|
|
|
2328
2328
|
try {
|
|
2329
2329
|
await scheduler.maybeCompactMemoryLifecycleLedger();
|
|
2330
2330
|
} finally {
|
|
2331
|
-
scheduler.dispose();
|
|
2331
|
+
await scheduler.dispose();
|
|
2332
2332
|
}
|
|
2333
2333
|
|
|
2334
2334
|
const ledger = await readFile(nsLedger, "utf-8");
|
|
@@ -2388,7 +2388,7 @@ test("filesystem-fallback compaction recovers a crash-orphaned *.claimed spill w
|
|
|
2388
2388
|
try {
|
|
2389
2389
|
await scheduler.maybeCompactMemoryLifecycleLedger();
|
|
2390
2390
|
} finally {
|
|
2391
|
-
scheduler.dispose();
|
|
2391
|
+
await scheduler.dispose();
|
|
2392
2392
|
}
|
|
2393
2393
|
|
|
2394
2394
|
const ledger = await readFile(nsLedger, "utf-8");
|
|
@@ -2454,7 +2454,7 @@ test("catalog-disabled fallback drain re-probes encryption UNDER the lock and de
|
|
|
2454
2454
|
try {
|
|
2455
2455
|
await scheduler.maybeCompactMemoryLifecycleLedger();
|
|
2456
2456
|
} finally {
|
|
2457
|
-
scheduler.dispose();
|
|
2457
|
+
await scheduler.dispose();
|
|
2458
2458
|
}
|
|
2459
2459
|
|
|
2460
2460
|
// nsA: encrypted spill deferred — byte-for-byte intact, the ledger never got
|
|
@@ -2514,7 +2514,7 @@ test("auto-compaction triggers on an encrypted ledger at/above the decrypt cap e
|
|
|
2514
2514
|
try {
|
|
2515
2515
|
await scheduler.maybeCompactMemoryLifecycleLedger();
|
|
2516
2516
|
} finally {
|
|
2517
|
-
scheduler.dispose();
|
|
2517
|
+
await scheduler.dispose();
|
|
2518
2518
|
}
|
|
2519
2519
|
const afterSize = (await stat(ledgerPath)).size;
|
|
2520
2520
|
assert.ok(afterSize < beforeSize, "over-cap encrypted ledger must compact despite the larger threshold");
|
|
@@ -2572,7 +2572,7 @@ test("auto-compaction bypasses the min-interval throttle for an over-cap encrypt
|
|
|
2572
2572
|
try {
|
|
2573
2573
|
await bypassScheduler.maybeCompactMemoryLifecycleLedger();
|
|
2574
2574
|
} finally {
|
|
2575
|
-
bypassScheduler.dispose();
|
|
2575
|
+
await bypassScheduler.dispose();
|
|
2576
2576
|
}
|
|
2577
2577
|
const bypassAfter = (await stat(bypassLedger)).size;
|
|
2578
2578
|
assert.ok(
|
|
@@ -2598,7 +2598,7 @@ test("auto-compaction bypasses the min-interval throttle for an over-cap encrypt
|
|
|
2598
2598
|
try {
|
|
2599
2599
|
await throttledScheduler.maybeCompactMemoryLifecycleLedger();
|
|
2600
2600
|
} finally {
|
|
2601
|
-
throttledScheduler.dispose();
|
|
2601
|
+
await throttledScheduler.dispose();
|
|
2602
2602
|
}
|
|
2603
2603
|
assert.equal(
|
|
2604
2604
|
(await stat(throttledLedger)).size,
|
|
@@ -2684,7 +2684,7 @@ test("auto-compaction reserves the secure-store envelope so an encrypted rewrite
|
|
|
2684
2684
|
"throttle armed after an effective encrypted compaction: second in-window pass is a no-op",
|
|
2685
2685
|
);
|
|
2686
2686
|
} finally {
|
|
2687
|
-
scheduler.dispose();
|
|
2687
|
+
await scheduler.dispose();
|
|
2688
2688
|
}
|
|
2689
2689
|
} finally {
|
|
2690
2690
|
await rm(memoryDir, { recursive: true, force: true });
|
|
@@ -2762,7 +2762,7 @@ test("auto-compaction reserves the envelope when a PLAINTEXT ledger will be rewr
|
|
|
2762
2762
|
"throttle armed after an effective compaction: second in-window pass is a no-op",
|
|
2763
2763
|
);
|
|
2764
2764
|
} finally {
|
|
2765
|
-
scheduler.dispose();
|
|
2765
|
+
await scheduler.dispose();
|
|
2766
2766
|
}
|
|
2767
2767
|
} finally {
|
|
2768
2768
|
await rm(memoryDir, { recursive: true, force: true });
|
|
@@ -2819,7 +2819,7 @@ test("catalog-disabled fallback pending drain skips unsafe spill entries (symlin
|
|
|
2819
2819
|
// (caught by the test timeout) and following the symlink would escape.
|
|
2820
2820
|
await scheduler.maybeCompactMemoryLifecycleLedger();
|
|
2821
2821
|
} finally {
|
|
2822
|
-
scheduler.dispose();
|
|
2822
|
+
await scheduler.dispose();
|
|
2823
2823
|
}
|
|
2824
2824
|
|
|
2825
2825
|
const ledger = await readFile(nsLedger, "utf-8");
|
|
@@ -57,6 +57,7 @@ import {
|
|
|
57
57
|
type LifecyclePendingIo,
|
|
58
58
|
} from "../storage/memory-lifecycle-ledger-access.js";
|
|
59
59
|
import { STATE_FILE_MAX_DECRYPT_BYTES } from "../storage/secure-line-reader.js";
|
|
60
|
+
import { ActivitySyncRegistrar } from "../activity/sync-registration.js";
|
|
60
61
|
import { resolveHomeDir } from "../runtime/env.js";
|
|
61
62
|
import { log } from "../logger.js";
|
|
62
63
|
import { isErrnoCode } from "../utils/errno.js";
|
|
@@ -133,7 +134,20 @@ export class MaintenanceScheduler {
|
|
|
133
134
|
// fixture.
|
|
134
135
|
private lifecycleLedgerMaxBytes = STATE_FILE_MAX_DECRYPT_BYTES;
|
|
135
136
|
|
|
136
|
-
|
|
137
|
+
// ── Activity (screen-capture) sync scheduler (issue #1900) ──
|
|
138
|
+
// The full arm/re-arm/teardown lifecycle lives in ActivitySyncRegistrar.
|
|
139
|
+
private readonly activityRegistrar: ActivitySyncRegistrar;
|
|
140
|
+
|
|
141
|
+
constructor(private readonly deps: MaintenanceSchedulerDeps) {
|
|
142
|
+
this.activityRegistrar = new ActivitySyncRegistrar({
|
|
143
|
+
config: deps.config.activity,
|
|
144
|
+
memoryDir: deps.config.memoryDir,
|
|
145
|
+
qmdCollection: deps.config.qmdCollection,
|
|
146
|
+
secureStoreEnabled: resolveRecallAuxiliaryCapabilities(deps.config).secureStore,
|
|
147
|
+
getQmd: () => deps.getQmd(),
|
|
148
|
+
requestReindexRetry: () => this.requestQmdMaintenanceForTool("activity-reindex-retry"),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
137
151
|
|
|
138
152
|
// ───────────────────────────────────────────────────────────────────────
|
|
139
153
|
// Cron auto-registration
|
|
@@ -148,7 +162,7 @@ export class MaintenanceScheduler {
|
|
|
148
162
|
* Returns when all eligible registrations have completed so callers that
|
|
149
163
|
* `await deferredReady` can rely on jobs.json being current.
|
|
150
164
|
*/
|
|
151
|
-
async autoRegisterCrons(
|
|
165
|
+
async autoRegisterCrons(signal: AbortSignal): Promise<void> {
|
|
152
166
|
if (resolveRecallAuxiliaryCapabilities(this.deps.config).daySummary) {
|
|
153
167
|
try {
|
|
154
168
|
await this.autoRegisterDaySummaryCron();
|
|
@@ -191,6 +205,11 @@ export class MaintenanceScheduler {
|
|
|
191
205
|
log.debug(`graph edge decay cron auto-register failed (non-fatal): ${err}`);
|
|
192
206
|
}
|
|
193
207
|
}
|
|
208
|
+
|
|
209
|
+
// Activity (screen-capture) in-process sync scheduler (issue #1900),
|
|
210
|
+
// master default-off. The registrar owns the arm/re-arm/teardown contract
|
|
211
|
+
// (stop-prior, abort/teardown guards, secure-store refusal, retry latch).
|
|
212
|
+
await this.activityRegistrar.register(signal);
|
|
194
213
|
}
|
|
195
214
|
|
|
196
215
|
async autoRegisterDaySummaryCron(): Promise<void> {
|
|
@@ -1125,10 +1144,23 @@ export class MaintenanceScheduler {
|
|
|
1125
1144
|
// ───────────────────────────────────────────────────────────────────────
|
|
1126
1145
|
|
|
1127
1146
|
/**
|
|
1128
|
-
* Clear any pending debounce timer
|
|
1129
|
-
* destroy() so a late tick does not fire on a
|
|
1147
|
+
* Clear any pending debounce timer and drain the activity sync scheduler.
|
|
1148
|
+
* Called from the orchestrator's destroy() so a late tick does not fire on a
|
|
1149
|
+
* torn-down instance and no in-flight activity tick keeps writing after
|
|
1150
|
+
* teardown. Async: awaits the scheduler's abort+drain before resolving.
|
|
1130
1151
|
*/
|
|
1131
|
-
dispose(): void {
|
|
1152
|
+
async dispose(): Promise<void> {
|
|
1153
|
+
// The registrar latches teardown first (so a draining tick's onRun cannot
|
|
1154
|
+
// re-arm QMD maintenance) and aborts+drains the sync. Capture its drain and
|
|
1155
|
+
// await it last so the rest of teardown runs while the aborted tick unwinds.
|
|
1156
|
+
const activityDrain = this.activityRegistrar.dispose();
|
|
1157
|
+
if (this.qmdMaintenanceTimer) {
|
|
1158
|
+
clearTimeout(this.qmdMaintenanceTimer);
|
|
1159
|
+
this.qmdMaintenanceTimer = null;
|
|
1160
|
+
}
|
|
1161
|
+
this.qmdMaintenancePending = false;
|
|
1162
|
+
await activityDrain;
|
|
1163
|
+
// Belt-and-suspenders: clear anything a late tick armed before the latch.
|
|
1132
1164
|
if (this.qmdMaintenanceTimer) {
|
|
1133
1165
|
clearTimeout(this.qmdMaintenanceTimer);
|
|
1134
1166
|
this.qmdMaintenanceTimer = null;
|
|
@@ -601,6 +601,39 @@ export function isArtifactMemoryPath(filePath: string): boolean {
|
|
|
601
601
|
return /(?:^|[\\/])artifacts(?:[\\/]|$)/i.test(filePath);
|
|
602
602
|
}
|
|
603
603
|
|
|
604
|
+
/** Exactly `activity/<YYYY-MM-DD>.md`, at the top level of a memory root. */
|
|
605
|
+
const ACTIVITY_DIGEST_TOPLEVEL = /^activity[\\/]\d{4}-\d{2}-\d{2}\.md$/i;
|
|
606
|
+
/** The digest FILE shape anywhere in a path (root-unaware best-effort). */
|
|
607
|
+
const ACTIVITY_DIGEST_ANYWHERE = /(?:^|[\\/])activity[\\/]\d{4}-\d{2}-\d{2}\.md$/i;
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Activity day-digests live at `<memoryRoot>/activity/<YYYY-MM-DD>.md` — a
|
|
611
|
+
* dedicated searchable surface (explicit activity search), never generic recall.
|
|
612
|
+
* Captured screen text must not auto-inject into ordinary prompts (issue #1899).
|
|
613
|
+
* Keyed on the path (parseFrontmatter drops the digest's `kind` marker).
|
|
614
|
+
*
|
|
615
|
+
* Root-aware: when `memoryRoot` is given, the path is resolved relative to it and
|
|
616
|
+
* must be the TOP-LEVEL `activity/<date>.md`, so an ordinary memory nested under
|
|
617
|
+
* a category (e.g. `facts/proj/activity/<date>.md`) stays recallable. Without a
|
|
618
|
+
* root, falls back to the digest file shape anywhere (best-effort).
|
|
619
|
+
*/
|
|
620
|
+
export function isActivityDigestPath(filePath: string, memoryRoot?: string): boolean {
|
|
621
|
+
if (memoryRoot !== undefined && memoryRoot.length > 0) {
|
|
622
|
+
const relative = path.relative(memoryRoot, path.resolve(memoryRoot, filePath));
|
|
623
|
+
return ACTIVITY_DIGEST_TOPLEVEL.test(relative);
|
|
624
|
+
}
|
|
625
|
+
return ACTIVITY_DIGEST_ANYWHERE.test(filePath);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Paths that dedicated surfaces own and generic recall must never inject:
|
|
630
|
+
* artifacts and activity digests. Explicit search paths (memory_search,
|
|
631
|
+
* activity search) do not apply this filter, so those surfaces still read them.
|
|
632
|
+
*/
|
|
633
|
+
export function isGenericRecallExcludedPath(filePath: string, memoryRoot?: string): boolean {
|
|
634
|
+
return isArtifactMemoryPath(filePath) || isActivityDigestPath(filePath, memoryRoot);
|
|
635
|
+
}
|
|
636
|
+
|
|
604
637
|
export function buildCompressionGuidelinesMarkdown(
|
|
605
638
|
events: MemoryActionEvent[],
|
|
606
639
|
generatedAtIso: string = new Date().toISOString(),
|
|
@@ -615,6 +648,8 @@ export function filterRecallCandidates(
|
|
|
615
648
|
recallNamespaces: string[];
|
|
616
649
|
resolveNamespace: (path: string) => string;
|
|
617
650
|
limit: number;
|
|
651
|
+
/** Memory root for top-level activity-digest detection. */
|
|
652
|
+
memoryRoot?: string;
|
|
618
653
|
},
|
|
619
654
|
): QmdSearchResult[] {
|
|
620
655
|
const scopedByNamespace = options.namespacesEnabled
|
|
@@ -623,7 +658,7 @@ export function filterRecallCandidates(
|
|
|
623
658
|
)
|
|
624
659
|
: candidates;
|
|
625
660
|
return scopedByNamespace
|
|
626
|
-
.filter((r) => !
|
|
661
|
+
.filter((r) => !isGenericRecallExcludedPath(r.path, options.memoryRoot))
|
|
627
662
|
.slice(0, Math.max(0, options.limit));
|
|
628
663
|
}
|
|
629
664
|
|
|
@@ -84,7 +84,6 @@ import {
|
|
|
84
84
|
computeArtifactRecallLimit,
|
|
85
85
|
computeQmdHybridFetchLimit,
|
|
86
86
|
defaultWorkspaceDir,
|
|
87
|
-
isArtifactMemoryPath,
|
|
88
87
|
raceRecallAbort,
|
|
89
88
|
resolveRecallModeDecision,
|
|
90
89
|
resolveRecallModeDecisionAsync,
|
|
@@ -97,6 +96,7 @@ import {
|
|
|
97
96
|
type QueryAwarePrefilter,
|
|
98
97
|
type RecallInvocationOptions,
|
|
99
98
|
} from "../orchestrator.js";
|
|
99
|
+
import { isGenericRecallExcludedPath } from "./orchestrator-helpers.js";
|
|
100
100
|
|
|
101
101
|
import type {
|
|
102
102
|
RecallSectionAppendOptions,
|
|
@@ -4161,10 +4161,8 @@ export class RecallInternalCoordinator {
|
|
|
4161
4161
|
memoryResults = memoryResults.filter((r) =>
|
|
4162
4162
|
recallNamespaces.includes(r.namespace ?? this.deps.namespaceFromPath(r.path)));
|
|
4163
4163
|
}
|
|
4164
|
-
// Artifacts
|
|
4165
|
-
memoryResults = memoryResults.filter(
|
|
4166
|
-
(r) => !isArtifactMemoryPath(r.path),
|
|
4167
|
-
);
|
|
4164
|
+
// Artifacts + activity digests are dedicated surfaces, never generic recall.
|
|
4165
|
+
memoryResults = memoryResults.filter((r) => !isGenericRecallExcludedPath(r.path, this.deps.config.memoryDir));
|
|
4168
4166
|
|
|
4169
4167
|
const isFullModeGraphAssist =
|
|
4170
4168
|
graphCaps.multiGraphMemory &&
|
|
@@ -4552,6 +4550,7 @@ export class RecallInternalCoordinator {
|
|
|
4552
4550
|
recallNamespaces,
|
|
4553
4551
|
resolveNamespace: (p) => this.deps.namespaceFromPath(p),
|
|
4554
4552
|
limit: embeddingFetchLimit,
|
|
4553
|
+
memoryRoot: this.deps.config.memoryDir,
|
|
4555
4554
|
},
|
|
4556
4555
|
);
|
|
4557
4556
|
const boostedScoped = await this.deps.boostSearchResults(
|
|
@@ -4749,6 +4748,7 @@ export class RecallInternalCoordinator {
|
|
|
4749
4748
|
recallNamespaces,
|
|
4750
4749
|
resolveNamespace: (p) => this.deps.namespaceFromPath(p),
|
|
4751
4750
|
limit: embeddingFetchLimit,
|
|
4751
|
+
memoryRoot: this.deps.config.memoryDir,
|
|
4752
4752
|
},
|
|
4753
4753
|
);
|
|
4754
4754
|
const boostedScoped = await this.deps.boostSearchResults(
|
|
@@ -4871,7 +4871,7 @@ export class RecallInternalCoordinator {
|
|
|
4871
4871
|
typeof asOfMs === "number" && Number.isFinite(asOfMs);
|
|
4872
4872
|
const activeMemories = memories.filter(
|
|
4873
4873
|
(m) => {
|
|
4874
|
-
if (
|
|
4874
|
+
if (isGenericRecallExcludedPath(m.path, this.deps.config.memoryDir)) return false;
|
|
4875
4875
|
const status = m.frontmatter.status;
|
|
4876
4876
|
if (!status || status === "active") return true;
|
|
4877
4877
|
if (status === "superseded") {
|
|
@@ -54,12 +54,12 @@ import {
|
|
|
54
54
|
shouldFilterLifecycleRecallCandidate,
|
|
55
55
|
computeQmdHybridFetchLimit,
|
|
56
56
|
filterRecallCandidates,
|
|
57
|
-
isArtifactMemoryPath,
|
|
58
57
|
throwIfRecallAborted,
|
|
59
58
|
tokenizeRecallQuery,
|
|
60
59
|
type QmdRecallSnapshot,
|
|
61
60
|
type QueryAwarePrefilter,
|
|
62
61
|
} from "../orchestrator.js";
|
|
62
|
+
import { isActivityDigestPath, isGenericRecallExcludedPath } from "./orchestrator-helpers.js";
|
|
63
63
|
|
|
64
64
|
export interface RecallSearchPipelineDeps {
|
|
65
65
|
applyMemoryWorthRerank(
|
|
@@ -466,6 +466,7 @@ export class RecallSearchPipelineCoordinator {
|
|
|
466
466
|
recallNamespaces: options.recallNamespaces,
|
|
467
467
|
resolveNamespace: options.resolveNamespace,
|
|
468
468
|
limit: qmdFetchLimit,
|
|
469
|
+
memoryRoot: this.deps.config.memoryDir,
|
|
469
470
|
});
|
|
470
471
|
const emitDebugSnapshot = async (
|
|
471
472
|
results: QmdSearchResult[],
|
|
@@ -610,6 +611,7 @@ export class RecallSearchPipelineCoordinator {
|
|
|
610
611
|
recallNamespaces: options.recallNamespaces,
|
|
611
612
|
resolveNamespace: options.resolveNamespace,
|
|
612
613
|
limit: fetchLimit,
|
|
614
|
+
memoryRoot: this.deps.config.memoryDir,
|
|
613
615
|
});
|
|
614
616
|
|
|
615
617
|
if (filteredResults.length >= qmdFetchLimit) {
|
|
@@ -693,7 +695,7 @@ export class RecallSearchPipelineCoordinator {
|
|
|
693
695
|
: [];
|
|
694
696
|
if (scopedSeedResults.length >= cappedLimit) {
|
|
695
697
|
return scopedSeedResults
|
|
696
|
-
.filter((result) => !
|
|
698
|
+
.filter((result) => !isGenericRecallExcludedPath(result.path, this.deps.config.memoryDir))
|
|
697
699
|
.slice(0, cappedLimit);
|
|
698
700
|
}
|
|
699
701
|
|
|
@@ -726,7 +728,7 @@ export class RecallSearchPipelineCoordinator {
|
|
|
726
728
|
[...scopedSeedResults, ...scored],
|
|
727
729
|
this.deps.namespaceFromPath,
|
|
728
730
|
cappedLimit,
|
|
729
|
-
{ filter: (result) => !
|
|
731
|
+
{ filter: (result) => !isGenericRecallExcludedPath(result.path, this.deps.config.memoryDir) },
|
|
730
732
|
);
|
|
731
733
|
}
|
|
732
734
|
|
|
@@ -974,8 +976,9 @@ export class RecallSearchPipelineCoordinator {
|
|
|
974
976
|
}
|
|
975
977
|
results = scopedResults;
|
|
976
978
|
}
|
|
977
|
-
//
|
|
978
|
-
|
|
979
|
+
// Dedicated-surface isolation: generic recall must exclude artifacts and
|
|
980
|
+
// activity digests (both remain readable via explicit search).
|
|
981
|
+
results = results.filter((r) => !isGenericRecallExcludedPath(r.path, this.deps.config.memoryDir));
|
|
979
982
|
if (results.length === 0) return [];
|
|
980
983
|
|
|
981
984
|
const isFullModeGraphAssist =
|
|
@@ -1351,10 +1354,15 @@ export class RecallSearchPipelineCoordinator {
|
|
|
1351
1354
|
continue;
|
|
1352
1355
|
}
|
|
1353
1356
|
|
|
1357
|
+
// Activity day-digests are a dedicated searchable surface (explicit
|
|
1358
|
+
// activity search), never generic recall — captured screen text must not
|
|
1359
|
+
// auto-inject into ordinary prompts (issue #1899). Keyed on the PATH:
|
|
1360
|
+
// the digest's `kind` frontmatter marker does not survive parseFrontmatter.
|
|
1354
1361
|
if (
|
|
1355
1362
|
options?.allowDedicatedSurface !== true &&
|
|
1356
1363
|
(memory.frontmatter.memoryKind === "dream" ||
|
|
1357
|
-
memory.frontmatter.memoryKind === "procedural"
|
|
1364
|
+
memory.frontmatter.memoryKind === "procedural" ||
|
|
1365
|
+
isActivityDigestPath(memory.path, this.deps.config.memoryDir))
|
|
1358
1366
|
) {
|
|
1359
1367
|
dedicatedSurfaceFilteredCount += 1;
|
|
1360
1368
|
continue;
|
|
@@ -1379,7 +1387,7 @@ export class RecallSearchPipelineCoordinator {
|
|
|
1379
1387
|
}
|
|
1380
1388
|
if (dedicatedSurfaceFilteredCount > 0) {
|
|
1381
1389
|
log.debug(
|
|
1382
|
-
`dedicated surface filter removed ${dedicatedSurfaceFilteredCount} dream/procedural candidates from generic recall`,
|
|
1390
|
+
`dedicated surface filter removed ${dedicatedSurfaceFilteredCount} dream/procedural/activity-digest candidates from generic recall`,
|
|
1383
1391
|
);
|
|
1384
1392
|
}
|
|
1385
1393
|
if (forgottenFilteredCount > 0) {
|
|
@@ -21,13 +21,13 @@ test("destroy cancels maintenance and waits for tracked writes before disposing
|
|
|
21
21
|
compoundingEnabled: false,
|
|
22
22
|
})
|
|
23
23
|
);
|
|
24
|
-
const maintenanceScheduler = (orchestrator as unknown as { maintenanceScheduler: { dispose(): void } })
|
|
24
|
+
const maintenanceScheduler = (orchestrator as unknown as { maintenanceScheduler: { dispose(): Promise<void> } })
|
|
25
25
|
.maintenanceScheduler;
|
|
26
26
|
const originalMaintenanceDispose = maintenanceScheduler.dispose.bind(maintenanceScheduler);
|
|
27
27
|
let maintenanceDisposed = false;
|
|
28
28
|
maintenanceScheduler.dispose = () => {
|
|
29
29
|
maintenanceDisposed = true;
|
|
30
|
-
originalMaintenanceDispose();
|
|
30
|
+
return originalMaintenanceDispose();
|
|
31
31
|
};
|
|
32
32
|
const writeGate = Promise.withResolvers<void>();
|
|
33
33
|
let destroySettled = false;
|