@remnic/core 9.7.11 → 9.7.12
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 +6 -6
- package/dist/access-admin-ops-surface.js +7 -7
- package/dist/access-boundary.d.ts +6 -6
- package/dist/access-boundary.js +8 -8
- package/dist/access-cli.js +31 -31
- package/dist/access-http.d.ts +6 -6
- package/dist/access-http.js +12 -12
- package/dist/access-identity-continuity-surface.d.ts +5 -5
- package/dist/access-identity-continuity-surface.js +7 -7
- package/dist/access-lcm-surface.d.ts +6 -6
- package/dist/access-lcm-surface.js +7 -7
- package/dist/access-mcp.d.ts +6 -6
- package/dist/access-mcp.js +11 -11
- package/dist/access-observe-write-surface.d.ts +6 -6
- package/dist/access-observe-write-surface.js +7 -7
- package/dist/access-operations-batch.js +9 -9
- package/dist/access-operations.d.ts +6 -6
- package/dist/access-operations.js +10 -10
- package/dist/access-recall-surface.d.ts +6 -6
- package/dist/access-recall-surface.js +7 -7
- package/dist/{access-service-DSuzikHQ.d.ts → access-service-tHd3eQpd.d.ts} +4 -4
- package/dist/access-service.d.ts +6 -6
- package/dist/access-service.js +7 -7
- package/dist/access-surface-catalog.d.ts +6 -6
- 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 +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +5 -5
- 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-BNwjACa5.d.ts → catalog-DEMiw6HZ.d.ts} +48 -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-U4KHQTJ6.js → chunk-2AL7N3BH.js} +4 -2
- package/dist/{chunk-U4KHQTJ6.js.map → chunk-2AL7N3BH.js.map} +1 -1
- package/dist/{chunk-L4H6MQ7I.js → chunk-2RSL6YRA.js} +2 -2
- package/dist/{chunk-JYRFO4EH.js → chunk-2ZPQUTMW.js} +4 -4
- package/dist/{chunk-673NPXE3.js → chunk-3SIC3E65.js} +2 -2
- package/dist/{chunk-OVMS3DCB.js → chunk-675YU5IK.js} +2 -2
- package/dist/{chunk-7LMEY5KZ.js → chunk-6N7R7TR2.js} +34 -1
- package/dist/chunk-6N7R7TR2.js.map +1 -0
- package/dist/{chunk-W6R43NLA.js → chunk-AOWPZ7TM.js} +17 -17
- package/dist/{chunk-TGBJ2OMK.js → chunk-BQTSGK5Y.js} +2 -2
- package/dist/{chunk-6LM6PPDX.js → chunk-CE3GMHT4.js} +2 -2
- package/dist/{chunk-YXOAQAH2.js → chunk-CLFY35ED.js} +3 -3
- package/dist/{chunk-HQ7QZJM5.js → chunk-D4TLWDYR.js} +2 -2
- package/dist/{chunk-LQKITFGB.js → chunk-FUUF7FMX.js} +2 -2
- package/dist/{chunk-3ZVFLMFQ.js → chunk-G5PVJJRA.js} +1 -1
- package/dist/chunk-G5PVJJRA.js.map +1 -0
- package/dist/{chunk-MXRMNKSY.js → chunk-I3GKTDM2.js} +3 -3
- package/dist/{chunk-EQF5763Z.js → chunk-IQULRIZM.js} +2 -2
- package/dist/{chunk-DJCKXI4M.js → chunk-NVXQTRBL.js} +2 -2
- package/dist/{chunk-GHVJASQ4.js → chunk-OCY3CRPG.js} +3 -3
- package/dist/{chunk-YLTG6BO4.js → chunk-OIFZII6J.js} +2 -2
- package/dist/{chunk-XF4KOVDK.js → chunk-PA6DMYEK.js} +6 -6
- package/dist/{chunk-3OQ4IZJN.js → chunk-QPZCAVDC.js} +7 -7
- package/dist/{chunk-DLWYAN6A.js → chunk-T6U7HDIY.js} +2 -2
- package/dist/{chunk-7XRUYC6G.js → chunk-TITSEN2M.js} +3 -3
- package/dist/{chunk-JZM5QUTE.js → chunk-TMGK6YE7.js} +171 -9
- package/dist/chunk-TMGK6YE7.js.map +1 -0
- package/dist/{chunk-KXLRMM35.js → chunk-TRH533CA.js} +30 -7
- package/dist/chunk-TRH533CA.js.map +1 -0
- package/dist/{chunk-UTDA43TB.js → chunk-TWGGNUWJ.js} +2 -2
- package/dist/{chunk-SBFDL2EQ.js → chunk-UTZW3X2R.js} +2 -2
- package/dist/{chunk-SECMZACR.js → chunk-XUQUBZ7O.js} +2 -2
- package/dist/{chunk-5U65RIVI.js → chunk-YI7XUXLX.js} +16 -15
- package/dist/chunk-YI7XUXLX.js.map +1 -0
- package/dist/{chunk-QHT4W3RU.js → chunk-ZASJ53ML.js} +6 -6
- package/dist/{chunk-WUDBMLC6.js → chunk-ZC3HG22I.js} +2 -2
- package/dist/{chunk-VCEH5UYS.js → chunk-ZRXSHGXT.js} +2 -2
- package/dist/{cli-DACyuK8-.d.ts → cli-D8Tsa4Sh.d.ts} +5 -5
- package/dist/cli.d.ts +8 -8
- package/dist/cli.js +25 -25
- 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 +1 -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 +5 -5
- 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/identity-continuity.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 +14 -14
- package/dist/index.js +31 -31
- 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.js +3 -3
- package/dist/maintenance/rebuild-memory-projection.js +4 -4
- package/dist/mcp-memory-inspector-app.d.ts +6 -6
- 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/operator-toolkit.d.ts +2 -2
- package/dist/operator-toolkit.js +8 -8
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +5 -5
- package/dist/{orchestrator-D83AvrPf.d.ts → orchestrator-B_WXBmuE.d.ts} +4 -4
- package/dist/orchestrator.d.ts +5 -5
- package/dist/orchestrator.js +31 -31
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-BSqGpYl1.d.ts → pipeline-Dvtvt141.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/{qmd-CutnpRVe.d.ts → qmd-DwBLh_hl.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-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-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 +2 -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/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-btIVRC4l.d.ts → semantic-consolidation-Dia_6FOn.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-BVv_Mqa0.d.ts → storage-RshM7i8-.d.ts} +18 -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-Cmkz7csa.d.ts → types-CHSXOq7s.d.ts} +34 -0
- 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/package.json +2 -2
- package/src/config.test.ts +44 -0
- package/src/config.ts +43 -0
- package/src/namespaces/catalog.test.ts +258 -0
- package/src/namespaces/catalog.ts +235 -10
- package/src/namespaces/storage.ts +9 -0
- package/src/orchestrator.ts +3 -0
- package/src/storage-catalog-touch-gating.test.ts +70 -0
- package/src/storage.ts +31 -5
- package/src/types.ts +34 -0
- package/dist/chunk-3ZVFLMFQ.js.map +0 -1
- package/dist/chunk-5U65RIVI.js.map +0 -1
- package/dist/chunk-7LMEY5KZ.js.map +0 -1
- package/dist/chunk-JZM5QUTE.js.map +0 -1
- package/dist/chunk-KXLRMM35.js.map +0 -1
- /package/dist/{chunk-L4H6MQ7I.js.map → chunk-2RSL6YRA.js.map} +0 -0
- /package/dist/{chunk-JYRFO4EH.js.map → chunk-2ZPQUTMW.js.map} +0 -0
- /package/dist/{chunk-673NPXE3.js.map → chunk-3SIC3E65.js.map} +0 -0
- /package/dist/{chunk-OVMS3DCB.js.map → chunk-675YU5IK.js.map} +0 -0
- /package/dist/{chunk-W6R43NLA.js.map → chunk-AOWPZ7TM.js.map} +0 -0
- /package/dist/{chunk-TGBJ2OMK.js.map → chunk-BQTSGK5Y.js.map} +0 -0
- /package/dist/{chunk-6LM6PPDX.js.map → chunk-CE3GMHT4.js.map} +0 -0
- /package/dist/{chunk-YXOAQAH2.js.map → chunk-CLFY35ED.js.map} +0 -0
- /package/dist/{chunk-HQ7QZJM5.js.map → chunk-D4TLWDYR.js.map} +0 -0
- /package/dist/{chunk-LQKITFGB.js.map → chunk-FUUF7FMX.js.map} +0 -0
- /package/dist/{chunk-MXRMNKSY.js.map → chunk-I3GKTDM2.js.map} +0 -0
- /package/dist/{chunk-EQF5763Z.js.map → chunk-IQULRIZM.js.map} +0 -0
- /package/dist/{chunk-DJCKXI4M.js.map → chunk-NVXQTRBL.js.map} +0 -0
- /package/dist/{chunk-GHVJASQ4.js.map → chunk-OCY3CRPG.js.map} +0 -0
- /package/dist/{chunk-YLTG6BO4.js.map → chunk-OIFZII6J.js.map} +0 -0
- /package/dist/{chunk-XF4KOVDK.js.map → chunk-PA6DMYEK.js.map} +0 -0
- /package/dist/{chunk-3OQ4IZJN.js.map → chunk-QPZCAVDC.js.map} +0 -0
- /package/dist/{chunk-DLWYAN6A.js.map → chunk-T6U7HDIY.js.map} +0 -0
- /package/dist/{chunk-7XRUYC6G.js.map → chunk-TITSEN2M.js.map} +0 -0
- /package/dist/{chunk-UTDA43TB.js.map → chunk-TWGGNUWJ.js.map} +0 -0
- /package/dist/{chunk-SBFDL2EQ.js.map → chunk-UTZW3X2R.js.map} +0 -0
- /package/dist/{chunk-SECMZACR.js.map → chunk-XUQUBZ7O.js.map} +0 -0
- /package/dist/{chunk-QHT4W3RU.js.map → chunk-ZASJ53ML.js.map} +0 -0
- /package/dist/{chunk-WUDBMLC6.js.map → chunk-ZC3HG22I.js.map} +0 -0
- /package/dist/{chunk-VCEH5UYS.js.map → chunk-ZRXSHGXT.js.map} +0 -0
|
@@ -2052,6 +2052,40 @@ interface PluginConfig {
|
|
|
2052
2052
|
* existing single-namespace behavior is unchanged. Default on.
|
|
2053
2053
|
*/
|
|
2054
2054
|
namespaceCatalogEnabled: boolean;
|
|
2055
|
+
/**
|
|
2056
|
+
* Size (bytes) at which a namespace-catalog touch triggers an in-lock
|
|
2057
|
+
* auto-compaction of `state/namespaces.jsonl` (issue #1903). The append-only
|
|
2058
|
+
* log grows one line per touch; once it exceeds this many bytes the next
|
|
2059
|
+
* touch folds it (last-record-wins, every namespace row preserved) and
|
|
2060
|
+
* atomically rewrites it. Default `16 * 1024 * 1024` (16 MB). `0` disables
|
|
2061
|
+
* auto-compaction (restores the pre-#1903 unbounded-append behavior).
|
|
2062
|
+
*/
|
|
2063
|
+
namespacesCatalogCompactBytes: number;
|
|
2064
|
+
/**
|
|
2065
|
+
* Coalescing window (ms) for pure-timestamp READ touches on an
|
|
2066
|
+
* already-known namespace record (issue #1903). Repeated `markRead` touches
|
|
2067
|
+
* that only refresh `lastReadAt` are buffered per (namespace, kind) and
|
|
2068
|
+
* flushed once per window instead of appending a line each time.
|
|
2069
|
+
* Semantically-observable touches (first sight, provenance/field changes)
|
|
2070
|
+
* always flush immediately. Default `60000`. `0` disables read coalescing
|
|
2071
|
+
* (each touch appends immediately, the pre-#1903 behavior).
|
|
2072
|
+
*/
|
|
2073
|
+
namespacesCatalogReadTouchCoalesceMs: number;
|
|
2074
|
+
/**
|
|
2075
|
+
* Coalescing window (ms) for pure-timestamp WRITE touches on an
|
|
2076
|
+
* already-known namespace record (issue #1903). Mirrors
|
|
2077
|
+
* `namespacesCatalogReadTouchCoalesceMs` for `markWrite`/`lastWriteAt`.
|
|
2078
|
+
* Default `1000`. `0` disables write coalescing.
|
|
2079
|
+
*/
|
|
2080
|
+
namespacesCatalogWriteTouchCoalesceMs: number;
|
|
2081
|
+
/**
|
|
2082
|
+
* Whether pure state-file writes (`state/buffer.json`, ledgers, indexes)
|
|
2083
|
+
* touch the namespace catalog (issue #1903). State files are not namespace
|
|
2084
|
+
* memory data, so by default their writes do NOT record a catalog touch.
|
|
2085
|
+
* Set `true` to restore the pre-#1903 behavior where every secure-file
|
|
2086
|
+
* write touched the catalog. Default `false`.
|
|
2087
|
+
*/
|
|
2088
|
+
namespacesCatalogTouchStateWrites: boolean;
|
|
2055
2089
|
defaultNamespace: string;
|
|
2056
2090
|
sharedNamespace: string;
|
|
2057
2091
|
principalFromSessionKeyMode: PrincipalFromSessionKeyMode;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { aD as AccessTrackingEntry, A as ActiveRecallChatType, f as ActiveRecallModelFallbackPolicy, d as ActiveRecallPromptStyle, c as ActiveRecallQueryMode, e as ActiveRecallThinking, a3 as AgentAccessAuthToken, bp as AgentAccessHttpConfig, bq as AgentDefaultsConfig, br as AgentPersona, r as AgentPersonaModelConfig, bs as BehaviorLoopAdjustment, g as BehaviorLoopPolicyState, bt as BehaviorSignalDirection, B as BehaviorSignalEvent, bu as BehaviorSignalType, aW as BootstrapOptions, aX as BootstrapResult, l as BriefingActiveThread, bv as BriefingCalendarSourceError, b2 as BriefingConfig, j as BriefingFocus, i as BriefingFollowup, b3 as BriefingOpenCommitment, n as BriefingRecentEntity, m as BriefingResult, h as BriefingSections, b4 as BriefingWindow, bw as BufferEntryState, ay as BufferState, Z as BufferSurpriseEvent, o as BufferTurn, k as CalendarEvent, C as CalendarSource, bx as CaptureMode, by as ChatConfig, q as Checkpoint, bz as CodexCliReasoningEffort, bA as CodexCompactionFlushMode, b7 as CodexCompatConfig, bB as CodexConnectorConfig, aG as CodingContext, bC as CodingGraphLspConfig, a_ as CodingKnowledgeConfig, aZ as CodingModeConfig, bD as CompressionGuidelineActivationState, a5 as CompressionGuidelineOptimizerActionSummary, a4 as CompressionGuidelineOptimizerEventCounts, a6 as CompressionGuidelineOptimizerRuleUpdate, bE as CompressionGuidelineOptimizerSourceWindow, a9 as CompressionGuidelineOptimizerState, bF as ConfidenceTier, bG as ConsolidationAction, bH as ConsolidationItem, aY as ConsolidationObservation, z as ConsolidationResult, ah as ContinuityImprovementLoop, af as ContinuityIncidentCloseInput, ag as ContinuityIncidentOpenInput, ae as ContinuityIncidentRecord, bI as ContinuityIncidentState, bJ as ContinuityLoopCadence, ai as ContinuityLoopReviewInput, bK as ContinuityLoopStatus, aj as ContinuityLoopUpsertInput, bL as ContradictionScanConfig, U as ConversationThread, bM as CronConversationRecallMode, bN as CronRecallMode, b8 as DEFAULT_RECALL_DISCLOSURE, J as DaySummaryResult, bO as DreamingConfig, bP as DreamingNarrativePromptStyle, bQ as DreamsDeepSleepConfig, bR as DreamsLightSleepConfig, D as DreamsPhase, bS as DreamsPhaseStatus, bT as DreamsPhasesConfig, bU as DreamsRemConfig, a as DreamsRunResult, aH as DreamsStatusResult, bV as EngramTraceEvent, aC as EntityActivityEntry, E as EntityFile, aa as EntityMention, aB as EntityRelationship, ab as EntitySchemaDefinition, ac as EntitySchemaSectionDefinition, ad as EntityStructuredSection, aF as EntityTimelineEntry, b9 as ExtractedFact, bW as ExtractedProcedureStep, bX as ExtractedQuestion, bY as ExtractedReasoningTrace, bZ as ExtractedReasoningTraceStep, b_ as ExtractedRelationship, K as ExtractionFailureClass, b$ as ExtractionPassSource, y as ExtractionResult, F as FaithfulnessFrontmatter, aA as FileHygieneConfig, G as GatewayConfig, c0 as GitHubLiveConnectorConfig, c1 as GmailLiveConnectorConfig, c2 as GoogleDriveLiveConnectorConfig, c3 as HeartbeatConfig, c4 as HeartbeatDetectionMode, H as HourlySummary, I as IdentityInjectionMode, Y as ImportanceLevel, ak as ImportanceScore, V as LifecycleState, L as LiveConnectorsConfig, c5 as LlmTraceCallback, c6 as LlmTraceEvent, am as MemoryActionEligibilityContext, bc as MemoryActionEligibilitySource, a8 as MemoryActionEvent, c7 as MemoryActionOutcome, c8 as MemoryActionPolicyDecision, an as MemoryActionPolicyResult, c9 as MemoryActionStatus, a7 as MemoryActionType, u as MemoryCategory, M as MemoryFile, p as MemoryFrontmatter, al as MemoryIntent, x as MemoryLifecycleEvent, ao as MemoryLifecycleEventType, ap as MemoryLifecycleStateSummary, ax as MemoryLink, ca as MemoryLinkType, bd as MemoryObservation, cb as MemoryOsPresetName, w as MemoryProjectionCurrentState, be as MemoryScope, v as MemoryStatus, aE as MemorySummary, az as MetaState, cc as ModelApi, cd as ModelDefinitionConfig, ce as ModelProviderAuthMode, aq as ModelProviderConfig, cf as NamespacePolicy, ar as NativeKnowledgeConfig, cg as NativeKnowledgeFolderRuleConfig, ch as NativeKnowledgeObsidianVaultConfig, ci as NativeKnowledgeOpenClawWorkspaceConfig, cj as NotionLiveConnectorConfig, P as PluginConfig, X as PolicyClass, ck as PrincipalFromSessionKeyMode, cl as PrincipalRule, cm as ProceduralConfig, as as ProvenanceConfig, N as ProvenanceSource, aw as QmdSearchExplain, Q as QmdSearchResult, cn as QuestionEntry, bf as RECALL_DISCLOSURE_LEVELS, co as ReasoningEffort, R as RecallDisclosure, cp as RecallPipelineConfig, b as RecallPlanMode, aV as RecallSectionConfig, s as RecallTierExplain, cq as RecallTraceEvent, cr as RelevanceFeedback, at as RetrievalTier, cs as SPECULATIVE_TTL_DAYS, ct as ScopeProfileAutoPromoteConfig, aI as ScopeProfileConfig, aJ as ScopeProfileLayerId, aK as ScopeProfilePromotionTarget, cu as ScopeProfileTeamProjectConfig, cv as ScopeTeamConfig, cw as ScoredEntity, a2 as SecretRef, cx as SemanticChunkingConfigShape, S as SessionObserverBandConfig, cy as SignalLevel, au as SignalScanResult, cz as SlotBehaviorConfig, cA as SlotMismatchMode, t as SourceConnectorProvenance, av as TopicScore, T as TranscriptEntry, cB as TriggerMode, O as TrustWeights, W as VerificationState, cC as confidenceTier, bm as isRecallDisclosure } from './types-
|
|
1
|
+
export { aD as AccessTrackingEntry, A as ActiveRecallChatType, f as ActiveRecallModelFallbackPolicy, d as ActiveRecallPromptStyle, c as ActiveRecallQueryMode, e as ActiveRecallThinking, a3 as AgentAccessAuthToken, bp as AgentAccessHttpConfig, bq as AgentDefaultsConfig, br as AgentPersona, r as AgentPersonaModelConfig, bs as BehaviorLoopAdjustment, g as BehaviorLoopPolicyState, bt as BehaviorSignalDirection, B as BehaviorSignalEvent, bu as BehaviorSignalType, aW as BootstrapOptions, aX as BootstrapResult, l as BriefingActiveThread, bv as BriefingCalendarSourceError, b2 as BriefingConfig, j as BriefingFocus, i as BriefingFollowup, b3 as BriefingOpenCommitment, n as BriefingRecentEntity, m as BriefingResult, h as BriefingSections, b4 as BriefingWindow, bw as BufferEntryState, ay as BufferState, Z as BufferSurpriseEvent, o as BufferTurn, k as CalendarEvent, C as CalendarSource, bx as CaptureMode, by as ChatConfig, q as Checkpoint, bz as CodexCliReasoningEffort, bA as CodexCompactionFlushMode, b7 as CodexCompatConfig, bB as CodexConnectorConfig, aG as CodingContext, bC as CodingGraphLspConfig, a_ as CodingKnowledgeConfig, aZ as CodingModeConfig, bD as CompressionGuidelineActivationState, a5 as CompressionGuidelineOptimizerActionSummary, a4 as CompressionGuidelineOptimizerEventCounts, a6 as CompressionGuidelineOptimizerRuleUpdate, bE as CompressionGuidelineOptimizerSourceWindow, a9 as CompressionGuidelineOptimizerState, bF as ConfidenceTier, bG as ConsolidationAction, bH as ConsolidationItem, aY as ConsolidationObservation, z as ConsolidationResult, ah as ContinuityImprovementLoop, af as ContinuityIncidentCloseInput, ag as ContinuityIncidentOpenInput, ae as ContinuityIncidentRecord, bI as ContinuityIncidentState, bJ as ContinuityLoopCadence, ai as ContinuityLoopReviewInput, bK as ContinuityLoopStatus, aj as ContinuityLoopUpsertInput, bL as ContradictionScanConfig, U as ConversationThread, bM as CronConversationRecallMode, bN as CronRecallMode, b8 as DEFAULT_RECALL_DISCLOSURE, J as DaySummaryResult, bO as DreamingConfig, bP as DreamingNarrativePromptStyle, bQ as DreamsDeepSleepConfig, bR as DreamsLightSleepConfig, D as DreamsPhase, bS as DreamsPhaseStatus, bT as DreamsPhasesConfig, bU as DreamsRemConfig, a as DreamsRunResult, aH as DreamsStatusResult, bV as EngramTraceEvent, aC as EntityActivityEntry, E as EntityFile, aa as EntityMention, aB as EntityRelationship, ab as EntitySchemaDefinition, ac as EntitySchemaSectionDefinition, ad as EntityStructuredSection, aF as EntityTimelineEntry, b9 as ExtractedFact, bW as ExtractedProcedureStep, bX as ExtractedQuestion, bY as ExtractedReasoningTrace, bZ as ExtractedReasoningTraceStep, b_ as ExtractedRelationship, K as ExtractionFailureClass, b$ as ExtractionPassSource, y as ExtractionResult, F as FaithfulnessFrontmatter, aA as FileHygieneConfig, G as GatewayConfig, c0 as GitHubLiveConnectorConfig, c1 as GmailLiveConnectorConfig, c2 as GoogleDriveLiveConnectorConfig, c3 as HeartbeatConfig, c4 as HeartbeatDetectionMode, H as HourlySummary, I as IdentityInjectionMode, Y as ImportanceLevel, ak as ImportanceScore, V as LifecycleState, L as LiveConnectorsConfig, c5 as LlmTraceCallback, c6 as LlmTraceEvent, am as MemoryActionEligibilityContext, bc as MemoryActionEligibilitySource, a8 as MemoryActionEvent, c7 as MemoryActionOutcome, c8 as MemoryActionPolicyDecision, an as MemoryActionPolicyResult, c9 as MemoryActionStatus, a7 as MemoryActionType, u as MemoryCategory, M as MemoryFile, p as MemoryFrontmatter, al as MemoryIntent, x as MemoryLifecycleEvent, ao as MemoryLifecycleEventType, ap as MemoryLifecycleStateSummary, ax as MemoryLink, ca as MemoryLinkType, bd as MemoryObservation, cb as MemoryOsPresetName, w as MemoryProjectionCurrentState, be as MemoryScope, v as MemoryStatus, aE as MemorySummary, az as MetaState, cc as ModelApi, cd as ModelDefinitionConfig, ce as ModelProviderAuthMode, aq as ModelProviderConfig, cf as NamespacePolicy, ar as NativeKnowledgeConfig, cg as NativeKnowledgeFolderRuleConfig, ch as NativeKnowledgeObsidianVaultConfig, ci as NativeKnowledgeOpenClawWorkspaceConfig, cj as NotionLiveConnectorConfig, P as PluginConfig, X as PolicyClass, ck as PrincipalFromSessionKeyMode, cl as PrincipalRule, cm as ProceduralConfig, as as ProvenanceConfig, N as ProvenanceSource, aw as QmdSearchExplain, Q as QmdSearchResult, cn as QuestionEntry, bf as RECALL_DISCLOSURE_LEVELS, co as ReasoningEffort, R as RecallDisclosure, cp as RecallPipelineConfig, b as RecallPlanMode, aV as RecallSectionConfig, s as RecallTierExplain, cq as RecallTraceEvent, cr as RelevanceFeedback, at as RetrievalTier, cs as SPECULATIVE_TTL_DAYS, ct as ScopeProfileAutoPromoteConfig, aI as ScopeProfileConfig, aJ as ScopeProfileLayerId, aK as ScopeProfilePromotionTarget, cu as ScopeProfileTeamProjectConfig, cv as ScopeTeamConfig, cw as ScoredEntity, a2 as SecretRef, cx as SemanticChunkingConfigShape, S as SessionObserverBandConfig, cy as SignalLevel, au as SignalScanResult, cz as SlotBehaviorConfig, cA as SlotMismatchMode, t as SourceConnectorProvenance, av as TopicScore, T as TranscriptEntry, cB as TriggerMode, O as TrustWeights, W as VerificationState, cC as confidenceTier, bm as isRecallDisclosure } from './types-CHSXOq7s.js';
|
|
2
2
|
import './message-parts/index.js';
|
package/dist/types.js
CHANGED
package/dist/verified-recall.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
compareVerifiedEpisodeResults,
|
|
3
3
|
searchVerifiedEpisodes
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-OIFZII6J.js";
|
|
5
5
|
import "./chunk-2A3OXAP2.js";
|
|
6
6
|
import "./chunk-ZBJMUXZH.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-TRH533CA.js";
|
|
8
8
|
import "./chunk-L2B3EE7B.js";
|
|
9
9
|
import "./chunk-B3ABVQ36.js";
|
|
10
10
|
import "./chunk-5UZXUTVO.js";
|
|
@@ -15,7 +15,7 @@ import "./chunk-6CIAGZ6X.js";
|
|
|
15
15
|
import "./chunk-J6A3CX5N.js";
|
|
16
16
|
import "./chunk-4KJLYTLS.js";
|
|
17
17
|
import "./chunk-SVOZFLIQ.js";
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-G5PVJJRA.js";
|
|
19
19
|
import "./chunk-RULE4VG5.js";
|
|
20
20
|
import "./chunk-SCU65EZI.js";
|
|
21
21
|
import "./chunk-RHOZ5LLO.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remnic/core",
|
|
3
|
-
"version": "9.7.
|
|
3
|
+
"version": "9.7.12",
|
|
4
4
|
"description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -3010,7 +3010,7 @@
|
|
|
3010
3010
|
"core"
|
|
3011
3011
|
],
|
|
3012
3012
|
"peerDependencies": {
|
|
3013
|
-
"@remnic/coding-graph": "^9.7.
|
|
3013
|
+
"@remnic/coding-graph": "^9.7.12"
|
|
3014
3014
|
},
|
|
3015
3015
|
"peerDependenciesMeta": {
|
|
3016
3016
|
"@remnic/coding-graph": {
|
package/src/config.test.ts
CHANGED
|
@@ -2161,3 +2161,47 @@ test("parseConfig rejects non-positive extraction retry/breaker numerics and fal
|
|
|
2161
2161
|
assert.equal(c.extractionBreakerAuthCooldownMs, 1_800_000, "non-positive auth cooldown -> default");
|
|
2162
2162
|
assert.deepEqual(c.extractionRetryScheduleMs, [60_000, 300_000, 1_800_000, 7_200_000], "schedule with non-positive entry -> default");
|
|
2163
2163
|
});
|
|
2164
|
+
|
|
2165
|
+
test("parseConfig namespace-catalog touch-path knobs: defaults, 0-accepting numerics, and validation (#1903)", () => {
|
|
2166
|
+
// Documented defaults when absent.
|
|
2167
|
+
const d = parseConfig({});
|
|
2168
|
+
assert.equal(d.namespacesCatalogCompactBytes, 16 * 1024 * 1024, "compactBytes default 16 MB");
|
|
2169
|
+
assert.equal(d.namespacesCatalogReadTouchCoalesceMs, 60_000, "read coalesce default 60000ms");
|
|
2170
|
+
assert.equal(d.namespacesCatalogWriteTouchCoalesceMs, 1_000, "write coalesce default 1000ms");
|
|
2171
|
+
assert.equal(d.namespacesCatalogTouchStateWrites, false, "state-write touch default false");
|
|
2172
|
+
|
|
2173
|
+
// 0 is an accepted disable switch for every numeric (resolveNonNegativeIntegerConfig).
|
|
2174
|
+
assert.equal(parseConfig({ namespacesCatalogCompactBytes: 0 }).namespacesCatalogCompactBytes, 0);
|
|
2175
|
+
assert.equal(parseConfig({ namespacesCatalogReadTouchCoalesceMs: 0 }).namespacesCatalogReadTouchCoalesceMs, 0);
|
|
2176
|
+
assert.equal(parseConfig({ namespacesCatalogWriteTouchCoalesceMs: 0 }).namespacesCatalogWriteTouchCoalesceMs, 0);
|
|
2177
|
+
|
|
2178
|
+
// Positive integers pass through; CLI/env numeric strings coerce.
|
|
2179
|
+
assert.equal(parseConfig({ namespacesCatalogCompactBytes: 4096 }).namespacesCatalogCompactBytes, 4096);
|
|
2180
|
+
assert.equal(parseConfig({ namespacesCatalogReadTouchCoalesceMs: "30000" }).namespacesCatalogReadTouchCoalesceMs, 30_000);
|
|
2181
|
+
|
|
2182
|
+
// Boolean-like coercion for the state-write toggle (gotcha #36).
|
|
2183
|
+
assert.equal(parseConfig({ namespacesCatalogTouchStateWrites: true }).namespacesCatalogTouchStateWrites, true);
|
|
2184
|
+
assert.equal(parseConfig({ namespacesCatalogTouchStateWrites: "true" }).namespacesCatalogTouchStateWrites, true);
|
|
2185
|
+
assert.equal(parseConfig({ namespacesCatalogTouchStateWrites: "off" }).namespacesCatalogTouchStateWrites, false);
|
|
2186
|
+
|
|
2187
|
+
// Negative and non-integer numerics are rejected with the documented message.
|
|
2188
|
+
for (const key of [
|
|
2189
|
+
"namespacesCatalogCompactBytes",
|
|
2190
|
+
"namespacesCatalogReadTouchCoalesceMs",
|
|
2191
|
+
"namespacesCatalogWriteTouchCoalesceMs",
|
|
2192
|
+
]) {
|
|
2193
|
+
for (const bad of [-1, 1.5, "1.5", "abc", Number.NaN, Infinity]) {
|
|
2194
|
+
assert.throws(
|
|
2195
|
+
() => parseConfig({ [key]: bad }),
|
|
2196
|
+
new RegExp(`${key} must be a non-negative integer`),
|
|
2197
|
+
`${key}=${JSON.stringify(bad)} should throw`,
|
|
2198
|
+
);
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
|
|
2202
|
+
// A present-but-malformed boolean toggle fails fast (gotcha #51).
|
|
2203
|
+
assert.throws(
|
|
2204
|
+
() => parseConfig({ namespacesCatalogTouchStateWrites: "maybe" }),
|
|
2205
|
+
/namespacesCatalogTouchStateWrites must be a boolean-like value/,
|
|
2206
|
+
);
|
|
2207
|
+
});
|
package/src/config.ts
CHANGED
|
@@ -435,6 +435,26 @@ function resolvePositiveIntegerConfig(
|
|
|
435
435
|
return coerced;
|
|
436
436
|
}
|
|
437
437
|
|
|
438
|
+
function resolveNonNegativeIntegerConfig(
|
|
439
|
+
value: unknown,
|
|
440
|
+
defaultValue: number,
|
|
441
|
+
keyName: string,
|
|
442
|
+
): number {
|
|
443
|
+
if (value === undefined || value === null) return defaultValue;
|
|
444
|
+
const coerced = coerceNumber(value);
|
|
445
|
+
if (
|
|
446
|
+
coerced === undefined ||
|
|
447
|
+
!Number.isFinite(coerced) ||
|
|
448
|
+
!Number.isInteger(coerced) ||
|
|
449
|
+
coerced < 0
|
|
450
|
+
) {
|
|
451
|
+
throw new Error(
|
|
452
|
+
`${keyName} must be a non-negative integer; got ${JSON.stringify(value)}`,
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
return coerced;
|
|
456
|
+
}
|
|
457
|
+
|
|
438
458
|
export function isOpenaiApiKeyDisabled(value: unknown): boolean {
|
|
439
459
|
return value === false || (typeof value === "string" && value.trim().toLowerCase() === "false");
|
|
440
460
|
}
|
|
@@ -2934,6 +2954,29 @@ export function parseConfig(
|
|
|
2934
2954
|
// silently defaulting to enabled (CLAUDE.md rule #51); default to enabled
|
|
2935
2955
|
// only when the value is absent.
|
|
2936
2956
|
namespaceCatalogEnabled: resolveNamespaceCatalogEnabled(cfg.namespaceCatalogEnabled, rawOperatorConfig, runtimeSet),
|
|
2957
|
+
// Namespace catalog touch-path performance knobs (issue #1903). Numerics use
|
|
2958
|
+
// resolveNonNegativeIntegerConfig so 0 is an accepted disable switch; a
|
|
2959
|
+
// present-but-invalid value (negative/non-integer) is REJECTED (rule #51).
|
|
2960
|
+
namespacesCatalogCompactBytes: resolveNonNegativeIntegerConfig(
|
|
2961
|
+
cfg.namespacesCatalogCompactBytes,
|
|
2962
|
+
16 * 1024 * 1024,
|
|
2963
|
+
"namespacesCatalogCompactBytes",
|
|
2964
|
+
),
|
|
2965
|
+
namespacesCatalogReadTouchCoalesceMs: resolveNonNegativeIntegerConfig(
|
|
2966
|
+
cfg.namespacesCatalogReadTouchCoalesceMs,
|
|
2967
|
+
60_000,
|
|
2968
|
+
"namespacesCatalogReadTouchCoalesceMs",
|
|
2969
|
+
),
|
|
2970
|
+
namespacesCatalogWriteTouchCoalesceMs: resolveNonNegativeIntegerConfig(
|
|
2971
|
+
cfg.namespacesCatalogWriteTouchCoalesceMs,
|
|
2972
|
+
1_000,
|
|
2973
|
+
"namespacesCatalogWriteTouchCoalesceMs",
|
|
2974
|
+
),
|
|
2975
|
+
namespacesCatalogTouchStateWrites: resolveBooleanConfig(
|
|
2976
|
+
cfg.namespacesCatalogTouchStateWrites,
|
|
2977
|
+
false,
|
|
2978
|
+
"namespacesCatalogTouchStateWrites",
|
|
2979
|
+
),
|
|
2937
2980
|
// NOTE: namespace identifiers are intentionally NOT sanitized here — the
|
|
2938
2981
|
// codebase rejects unsafe namespaces at the point of use (see
|
|
2939
2982
|
// codex-materialize-runner and NamespaceStorageRouter / resolveNamespaceDir),
|
|
@@ -3694,3 +3694,261 @@ test("router resolve-hook serializer recovers after a prior hook rejects (issue
|
|
|
3694
3694
|
await rm(memoryDir, { recursive: true, force: true });
|
|
3695
3695
|
}
|
|
3696
3696
|
});
|
|
3697
|
+
|
|
3698
|
+
// ── Issue #1903: touch-path performance (auto-compaction, coalescing, streaming) ──
|
|
3699
|
+
|
|
3700
|
+
async function countCatalogLines(memoryDir: string): Promise<number> {
|
|
3701
|
+
const raw = await readFile(path.join(memoryDir, "state", "namespaces.jsonl"), "utf8").catch(() => "");
|
|
3702
|
+
return raw.split("\n").filter((line) => line.trim().length > 0).length;
|
|
3703
|
+
}
|
|
3704
|
+
|
|
3705
|
+
// 1. Warm cache: with coalescing OFF every touch appends, but a warm cache means
|
|
3706
|
+
// none of them re-parses the JSONL after the initial warm-up parse.
|
|
3707
|
+
test("#1903 warm cache: repeated touches never re-parse the log (coalescing off)", async () => {
|
|
3708
|
+
const memoryDir = await mkMemoryDir();
|
|
3709
|
+
try {
|
|
3710
|
+
const catalog = new CountingNamespaceCatalog(
|
|
3711
|
+
makeConfig(memoryDir, {
|
|
3712
|
+
namespacesCatalogReadTouchCoalesceMs: 0,
|
|
3713
|
+
namespacesCatalogWriteTouchCoalesceMs: 0,
|
|
3714
|
+
}),
|
|
3715
|
+
);
|
|
3716
|
+
// Warm the cache: the first write creates the file; a read then performs the
|
|
3717
|
+
// one-time full parse and warms the in-process cache.
|
|
3718
|
+
await catalog.markWrite("alpha", { discoveredBy: "write" });
|
|
3719
|
+
await catalog.listNamespaces();
|
|
3720
|
+
const warm = catalog.catalogReadCount;
|
|
3721
|
+
assert.ok(warm >= 1, "the warm-up performed at least one full parse");
|
|
3722
|
+
for (let i = 0; i < 25; i++) {
|
|
3723
|
+
await catalog.markWrite("alpha", { discoveredBy: "write" });
|
|
3724
|
+
await catalog.markRead("alpha", { discoveredBy: "read" });
|
|
3725
|
+
}
|
|
3726
|
+
assert.equal(
|
|
3727
|
+
catalog.catalogReadCount,
|
|
3728
|
+
warm,
|
|
3729
|
+
"every subsequent touch is served from the warm cache without a re-parse",
|
|
3730
|
+
);
|
|
3731
|
+
} finally {
|
|
3732
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
3733
|
+
}
|
|
3734
|
+
});
|
|
3735
|
+
|
|
3736
|
+
// 2. Write-touch coalescing collapses many in-window writes into a single append,
|
|
3737
|
+
// and the newest buffered timestamp wins on flush.
|
|
3738
|
+
test("#1903 write-touch coalescing collapses 50 in-window writes to one append", async () => {
|
|
3739
|
+
const memoryDir = await mkMemoryDir();
|
|
3740
|
+
try {
|
|
3741
|
+
const catalog = new NamespaceCatalog(
|
|
3742
|
+
makeConfig(memoryDir, { namespacesCatalogWriteTouchCoalesceMs: 60_000 }),
|
|
3743
|
+
);
|
|
3744
|
+
// Seed the record, then read it back so the in-process cache is warm — the
|
|
3745
|
+
// following writes are then pure-timestamp refreshes on a known record and
|
|
3746
|
+
// are deferred (a cold cache would force the first one to flush immediately).
|
|
3747
|
+
await catalog.markWrite("alpha", { discoveredBy: "write" });
|
|
3748
|
+
await catalog.getNamespaceRecord("alpha");
|
|
3749
|
+
const linesAfterSeed = await countCatalogLines(memoryDir);
|
|
3750
|
+
let newest = new Date();
|
|
3751
|
+
for (let i = 0; i < 50; i++) {
|
|
3752
|
+
newest = new Date(Date.now() + (i + 1) * 1000);
|
|
3753
|
+
await catalog.markWrite("alpha", { discoveredBy: "write", at: newest });
|
|
3754
|
+
}
|
|
3755
|
+
assert.equal(
|
|
3756
|
+
await countCatalogLines(memoryDir),
|
|
3757
|
+
linesAfterSeed,
|
|
3758
|
+
"coalesced writes stay buffered — no per-touch append",
|
|
3759
|
+
);
|
|
3760
|
+
await catalog.flushPendingTouches();
|
|
3761
|
+
assert.equal(
|
|
3762
|
+
await countCatalogLines(memoryDir),
|
|
3763
|
+
linesAfterSeed + 1,
|
|
3764
|
+
"the 50 buffered writes collapse into exactly one append on flush",
|
|
3765
|
+
);
|
|
3766
|
+
const record = await catalog.getNamespaceRecord("alpha");
|
|
3767
|
+
assert.equal(
|
|
3768
|
+
record?.lastWriteAt,
|
|
3769
|
+
newest.toISOString(),
|
|
3770
|
+
"the newest in-window write timestamp wins",
|
|
3771
|
+
);
|
|
3772
|
+
} finally {
|
|
3773
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
3774
|
+
}
|
|
3775
|
+
});
|
|
3776
|
+
|
|
3777
|
+
// 3. Read-touch coalescing collapses in-window reads and keeps the latest freshness.
|
|
3778
|
+
test("#1903 read-touch coalescing keeps the latest in-window lastReadAt", async () => {
|
|
3779
|
+
const memoryDir = await mkMemoryDir();
|
|
3780
|
+
try {
|
|
3781
|
+
const catalog = new NamespaceCatalog(
|
|
3782
|
+
makeConfig(memoryDir, { namespacesCatalogReadTouchCoalesceMs: 60_000 }),
|
|
3783
|
+
);
|
|
3784
|
+
// Seed the read field, then warm the cache so the following reads defer.
|
|
3785
|
+
await catalog.markRead("alpha", { discoveredBy: "read" });
|
|
3786
|
+
await catalog.getNamespaceRecord("alpha");
|
|
3787
|
+
const linesAfterSeed = await countCatalogLines(memoryDir);
|
|
3788
|
+
let newest = new Date();
|
|
3789
|
+
for (let i = 0; i < 30; i++) {
|
|
3790
|
+
newest = new Date(Date.now() + (i + 1) * 1000);
|
|
3791
|
+
await catalog.markRead("alpha", { discoveredBy: "read", at: newest });
|
|
3792
|
+
}
|
|
3793
|
+
assert.equal(
|
|
3794
|
+
await countCatalogLines(memoryDir),
|
|
3795
|
+
linesAfterSeed,
|
|
3796
|
+
"coalesced reads stay buffered — no per-touch append",
|
|
3797
|
+
);
|
|
3798
|
+
await catalog.flushPendingTouches();
|
|
3799
|
+
assert.equal(await countCatalogLines(memoryDir), linesAfterSeed + 1);
|
|
3800
|
+
const record = await catalog.getNamespaceRecord("alpha");
|
|
3801
|
+
assert.equal(
|
|
3802
|
+
record?.lastReadAt,
|
|
3803
|
+
newest.toISOString(),
|
|
3804
|
+
"the newest in-window read timestamp wins",
|
|
3805
|
+
);
|
|
3806
|
+
} finally {
|
|
3807
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
3808
|
+
}
|
|
3809
|
+
});
|
|
3810
|
+
|
|
3811
|
+
// 4. Provenance upgrade under coalescing: a config pre-registration followed by a
|
|
3812
|
+
// write must read back "write" WITHOUT an explicit flush (immediate-flush rule).
|
|
3813
|
+
test("#1903 markWrite upgrades config→write under coalescing without an explicit flush", async () => {
|
|
3814
|
+
const memoryDir = await mkMemoryDir();
|
|
3815
|
+
try {
|
|
3816
|
+
const catalog = new NamespaceCatalog(
|
|
3817
|
+
makeConfig(memoryDir, {
|
|
3818
|
+
namespacesCatalogReadTouchCoalesceMs: 60_000,
|
|
3819
|
+
namespacesCatalogWriteTouchCoalesceMs: 60_000,
|
|
3820
|
+
}),
|
|
3821
|
+
);
|
|
3822
|
+
const ns = "project-origin-prov";
|
|
3823
|
+
const storageDir = path.join(memoryDir, "namespaces", namespaceIdentityToken(ns));
|
|
3824
|
+
await catalog.registerResolved(ns, storageDir);
|
|
3825
|
+
assert.equal(
|
|
3826
|
+
(await catalog.getNamespaceRecord(ns))?.discoveredBy,
|
|
3827
|
+
"config",
|
|
3828
|
+
"pre-registration is discovered by config",
|
|
3829
|
+
);
|
|
3830
|
+
// A real write must upgrade the provenance immediately even with coalescing on.
|
|
3831
|
+
await catalog.markWrite(ns, { discoveredBy: "write", storageDir });
|
|
3832
|
+
assert.equal(
|
|
3833
|
+
(await catalog.getNamespaceRecord(ns))?.discoveredBy,
|
|
3834
|
+
"write",
|
|
3835
|
+
"the config→write upgrade flushes immediately (not coalesced away)",
|
|
3836
|
+
);
|
|
3837
|
+
} finally {
|
|
3838
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
3839
|
+
}
|
|
3840
|
+
});
|
|
3841
|
+
|
|
3842
|
+
// 5. Zero-limit semantics: CompactBytes=0 never rewrites and CoalesceMs=0 appends
|
|
3843
|
+
// one line per touch (line count == touch count) — the pre-#1903 behavior.
|
|
3844
|
+
test("#1903 zero knobs restore append-per-touch with no compaction", async () => {
|
|
3845
|
+
const memoryDir = await mkMemoryDir();
|
|
3846
|
+
try {
|
|
3847
|
+
const catalog = new NamespaceCatalog(
|
|
3848
|
+
makeConfig(memoryDir, {
|
|
3849
|
+
namespacesCatalogCompactBytes: 0,
|
|
3850
|
+
namespacesCatalogReadTouchCoalesceMs: 0,
|
|
3851
|
+
namespacesCatalogWriteTouchCoalesceMs: 0,
|
|
3852
|
+
}),
|
|
3853
|
+
);
|
|
3854
|
+
const touches = 12;
|
|
3855
|
+
for (let i = 0; i < touches; i++) {
|
|
3856
|
+
await catalog.markWrite("alpha", { discoveredBy: "write" });
|
|
3857
|
+
}
|
|
3858
|
+
assert.equal(
|
|
3859
|
+
await countCatalogLines(memoryDir),
|
|
3860
|
+
touches,
|
|
3861
|
+
"no coalescing and no compaction → exactly one append per touch",
|
|
3862
|
+
);
|
|
3863
|
+
} finally {
|
|
3864
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
3865
|
+
}
|
|
3866
|
+
});
|
|
3867
|
+
|
|
3868
|
+
// 6. Auto-compaction bounds the log to one row per namespace and preserves every
|
|
3869
|
+
// namespace with its newest fields. A tiny limit forces compaction on each touch.
|
|
3870
|
+
test("#1903 auto-compaction bounds the log to one row per namespace and preserves all", async () => {
|
|
3871
|
+
const memoryDir = await mkMemoryDir();
|
|
3872
|
+
try {
|
|
3873
|
+
const catalog = new NamespaceCatalog(
|
|
3874
|
+
makeConfig(memoryDir, {
|
|
3875
|
+
namespacesCatalogCompactBytes: 100,
|
|
3876
|
+
namespacesCatalogReadTouchCoalesceMs: 0,
|
|
3877
|
+
namespacesCatalogWriteTouchCoalesceMs: 0,
|
|
3878
|
+
}),
|
|
3879
|
+
);
|
|
3880
|
+
const namespaces = [
|
|
3881
|
+
"project-origin-a",
|
|
3882
|
+
"project-origin-b",
|
|
3883
|
+
"project-origin-c",
|
|
3884
|
+
"project-origin-d",
|
|
3885
|
+
"project-origin-e",
|
|
3886
|
+
];
|
|
3887
|
+
const newest = new Map<string, string>();
|
|
3888
|
+
for (let round = 0; round < 20; round++) {
|
|
3889
|
+
for (const ns of namespaces) {
|
|
3890
|
+
const at = new Date(Date.now() + (round * namespaces.length + namespaces.indexOf(ns)) * 1000);
|
|
3891
|
+
newest.set(ns, at.toISOString());
|
|
3892
|
+
await catalog.markWrite(ns, { discoveredBy: "write", at });
|
|
3893
|
+
}
|
|
3894
|
+
}
|
|
3895
|
+
assert.equal(
|
|
3896
|
+
await countCatalogLines(memoryDir),
|
|
3897
|
+
namespaces.length,
|
|
3898
|
+
"the log is bounded to exactly one row per namespace after compaction",
|
|
3899
|
+
);
|
|
3900
|
+
const list = await catalog.listNamespaces();
|
|
3901
|
+
for (const ns of namespaces) {
|
|
3902
|
+
const record = list.find((r) => r.namespace === ns);
|
|
3903
|
+
assert.ok(record, `namespace ${ns} survives compaction`);
|
|
3904
|
+
assert.equal(
|
|
3905
|
+
record?.lastWriteAt,
|
|
3906
|
+
newest.get(ns),
|
|
3907
|
+
`namespace ${ns} keeps its newest write timestamp through compaction`,
|
|
3908
|
+
);
|
|
3909
|
+
}
|
|
3910
|
+
} finally {
|
|
3911
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
3912
|
+
}
|
|
3913
|
+
});
|
|
3914
|
+
|
|
3915
|
+
// 7. Cross-process cache-coherence: compaction on one instance must never drop
|
|
3916
|
+
// another instance's rows (mirrors the rebuild-race tests). A third fresh
|
|
3917
|
+
// instance must read back every namespace touched by either.
|
|
3918
|
+
test("#1903 cross-instance compaction never drops another instance's rows", async () => {
|
|
3919
|
+
const memoryDir = await mkMemoryDir();
|
|
3920
|
+
try {
|
|
3921
|
+
const cfg = () =>
|
|
3922
|
+
makeConfig(memoryDir, {
|
|
3923
|
+
namespacesCatalogCompactBytes: 100,
|
|
3924
|
+
namespacesCatalogReadTouchCoalesceMs: 0,
|
|
3925
|
+
namespacesCatalogWriteTouchCoalesceMs: 0,
|
|
3926
|
+
});
|
|
3927
|
+
// Separate instances behave like separate processes (own lock owner id).
|
|
3928
|
+
const a = new NamespaceCatalog(cfg());
|
|
3929
|
+
const b = new NamespaceCatalog(cfg());
|
|
3930
|
+
const written = new Set<string>();
|
|
3931
|
+
for (let round = 0; round < 8; round++) {
|
|
3932
|
+
const nsA = `project-origin-a${round}`;
|
|
3933
|
+
const nsB = `project-origin-b${round}`;
|
|
3934
|
+
written.add(nsA);
|
|
3935
|
+
written.add(nsB);
|
|
3936
|
+
// Interleave: A appends a fresh namespace while B triggers a compaction of
|
|
3937
|
+
// the shared log. The cross-process lock serializes the two.
|
|
3938
|
+
await Promise.all([
|
|
3939
|
+
a.markWrite(nsA, { discoveredBy: "write" }),
|
|
3940
|
+
b.markWrite(nsB, { discoveredBy: "write" }),
|
|
3941
|
+
]);
|
|
3942
|
+
}
|
|
3943
|
+
const fresh = new NamespaceCatalog(makeConfig(memoryDir));
|
|
3944
|
+
const list = await fresh.listNamespaces();
|
|
3945
|
+
for (const ns of written) {
|
|
3946
|
+
assert.ok(
|
|
3947
|
+
list.some((r) => r.namespace === ns),
|
|
3948
|
+
`namespace ${ns} must survive cross-instance interleaved compaction`,
|
|
3949
|
+
);
|
|
3950
|
+
}
|
|
3951
|
+
} finally {
|
|
3952
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
3953
|
+
}
|
|
3954
|
+
});
|