@remnic/core 9.3.717 → 9.3.718
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-boundary.d.ts +5 -5
- package/dist/access-boundary.js +9 -9
- package/dist/access-cli.js +23 -23
- package/dist/access-http.d.ts +5 -5
- package/dist/access-http.js +13 -13
- package/dist/access-mcp.d.ts +5 -5
- package/dist/access-mcp.js +12 -12
- package/dist/access-operations-batch.js +10 -10
- package/dist/access-operations.d.ts +5 -5
- package/dist/access-operations.js +11 -11
- package/dist/{access-service-d4Tk-Dlr.d.ts → access-service-CZbnt0t2.d.ts} +3 -3
- package/dist/access-service.d.ts +5 -5
- package/dist/access-service.js +8 -8
- package/dist/access-surface-catalog.d.ts +5 -5
- 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 +4 -4
- package/dist/briefing.d.ts +3 -1
- package/dist/briefing.js +3 -3
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{catalog-CbR0CsUw.d.ts → catalog-CEYlMs9X.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +4 -4
- package/dist/{chunk-JEIROMLX.js → chunk-2COL35PK.js} +95 -9
- package/dist/chunk-2COL35PK.js.map +1 -0
- package/dist/{chunk-XZTUMWKQ.js → chunk-2PTBLS2S.js} +2 -2
- package/dist/{chunk-2Y6LMOQQ.js → chunk-2VHMVWPU.js} +2 -2
- package/dist/{chunk-6UU43ZGD.js → chunk-4KZGLDJJ.js} +2 -2
- package/dist/{chunk-K44MIN6D.js → chunk-5RHM43BJ.js} +3 -3
- package/dist/{chunk-2B43BYYZ.js → chunk-72VDBALG.js} +18 -18
- package/dist/{chunk-UY4JMEAK.js → chunk-7EEVXW7X.js} +2 -2
- package/dist/{chunk-XCTDHF7U.js → chunk-A5TUPZ3N.js} +33 -1
- package/dist/chunk-A5TUPZ3N.js.map +1 -0
- package/dist/{chunk-WI4QX7GH.js → chunk-A66YRSOS.js} +2 -2
- package/dist/{chunk-EM22PCQR.js → chunk-ANI5DUAE.js} +8 -6
- package/dist/{chunk-EM22PCQR.js.map → chunk-ANI5DUAE.js.map} +1 -1
- package/dist/{chunk-VZQXJNBD.js → chunk-APUJIMDM.js} +2 -2
- package/dist/{chunk-MPHDVHIB.js → chunk-DIFU33GU.js} +2 -2
- package/dist/{chunk-DXGS5YOQ.js → chunk-EH27LHML.js} +2 -2
- package/dist/{chunk-YAINYEM3.js → chunk-F3PVXKHP.js} +25 -1398
- package/dist/chunk-F3PVXKHP.js.map +1 -0
- package/dist/{chunk-DZYARLJ7.js → chunk-HLIR3RJ7.js} +2 -2
- package/dist/{chunk-6FUJ2VYY.js → chunk-JAKYZGV4.js} +3 -3
- package/dist/{chunk-ZAVTEQFM.js → chunk-JIZGYQYH.js} +3 -3
- package/dist/{chunk-QOIONSOI.js → chunk-KRGC4EDX.js} +2 -2
- package/dist/{chunk-AJOIM6UR.js → chunk-L5ASZA2F.js} +2 -2
- package/dist/{chunk-I56LKMF7.js → chunk-LXSG4L55.js} +2 -2
- package/dist/{chunk-MSVSP5VO.js → chunk-N3DUH6OO.js} +1 -1
- package/dist/chunk-N3DUH6OO.js.map +1 -0
- package/dist/{chunk-CTUWGJRI.js → chunk-NFRBADNR.js} +166 -28
- package/dist/chunk-NFRBADNR.js.map +1 -0
- package/dist/chunk-OJU73BUX.js +1688 -0
- package/dist/chunk-OJU73BUX.js.map +1 -0
- package/dist/{chunk-JVEMUX6L.js → chunk-OZ2KQ7HF.js} +2 -2
- package/dist/{chunk-OUDAU3T5.js → chunk-P5IPFZVH.js} +4 -4
- package/dist/{chunk-KHQ433G5.js → chunk-REWQAFSA.js} +2 -2
- package/dist/{chunk-V7GDTQ6I.js → chunk-S35FX6MU.js} +2 -2
- package/dist/{chunk-MTHNJCOJ.js → chunk-S3OPGGZB.js} +2 -2
- package/dist/{chunk-ZXLSNG3T.js → chunk-U5H7WHTS.js} +6 -4
- package/dist/{chunk-ZXLSNG3T.js.map → chunk-U5H7WHTS.js.map} +1 -1
- package/dist/{chunk-BZAK3RBN.js → chunk-UCJ5CDTK.js} +6 -6
- package/dist/{chunk-BF2426TN.js → chunk-URM3HW2R.js} +2 -2
- package/dist/{chunk-VO4UICII.js → chunk-YTZLBBEB.js} +2 -2
- package/dist/{chunk-OC56UWV5.js → chunk-YYOK4GVF.js} +2 -2
- package/dist/{cli-insNLYs6.d.ts → cli-1orcdXOY.d.ts} +3 -3
- package/dist/cli.d.ts +6 -6
- package/dist/cli.js +27 -27
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +3 -3
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +3 -3
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +3 -3
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +1 -1
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +3 -3
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +4 -4
- package/dist/extraction-faithfulness.d.ts +1 -1
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +9 -9
- package/dist/index.js +33 -33
- 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 -3
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
- package/dist/maintenance/rebuild-memory-projection.js +4 -4
- package/dist/mcp-memory-inspector-app.d.ts +5 -5
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +2 -2
- package/dist/namespaces/migrate.js +4 -4
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/storage.d.ts +2 -2
- package/dist/namespaces/storage.js +3 -3
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +9 -9
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +5 -5
- package/dist/{orchestrator-XPKhY2OV.d.ts → orchestrator-kOxredSr.d.ts} +20 -3
- package/dist/orchestrator.d.ts +4 -4
- package/dist/orchestrator.js +16 -16
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/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-DSjMDZ1u.d.ts → semantic-consolidation-B58v3S-a.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +4 -4
- package/dist/semantic-rule-promotion.js +3 -3
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +3 -3
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/storage.js +2 -2
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/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-D9dwzU_x.d.ts → types-ACmDOScJ.d.ts} +36 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +3 -3
- package/package.json +2 -2
- package/src/briefing.ts +32 -0
- package/src/config.ts +32 -0
- package/src/correction/index.ts +24 -0
- package/src/correction/passive-capture.test.ts +500 -0
- package/src/correction/passive-capture.ts +335 -0
- package/src/correction/passive-correction-detector.test.ts +263 -0
- package/src/correction/passive-correction-detector.ts +325 -0
- package/src/correction/passive-correction-notifications.ts +123 -0
- package/src/orchestrator.ts +196 -12
- package/src/types.ts +36 -0
- package/dist/chunk-2KF4HDG2.js +0 -24
- package/dist/chunk-2KF4HDG2.js.map +0 -1
- package/dist/chunk-CTUWGJRI.js.map +0 -1
- package/dist/chunk-JEIROMLX.js.map +0 -1
- package/dist/chunk-MSVSP5VO.js.map +0 -1
- package/dist/chunk-XCTDHF7U.js.map +0 -1
- package/dist/chunk-YAINYEM3.js.map +0 -1
- /package/dist/{chunk-XZTUMWKQ.js.map → chunk-2PTBLS2S.js.map} +0 -0
- /package/dist/{chunk-2Y6LMOQQ.js.map → chunk-2VHMVWPU.js.map} +0 -0
- /package/dist/{chunk-6UU43ZGD.js.map → chunk-4KZGLDJJ.js.map} +0 -0
- /package/dist/{chunk-K44MIN6D.js.map → chunk-5RHM43BJ.js.map} +0 -0
- /package/dist/{chunk-2B43BYYZ.js.map → chunk-72VDBALG.js.map} +0 -0
- /package/dist/{chunk-UY4JMEAK.js.map → chunk-7EEVXW7X.js.map} +0 -0
- /package/dist/{chunk-WI4QX7GH.js.map → chunk-A66YRSOS.js.map} +0 -0
- /package/dist/{chunk-VZQXJNBD.js.map → chunk-APUJIMDM.js.map} +0 -0
- /package/dist/{chunk-MPHDVHIB.js.map → chunk-DIFU33GU.js.map} +0 -0
- /package/dist/{chunk-DXGS5YOQ.js.map → chunk-EH27LHML.js.map} +0 -0
- /package/dist/{chunk-DZYARLJ7.js.map → chunk-HLIR3RJ7.js.map} +0 -0
- /package/dist/{chunk-6FUJ2VYY.js.map → chunk-JAKYZGV4.js.map} +0 -0
- /package/dist/{chunk-ZAVTEQFM.js.map → chunk-JIZGYQYH.js.map} +0 -0
- /package/dist/{chunk-QOIONSOI.js.map → chunk-KRGC4EDX.js.map} +0 -0
- /package/dist/{chunk-AJOIM6UR.js.map → chunk-L5ASZA2F.js.map} +0 -0
- /package/dist/{chunk-I56LKMF7.js.map → chunk-LXSG4L55.js.map} +0 -0
- /package/dist/{chunk-JVEMUX6L.js.map → chunk-OZ2KQ7HF.js.map} +0 -0
- /package/dist/{chunk-OUDAU3T5.js.map → chunk-P5IPFZVH.js.map} +0 -0
- /package/dist/{chunk-KHQ433G5.js.map → chunk-REWQAFSA.js.map} +0 -0
- /package/dist/{chunk-V7GDTQ6I.js.map → chunk-S35FX6MU.js.map} +0 -0
- /package/dist/{chunk-MTHNJCOJ.js.map → chunk-S3OPGGZB.js.map} +0 -0
- /package/dist/{chunk-BZAK3RBN.js.map → chunk-UCJ5CDTK.js.map} +0 -0
- /package/dist/{chunk-BF2426TN.js.map → chunk-URM3HW2R.js.map} +0 -0
- /package/dist/{chunk-VO4UICII.js.map → chunk-YTZLBBEB.js.map} +0 -0
- /package/dist/{chunk-OC56UWV5.js.map → chunk-YYOK4GVF.js.map} +0 -0
package/src/orchestrator.ts
CHANGED
|
@@ -24,6 +24,10 @@ import { SmartBuffer } from "./buffer.js";
|
|
|
24
24
|
import { chunkContent, type ChunkingConfig } from "./chunking.js";
|
|
25
25
|
import { semanticChunkContent, type SemanticChunkResult } from "./semantic-chunking.js";
|
|
26
26
|
import { ExtractionEngine } from "./extraction.js";
|
|
27
|
+
import { detectPassiveCorrections } from "./correction/passive-correction-detector.js";
|
|
28
|
+
import { capturePassiveCorrections, type PassiveCaptureConfig } from "./correction/passive-capture.js";
|
|
29
|
+
import { createCorrectionService } from "./correction/correction-access-wiring.js";
|
|
30
|
+
import type { CorrectionService } from "./correction/correction-service.js";
|
|
27
31
|
import { isAboveImportanceThreshold, scoreImportance } from "./importance.js";
|
|
28
32
|
import {
|
|
29
33
|
judgeFactDurability,
|
|
@@ -338,6 +342,7 @@ import {
|
|
|
338
342
|
} from "./namespaces/identity.js";
|
|
339
343
|
import {
|
|
340
344
|
canReadNamespace,
|
|
345
|
+
canWriteNamespace,
|
|
341
346
|
defaultNamespaceForPrincipal,
|
|
342
347
|
recallNamespacesForPrincipal,
|
|
343
348
|
resolvePrincipal,
|
|
@@ -1980,6 +1985,16 @@ export class Orchestrator {
|
|
|
1980
1985
|
{ count: number; lastAccessed: string }
|
|
1981
1986
|
> = new Map();
|
|
1982
1987
|
|
|
1988
|
+
// Passive correction capture (issue #1581) — dedup state + lazy service.
|
|
1989
|
+
private passiveCorrectionDedup: Set<string> = new Set();
|
|
1990
|
+
private _passiveCorrectionService: CorrectionService | null = null;
|
|
1991
|
+
private passiveCorrectionTelemetry: {
|
|
1992
|
+
detected: number;
|
|
1993
|
+
queued: number;
|
|
1994
|
+
autoApplied: number;
|
|
1995
|
+
suppressedReasonCounts: Record<string, number>;
|
|
1996
|
+
} = { detected: 0, queued: 0, autoApplied: 0, suppressedReasonCounts: {} };
|
|
1997
|
+
|
|
1983
1998
|
// Background serial queue for extractions (agent_end optimization)
|
|
1984
1999
|
// Queue stores promises that resolve when extraction should run
|
|
1985
2000
|
private extractionQueue: Array<() => Promise<void>> = [];
|
|
@@ -13012,6 +13027,139 @@ export class Orchestrator {
|
|
|
13012
13027
|
}
|
|
13013
13028
|
}
|
|
13014
13029
|
|
|
13030
|
+
/**
|
|
13031
|
+
* Passive correction capture (issue #1581) — detects corrections expressed
|
|
13032
|
+
* passively in conversation turns and routes them to the Correction Contract
|
|
13033
|
+
* (#1580). Called from `runExtraction` after persistence completes.
|
|
13034
|
+
*
|
|
13035
|
+
* Thin wiring: delegates ALL correction logic to the detector + capture
|
|
13036
|
+
* modules + the CorrectionService. This method only checks gates, calls the
|
|
13037
|
+
* detector, and routes results. Fail-open: capture errors never block the
|
|
13038
|
+
* extraction return path.
|
|
13039
|
+
*/
|
|
13040
|
+
private async maybeCapturePassiveCorrections(
|
|
13041
|
+
turns: readonly BufferTurn[],
|
|
13042
|
+
opts: {
|
|
13043
|
+
sessionKey: string;
|
|
13044
|
+
principal?: string;
|
|
13045
|
+
namespace: string;
|
|
13046
|
+
bufferKey: string;
|
|
13047
|
+
isLiveSession: boolean;
|
|
13048
|
+
},
|
|
13049
|
+
): Promise<void> {
|
|
13050
|
+
const mode = this.config.correctionCaptureMode;
|
|
13051
|
+
if (mode === "off") return;
|
|
13052
|
+
if (!this.config.correctionEnabled) return;
|
|
13053
|
+
|
|
13054
|
+
try {
|
|
13055
|
+
const corrections = detectPassiveCorrections(
|
|
13056
|
+
turns.map((t) => ({ role: t.role, content: t.content })),
|
|
13057
|
+
);
|
|
13058
|
+
if (corrections.length === 0) return;
|
|
13059
|
+
|
|
13060
|
+
// Replay/import: force queue-only mode even if config says auto.
|
|
13061
|
+
const effectiveMode = opts.isLiveSession ? mode : "queue";
|
|
13062
|
+
const captureConfig: PassiveCaptureConfig = {
|
|
13063
|
+
mode: effectiveMode,
|
|
13064
|
+
confidenceFloor: this.config.correctionCaptureConfidenceFloor,
|
|
13065
|
+
autoApplyMaxAffected: this.config.correctionCaptureAutoApplyMaxAffected,
|
|
13066
|
+
};
|
|
13067
|
+
|
|
13068
|
+
const service = this.passiveCorrectionService();
|
|
13069
|
+
const result = await capturePassiveCorrections(
|
|
13070
|
+
corrections,
|
|
13071
|
+
{
|
|
13072
|
+
correctionEnabled: this.config.correctionEnabled,
|
|
13073
|
+
isLiveSession: opts.isLiveSession,
|
|
13074
|
+
bufferKey: opts.bufferKey,
|
|
13075
|
+
sessionKey: opts.sessionKey,
|
|
13076
|
+
principal: opts.principal,
|
|
13077
|
+
namespace: opts.namespace,
|
|
13078
|
+
},
|
|
13079
|
+
captureConfig,
|
|
13080
|
+
{
|
|
13081
|
+
planCorrection: (req) => service.plan(req),
|
|
13082
|
+
applyCorrection: (planId, applyOpts) => service.apply(planId, applyOpts),
|
|
13083
|
+
storageDir: async (ns) => (await this.getStorage(ns)).dir,
|
|
13084
|
+
// Resolve `[m:xxxx]` handles to concrete memory ids via the single
|
|
13085
|
+
// shared helper (#1582). Returns null on miss/ambiguity so the
|
|
13086
|
+
// capture loop drops the handle and the planner falls back to text
|
|
13087
|
+
// search (review: "memory handles not resolved").
|
|
13088
|
+
resolveHandle: (ref, sessionKey) => {
|
|
13089
|
+
try {
|
|
13090
|
+
return this.resolveMemoryIdOrHandle(ref, sessionKey);
|
|
13091
|
+
} catch {
|
|
13092
|
+
return null;
|
|
13093
|
+
}
|
|
13094
|
+
},
|
|
13095
|
+
},
|
|
13096
|
+
this.passiveCorrectionDedup,
|
|
13097
|
+
);
|
|
13098
|
+
|
|
13099
|
+
// Accumulate telemetry
|
|
13100
|
+
this.passiveCorrectionTelemetry.detected += result.telemetry.detected;
|
|
13101
|
+
this.passiveCorrectionTelemetry.queued += result.telemetry.queued;
|
|
13102
|
+
this.passiveCorrectionTelemetry.autoApplied += result.telemetry.autoApplied;
|
|
13103
|
+
for (const [reason, count] of Object.entries(result.telemetry.suppressedReasons)) {
|
|
13104
|
+
this.passiveCorrectionTelemetry.suppressedReasonCounts[reason] =
|
|
13105
|
+
(this.passiveCorrectionTelemetry.suppressedReasonCounts[reason] ?? 0) + count;
|
|
13106
|
+
}
|
|
13107
|
+
} catch (err) {
|
|
13108
|
+
// Fail-open: passive capture never blocks extraction.
|
|
13109
|
+
log.debug(
|
|
13110
|
+
`passive-correction: capture failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`,
|
|
13111
|
+
);
|
|
13112
|
+
}
|
|
13113
|
+
}
|
|
13114
|
+
|
|
13115
|
+
/** Lazily construct the CorrectionService for passive capture. Stateless
|
|
13116
|
+
* across requests (per #1580 design); cached for the orchestrator's life. */
|
|
13117
|
+
private passiveCorrectionService(): CorrectionService {
|
|
13118
|
+
if (this._passiveCorrectionService) return this._passiveCorrectionService;
|
|
13119
|
+
this._passiveCorrectionService = createCorrectionService({
|
|
13120
|
+
orchestrator: this,
|
|
13121
|
+
// Session-scoped write ACL (review: "passive capture bypasses write
|
|
13122
|
+
// ACL"). A correction detected in session S plans only against S readable
|
|
13123
|
+
// namespaces and applies only to writable ones (rule 42) — passive
|
|
13124
|
+
// capture never becomes a cross-tenant mutation vector. Mirrors the
|
|
13125
|
+
// access-service createCorrectionService wiring rather than bypassing it.
|
|
13126
|
+
resolveAuthorizedNamespace: async (req) => {
|
|
13127
|
+
const principal = req.principal || resolvePrincipal(req.sessionKey, this.config);
|
|
13128
|
+
const ns = req.namespace ?? defaultNamespaceForPrincipal(principal, this.config);
|
|
13129
|
+
if (!canWriteNamespace(principal, ns, this.config)) {
|
|
13130
|
+
throw new Error(
|
|
13131
|
+
`passive correction: namespace "${ns}" is not writable for principal ${principal ?? "(none)"}`,
|
|
13132
|
+
);
|
|
13133
|
+
}
|
|
13134
|
+
return ns;
|
|
13135
|
+
},
|
|
13136
|
+
resolveReadableNamespaces: (req) => {
|
|
13137
|
+
const principal = req.principal || resolvePrincipal(req.sessionKey, this.config);
|
|
13138
|
+
return recallNamespacesForPrincipal(principal, this.config);
|
|
13139
|
+
},
|
|
13140
|
+
canWriteNamespace: async (req) => {
|
|
13141
|
+
const principal = req.principal || resolvePrincipal(req.sessionKey, this.config);
|
|
13142
|
+
return canWriteNamespace(principal, req.namespace, this.config);
|
|
13143
|
+
},
|
|
13144
|
+
llmComplete: async ({ system, user }) => {
|
|
13145
|
+
const llmResult = await this.localLlm.chatCompletion(
|
|
13146
|
+
[
|
|
13147
|
+
{ role: "system", content: system },
|
|
13148
|
+
{ role: "user", content: user },
|
|
13149
|
+
],
|
|
13150
|
+
{ operation: "correction-classify", priority: "background" },
|
|
13151
|
+
);
|
|
13152
|
+
if (!llmResult) {
|
|
13153
|
+
throw new Error(
|
|
13154
|
+
"passive correction classify+draft: local LLM unavailable (disabled or in cooldown)",
|
|
13155
|
+
);
|
|
13156
|
+
}
|
|
13157
|
+
return llmResult.content;
|
|
13158
|
+
},
|
|
13159
|
+
});
|
|
13160
|
+
return this._passiveCorrectionService;
|
|
13161
|
+
}
|
|
13162
|
+
|
|
13015
13163
|
private async runExtraction(
|
|
13016
13164
|
turns: BufferTurn[],
|
|
13017
13165
|
options: {
|
|
@@ -13097,13 +13245,13 @@ export class Orchestrator {
|
|
|
13097
13245
|
);
|
|
13098
13246
|
if (targetTurns.length === 0) {
|
|
13099
13247
|
log.debug("skipping extraction: no non-context turns after normalization");
|
|
13248
|
+
// Context-only turns may still contain corrections (review: "context-only
|
|
13249
|
+
// turns skip capture"). Scan normalizedTurns before clearing the buffer.
|
|
13250
|
+
if (normalizedTurns.length > 0) {
|
|
13251
|
+
await this.maybeCapturePassiveCorrections(normalizedTurns as BufferTurn[], { sessionKey, principal: resolvePrincipal(sessionKey, this.config), namespace: this.resolveSelfNamespace(sessionKey), bufferKey, isLiveSession: clearBufferAfterExtraction });
|
|
13252
|
+
}
|
|
13100
13253
|
await clearBuffer();
|
|
13101
|
-
return {
|
|
13102
|
-
status: "skipped",
|
|
13103
|
-
reason: "empty_normalized_turns",
|
|
13104
|
-
persistedCount: 0,
|
|
13105
|
-
durableOutputCount: 0,
|
|
13106
|
-
};
|
|
13254
|
+
return { status: "skipped", reason: "empty_normalized_turns", persistedCount: 0, durableOutputCount: 0 };
|
|
13107
13255
|
}
|
|
13108
13256
|
const sourceValidAt = latestSourceValidAtFromTurns(targetTurns);
|
|
13109
13257
|
throwIfDeadlineExceeded("before_extract");
|
|
@@ -13123,6 +13271,30 @@ export class Orchestrator {
|
|
|
13123
13271
|
`skipping extraction: below threshold (totalChars=${totalChars}, userTurns=${userTurns.length})`,
|
|
13124
13272
|
);
|
|
13125
13273
|
await clearBuffer();
|
|
13274
|
+
// Passive correction capture runs even when extraction is skipped for
|
|
13275
|
+
// being below the char/user-turn threshold (review: "skipped extraction
|
|
13276
|
+
// skips capture"). A short correction like "stop using Vim" is under
|
|
13277
|
+
// extractionMinChars but is exactly the high-value case this feature
|
|
13278
|
+
// exists for. The write namespace resolves through the SAME scope-profile
|
|
13279
|
+
// plan as the full extraction path so corrections target the active
|
|
13280
|
+
// profile's write layer, not just resolveSelfNamespace (review:
|
|
13281
|
+
// "below-threshold wrong namespace"). The ACL in passiveCorrectionService
|
|
13282
|
+
// authorizes the actual plan/apply.
|
|
13283
|
+
{
|
|
13284
|
+
const capturePrincipal =
|
|
13285
|
+
typeof options.principalOverride === "string" && options.principalOverride.length > 0
|
|
13286
|
+
? options.principalOverride
|
|
13287
|
+
: resolvePrincipal(sessionKey, this.config);
|
|
13288
|
+
const captureWO = typeof options.writeNamespaceOverride === "string" && options.writeNamespaceOverride.length > 0
|
|
13289
|
+
? options.writeNamespaceOverride : undefined;
|
|
13290
|
+
const captureCodingCtx = sessionKey ? this.getCodingContextForSession(sessionKey) : null;
|
|
13291
|
+
const captureCodingOv = resolveCodingNamespaceOverlay(captureCodingCtx, this.config.codingMode, this.config.defaultNamespace);
|
|
13292
|
+
const captureScopePlan = resolveScopeProfilePlan({ config: this.config, principal: capturePrincipal, codingContext: captureCodingCtx, codingOverlay: captureCodingOv });
|
|
13293
|
+
const captureNamespace = captureWO ?? captureScopePlan?.writeNamespace ?? this.resolveSelfNamespace(sessionKey);
|
|
13294
|
+
await this.maybeCapturePassiveCorrections(normalizedTurns as BufferTurn[], {
|
|
13295
|
+
sessionKey, principal: capturePrincipal, namespace: captureNamespace, bufferKey, isLiveSession: clearBufferAfterExtraction,
|
|
13296
|
+
});
|
|
13297
|
+
}
|
|
13126
13298
|
return {
|
|
13127
13299
|
status: "skipped",
|
|
13128
13300
|
reason: "below_threshold",
|
|
@@ -13322,13 +13494,12 @@ export class Orchestrator {
|
|
|
13322
13494
|
meta.lastExtractionAt = new Date().toISOString();
|
|
13323
13495
|
await storage.saveMeta(meta);
|
|
13324
13496
|
}
|
|
13497
|
+
// Correction-only turns that meet char/user-turn thresholds but yield
|
|
13498
|
+
// zero facts still need passive capture (review: "empty extraction skips
|
|
13499
|
+
// capture"). selfNamespace/principal already resolved above.
|
|
13500
|
+
await this.maybeCapturePassiveCorrections(normalizedTurns as BufferTurn[], { sessionKey, principal, namespace: selfNamespace, bufferKey, isLiveSession: clearBufferAfterExtraction });
|
|
13325
13501
|
await clearBuffer();
|
|
13326
|
-
return {
|
|
13327
|
-
status: "skipped",
|
|
13328
|
-
reason: "empty_extraction_result",
|
|
13329
|
-
persistedCount: 0,
|
|
13330
|
-
durableOutputCount: 0,
|
|
13331
|
-
};
|
|
13502
|
+
return { status: "skipped", reason: "empty_extraction_result", persistedCount: 0, durableOutputCount: 0 };
|
|
13332
13503
|
}
|
|
13333
13504
|
|
|
13334
13505
|
let threadIdForExtraction: string | null = null;
|
|
@@ -13445,6 +13616,19 @@ export class Orchestrator {
|
|
|
13445
13616
|
|
|
13446
13617
|
await clearBuffer({ ignoreAbort: true });
|
|
13447
13618
|
|
|
13619
|
+
// Passive correction capture (issue #1581) — detect corrections expressed
|
|
13620
|
+
// passively in the extracted turns and route to the Correction Contract.
|
|
13621
|
+
// Runs AFTER persistence + buffer clear so a capture failure never blocks
|
|
13622
|
+
// the extraction return. `clearBufferAfterExtraction` gates live-session
|
|
13623
|
+
// auto-apply (replay/import → queue-only).
|
|
13624
|
+
await this.maybeCapturePassiveCorrections(normalizedTurns as BufferTurn[], {
|
|
13625
|
+
sessionKey,
|
|
13626
|
+
principal,
|
|
13627
|
+
namespace: selfNamespace,
|
|
13628
|
+
bufferKey,
|
|
13629
|
+
isLiveSession: clearBufferAfterExtraction,
|
|
13630
|
+
});
|
|
13631
|
+
|
|
13448
13632
|
// Build memory box from this extraction (v8.0 Phase 2A)
|
|
13449
13633
|
// Topics are derived from the current extraction's facts and entities only —
|
|
13450
13634
|
// not from readAllMemories() — so box topics accurately reflect the current
|
package/src/types.ts
CHANGED
|
@@ -862,6 +862,29 @@ export interface PluginConfig {
|
|
|
862
862
|
* `24`. Parsed from `correction.planTtlHours` / `correctionPlanTtlHours`.
|
|
863
863
|
*/
|
|
864
864
|
correctionPlanTtlHours: number;
|
|
865
|
+
/**
|
|
866
|
+
* Passive correction capture (issue #1581) — detects corrections expressed
|
|
867
|
+
* passively in conversation turns during extraction and routes them to the
|
|
868
|
+
* Correction Contract (#1580). `"off"` disables detection entirely; `"queue"`
|
|
869
|
+
* plans corrections for human review (conservative); `"auto"` applies
|
|
870
|
+
* immediately when all safety guards pass, otherwise falls back to queue.
|
|
871
|
+
* Default `"off"` — operators opt in (rule 48). Parsed from
|
|
872
|
+
* `correctionCapture.mode` / `correctionCaptureMode`.
|
|
873
|
+
*/
|
|
874
|
+
correctionCaptureMode: "off" | "queue" | "auto";
|
|
875
|
+
/**
|
|
876
|
+
* Minimum planner confidence for auto-apply (issue #1581). Plans below this
|
|
877
|
+
* floor are queued even in `"auto"` mode. Default `0.85`. Parsed from
|
|
878
|
+
* `correctionCapture.confidenceFloor` / `correctionCaptureConfidenceFloor`.
|
|
879
|
+
*/
|
|
880
|
+
correctionCaptureConfidenceFloor: number;
|
|
881
|
+
/**
|
|
882
|
+
* Maximum affected memories for auto-apply (issue #1581). Plans touching more
|
|
883
|
+
* memories than this are queued even in `"auto"` mode — a blast-radius cap.
|
|
884
|
+
* Default `2`. Parsed from `correctionCapture.autoApplyMaxAffected` /
|
|
885
|
+
* `correctionCaptureAutoApplyMaxAffected`.
|
|
886
|
+
*/
|
|
887
|
+
correctionCaptureAutoApplyMaxAffected: number;
|
|
865
888
|
// Tombstones — non-resurrection invariant (issue #1579).
|
|
866
889
|
/**
|
|
867
890
|
* Master gate for the tombstone non-resurrection invariant. When `true`
|
|
@@ -2178,6 +2201,19 @@ export interface BriefingResult {
|
|
|
2178
2201
|
* Allows callers to distinguish "no events today" from "source unavailable".
|
|
2179
2202
|
*/
|
|
2180
2203
|
calendarSourceErrors?: BriefingCalendarSourceError[];
|
|
2204
|
+
/**
|
|
2205
|
+
* Auto-applied passive corrections drained from the notification queue at
|
|
2206
|
+
* briefing time (issue #1581). Each carries a one-line summary and the undo
|
|
2207
|
+
* command. Drained exactly once — the queue file is cleared on read, so a
|
|
2208
|
+
* notification appears in at most one briefing. Absent when the correction
|
|
2209
|
+
* capture feature is off or no corrections were auto-applied.
|
|
2210
|
+
*/
|
|
2211
|
+
correctionNotifications?: ReadonlyArray<{
|
|
2212
|
+
planId: string;
|
|
2213
|
+
summary: string;
|
|
2214
|
+
undoCommand: string;
|
|
2215
|
+
createdAt: string;
|
|
2216
|
+
}>;
|
|
2181
2217
|
}
|
|
2182
2218
|
|
|
2183
2219
|
/**
|
package/dist/chunk-2KF4HDG2.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
// src/procedural/reinforcement-core.ts
|
|
2
|
-
function clusterByKey(items, keyFn) {
|
|
3
|
-
const clusters = /* @__PURE__ */ new Map();
|
|
4
|
-
for (const item of items) {
|
|
5
|
-
const key = keyFn(item);
|
|
6
|
-
if (typeof key !== "string") {
|
|
7
|
-
throw new TypeError(
|
|
8
|
-
`clusterByKey: keyFn must return a string, got ${key === null ? "null" : typeof key}`
|
|
9
|
-
);
|
|
10
|
-
}
|
|
11
|
-
const existing = clusters.get(key);
|
|
12
|
-
if (existing) {
|
|
13
|
-
existing.push(item);
|
|
14
|
-
} else {
|
|
15
|
-
clusters.set(key, [item]);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return clusters;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export {
|
|
22
|
-
clusterByKey
|
|
23
|
-
};
|
|
24
|
-
//# sourceMappingURL=chunk-2KF4HDG2.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/procedural/reinforcement-core.ts"],"sourcesContent":["/**\n * Generic reinforcement-core primitives extracted from `procedure-miner.ts`\n * (issue #687 PR 1/4). Procedure-specific scoring (success rate, step\n * normalization) intentionally stays in the miner — this module only\n * exposes category-agnostic clustering and cluster summarization helpers\n * so future PRs can run reinforcement across non-procedural categories.\n *\n * Pure refactor — no behavior change.\n */\n\n/**\n * Group `items` into clusters keyed by `keyFn(item)`.\n *\n * - Preserves the original input order within each cluster's array.\n * - The returned `Map` insertion order matches first-seen key order, so\n * downstream iteration is deterministic for a given input.\n * - Throws `TypeError` if `keyFn` returns a non-string (e.g. `undefined`,\n * `null`, or a number). Callers must produce a stable string key.\n */\nexport function clusterByKey<T>(items: readonly T[], keyFn: (item: T) => string): Map<string, T[]> {\n const clusters = new Map<string, T[]>();\n for (const item of items) {\n const key = keyFn(item);\n if (typeof key !== \"string\") {\n throw new TypeError(\n `clusterByKey: keyFn must return a string, got ${key === null ? \"null\" : typeof key}`,\n );\n }\n const existing = clusters.get(key);\n if (existing) {\n existing.push(item);\n } else {\n clusters.set(key, [item]);\n }\n }\n return clusters;\n}\n\nexport interface ClusterSummary {\n /** Number of items in the cluster. */\n count: number;\n /** Earliest timestamp seen in the cluster (string min via `localeCompare`). */\n firstSeen: string;\n /** Latest timestamp seen in the cluster (string max via `localeCompare`). */\n lastSeen: string;\n}\n\n/**\n * Summarize a cluster by counting items and tracking earliest/latest\n * timestamps. Timestamp comparison uses `String#localeCompare`, which is\n * correct for ISO-8601 strings (lexicographic order matches chronological\n * order).\n *\n * - Throws `RangeError` on empty clusters — `firstSeen`/`lastSeen` are not\n * meaningful without at least one item.\n * - When all timestamps are equal, `firstSeen === lastSeen`.\n */\nexport function summarizeCluster<T>(\n cluster: readonly T[],\n extractTimestamp: (item: T) => string,\n): ClusterSummary {\n if (cluster.length === 0) {\n throw new RangeError(\"summarizeCluster: cluster must contain at least one item\");\n }\n let firstSeen = extractTimestamp(cluster[0]);\n let lastSeen = firstSeen;\n for (let i = 1; i < cluster.length; i += 1) {\n const ts = extractTimestamp(cluster[i]);\n if (ts.localeCompare(firstSeen) < 0) firstSeen = ts;\n if (ts.localeCompare(lastSeen) > 0) lastSeen = ts;\n }\n return { count: cluster.length, firstSeen, lastSeen };\n}\n"],"mappings":";AAmBO,SAAS,aAAgB,OAAqB,OAA8C;AACjG,QAAM,WAAW,oBAAI,IAAiB;AACtC,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,MAAM,IAAI;AACtB,QAAI,OAAO,QAAQ,UAAU;AAC3B,YAAM,IAAI;AAAA,QACR,iDAAiD,QAAQ,OAAO,SAAS,OAAO,GAAG;AAAA,MACrF;AAAA,IACF;AACA,UAAM,WAAW,SAAS,IAAI,GAAG;AACjC,QAAI,UAAU;AACZ,eAAS,KAAK,IAAI;AAAA,IACpB,OAAO;AACL,eAAS,IAAI,KAAK,CAAC,IAAI,CAAC;AAAA,IAC1B;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
|