Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2365,9 +2365,14 @@ const memoryLanceDBProPlugin = {
// effect when a delete genuinely happens inside this same plugin instance.
//
// The actual cross-process staleness bound comes from two other layers:
// - DEFAULT_REFLECTION_CACHE_TTL_MS bounds how long either cache below can
// serve stale content after ANY delete, same-process or not (see the read
// sites in loadAgentReflectionSlices and the derived-focus injector).
// - DEFAULT_REFLECTION_CACHE_TTL_MS bounds staleness measured from the
// LAST DB READ, not from cache priming: the derived-focus injector
// falls back to loadAgentReflectionSlices when its session cache is
// stale, and that fallback keeps its own independently-clocked TTL
// cache. Two caches in series mean a delete can keep being served for
// up to one full TTL after whichever cache last re-read the DB (see
// the read sites in loadAgentReflectionSlices and the derived-focus
// injector).
// - readConsistencyInterval (store config) bounds how long the underlying
// LanceDB table handle can serve stale rows to a fresh query in the first
// place, which is what a TTL-expired cache re-populates from.
Expand Down Expand Up @@ -4734,6 +4739,10 @@ const memoryLanceDBProPlugin = {
}
}
if (reflectionStoreToLanceDB) {
// Mirror of loadAgentReflectionSlices' TOCTOU guard: a delete's
// invalidation while the awaits below are in flight must not be
// undone by the late reflectionDerivedBySession.set further down.
const derivedGenerationAtStart = reflectionByAgentCacheGeneration.count;
const stored = await storeReflectionToLanceDB({
reflectionText,
sessionKey,
Expand Down Expand Up @@ -4763,7 +4772,10 @@ const memoryLanceDBProPlugin = {
}
: undefined,
});
if (sessionKey && stored.slices.derived.length > 0 && !isSessionBoundaryReflectionAction(action)) {
if (sessionKey &&
stored.slices.derived.length > 0 &&
!isSessionBoundaryReflectionAction(action) &&
reflectionByAgentCacheGeneration.count === derivedGenerationAtStart) {
reflectionDerivedBySession.set(sessionKey, {
// Deliberately Date.now(), not nowTs (which mirrors the host-supplied
// event.timestamp and can be skewed/future-dated): this field is a TTL
Expand Down
22 changes: 18 additions & 4 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3182,9 +3182,14 @@ const memoryLanceDBProPlugin = {
// effect when a delete genuinely happens inside this same plugin instance.
//
// The actual cross-process staleness bound comes from two other layers:
// - DEFAULT_REFLECTION_CACHE_TTL_MS bounds how long either cache below can
// serve stale content after ANY delete, same-process or not (see the read
// sites in loadAgentReflectionSlices and the derived-focus injector).
// - DEFAULT_REFLECTION_CACHE_TTL_MS bounds staleness measured from the
// LAST DB READ, not from cache priming: the derived-focus injector
// falls back to loadAgentReflectionSlices when its session cache is
// stale, and that fallback keeps its own independently-clocked TTL
// cache. Two caches in series mean a delete can keep being served for
// up to one full TTL after whichever cache last re-read the DB (see
// the read sites in loadAgentReflectionSlices and the derived-focus
// injector).
// - readConsistencyInterval (store config) bounds how long the underlying
// LanceDB table handle can serve stale rows to a fresh query in the first
// place, which is what a TTL-expired cache re-populates from.
Expand Down Expand Up @@ -5979,6 +5984,10 @@ const memoryLanceDBProPlugin = {
}

if (reflectionStoreToLanceDB) {
// Mirror of loadAgentReflectionSlices' TOCTOU guard: a delete's
// invalidation while the awaits below are in flight must not be
// undone by the late reflectionDerivedBySession.set further down.
const derivedGenerationAtStart = reflectionByAgentCacheGeneration.count;
const stored = await storeReflectionToLanceDB({
reflectionText,
sessionKey,
Expand Down Expand Up @@ -6012,7 +6021,12 @@ const memoryLanceDBProPlugin = {
}
: undefined,
});
if (sessionKey && stored.slices.derived.length > 0 && !isSessionBoundaryReflectionAction(action)) {
if (
sessionKey &&
stored.slices.derived.length > 0 &&
!isSessionBoundaryReflectionAction(action) &&
reflectionByAgentCacheGeneration.count === derivedGenerationAtStart
) {
reflectionDerivedBySession.set(sessionKey, {
// Deliberately Date.now(), not nowTs (which mirrors the host-supplied
// event.timestamp and can be skewed/future-dated): this field is a TTL
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"skills/**/*.md"
],
"scripts": {
"test": "node test/embedder-error-hints.test.mjs && node --test test/embedder-max-input-chars.test.mjs && node test/cjk-recursion-regression.test.mjs && node test/extraction-prompt-structural-noise.test.mjs && node test/i18n-memory-triggers.test.mjs && node test/migrate-legacy-schema.test.mjs && node --test test/config-session-strategy-migration.test.mjs && node --test test/scope-access-undefined.test.mjs && node --test test/reflection-bypass-hook.test.mjs && node --test test/reflection-unattributed-session-read.test.mjs && node --test test/smart-extractor-scope-filter.test.mjs && node --test test/store-empty-scope-filter.test.mjs && node --test test/recall-text-cleanup.test.mjs && node test/update-consistency-lancedb.test.mjs && node --test test/strip-envelope-metadata.test.mjs && node test/cli-smoke.mjs && node test/functional-e2e.mjs && node --test test/per-agent-auto-recall.test.mjs && node test/retriever-rerank-regression.mjs && node test/smart-memory-lifecycle.mjs && node test/smart-extractor-branches.mjs && node --test test/smart-extractor-noise-gating.test.mjs && node test/memory-capability-runtime.test.mjs && node --test test/startup-health-diagnostics.test.mjs && node test/corpus-indexer.test.mjs && node --test test/regex-fallback-bulk-store.test.mjs && node test/plugin-manifest-regression.mjs && node --test test/dreaming-engine.test.mjs && node --test test/session-summary-before-reset.test.mjs && node --test test/sync-plugin-version.test.mjs && node test/smart-metadata-v2.mjs && node test/vector-search-cosine.test.mjs && node test/context-support-e2e.mjs && node test/temporal-facts.test.mjs && node test/memory-update-supersede.test.mjs && node test/memory-update-metadata-refresh.test.mjs && node test/memory-upgrader-diagnostics.test.mjs && node --test test/llm-api-key-client.test.mjs && node --test test/llm-oauth-client.test.mjs && node --test test/cli-oauth-login.test.mjs && node --test test/workflow-fork-guards.test.mjs && node --test test/clawteam-scope.test.mjs && node --test test/cross-process-lock.test.mjs && node --test test/preference-slots.test.mjs && node test/is-latest-auto-supersede.test.mjs && node --test test/temporal-awareness.test.mjs && node --test test/command-reflection-guard.test.mjs && node --test test/tier1-counters.test.mjs && node --test test/startup-check-timeout.test.mjs && node --test test/memory-subsession-prompt-hooks.test.mjs && node --test test/read-consistency-interval.test.mjs && node --test test/reflection-distiller-hook-skip.test.mjs && node --test test/register-scope-dedup.test.mjs && node --test test/raw-run-distiller-hooks.test.mjs && node --test test/autocapture-watermark-reset.test.mjs && node --test test/autocapture-internal-session-guard.test.mjs && node --test test/memory-categories-storage-map.test.mjs && node --test test/delete-invalidate-reflection-caches.test.mjs && node --test test/reflection-mapped-rows-admission.test.mjs && node --test test/smart-metadata-source-classification.test.mjs && node --test test/reflection-embed-transient-retry.test.mjs && node --test test/scope-owner-leak-hardening.test.mjs && node --test test/isOwnedByAgent.test.mjs && node --test test/typed-array-vector-fetch.test.mjs && node --test test/extraction-grounding-register.test.mjs && node test/grounding-rejudge.test.mjs && node --test test/reverse-map-legacy-category.test.mjs && node --test test/reflection-mapped-category-stamping.test.mjs && node --test test/memory-upgrader-category-normalization.test.mjs && node --test test/autocapture-fallback-gating.test.mjs && node --test test/prompt-architecture.test.mjs && node test/extraction-category-rubric.test.mjs && node --test test/admission-control-batch-utility.test.mjs && node --test test/smart-extractor-batch-admission.test.mjs && node --test test/admission-control-prompt-shape.test.mjs && node --test test/smart-extractor-merge-accounting.test.mjs && node --test test/admission-utility-veto.test.mjs && node --test test/cli-subcommand-attachment.test.mjs && node --test test/admission-lane-model-affinity.test.mjs && node --test test/admission-model-resolution.test.mjs && node --test test/admission-controller-standalone.test.mjs && node --test test/smart-extractor-admission-controller-injection.test.mjs && node --test test/admission-without-smart-extraction.test.mjs && node --test test/llm-thinklevel.test.mjs && node --test test/memory-id-prefix-resolution.test.mjs && node --test test/manual-store-supersede.test.mjs && node --test test/extraction-transcript-speaker-tags.test.mjs && node --test test/session-compressor.test.mjs",
"test": "node test/embedder-error-hints.test.mjs && node --test test/embedder-max-input-chars.test.mjs && node test/cjk-recursion-regression.test.mjs && node test/extraction-prompt-structural-noise.test.mjs && node test/i18n-memory-triggers.test.mjs && node test/migrate-legacy-schema.test.mjs && node --test test/config-session-strategy-migration.test.mjs && node --test test/scope-access-undefined.test.mjs && node --test test/reflection-bypass-hook.test.mjs && node --test test/reflection-unattributed-session-read.test.mjs && node --test test/smart-extractor-scope-filter.test.mjs && node --test test/store-empty-scope-filter.test.mjs && node --test test/recall-text-cleanup.test.mjs && node test/update-consistency-lancedb.test.mjs && node --test test/strip-envelope-metadata.test.mjs && node test/cli-smoke.mjs && node test/functional-e2e.mjs && node --test test/per-agent-auto-recall.test.mjs && node test/retriever-rerank-regression.mjs && node test/smart-memory-lifecycle.mjs && node test/smart-extractor-branches.mjs && node --test test/smart-extractor-noise-gating.test.mjs && node test/memory-capability-runtime.test.mjs && node --test test/startup-health-diagnostics.test.mjs && node test/corpus-indexer.test.mjs && node --test test/regex-fallback-bulk-store.test.mjs && node test/plugin-manifest-regression.mjs && node --test test/dreaming-engine.test.mjs && node --test test/session-summary-before-reset.test.mjs && node --test test/sync-plugin-version.test.mjs && node test/smart-metadata-v2.mjs && node test/vector-search-cosine.test.mjs && node test/context-support-e2e.mjs && node test/temporal-facts.test.mjs && node test/memory-update-supersede.test.mjs && node test/memory-update-metadata-refresh.test.mjs && node test/memory-upgrader-diagnostics.test.mjs && node --test test/llm-api-key-client.test.mjs && node --test test/llm-oauth-client.test.mjs && node --test test/cli-oauth-login.test.mjs && node --test test/workflow-fork-guards.test.mjs && node --test test/clawteam-scope.test.mjs && node --test test/cross-process-lock.test.mjs && node --test test/preference-slots.test.mjs && node test/is-latest-auto-supersede.test.mjs && node --test test/temporal-awareness.test.mjs && node --test test/command-reflection-guard.test.mjs && node --test test/tier1-counters.test.mjs && node --test test/startup-check-timeout.test.mjs && node --test test/memory-subsession-prompt-hooks.test.mjs && node --test test/read-consistency-interval.test.mjs && node --test test/reflection-distiller-hook-skip.test.mjs && node --test test/register-scope-dedup.test.mjs && node --test test/raw-run-distiller-hooks.test.mjs && node --test test/autocapture-watermark-reset.test.mjs && node --test test/autocapture-internal-session-guard.test.mjs && node --test test/memory-categories-storage-map.test.mjs && node --test test/delete-invalidate-reflection-caches.test.mjs && node --test test/reflection-mapped-rows-admission.test.mjs && node --test test/smart-metadata-source-classification.test.mjs && node --test test/reflection-embed-transient-retry.test.mjs && node --test test/scope-owner-leak-hardening.test.mjs && node --test test/isOwnedByAgent.test.mjs && node --test test/typed-array-vector-fetch.test.mjs && node --test test/extraction-grounding-register.test.mjs && node test/grounding-rejudge.test.mjs && node --test test/reverse-map-legacy-category.test.mjs && node --test test/reflection-mapped-category-stamping.test.mjs && node --test test/memory-upgrader-category-normalization.test.mjs && node --test test/autocapture-fallback-gating.test.mjs && node --test test/prompt-architecture.test.mjs && node test/extraction-category-rubric.test.mjs && node --test test/admission-control-batch-utility.test.mjs && node --test test/smart-extractor-batch-admission.test.mjs && node --test test/admission-control-prompt-shape.test.mjs && node --test test/smart-extractor-merge-accounting.test.mjs && node --test test/admission-utility-veto.test.mjs && node --test test/cli-subcommand-attachment.test.mjs && node --test test/admission-lane-model-affinity.test.mjs && node --test test/admission-model-resolution.test.mjs && node --test test/admission-controller-standalone.test.mjs && node --test test/smart-extractor-admission-controller-injection.test.mjs && node --test test/admission-without-smart-extraction.test.mjs && node --test test/llm-thinklevel.test.mjs && node --test test/memory-id-prefix-resolution.test.mjs && node --test test/manual-store-supersede.test.mjs && node --test test/extraction-transcript-speaker-tags.test.mjs && node --test test/session-compressor.test.mjs && node --test test/reflection-derived-cache-invalidation.test.mjs",
"test:cli-smoke": "node scripts/run-ci-tests.mjs --group cli-smoke",
"test:core-regression": "node scripts/run-ci-tests.mjs --group core-regression",
"test:storage-and-schema": "node scripts/run-ci-tests.mjs --group storage-and-schema",
Expand Down
1 change: 1 addition & 0 deletions scripts/ci-test-manifest.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export const CI_TEST_MANIFEST = [
{ group: "core-regression", runner: "node", file: "test/manual-store-supersede.test.mjs", args: ["--test"] },
{ group: "core-regression", runner: "node", file: "test/session-compressor.test.mjs", args: ["--test"] },
{ group: "core-regression", runner: "node", file: "test/extraction-transcript-speaker-tags.test.mjs", args: ["--test"] },
{ group: "core-regression", runner: "node", file: "test/reflection-derived-cache-invalidation.test.mjs", args: ["--test"] },
];

export function getEntriesForGroup(group) {
Expand Down
Loading
Loading