@remnic/core 9.3.628 → 9.3.630
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 +18 -18
- package/dist/access-http.d.ts +6 -4
- package/dist/access-http.js +7 -6
- package/dist/access-mcp.d.ts +6 -4
- package/dist/access-mcp.js +6 -5
- package/dist/{access-service-C_sfOHsX.d.ts → access-service-C4v-eFjB.d.ts} +2 -2
- package/dist/access-service.d.ts +6 -4
- package/dist/access-service.js +5 -4
- 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 +6 -4
- package/dist/briefing.d.ts +33 -2
- package/dist/briefing.js +5 -2
- 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/calibration.js +2 -2
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +5 -5
- package/dist/{chunk-GE7Q7KXP.js → chunk-2VJ7AJFX.js} +2 -2
- package/dist/{chunk-KVFYTRMV.js → chunk-4QEUKASL.js} +2 -2
- package/dist/{chunk-KB4MFBF5.js → chunk-5S6IREG3.js} +3 -3
- package/dist/{chunk-LQYTQCXM.js → chunk-6LBQL5US.js} +2 -2
- package/dist/{chunk-KGIGRNR6.js → chunk-723OMPUI.js} +4 -4
- package/dist/{chunk-TZDSNIRO.js → chunk-ADOD7PJC.js} +5 -5
- package/dist/{chunk-SHV5Y2WU.js → chunk-BL33LBTN.js} +3 -3
- package/dist/{chunk-532VCWYW.js → chunk-BWK5EEKS.js} +2 -2
- package/dist/{chunk-KKTXCFD7.js → chunk-EORL2IDM.js} +39 -8
- package/dist/{chunk-KKTXCFD7.js.map → chunk-EORL2IDM.js.map} +1 -1
- package/dist/{chunk-F3FY3D3S.js → chunk-F6USGHMO.js} +10 -5
- package/dist/chunk-F6USGHMO.js.map +1 -0
- package/dist/{chunk-STDAAGH7.js → chunk-GXWFZYSR.js} +39 -3
- package/dist/chunk-GXWFZYSR.js.map +1 -0
- package/dist/{chunk-3VONWEQB.js → chunk-HZVIYZYN.js} +2 -2
- package/dist/{chunk-Y3TMFC6I.js → chunk-K3BTOW7N.js} +3 -3
- package/dist/{chunk-Z3CCEP6F.js → chunk-K47C6M2C.js} +5 -5
- package/dist/{chunk-N5RGXWLQ.js → chunk-MQ24KOOR.js} +2 -2
- package/dist/{chunk-3MNBW7R7.js → chunk-NRQJBK36.js} +2 -2
- package/dist/{chunk-MON3LMO7.js → chunk-NRST7W5Q.js} +5 -5
- package/dist/{chunk-3R2UZV3U.js → chunk-OOFBE62K.js} +2 -2
- package/dist/{chunk-MVQN73GT.js → chunk-OQMR2SDZ.js} +2 -2
- package/dist/{chunk-UGHUNQ74.js → chunk-RSKUUEBA.js} +73 -1
- package/dist/chunk-RSKUUEBA.js.map +1 -0
- package/dist/{chunk-QDV6VAD4.js → chunk-S5W37FPX.js} +2 -2
- package/dist/{chunk-57QXN2CS.js → chunk-SACS6KE6.js} +2 -2
- package/dist/{chunk-UELS6WWF.js → chunk-UE57H4MA.js} +2 -2
- package/dist/{chunk-2RHI3FGV.js → chunk-VUTPRX7K.js} +20 -14
- package/dist/{chunk-2RHI3FGV.js.map → chunk-VUTPRX7K.js.map} +1 -1
- package/dist/{chunk-AZ4RI3QD.js → chunk-YJOWWRRS.js} +450 -48
- package/dist/chunk-YJOWWRRS.js.map +1 -0
- package/dist/{chunk-P2D2MM47.js → chunk-ZZSXUZF3.js} +2 -2
- package/dist/{cli-EZv6YE6_.d.ts → cli-B_6EMiQc.d.ts} +3 -3
- package/dist/cli.d.ts +7 -5
- package/dist/cli.js +18 -17
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +2 -2
- 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 +2 -2
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +2 -2
- 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 +2 -2
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +6 -4
- 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-judge.js +3 -3
- package/dist/extraction.d.ts +1 -1
- package/dist/extraction.js +3 -3
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/fallback-llm.js +2 -2
- 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 +29 -27
- 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/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 +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +2 -2
- package/dist/maintenance/rebuild-memory-projection.js +3 -3
- package/dist/mcp-memory-inspector-app.d.ts +6 -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 +3 -3
- 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 +2 -2
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +6 -6
- package/dist/{orchestrator-CEycaY3M.d.ts → orchestrator-Dlw3ae4B.d.ts} +111 -10
- package/dist/orchestrator.d.ts +5 -3
- package/dist/orchestrator.js +15 -14
- 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-planner-llm.d.ts +1 -1
- package/dist/recall-planner-llm.js +2 -2
- 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-renderer.d.ts +1 -1
- package/dist/recall-xray.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +2 -2
- package/dist/retrieval-agents.d.ts +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 +24 -24
- 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-FbhPeJjB.d.ts → semantic-consolidation-C4sefXEI.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +3 -3
- package/dist/semantic-rule-promotion.js +2 -2
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +2 -2
- 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 +38 -2
- package/dist/storage.js +5 -3
- package/dist/summarizer.d.ts +1 -1
- package/dist/summarizer.js +3 -3
- 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/types.d.ts +12 -12
- package/dist/{types-D5VRAI04.d.ts → types-2vqxmO0j.d.ts} +39 -10
- package/dist/types.d.ts +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +2 -2
- package/package.json +1 -1
- package/src/access-service.ts +7 -0
- package/src/briefing.ts +67 -1
- package/src/index.ts +2 -0
- package/src/orchestrator.ts +42 -0
- package/src/storage.ts +100 -0
- package/src/wearables/cli.ts +6 -0
- package/src/wearables/config.test.ts +33 -4
- package/src/wearables/config.ts +39 -7
- package/src/wearables/memory-gen.test.ts +416 -1
- package/src/wearables/memory-gen.ts +381 -23
- package/src/wearables/pipeline.test.ts +309 -1
- package/src/wearables/pipeline.ts +131 -9
- package/src/wearables/service.test.ts +172 -0
- package/src/wearables/service.ts +84 -3
- package/src/wearables/storage-io.test.ts +81 -0
- package/src/wearables/trust.test.ts +123 -0
- package/src/wearables/trust.ts +168 -0
- package/src/wearables/types.ts +37 -8
- package/dist/chunk-AZ4RI3QD.js.map +0 -1
- package/dist/chunk-F3FY3D3S.js.map +0 -1
- package/dist/chunk-STDAAGH7.js.map +0 -1
- package/dist/chunk-UGHUNQ74.js.map +0 -1
- /package/dist/{chunk-GE7Q7KXP.js.map → chunk-2VJ7AJFX.js.map} +0 -0
- /package/dist/{chunk-KVFYTRMV.js.map → chunk-4QEUKASL.js.map} +0 -0
- /package/dist/{chunk-KB4MFBF5.js.map → chunk-5S6IREG3.js.map} +0 -0
- /package/dist/{chunk-LQYTQCXM.js.map → chunk-6LBQL5US.js.map} +0 -0
- /package/dist/{chunk-KGIGRNR6.js.map → chunk-723OMPUI.js.map} +0 -0
- /package/dist/{chunk-TZDSNIRO.js.map → chunk-ADOD7PJC.js.map} +0 -0
- /package/dist/{chunk-SHV5Y2WU.js.map → chunk-BL33LBTN.js.map} +0 -0
- /package/dist/{chunk-532VCWYW.js.map → chunk-BWK5EEKS.js.map} +0 -0
- /package/dist/{chunk-3VONWEQB.js.map → chunk-HZVIYZYN.js.map} +0 -0
- /package/dist/{chunk-Y3TMFC6I.js.map → chunk-K3BTOW7N.js.map} +0 -0
- /package/dist/{chunk-Z3CCEP6F.js.map → chunk-K47C6M2C.js.map} +0 -0
- /package/dist/{chunk-N5RGXWLQ.js.map → chunk-MQ24KOOR.js.map} +0 -0
- /package/dist/{chunk-3MNBW7R7.js.map → chunk-NRQJBK36.js.map} +0 -0
- /package/dist/{chunk-MON3LMO7.js.map → chunk-NRST7W5Q.js.map} +0 -0
- /package/dist/{chunk-3R2UZV3U.js.map → chunk-OOFBE62K.js.map} +0 -0
- /package/dist/{chunk-MVQN73GT.js.map → chunk-OQMR2SDZ.js.map} +0 -0
- /package/dist/{chunk-QDV6VAD4.js.map → chunk-S5W37FPX.js.map} +0 -0
- /package/dist/{chunk-57QXN2CS.js.map → chunk-SACS6KE6.js.map} +0 -0
- /package/dist/{chunk-UELS6WWF.js.map → chunk-UE57H4MA.js.map} +0 -0
- /package/dist/{chunk-P2D2MM47.js.map → chunk-ZZSXUZF3.js.map} +0 -0
package/src/orchestrator.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { log } from "./logger.js";
|
|
2
|
+
import {
|
|
3
|
+
buildChainFollowupGenerator,
|
|
4
|
+
type BriefingFollowupGenerator,
|
|
5
|
+
} from "./briefing.js";
|
|
2
6
|
import path from "node:path";
|
|
3
7
|
import os from "node:os";
|
|
4
8
|
import { createHash, randomBytes } from "node:crypto";
|
|
@@ -2516,6 +2520,28 @@ export class Orchestrator {
|
|
|
2516
2520
|
};
|
|
2517
2521
|
}
|
|
2518
2522
|
|
|
2523
|
+
/**
|
|
2524
|
+
* Build a briefing follow-up generator backed by the configured LLM chain
|
|
2525
|
+
* (gateway model source or local LLM). Returns `undefined` when no chain
|
|
2526
|
+
* is available so `buildBriefing` can surface a clear unavailable reason
|
|
2527
|
+
* instead of failing at call time. Used by the access service and CLI as
|
|
2528
|
+
* the fallback when no direct `openaiApiKey` is configured, so briefing
|
|
2529
|
+
* follow-ups ride the same routing as every other fast-tier LLM feature.
|
|
2530
|
+
*/
|
|
2531
|
+
get briefingChainFollowupGenerator(): BriefingFollowupGenerator | undefined {
|
|
2532
|
+
// Plugin mode gates on `localLlmEnabled` alone: `LocalLlmClient.chatCompletion`
|
|
2533
|
+
// returns null when the master switch is off, so `localLlmFastEnabled` by
|
|
2534
|
+
// itself cannot serve requests (Cursor review on PR #1463).
|
|
2535
|
+
const chainAvailable =
|
|
2536
|
+
this.config.modelSource === "gateway"
|
|
2537
|
+
? this._fastGatewayLlm?.isAvailable(
|
|
2538
|
+
this.config.fastGatewayAgentId || this.config.gatewayAgentId || undefined,
|
|
2539
|
+
) === true
|
|
2540
|
+
: this.config.localLlmEnabled;
|
|
2541
|
+
if (!chainAvailable) return undefined;
|
|
2542
|
+
return buildChainFollowupGenerator(this.fastLlmForRerank);
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2519
2545
|
async initialize(): Promise<void> {
|
|
2520
2546
|
// Recreate the deferred-ready gate on every initialize() call.
|
|
2521
2547
|
// The same Orchestrator instance may be reused across stop/start cycles
|
|
@@ -10781,6 +10807,22 @@ export class Orchestrator {
|
|
|
10781
10807
|
getStorage: async () =>
|
|
10782
10808
|
await this.getStorageForNamespace(this.bulkImportWriteNamespace()),
|
|
10783
10809
|
extract: (turns) => this.extraction.extract(turns),
|
|
10810
|
+
// Smart memoryMode runs candidates through the SAME extraction
|
|
10811
|
+
// judge (cache + defer counters included) the live extraction
|
|
10812
|
+
// pipeline uses, so wearable facts get identical LLM-as-judge
|
|
10813
|
+
// durability gating.
|
|
10814
|
+
judgeFacts: (candidates) =>
|
|
10815
|
+
judgeFactDurability(
|
|
10816
|
+
candidates,
|
|
10817
|
+
this.config,
|
|
10818
|
+
this.localLlm,
|
|
10819
|
+
new FallbackLlmClient(
|
|
10820
|
+
this.config.gatewayConfig,
|
|
10821
|
+
fallbackLlmRuntimeContextFromConfig(this.config),
|
|
10822
|
+
),
|
|
10823
|
+
this.judgeVerdictCache,
|
|
10824
|
+
this.judgeDeferCounts,
|
|
10825
|
+
),
|
|
10784
10826
|
searchBackend: {
|
|
10785
10827
|
search: async (query, maxResults) => {
|
|
10786
10828
|
if (!this.qmd.isAvailable()) return null;
|
package/src/storage.ts
CHANGED
|
@@ -1168,6 +1168,27 @@ export class ContentHashIndex {
|
|
|
1168
1168
|
* normalizeAttributePairs({ foo: "bar", BAZ: "qux" })
|
|
1169
1169
|
* // → "baz: qux; foo: bar"
|
|
1170
1170
|
*/
|
|
1171
|
+
/**
|
|
1172
|
+
* Remove the "[Attributes: ...]" suffix `writeMemory` appends to the
|
|
1173
|
+
* stored body when structuredAttributes are present, yielding the raw
|
|
1174
|
+
* fact text for content comparison. Inverse companion of
|
|
1175
|
+
* `normalizeAttributePairs` enrichment. String operations, not regex —
|
|
1176
|
+
* CodeQL js/polynomial-redos on a suffix-anchored pattern over
|
|
1177
|
+
* library-supplied content.
|
|
1178
|
+
*/
|
|
1179
|
+
export function stripAttributesSuffix(content: string): string {
|
|
1180
|
+
const trimmed = content.trimEnd();
|
|
1181
|
+
if (!trimmed.endsWith("]")) return content.trim();
|
|
1182
|
+
const marker = "\n[Attributes: ";
|
|
1183
|
+
const markerIndex = trimmed.lastIndexOf(marker);
|
|
1184
|
+
if (markerIndex === -1) return content.trim();
|
|
1185
|
+
// The block must be the FINAL line and contain no "]" before the
|
|
1186
|
+
// closing bracket (mirrors the shape normalizeAttributePairs emits).
|
|
1187
|
+
const inner = trimmed.slice(markerIndex + marker.length, -1);
|
|
1188
|
+
if (inner.includes("]") || inner.includes("\n")) return content.trim();
|
|
1189
|
+
return trimmed.slice(0, markerIndex).trim();
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1171
1192
|
export function normalizeAttributePairs(pairs: Record<string, string>): string {
|
|
1172
1193
|
return Object.entries(pairs)
|
|
1173
1194
|
.map(([k, v]) => [k.trim().toLowerCase(), v.trim()] as [string, string])
|
|
@@ -2596,6 +2617,85 @@ export class StorageManager {
|
|
|
2596
2617
|
return days;
|
|
2597
2618
|
}
|
|
2598
2619
|
|
|
2620
|
+
/**
|
|
2621
|
+
* Locate a wearable-sourced memory by exact (trimmed) content,
|
|
2622
|
+
* ignoring the "[Attributes: ...]" suffix writeMemory appends for
|
|
2623
|
+
* structuredAttributes — callers pass the raw fact text. Used by the
|
|
2624
|
+
* smart trust pipeline to find an earlier borderline write when the
|
|
2625
|
+
* same fact re-extracts with stronger evidence.
|
|
2626
|
+
*/
|
|
2627
|
+
async findWearableMemoryByContent(
|
|
2628
|
+
content: string,
|
|
2629
|
+
): Promise<{ id: string; status: MemoryStatus | undefined } | null> {
|
|
2630
|
+
const needle = stripAttributesSuffix(content);
|
|
2631
|
+
const memories = await this.readAllMemories();
|
|
2632
|
+
for (const memory of memories) {
|
|
2633
|
+
if (
|
|
2634
|
+
typeof memory.frontmatter.source === "string" &&
|
|
2635
|
+
memory.frontmatter.source.startsWith("wearable:") &&
|
|
2636
|
+
stripAttributesSuffix(memory.content) === needle
|
|
2637
|
+
) {
|
|
2638
|
+
return { id: memory.frontmatter.id, status: memory.frontmatter.status };
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
return null;
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
/**
|
|
2645
|
+
* Promote a pending_review wearable memory to active in place,
|
|
2646
|
+
* merging updated trust evidence into structuredAttributes. Returns
|
|
2647
|
+
* false when the memory is missing or no longer pending_review (a
|
|
2648
|
+
* concurrent review decision wins).
|
|
2649
|
+
*/
|
|
2650
|
+
async promoteWearableMemory(
|
|
2651
|
+
id: string,
|
|
2652
|
+
attributeUpdates: Record<string, string>,
|
|
2653
|
+
confidence?: number,
|
|
2654
|
+
): Promise<boolean> {
|
|
2655
|
+
const memories = await this.readAllMemories();
|
|
2656
|
+
const memory = memories.find((entry) => entry.frontmatter.id === id);
|
|
2657
|
+
if (!memory) return false;
|
|
2658
|
+
if (memory.frontmatter.status !== "pending_review") return false;
|
|
2659
|
+
return this.writeMemoryFrontmatter(memory, {
|
|
2660
|
+
status: "active",
|
|
2661
|
+
// Keep frontmatter confidence in step with the re-scored trust —
|
|
2662
|
+
// new smart writes persist trust as confidence, and a promoted
|
|
2663
|
+
// row must not keep its stale borderline value.
|
|
2664
|
+
...(typeof confidence === "number" && Number.isFinite(confidence)
|
|
2665
|
+
? { confidence: Math.min(1, Math.max(0, confidence)) }
|
|
2666
|
+
: {}),
|
|
2667
|
+
structuredAttributes: {
|
|
2668
|
+
...(memory.frontmatter.structuredAttributes ?? {}),
|
|
2669
|
+
...attributeUpdates,
|
|
2670
|
+
},
|
|
2671
|
+
});
|
|
2672
|
+
}
|
|
2673
|
+
|
|
2674
|
+
/**
|
|
2675
|
+
* Demote a pending_review wearable memory to rejected when a re-pass
|
|
2676
|
+
* produced an explicit judge-reject verdict, merging the evidence.
|
|
2677
|
+
* Returns false when the memory is missing or no longer
|
|
2678
|
+
* pending_review — active rows are NEVER auto-demoted (operator
|
|
2679
|
+
* approvals and accrued recall signals win; contradiction scans and
|
|
2680
|
+
* supersession own active-row retirement).
|
|
2681
|
+
*/
|
|
2682
|
+
async demoteWearableMemory(
|
|
2683
|
+
id: string,
|
|
2684
|
+
attributeUpdates: Record<string, string>,
|
|
2685
|
+
): Promise<boolean> {
|
|
2686
|
+
const memories = await this.readAllMemories();
|
|
2687
|
+
const memory = memories.find((entry) => entry.frontmatter.id === id);
|
|
2688
|
+
if (!memory) return false;
|
|
2689
|
+
if (memory.frontmatter.status !== "pending_review") return false;
|
|
2690
|
+
return this.writeMemoryFrontmatter(memory, {
|
|
2691
|
+
status: "rejected",
|
|
2692
|
+
structuredAttributes: {
|
|
2693
|
+
...(memory.frontmatter.structuredAttributes ?? {}),
|
|
2694
|
+
...attributeUpdates,
|
|
2695
|
+
},
|
|
2696
|
+
});
|
|
2697
|
+
}
|
|
2698
|
+
|
|
2599
2699
|
private get factsDir(): string {
|
|
2600
2700
|
return path.join(this.baseDir, "facts");
|
|
2601
2701
|
}
|
package/src/wearables/cli.ts
CHANGED
|
@@ -125,6 +125,12 @@ function renderSyncSummary(summary: WearableSyncSummary): string {
|
|
|
125
125
|
` transcripts written: ${summary.transcriptsWritten.length > 0 ? summary.transcriptsWritten.join(", ") : "(none — unchanged)"}`,
|
|
126
126
|
` memories created: ${summary.memoriesCreated} (skipped ${summary.memoriesSkipped})`,
|
|
127
127
|
];
|
|
128
|
+
if (summary.memoriesPromoted > 0) {
|
|
129
|
+
lines.push(` memories promoted: ${summary.memoriesPromoted}`);
|
|
130
|
+
}
|
|
131
|
+
if (summary.memoriesDemoted > 0) {
|
|
132
|
+
lines.push(` memories demoted: ${summary.memoriesDemoted}`);
|
|
133
|
+
}
|
|
128
134
|
if (summary.nativeMemoriesImported > 0) {
|
|
129
135
|
lines.push(` native memories queued: ${summary.nativeMemoriesImported}`);
|
|
130
136
|
}
|
|
@@ -25,17 +25,20 @@ test("boolean-ish strings coerce; garbage booleans throw", () => {
|
|
|
25
25
|
assert.throws(() => parseWearablesConfig({ enabled: "fales" }), /wearables.enabled/);
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
test("source settings default to the
|
|
28
|
+
test("source settings default to the fully-automated smart pipeline", () => {
|
|
29
29
|
const parsed = parseWearablesConfig({
|
|
30
30
|
enabled: true,
|
|
31
31
|
sources: { limitless: { enabled: true } },
|
|
32
32
|
});
|
|
33
33
|
const source = parsed.sources.limitless;
|
|
34
|
-
assert.equal(source.memoryMode, "
|
|
34
|
+
assert.equal(source.memoryMode, "smart");
|
|
35
|
+
assert.equal(source.sourceTrust, 0.8);
|
|
36
|
+
assert.equal(source.autoApproveTrust, 0.7);
|
|
37
|
+
assert.equal(source.reviewTrust, 0.45);
|
|
35
38
|
assert.equal(source.minConfidence, 0.6);
|
|
36
39
|
assert.equal(source.minImportance, "low");
|
|
37
|
-
assert.equal(source.maxMemoriesPerDay,
|
|
38
|
-
assert.equal(source.importNativeMemories, "
|
|
40
|
+
assert.equal(source.maxMemoriesPerDay, 50);
|
|
41
|
+
assert.equal(source.importNativeMemories, "smart");
|
|
39
42
|
assert.deepEqual(source.cleanup, {
|
|
40
43
|
mergeSameSpeaker: true,
|
|
41
44
|
stripFillers: true,
|
|
@@ -44,6 +47,32 @@ test("source settings default to the least-privileged memory mode", () => {
|
|
|
44
47
|
});
|
|
45
48
|
});
|
|
46
49
|
|
|
50
|
+
test("top-level defaults are full-featured: digest and off-the-record on", () => {
|
|
51
|
+
const parsed = parseWearablesConfig({});
|
|
52
|
+
assert.equal(parsed.digestEnabled, true);
|
|
53
|
+
assert.equal(parsed.offTheRecordEnabled, true);
|
|
54
|
+
assert.equal(parsed.redactionEnabled, true);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("trust knobs validate range and ordering", () => {
|
|
58
|
+
assert.throws(
|
|
59
|
+
() => parseWearablesConfig({ sources: { bee: { sourceTrust: 1.5 } } }),
|
|
60
|
+
/sourceTrust must be a number between 0 and 1/,
|
|
61
|
+
);
|
|
62
|
+
assert.throws(
|
|
63
|
+
() => parseWearablesConfig({ sources: { bee: { autoApproveTrust: -1 } } }),
|
|
64
|
+
/autoApproveTrust/,
|
|
65
|
+
);
|
|
66
|
+
assert.throws(
|
|
67
|
+
() => parseWearablesConfig({ sources: { bee: { reviewTrust: 0.9, autoApproveTrust: 0.7 } } }),
|
|
68
|
+
/reviewTrust .* must be below autoApproveTrust/,
|
|
69
|
+
);
|
|
70
|
+
const parsed = parseWearablesConfig({
|
|
71
|
+
sources: { bee: { sourceTrust: 0.5, autoApproveTrust: 0.8, reviewTrust: 0.3 } },
|
|
72
|
+
});
|
|
73
|
+
assert.equal(parsed.sources.bee.sourceTrust, 0.5);
|
|
74
|
+
});
|
|
75
|
+
|
|
47
76
|
test("invalid enum values list the valid options", () => {
|
|
48
77
|
assert.throws(
|
|
49
78
|
() =>
|
package/src/wearables/config.ts
CHANGED
|
@@ -22,7 +22,7 @@ import type {
|
|
|
22
22
|
|
|
23
23
|
export const KNOWN_WEARABLE_SOURCE_IDS = ["limitless", "bee", "omi"] as const;
|
|
24
24
|
|
|
25
|
-
const MEMORY_MODES: WearableMemoryMode[] = ["off", "review", "auto"];
|
|
25
|
+
const MEMORY_MODES: WearableMemoryMode[] = ["off", "review", "auto", "smart"];
|
|
26
26
|
const IMPORTANCE_LEVELS: ImportanceLevel[] = [
|
|
27
27
|
"trivial",
|
|
28
28
|
"low",
|
|
@@ -30,12 +30,15 @@ const IMPORTANCE_LEVELS: ImportanceLevel[] = [
|
|
|
30
30
|
"high",
|
|
31
31
|
"critical",
|
|
32
32
|
];
|
|
33
|
-
const NATIVE_IMPORT_MODES = ["off", "review"] as const;
|
|
33
|
+
const NATIVE_IMPORT_MODES = ["off", "review", "smart"] as const;
|
|
34
34
|
|
|
35
35
|
const DEFAULT_MIN_CONFIDENCE = 0.6;
|
|
36
36
|
const DEFAULT_MIN_IMPORTANCE: ImportanceLevel = "low";
|
|
37
|
-
const DEFAULT_MAX_MEMORIES_PER_DAY =
|
|
37
|
+
const DEFAULT_MAX_MEMORIES_PER_DAY = 50;
|
|
38
38
|
const MAX_MEMORIES_PER_DAY_CEILING = 500;
|
|
39
|
+
const DEFAULT_SOURCE_TRUST = 0.8;
|
|
40
|
+
const DEFAULT_AUTO_APPROVE_TRUST = 0.7;
|
|
41
|
+
const DEFAULT_REVIEW_TRUST = 0.45;
|
|
39
42
|
|
|
40
43
|
export function defaultWearableCleanupSettings(): WearableCleanupSettings {
|
|
41
44
|
return {
|
|
@@ -49,11 +52,14 @@ export function defaultWearableCleanupSettings(): WearableCleanupSettings {
|
|
|
49
52
|
export function defaultWearableSourceSettings(): WearableSourceSettings {
|
|
50
53
|
return {
|
|
51
54
|
enabled: false,
|
|
52
|
-
memoryMode: "
|
|
55
|
+
memoryMode: "smart",
|
|
56
|
+
sourceTrust: DEFAULT_SOURCE_TRUST,
|
|
57
|
+
autoApproveTrust: DEFAULT_AUTO_APPROVE_TRUST,
|
|
58
|
+
reviewTrust: DEFAULT_REVIEW_TRUST,
|
|
53
59
|
minConfidence: DEFAULT_MIN_CONFIDENCE,
|
|
54
60
|
minImportance: DEFAULT_MIN_IMPORTANCE,
|
|
55
61
|
maxMemoriesPerDay: DEFAULT_MAX_MEMORIES_PER_DAY,
|
|
56
|
-
importNativeMemories: "
|
|
62
|
+
importNativeMemories: "smart",
|
|
57
63
|
cleanup: defaultWearableCleanupSettings(),
|
|
58
64
|
};
|
|
59
65
|
}
|
|
@@ -63,8 +69,8 @@ export function defaultWearablesConfig(): WearablesConfig {
|
|
|
63
69
|
enabled: false,
|
|
64
70
|
redactionEnabled: true,
|
|
65
71
|
redactionPatterns: [],
|
|
66
|
-
offTheRecordEnabled:
|
|
67
|
-
digestEnabled:
|
|
72
|
+
offTheRecordEnabled: true,
|
|
73
|
+
digestEnabled: true,
|
|
68
74
|
corrections: [],
|
|
69
75
|
sources: {},
|
|
70
76
|
};
|
|
@@ -203,6 +209,29 @@ function parseSourceSettings(
|
|
|
203
209
|
// the schema minimum (CLAUDE.md rule 45).
|
|
204
210
|
const maxMemoriesPerDay = maxPerDayRaw ?? defaults.maxMemoriesPerDay;
|
|
205
211
|
|
|
212
|
+
const parseUnitInterval = (value: unknown, name: string, fallback: number): number => {
|
|
213
|
+
if (value === undefined) return fallback;
|
|
214
|
+
const coerced = coerceNumber(value);
|
|
215
|
+
if (coerced === undefined || coerced < 0 || coerced > 1) {
|
|
216
|
+
throw new Error(
|
|
217
|
+
`${keyPath}.${name} must be a number between 0 and 1 (got ${JSON.stringify(value)})`,
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
return coerced;
|
|
221
|
+
};
|
|
222
|
+
const sourceTrust = parseUnitInterval(raw.sourceTrust, "sourceTrust", defaults.sourceTrust);
|
|
223
|
+
const autoApproveTrust = parseUnitInterval(
|
|
224
|
+
raw.autoApproveTrust,
|
|
225
|
+
"autoApproveTrust",
|
|
226
|
+
defaults.autoApproveTrust,
|
|
227
|
+
);
|
|
228
|
+
const reviewTrust = parseUnitInterval(raw.reviewTrust, "reviewTrust", defaults.reviewTrust);
|
|
229
|
+
if (reviewTrust >= autoApproveTrust) {
|
|
230
|
+
throw new Error(
|
|
231
|
+
`${keyPath}.reviewTrust (${reviewTrust}) must be below autoApproveTrust (${autoApproveTrust})`,
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
206
235
|
const rawCleanup =
|
|
207
236
|
raw.cleanup === undefined ? {} : requireObject(raw.cleanup, `${keyPath}.cleanup`);
|
|
208
237
|
const cleanup: WearableCleanupSettings = {
|
|
@@ -240,6 +269,9 @@ function parseSourceSettings(
|
|
|
240
269
|
MEMORY_MODES,
|
|
241
270
|
defaults.memoryMode,
|
|
242
271
|
),
|
|
272
|
+
sourceTrust,
|
|
273
|
+
autoApproveTrust,
|
|
274
|
+
reviewTrust,
|
|
243
275
|
minConfidence,
|
|
244
276
|
minImportance: parseEnum(
|
|
245
277
|
raw.minImportance,
|