@remnic/core 9.3.655 → 9.3.657
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-cli.js +22 -22
- package/dist/access-http.d.ts +4 -4
- package/dist/access-http.js +10 -10
- package/dist/access-mcp.d.ts +4 -4
- package/dist/access-mcp.js +9 -9
- package/dist/access-schema.d.ts +10 -10
- package/dist/{access-service-BEJvriUt.d.ts → access-service-D_nbpexW.d.ts} +33 -2
- package/dist/access-service.d.ts +4 -4
- package/dist/access-service.js +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 +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +3 -3
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +3 -3
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/calibration.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/{chunk-PVE7KSQP.js → chunk-2BD7DG37.js} +2 -2
- package/dist/{chunk-54LOUIBE.js → chunk-2MXEVL75.js} +2 -2
- package/dist/{chunk-55ZMNKMQ.js → chunk-4UL7VPTD.js} +276 -57
- package/dist/chunk-4UL7VPTD.js.map +1 -0
- package/dist/{chunk-COVZLGMR.js → chunk-54XF2FY7.js} +17 -17
- package/dist/{chunk-UYNFWZWG.js → chunk-AGJKWOKV.js} +2 -2
- package/dist/{chunk-TDZSSJV4.js → chunk-AZBV4RRY.js} +1 -1
- package/dist/chunk-AZBV4RRY.js.map +1 -0
- package/dist/{chunk-KOI765XP.js → chunk-CTAV55JM.js} +241 -1
- package/dist/chunk-CTAV55JM.js.map +1 -0
- package/dist/{chunk-A3Y37UWI.js → chunk-DIBWFCLA.js} +3 -3
- package/dist/{chunk-QDVQ4AN2.js → chunk-DR67OK4E.js} +5 -5
- package/dist/{chunk-XBIACVCO.js → chunk-EC2AYKRX.js} +2 -2
- package/dist/{chunk-IQ53ZSXV.js → chunk-GCYFUTUC.js} +2 -2
- package/dist/{chunk-YYN3LIYA.js → chunk-GSHW5VVD.js} +5 -5
- package/dist/chunk-GYSYLGNE.js +650 -0
- package/dist/chunk-GYSYLGNE.js.map +1 -0
- package/dist/{chunk-NRBGRZW4.js → chunk-IOZ5WBWD.js} +2 -2
- package/dist/{chunk-NCSJKK23.js → chunk-JSVFEHLL.js} +7 -5
- package/dist/chunk-JSVFEHLL.js.map +1 -0
- package/dist/{chunk-7LWRCOP7.js → chunk-LZTFCAKE.js} +2 -2
- package/dist/{chunk-TEO46GMM.js → chunk-NXCK7DO7.js} +2 -2
- package/dist/{chunk-XOFXKASO.js → chunk-PEPHBH2W.js} +2 -2
- package/dist/{chunk-WDTUYOLS.js → chunk-QZRKNA5F.js} +2 -2
- package/dist/{chunk-PS3SYNHP.js → chunk-R5DB26G6.js} +2 -2
- package/dist/{chunk-5QD3QD76.js → chunk-RDW5G6DO.js} +659 -123
- package/dist/chunk-RDW5G6DO.js.map +1 -0
- package/dist/{chunk-BGKXTVNG.js → chunk-SWDHVH2P.js} +2 -2
- package/dist/{chunk-67G4T7KI.js → chunk-SXYCVRLK.js} +3 -3
- package/dist/{chunk-UCEABZZN.js → chunk-TFFZUFEP.js} +7 -5
- package/dist/chunk-TFFZUFEP.js.map +1 -0
- package/dist/{chunk-UCEDY5M7.js → chunk-TIJYQXDI.js} +2 -2
- package/dist/{chunk-2RCGZ67B.js → chunk-VAEAGTEQ.js} +3 -3
- package/dist/{chunk-XRKQOQLY.js → chunk-WIKMCJUR.js} +2 -2
- package/dist/{chunk-KZZ4YAEC.js → chunk-WWMHAMAY.js} +2 -2
- package/dist/{chunk-OKW6F5S5.js → chunk-YEZHZCUO.js} +4 -4
- package/dist/{chunk-5FOCXX5E.js → chunk-YVVQUAOO.js} +3 -3
- package/dist/{chunk-5FOCXX5E.js.map → chunk-YVVQUAOO.js.map} +1 -1
- package/dist/{chunk-3XGWCZ63.js → chunk-YXLT4EMM.js} +2 -2
- package/dist/{chunk-PTMJ2FH2.js → chunk-Z6UDTNY6.js} +2 -2
- package/dist/{cli-BGahB_d3.d.ts → cli-aYxSuPvP.d.ts} +3 -3
- package/dist/cli.d.ts +5 -5
- package/dist/cli.js +22 -22
- package/dist/compounding/engine.d.ts +1 -1
- 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 +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +1 -1
- 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 +1 -1
- package/dist/entity-retrieval.js +3 -3
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +3 -3
- package/dist/explicit-cue-recall.js +2 -2
- 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/focused-list-recall.js +2 -2
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +121 -121
- package/dist/index.js +32 -32
- 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/lcm-fallback-read.js +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/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 +4 -4
- 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 +1 -1
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +1 -1
- 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 +1 -1
- package/dist/namespaces/storage.js +3 -3
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +7 -7
- package/dist/{orchestrator-BgzZlWxH.d.ts → orchestrator-D1wcmPNj.d.ts} +8 -2
- package/dist/orchestrator.d.ts +3 -3
- package/dist/orchestrator.js +18 -18
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.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-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-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/resolve-auth-token.d.ts +1 -1
- package/dist/response-guidance-recall.js +2 -2
- package/dist/resume-bundles.js +2 -2
- package/dist/retrieval-agents.d.ts +1 -1
- 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/schemas.d.ts +22 -22
- 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-Z8d_uMq8.d.ts → semantic-consolidation-MWOdNtSE.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 +3 -2
- package/dist/semantic-rule-verifier.js +5 -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.d.ts +1 -1
- package/dist/storage.js +2 -2
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/targeted-fact-recall.js +2 -2
- package/dist/temporal-supersession.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 +1 -1
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/transfer/types.d.ts +12 -12
- package/dist/{types-2OPlQWJG.d.ts → types-CgcCpUrf.d.ts} +39 -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.d.ts +2 -1
- package/dist/verified-recall.js +5 -3
- package/package.json +1 -1
- package/src/access-service-observe-lcm-parity.test.ts +86 -1
- package/src/access-service-observe-scope.test.ts +283 -1
- package/src/access-service-raw-excerpt-read-gate.test.ts +53 -0
- package/src/access-service.ts +391 -93
- package/src/coding/coding-namespace.ts +0 -3
- package/src/config.ts +282 -0
- package/src/lcm-fallback-read.ts +2 -6
- package/src/namespaces/scope-profiles.test.ts +1074 -0
- package/src/namespaces/scope-profiles.ts +456 -0
- package/src/orchestrator-flush.test.ts +142 -0
- package/src/orchestrator-source-attribution.test.ts +73 -0
- package/src/orchestrator.ts +835 -163
- package/src/semantic-rule-verifier.ts +13 -6
- package/src/types.ts +52 -0
- package/src/verified-recall.ts +10 -6
- package/dist/chunk-55ZMNKMQ.js.map +0 -1
- package/dist/chunk-5QD3QD76.js.map +0 -1
- package/dist/chunk-KOI765XP.js.map +0 -1
- package/dist/chunk-MMJANTJX.js +0 -339
- package/dist/chunk-MMJANTJX.js.map +0 -1
- package/dist/chunk-NCSJKK23.js.map +0 -1
- package/dist/chunk-TDZSSJV4.js.map +0 -1
- package/dist/chunk-UCEABZZN.js.map +0 -1
- /package/dist/{chunk-PVE7KSQP.js.map → chunk-2BD7DG37.js.map} +0 -0
- /package/dist/{chunk-54LOUIBE.js.map → chunk-2MXEVL75.js.map} +0 -0
- /package/dist/{chunk-COVZLGMR.js.map → chunk-54XF2FY7.js.map} +0 -0
- /package/dist/{chunk-UYNFWZWG.js.map → chunk-AGJKWOKV.js.map} +0 -0
- /package/dist/{chunk-A3Y37UWI.js.map → chunk-DIBWFCLA.js.map} +0 -0
- /package/dist/{chunk-QDVQ4AN2.js.map → chunk-DR67OK4E.js.map} +0 -0
- /package/dist/{chunk-XBIACVCO.js.map → chunk-EC2AYKRX.js.map} +0 -0
- /package/dist/{chunk-IQ53ZSXV.js.map → chunk-GCYFUTUC.js.map} +0 -0
- /package/dist/{chunk-YYN3LIYA.js.map → chunk-GSHW5VVD.js.map} +0 -0
- /package/dist/{chunk-NRBGRZW4.js.map → chunk-IOZ5WBWD.js.map} +0 -0
- /package/dist/{chunk-7LWRCOP7.js.map → chunk-LZTFCAKE.js.map} +0 -0
- /package/dist/{chunk-TEO46GMM.js.map → chunk-NXCK7DO7.js.map} +0 -0
- /package/dist/{chunk-XOFXKASO.js.map → chunk-PEPHBH2W.js.map} +0 -0
- /package/dist/{chunk-WDTUYOLS.js.map → chunk-QZRKNA5F.js.map} +0 -0
- /package/dist/{chunk-PS3SYNHP.js.map → chunk-R5DB26G6.js.map} +0 -0
- /package/dist/{chunk-BGKXTVNG.js.map → chunk-SWDHVH2P.js.map} +0 -0
- /package/dist/{chunk-67G4T7KI.js.map → chunk-SXYCVRLK.js.map} +0 -0
- /package/dist/{chunk-UCEDY5M7.js.map → chunk-TIJYQXDI.js.map} +0 -0
- /package/dist/{chunk-2RCGZ67B.js.map → chunk-VAEAGTEQ.js.map} +0 -0
- /package/dist/{chunk-XRKQOQLY.js.map → chunk-WIKMCJUR.js.map} +0 -0
- /package/dist/{chunk-KZZ4YAEC.js.map → chunk-WWMHAMAY.js.map} +0 -0
- /package/dist/{chunk-OKW6F5S5.js.map → chunk-YEZHZCUO.js.map} +0 -0
- /package/dist/{chunk-3XGWCZ63.js.map → chunk-YXLT4EMM.js.map} +0 -0
- /package/dist/{chunk-PTMJ2FH2.js.map → chunk-Z6UDTNY6.js.map} +0 -0
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
projectNamespaceName,
|
|
39
39
|
projectTagProjectId,
|
|
40
40
|
} from "./coding/coding-namespace.js";
|
|
41
|
-
import { resolveGitContext } from "./coding/git-context.js";
|
|
41
|
+
import { resolveGitContext, stableHash } from "./coding/git-context.js";
|
|
42
42
|
import { defaultNamespaceForPrincipal } from "./namespaces/principal.js";
|
|
43
43
|
import type { CodingContext, PluginConfig } from "./types.js";
|
|
44
44
|
|
|
@@ -652,6 +652,91 @@ test("#1505 thread 2 compaction regression: flush/record overlay-derived key mat
|
|
|
652
652
|
);
|
|
653
653
|
});
|
|
654
654
|
|
|
655
|
+
test("#1501 scope profile lcmSearch fans out prefix-only reads across profile namespaces", async () => {
|
|
656
|
+
const probe = makeParityProbe({
|
|
657
|
+
...withSelfPolicyPrefix("pi-observer"),
|
|
658
|
+
namespacePolicies: [
|
|
659
|
+
{ name: "pi-observer", readPrincipals: ["pi-observer"], writePrincipals: ["pi-observer"] },
|
|
660
|
+
{ name: "shared", readPrincipals: ["pi-observer"], writePrincipals: [] },
|
|
661
|
+
],
|
|
662
|
+
defaultScopeProfile: "profilePrefix",
|
|
663
|
+
scopeProfiles: {
|
|
664
|
+
profilePrefix: {
|
|
665
|
+
readOrder: ["userGlobal", "serverShared"],
|
|
666
|
+
writeDefault: "userGlobal",
|
|
667
|
+
promotionTargets: [],
|
|
668
|
+
autoPromote: {
|
|
669
|
+
enabled: false,
|
|
670
|
+
targets: [],
|
|
671
|
+
categories: ["fact", "correction", "decision", "preference"],
|
|
672
|
+
minConfidenceTier: "explicit",
|
|
673
|
+
},
|
|
674
|
+
},
|
|
675
|
+
},
|
|
676
|
+
} as Partial<PluginConfig>);
|
|
677
|
+
const service = new EngramAccessService(probe.orch);
|
|
678
|
+
|
|
679
|
+
await service.lcmSearch({
|
|
680
|
+
query: "database",
|
|
681
|
+
sessionPrefix: "pi-observer:",
|
|
682
|
+
authenticatedPrincipal: "pi-observer",
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
assert.deepEqual(probe.searchSessionIds, [undefined, undefined]);
|
|
686
|
+
assert.deepEqual(probe.searchSessionPrefixes, [
|
|
687
|
+
encodeNs("pi-observer", "pi-observer:"),
|
|
688
|
+
encodeNs("shared", "pi-observer:"),
|
|
689
|
+
]);
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
test("#1501 scope profile lcmSearch reads the team-project profile key", async () => {
|
|
693
|
+
const probe = makeParityProbe({
|
|
694
|
+
...withSelfPolicyPrefix("pi-observer"),
|
|
695
|
+
defaultScopeProfile: "teamCoding",
|
|
696
|
+
scopeProfiles: {
|
|
697
|
+
teamCoding: {
|
|
698
|
+
readOrder: ["teamProject"],
|
|
699
|
+
writeDefault: "teamProject",
|
|
700
|
+
promotionTargets: ["teamProject"],
|
|
701
|
+
autoPromote: {
|
|
702
|
+
enabled: false,
|
|
703
|
+
targets: [],
|
|
704
|
+
categories: ["fact", "correction", "decision", "preference"],
|
|
705
|
+
minConfidenceTier: "explicit",
|
|
706
|
+
},
|
|
707
|
+
teamProject: { namespaceTemplate: "team-{teamId}-project-{projectHash}" },
|
|
708
|
+
},
|
|
709
|
+
},
|
|
710
|
+
teams: {
|
|
711
|
+
pi: {
|
|
712
|
+
principals: ["pi-observer"],
|
|
713
|
+
read: ["pi-observer"],
|
|
714
|
+
write: ["pi-observer"],
|
|
715
|
+
promote: ["pi-observer"],
|
|
716
|
+
},
|
|
717
|
+
},
|
|
718
|
+
} as Partial<PluginConfig>);
|
|
719
|
+
const service = new EngramAccessService(probe.orch);
|
|
720
|
+
|
|
721
|
+
await service.observe(
|
|
722
|
+
observeRequest({ sessionKey: "pi-observer:abc123", projectTag: "Remnic" }),
|
|
723
|
+
);
|
|
724
|
+
const expectedTeamProject = `team-pi-project-${stableHash(projectTagProjectId("Remnic"))}`;
|
|
725
|
+
const expectedKey = encodeNs(expectedTeamProject, "pi-observer:abc123");
|
|
726
|
+
assert.equal(probe.lcmWriteKeys[0], expectedKey);
|
|
727
|
+
|
|
728
|
+
await service.lcmSearch({
|
|
729
|
+
query: "what database are we using?",
|
|
730
|
+
sessionKey: "pi-observer:abc123",
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
assert.equal(
|
|
734
|
+
probe.searchSessionIds[0],
|
|
735
|
+
expectedKey,
|
|
736
|
+
"lcmSearch must read the same team-project key the scope-profile observe wrote",
|
|
737
|
+
);
|
|
738
|
+
});
|
|
739
|
+
|
|
655
740
|
test("#1505 round 3: access lcmSearch routes the session_id through the SCOPED (overlay) key", async () => {
|
|
656
741
|
// cursor "LCM search misses overlay keys" / codex "Route access LCM search
|
|
657
742
|
// through the scoped key". A project-scoped observe (no explicit namespace)
|
|
@@ -41,7 +41,8 @@ import {
|
|
|
41
41
|
projectNamespaceName,
|
|
42
42
|
projectTagProjectId,
|
|
43
43
|
} from "./coding/coding-namespace.js";
|
|
44
|
-
import { resolveGitContext } from "./coding/git-context.js";
|
|
44
|
+
import { resolveGitContext, stableHash } from "./coding/git-context.js";
|
|
45
|
+
import { namespaceCollectionName } from "./namespaces/search.js";
|
|
45
46
|
import type { CodingContext, PluginConfig } from "./types.js";
|
|
46
47
|
|
|
47
48
|
/**
|
|
@@ -212,6 +213,72 @@ test("#1495 projectTag: LCM, extraction, objective-state, and response all agree
|
|
|
212
213
|
);
|
|
213
214
|
});
|
|
214
215
|
|
|
216
|
+
test("#1501 scope profile exposes layered read/write/promotion diagnostics without changing user-project write default", async () => {
|
|
217
|
+
const probe = makeObserveProbe({
|
|
218
|
+
namespacePolicies: [
|
|
219
|
+
{ name: "pi-geek", readPrincipals: ["pi-geek"], writePrincipals: ["pi-geek"] },
|
|
220
|
+
{ name: "shared", readPrincipals: ["pi-geek"], writePrincipals: ["pi-geek"] },
|
|
221
|
+
],
|
|
222
|
+
principalFromSessionKeyMode: "prefix",
|
|
223
|
+
principalFromSessionKeyRules: [{ match: "pi-geek:", principal: "pi-geek" }],
|
|
224
|
+
scopeProfiles: {
|
|
225
|
+
teamCoding: {
|
|
226
|
+
readOrder: ["userProject", "teamProject", "userGlobal", "serverShared"],
|
|
227
|
+
writeDefault: "userProject",
|
|
228
|
+
promotionTargets: ["teamProject", "serverShared"],
|
|
229
|
+
teamProject: { namespaceTemplate: "team-{teamId}-project-{projectHash}" },
|
|
230
|
+
autoPromote: {
|
|
231
|
+
enabled: false,
|
|
232
|
+
targets: [],
|
|
233
|
+
categories: ["fact", "correction", "decision", "preference"],
|
|
234
|
+
minConfidenceTier: "explicit",
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
defaultScopeProfile: "teamCoding",
|
|
239
|
+
teams: {
|
|
240
|
+
pi: {
|
|
241
|
+
principals: ["pi-geek", "pi-friend"],
|
|
242
|
+
read: ["pi-geek", "pi-friend"],
|
|
243
|
+
write: ["pi-geek", "pi-friend"],
|
|
244
|
+
promote: ["pi-geek", "pi-friend"],
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
} as Partial<PluginConfig>);
|
|
248
|
+
const service = new EngramAccessService(probe.orch);
|
|
249
|
+
|
|
250
|
+
const res = await service.observe(
|
|
251
|
+
observeRequest({ sessionKey: "pi-geek:abc123", projectTag: "Remnic" }),
|
|
252
|
+
);
|
|
253
|
+
const expectedUserProject = combineNamespaces(
|
|
254
|
+
"pi-geek",
|
|
255
|
+
projectNamespaceName(projectTagProjectId("Remnic")),
|
|
256
|
+
);
|
|
257
|
+
const expectedTeamProject = `team-pi-project-${stableHash(projectTagProjectId("Remnic"))}`;
|
|
258
|
+
|
|
259
|
+
assert.equal(res.effectiveNamespace, expectedUserProject);
|
|
260
|
+
assert.equal(res.scopeDebug?.scopeProfile, "teamCoding");
|
|
261
|
+
assert.equal(res.scopeDebug?.writeLayer, "userProject");
|
|
262
|
+
assert.deepEqual(res.scopeDebug?.readNamespaces, [
|
|
263
|
+
expectedUserProject,
|
|
264
|
+
expectedTeamProject,
|
|
265
|
+
"pi-geek",
|
|
266
|
+
"shared",
|
|
267
|
+
]);
|
|
268
|
+
assert.deepEqual(
|
|
269
|
+
res.scopeDebug?.promotionTargets?.map((target) => [
|
|
270
|
+
target.target,
|
|
271
|
+
target.namespace,
|
|
272
|
+
target.authorized,
|
|
273
|
+
]),
|
|
274
|
+
[
|
|
275
|
+
["teamProject", expectedTeamProject, true],
|
|
276
|
+
["serverShared", "shared", true],
|
|
277
|
+
],
|
|
278
|
+
);
|
|
279
|
+
assert.equal(probe.extractionCalls[0]?.writeNamespaceOverride, expectedUserProject);
|
|
280
|
+
});
|
|
281
|
+
|
|
215
282
|
test("#1495 cwd (git repo): every observe side effect agrees on the effective namespace", async () => {
|
|
216
283
|
const repoDir = mkdtempSync(join(tmpdir(), "remnic-observe-git-"));
|
|
217
284
|
// A real (synthetic) git repo so resolveGitContext can read rev-parse output.
|
|
@@ -577,6 +644,120 @@ test("#1495 the scope plan's writeNamespace matches resolveCodingScopedWriteName
|
|
|
577
644
|
}
|
|
578
645
|
});
|
|
579
646
|
|
|
647
|
+
test("#1501 profile write auth rejects memory_store when no profile layer is writable", async () => {
|
|
648
|
+
const probe = makeObserveProbe({
|
|
649
|
+
namespacePolicies: [
|
|
650
|
+
{ name: "pi-observer", readPrincipals: ["pi-observer"], writePrincipals: [] },
|
|
651
|
+
{ name: "shared", readPrincipals: ["pi-observer"], writePrincipals: [] },
|
|
652
|
+
],
|
|
653
|
+
principalFromSessionKeyMode: "prefix",
|
|
654
|
+
principalFromSessionKeyRules: [{ match: "pi-observer:", principal: "pi-observer" }],
|
|
655
|
+
scopeProfiles: {
|
|
656
|
+
teamCoding: {
|
|
657
|
+
readOrder: ["userProject", "teamProject", "serverShared"],
|
|
658
|
+
writeDefault: "userProject",
|
|
659
|
+
promotionTargets: ["teamProject", "serverShared"],
|
|
660
|
+
teamProject: { namespaceTemplate: "team-{teamId}-project-{projectHash}" },
|
|
661
|
+
autoPromote: {
|
|
662
|
+
enabled: false,
|
|
663
|
+
targets: [],
|
|
664
|
+
categories: ["fact", "correction", "decision", "preference"],
|
|
665
|
+
minConfidenceTier: "explicit",
|
|
666
|
+
},
|
|
667
|
+
},
|
|
668
|
+
},
|
|
669
|
+
defaultScopeProfile: "teamCoding",
|
|
670
|
+
teams: {
|
|
671
|
+
pi: {
|
|
672
|
+
principals: ["pi-observer"],
|
|
673
|
+
read: ["pi-observer"],
|
|
674
|
+
write: [],
|
|
675
|
+
promote: [],
|
|
676
|
+
},
|
|
677
|
+
},
|
|
678
|
+
} as Partial<PluginConfig>);
|
|
679
|
+
probe.contexts.set("pi-observer:abc123", {
|
|
680
|
+
projectId: projectTagProjectId("Remnic"),
|
|
681
|
+
branch: null,
|
|
682
|
+
rootPath: projectTagProjectId("Remnic"),
|
|
683
|
+
defaultBranch: null,
|
|
684
|
+
});
|
|
685
|
+
const service = new EngramAccessService(probe.orch);
|
|
686
|
+
const internals = service as unknown as {
|
|
687
|
+
resolveMemoryScopePlan: (r: unknown) => Promise<{ writeNamespace: string }>;
|
|
688
|
+
resolveCodingScopedWriteNamespace: (r: unknown) => Promise<string>;
|
|
689
|
+
};
|
|
690
|
+
const req = {
|
|
691
|
+
sessionKey: "pi-observer:abc123",
|
|
692
|
+
authenticatedPrincipal: "pi-observer",
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
await assert.rejects(
|
|
696
|
+
() => internals.resolveMemoryScopePlan.call(service, req),
|
|
697
|
+
/scope profile teamCoding has no writable layer/,
|
|
698
|
+
);
|
|
699
|
+
await assert.rejects(
|
|
700
|
+
() => internals.resolveCodingScopedWriteNamespace.call(service, req),
|
|
701
|
+
/scope profile teamCoding has no writable layer/,
|
|
702
|
+
);
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
test("#1501 team-project profile observe reports the profile write namespace as legacy namespace", async () => {
|
|
706
|
+
const projectId = projectTagProjectId("Remnic");
|
|
707
|
+
const expectedTeamProject = `team-pi-project-${stableHash(projectId)}`;
|
|
708
|
+
const probe = makeObserveProbe({
|
|
709
|
+
namespacePolicies: [
|
|
710
|
+
{
|
|
711
|
+
name: expectedTeamProject,
|
|
712
|
+
readPrincipals: ["pi-observer"],
|
|
713
|
+
writePrincipals: ["pi-observer"],
|
|
714
|
+
},
|
|
715
|
+
],
|
|
716
|
+
principalFromSessionKeyMode: "prefix",
|
|
717
|
+
principalFromSessionKeyRules: [{ match: "pi-observer:", principal: "pi-observer" }],
|
|
718
|
+
scopeProfiles: {
|
|
719
|
+
teamCoding: {
|
|
720
|
+
readOrder: ["teamProject", "serverShared"],
|
|
721
|
+
writeDefault: "teamProject",
|
|
722
|
+
promotionTargets: ["teamProject"],
|
|
723
|
+
teamProject: { namespaceTemplate: "team-{teamId}-project-{projectHash}" },
|
|
724
|
+
autoPromote: {
|
|
725
|
+
enabled: false,
|
|
726
|
+
targets: [],
|
|
727
|
+
categories: ["fact", "correction", "decision", "preference"],
|
|
728
|
+
minConfidenceTier: "explicit",
|
|
729
|
+
},
|
|
730
|
+
},
|
|
731
|
+
},
|
|
732
|
+
defaultScopeProfile: "teamCoding",
|
|
733
|
+
teams: {
|
|
734
|
+
pi: {
|
|
735
|
+
principals: ["pi-observer"],
|
|
736
|
+
read: ["pi-observer"],
|
|
737
|
+
write: ["pi-observer"],
|
|
738
|
+
promote: ["pi-observer"],
|
|
739
|
+
},
|
|
740
|
+
},
|
|
741
|
+
} as Partial<PluginConfig>);
|
|
742
|
+
const service = new EngramAccessService(probe.orch);
|
|
743
|
+
|
|
744
|
+
const res = await service.observe(
|
|
745
|
+
observeRequest({
|
|
746
|
+
sessionKey: "pi-observer:abc123",
|
|
747
|
+
authenticatedPrincipal: "pi-observer",
|
|
748
|
+
projectTag: "Remnic",
|
|
749
|
+
}),
|
|
750
|
+
);
|
|
751
|
+
|
|
752
|
+
assert.equal(res.scopeDebug?.baseNamespace, "pi-observer");
|
|
753
|
+
assert.equal(res.scopeDebug?.writeLayer, "teamProject");
|
|
754
|
+
assert.equal(res.scopeDebug?.codingOverlayApplied, true);
|
|
755
|
+
assert.equal(res.namespace, expectedTeamProject);
|
|
756
|
+
assert.equal(res.effectiveNamespace, expectedTeamProject);
|
|
757
|
+
assert.equal(probe.lcmCalls[0]?.sessionKey, encodeNs(expectedTeamProject, "pi-observer:abc123"));
|
|
758
|
+
assert.equal(probe.extractionCalls[0]?.writeNamespaceOverride, expectedTeamProject);
|
|
759
|
+
});
|
|
760
|
+
|
|
580
761
|
test("#1495 skipExtraction does not enqueue extraction but still archives LCM under the effective namespace", async () => {
|
|
581
762
|
const probe = makeObserveProbe(withSelfPolicyPrefix("pi-geek"));
|
|
582
763
|
const service = new EngramAccessService(probe.orch);
|
|
@@ -597,3 +778,104 @@ test("#1495 skipExtraction does not enqueue extraction but still archives LCM un
|
|
|
597
778
|
assert.equal(probe.extractionCalls.length, 0);
|
|
598
779
|
assert.equal(probe.lcmCalls[0].sessionKey, encodeNs(expected, "pi-geek:abc123"));
|
|
599
780
|
});
|
|
781
|
+
|
|
782
|
+
test("#1501 implicit memorySearch honors active scope profile readOrder", async () => {
|
|
783
|
+
let searchedNamespaces: string[] | null = null;
|
|
784
|
+
const config = {
|
|
785
|
+
namespacesEnabled: true,
|
|
786
|
+
defaultNamespace: "default",
|
|
787
|
+
sharedNamespace: "shared",
|
|
788
|
+
memoryDir: "/synthetic/remnic-memory-search",
|
|
789
|
+
namespacePolicies: [
|
|
790
|
+
{ name: "pi-geek", readPrincipals: ["pi-geek"], writePrincipals: ["pi-geek"] },
|
|
791
|
+
{ name: "shared", readPrincipals: ["pi-geek"], writePrincipals: ["pi-geek"] },
|
|
792
|
+
],
|
|
793
|
+
defaultRecallNamespaces: ["self", "shared"],
|
|
794
|
+
defaultScopeProfile: "projectOnly",
|
|
795
|
+
scopeProfiles: {
|
|
796
|
+
projectOnly: {
|
|
797
|
+
readOrder: ["userProject"],
|
|
798
|
+
writeDefault: "userProject",
|
|
799
|
+
promotionTargets: [],
|
|
800
|
+
autoPromote: {
|
|
801
|
+
enabled: false,
|
|
802
|
+
targets: [],
|
|
803
|
+
categories: ["fact", "correction", "decision", "preference"],
|
|
804
|
+
minConfidenceTier: "explicit",
|
|
805
|
+
},
|
|
806
|
+
},
|
|
807
|
+
},
|
|
808
|
+
codingMode: { projectScope: true },
|
|
809
|
+
} as unknown as PluginConfig;
|
|
810
|
+
const orch = {
|
|
811
|
+
config,
|
|
812
|
+
qmd: { isAvailable: () => true },
|
|
813
|
+
searchAcrossNamespaces: async (options: { namespaces: string[] }) => {
|
|
814
|
+
searchedNamespaces = options.namespaces;
|
|
815
|
+
return [];
|
|
816
|
+
},
|
|
817
|
+
} as unknown as Orchestrator;
|
|
818
|
+
const service = new EngramAccessService(orch);
|
|
819
|
+
|
|
820
|
+
const result = await service.memorySearch({
|
|
821
|
+
query: "deployment",
|
|
822
|
+
principal: "pi-geek",
|
|
823
|
+
});
|
|
824
|
+
|
|
825
|
+
assert.equal(result.count, 0);
|
|
826
|
+
assert.equal(
|
|
827
|
+
searchedNamespaces,
|
|
828
|
+
null,
|
|
829
|
+
"userProject-only profiles without project context must not fall back to shared/global search",
|
|
830
|
+
);
|
|
831
|
+
});
|
|
832
|
+
|
|
833
|
+
test("#1501 memorySearch collection names stay constrained to active scope profile namespaces", async () => {
|
|
834
|
+
let searchedNamespaces: string[] | null = null;
|
|
835
|
+
const config = {
|
|
836
|
+
namespacesEnabled: true,
|
|
837
|
+
defaultNamespace: "default",
|
|
838
|
+
sharedNamespace: "shared",
|
|
839
|
+
memoryDir: "/synthetic/remnic-memory-search-collection",
|
|
840
|
+
qmdCollection: "memories",
|
|
841
|
+
namespacePolicies: [
|
|
842
|
+
{ name: "pi-geek", readPrincipals: ["pi-geek"], writePrincipals: ["pi-geek"] },
|
|
843
|
+
{ name: "shared", readPrincipals: ["pi-geek"], writePrincipals: ["pi-geek"] },
|
|
844
|
+
],
|
|
845
|
+
defaultRecallNamespaces: ["self", "shared"],
|
|
846
|
+
defaultScopeProfile: "privateOnly",
|
|
847
|
+
scopeProfiles: {
|
|
848
|
+
privateOnly: {
|
|
849
|
+
readOrder: ["userGlobal"],
|
|
850
|
+
writeDefault: "userGlobal",
|
|
851
|
+
promotionTargets: [],
|
|
852
|
+
autoPromote: {
|
|
853
|
+
enabled: false,
|
|
854
|
+
targets: [],
|
|
855
|
+
categories: ["fact", "correction", "decision", "preference"],
|
|
856
|
+
minConfidenceTier: "explicit",
|
|
857
|
+
},
|
|
858
|
+
},
|
|
859
|
+
},
|
|
860
|
+
codingMode: { projectScope: true },
|
|
861
|
+
} as unknown as PluginConfig;
|
|
862
|
+
const orch = {
|
|
863
|
+
config,
|
|
864
|
+
qmd: { isAvailable: () => true },
|
|
865
|
+
searchAcrossNamespaces: async (options: { namespaces: string[] }) => {
|
|
866
|
+
searchedNamespaces = options.namespaces;
|
|
867
|
+
return [];
|
|
868
|
+
},
|
|
869
|
+
} as unknown as Orchestrator;
|
|
870
|
+
const service = new EngramAccessService(orch);
|
|
871
|
+
const sharedCollection = namespaceCollectionName(config.qmdCollection, "shared", {
|
|
872
|
+
defaultNamespace: config.defaultNamespace,
|
|
873
|
+
useLegacyDefaultCollection: false,
|
|
874
|
+
});
|
|
875
|
+
|
|
876
|
+
await assert.rejects(
|
|
877
|
+
() => service.memorySearch({ query: "deployment", principal: "pi-geek", collection: sharedCollection }),
|
|
878
|
+
/collection is not namespace-scoped/,
|
|
879
|
+
);
|
|
880
|
+
assert.equal(searchedNamespaces, null);
|
|
881
|
+
});
|
|
@@ -165,6 +165,13 @@ type ExecuteRecallInternals = {
|
|
|
165
165
|
executeRecall: (request: unknown) => Promise<unknown>;
|
|
166
166
|
};
|
|
167
167
|
|
|
168
|
+
type RawExcerptInternals = {
|
|
169
|
+
fetchRawExcerpts: (
|
|
170
|
+
disclosure: "raw",
|
|
171
|
+
context: { query: string; sessionKey: string; lcmSessionIds: string[] },
|
|
172
|
+
) => Promise<Array<{ turnIndex: number; role: string; content: string; sessionId: string }> | null>;
|
|
173
|
+
};
|
|
174
|
+
|
|
168
175
|
const SESSION_KEY = "pi-geek:abc123";
|
|
169
176
|
const PROJECT_TAG = "Blend/Supply";
|
|
170
177
|
|
|
@@ -441,3 +448,49 @@ test("#1505 thread 2f7 (single-store regression): namespaces disabled ⇒ raw ex
|
|
|
441
448
|
assert.equal(probe.searchSessionIds.length, 1);
|
|
442
449
|
assert.equal(probe.searchSessionIds[0], SESSION_KEY);
|
|
443
450
|
});
|
|
451
|
+
|
|
452
|
+
test("scope-profile raw excerpts preserve successful sibling LCM keys when one key fails", async () => {
|
|
453
|
+
const probe = makeRawExcerptProbe({
|
|
454
|
+
config: {},
|
|
455
|
+
snapshotNamespace: "default",
|
|
456
|
+
sessionKey: SESSION_KEY,
|
|
457
|
+
});
|
|
458
|
+
const orchestrator = (probe.service as unknown as { orchestrator: Orchestrator }).orchestrator as unknown as {
|
|
459
|
+
lcmEngine: {
|
|
460
|
+
enabled: boolean;
|
|
461
|
+
searchContextFull: (query: string, limit: number, sessionId?: string) => Promise<Array<{
|
|
462
|
+
session_id: string;
|
|
463
|
+
turn_index: number;
|
|
464
|
+
role: string;
|
|
465
|
+
content: string;
|
|
466
|
+
}>>;
|
|
467
|
+
};
|
|
468
|
+
};
|
|
469
|
+
orchestrator.lcmEngine.searchContextFull = async (_query, _limit, sessionId) => {
|
|
470
|
+
probe.searchSessionIds.push(sessionId);
|
|
471
|
+
if (sessionId === "bad") throw new Error("synthetic LCM failure");
|
|
472
|
+
return [
|
|
473
|
+
{
|
|
474
|
+
session_id: sessionId ?? "default",
|
|
475
|
+
turn_index: sessionId === "good" ? 1 : 2,
|
|
476
|
+
role: "user",
|
|
477
|
+
content: `raw row from ${sessionId}`,
|
|
478
|
+
},
|
|
479
|
+
];
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
const excerpts = await (probe.service as unknown as RawExcerptInternals).fetchRawExcerpts("raw", {
|
|
483
|
+
query: "what happened?",
|
|
484
|
+
sessionKey: SESSION_KEY,
|
|
485
|
+
lcmSessionIds: ["good", "bad", "later"],
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
assert.deepEqual(probe.searchSessionIds, ["good", "bad", "later"]);
|
|
489
|
+
assert.deepEqual(
|
|
490
|
+
excerpts?.map((excerpt) => [excerpt.sessionId, excerpt.turnIndex, excerpt.content]),
|
|
491
|
+
[
|
|
492
|
+
["good", 1, "raw row from good"],
|
|
493
|
+
["later", 2, "raw row from later"],
|
|
494
|
+
],
|
|
495
|
+
);
|
|
496
|
+
});
|