@remnic/core 9.3.630 → 9.3.631
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 +15 -13
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +4 -4
- package/dist/access-http.js +7 -6
- package/dist/access-mcp.d.ts +4 -4
- package/dist/access-mcp.js +6 -5
- package/dist/{access-service-C4v-eFjB.d.ts → access-service-C9_EpVHd.d.ts} +2 -2
- package/dist/access-service.d.ts +4 -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/auto-sync-RFADEHIQ.js +75 -0
- package/dist/auto-sync-RFADEHIQ.js.map +1 -0
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +3 -3
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +3 -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/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +4 -3
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/{chunk-BWK5EEKS.js → chunk-242XFZ36.js} +2 -2
- package/dist/{chunk-K3BTOW7N.js → chunk-32U3N7H5.js} +3 -3
- package/dist/{chunk-5S6IREG3.js → chunk-3RDYU3JS.js} +3 -3
- package/dist/{chunk-SACS6KE6.js → chunk-4S3N6HFG.js} +2 -2
- package/dist/{chunk-VUTPRX7K.js → chunk-5PT5I6JQ.js} +14 -14
- package/dist/{chunk-2VJ7AJFX.js → chunk-7A2QKUUA.js} +2 -2
- package/dist/{chunk-EORL2IDM.js → chunk-7H5WCPBS.js} +58 -5
- package/dist/{chunk-EORL2IDM.js.map → chunk-7H5WCPBS.js.map} +1 -1
- package/dist/{chunk-NRQJBK36.js → chunk-C4KKM62E.js} +2 -2
- package/dist/{chunk-GXWFZYSR.js → chunk-CMN5AWAZ.js} +2 -2
- package/dist/{chunk-F6USGHMO.js → chunk-DOBJH4I6.js} +4 -4
- package/dist/{chunk-ADOD7PJC.js → chunk-IFVFQRZ2.js} +5 -5
- package/dist/{chunk-6LBQL5US.js → chunk-JCLECECB.js} +2 -2
- package/dist/chunk-KVDUDYEN.js +1164 -0
- package/dist/chunk-KVDUDYEN.js.map +1 -0
- package/dist/{chunk-S5W37FPX.js → chunk-LEG7XWS2.js} +2 -2
- package/dist/chunk-M7XQSUBB.js +280 -0
- package/dist/chunk-M7XQSUBB.js.map +1 -0
- package/dist/{chunk-MQ24KOOR.js → chunk-PUEAEQSN.js} +2 -2
- package/dist/{chunk-RSKUUEBA.js → chunk-QYGIQ5NM.js} +140 -417
- package/dist/chunk-QYGIQ5NM.js.map +1 -0
- package/dist/{chunk-UE57H4MA.js → chunk-UXFOGILU.js} +2 -2
- package/dist/{chunk-OQMR2SDZ.js → chunk-VTR3MNYF.js} +2 -2
- package/dist/{chunk-4QEUKASL.js → chunk-W25I7G6U.js} +2 -2
- package/dist/{chunk-YJOWWRRS.js → chunk-WLZBVYC6.js} +125 -1206
- package/dist/chunk-WLZBVYC6.js.map +1 -0
- package/dist/{chunk-OOFBE62K.js → chunk-X7EJF46S.js} +2 -2
- package/dist/{chunk-BL33LBTN.js → chunk-XG4NAWAV.js} +3 -3
- package/dist/{chunk-ZZSXUZF3.js → chunk-YROCXMCK.js} +2 -2
- package/dist/{cli-B_6EMiQc.d.ts → cli-CuVEQWKr.d.ts} +3 -3
- package/dist/cli.d.ts +5 -5
- package/dist/cli.js +18 -17
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +3 -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 +3 -2
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +3 -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/contradiction/index.js +4 -4
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +3 -2
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +3 -3
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.js +49 -45
- 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 +3 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -2
- package/dist/maintenance/rebuild-memory-projection.js +4 -3
- package/dist/mcp-memory-inspector-app.d.ts +4 -4
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +1 -1
- package/dist/namespaces/migrate.js +4 -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 +3 -2
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +7 -6
- package/dist/{orchestrator-Dlw3ae4B.d.ts → orchestrator-CoqytbK_.d.ts} +3 -2
- package/dist/orchestrator.d.ts +3 -3
- package/dist/orchestrator.js +12 -10
- 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-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 +22 -22
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/index.d.ts +1 -1
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-C4sefXEI.d.ts → semantic-consolidation-BPs6BURk.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +4 -3
- package/dist/semantic-rule-promotion.js +3 -2
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +3 -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 +1 -1
- package/dist/storage.js +2 -1
- 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/types.d.ts +12 -12
- package/dist/{types-2vqxmO0j.d.ts → types-CpMPD8xl.d.ts} +20 -1
- package/dist/types.d.ts +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +3 -2
- package/package.json +1 -1
- package/src/orchestrator.ts +58 -0
- package/src/wearables/auto-sync.test.ts +181 -0
- package/src/wearables/auto-sync.ts +129 -0
- package/src/wearables/config.test.ts +58 -8
- package/src/wearables/config.ts +75 -5
- package/src/wearables/pipeline.test.ts +87 -4
- package/src/wearables/pipeline.ts +43 -13
- package/src/wearables/types.ts +20 -1
- package/dist/chunk-RSKUUEBA.js.map +0 -1
- package/dist/chunk-YJOWWRRS.js.map +0 -1
- /package/dist/{chunk-BWK5EEKS.js.map → chunk-242XFZ36.js.map} +0 -0
- /package/dist/{chunk-K3BTOW7N.js.map → chunk-32U3N7H5.js.map} +0 -0
- /package/dist/{chunk-5S6IREG3.js.map → chunk-3RDYU3JS.js.map} +0 -0
- /package/dist/{chunk-SACS6KE6.js.map → chunk-4S3N6HFG.js.map} +0 -0
- /package/dist/{chunk-VUTPRX7K.js.map → chunk-5PT5I6JQ.js.map} +0 -0
- /package/dist/{chunk-2VJ7AJFX.js.map → chunk-7A2QKUUA.js.map} +0 -0
- /package/dist/{chunk-NRQJBK36.js.map → chunk-C4KKM62E.js.map} +0 -0
- /package/dist/{chunk-GXWFZYSR.js.map → chunk-CMN5AWAZ.js.map} +0 -0
- /package/dist/{chunk-F6USGHMO.js.map → chunk-DOBJH4I6.js.map} +0 -0
- /package/dist/{chunk-ADOD7PJC.js.map → chunk-IFVFQRZ2.js.map} +0 -0
- /package/dist/{chunk-6LBQL5US.js.map → chunk-JCLECECB.js.map} +0 -0
- /package/dist/{chunk-S5W37FPX.js.map → chunk-LEG7XWS2.js.map} +0 -0
- /package/dist/{chunk-MQ24KOOR.js.map → chunk-PUEAEQSN.js.map} +0 -0
- /package/dist/{chunk-UE57H4MA.js.map → chunk-UXFOGILU.js.map} +0 -0
- /package/dist/{chunk-OQMR2SDZ.js.map → chunk-VTR3MNYF.js.map} +0 -0
- /package/dist/{chunk-4QEUKASL.js.map → chunk-W25I7G6U.js.map} +0 -0
- /package/dist/{chunk-OOFBE62K.js.map → chunk-X7EJF46S.js.map} +0 -0
- /package/dist/{chunk-BL33LBTN.js.map → chunk-XG4NAWAV.js.map} +0 -0
- /package/dist/{chunk-ZZSXUZF3.js.map → chunk-YROCXMCK.js.map} +0 -0
|
@@ -169,7 +169,9 @@ interface WearableSourceSettings {
|
|
|
169
169
|
/** Drop extracted facts scored below this importance level. */
|
|
170
170
|
minImportance: ImportanceLevel;
|
|
171
171
|
/**
|
|
172
|
-
* Cap on memories created per source per day. 0
|
|
172
|
+
* Cap on memories created per source per day. 0 (the default)
|
|
173
|
+
* disables the cap — the smart trust pipeline is the quality gate,
|
|
174
|
+
* and a count cap would drop real memories on busy days.
|
|
173
175
|
*/
|
|
174
176
|
maxMemoriesPerDay: number;
|
|
175
177
|
/**
|
|
@@ -239,6 +241,23 @@ interface WearablesConfig {
|
|
|
239
241
|
* Default false.
|
|
240
242
|
*/
|
|
241
243
|
digestEnabled: boolean;
|
|
244
|
+
/**
|
|
245
|
+
* Periodically refresh transcripts in-process (long-lived hosts).
|
|
246
|
+
* Every tick re-syncs `autoSyncDays` ending today — existing day
|
|
247
|
+
* files included, so the current day keeps growing while the
|
|
248
|
+
* wearable records. Default true.
|
|
249
|
+
*/
|
|
250
|
+
autoSyncEnabled: boolean;
|
|
251
|
+
/** Minutes between auto-sync ticks (1-1440). Default 15. */
|
|
252
|
+
autoSyncIntervalMinutes: number;
|
|
253
|
+
/** Rolling window (days ending today) per tick (1-90). Default 2. */
|
|
254
|
+
autoSyncDays: number;
|
|
255
|
+
/**
|
|
256
|
+
* Once-per-local-day deep pass window (days, 0-90) picking up late
|
|
257
|
+
* uploads and provider re-processing. 0 disables; otherwise must be
|
|
258
|
+
* >= autoSyncDays. Default 7.
|
|
259
|
+
*/
|
|
260
|
+
autoSyncDeepDays: number;
|
|
242
261
|
/** Correction rules from config (merged with CLI-managed rules). */
|
|
243
262
|
corrections: WearableCorrectionRule[];
|
|
244
263
|
/** Per-source settings, keyed by connector id. */
|
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import './types-BliCnURB.js';
|
|
2
2
|
import './index-DJ9QWMw-.js';
|
|
3
|
-
export { y as AccessTrackingEntry, A as ActiveRecallChatType, d as ActiveRecallModelFallbackPolicy, b as ActiveRecallPromptStyle, a as ActiveRecallQueryMode, c as ActiveRecallThinking, a7 as AgentAccessAuthToken, b2 as AgentAccessHttpConfig, b3 as AgentDefaultsConfig, b4 as AgentPersona, f as AgentPersonaModelConfig, b5 as BehaviorLoopAdjustment, e as BehaviorLoopPolicyState, b6 as BehaviorSignalDirection, B as BehaviorSignalEvent, b7 as BehaviorSignalType, aH as BootstrapOptions, aI as BootstrapResult, V as BriefingActiveThread, b8 as BriefingCalendarSourceError, aO as BriefingConfig, Q as BriefingFocus, O as BriefingFollowup, aP as BriefingOpenCommitment, X as BriefingRecentEntity, W as BriefingResult, N as BriefingSections, aQ as BriefingWindow, b9 as BufferEntryState, k as BufferState, o as BufferSurpriseEvent, Y as BufferTurn, U as CalendarEvent, S as CalendarSource, ba as CaptureMode, $ as Checkpoint, bb as CodexCliReasoningEffort, bc as CodexCompactionFlushMode, aR as CodexCompatConfig, bd as CodexConnectorConfig, aG as CodingContext, aL as CodingModeConfig, be as CompressionGuidelineActivationState, a9 as CompressionGuidelineOptimizerActionSummary, a8 as CompressionGuidelineOptimizerEventCounts, aa as CompressionGuidelineOptimizerRuleUpdate, bf as CompressionGuidelineOptimizerSourceWindow, C as CompressionGuidelineOptimizerState, bg as ConfidenceTier, bh as ConsolidationAction, bi as ConsolidationItem, aJ as ConsolidationObservation, ag as ConsolidationResult, s as ContinuityImprovementLoop, r as ContinuityIncidentCloseInput, p as ContinuityIncidentOpenInput, q as ContinuityIncidentRecord, bj as ContinuityIncidentState, bk as ContinuityLoopCadence, u as ContinuityLoopReviewInput, bl as ContinuityLoopStatus, t as ContinuityLoopUpsertInput, bm as ContradictionScanConfig, as as ConversationThread, bn as CronConversationRecallMode, bo as CronRecallMode, aS as DEFAULT_RECALL_DISCLOSURE, ah as DaySummaryResult, bp as DreamingConfig, bq as DreamingNarrativePromptStyle, br as DreamsDeepSleepConfig, bs as DreamsLightSleepConfig, au as DreamsPhase, bt as DreamsPhaseStatus, bu as DreamsPhasesConfig, bv as DreamsRemConfig, av as DreamsRunResult, at as DreamsStatusResult, bw as EngramTraceEvent, w as EntityActivityEntry, x as EntityFile, ac as EntityMention, v as EntityRelationship, ad as EntitySchemaDefinition, ae as EntitySchemaSectionDefinition, E as EntityStructuredSection, aK as EntityTimelineEntry, aT as ExtractedFact, bx as ExtractedProcedureStep, by as ExtractedQuestion, bz as ExtractedReasoningTrace, bA as ExtractedReasoningTraceStep, bB as ExtractedRelationship, bC as ExtractionPassSource, af as ExtractionResult, F as FileHygieneConfig, G as GatewayConfig, bD as GitHubLiveConnectorConfig, bE as GmailLiveConnectorConfig, bF as GoogleDriveLiveConnectorConfig, bG as HeartbeatConfig, bH as HeartbeatDetectionMode, a0 as HourlySummary, J as IdentityInjectionMode, a5 as ImportanceLevel, I as ImportanceScore, a2 as LifecycleState, L as LiveConnectorsConfig, bI as LlmTraceCallback, bJ as LlmTraceEvent, ak as MemoryActionEligibilityContext, aU as MemoryActionEligibilitySource, m as MemoryActionEvent, bK as MemoryActionOutcome, bL as MemoryActionPolicyDecision, al as MemoryActionPolicyResult, bM as MemoryActionStatus, ab as MemoryActionType, M as MemoryCategory, g as MemoryFile, j as MemoryFrontmatter, ai as MemoryIntent, n as MemoryLifecycleEvent, am as MemoryLifecycleEventType, an as MemoryLifecycleStateSummary, i as MemoryLink, bN as MemoryLinkType, aV as MemoryObservation, bO as MemoryOsPresetName, z as MemoryProjectionCurrentState, aW as MemoryScope, h as MemoryStatus, D as MemorySummary, l as MetaState, bP as ModelApi, bQ as ModelDefinitionConfig, bR as ModelProviderAuthMode, ao as ModelProviderConfig, bS as NamespacePolicy, ap as NativeKnowledgeConfig, bT as NativeKnowledgeFolderRuleConfig, bU as NativeKnowledgeObsidianVaultConfig, bV as NativeKnowledgeOpenClawWorkspaceConfig, bW as NotionLiveConnectorConfig, P as PluginConfig, a4 as PolicyClass, bX as PrincipalFromSessionKeyMode, bY as PrincipalRule, bZ as ProceduralConfig, aj as QmdSearchExplain, Z as QmdSearchResult, b_ as QuestionEntry, aX as RECALL_DISCLOSURE_LEVELS, b$ as ReasoningEffort, K as RecallDisclosure, c0 as RecallPipelineConfig, H as RecallPlanMode, c1 as RecallSectionConfig, R as RecallTierExplain, c2 as RecallTraceEvent, c3 as RelevanceFeedback, aq as RetrievalTier, c4 as SPECULATIVE_TTL_DAYS, c5 as ScoredEntity, a6 as SecretRef, c6 as SemanticChunkingConfigShape, a1 as SessionObserverBandConfig, c7 as SignalLevel, ar as SignalScanResult, c8 as SlotBehaviorConfig, c9 as SlotMismatchMode, T as TopicScore, _ as TranscriptEntry, ca as TriggerMode, a3 as VerificationState, cb as confidenceTier, b1 as isRecallDisclosure } from './types-
|
|
3
|
+
export { y as AccessTrackingEntry, A as ActiveRecallChatType, d as ActiveRecallModelFallbackPolicy, b as ActiveRecallPromptStyle, a as ActiveRecallQueryMode, c as ActiveRecallThinking, a7 as AgentAccessAuthToken, b2 as AgentAccessHttpConfig, b3 as AgentDefaultsConfig, b4 as AgentPersona, f as AgentPersonaModelConfig, b5 as BehaviorLoopAdjustment, e as BehaviorLoopPolicyState, b6 as BehaviorSignalDirection, B as BehaviorSignalEvent, b7 as BehaviorSignalType, aH as BootstrapOptions, aI as BootstrapResult, V as BriefingActiveThread, b8 as BriefingCalendarSourceError, aO as BriefingConfig, Q as BriefingFocus, O as BriefingFollowup, aP as BriefingOpenCommitment, X as BriefingRecentEntity, W as BriefingResult, N as BriefingSections, aQ as BriefingWindow, b9 as BufferEntryState, k as BufferState, o as BufferSurpriseEvent, Y as BufferTurn, U as CalendarEvent, S as CalendarSource, ba as CaptureMode, $ as Checkpoint, bb as CodexCliReasoningEffort, bc as CodexCompactionFlushMode, aR as CodexCompatConfig, bd as CodexConnectorConfig, aG as CodingContext, aL as CodingModeConfig, be as CompressionGuidelineActivationState, a9 as CompressionGuidelineOptimizerActionSummary, a8 as CompressionGuidelineOptimizerEventCounts, aa as CompressionGuidelineOptimizerRuleUpdate, bf as CompressionGuidelineOptimizerSourceWindow, C as CompressionGuidelineOptimizerState, bg as ConfidenceTier, bh as ConsolidationAction, bi as ConsolidationItem, aJ as ConsolidationObservation, ag as ConsolidationResult, s as ContinuityImprovementLoop, r as ContinuityIncidentCloseInput, p as ContinuityIncidentOpenInput, q as ContinuityIncidentRecord, bj as ContinuityIncidentState, bk as ContinuityLoopCadence, u as ContinuityLoopReviewInput, bl as ContinuityLoopStatus, t as ContinuityLoopUpsertInput, bm as ContradictionScanConfig, as as ConversationThread, bn as CronConversationRecallMode, bo as CronRecallMode, aS as DEFAULT_RECALL_DISCLOSURE, ah as DaySummaryResult, bp as DreamingConfig, bq as DreamingNarrativePromptStyle, br as DreamsDeepSleepConfig, bs as DreamsLightSleepConfig, au as DreamsPhase, bt as DreamsPhaseStatus, bu as DreamsPhasesConfig, bv as DreamsRemConfig, av as DreamsRunResult, at as DreamsStatusResult, bw as EngramTraceEvent, w as EntityActivityEntry, x as EntityFile, ac as EntityMention, v as EntityRelationship, ad as EntitySchemaDefinition, ae as EntitySchemaSectionDefinition, E as EntityStructuredSection, aK as EntityTimelineEntry, aT as ExtractedFact, bx as ExtractedProcedureStep, by as ExtractedQuestion, bz as ExtractedReasoningTrace, bA as ExtractedReasoningTraceStep, bB as ExtractedRelationship, bC as ExtractionPassSource, af as ExtractionResult, F as FileHygieneConfig, G as GatewayConfig, bD as GitHubLiveConnectorConfig, bE as GmailLiveConnectorConfig, bF as GoogleDriveLiveConnectorConfig, bG as HeartbeatConfig, bH as HeartbeatDetectionMode, a0 as HourlySummary, J as IdentityInjectionMode, a5 as ImportanceLevel, I as ImportanceScore, a2 as LifecycleState, L as LiveConnectorsConfig, bI as LlmTraceCallback, bJ as LlmTraceEvent, ak as MemoryActionEligibilityContext, aU as MemoryActionEligibilitySource, m as MemoryActionEvent, bK as MemoryActionOutcome, bL as MemoryActionPolicyDecision, al as MemoryActionPolicyResult, bM as MemoryActionStatus, ab as MemoryActionType, M as MemoryCategory, g as MemoryFile, j as MemoryFrontmatter, ai as MemoryIntent, n as MemoryLifecycleEvent, am as MemoryLifecycleEventType, an as MemoryLifecycleStateSummary, i as MemoryLink, bN as MemoryLinkType, aV as MemoryObservation, bO as MemoryOsPresetName, z as MemoryProjectionCurrentState, aW as MemoryScope, h as MemoryStatus, D as MemorySummary, l as MetaState, bP as ModelApi, bQ as ModelDefinitionConfig, bR as ModelProviderAuthMode, ao as ModelProviderConfig, bS as NamespacePolicy, ap as NativeKnowledgeConfig, bT as NativeKnowledgeFolderRuleConfig, bU as NativeKnowledgeObsidianVaultConfig, bV as NativeKnowledgeOpenClawWorkspaceConfig, bW as NotionLiveConnectorConfig, P as PluginConfig, a4 as PolicyClass, bX as PrincipalFromSessionKeyMode, bY as PrincipalRule, bZ as ProceduralConfig, aj as QmdSearchExplain, Z as QmdSearchResult, b_ as QuestionEntry, aX as RECALL_DISCLOSURE_LEVELS, b$ as ReasoningEffort, K as RecallDisclosure, c0 as RecallPipelineConfig, H as RecallPlanMode, c1 as RecallSectionConfig, R as RecallTierExplain, c2 as RecallTraceEvent, c3 as RelevanceFeedback, aq as RetrievalTier, c4 as SPECULATIVE_TTL_DAYS, c5 as ScoredEntity, a6 as SecretRef, c6 as SemanticChunkingConfigShape, a1 as SessionObserverBandConfig, c7 as SignalLevel, ar as SignalScanResult, c8 as SlotBehaviorConfig, c9 as SlotMismatchMode, T as TopicScore, _ as TranscriptEntry, ca as TriggerMode, a3 as VerificationState, cb as confidenceTier, b1 as isRecallDisclosure } from './types-CpMPD8xl.js';
|
package/dist/verified-recall.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
searchVerifiedEpisodes
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YROCXMCK.js";
|
|
4
4
|
import "./chunk-HQ6NIBL6.js";
|
|
5
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-QYGIQ5NM.js";
|
|
6
|
+
import "./chunk-M7XQSUBB.js";
|
|
6
7
|
import "./chunk-5UZXUTVO.js";
|
|
7
8
|
import "./chunk-J6A3CX5N.js";
|
|
8
9
|
import "./chunk-FPNQF475.js";
|
package/package.json
CHANGED
package/src/orchestrator.ts
CHANGED
|
@@ -1700,6 +1700,7 @@ export class Orchestrator {
|
|
|
1700
1700
|
>();
|
|
1701
1701
|
private qmdMaintenanceTimer: NodeJS.Timeout | null = null;
|
|
1702
1702
|
private wearablesServiceInstance: WearablesService | null = null;
|
|
1703
|
+
private wearablesAutoSyncHandle: { stop(): Promise<void> } | null = null;
|
|
1703
1704
|
private qmdMaintenancePending = false;
|
|
1704
1705
|
private qmdMaintenanceInFlight = false;
|
|
1705
1706
|
private lastQmdEmbedAtMs = 0;
|
|
@@ -1781,6 +1782,12 @@ export class Orchestrator {
|
|
|
1781
1782
|
*/
|
|
1782
1783
|
async destroy(): Promise<void> {
|
|
1783
1784
|
this.abortDeferredInit();
|
|
1785
|
+
if (this.wearablesAutoSyncHandle) {
|
|
1786
|
+
// Aborts in-flight provider fetches and waits for the tick to
|
|
1787
|
+
// settle, so nothing is writing or reindexing past destroy().
|
|
1788
|
+
await this.wearablesAutoSyncHandle.stop();
|
|
1789
|
+
this.wearablesAutoSyncHandle = null;
|
|
1790
|
+
}
|
|
1784
1791
|
if (this.qmdMaintenanceTimer) {
|
|
1785
1792
|
clearTimeout(this.qmdMaintenanceTimer);
|
|
1786
1793
|
this.qmdMaintenanceTimer = null;
|
|
@@ -2957,6 +2964,57 @@ export class Orchestrator {
|
|
|
2957
2964
|
}
|
|
2958
2965
|
}
|
|
2959
2966
|
|
|
2967
|
+
// Wearables auto-sync: in-process periodic transcript refresh for
|
|
2968
|
+
// long-lived hosts (default on). Today's transcript keeps growing
|
|
2969
|
+
// while the wearable records; a once-per-local-day deep pass picks
|
|
2970
|
+
// up late uploads and provider re-processing. Static config gate —
|
|
2971
|
+
// sources can't appear at runtime, so checking once here is safe.
|
|
2972
|
+
// The timer is unref'd, so one-shot CLI runs exit naturally without
|
|
2973
|
+
// ever ticking; idempotent across stop/start cycles via the handle
|
|
2974
|
+
// guard. Non-fatal: a failure to start must not break init.
|
|
2975
|
+
if (signal.aborted) return;
|
|
2976
|
+
if (
|
|
2977
|
+
!this.wearablesAutoSyncHandle &&
|
|
2978
|
+
this.config.wearables.enabled &&
|
|
2979
|
+
this.config.wearables.autoSyncEnabled &&
|
|
2980
|
+
Object.values(this.config.wearables.sources).some((source) => source.enabled)
|
|
2981
|
+
) {
|
|
2982
|
+
try {
|
|
2983
|
+
const { startWearablesAutoSync } = await import("./wearables/auto-sync.js");
|
|
2984
|
+
// Re-check after the await: destroy() may have aborted while
|
|
2985
|
+
// the import was in flight, having found no handle to stop —
|
|
2986
|
+
// starting now would leave a live interval on a destroyed
|
|
2987
|
+
// orchestrator (Cursor review on PR #1464). Handle creation
|
|
2988
|
+
// below is synchronous, so no further window exists.
|
|
2989
|
+
if (signal.aborted) return;
|
|
2990
|
+
this.wearablesAutoSyncHandle = startWearablesAutoSync(
|
|
2991
|
+
{
|
|
2992
|
+
intervalMinutes: this.config.wearables.autoSyncIntervalMinutes,
|
|
2993
|
+
days: this.config.wearables.autoSyncDays,
|
|
2994
|
+
deepDays: this.config.wearables.autoSyncDeepDays,
|
|
2995
|
+
...(this.config.wearables.timezone !== undefined
|
|
2996
|
+
? { timezone: this.config.wearables.timezone }
|
|
2997
|
+
: {}),
|
|
2998
|
+
},
|
|
2999
|
+
{
|
|
3000
|
+
sync: (options) => this.getWearablesService().sync(options),
|
|
3001
|
+
log: {
|
|
3002
|
+
info: (message) => log.info(message),
|
|
3003
|
+
warn: (message) => log.warn(message),
|
|
3004
|
+
},
|
|
3005
|
+
},
|
|
3006
|
+
);
|
|
3007
|
+
log.info(
|
|
3008
|
+
`wearables auto-sync started: every ${this.config.wearables.autoSyncIntervalMinutes}m over ${this.config.wearables.autoSyncDays}d (deep ${this.config.wearables.autoSyncDeepDays}d daily)`,
|
|
3009
|
+
);
|
|
3010
|
+
} catch (err) {
|
|
3011
|
+
const { displayErrorDetail } = await import("./runtime/better-sqlite.js");
|
|
3012
|
+
log.warn(
|
|
3013
|
+
`wearables auto-sync failed to start (non-fatal): ${displayErrorDetail(err)}`,
|
|
3014
|
+
);
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
3017
|
+
|
|
2960
3018
|
log.info("orchestrator initialized (full — deferred steps complete)");
|
|
2961
3019
|
}
|
|
2962
3020
|
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { startWearablesAutoSync } from "./auto-sync.js";
|
|
5
|
+
|
|
6
|
+
function makeDeps(overrides: { failTimes?: number } = {}) {
|
|
7
|
+
const calls: Array<{ days: number }> = [];
|
|
8
|
+
const warnings: string[] = [];
|
|
9
|
+
let remainingFailures = overrides.failTimes ?? 0;
|
|
10
|
+
let nowIso = "2026-06-12T10:00:00.000Z";
|
|
11
|
+
return {
|
|
12
|
+
calls,
|
|
13
|
+
warnings,
|
|
14
|
+
setNow(iso: string) {
|
|
15
|
+
nowIso = iso;
|
|
16
|
+
},
|
|
17
|
+
deps: {
|
|
18
|
+
sync: async (options: { days: number }) => {
|
|
19
|
+
if (remainingFailures > 0) {
|
|
20
|
+
remainingFailures -= 1;
|
|
21
|
+
throw new Error("provider down");
|
|
22
|
+
}
|
|
23
|
+
calls.push(options);
|
|
24
|
+
return [];
|
|
25
|
+
},
|
|
26
|
+
log: {
|
|
27
|
+
info: () => {},
|
|
28
|
+
warn: (message: string) => {
|
|
29
|
+
warnings.push(message);
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
now: () => new Date(nowIso),
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const SETTINGS = {
|
|
38
|
+
intervalMinutes: 15,
|
|
39
|
+
days: 2,
|
|
40
|
+
deepDays: 7,
|
|
41
|
+
timezone: "UTC",
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
test("first tick runs the deep window, same-day ticks run the shallow window", async () => {
|
|
45
|
+
const { calls, deps } = makeDeps();
|
|
46
|
+
const handle = startWearablesAutoSync(SETTINGS, deps);
|
|
47
|
+
try {
|
|
48
|
+
await handle.tick();
|
|
49
|
+
await handle.tick();
|
|
50
|
+
await handle.tick();
|
|
51
|
+
assert.deepEqual(
|
|
52
|
+
calls.map((call) => call.days),
|
|
53
|
+
[7, 2, 2],
|
|
54
|
+
"deep once, then shallow for the rest of the day",
|
|
55
|
+
);
|
|
56
|
+
} finally {
|
|
57
|
+
handle.stop();
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("a new local day triggers the deep pass again", async () => {
|
|
62
|
+
const { calls, deps, setNow } = makeDeps();
|
|
63
|
+
const handle = startWearablesAutoSync(SETTINGS, deps);
|
|
64
|
+
try {
|
|
65
|
+
await handle.tick();
|
|
66
|
+
await handle.tick();
|
|
67
|
+
setNow("2026-06-13T00:05:00.000Z");
|
|
68
|
+
await handle.tick();
|
|
69
|
+
await handle.tick();
|
|
70
|
+
assert.deepEqual(
|
|
71
|
+
calls.map((call) => call.days),
|
|
72
|
+
[7, 2, 7, 2],
|
|
73
|
+
);
|
|
74
|
+
} finally {
|
|
75
|
+
handle.stop();
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("a failed deep pass retries deep on the next tick, never throws", async () => {
|
|
80
|
+
const { calls, warnings, deps } = makeDeps({ failTimes: 1 });
|
|
81
|
+
const handle = startWearablesAutoSync(SETTINGS, deps);
|
|
82
|
+
try {
|
|
83
|
+
await handle.tick();
|
|
84
|
+
assert.equal(calls.length, 0, "first tick failed");
|
|
85
|
+
assert.equal(warnings.length, 1);
|
|
86
|
+
assert.match(warnings[0], /retrying on the next tick/);
|
|
87
|
+
await handle.tick();
|
|
88
|
+
assert.deepEqual(
|
|
89
|
+
calls.map((call) => call.days),
|
|
90
|
+
[7],
|
|
91
|
+
"deep window retries — a failure must not consume the daily deep slot",
|
|
92
|
+
);
|
|
93
|
+
} finally {
|
|
94
|
+
handle.stop();
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test("deepDays 0 disables the deep pass entirely", async () => {
|
|
99
|
+
const { calls, deps } = makeDeps();
|
|
100
|
+
const handle = startWearablesAutoSync({ ...SETTINGS, deepDays: 0 }, deps);
|
|
101
|
+
try {
|
|
102
|
+
await handle.tick();
|
|
103
|
+
await handle.tick();
|
|
104
|
+
assert.deepEqual(
|
|
105
|
+
calls.map((call) => call.days),
|
|
106
|
+
[2, 2],
|
|
107
|
+
);
|
|
108
|
+
} finally {
|
|
109
|
+
handle.stop();
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("overlapping ticks are skipped, not stacked", async () => {
|
|
114
|
+
const calls: Array<{ days: number }> = [];
|
|
115
|
+
let release: (() => void) | null = null;
|
|
116
|
+
const handle = startWearablesAutoSync(SETTINGS, {
|
|
117
|
+
sync: async (options) => {
|
|
118
|
+
calls.push(options);
|
|
119
|
+
await new Promise<void>((resolve) => {
|
|
120
|
+
release = resolve;
|
|
121
|
+
});
|
|
122
|
+
return [];
|
|
123
|
+
},
|
|
124
|
+
log: { info: () => {}, warn: () => {} },
|
|
125
|
+
now: () => new Date("2026-06-12T10:00:00.000Z"),
|
|
126
|
+
});
|
|
127
|
+
try {
|
|
128
|
+
const first = handle.tick();
|
|
129
|
+
const second = handle.tick();
|
|
130
|
+
await second;
|
|
131
|
+
assert.equal(calls.length, 1, "second tick is a no-op while the first runs");
|
|
132
|
+
release!();
|
|
133
|
+
await first;
|
|
134
|
+
} finally {
|
|
135
|
+
handle.stop();
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("stop() prevents any further ticks", async () => {
|
|
140
|
+
const { calls, deps } = makeDeps();
|
|
141
|
+
const handle = startWearablesAutoSync(SETTINGS, deps);
|
|
142
|
+
await handle.stop();
|
|
143
|
+
await handle.tick();
|
|
144
|
+
assert.equal(calls.length, 0);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("stop() aborts the in-flight sync and awaits its settlement", async () => {
|
|
148
|
+
const warnings: string[] = [];
|
|
149
|
+
let sawSignal: AbortSignal | undefined;
|
|
150
|
+
let syncSettled = false;
|
|
151
|
+
const handle = startWearablesAutoSync(SETTINGS, {
|
|
152
|
+
sync: async (options) => {
|
|
153
|
+
sawSignal = options.signal;
|
|
154
|
+
// Hang until the shutdown abort arrives, like a slow provider.
|
|
155
|
+
await new Promise<void>((_resolve, reject) => {
|
|
156
|
+
options.signal!.addEventListener("abort", () =>
|
|
157
|
+
reject(new Error("aborted")),
|
|
158
|
+
);
|
|
159
|
+
}).finally(() => {
|
|
160
|
+
syncSettled = true;
|
|
161
|
+
});
|
|
162
|
+
},
|
|
163
|
+
log: {
|
|
164
|
+
info: () => {},
|
|
165
|
+
warn: (message: string) => {
|
|
166
|
+
warnings.push(message);
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
now: () => new Date("2026-06-12T10:00:00.000Z"),
|
|
170
|
+
});
|
|
171
|
+
const inFlight = handle.tick();
|
|
172
|
+
assert.ok(sawSignal instanceof AbortSignal, "sync receives the abort signal");
|
|
173
|
+
await handle.stop();
|
|
174
|
+
assert.equal(syncSettled, true, "stop() resolves only after the tick settled");
|
|
175
|
+
assert.equal(
|
|
176
|
+
warnings.length,
|
|
177
|
+
0,
|
|
178
|
+
"an abort raised by shutdown is intentional, never warned",
|
|
179
|
+
);
|
|
180
|
+
await inFlight;
|
|
181
|
+
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wearables auto-sync — in-process periodic transcript refresh.
|
|
3
|
+
*
|
|
4
|
+
* Every tick re-syncs a short rolling window ending today for ALL
|
|
5
|
+
* enabled sources, so the current day's transcript keeps growing while
|
|
6
|
+
* the wearable records and provider-side revisions of recent days flow
|
|
7
|
+
* in without operator action. Once per local day the window deepens to
|
|
8
|
+
* `autoSyncDeepDays` to pick up late uploads and provider reprocessing
|
|
9
|
+
* further back (phones syncing hours later, re-diarized transcripts).
|
|
10
|
+
*
|
|
11
|
+
* Day fetches are unconditional within the window — existing day files
|
|
12
|
+
* are always re-fetched and re-composed; the content-hash skip in the
|
|
13
|
+
* pipeline keeps unchanged days write-free, so a tick on a quiet day
|
|
14
|
+
* is read-only. The timer is unref'd: it never keeps a one-shot CLI
|
|
15
|
+
* process alive, and long-lived hosts stop it via the returned handle.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { describeErrorForOperator } from "./errors.js";
|
|
19
|
+
import { dateInTimezone, defaultTimezone } from "./pipeline.js";
|
|
20
|
+
|
|
21
|
+
export interface WearablesAutoSyncSettings {
|
|
22
|
+
/** Minutes between ticks. */
|
|
23
|
+
intervalMinutes: number;
|
|
24
|
+
/** Rolling window (days ending today) refreshed on a normal tick. */
|
|
25
|
+
days: number;
|
|
26
|
+
/**
|
|
27
|
+
* Window for the once-per-local-day deep pass. 0 disables the deep
|
|
28
|
+
* pass; otherwise must be >= `days` (validated at config parse).
|
|
29
|
+
*/
|
|
30
|
+
deepDays: number;
|
|
31
|
+
/** IANA timezone used to detect the local-day rollover. */
|
|
32
|
+
timezone?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface WearablesAutoSyncDeps {
|
|
36
|
+
/** Run a sync across all enabled sources (WearablesService.sync). */
|
|
37
|
+
sync(options: { days: number; signal?: AbortSignal }): Promise<unknown>;
|
|
38
|
+
log: { info(message: string): void; warn(message: string): void };
|
|
39
|
+
/** Clock injection for tests. */
|
|
40
|
+
now?: () => Date;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface WearablesAutoSyncHandle {
|
|
44
|
+
/** Run one scheduler tick now (first-run hook and test seam). */
|
|
45
|
+
tick(): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Stop the scheduler: clears the timer, aborts the in-flight sync's
|
|
48
|
+
* provider fetches via AbortSignal, and resolves once the in-flight
|
|
49
|
+
* tick has fully settled — after `await stop()` nothing is writing
|
|
50
|
+
* or reindexing anymore. The handle is single-use; a restarted host
|
|
51
|
+
* starts a fresh one.
|
|
52
|
+
*/
|
|
53
|
+
stop(): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Start the periodic refresh. The first tick fires after one full
|
|
58
|
+
* interval rather than at start — gateways on low-power hardware can
|
|
59
|
+
* restart-loop during setup (issue #462), and an immediate fetch on
|
|
60
|
+
* every restart would hammer provider APIs. Operators who want an
|
|
61
|
+
* instant refresh run `wearables sync` (or call `tick()`).
|
|
62
|
+
*/
|
|
63
|
+
export function startWearablesAutoSync(
|
|
64
|
+
settings: WearablesAutoSyncSettings,
|
|
65
|
+
deps: WearablesAutoSyncDeps,
|
|
66
|
+
): WearablesAutoSyncHandle {
|
|
67
|
+
let inFlight: Promise<void> | null = null;
|
|
68
|
+
let stopped = false;
|
|
69
|
+
let lastDeepDate: string | null = null;
|
|
70
|
+
// Aborting cancels the in-flight sync's provider fetches promptly on
|
|
71
|
+
// shutdown — without it, a slow tick would keep writing/reindexing
|
|
72
|
+
// after orchestrator.destroy() while a restarted host starts a
|
|
73
|
+
// second scheduler (Kilo review on PR #1464).
|
|
74
|
+
const abortController = new AbortController();
|
|
75
|
+
|
|
76
|
+
const tick = async (): Promise<void> => {
|
|
77
|
+
// Overlap guard: a slow provider or large deep window must never
|
|
78
|
+
// stack a second sync on top of a running one. The skipped call
|
|
79
|
+
// resolves immediately — it must NOT await the running tick, or a
|
|
80
|
+
// caller holding both promises could deadlock itself.
|
|
81
|
+
if (inFlight || stopped) return;
|
|
82
|
+
const run = (async () => {
|
|
83
|
+
try {
|
|
84
|
+
const now = deps.now ? deps.now() : new Date();
|
|
85
|
+
const today = dateInTimezone(now, settings.timezone ?? defaultTimezone());
|
|
86
|
+
const deep = settings.deepDays > 0 && lastDeepDate !== today;
|
|
87
|
+
const days = deep ? settings.deepDays : settings.days;
|
|
88
|
+
await deps.sync({ days, signal: abortController.signal });
|
|
89
|
+
// Mark the deep pass done only AFTER it succeeded — a failed
|
|
90
|
+
// deep pass retries on the next tick instead of silently
|
|
91
|
+
// waiting for tomorrow (CLAUDE.md rule 25's "confirm before
|
|
92
|
+
// consuming the one-shot" shape).
|
|
93
|
+
if (deep) lastDeepDate = today;
|
|
94
|
+
deps.log.info(
|
|
95
|
+
`wearables auto-sync: refreshed ${days}-day window${deep ? " (daily deep pass)" : ""}`,
|
|
96
|
+
);
|
|
97
|
+
} catch (err) {
|
|
98
|
+
// An abort raised by stop() is intentional shutdown, not a
|
|
99
|
+
// failure — warning about it would be noise in every clean
|
|
100
|
+
// shutdown log.
|
|
101
|
+
if (!stopped) {
|
|
102
|
+
deps.log.warn(
|
|
103
|
+
`wearables auto-sync failed: ${describeErrorForOperator(err)} — retrying on the next tick`,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
} finally {
|
|
107
|
+
inFlight = null;
|
|
108
|
+
}
|
|
109
|
+
})();
|
|
110
|
+
inFlight = run;
|
|
111
|
+
await run;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const timer = setInterval(() => {
|
|
115
|
+
void tick();
|
|
116
|
+
}, settings.intervalMinutes * 60_000);
|
|
117
|
+
timer.unref?.();
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
tick,
|
|
121
|
+
stop: async () => {
|
|
122
|
+
stopped = true;
|
|
123
|
+
clearInterval(timer);
|
|
124
|
+
abortController.abort();
|
|
125
|
+
// tick() never rejects (all paths caught), so this only waits.
|
|
126
|
+
if (inFlight) await inFlight;
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
@@ -37,7 +37,7 @@ test("source settings default to the fully-automated smart pipeline", () => {
|
|
|
37
37
|
assert.equal(source.reviewTrust, 0.45);
|
|
38
38
|
assert.equal(source.minConfidence, 0.6);
|
|
39
39
|
assert.equal(source.minImportance, "low");
|
|
40
|
-
assert.equal(source.maxMemoriesPerDay,
|
|
40
|
+
assert.equal(source.maxMemoriesPerDay, 0, "uncapped by default");
|
|
41
41
|
assert.equal(source.importNativeMemories, "smart");
|
|
42
42
|
assert.deepEqual(source.cleanup, {
|
|
43
43
|
mergeSameSpeaker: true,
|
|
@@ -95,15 +95,15 @@ test("maxMemoriesPerDay honors the documented 0-disables value and bounds", () =
|
|
|
95
95
|
sources: { limitless: { maxMemoriesPerDay: 0 } },
|
|
96
96
|
});
|
|
97
97
|
assert.equal(parsed.sources.limitless.maxMemoriesPerDay, 0);
|
|
98
|
-
//
|
|
99
|
-
assert.throws(
|
|
100
|
-
() => parseWearablesConfig({ sources: { limitless: { maxMemoriesPerDay: 99999 } } }),
|
|
101
|
-
/maxMemoriesPerDay must be an integer between 0 and 500/,
|
|
102
|
-
);
|
|
98
|
+
// No ceiling: any non-negative integer cap is the operator's call.
|
|
103
99
|
assert.equal(
|
|
104
|
-
parseWearablesConfig({ sources: { limitless: { maxMemoriesPerDay:
|
|
100
|
+
parseWearablesConfig({ sources: { limitless: { maxMemoriesPerDay: 99999 } } })
|
|
105
101
|
.sources.limitless.maxMemoriesPerDay,
|
|
106
|
-
|
|
102
|
+
99999,
|
|
103
|
+
);
|
|
104
|
+
assert.throws(
|
|
105
|
+
() => parseWearablesConfig({ sources: { limitless: { maxMemoriesPerDay: -1 } } }),
|
|
106
|
+
/maxMemoriesPerDay must be a non-negative integer/,
|
|
107
107
|
);
|
|
108
108
|
assert.throws(
|
|
109
109
|
() => parseWearablesConfig({ sources: { limitless: { maxMemoriesPerDay: "lots" } } }),
|
|
@@ -170,3 +170,53 @@ test("minConfidence rejects out-of-range values instead of clamping", () => {
|
|
|
170
170
|
0.85,
|
|
171
171
|
);
|
|
172
172
|
});
|
|
173
|
+
|
|
174
|
+
test("auto-sync defaults to enabled with sane window settings", () => {
|
|
175
|
+
const parsed = parseWearablesConfig({});
|
|
176
|
+
assert.equal(parsed.autoSyncEnabled, true);
|
|
177
|
+
assert.equal(parsed.autoSyncIntervalMinutes, 15);
|
|
178
|
+
assert.equal(parsed.autoSyncDays, 2);
|
|
179
|
+
assert.equal(parsed.autoSyncDeepDays, 7);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test("auto-sync knobs parse, coerce, and loud-reject invalid values", () => {
|
|
183
|
+
const parsed = parseWearablesConfig({
|
|
184
|
+
autoSyncEnabled: "false",
|
|
185
|
+
autoSyncIntervalMinutes: "30",
|
|
186
|
+
autoSyncDays: 3,
|
|
187
|
+
autoSyncDeepDays: 14,
|
|
188
|
+
});
|
|
189
|
+
assert.equal(parsed.autoSyncEnabled, false, "boolean-ish strings coerce");
|
|
190
|
+
assert.equal(parsed.autoSyncIntervalMinutes, 30, "numeric strings coerce");
|
|
191
|
+
assert.equal(parsed.autoSyncDays, 3);
|
|
192
|
+
assert.equal(parsed.autoSyncDeepDays, 14);
|
|
193
|
+
|
|
194
|
+
assert.throws(
|
|
195
|
+
() => parseWearablesConfig({ autoSyncIntervalMinutes: 0 }),
|
|
196
|
+
/autoSyncIntervalMinutes must be an integer between 1 and 1440/,
|
|
197
|
+
);
|
|
198
|
+
assert.throws(
|
|
199
|
+
() => parseWearablesConfig({ autoSyncIntervalMinutes: 2.5 }),
|
|
200
|
+
/autoSyncIntervalMinutes/,
|
|
201
|
+
);
|
|
202
|
+
assert.throws(
|
|
203
|
+
() => parseWearablesConfig({ autoSyncDays: 0 }),
|
|
204
|
+
/autoSyncDays must be an integer between 1 and 90/,
|
|
205
|
+
);
|
|
206
|
+
assert.throws(
|
|
207
|
+
() => parseWearablesConfig({ autoSyncDeepDays: 91 }),
|
|
208
|
+
/autoSyncDeepDays must be an integer between 0 and 90/,
|
|
209
|
+
);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test("a deep window narrower than the tick window is rejected, 0 disables", () => {
|
|
213
|
+
assert.throws(
|
|
214
|
+
() => parseWearablesConfig({ autoSyncDays: 5, autoSyncDeepDays: 3 }),
|
|
215
|
+
/autoSyncDeepDays must be 0 \(disabled\) or >= wearables.autoSyncDays/,
|
|
216
|
+
);
|
|
217
|
+
assert.equal(parseWearablesConfig({ autoSyncDeepDays: 0 }).autoSyncDeepDays, 0);
|
|
218
|
+
assert.equal(
|
|
219
|
+
parseWearablesConfig({ autoSyncDays: 5, autoSyncDeepDays: 5 }).autoSyncDeepDays,
|
|
220
|
+
5,
|
|
221
|
+
);
|
|
222
|
+
});
|
package/src/wearables/config.ts
CHANGED
|
@@ -34,8 +34,16 @@ 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
|
-
|
|
38
|
-
|
|
37
|
+
// Uncapped by default — wearables capture full days and the smart trust
|
|
38
|
+
// pipeline is the quality gate; a count cap would drop real memories on
|
|
39
|
+
// busy days. Operators who want a ceiling set any positive integer.
|
|
40
|
+
const DEFAULT_MAX_MEMORIES_PER_DAY = 0;
|
|
41
|
+
const DEFAULT_AUTO_SYNC_ENABLED = true;
|
|
42
|
+
const DEFAULT_AUTO_SYNC_INTERVAL_MINUTES = 15;
|
|
43
|
+
const MAX_AUTO_SYNC_INTERVAL_MINUTES = 1440;
|
|
44
|
+
const DEFAULT_AUTO_SYNC_DAYS = 2;
|
|
45
|
+
const DEFAULT_AUTO_SYNC_DEEP_DAYS = 7;
|
|
46
|
+
const MAX_AUTO_SYNC_WINDOW_DAYS = 90;
|
|
39
47
|
const DEFAULT_SOURCE_TRUST = 0.8;
|
|
40
48
|
const DEFAULT_AUTO_APPROVE_TRUST = 0.7;
|
|
41
49
|
const DEFAULT_REVIEW_TRUST = 0.45;
|
|
@@ -71,6 +79,10 @@ export function defaultWearablesConfig(): WearablesConfig {
|
|
|
71
79
|
redactionPatterns: [],
|
|
72
80
|
offTheRecordEnabled: true,
|
|
73
81
|
digestEnabled: true,
|
|
82
|
+
autoSyncEnabled: DEFAULT_AUTO_SYNC_ENABLED,
|
|
83
|
+
autoSyncIntervalMinutes: DEFAULT_AUTO_SYNC_INTERVAL_MINUTES,
|
|
84
|
+
autoSyncDays: DEFAULT_AUTO_SYNC_DAYS,
|
|
85
|
+
autoSyncDeepDays: DEFAULT_AUTO_SYNC_DEEP_DAYS,
|
|
74
86
|
corrections: [],
|
|
75
87
|
sources: {},
|
|
76
88
|
};
|
|
@@ -198,11 +210,10 @@ function parseSourceSettings(
|
|
|
198
210
|
raw.maxMemoriesPerDay !== undefined &&
|
|
199
211
|
(maxPerDayRaw === undefined ||
|
|
200
212
|
!Number.isInteger(maxPerDayRaw) ||
|
|
201
|
-
maxPerDayRaw < 0
|
|
202
|
-
maxPerDayRaw > MAX_MEMORIES_PER_DAY_CEILING)
|
|
213
|
+
maxPerDayRaw < 0)
|
|
203
214
|
) {
|
|
204
215
|
throw new Error(
|
|
205
|
-
`${keyPath}.maxMemoriesPerDay must be
|
|
216
|
+
`${keyPath}.maxMemoriesPerDay must be a non-negative integer (0, the default, disables the cap); got ${JSON.stringify(raw.maxMemoriesPerDay)}`,
|
|
206
217
|
);
|
|
207
218
|
}
|
|
208
219
|
// 0 is the documented "disable the cap" value — honored here AND in
|
|
@@ -323,6 +334,57 @@ export function parseWearablesConfig(value: unknown): WearablesConfig {
|
|
|
323
334
|
compileRedactionPatterns(redactionPatterns);
|
|
324
335
|
}
|
|
325
336
|
|
|
337
|
+
const parseBoundedInt = (
|
|
338
|
+
value: unknown,
|
|
339
|
+
name: string,
|
|
340
|
+
fallback: number,
|
|
341
|
+
min: number,
|
|
342
|
+
max: number,
|
|
343
|
+
): number => {
|
|
344
|
+
if (value === undefined) return fallback;
|
|
345
|
+
const coerced = coerceNumber(value);
|
|
346
|
+
if (
|
|
347
|
+
coerced === undefined ||
|
|
348
|
+
!Number.isInteger(coerced) ||
|
|
349
|
+
coerced < min ||
|
|
350
|
+
coerced > max
|
|
351
|
+
) {
|
|
352
|
+
throw new Error(
|
|
353
|
+
`${name} must be an integer between ${min} and ${max}; got ${JSON.stringify(value)}`,
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
return coerced;
|
|
357
|
+
};
|
|
358
|
+
const autoSyncIntervalMinutes = parseBoundedInt(
|
|
359
|
+
raw.autoSyncIntervalMinutes,
|
|
360
|
+
"wearables.autoSyncIntervalMinutes",
|
|
361
|
+
defaults.autoSyncIntervalMinutes,
|
|
362
|
+
1,
|
|
363
|
+
MAX_AUTO_SYNC_INTERVAL_MINUTES,
|
|
364
|
+
);
|
|
365
|
+
const autoSyncDays = parseBoundedInt(
|
|
366
|
+
raw.autoSyncDays,
|
|
367
|
+
"wearables.autoSyncDays",
|
|
368
|
+
defaults.autoSyncDays,
|
|
369
|
+
1,
|
|
370
|
+
MAX_AUTO_SYNC_WINDOW_DAYS,
|
|
371
|
+
);
|
|
372
|
+
const autoSyncDeepDays = parseBoundedInt(
|
|
373
|
+
raw.autoSyncDeepDays,
|
|
374
|
+
"wearables.autoSyncDeepDays",
|
|
375
|
+
defaults.autoSyncDeepDays,
|
|
376
|
+
0,
|
|
377
|
+
MAX_AUTO_SYNC_WINDOW_DAYS,
|
|
378
|
+
);
|
|
379
|
+
// A deep window narrower than the every-tick window would make the
|
|
380
|
+
// "deep" pass fetch LESS than a normal tick — reject the confusion
|
|
381
|
+
// instead of silently honoring it (0 disables the deep pass).
|
|
382
|
+
if (autoSyncDeepDays !== 0 && autoSyncDeepDays < autoSyncDays) {
|
|
383
|
+
throw new Error(
|
|
384
|
+
`wearables.autoSyncDeepDays must be 0 (disabled) or >= wearables.autoSyncDays (${autoSyncDays}); got ${autoSyncDeepDays}`,
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
|
|
326
388
|
const sources: Record<string, WearableSourceSettings> = {};
|
|
327
389
|
if (raw.sources !== undefined) {
|
|
328
390
|
const rawSources = requireObject(raw.sources, "wearables.sources");
|
|
@@ -358,6 +420,14 @@ export function parseWearablesConfig(value: unknown): WearablesConfig {
|
|
|
358
420
|
"wearables.digestEnabled",
|
|
359
421
|
defaults.digestEnabled,
|
|
360
422
|
),
|
|
423
|
+
autoSyncEnabled: parseBool(
|
|
424
|
+
raw.autoSyncEnabled,
|
|
425
|
+
"wearables.autoSyncEnabled",
|
|
426
|
+
defaults.autoSyncEnabled,
|
|
427
|
+
),
|
|
428
|
+
autoSyncIntervalMinutes,
|
|
429
|
+
autoSyncDays,
|
|
430
|
+
autoSyncDeepDays,
|
|
361
431
|
corrections: parseCorrectionRules(raw.corrections, "wearables.corrections"),
|
|
362
432
|
sources,
|
|
363
433
|
};
|