@remnic/core 9.3.713 → 9.3.715
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-boundary.d.ts +6 -6
- package/dist/access-boundary.js +17 -16
- package/dist/access-cli.js +39 -38
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +5 -5
- package/dist/access-http.js +23 -22
- package/dist/access-mcp.d.ts +12 -5
- package/dist/access-mcp.js +20 -19
- package/dist/access-operations-batch.js +18 -17
- package/dist/access-operations.d.ts +6 -5
- package/dist/access-operations.js +19 -18
- package/dist/{access-service-DwVmvgBg.d.ts → access-service-GgnA--CE.d.ts} +12 -4
- package/dist/access-service.d.ts +5 -5
- package/dist/access-service.js +16 -15
- package/dist/access-surface-catalog.d.ts +5 -5
- package/dist/access-surface-catalog.js +6 -1
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +3 -1
- package/dist/active-memory-bridge.js +2 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +4 -3
- package/dist/active-recall.js.map +1 -1
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/registry.js +2 -2
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +4 -4
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +8 -7
- 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/capabilities.d.ts +1 -1
- package/dist/{catalog-CadPvH29.d.ts → catalog-CbR0CsUw.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 +9 -8
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/{chunk-OMSTU233.js → chunk-2KAYTPPT.js} +4 -4
- package/dist/{chunk-VYZNWH4J.js → chunk-2SXMCQEQ.js} +3 -3
- package/dist/{chunk-NXL5CVE7.js → chunk-2Y6LMOQQ.js} +2 -2
- package/dist/{chunk-ZDUF7K5V.js → chunk-3VUPWDSE.js} +15 -3
- package/dist/{chunk-ZDUF7K5V.js.map → chunk-3VUPWDSE.js.map} +1 -1
- package/dist/{chunk-FVQJYWH7.js → chunk-5GKPFL3S.js} +1 -1
- package/dist/{chunk-FVQJYWH7.js.map → chunk-5GKPFL3S.js.map} +1 -1
- package/dist/{chunk-LQ4J7ELC.js → chunk-67HG7KFE.js} +2 -2
- package/dist/{chunk-ZBG4K36I.js → chunk-6FUJ2VYY.js} +3 -3
- package/dist/{chunk-GMRNKPWO.js → chunk-6QUPUTT7.js} +2 -2
- package/dist/{chunk-Z56IHRVV.js → chunk-6UU43ZGD.js} +2 -2
- package/dist/{chunk-APJQ6UEA.js → chunk-AGNBY3VG.js} +4 -4
- package/dist/{chunk-OWOKOFXK.js → chunk-AJOIM6UR.js} +2 -2
- package/dist/{chunk-JBPKEARU.js → chunk-AU7Q3LSC.js} +4 -4
- package/dist/{chunk-UHN2TNSB.js → chunk-BNOAB5HH.js} +38 -11
- package/dist/chunk-BNOAB5HH.js.map +1 -0
- package/dist/{chunk-VW24K2Q4.js → chunk-CTAHKIG6.js} +169 -8
- package/dist/chunk-CTAHKIG6.js.map +1 -0
- package/dist/{chunk-K22IJO4R.js → chunk-CTOQEZSN.js} +2 -2
- package/dist/{chunk-SINGJCUR.js → chunk-CX77GNMB.js} +14 -3
- package/dist/chunk-CX77GNMB.js.map +1 -0
- package/dist/{chunk-HSDJCT3V.js → chunk-DXGS5YOQ.js} +3 -3
- package/dist/{chunk-HV57RHMD.js → chunk-EH5ED3C6.js} +2 -2
- package/dist/{chunk-7NDYFAJS.js → chunk-GM3BMWKR.js} +2 -2
- package/dist/{chunk-RMT7PAVW.js → chunk-HHLWSWWF.js} +2 -2
- package/dist/chunk-HHLWSWWF.js.map +1 -0
- package/dist/{chunk-5QUS24F7.js → chunk-I56LKMF7.js} +2 -2
- package/dist/{chunk-VUNI6Y3D.js → chunk-IHMT6XTY.js} +8 -4
- package/dist/chunk-IHMT6XTY.js.map +1 -0
- package/dist/chunk-JAKIDQB2.js +173 -0
- package/dist/chunk-JAKIDQB2.js.map +1 -0
- package/dist/{chunk-35YJ6KCV.js → chunk-JEIROMLX.js} +2 -2
- package/dist/{chunk-SKQCFAYU.js → chunk-JVEMUX6L.js} +2 -2
- package/dist/{chunk-CXMXAC5R.js → chunk-K44MIN6D.js} +3 -3
- package/dist/{chunk-JC3MIKR4.js → chunk-MECU6WSH.js} +188 -31
- package/dist/chunk-MECU6WSH.js.map +1 -0
- package/dist/{chunk-BQCFXAMN.js → chunk-MPHDVHIB.js} +2 -2
- package/dist/{chunk-BOGENF7P.js → chunk-MSVSP5VO.js} +1 -1
- package/dist/chunk-MSVSP5VO.js.map +1 -0
- package/dist/{chunk-QXNFQKWU.js → chunk-MTHNJCOJ.js} +2 -2
- package/dist/{chunk-3TCRU4JA.js → chunk-O62P2LFL.js} +2 -2
- package/dist/{chunk-JSDZMOT7.js → chunk-OC56UWV5.js} +11 -11
- package/dist/{chunk-7IBEWQLG.js → chunk-QOIONSOI.js} +2 -2
- package/dist/{chunk-4P5UAL3C.js → chunk-RBHANGVX.js} +6 -6
- package/dist/{chunk-SK2CR6MW.js → chunk-RVLB4E6N.js} +2 -2
- package/dist/{chunk-DJNKN3XY.js → chunk-SYDHFFAW.js} +1084 -12
- package/dist/chunk-SYDHFFAW.js.map +1 -0
- package/dist/{chunk-VILEUJXC.js → chunk-UC4YOAC2.js} +74 -2
- package/dist/{chunk-VILEUJXC.js.map → chunk-UC4YOAC2.js.map} +1 -1
- package/dist/{chunk-CNVIWMQI.js → chunk-UY4JMEAK.js} +2 -2
- package/dist/{chunk-S6FQLQGH.js → chunk-V7GDTQ6I.js} +2 -2
- package/dist/{chunk-JNOYYWCA.js → chunk-VO4UICII.js} +3 -3
- package/dist/{chunk-54TI5GLV.js → chunk-WI4QX7GH.js} +3 -3
- package/dist/{chunk-3XHD3XGK.js → chunk-XCTDHF7U.js} +30 -2
- package/dist/chunk-XCTDHF7U.js.map +1 -0
- package/dist/{chunk-XKU4YE6Z.js → chunk-XZTUMWKQ.js} +2 -2
- package/dist/{chunk-GKPIY7EQ.js → chunk-YUJL27ET.js} +160 -61
- package/dist/chunk-YUJL27ET.js.map +1 -0
- package/dist/{cli-DfDMJqPP.d.ts → cli-Do1YtfnH.d.ts} +3 -3
- package/dist/cli.d.ts +6 -6
- package/dist/cli.js +42 -41
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +8 -7
- 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 +4 -3
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +8 -7
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +9 -8
- 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 +8 -7
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +4 -4
- package/dist/explicit-capture.js +3 -2
- 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/extraction.js +4 -3
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +9 -9
- package/dist/index.js +61 -60
- package/dist/index.js.map +1 -1
- 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/index.js +3 -3
- 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/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +8 -7
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +8 -7
- package/dist/maintenance/rebuild-memory-projection.js +9 -8
- package/dist/mcp-memory-inspector-app.d.ts +5 -5
- 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 +2 -2
- package/dist/namespaces/migrate.js +12 -11
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +3 -3
- package/dist/namespaces/storage.d.ts +2 -2
- package/dist/namespaces/storage.js +8 -7
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +17 -16
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +10 -9
- package/dist/{orchestrator-B1iVjEyc.d.ts → orchestrator-BOaVstFG.d.ts} +32 -4
- package/dist/orchestrator.d.ts +4 -4
- package/dist/orchestrator.js +32 -31
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/provenance.js +3 -2
- 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-handles.d.ts +228 -0
- package/dist/recall-handles.js +42 -0
- package/dist/recall-handles.js.map +1 -0
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +40 -2
- package/dist/recall-state.js +3 -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/resume-bundles.js +5 -4
- 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/sanitize.d.ts +2 -0
- package/dist/sanitize.js +6 -2
- 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/factory.js +2 -2
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +4 -4
- 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-CY8uVRNJ.d.ts → semantic-consolidation-DSjMDZ1u.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +9 -8
- package/dist/semantic-rule-promotion.js +8 -7
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +8 -7
- 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 +3 -3
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/storage.js +7 -6
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- 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/import-sqlite.js +2 -2
- package/dist/transfer/types.d.ts +12 -12
- package/dist/{types-Dr0Cw3L9.d.ts → types-D9dwzU_x.d.ts} +25 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +8 -7
- package/package.json +2 -2
- package/src/access-boundary.ts +4 -1
- package/src/access-http.ts +33 -1
- package/src/access-mcp.test.ts +28 -0
- package/src/access-mcp.ts +67 -2
- package/src/access-operations-batch.ts +14 -0
- package/src/access-operations.ts +5 -0
- package/src/access-service.ts +43 -2
- package/src/access-surface-catalog.test.ts +4 -2
- package/src/access-surface-catalog.ts +5 -0
- package/src/active-memory-bridge.test.ts +72 -0
- package/src/active-memory-bridge.ts +21 -2
- package/src/chat/chat-cli.test.ts +142 -0
- package/src/chat/chat-cli.ts +206 -0
- package/src/chat/chat-config.ts +57 -0
- package/src/chat/chat-engine.test.ts +272 -0
- package/src/chat/chat-engine.ts +518 -0
- package/src/chat/chat-executor.ts +133 -0
- package/src/chat/chat-factory.ts +161 -0
- package/src/chat/chat-http.test.ts +197 -0
- package/src/chat/chat-http.ts +222 -0
- package/src/chat/chat-llm.ts +229 -0
- package/src/chat/chat-mcp.test.ts +135 -0
- package/src/chat/chat-security.test.ts +491 -0
- package/src/chat/chat-session.ts +296 -0
- package/src/chat/chat-system-prompt.ts +76 -0
- package/src/chat/chat-tools.ts +255 -0
- package/src/chat/chat-types.ts +167 -0
- package/src/cli.ts +20 -0
- package/src/config.ts +9 -0
- package/src/faithfulness-graph-guard.test.ts +214 -8
- package/src/orchestrator.ts +167 -22
- package/src/recall-handles-wiring.test.ts +477 -0
- package/src/recall-handles.test.ts +283 -0
- package/src/recall-handles.ts +414 -0
- package/src/recall-state.ts +99 -0
- package/src/sanitize.ts +6 -0
- package/src/types.ts +29 -0
- package/dist/chunk-3XHD3XGK.js.map +0 -1
- package/dist/chunk-BOGENF7P.js.map +0 -1
- package/dist/chunk-DJNKN3XY.js.map +0 -1
- package/dist/chunk-GKPIY7EQ.js.map +0 -1
- package/dist/chunk-JC3MIKR4.js.map +0 -1
- package/dist/chunk-RMT7PAVW.js.map +0 -1
- package/dist/chunk-SINGJCUR.js.map +0 -1
- package/dist/chunk-UHN2TNSB.js.map +0 -1
- package/dist/chunk-VUNI6Y3D.js.map +0 -1
- package/dist/chunk-VW24K2Q4.js.map +0 -1
- /package/dist/{chunk-OMSTU233.js.map → chunk-2KAYTPPT.js.map} +0 -0
- /package/dist/{chunk-VYZNWH4J.js.map → chunk-2SXMCQEQ.js.map} +0 -0
- /package/dist/{chunk-NXL5CVE7.js.map → chunk-2Y6LMOQQ.js.map} +0 -0
- /package/dist/{chunk-LQ4J7ELC.js.map → chunk-67HG7KFE.js.map} +0 -0
- /package/dist/{chunk-ZBG4K36I.js.map → chunk-6FUJ2VYY.js.map} +0 -0
- /package/dist/{chunk-GMRNKPWO.js.map → chunk-6QUPUTT7.js.map} +0 -0
- /package/dist/{chunk-Z56IHRVV.js.map → chunk-6UU43ZGD.js.map} +0 -0
- /package/dist/{chunk-APJQ6UEA.js.map → chunk-AGNBY3VG.js.map} +0 -0
- /package/dist/{chunk-OWOKOFXK.js.map → chunk-AJOIM6UR.js.map} +0 -0
- /package/dist/{chunk-JBPKEARU.js.map → chunk-AU7Q3LSC.js.map} +0 -0
- /package/dist/{chunk-K22IJO4R.js.map → chunk-CTOQEZSN.js.map} +0 -0
- /package/dist/{chunk-HSDJCT3V.js.map → chunk-DXGS5YOQ.js.map} +0 -0
- /package/dist/{chunk-HV57RHMD.js.map → chunk-EH5ED3C6.js.map} +0 -0
- /package/dist/{chunk-7NDYFAJS.js.map → chunk-GM3BMWKR.js.map} +0 -0
- /package/dist/{chunk-5QUS24F7.js.map → chunk-I56LKMF7.js.map} +0 -0
- /package/dist/{chunk-35YJ6KCV.js.map → chunk-JEIROMLX.js.map} +0 -0
- /package/dist/{chunk-SKQCFAYU.js.map → chunk-JVEMUX6L.js.map} +0 -0
- /package/dist/{chunk-CXMXAC5R.js.map → chunk-K44MIN6D.js.map} +0 -0
- /package/dist/{chunk-BQCFXAMN.js.map → chunk-MPHDVHIB.js.map} +0 -0
- /package/dist/{chunk-QXNFQKWU.js.map → chunk-MTHNJCOJ.js.map} +0 -0
- /package/dist/{chunk-3TCRU4JA.js.map → chunk-O62P2LFL.js.map} +0 -0
- /package/dist/{chunk-JSDZMOT7.js.map → chunk-OC56UWV5.js.map} +0 -0
- /package/dist/{chunk-7IBEWQLG.js.map → chunk-QOIONSOI.js.map} +0 -0
- /package/dist/{chunk-4P5UAL3C.js.map → chunk-RBHANGVX.js.map} +0 -0
- /package/dist/{chunk-SK2CR6MW.js.map → chunk-RVLB4E6N.js.map} +0 -0
- /package/dist/{chunk-CNVIWMQI.js.map → chunk-UY4JMEAK.js.map} +0 -0
- /package/dist/{chunk-S6FQLQGH.js.map → chunk-V7GDTQ6I.js.map} +0 -0
- /package/dist/{chunk-JNOYYWCA.js.map → chunk-VO4UICII.js.map} +0 -0
- /package/dist/{chunk-54TI5GLV.js.map → chunk-WI4QX7GH.js.map} +0 -0
- /package/dist/{chunk-XKU4YE6Z.js.map → chunk-XZTUMWKQ.js.map} +0 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the conversational memory chat engine (issue #1583).
|
|
3
|
+
*
|
|
4
|
+
* The chat engine is a deliberately bounded tool-loop agent — NOT a general
|
|
5
|
+
* assistant. It exposes a fixed set of read-only and (confirmation-gated)
|
|
6
|
+
* mutating tools, each a thin adapter over an existing access-service method.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// LLM adapter — production signature (rule 33), stubbable for tests
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A single chat message in the LLM conversation.
|
|
15
|
+
*/
|
|
16
|
+
export interface ChatLlmMessage {
|
|
17
|
+
role: "system" | "user" | "assistant" | "tool";
|
|
18
|
+
content: string;
|
|
19
|
+
/** Tool-call id when role === "tool" (correlates the result back). */
|
|
20
|
+
toolCallId?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A tool-call request emitted by the LLM. The engine parses these from the
|
|
25
|
+
* LLM response and dispatches them through the tool registry.
|
|
26
|
+
*/
|
|
27
|
+
export interface ChatLlmToolCall {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
arguments: Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Structured LLM response — either a text reply or a set of tool calls.
|
|
35
|
+
* The adapter (stub or production) is responsible for parsing the raw model
|
|
36
|
+
* output into this shape.
|
|
37
|
+
*/
|
|
38
|
+
export interface ChatLlmResponse {
|
|
39
|
+
/** Assistant text reply (empty when only tool calls are present). */
|
|
40
|
+
content: string;
|
|
41
|
+
/** Tool calls to execute (empty for a final text reply). */
|
|
42
|
+
toolCalls: ChatLlmToolCall[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Production-grade LLM adapter interface. The stub implementation used in
|
|
47
|
+
* tests drives scripted sequences; the production implementation wraps the
|
|
48
|
+
* existing FallbackLlmClient routing chain so local Ollama/vLLM models are
|
|
49
|
+
* fully supported (gotcha 1).
|
|
50
|
+
*/
|
|
51
|
+
export interface ChatLlmAdapter {
|
|
52
|
+
/**
|
|
53
|
+
* Send the conversation so far to the LLM and receive the next response.
|
|
54
|
+
* Returns `null` when no model is available or the request fails (rule 13).
|
|
55
|
+
*/
|
|
56
|
+
complete(
|
|
57
|
+
messages: ChatLlmMessage[],
|
|
58
|
+
options: {
|
|
59
|
+
tools: ChatToolSchema[];
|
|
60
|
+
model?: string;
|
|
61
|
+
signal?: AbortSignal;
|
|
62
|
+
},
|
|
63
|
+
): Promise<ChatLlmResponse | null>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// Tool schema + execution
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* JSON-Schema description of a chat tool, sent to the LLM so it knows what
|
|
72
|
+
* tools are available and how to call them.
|
|
73
|
+
*/
|
|
74
|
+
export interface ChatToolSchema {
|
|
75
|
+
type: "function";
|
|
76
|
+
function: {
|
|
77
|
+
name: string;
|
|
78
|
+
description: string;
|
|
79
|
+
parameters: Record<string, unknown>;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Result of executing a chat tool. Read-only tools return data; mutating
|
|
85
|
+
* tools go through the confirmation protocol before they reach the executor.
|
|
86
|
+
*/
|
|
87
|
+
export interface ChatToolResult {
|
|
88
|
+
/** Structured payload returned to the LLM as a tool message. */
|
|
89
|
+
content: string;
|
|
90
|
+
/** Whether the tool call was intercepted by the confirmation protocol. */
|
|
91
|
+
pendingConfirmation?: boolean;
|
|
92
|
+
/** Plan preview when pendingConfirmation is true. */
|
|
93
|
+
planPreview?: string;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// Chat session — transcript + pending-plan state
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* A single line in the persisted chat transcript (JSONL).
|
|
102
|
+
*/
|
|
103
|
+
export interface ChatTranscriptEntry {
|
|
104
|
+
/** Monotonic sequence number within the session. */
|
|
105
|
+
seq: number;
|
|
106
|
+
/** ISO 8601 timestamp. */
|
|
107
|
+
ts: string;
|
|
108
|
+
role: "user" | "assistant" | "tool" | "system";
|
|
109
|
+
content: string;
|
|
110
|
+
/** Tool-call id for tool messages. */
|
|
111
|
+
toolCallId?: string;
|
|
112
|
+
/** Tool name for tool messages. */
|
|
113
|
+
toolName?: string;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* In-memory session state, backed by the JSONL transcript on disk.
|
|
118
|
+
*/
|
|
119
|
+
export interface ChatSessionState {
|
|
120
|
+
id: string;
|
|
121
|
+
/** Caller principal bound at creation (rule 42). */
|
|
122
|
+
principal?: string;
|
|
123
|
+
/** Session key for namespace resolution. */
|
|
124
|
+
sessionKey?: string;
|
|
125
|
+
/** Namespace override. */
|
|
126
|
+
namespace?: string;
|
|
127
|
+
/** Transcript entries loaded from disk. */
|
|
128
|
+
transcript: ChatTranscriptEntry[];
|
|
129
|
+
/** Plan ids confirmed by the user for exactly one apply. */
|
|
130
|
+
confirmedPlanIds: Set<string>;
|
|
131
|
+
/** The pending plan awaiting confirmation (if any). */
|
|
132
|
+
pendingPlanId?: string;
|
|
133
|
+
/** The pending memory-promotion memory id awaiting confirmation (if any). */
|
|
134
|
+
pendingPromotionId?: string;
|
|
135
|
+
/** Creation timestamp. */
|
|
136
|
+
createdAt: string;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ---------------------------------------------------------------------------
|
|
140
|
+
// Engine turn result
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* What the engine returns for a single user message.
|
|
145
|
+
*/
|
|
146
|
+
export interface ChatTurnResult {
|
|
147
|
+
/** The assistant's text reply (may be partial on budget exhaustion). */
|
|
148
|
+
reply: string;
|
|
149
|
+
/** The chat session id (existing or newly created). */
|
|
150
|
+
chatSessionId: string;
|
|
151
|
+
/** A pending plan awaiting user confirmation, if surfaced. */
|
|
152
|
+
pendingPlan?: {
|
|
153
|
+
planId: string;
|
|
154
|
+
preview: string;
|
|
155
|
+
};
|
|
156
|
+
/** Tool calls that were skipped due to budget exhaustion. */
|
|
157
|
+
skippedTools?: string[];
|
|
158
|
+
/** Whether the reply is a tagged error (rule 13). */
|
|
159
|
+
error?: string;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ---------------------------------------------------------------------------
|
|
163
|
+
// Chat config — re-exported from types.ts (canonical definition).
|
|
164
|
+
// DEFAULT_CHAT_CONFIG lives in chat-config.ts.
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
|
|
167
|
+
export type { ChatConfig } from "../types.js";
|
package/src/cli.ts
CHANGED
|
@@ -95,6 +95,7 @@ import { WebDavServer } from "./network/webdav.js";
|
|
|
95
95
|
import { GraphDashboardServer, type DashboardStatus } from "./dashboard-runtime.js";
|
|
96
96
|
import { EngramAccessService } from "./access-service.js";
|
|
97
97
|
import { EngramAccessHttpServer } from "./access-http.js";
|
|
98
|
+
import { runChatCli } from "./chat/chat-cli.js";
|
|
98
99
|
import {
|
|
99
100
|
buildActionConfidenceInputFromOptions,
|
|
100
101
|
evaluateActionConfidence,
|
|
@@ -2807,6 +2808,7 @@ export async function runAccessMcpServeCliCommand(
|
|
|
2807
2808
|
architectureCardVisible: service.architectureCardSurfaceVisible,
|
|
2808
2809
|
codegraphVisible: service.codegraphSurfaceVisible,
|
|
2809
2810
|
sessionDeltaVisible: service.sessionDeltaSurfaceVisible,
|
|
2811
|
+
chatVisible: service.configRef?.chat?.enabled === true,
|
|
2810
2812
|
correctionVisible: service.correctionSurfaceVisible,
|
|
2811
2813
|
});
|
|
2812
2814
|
await server.runStdio(options.stdin ?? process.stdin, options.stdout ?? process.stdout);
|
|
@@ -9336,6 +9338,24 @@ export function registerCli(
|
|
|
9336
9338
|
}
|
|
9337
9339
|
}
|
|
9338
9340
|
});
|
|
9341
|
+
// ── Chat — conversational memory inspection + correction (#1583) ────
|
|
9342
|
+
cmd
|
|
9343
|
+
.command("chat")
|
|
9344
|
+
.description("Conversational memory inspection and correction (issue #1583)")
|
|
9345
|
+
.option("--session <id>", "Resume an existing chat session")
|
|
9346
|
+
.option("--once", "Process a single message from stdin and exit (non-TTY/scripting)")
|
|
9347
|
+
.option("--principal <principal>", "Trusted principal (defaults to config/env)")
|
|
9348
|
+
.action(async (...args: unknown[]) => {
|
|
9349
|
+
const options = (args[0] ?? {}) as Record<string, unknown>;
|
|
9350
|
+
await runChatCli({
|
|
9351
|
+
service: new EngramAccessService(orchestrator),
|
|
9352
|
+
config: orchestrator.config?.chat,
|
|
9353
|
+
memoryDir: orchestrator.config.memoryDir,
|
|
9354
|
+
principal: resolveAccessPrincipalOverride(options.principal, orchestrator.config.agentAccessHttp.principal),
|
|
9355
|
+
...(typeof options.session === "string" ? { sessionId: options.session } : {}),
|
|
9356
|
+
...(options.once === true ? { once: true } : {}),
|
|
9357
|
+
});
|
|
9358
|
+
});
|
|
9339
9359
|
},
|
|
9340
9360
|
{ commands: ["engram"] },
|
|
9341
9361
|
);
|
package/src/config.ts
CHANGED
|
@@ -47,6 +47,7 @@ import {
|
|
|
47
47
|
import { parseWearablesConfig } from "./wearables/config.js";
|
|
48
48
|
import { parseProvenanceConfig } from "./provenance.js";
|
|
49
49
|
import { parseCodingKnowledgeConfig } from "./coding/coding-knowledge-config.js";
|
|
50
|
+
import { parseChatConfig } from "./chat/chat-config.js";
|
|
50
51
|
const DEFAULT_MEMORY_DIR = path.join(
|
|
51
52
|
resolveHomeDir(),
|
|
52
53
|
".openclaw",
|
|
@@ -2507,6 +2508,7 @@ export function parseConfig(
|
|
|
2507
2508
|
slotBehavior,
|
|
2508
2509
|
codexCompat,
|
|
2509
2510
|
codingKnowledge: parseCodingKnowledgeConfig(cfg.codingKnowledge),
|
|
2511
|
+
chat: parseChatConfig(cfg.chat),
|
|
2510
2512
|
// Hourly summaries
|
|
2511
2513
|
hourlySummariesEnabled: cfg.hourlySummariesEnabled !== false, // default: true
|
|
2512
2514
|
daySummaryEnabled: cfg.daySummaryEnabled !== false, // default: true
|
|
@@ -3246,6 +3248,13 @@ export function parseConfig(
|
|
|
3246
3248
|
// Issue #564 PR 3: off by default; enable explicitly after bench validation.
|
|
3247
3249
|
recallReasoningTraceBoostEnabled:
|
|
3248
3250
|
coerceBool(cfg.recallReasoningTraceBoostEnabled) ?? false,
|
|
3251
|
+
// Issue #1582: off by default — handles are byte-additive at injection time.
|
|
3252
|
+
recallMemoryHandles: coerceBool(cfg.recallMemoryHandles) ?? false,
|
|
3253
|
+
recallHandleSnapshotDepth:
|
|
3254
|
+
typeof cfg.recallHandleSnapshotDepth === "number" &&
|
|
3255
|
+
Number.isFinite(cfg.recallHandleSnapshotDepth)
|
|
3256
|
+
? Math.max(1, Math.min(50, Math.floor(cfg.recallHandleSnapshotDepth)))
|
|
3257
|
+
: 5,
|
|
3249
3258
|
qmdRecallCacheTtlMs:
|
|
3250
3259
|
typeof cfg.qmdRecallCacheTtlMs === "number" ? Math.max(0, Math.floor(cfg.qmdRecallCacheTtlMs)) : 60_000,
|
|
3251
3260
|
qmdRecallCacheStaleTtlMs:
|
|
@@ -25,6 +25,7 @@ import { Orchestrator } from "./orchestrator.js";
|
|
|
25
25
|
import { readEdges } from "./graph.js";
|
|
26
26
|
import type { ExtractionResult, PluginConfig } from "./types.js";
|
|
27
27
|
import type { LocalLlmClient } from "./local-llm.js";
|
|
28
|
+
import type { BufferTurn, ConversationThread } from "./types.js";
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* Stub local LLM whose `chatCompletion` only answers faithfulness-gate calls
|
|
@@ -42,15 +43,20 @@ function faithfulnessStubLocalLlm(
|
|
|
42
43
|
) => {
|
|
43
44
|
if (options.operation !== "extraction-faithfulness") return null;
|
|
44
45
|
const userMsg = messages.find((m) => m.role === "user");
|
|
45
|
-
// The prompt emits `FACT: "<text>"`
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const
|
|
46
|
+
// The batch prompt emits one `FACT: "<text>"` line per fact, each
|
|
47
|
+
// followed by `Respond with the JSON array entry for index <i>`. The
|
|
48
|
+
// gate maps verdicts back to facts by that index, so return one entry
|
|
49
|
+
// per fact in prompt order. (Single-fact callers still get one entry.)
|
|
50
|
+
const factMatches = [...(userMsg?.content ?? "").matchAll(/FACT: "([^"]*)"/g)];
|
|
51
|
+
const entries = factMatches.map((m, i) => ({
|
|
52
|
+
index: i,
|
|
53
|
+
verdict: verdictForFactContent(m[1] ?? ""),
|
|
54
|
+
rationale: "stub verdict",
|
|
55
|
+
}));
|
|
50
56
|
return {
|
|
51
|
-
content: JSON.stringify(
|
|
52
|
-
{ index: 0, verdict, rationale: "stub
|
|
53
|
-
|
|
57
|
+
content: JSON.stringify(
|
|
58
|
+
entries.length > 0 ? entries : [{ index: 0, verdict: "entailed" as const, rationale: "stub" }],
|
|
59
|
+
),
|
|
54
60
|
};
|
|
55
61
|
},
|
|
56
62
|
} as unknown as LocalLlmClient;
|
|
@@ -250,3 +256,203 @@ test("pending_review fact gets no graph edge; an active fact with the same entit
|
|
|
250
256
|
await rm(memoryDir, { recursive: true, force: true });
|
|
251
257
|
}
|
|
252
258
|
});
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Thread-enabled harness for issue #1635: time + causal graph ON (so
|
|
263
|
+
* thread-predecessor edges are built), faithfulness gate in enforce mode.
|
|
264
|
+
* Entity graph is left OFF to isolate the thread-episode predecessor
|
|
265
|
+
* mechanism (entity-sibling edges are a separate, out-of-scope path).
|
|
266
|
+
*/
|
|
267
|
+
async function makeThreadHarness(): Promise<OrchHarness> {
|
|
268
|
+
const memoryDir = await mkdtemp(
|
|
269
|
+
path.join(os.tmpdir(), "remnic-faithfulness-thread-"),
|
|
270
|
+
);
|
|
271
|
+
const config: PluginConfig = parseConfig({
|
|
272
|
+
openaiApiKey: "sk-test",
|
|
273
|
+
memoryDir,
|
|
274
|
+
workspaceDir: path.join(memoryDir, "workspace"),
|
|
275
|
+
multiGraphMemoryEnabled: true,
|
|
276
|
+
entityGraphEnabled: false,
|
|
277
|
+
timeGraphEnabled: true,
|
|
278
|
+
causalGraphEnabled: true,
|
|
279
|
+
extractionFaithfulnessGate: "enforce",
|
|
280
|
+
extractionFaithfulnessContextChars: 400,
|
|
281
|
+
extractionFaithfulnessTimeoutMs: 2000,
|
|
282
|
+
extractionJudgeEnabled: false,
|
|
283
|
+
temporalSupersessionEnabled: false,
|
|
284
|
+
contradictionDetectionEnabled: false,
|
|
285
|
+
chunkingEnabled: false,
|
|
286
|
+
embeddingFallbackEnabled: false,
|
|
287
|
+
qmdEnabled: false,
|
|
288
|
+
extractionMinChars: 0,
|
|
289
|
+
extractionMinImportanceLevel: "trivial",
|
|
290
|
+
inlineSourceAttributionEnabled: false,
|
|
291
|
+
});
|
|
292
|
+
const orchestrator = new Orchestrator(config);
|
|
293
|
+
return { orchestrator, memoryDir };
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/** ExtractionResult with two facts (order preserved by the persist loop). */
|
|
297
|
+
function twoFactResult(
|
|
298
|
+
contentA: string,
|
|
299
|
+
entityRefA: string,
|
|
300
|
+
contentB: string,
|
|
301
|
+
entityRefB: string,
|
|
302
|
+
): ExtractionResult {
|
|
303
|
+
return {
|
|
304
|
+
facts: [
|
|
305
|
+
{ content: contentA, category: "fact", tags: [], confidence: 0.9, entityRef: entityRefA },
|
|
306
|
+
{ content: contentB, category: "fact", tags: [], confidence: 0.9, entityRef: entityRefB },
|
|
307
|
+
],
|
|
308
|
+
entities: [],
|
|
309
|
+
relationships: [],
|
|
310
|
+
questions: [],
|
|
311
|
+
profileUpdates: [],
|
|
312
|
+
} as unknown as ExtractionResult;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
interface StorageLike {
|
|
316
|
+
ensureDirectories: () => Promise<void>;
|
|
317
|
+
dir: string;
|
|
318
|
+
readAllMemories: () => Promise<
|
|
319
|
+
Array<{ path: string; frontmatter: { id: string; status?: string } }>
|
|
320
|
+
>;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
interface PersistExtractionSig {
|
|
324
|
+
(
|
|
325
|
+
r: ExtractionResult,
|
|
326
|
+
s: unknown,
|
|
327
|
+
t: string | null,
|
|
328
|
+
ctx: unknown,
|
|
329
|
+
bn: unknown,
|
|
330
|
+
plan: unknown,
|
|
331
|
+
src: string,
|
|
332
|
+
): Promise<string[]>;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
test("pending_review id must NOT enter persisted thread episodes across a cross-flush (#1635)", async () => {
|
|
336
|
+
const { orchestrator, memoryDir } = await makeThreadHarness();
|
|
337
|
+
try {
|
|
338
|
+
// fact content containing "closed permanently" → unsupported → pending_review.
|
|
339
|
+
(orchestrator as unknown as { localLlm: LocalLlmClient }).localLlm =
|
|
340
|
+
faithfulnessStubLocalLlm((c) =>
|
|
341
|
+
c.includes("closed permanently") ? "unsupported" : "entailed",
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
const getStorage = orchestrator as unknown as {
|
|
345
|
+
getStorage: (ns: string) => Promise<StorageLike>;
|
|
346
|
+
};
|
|
347
|
+
const storage = await getStorage.getStorage("default");
|
|
348
|
+
await storage.ensureDirectories();
|
|
349
|
+
|
|
350
|
+
// Establish a real thread (mirrors runExtraction's processTurn step) so
|
|
351
|
+
// appendEpisodeIds has a thread file to write episode ids into.
|
|
352
|
+
const threading = orchestrator as unknown as {
|
|
353
|
+
threading: {
|
|
354
|
+
processTurn: (turn: BufferTurn, ids: string[]) => Promise<string>;
|
|
355
|
+
loadThread: (id: string) => Promise<ConversationThread | null>;
|
|
356
|
+
};
|
|
357
|
+
};
|
|
358
|
+
const seedTurn: BufferTurn = {
|
|
359
|
+
role: "user",
|
|
360
|
+
content: "Tell me about the widget factory.",
|
|
361
|
+
timestamp: "2026-07-06T10:00:00.000Z",
|
|
362
|
+
sessionKey: "agent:test:main",
|
|
363
|
+
};
|
|
364
|
+
const threadId = await threading.threading.processTurn(seedTurn, []);
|
|
365
|
+
assert.ok(threadId, "thread established via processTurn");
|
|
366
|
+
|
|
367
|
+
const persist = orchestrator as unknown as {
|
|
368
|
+
persistExtraction: PersistExtractionSig;
|
|
369
|
+
appendPersistedThreadEpisodes: (
|
|
370
|
+
threadId: string,
|
|
371
|
+
persistedIds: string[],
|
|
372
|
+
) => Promise<void>;
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
const sourceText =
|
|
376
|
+
"The widget factory reopened this quarter after being closed permanently last year.";
|
|
377
|
+
|
|
378
|
+
// --- Flush 1: an active fact + a pending_review fact, same thread ---
|
|
379
|
+
const flush1 = await persist.persistExtraction(
|
|
380
|
+
twoFactResult(
|
|
381
|
+
"The widget factory reopened this quarter.", "wf-active",
|
|
382
|
+
"The widget factory closed permanently last year.", "wf-pending",
|
|
383
|
+
),
|
|
384
|
+
storage,
|
|
385
|
+
threadId,
|
|
386
|
+
{ sessionKey: "agent:test:main", principal: "test" },
|
|
387
|
+
undefined,
|
|
388
|
+
null,
|
|
389
|
+
sourceText,
|
|
390
|
+
);
|
|
391
|
+
const [activeId1, pendingId] = flush1;
|
|
392
|
+
assert.ok(activeId1, "flush1 active fact persisted");
|
|
393
|
+
assert.ok(pendingId, "flush1 pending_review fact persisted");
|
|
394
|
+
|
|
395
|
+
// runExtraction's append step (the real helper; filters pending_review).
|
|
396
|
+
await persist.appendPersistedThreadEpisodes(threadId, flush1);
|
|
397
|
+
|
|
398
|
+
// PART (a): the thread FILE must hold the active id but NOT the pending id.
|
|
399
|
+
const threadAfter1 = await threading.threading.loadThread(threadId);
|
|
400
|
+
assert.ok(threadAfter1, "thread file readable after flush 1");
|
|
401
|
+
assert.ok(
|
|
402
|
+
threadAfter1!.episodeIds.includes(activeId1),
|
|
403
|
+
"active fact id is in persisted thread episodes",
|
|
404
|
+
);
|
|
405
|
+
assert.ok(
|
|
406
|
+
!threadAfter1!.episodeIds.includes(pendingId),
|
|
407
|
+
"pending_review id must NOT enter persisted thread episodes (#1635)",
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
// The pending fact IS durable (with status pending_review) — proves the
|
|
411
|
+
// gate routed it correctly; the guard is about its absence from the thread.
|
|
412
|
+
const memsAfter1 = await storage.readAllMemories();
|
|
413
|
+
const pendingMem = memsAfter1.find((m) => m.frontmatter.id === pendingId);
|
|
414
|
+
assert.ok(pendingMem, "pending_review fact is durable");
|
|
415
|
+
assert.equal(
|
|
416
|
+
pendingMem!.frontmatter.status,
|
|
417
|
+
"pending_review",
|
|
418
|
+
"unsupported fact is pending_review under enforce",
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
// --- Flush 2: an active fact in the SAME thread ---
|
|
422
|
+
const flush2 = await persist.persistExtraction(
|
|
423
|
+
factResult("The widget factory hired ten new engineers.", "wf-active"),
|
|
424
|
+
storage,
|
|
425
|
+
threadId,
|
|
426
|
+
{ sessionKey: "agent:test:main", principal: "test" },
|
|
427
|
+
undefined,
|
|
428
|
+
null,
|
|
429
|
+
sourceText,
|
|
430
|
+
);
|
|
431
|
+
const activeId2 = flush2[0];
|
|
432
|
+
assert.ok(activeId2, "flush2 active fact persisted");
|
|
433
|
+
await persist.appendPersistedThreadEpisodes(threadId, flush2);
|
|
434
|
+
|
|
435
|
+
// PART (a)+(b): no predecessor edge may reference the pending fact. Under
|
|
436
|
+
// the bug, flush 1 would have appended pendingId to the thread file, flush
|
|
437
|
+
// 2's loadThread would re-seed it into threadEpisodeIdsForGraph, and the
|
|
438
|
+
// active fact2 would build a time/causal predecessor edge to it.
|
|
439
|
+
const pendingPath = path.relative(memoryDir, pendingMem!.path);
|
|
440
|
+
for (const gtype of ["time", "causal"] as const) {
|
|
441
|
+
const edges = await readEdges(memoryDir, gtype);
|
|
442
|
+
assert.ok(
|
|
443
|
+
!edges.some((e) => e.from === pendingPath || e.to === pendingPath),
|
|
444
|
+
`no ${gtype} edge references the pending_review fact path (${pendingPath}); got ${edges.length} edges`,
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// Control: the graph + threading are wired — the active fact2 builds a
|
|
449
|
+
// time predecessor edge to the active fact1 (which IS in the thread file).
|
|
450
|
+
const timeEdges = await readEdges(memoryDir, "time");
|
|
451
|
+
assert.ok(
|
|
452
|
+
timeEdges.length > 0,
|
|
453
|
+
"active fact2 builds a time predecessor edge (control: graph+threading wired)",
|
|
454
|
+
);
|
|
455
|
+
} finally {
|
|
456
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
457
|
+
}
|
|
458
|
+
});
|