@remnic/core 9.63.5 → 9.63.7
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 +1 -1
- package/dist/access-admin-ops-surface.js +27 -25
- package/dist/access-authorization-probe.d.ts +1 -1
- package/dist/access-authorization-probe.js +28 -26
- package/dist/access-boundary.d.ts +1 -1
- package/dist/access-boundary.js +27 -25
- package/dist/access-cli.js +83 -81
- package/dist/access-cli.js.map +1 -1
- package/dist/access-extraction-force-flush.d.ts +1 -1
- package/dist/access-extraction-force-flush.js +27 -25
- package/dist/access-http-lcm-compaction.d.ts +1 -1
- package/dist/access-http-lifecycle-flush.d.ts +1 -1
- package/dist/access-http-offline-stream.d.ts +1 -1
- package/dist/access-http-query.js +29 -27
- package/dist/access-http.d.ts +2 -2
- package/dist/access-http.js +43 -41
- package/dist/access-identity-continuity-surface.js +27 -25
- package/dist/access-lcm-surface.d.ts +1 -1
- package/dist/access-lcm-surface.js +27 -25
- package/dist/access-mcp.d.ts +1 -1
- package/dist/access-mcp.js +34 -32
- package/dist/access-namespace-preflight.js +27 -25
- package/dist/access-observe-write-surface.d.ts +1 -1
- package/dist/access-observe-write-surface.js +27 -25
- package/dist/access-offline-manifest.js +6 -5
- package/dist/access-operations-batch.js +29 -27
- package/dist/access-operations.d.ts +4 -4
- package/dist/access-operations.js +33 -31
- package/dist/access-recall-concurrency.d.ts +1 -1
- package/dist/access-recall-concurrency.js +27 -25
- package/dist/access-recall-response.d.ts +1 -1
- package/dist/access-recall-response.js +27 -25
- package/dist/access-recall-surface.d.ts +1 -1
- package/dist/access-recall-surface.js +27 -25
- package/dist/access-schema.d.ts +88 -88
- package/dist/access-schema.js +6 -5
- package/dist/access-service-helpers.d.ts +1 -1
- package/dist/access-service.d.ts +1 -1
- package/dist/access-service.js +27 -25
- package/dist/access-surface-catalog.d.ts +1 -1
- package/dist/access-surface-catalog.js +29 -27
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/active-recall.js +5 -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/{auto-sync-BKRJDMKX.js → auto-sync-3SHMZVQS.js} +5 -3
- package/dist/{auto-sync-BKRJDMKX.js.map → auto-sync-3SHMZVQS.js.map} +1 -1
- package/dist/briefing.js +10 -10
- package/dist/calibration.d.ts +2 -1
- package/dist/calibration.js +7 -0
- package/dist/calibration.js.map +1 -1
- package/dist/causal-consolidation.js +11 -11
- package/dist/census-validation.d.ts +19 -0
- package/dist/census-validation.js +14 -0
- package/dist/census-validation.js.map +1 -0
- package/dist/{chunk-LEPOP46W.js → chunk-227UFSEQ.js} +4 -4
- package/dist/{chunk-Z4N7SVVF.js → chunk-2L7DKNVE.js} +12 -7
- package/dist/chunk-2L7DKNVE.js.map +1 -0
- package/dist/{chunk-3Z5TGRFA.js → chunk-3NZAVWU5.js} +9 -9
- package/dist/{chunk-I5FLIB2J.js → chunk-3S3PNR5H.js} +2 -2
- package/dist/{chunk-R6UMNP5C.js → chunk-3T6HIIKA.js} +2 -2
- package/dist/{chunk-77QZW2D6.js → chunk-3TDAA7VA.js} +2 -2
- package/dist/{chunk-TWTUGCTY.js → chunk-3YTTAGPB.js} +6 -1
- package/dist/chunk-3YTTAGPB.js.map +1 -0
- package/dist/{chunk-DXDAQZ2K.js → chunk-42TIIO2M.js} +2 -2
- package/dist/{chunk-Y7COCXY2.js → chunk-4F67JJPG.js} +2 -2
- package/dist/{chunk-PB4WVYGC.js → chunk-5S5DUJFJ.js} +2 -2
- package/dist/{chunk-KYTRF64R.js → chunk-5SCFDQEJ.js} +2 -2
- package/dist/{chunk-GG4DN63W.js → chunk-62Y5AGCM.js} +2 -2
- package/dist/{chunk-KHCUVYCY.js → chunk-6UKSOXAO.js} +3 -3
- package/dist/{chunk-F6JYBVL6.js → chunk-7ZAC2C2U.js} +24 -24
- package/dist/{chunk-GF7RQWXC.js → chunk-AJRJDXYR.js} +2 -2
- package/dist/{chunk-YEQCMA5L.js → chunk-BOSIHHOH.js} +2 -2
- package/dist/{chunk-7LF2OHIJ.js → chunk-BRHKW7GY.js} +2 -2
- package/dist/{chunk-LX4TNSAE.js → chunk-CBY54QYW.js} +4 -4
- package/dist/chunk-FEHIOYML.js +168 -0
- package/dist/chunk-FEHIOYML.js.map +1 -0
- package/dist/{chunk-6YMEU6OQ.js → chunk-G72IPMR7.js} +2 -2
- package/dist/{chunk-7AF243WZ.js → chunk-GBVRVYF4.js} +1 -1
- package/dist/{chunk-GTD4Q62X.js → chunk-H4GQ2Y24.js} +3 -3
- package/dist/{chunk-QI5RDDEL.js → chunk-HXZNTZ3Y.js} +6 -6
- package/dist/{chunk-CIAI24TQ.js → chunk-IBZQQOM5.js} +3 -3
- package/dist/{chunk-RYST72N5.js → chunk-IINVXO3U.js} +4 -154
- package/dist/chunk-IINVXO3U.js.map +1 -0
- package/dist/{chunk-R7TZ2HCS.js → chunk-JG22O53B.js} +58 -3
- package/dist/chunk-JG22O53B.js.map +1 -0
- package/dist/{chunk-VPHSMJ2E.js → chunk-JPWSYHLB.js} +2 -2
- package/dist/{chunk-X7LEDA74.js → chunk-KFB4YNXM.js} +2 -2
- package/dist/{chunk-IPLYGWQF.js → chunk-KQAFEZQX.js} +5 -5
- package/dist/chunk-LQWOFU6L.js +17 -0
- package/dist/chunk-LQWOFU6L.js.map +1 -0
- package/dist/{chunk-ZUPKNWRZ.js → chunk-MIUL6AUZ.js} +3 -3
- package/dist/{chunk-EJY3HJMT.js → chunk-MYI3RKI6.js} +2 -2
- package/dist/{chunk-NA56NSKL.js → chunk-OOJCXJBN.js} +2 -2
- package/dist/{chunk-7KQB4EBS.js → chunk-OPPBTPUU.js} +4 -4
- package/dist/{chunk-ERPBRXVZ.js → chunk-PZKWPXRF.js} +2 -2
- package/dist/{chunk-FHKXVTM5.js → chunk-Q5XKKDFQ.js} +16 -16
- package/dist/{chunk-QRWMS6SI.js → chunk-Q6OL23WM.js} +2 -2
- package/dist/{chunk-OW7NVMGQ.js → chunk-QIZOU3FN.js} +2 -2
- package/dist/{chunk-V3KIRICY.js → chunk-QQYHYW2N.js} +3 -3
- package/dist/{chunk-YFCEBB5P.js → chunk-QTXNS3HB.js} +2 -2
- package/dist/{chunk-2QSZNTDO.js → chunk-RKNJBZ55.js} +4 -4
- package/dist/{chunk-E4KMY4KR.js → chunk-SNEUAZ6B.js} +2 -2
- package/dist/{chunk-TSTI6A3A.js → chunk-SYJW273H.js} +11 -11
- package/dist/{chunk-EFKZT6AY.js → chunk-T42L3S6A.js} +6 -11
- package/dist/chunk-T42L3S6A.js.map +1 -0
- package/dist/{chunk-YXMHUBN2.js → chunk-TOP3FSDW.js} +25 -102
- package/dist/chunk-TOP3FSDW.js.map +1 -0
- package/dist/{chunk-PBRCYYO7.js → chunk-ULZFZL7K.js} +2 -2
- package/dist/{chunk-UGHCZS6K.js → chunk-VFZQXYN5.js} +2 -2
- package/dist/{chunk-IVXVLDNT.js → chunk-WKJTMXME.js} +37 -54
- package/dist/chunk-WKJTMXME.js.map +1 -0
- package/dist/{chunk-NKB43PGI.js → chunk-WZDTSBGQ.js} +2 -2
- package/dist/{chunk-2UM6WHME.js → chunk-XE2QCCT2.js} +2 -2
- package/dist/{chunk-FPEZ74F7.js → chunk-XNJQZLAP.js} +3 -3
- package/dist/{chunk-SYVGVK4S.js → chunk-XTMYB2HY.js} +2 -2
- package/dist/{chunk-OETHJBAL.js → chunk-XV6PUXJ5.js} +71 -71
- package/dist/{chunk-UCLMKNHA.js → chunk-YIMV2KYM.js} +2 -2
- package/dist/{chunk-DYZR3Z6D.js → chunk-YMQKPSB2.js} +4 -4
- package/dist/{chunk-AYVCKGA6.js → chunk-YTXNDEUS.js} +2 -2
- package/dist/{chunk-L3CHRBHE.js → chunk-ZRUEP4IK.js} +17 -11
- package/dist/chunk-ZRUEP4IK.js.map +1 -0
- package/dist/{cli-BFBDYV0D.d.ts → cli-BTNj5DzK.d.ts} +1 -1
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +59 -57
- package/dist/compounding/engine.js +10 -10
- package/dist/config.js +5 -3
- package/dist/connectors/codex-materialize-runner.js +10 -10
- package/dist/connectors/index.js +10 -10
- package/dist/consolidation-provenance-check.js +2 -2
- package/dist/convergence-refresh.js +12 -12
- package/dist/conversation-index/backend.js +2 -2
- package/dist/corpus-watermark.js +12 -12
- package/dist/entity-retrieval.js +10 -10
- package/dist/external-wiki-access.d.ts +1 -1
- package/dist/external-wiki-access.js +28 -26
- package/dist/external-wiki-mcp-tools.d.ts +1 -1
- package/dist/extraction-judge.d.ts +2 -1
- package/dist/extraction-judge.js +6 -1
- package/dist/extraction-normalization.js +2 -2
- package/dist/extraction-prompt.d.ts +20 -1
- package/dist/extraction-prompt.js +11 -1
- package/dist/extraction.js +13 -13
- package/dist/{first-start-migration-4NETATFF.js → first-start-migration-Q2VB2E2D.js} +4 -4
- package/dist/harmonic-retrieval.js +1 -1
- package/dist/index.d.ts +680 -680
- package/dist/index.js +92 -90
- package/dist/maintenance/memory-governance.js +10 -10
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +10 -10
- package/dist/maintenance/rebuild-memory-projection.js +11 -11
- package/dist/mcp-memory-inspector-app.d.ts +1 -1
- package/dist/namespaces/migrate.js +11 -11
- package/dist/namespaces/search.js +4 -4
- package/dist/namespaces/storage.js +10 -10
- package/dist/offline-sync.js +3 -2
- package/dist/operator-doctor-corpus.js +13 -13
- package/dist/operator-toolkit.js +24 -22
- package/dist/orchestration/maintenance.js +16 -16
- package/dist/orchestrator.js +85 -83
- package/dist/{public-http-8PcrDIYi.d.ts → public-http-BmPktTe3.d.ts} +1 -1
- package/dist/reconcile/cursor.js +7 -3
- package/dist/reconcile/cursor.js.map +1 -1
- package/dist/reconcile/manifest.js +3 -7
- package/dist/reconcile/plan.d.ts +15 -1
- package/dist/reconcile/plan.js +6 -10
- package/dist/resume-bundles.js +6 -4
- package/dist/schemas.d.ts +108 -108
- package/dist/search/factory.js +3 -3
- package/dist/search/index.js +3 -3
- package/dist/semantic-consolidation.js +16 -16
- package/dist/semantic-rule-promotion.js +10 -10
- package/dist/semantic-rule-verifier.js +10 -10
- package/dist/shared-context/manager.d.ts +8 -8
- package/dist/source-agent-qualifier.js +10 -10
- package/dist/storage.js +9 -9
- package/dist/support-passport/index.d.ts +4 -4
- package/dist/support-passport/index.js +30 -28
- package/dist/transfer/autodetect.js +1 -1
- package/dist/transfer/backup.js +1 -1
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/types.d.ts +66 -66
- package/dist/verified-recall.js +10 -10
- package/package.json +2 -2
- package/src/calibration.ts +3 -1
- package/src/census-validation.ts +25 -0
- package/src/coding/architecture-surfaces.test.ts +9 -10
- package/src/coding/architecture-surfaces.ts +2 -35
- package/src/coding/codegraph-runtime-loader.test.ts +228 -0
- package/src/coding/codegraph-runtime.ts +30 -50
- package/src/coding/codegraph-surfaces.ts +2 -2
- package/src/coding/coding-knowledge-config.ts +35 -1
- package/src/coding/decision-surfaces.test.ts +9 -10
- package/src/coding/decision-surfaces.ts +2 -40
- package/src/coding/session-delta-surfaces.test.ts +9 -10
- package/src/coding/session-delta-surfaces.ts +2 -33
- package/src/extraction-judge.ts +3 -1
- package/src/extraction-output-language.test.ts +116 -0
- package/src/extraction-prompt.ts +70 -1
- package/src/extraction.ts +23 -95
- package/src/offline-sync.ts +4 -4
- package/src/reconcile/census-parity.test.ts +152 -0
- package/src/reconcile/cursor.ts +5 -5
- package/src/reconcile/manifest.ts +4 -11
- package/src/reconcile/plan.ts +18 -15
- package/dist/chunk-EFKZT6AY.js.map +0 -1
- package/dist/chunk-IVXVLDNT.js.map +0 -1
- package/dist/chunk-L3CHRBHE.js.map +0 -1
- package/dist/chunk-R7TZ2HCS.js.map +0 -1
- package/dist/chunk-RYST72N5.js.map +0 -1
- package/dist/chunk-TWTUGCTY.js.map +0 -1
- package/dist/chunk-YXMHUBN2.js.map +0 -1
- package/dist/chunk-Z4N7SVVF.js.map +0 -1
- package/dist/{access-service-cKQrte9Z.d.ts → access-service-CocW74uA.d.ts} +64 -64
- /package/dist/{chunk-LEPOP46W.js.map → chunk-227UFSEQ.js.map} +0 -0
- /package/dist/{chunk-3Z5TGRFA.js.map → chunk-3NZAVWU5.js.map} +0 -0
- /package/dist/{chunk-I5FLIB2J.js.map → chunk-3S3PNR5H.js.map} +0 -0
- /package/dist/{chunk-R6UMNP5C.js.map → chunk-3T6HIIKA.js.map} +0 -0
- /package/dist/{chunk-77QZW2D6.js.map → chunk-3TDAA7VA.js.map} +0 -0
- /package/dist/{chunk-DXDAQZ2K.js.map → chunk-42TIIO2M.js.map} +0 -0
- /package/dist/{chunk-Y7COCXY2.js.map → chunk-4F67JJPG.js.map} +0 -0
- /package/dist/{chunk-PB4WVYGC.js.map → chunk-5S5DUJFJ.js.map} +0 -0
- /package/dist/{chunk-KYTRF64R.js.map → chunk-5SCFDQEJ.js.map} +0 -0
- /package/dist/{chunk-GG4DN63W.js.map → chunk-62Y5AGCM.js.map} +0 -0
- /package/dist/{chunk-KHCUVYCY.js.map → chunk-6UKSOXAO.js.map} +0 -0
- /package/dist/{chunk-F6JYBVL6.js.map → chunk-7ZAC2C2U.js.map} +0 -0
- /package/dist/{chunk-GF7RQWXC.js.map → chunk-AJRJDXYR.js.map} +0 -0
- /package/dist/{chunk-YEQCMA5L.js.map → chunk-BOSIHHOH.js.map} +0 -0
- /package/dist/{chunk-7LF2OHIJ.js.map → chunk-BRHKW7GY.js.map} +0 -0
- /package/dist/{chunk-LX4TNSAE.js.map → chunk-CBY54QYW.js.map} +0 -0
- /package/dist/{chunk-6YMEU6OQ.js.map → chunk-G72IPMR7.js.map} +0 -0
- /package/dist/{chunk-7AF243WZ.js.map → chunk-GBVRVYF4.js.map} +0 -0
- /package/dist/{chunk-GTD4Q62X.js.map → chunk-H4GQ2Y24.js.map} +0 -0
- /package/dist/{chunk-QI5RDDEL.js.map → chunk-HXZNTZ3Y.js.map} +0 -0
- /package/dist/{chunk-CIAI24TQ.js.map → chunk-IBZQQOM5.js.map} +0 -0
- /package/dist/{chunk-VPHSMJ2E.js.map → chunk-JPWSYHLB.js.map} +0 -0
- /package/dist/{chunk-X7LEDA74.js.map → chunk-KFB4YNXM.js.map} +0 -0
- /package/dist/{chunk-IPLYGWQF.js.map → chunk-KQAFEZQX.js.map} +0 -0
- /package/dist/{chunk-ZUPKNWRZ.js.map → chunk-MIUL6AUZ.js.map} +0 -0
- /package/dist/{chunk-EJY3HJMT.js.map → chunk-MYI3RKI6.js.map} +0 -0
- /package/dist/{chunk-NA56NSKL.js.map → chunk-OOJCXJBN.js.map} +0 -0
- /package/dist/{chunk-7KQB4EBS.js.map → chunk-OPPBTPUU.js.map} +0 -0
- /package/dist/{chunk-ERPBRXVZ.js.map → chunk-PZKWPXRF.js.map} +0 -0
- /package/dist/{chunk-FHKXVTM5.js.map → chunk-Q5XKKDFQ.js.map} +0 -0
- /package/dist/{chunk-QRWMS6SI.js.map → chunk-Q6OL23WM.js.map} +0 -0
- /package/dist/{chunk-OW7NVMGQ.js.map → chunk-QIZOU3FN.js.map} +0 -0
- /package/dist/{chunk-V3KIRICY.js.map → chunk-QQYHYW2N.js.map} +0 -0
- /package/dist/{chunk-YFCEBB5P.js.map → chunk-QTXNS3HB.js.map} +0 -0
- /package/dist/{chunk-2QSZNTDO.js.map → chunk-RKNJBZ55.js.map} +0 -0
- /package/dist/{chunk-E4KMY4KR.js.map → chunk-SNEUAZ6B.js.map} +0 -0
- /package/dist/{chunk-TSTI6A3A.js.map → chunk-SYJW273H.js.map} +0 -0
- /package/dist/{chunk-PBRCYYO7.js.map → chunk-ULZFZL7K.js.map} +0 -0
- /package/dist/{chunk-UGHCZS6K.js.map → chunk-VFZQXYN5.js.map} +0 -0
- /package/dist/{chunk-NKB43PGI.js.map → chunk-WZDTSBGQ.js.map} +0 -0
- /package/dist/{chunk-2UM6WHME.js.map → chunk-XE2QCCT2.js.map} +0 -0
- /package/dist/{chunk-FPEZ74F7.js.map → chunk-XNJQZLAP.js.map} +0 -0
- /package/dist/{chunk-SYVGVK4S.js.map → chunk-XTMYB2HY.js.map} +0 -0
- /package/dist/{chunk-OETHJBAL.js.map → chunk-XV6PUXJ5.js.map} +0 -0
- /package/dist/{chunk-UCLMKNHA.js.map → chunk-YIMV2KYM.js.map} +0 -0
- /package/dist/{chunk-DYZR3Z6D.js.map → chunk-YMQKPSB2.js.map} +0 -0
- /package/dist/{chunk-AYVCKGA6.js.map → chunk-YTXNDEUS.js.map} +0 -0
- /package/dist/{first-start-migration-4NETATFF.js.map → first-start-migration-Q2VB2E2D.js.map} +0 -0
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
type SessionDeltaGitInvoker,
|
|
38
38
|
type SessionDeltaResult,
|
|
39
39
|
} from "./session-delta.js";
|
|
40
|
+
import { isCodingKnowledgeFeatureEnabled } from "./coding-knowledge-config.js";
|
|
40
41
|
import { log } from "../logger.js";
|
|
41
42
|
|
|
42
43
|
// ──────────────────────────────────────────────────────────────────────────
|
|
@@ -59,38 +60,6 @@ export function formatDeltaSubcommands(): string {
|
|
|
59
60
|
return DELTA_SUBCOMMANDS.join(", ");
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
// ──────────────────────────────────────────────────────────────────────────
|
|
63
|
-
// Gate predicates — rule 39: one predicate, identical on every surface
|
|
64
|
-
// ──────────────────────────────────────────────────────────────────────────
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* The single session-delta surface gate. Returns `true` only when:
|
|
68
|
-
* 1. `codingKnowledge.enabled` is true,
|
|
69
|
-
* 2. `codingKnowledge.sessionDelta` is true,
|
|
70
|
-
* 3. a coding context is attached (so a repo root is available).
|
|
71
|
-
*/
|
|
72
|
-
export function isSessionDeltaSurfaceEnabled(
|
|
73
|
-
config: CodingKnowledgeConfig,
|
|
74
|
-
codingContext: CodingContext | null | undefined,
|
|
75
|
-
): boolean {
|
|
76
|
-
return (
|
|
77
|
-
config.enabled === true &&
|
|
78
|
-
config.sessionDelta === true &&
|
|
79
|
-
codingContext !== null &&
|
|
80
|
-
codingContext !== undefined
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Config-only visibility gate — used by the MCP constructor to decide
|
|
86
|
-
* whether to advertise `engram.coding_delta` in `tools/list`. When this
|
|
87
|
-
* returns `false` the tools array is byte-identical to pre-feature (rule 39).
|
|
88
|
-
*/
|
|
89
|
-
export function isSessionDeltaSurfaceVisible(
|
|
90
|
-
config: CodingKnowledgeConfig,
|
|
91
|
-
): boolean {
|
|
92
|
-
return config.enabled === true && config.sessionDelta === true;
|
|
93
|
-
}
|
|
94
63
|
|
|
95
64
|
// ──────────────────────────────────────────────────────────────────────────
|
|
96
65
|
// Surface request / response shapes
|
|
@@ -222,7 +191,7 @@ export async function handleCodingDelta(
|
|
|
222
191
|
: null;
|
|
223
192
|
if (
|
|
224
193
|
codingContext === null ||
|
|
225
|
-
!
|
|
194
|
+
!isCodingKnowledgeFeatureEnabled(ctx.codingKnowledge, "sessionDelta", codingContext)
|
|
226
195
|
) {
|
|
227
196
|
ctx.throwInputError(
|
|
228
197
|
"coding_delta requires codingKnowledge.enabled, codingKnowledge.sessionDelta, and an attached coding context",
|
package/src/extraction-judge.ts
CHANGED
|
@@ -20,6 +20,7 @@ import type { LocalLlmClient } from "./local-llm.js";
|
|
|
20
20
|
import { type FallbackLlmClient, gatewayTaskChainOptions } from "./fallback-llm.js";
|
|
21
21
|
import { extractJsonCandidates } from "./json-extract.js";
|
|
22
22
|
import { normalizeProcedureSteps } from "./procedural/procedure-types.js";
|
|
23
|
+
import { OUTPUT_LANGUAGE_POLICY } from "./extraction-prompt.js";
|
|
23
24
|
|
|
24
25
|
// ---------------------------------------------------------------------------
|
|
25
26
|
// Public interfaces
|
|
@@ -210,7 +211,7 @@ export interface JudgeVerdictObservation {
|
|
|
210
211
|
// Prompt (embedded; mirrors prompts/extraction_judge.prompt.md)
|
|
211
212
|
// ---------------------------------------------------------------------------
|
|
212
213
|
|
|
213
|
-
const JUDGE_SYSTEM_PROMPT = `You are a memory curator evaluating whether extracted facts are **durable** — worth storing for long-term recall across sessions.
|
|
214
|
+
export const JUDGE_SYSTEM_PROMPT = `You are a memory curator evaluating whether extracted facts are **durable** — worth storing for long-term recall across sessions.
|
|
214
215
|
|
|
215
216
|
A fact is **durable** if it will still be useful 30+ days from now and is relevant across multiple sessions, not just the current task.
|
|
216
217
|
|
|
@@ -252,6 +253,7 @@ Rules:
|
|
|
252
253
|
2. When in doubt between accept and reject, lean toward accept — false negatives (losing a useful fact) are worse than false positives (keeping a marginal one).
|
|
253
254
|
3. Use defer only when another turn of context would genuinely change the verdict.
|
|
254
255
|
4. Output valid JSON only. No markdown fences, no commentary.
|
|
256
|
+
5. ${OUTPUT_LANGUAGE_POLICY}
|
|
255
257
|
|
|
256
258
|
Example output:
|
|
257
259
|
[{"index": 0, "kind": "accept", "durable": true, "reason": "Stable personal preference"}, {"index": 1, "kind": "reject", "durable": false, "reason": "Ephemeral build status"}, {"index": 2, "kind": "defer", "durable": false, "reason": "Ambiguous pronoun"}]`;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { parseConfig } from "./config.js";
|
|
5
|
+
import { CLUSTER_PROMPT } from "./calibration.js";
|
|
6
|
+
import { ExtractionEngine } from "./extraction.js";
|
|
7
|
+
import { JUDGE_SYSTEM_PROMPT } from "./extraction-judge.js";
|
|
8
|
+
import {
|
|
9
|
+
OUTPUT_LANGUAGE_POLICY,
|
|
10
|
+
buildConsolidationSystemPrompt,
|
|
11
|
+
buildExtractionInstructions,
|
|
12
|
+
buildProfileConsolidationSystemPrompt,
|
|
13
|
+
} from "./extraction-prompt.js";
|
|
14
|
+
import type { BufferTurn } from "./types.js";
|
|
15
|
+
|
|
16
|
+
// Issue #2190: prompts that produce memory content must embed the
|
|
17
|
+
// output-language policy so a non-English conversation is not silently
|
|
18
|
+
// translated to English — translated memories fail later lexical recall.
|
|
19
|
+
const ENGLISH_OUTPUT_DIRECTIVE_RE =
|
|
20
|
+
/\b(?:write|respond|answer|output|produce|always reply)[^.]{0,60}\bin English\b/i;
|
|
21
|
+
|
|
22
|
+
// Japanese fixture: a non-English conversation that must stay Japanese.
|
|
23
|
+
const JAPANESE_TURNS: BufferTurn[] = [
|
|
24
|
+
{ role: "user", content: "私は毎朝緑茶を飲みます。", timestamp: "2026-08-17T01:00:00.000Z" },
|
|
25
|
+
{ role: "assistant", content: "承知しました。", timestamp: "2026-08-17T01:00:05.000Z" },
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
function allInstructionPrompts(): string[] {
|
|
29
|
+
const config = parseConfig({});
|
|
30
|
+
return [
|
|
31
|
+
buildExtractionInstructions(config),
|
|
32
|
+
buildConsolidationSystemPrompt(config),
|
|
33
|
+
buildProfileConsolidationSystemPrompt(50),
|
|
34
|
+
JUDGE_SYSTEM_PROMPT,
|
|
35
|
+
CLUSTER_PROMPT,
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
test("extraction, consolidation, and profile-consolidation prompts embed the output-language policy", () => {
|
|
40
|
+
const config = parseConfig({});
|
|
41
|
+
assert.ok(
|
|
42
|
+
buildExtractionInstructions(config).includes(OUTPUT_LANGUAGE_POLICY),
|
|
43
|
+
"extraction instructions missing policy",
|
|
44
|
+
);
|
|
45
|
+
assert.ok(
|
|
46
|
+
buildConsolidationSystemPrompt(config).includes(OUTPUT_LANGUAGE_POLICY),
|
|
47
|
+
"consolidation prompt missing policy",
|
|
48
|
+
);
|
|
49
|
+
assert.ok(
|
|
50
|
+
buildProfileConsolidationSystemPrompt(50).includes(OUTPUT_LANGUAGE_POLICY),
|
|
51
|
+
"profile-consolidation prompt missing policy",
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("judge and calibration prompts embed the output-language policy", () => {
|
|
56
|
+
assert.ok(JUDGE_SYSTEM_PROMPT.includes(OUTPUT_LANGUAGE_POLICY), "judge prompt missing policy");
|
|
57
|
+
assert.ok(CLUSTER_PROMPT.includes(OUTPUT_LANGUAGE_POLICY), "calibration prompt missing policy");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("no prompt surface instructs English output", () => {
|
|
61
|
+
for (const prompt of allInstructionPrompts()) {
|
|
62
|
+
assert.doesNotMatch(prompt, ENGLISH_OUTPUT_DIRECTIVE_RE);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("local extraction of a Japanese conversation keeps the source language and is not told to emit English", async () => {
|
|
67
|
+
const engine = new ExtractionEngine(
|
|
68
|
+
parseConfig({
|
|
69
|
+
localLlmEnabled: true,
|
|
70
|
+
localLlmModel: "fixture-local",
|
|
71
|
+
localLlmFallback: false,
|
|
72
|
+
}),
|
|
73
|
+
);
|
|
74
|
+
let capturedPrompt = "";
|
|
75
|
+
const localLlm = {
|
|
76
|
+
async chatCompletion(messages: { content: string }[]) {
|
|
77
|
+
capturedPrompt = messages.map((m) => m.content).join("\n");
|
|
78
|
+
return {
|
|
79
|
+
content: JSON.stringify({
|
|
80
|
+
facts: [
|
|
81
|
+
{
|
|
82
|
+
category: "preference",
|
|
83
|
+
content: "私は毎朝緑茶を飲みます。",
|
|
84
|
+
confidence: 0.9,
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
profileUpdates: [],
|
|
88
|
+
entities: [],
|
|
89
|
+
questions: [],
|
|
90
|
+
relationships: [],
|
|
91
|
+
}),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
const modelRegistry = {
|
|
96
|
+
calculateContextSizes: () => ({
|
|
97
|
+
maxInputChars: 8_000,
|
|
98
|
+
maxOutputTokens: 1_000,
|
|
99
|
+
description: "fixture",
|
|
100
|
+
}),
|
|
101
|
+
};
|
|
102
|
+
assert.equal(Reflect.set(engine, "localLlm", localLlm), true);
|
|
103
|
+
assert.equal(Reflect.set(engine, "modelRegistry", modelRegistry), true);
|
|
104
|
+
const result = await engine.extract(JAPANESE_TURNS);
|
|
105
|
+
|
|
106
|
+
assert.ok(capturedPrompt.length > 0, "no prompt captured from local extraction");
|
|
107
|
+
assert.ok(
|
|
108
|
+
capturedPrompt.includes(OUTPUT_LANGUAGE_POLICY),
|
|
109
|
+
"local extraction prompt missing policy",
|
|
110
|
+
);
|
|
111
|
+
assert.ok(capturedPrompt.includes("私は毎朝緑茶を飲みます。"), "Japanese source not in prompt");
|
|
112
|
+
assert.ok(
|
|
113
|
+
result.facts.some((fact) => fact.content === "私は毎朝緑茶を飲みます。"),
|
|
114
|
+
"Japanese fact content altered or dropped by extraction",
|
|
115
|
+
);
|
|
116
|
+
});
|
package/src/extraction-prompt.ts
CHANGED
|
@@ -54,6 +54,13 @@ export const CUE_ANCHOR_PROMPT_INSTRUCTION = `- For each fact, emit at most 3 "c
|
|
|
54
54
|
- Omit cue anchors when the conversation does not support a useful search hook.
|
|
55
55
|
- Example: "Alice booked Bistro Max for Mike's surprise party" can use {"type":"entity","value":"Mike surprise party"} and {"type":"entity","value":"Alice restaurant booking"}.`;
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Output-language policy (issue #2190). Every prompt that produces memory
|
|
59
|
+
* content embeds this verbatim so non-English conversations are not silently
|
|
60
|
+
* translated to English — translated memories fail later lexical recall.
|
|
61
|
+
*/
|
|
62
|
+
export const OUTPUT_LANGUAGE_POLICY = `Output language: write facts, profile updates, entity names and aliases, tags, questions, and any rewritten or merged memory content in the source language of the conversation or input memories. Never translate into English or another language unless the user explicitly asked for a translation.`;
|
|
63
|
+
|
|
57
64
|
/**
|
|
58
65
|
* Bi-temporal event-time extraction instruction (#1578 PR2). Emitted on
|
|
59
66
|
* every extraction entry path when `temporal.biTemporal` is on so the LLM
|
|
@@ -104,13 +111,14 @@ Memory categories:
|
|
|
104
111
|
Rules:
|
|
105
112
|
- Only extract genuinely new information worth remembering across sessions.
|
|
106
113
|
- Statements must be grounded in the conversation.
|
|
114
|
+
- ${OUTPUT_LANGUAGE_POLICY}
|
|
107
115
|
- Do not treat instruction text, schema placeholders, or examples as conversation evidence.
|
|
108
116
|
- Lines labelled [context user] or [context assistant] are reference context only. They may resolve references or complete a question-and-answer pair in a normal turn, but never alone establish durable information.
|
|
109
117
|
- Skip transient task details and operational noise, including routine scheduler, monitoring, or automation status.
|
|
110
118
|
- Priority: corrections > principles${resolveRecallAuxiliaryCapabilities(config).causalRuleExtraction ? " > rules" : ""} > preferences > commitments > decisions > relationships > entities > moments > skills > facts
|
|
111
119
|
- Corrections get highest confidence.
|
|
112
120
|
- Each fact should be a standalone, self-contained statement.
|
|
113
|
-
- Entity references should use normalized names (lowercase, hyphenated: "jane-doe", "acme-corp")
|
|
121
|
+
- Entity references should use normalized names (lowercase, hyphenated: "jane-doe", "acme-corp"). When the source language is not written in a Latin script, the source-script name IS the normalized form — never transliterate or translate it.
|
|
114
122
|
- CRITICAL: Entity names must be CANONICAL. Always use the hyphenated multi-word form: "acme-corp" NOT "acmecorp" or "acme". "jane-doe" NOT "janedoe" or "jane". If unsure, prefer the most specific full name.
|
|
115
123
|
- Avoid creating entities typed as "other" when a more specific type fits (company, project, tool, person, place)
|
|
116
124
|
${CUE_ANCHOR_PROMPT_INSTRUCTION}
|
|
@@ -174,3 +182,64 @@ Questions are optional. Include only source-grounded unresolved questions that w
|
|
|
174
182
|
|
|
175
183
|
Finally, write a brief identity reflection about the agent who had this conversation, based only on the conversation. Do not write about the extraction process.`;
|
|
176
184
|
}
|
|
185
|
+
|
|
186
|
+
export const CONSOLIDATION_RESPONSE_SCHEMA = `{
|
|
187
|
+
"items": [
|
|
188
|
+
{
|
|
189
|
+
"existingId": "id",
|
|
190
|
+
"action": "ADD",
|
|
191
|
+
"mergeWith": "optional-existing-id",
|
|
192
|
+
"updatedContent": "optional replacement content",
|
|
193
|
+
"reason": "brief reason for this action"
|
|
194
|
+
}
|
|
195
|
+
],
|
|
196
|
+
"profileUpdates": ["optional profile update"],
|
|
197
|
+
"entityUpdates": [{"name": "person-jane-doe", "type": "person", "facts": ["Now leads the backend team", "Recently migrated the user service to TypeScript"]}]
|
|
198
|
+
}`;
|
|
199
|
+
|
|
200
|
+
export const PROFILE_CONSOLIDATION_RESPONSE_SCHEMA = `{
|
|
201
|
+
"consolidatedProfile": "# Behavioral Profile\\n\\n... (complete markdown)",
|
|
202
|
+
"removedCount": 42,
|
|
203
|
+
"summary": "brief summary of what was consolidated"
|
|
204
|
+
}`;
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* System prompt shared by every consolidation path (gateway, direct client,
|
|
208
|
+
* local LLM). Owns the causal-rule clause and the output-language policy so
|
|
209
|
+
* the three paths cannot drift (issue #2190).
|
|
210
|
+
*/
|
|
211
|
+
export function buildConsolidationSystemPrompt(config: PluginConfig): string {
|
|
212
|
+
return `You are a memory consolidation system. Compare new memories against existing ones and decide what to do with each.
|
|
213
|
+
|
|
214
|
+
Actions:
|
|
215
|
+
- ADD: Keep the new memory as-is (no duplicate exists)
|
|
216
|
+
- MERGE: Combine with an existing memory (provide mergeWith ID and updated content)
|
|
217
|
+
- UPDATE: Replace existing memory content (provide updated content)
|
|
218
|
+
- INVALIDATE: Remove existing memory (it's been superseded or is wrong)
|
|
219
|
+
- SKIP: This new memory is redundant (exact duplicate or subset of existing)
|
|
220
|
+
|
|
221
|
+
Also:
|
|
222
|
+
- Suggest profile updates based on patterns across memories
|
|
223
|
+
- Identify entity updates for entity tracking${resolveRecallAuxiliaryCapabilities(config).causalRuleExtraction ? `
|
|
224
|
+
- When merging or updating memories, look for IF→THEN causal patterns. If a memory describes "X failed/succeeded because Y" or "doing X led to Y", rewrite its content to make the causal rule explicit in the form "IF <condition> THEN <action/outcome>".` : ""}
|
|
225
|
+
- ${OUTPUT_LANGUAGE_POLICY}`;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* System prompt shared by every profile-consolidation path (gateway, direct
|
|
230
|
+
* client, local LLM). Owns the output-language policy (issue #2190).
|
|
231
|
+
*/
|
|
232
|
+
export function buildProfileConsolidationSystemPrompt(targetLines: number): string {
|
|
233
|
+
return `You are a profile consolidation system. You are given a behavioral profile (markdown) that has grown too large. Your job is to produce a CONSOLIDATED version that:
|
|
234
|
+
|
|
235
|
+
1. PRESERVES all ## section headers and their structure
|
|
236
|
+
2. MERGES duplicate or near-duplicate bullet points into single, clear statements
|
|
237
|
+
3. REMOVES stale information that has been superseded by newer bullets
|
|
238
|
+
4. REMOVES trivial or overly specific operational details that won't be useful across sessions
|
|
239
|
+
5. KEEPS the most important, durable observations about the user's preferences, habits, identity, and working style
|
|
240
|
+
6. Target roughly ${targetLines} lines — this is a soft target, prioritize quality over length
|
|
241
|
+
7. Write in the same style as the existing profile — concise bullets, no fluff
|
|
242
|
+
8. ${OUTPUT_LANGUAGE_POLICY}
|
|
243
|
+
|
|
244
|
+
The output should be the COMPLETE consolidated profile as valid markdown, starting with "# Behavioral Profile".`;
|
|
245
|
+
}
|
package/src/extraction.ts
CHANGED
|
@@ -49,7 +49,17 @@ import { applyGroundingWithConnector, headerConnector, renderExtractionConversat
|
|
|
49
49
|
import { isMemoryCategory } from "./write-envelope.js";
|
|
50
50
|
import { classifyExtractionThrownError, classifyFallbackParseFailure } from "./extraction-error-classification.js";
|
|
51
51
|
import { AMBIENT_CAPTURE_PROMPT_SECTION_COMPACT, clampAmbientCaptureConfidence } from "./ambient-provenance.js";
|
|
52
|
-
import {
|
|
52
|
+
import {
|
|
53
|
+
CONSOLIDATION_RESPONSE_SCHEMA,
|
|
54
|
+
CUE_ANCHOR_PROMPT_INSTRUCTION,
|
|
55
|
+
EXTRACTION_RESPONSE_SHAPE,
|
|
56
|
+
OUTPUT_LANGUAGE_POLICY,
|
|
57
|
+
PROFILE_CONSOLIDATION_RESPONSE_SCHEMA,
|
|
58
|
+
buildConsolidationSystemPrompt,
|
|
59
|
+
buildExtractionInstructions,
|
|
60
|
+
buildProfileConsolidationSystemPrompt,
|
|
61
|
+
eventTimePromptInstruction,
|
|
62
|
+
} from "./extraction-prompt.js";
|
|
53
63
|
import {
|
|
54
64
|
containsExtractionPlaceholder,
|
|
55
65
|
extractionAttributes,
|
|
@@ -66,19 +76,6 @@ type ExtractedEntityResult = ExtractionResult["entities"][number];
|
|
|
66
76
|
type ExtractedRelationshipResult = NonNullable<ExtractionResult["relationships"]>[number];
|
|
67
77
|
|
|
68
78
|
const PROACTIVE_MIN_CONFIDENCE = 0.8;
|
|
69
|
-
const CONSOLIDATION_RESPONSE_SCHEMA = `{
|
|
70
|
-
"items": [
|
|
71
|
-
{
|
|
72
|
-
"existingId": "id",
|
|
73
|
-
"action": "ADD",
|
|
74
|
-
"mergeWith": "optional-existing-id",
|
|
75
|
-
"updatedContent": "optional replacement content",
|
|
76
|
-
"reason": "brief reason for this action"
|
|
77
|
-
}
|
|
78
|
-
],
|
|
79
|
-
"profileUpdates": ["optional profile update"],
|
|
80
|
-
"entityUpdates": [{"name": "person-jane-doe", "type": "person", "facts": ["Now leads the backend team", "Recently migrated the user service to TypeScript"]}]
|
|
81
|
-
}`;
|
|
82
79
|
|
|
83
80
|
function extractionEntityType(value: unknown): ExtractedEntityResult["type"] | undefined {
|
|
84
81
|
const type = extractionText(value);
|
|
@@ -688,6 +685,7 @@ export class ExtractionEngine {
|
|
|
688
685
|
const prompt = [
|
|
689
686
|
"You are doing a proactive second-pass memory extraction.",
|
|
690
687
|
`Generate up to ${maxAdditional} additional high-value follow-up questions not already covered.${ambientCapture ? AMBIENT_CAPTURE_PROMPT_SECTION_COMPACT : ""}`,
|
|
688
|
+
OUTPUT_LANGUAGE_POLICY,
|
|
691
689
|
"Return only valid JSON with this shape:",
|
|
692
690
|
'{"questions":[{"question":"...","context":"...","priority":0.0}]}',
|
|
693
691
|
"",
|
|
@@ -790,6 +788,7 @@ export class ExtractionEngine {
|
|
|
790
788
|
"You are answering proactive memory follow-up questions using only the provided buffered conversation.",
|
|
791
789
|
`Return at most ${maxAdditional} additional high-confidence memory candidates that were omitted from the base extraction.`,
|
|
792
790
|
`Only include information directly supported by the conversation. Do not speculate. Do not repeat the base extraction.${ambientCapture ? AMBIENT_CAPTURE_PROMPT_SECTION_COMPACT : ""}`,
|
|
791
|
+
OUTPUT_LANGUAGE_POLICY,
|
|
793
792
|
"Return only valid JSON with this shape:",
|
|
794
793
|
'{"facts":[{"category":"fact","content":"...","confidence":0.0,"tags":["..."],"entityRef":"optional","promptedByQuestion":"optional","quote":"optional verbatim span from a single turn"}],"profileUpdates":["..."],"entities":[{"name":"...","type":"person","facts":["..."],"structuredSections":[{"key":"beliefs","title":"Beliefs","facts":["..."]}],"promptedByQuestion":"optional"}],"relationships":[{"source":"...","target":"...","label":"...","promptedByQuestion":"optional"}]}',
|
|
795
794
|
this.config.provenance?.enabled
|
|
@@ -1420,9 +1419,10 @@ Rules:
|
|
|
1420
1419
|
- Lines labelled [context user] or [context assistant] are reference context only. They may resolve references or complete a question-and-answer pair in a normal turn, but never alone establish durable information.
|
|
1421
1420
|
- Questions are optional. Return an empty array when the conversation does not support a useful unresolved question.
|
|
1422
1421
|
- Set confidence from source evidence: Explicit (0.95-1.0), Implied (0.70-0.94), Inferred (0.40-0.69), or Speculative (0.00-0.39). Corrections get highest confidence.
|
|
1423
|
-
- Use normalized, hyphenated entity names and keep the entity list short.
|
|
1422
|
+
- Use normalized, hyphenated entity names and keep the entity list short. When the source language is not written in a Latin script, the source-script name IS the normalized form — never transliterate or translate it.
|
|
1424
1423
|
- Keep facts standalone. Skip transient task state and operational noise such as routine scheduler, monitoring, or automation status.
|
|
1425
1424
|
- Add structuredAttributes only for concrete values.
|
|
1425
|
+
- ${OUTPUT_LANGUAGE_POLICY}
|
|
1426
1426
|
${CUE_ANCHOR_PROMPT_INSTRUCTION}\n- Include at most five durable relationships.${this.config.provenance?.enabled ? `
|
|
1427
1427
|
- Each fact must include a quote copied verbatim from one contiguous conversation span.` : ""}${lifecycleCaps.extractionScopeClassification ? `
|
|
1428
1428
|
- Set each fact scope to "global" for cross-project knowledge or "project" for codebase-specific knowledge. Tool, command, or CLI-flag instructions tied to one agent are "project" (the same tool name can mean different things across agents); when keeping one, begin the fact with a leading "In <agent>," clause naming that agent.` : ""}${ambientCapture ? AMBIENT_CAPTURE_PROMPT_SECTION_COMPACT : ""}
|
|
@@ -1650,19 +1650,7 @@ ${truncatedConversation}`;
|
|
|
1650
1650
|
[
|
|
1651
1651
|
{
|
|
1652
1652
|
role: "system",
|
|
1653
|
-
content:
|
|
1654
|
-
|
|
1655
|
-
Actions:
|
|
1656
|
-
- ADD: Keep the new memory as-is (no duplicate exists)
|
|
1657
|
-
- MERGE: Combine with an existing memory (provide mergeWith ID and updated content)
|
|
1658
|
-
- UPDATE: Replace existing memory content (provide updated content)
|
|
1659
|
-
- INVALIDATE: Remove existing memory (it's been superseded or is wrong)
|
|
1660
|
-
- SKIP: This new memory is redundant (exact duplicate or subset of existing)
|
|
1661
|
-
|
|
1662
|
-
Also:
|
|
1663
|
-
- Suggest profile updates based on patterns across memories
|
|
1664
|
-
- Identify entity updates for entity tracking${resolveRecallAuxiliaryCapabilities(this.config).causalRuleExtraction ? `
|
|
1665
|
-
- When merging or updating memories, look for IF→THEN causal patterns. If a memory describes "X failed/succeeded because Y" or "doing X led to Y", rewrite its content to make the causal rule explicit in the form "IF <condition> THEN <action/outcome>".` : ""}`,
|
|
1653
|
+
content: buildConsolidationSystemPrompt(this.config),
|
|
1666
1654
|
},
|
|
1667
1655
|
{
|
|
1668
1656
|
role: "user",
|
|
@@ -1696,19 +1684,7 @@ Consolidate the new memories against existing ones.`,
|
|
|
1696
1684
|
}
|
|
1697
1685
|
|
|
1698
1686
|
try {
|
|
1699
|
-
const instructionText =
|
|
1700
|
-
|
|
1701
|
-
Actions:
|
|
1702
|
-
- ADD: Keep the new memory as-is (no duplicate exists)
|
|
1703
|
-
- MERGE: Combine with an existing memory (provide mergeWith ID and updated content)
|
|
1704
|
-
- UPDATE: Replace existing memory content (provide updated content)
|
|
1705
|
-
- INVALIDATE: Remove existing memory (it's been superseded or is wrong)
|
|
1706
|
-
- SKIP: This new memory is redundant (exact duplicate or subset of existing)
|
|
1707
|
-
|
|
1708
|
-
Also:
|
|
1709
|
-
- Suggest profile updates based on patterns across memories
|
|
1710
|
-
- Identify entity updates for entity tracking${resolveRecallAuxiliaryCapabilities(this.config).causalRuleExtraction ? `
|
|
1711
|
-
- When merging or updating memories, look for IF→THEN causal patterns. If a memory describes "X failed/succeeded because Y" or "doing X led to Y", rewrite its content to make the causal rule explicit in the form "IF <condition> THEN <action/outcome>".` : ""}
|
|
1687
|
+
const instructionText = `${buildConsolidationSystemPrompt(this.config)}
|
|
1712
1688
|
|
|
1713
1689
|
Current behavioral profile:
|
|
1714
1690
|
${currentProfile || "(empty)"}
|
|
@@ -1794,19 +1770,7 @@ ${CONSOLIDATION_RESPONSE_SCHEMA}`;
|
|
|
1794
1770
|
);
|
|
1795
1771
|
log.debug(`Consolidation model context: ${contextSizes.description}`);
|
|
1796
1772
|
|
|
1797
|
-
const prompt =
|
|
1798
|
-
|
|
1799
|
-
Actions:
|
|
1800
|
-
- ADD: Keep the new memory as-is (no duplicate exists)
|
|
1801
|
-
- MERGE: Combine with an existing memory (provide mergeWith ID and updated content)
|
|
1802
|
-
- UPDATE: Replace existing memory content (provide updated content)
|
|
1803
|
-
- INVALIDATE: Remove existing memory (it's been superseded or is wrong)
|
|
1804
|
-
- SKIP: This new memory is redundant (exact duplicate or subset of existing)
|
|
1805
|
-
|
|
1806
|
-
Also:
|
|
1807
|
-
- Suggest profile updates based on patterns across memories
|
|
1808
|
-
- Identify entity updates for entity tracking${resolveRecallAuxiliaryCapabilities(this.config).causalRuleExtraction ? `
|
|
1809
|
-
- When merging or updating memories, look for IF→THEN causal patterns. If a memory describes "X failed/succeeded because Y" or "doing X led to Y", rewrite its content to make the causal rule explicit in the form "IF <condition> THEN <action/outcome>".` : ""}
|
|
1773
|
+
const prompt = `${buildConsolidationSystemPrompt(this.config)}
|
|
1810
1774
|
|
|
1811
1775
|
Current behavioral profile:
|
|
1812
1776
|
${currentProfile || "(empty)"}
|
|
@@ -1907,17 +1871,7 @@ ${CONSOLIDATION_RESPONSE_SCHEMA}`;
|
|
|
1907
1871
|
[
|
|
1908
1872
|
{
|
|
1909
1873
|
role: "system",
|
|
1910
|
-
content:
|
|
1911
|
-
|
|
1912
|
-
1. PRESERVES all ## section headers and their structure
|
|
1913
|
-
2. MERGES duplicate or near-duplicate bullet points into single, clear statements
|
|
1914
|
-
3. REMOVES stale information that has been superseded by newer bullets
|
|
1915
|
-
4. REMOVES trivial or overly specific operational details that won't be useful across sessions
|
|
1916
|
-
5. KEEPS the most important, durable observations about the user's preferences, habits, identity, and working style
|
|
1917
|
-
6. Target roughly ${targetLines} lines — this is a soft target, prioritize quality over length
|
|
1918
|
-
7. Write in the same style as the existing profile — concise bullets, no fluff
|
|
1919
|
-
|
|
1920
|
-
The output should be the COMPLETE consolidated profile as valid markdown, starting with "# Behavioral Profile".`,
|
|
1874
|
+
content: buildProfileConsolidationSystemPrompt(targetLines),
|
|
1921
1875
|
},
|
|
1922
1876
|
{ role: "user", content: fullProfileContent },
|
|
1923
1877
|
],
|
|
@@ -1937,24 +1891,10 @@ The output should be the COMPLETE consolidated profile as valid markdown, starti
|
|
|
1937
1891
|
}
|
|
1938
1892
|
|
|
1939
1893
|
try {
|
|
1940
|
-
const instructionText =
|
|
1941
|
-
|
|
1942
|
-
1. PRESERVES all ## section headers and their structure
|
|
1943
|
-
2. MERGES duplicate or near-duplicate bullet points into single, clear statements
|
|
1944
|
-
3. REMOVES stale information that has been superseded by newer bullets
|
|
1945
|
-
4. REMOVES trivial or overly specific operational details that won't be useful across sessions
|
|
1946
|
-
5. KEEPS the most important, durable observations about the user's preferences, habits, identity, and working style
|
|
1947
|
-
6. Target roughly ${targetLines} lines — this is a soft target, prioritize quality over length
|
|
1948
|
-
7. Write in the same style as the existing profile — concise bullets, no fluff
|
|
1949
|
-
|
|
1950
|
-
The output should be the COMPLETE consolidated profile as valid markdown, starting with "# Behavioral Profile".
|
|
1894
|
+
const instructionText = `${buildProfileConsolidationSystemPrompt(targetLines)}
|
|
1951
1895
|
|
|
1952
1896
|
Respond with valid JSON matching this schema:
|
|
1953
|
-
{
|
|
1954
|
-
"consolidatedProfile": "# Behavioral Profile\\n\\n... (complete markdown)",
|
|
1955
|
-
"removedCount": 42,
|
|
1956
|
-
"summary": "brief summary of what was consolidated"
|
|
1957
|
-
}`;
|
|
1897
|
+
${PROFILE_CONSOLIDATION_RESPONSE_SCHEMA}`;
|
|
1958
1898
|
|
|
1959
1899
|
const response = await this.client.chat.completions.create({
|
|
1960
1900
|
model: this.config.model,
|
|
@@ -2027,25 +1967,13 @@ Respond with valid JSON matching this schema:
|
|
|
2027
1967
|
);
|
|
2028
1968
|
log.debug(`Profile consolidation model context: ${contextSizes.description}`);
|
|
2029
1969
|
|
|
2030
|
-
const prompt =
|
|
2031
|
-
|
|
2032
|
-
1. PRESERVES all ## section headers and their structure
|
|
2033
|
-
2. MERGES duplicate or near-duplicate bullet points into single, clear statements
|
|
2034
|
-
3. REMOVES stale information that has been superseded by newer bullets
|
|
2035
|
-
4. REMOVES trivial or overly specific operational details that won't be useful across sessions
|
|
2036
|
-
5. KEEPS the most important, durable observations about the user's preferences, habits, identity, and working style
|
|
2037
|
-
6. Target roughly ${targetLines} lines — this is a soft target, prioritize quality over length
|
|
2038
|
-
7. Write in the same style as the existing profile — concise bullets, no fluff
|
|
1970
|
+
const prompt = `${buildProfileConsolidationSystemPrompt(targetLines)}
|
|
2039
1971
|
|
|
2040
1972
|
Profile to consolidate:
|
|
2041
1973
|
${fullProfileContent}
|
|
2042
1974
|
|
|
2043
1975
|
Respond with valid JSON matching this schema:
|
|
2044
|
-
{
|
|
2045
|
-
"consolidatedProfile": "# Behavioral Profile\\n\\n... (complete markdown)",
|
|
2046
|
-
"removedCount": 42,
|
|
2047
|
-
"summary": "brief summary of what was consolidated"
|
|
2048
|
-
}`;
|
|
1976
|
+
${PROFILE_CONSOLIDATION_RESPONSE_SCHEMA}`;
|
|
2049
1977
|
|
|
2050
1978
|
const response = await this.localLlm.chatCompletion(
|
|
2051
1979
|
[
|
package/src/offline-sync.ts
CHANGED
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
type OfflineSyncExcludeFile,
|
|
34
34
|
type OfflineSyncFileTarget,
|
|
35
35
|
} from "./offline-sync-file-io.js";
|
|
36
|
-
|
|
36
|
+
import { CENSUS_MAX_MTIME_MS, isCensusMtimeMs, isSha256Hex } from "./census-validation.js";
|
|
37
37
|
export type { OfflineSyncExcludeFile, OfflineSyncFileTarget } from "./offline-sync-file-io.js";
|
|
38
38
|
|
|
39
39
|
export const OFFLINE_SYNC_SNAPSHOT_FORMAT = "remnic.offline-sync.snapshot.v1";
|
|
@@ -43,7 +43,7 @@ export const OFFLINE_SYNC_FILE_CONTENT_MAX_CHUNK_BYTES = 64 * 1024 * 1024;
|
|
|
43
43
|
export const OFFLINE_SYNC_FILE_CONTENT_TRANSFER_CHUNK_BYTES = 8 * 1024 * 1024;
|
|
44
44
|
export const OFFLINE_SYNC_APPLY_MAX_BODY_BYTES = 16 * 1024 * 1024;
|
|
45
45
|
export const OFFLINE_SYNC_SNAPSHOT_BASE_MAX_BODY_BYTES = 64 * 1024 * 1024;
|
|
46
|
-
export const OFFLINE_SYNC_MAX_MTIME_MS =
|
|
46
|
+
export const OFFLINE_SYNC_MAX_MTIME_MS = CENSUS_MAX_MTIME_MS;
|
|
47
47
|
|
|
48
48
|
export interface OfflineSyncFileState {
|
|
49
49
|
path: string;
|
|
@@ -288,7 +288,7 @@ function compareByPath<T extends { path: string }>(left: T, right: T): number {
|
|
|
288
288
|
}
|
|
289
289
|
|
|
290
290
|
function assertSha256(value: unknown, field: string): string {
|
|
291
|
-
if (
|
|
291
|
+
if (!isSha256Hex(value)) {
|
|
292
292
|
throw new Error(`${field} must be a 64-character sha256 hex string`);
|
|
293
293
|
}
|
|
294
294
|
return value.toLowerCase();
|
|
@@ -315,7 +315,7 @@ function assertNonNegativeFinite(value: unknown, field: string): number {
|
|
|
315
315
|
|
|
316
316
|
function assertOfflineSyncMtimeMs(value: unknown, field: string): number {
|
|
317
317
|
const mtimeMs = assertNonNegativeFinite(value, field);
|
|
318
|
-
if (mtimeMs
|
|
318
|
+
if (!isCensusMtimeMs(mtimeMs)) {
|
|
319
319
|
throw new Error(`${field} must be within JavaScript Date range`);
|
|
320
320
|
}
|
|
321
321
|
return mtimeMs;
|