@remnic/core 10.0.65 → 10.0.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-admin-ops-surface.js +16 -16
- package/dist/access-authorization-probe.js +17 -17
- package/dist/access-boundary.js +16 -16
- package/dist/access-cli.js +61 -61
- package/dist/access-extraction-force-flush.js +16 -16
- package/dist/access-http-briefing.js +17 -17
- package/dist/access-http-query.js +18 -18
- package/dist/access-http.js +33 -33
- package/dist/access-identity-continuity-surface.js +16 -16
- package/dist/access-lcm-surface.js +16 -16
- package/dist/access-mcp.js +26 -26
- package/dist/access-namespace-preflight.js +16 -16
- package/dist/access-observe-write-surface.js +16 -16
- package/dist/access-operations-batch.js +17 -17
- package/dist/access-operations.js +24 -24
- package/dist/access-recall-concurrency.js +16 -16
- package/dist/access-recall-diagnostics.js +2 -2
- package/dist/access-recall-response.js +16 -16
- package/dist/access-recall-surface.js +16 -16
- package/dist/access-service.js +16 -16
- package/dist/access-surface-catalog.js +18 -18
- package/dist/active-recall.js +3 -3
- package/dist/briefing.js +3 -3
- package/dist/buffer.js +2 -2
- package/dist/causal-consolidation.js +4 -4
- package/dist/{chunk-KISOMGY2.js → chunk-3RHU5MD7.js} +2 -2
- package/dist/{chunk-3LSTL6EY.js → chunk-4MPAKYZU.js} +2 -2
- package/dist/{chunk-OVL5AD3N.js → chunk-4NV7O76Q.js} +2 -2
- package/dist/{chunk-BH7NVSEC.js → chunk-4SOWMA55.js} +3 -3
- package/dist/{chunk-GROHOWR5.js → chunk-5MGKGEL7.js} +2 -2
- package/dist/{chunk-ZPLQ27MY.js → chunk-5UM4H64E.js} +2 -2
- package/dist/{chunk-2DNFRLLL.js → chunk-5Y6VA6X2.js} +2 -2
- package/dist/{chunk-GRAUQXQB.js → chunk-6WKWL53V.js} +13 -13
- package/dist/{chunk-HOR4RMUM.js → chunk-75DCOS6I.js} +24 -24
- package/dist/{chunk-25QK3LR2.js → chunk-7O2MC42R.js} +2 -2
- package/dist/{chunk-7ETWIBTO.js → chunk-ADYP7HXE.js} +3 -3
- package/dist/{chunk-FUDKGJDN.js → chunk-AVGDYYMA.js} +2 -2
- package/dist/{chunk-ECF627KC.js → chunk-AYJQ644F.js} +2 -2
- package/dist/{chunk-T22FBDG3.js → chunk-B3MWELZ3.js} +2 -2
- package/dist/{chunk-DRTSPRWL.js → chunk-B4DXREWC.js} +2 -2
- package/dist/{chunk-5UEGL5BF.js → chunk-CI3MAAIY.js} +2 -2
- package/dist/{chunk-7JYK7NNY.js → chunk-CTH2CQCB.js} +2 -2
- package/dist/{chunk-UVHXLVFJ.js → chunk-EURPSF4Y.js} +2 -2
- package/dist/{chunk-VPEA63FC.js → chunk-EWJZZDRG.js} +2 -2
- package/dist/{chunk-BOZQAUAJ.js → chunk-EXQJMFRF.js} +2 -2
- package/dist/{chunk-UH6ROXFJ.js → chunk-GGD2YDS6.js} +2 -2
- package/dist/{chunk-5JABRT5G.js → chunk-GHHQLSSY.js} +3 -3
- package/dist/{chunk-N4T5FW6U.js → chunk-GJ4HU6LK.js} +2 -2
- package/dist/{chunk-HRRAOTOQ.js → chunk-H5DIRCZP.js} +12 -12
- package/dist/{chunk-434E4BTO.js → chunk-HH73M65H.js} +3 -3
- package/dist/{chunk-LIGZO7XN.js → chunk-HPB5TF55.js} +2 -2
- package/dist/{chunk-E4QIX2OB.js → chunk-IAGVM7EY.js} +2 -2
- package/dist/{chunk-YJQJRXUI.js → chunk-IG3EZ3TF.js} +2 -2
- package/dist/{chunk-KNMSD2MQ.js → chunk-IVUVQPTQ.js} +2 -2
- package/dist/{chunk-XOFIJGB2.js → chunk-IZBIDPMY.js} +2 -2
- package/dist/{chunk-HFEGRMFG.js → chunk-JLGBJ4AX.js} +7 -7
- package/dist/{chunk-BBHKN2CN.js → chunk-JLMOH5JA.js} +2 -2
- package/dist/{chunk-TPCRDPUY.js → chunk-KZSGBWOJ.js} +2 -2
- package/dist/{chunk-SHHZWSSE.js → chunk-KZZ5EZ7O.js} +2 -2
- package/dist/{chunk-2ZSRACNK.js → chunk-LFYEQK45.js} +682 -549
- package/dist/chunk-LFYEQK45.js.map +1 -0
- package/dist/{chunk-FKGLJJVS.js → chunk-LN4X2NDA.js} +2 -2
- package/dist/{chunk-5ZHFPUBC.js → chunk-MOIJWWNA.js} +8 -8
- package/dist/{chunk-KO224R36.js → chunk-NCZGGGWI.js} +2 -2
- package/dist/{chunk-XVQVF2TK.js → chunk-NHWDTOBN.js} +269 -230
- package/dist/chunk-NHWDTOBN.js.map +1 -0
- package/dist/{chunk-7ZTGMEXF.js → chunk-O5ZINWW3.js} +2 -2
- package/dist/{chunk-WWH7GJ42.js → chunk-OCK4D5PC.js} +2 -2
- package/dist/{chunk-G6L3REL3.js → chunk-OPFVXM2D.js} +2 -2
- package/dist/{chunk-FR7PK7ED.js → chunk-P4TV3TQ2.js} +2 -2
- package/dist/{chunk-P2EM5LKH.js → chunk-PMDOGXA2.js} +2 -2
- package/dist/{chunk-NM2II57L.js → chunk-PRKNAIGZ.js} +2 -1
- package/dist/chunk-PRKNAIGZ.js.map +1 -0
- package/dist/{chunk-MRF5V5CD.js → chunk-QGFR73SN.js} +2 -2
- package/dist/{chunk-6D3IWYNY.js → chunk-R2BIVU2Z.js} +354 -292
- package/dist/chunk-R2BIVU2Z.js.map +1 -0
- package/dist/{chunk-HG3CG557.js → chunk-RLVI2M5Q.js} +2 -2
- package/dist/{chunk-HHL4MX3W.js → chunk-SXTVZ6JL.js} +2 -2
- package/dist/{chunk-CLSKGTAT.js → chunk-TECK5IVY.js} +2 -2
- package/dist/{chunk-SNS3DWG6.js → chunk-TVE7W67N.js} +2 -2
- package/dist/{chunk-KYSSUY66.js → chunk-U2CAGMUD.js} +2 -2
- package/dist/{chunk-XLCEFUAU.js → chunk-UVVFPCPX.js} +2 -2
- package/dist/{chunk-KQJUEQ2E.js → chunk-UW6LBFYN.js} +5 -5
- package/dist/{chunk-SEA56G6S.js → chunk-V4XE263I.js} +1 -1
- package/dist/chunk-V4XE263I.js.map +1 -0
- package/dist/{chunk-JL5HXL25.js → chunk-V6SBA5O7.js} +3 -3
- package/dist/{chunk-R7WYAXPO.js → chunk-VHSQU3RO.js} +81 -42
- package/dist/chunk-VHSQU3RO.js.map +1 -0
- package/dist/{chunk-B7VD36TI.js → chunk-WHROVQ5Q.js} +3 -3
- package/dist/{chunk-LDHR465K.js → chunk-Y3XPSGNF.js} +2 -2
- package/dist/{chunk-JPY3RMG2.js → chunk-ZORS5BG5.js} +4 -4
- package/dist/{chunk-KXY4HW2Y.js → chunk-ZXF3O7P4.js} +2 -2
- package/dist/cli.js +47 -47
- package/dist/coding/export-okf-codegraph.js +2 -2
- package/dist/compounding/engine.js +4 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -3
- package/dist/connectors/codex-materialize-runner.js +3 -3
- package/dist/connectors/index.js +3 -3
- package/dist/convergence-refresh.js +5 -5
- package/dist/corpus-watermark.js +5 -5
- package/dist/entity-retrieval.js +3 -3
- package/dist/external-wiki-access.js +17 -17
- package/dist/extraction.js +6 -6
- package/dist/harmonic-retrieval.js +3 -3
- package/dist/index.js +61 -61
- package/dist/location/index.js +5 -5
- package/dist/maintenance/memory-governance.js +3 -3
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
- package/dist/maintenance/rebuild-memory-projection-runner.js +5 -5
- package/dist/maintenance/rebuild-memory-projection.js +4 -4
- package/dist/memory-browse-operations.js +17 -17
- package/dist/namespaces/migrate.js +4 -4
- package/dist/namespaces/storage.js +3 -3
- package/dist/operator-doctor-corpus.js +6 -6
- package/dist/operator-toolkit.js +12 -12
- package/dist/orchestration/buffer-drain-runner.js +61 -61
- package/dist/orchestration/consolidation-run.d.ts.map +1 -1
- package/dist/orchestration/extraction-drain.d.ts +4 -4
- package/dist/orchestration/extraction-drain.d.ts.map +1 -1
- package/dist/orchestration/extraction-persist-deps.d.ts +0 -2
- package/dist/orchestration/extraction-persist-deps.d.ts.map +1 -1
- package/dist/orchestration/extraction-persist.d.ts +10 -4
- package/dist/orchestration/extraction-persist.d.ts.map +1 -1
- package/dist/orchestration/extraction-queue-coordinator.d.ts +67 -33
- package/dist/orchestration/extraction-queue-coordinator.d.ts.map +1 -1
- package/dist/orchestration/extraction-run-helpers.d.ts +3 -2
- package/dist/orchestration/extraction-run-helpers.d.ts.map +1 -1
- package/dist/orchestration/extraction-run.d.ts +4 -14
- package/dist/orchestration/extraction-run.d.ts.map +1 -1
- package/dist/orchestration/fact-dedup-window.d.ts +49 -0
- package/dist/orchestration/fact-dedup-window.d.ts.map +1 -0
- package/dist/orchestration/maintenance.js +13 -13
- package/dist/orchestration/provider-breaker.d.ts +58 -0
- package/dist/orchestration/provider-breaker.d.ts.map +1 -0
- package/dist/orchestrator.d.ts +2 -17
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +61 -61
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-navigate-access.js +2 -2
- package/dist/recall-navigate-disclosure.js +2 -2
- package/dist/recall-navigate.js +2 -2
- package/dist/recall-navigation-operations.js +17 -17
- package/dist/recall-navigation.js +16 -16
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.js +2 -2
- package/dist/resume-bundles.js +4 -4
- package/dist/semantic-consolidation.js +4 -4
- package/dist/semantic-rule-promotion.js +3 -3
- package/dist/semantic-rule-verifier.js +3 -3
- package/dist/source-agent-qualifier.js +5 -5
- package/dist/standup/build.js +3 -3
- package/dist/storage/profile-mutation.d.ts +25 -0
- package/dist/storage/profile-mutation.d.ts.map +1 -0
- package/dist/storage.d.ts +4 -6
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +2 -2
- package/dist/support-passport/index.js +19 -19
- package/dist/threading.d.ts +21 -4
- package/dist/threading.d.ts.map +1 -1
- package/dist/threading.js +1 -1
- package/dist/transfer/export-okf.js +3 -3
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/verified-recall.js +3 -3
- package/dist/who-knows-cli.js +4 -4
- package/dist/who-knows.js +3 -3
- package/package.json +2 -2
- package/src/access-observe-replay-durability.test.ts +1 -1
- package/src/buffer-drain-handover.test.ts +3 -3
- package/src/buffer-drop-extraction-chunk.test.ts +0 -1
- package/src/config.test.ts +12 -0
- package/src/config.ts +2 -0
- package/src/connector-provenance-lifecycle.test.ts +5 -8
- package/src/fact-dedup-window.test.ts +116 -0
- package/src/faithfulness-graph-guard.test.ts +11 -6
- package/src/harmonic-construction.test.ts +16 -10
- package/src/orchestration/consolidation-profile-race.test.ts +178 -0
- package/src/orchestration/consolidation-run.ts +19 -7
- package/src/orchestration/extraction-drain.ts +10 -3
- package/src/orchestration/extraction-persist-deps.ts +0 -2
- package/src/orchestration/extraction-persist.ts +159 -148
- package/src/orchestration/extraction-queue-coordinator.ts +167 -56
- package/src/orchestration/extraction-run-helpers.ts +5 -4
- package/src/orchestration/extraction-run.test.ts +1 -2
- package/src/orchestration/extraction-run.ts +56 -99
- package/src/orchestration/fact-dedup-window.ts +122 -0
- package/src/orchestration/provider-breaker.test.ts +89 -0
- package/src/orchestration/provider-breaker.ts +158 -0
- package/src/orchestration/turn-ingestion.ts +5 -5
- package/src/orchestrator-extraction-queue.test.ts +179 -8
- package/src/orchestrator.ts +7 -23
- package/src/storage/profile-mutation.ts +119 -0
- package/src/storage-append-profile.test.ts +114 -0
- package/src/storage.ts +17 -48
- package/src/testing/orchestrator-lite.ts +1 -1
- package/src/threading.test.ts +153 -0
- package/src/threading.ts +95 -45
- package/src/types.ts +2 -0
- package/dist/chunk-2ZSRACNK.js.map +0 -1
- package/dist/chunk-6D3IWYNY.js.map +0 -1
- package/dist/chunk-NM2II57L.js.map +0 -1
- package/dist/chunk-R7WYAXPO.js.map +0 -1
- package/dist/chunk-SEA56G6S.js.map +0 -1
- package/dist/chunk-XVQVF2TK.js.map +0 -1
- /package/dist/{chunk-KISOMGY2.js.map → chunk-3RHU5MD7.js.map} +0 -0
- /package/dist/{chunk-3LSTL6EY.js.map → chunk-4MPAKYZU.js.map} +0 -0
- /package/dist/{chunk-OVL5AD3N.js.map → chunk-4NV7O76Q.js.map} +0 -0
- /package/dist/{chunk-BH7NVSEC.js.map → chunk-4SOWMA55.js.map} +0 -0
- /package/dist/{chunk-GROHOWR5.js.map → chunk-5MGKGEL7.js.map} +0 -0
- /package/dist/{chunk-ZPLQ27MY.js.map → chunk-5UM4H64E.js.map} +0 -0
- /package/dist/{chunk-2DNFRLLL.js.map → chunk-5Y6VA6X2.js.map} +0 -0
- /package/dist/{chunk-GRAUQXQB.js.map → chunk-6WKWL53V.js.map} +0 -0
- /package/dist/{chunk-HOR4RMUM.js.map → chunk-75DCOS6I.js.map} +0 -0
- /package/dist/{chunk-25QK3LR2.js.map → chunk-7O2MC42R.js.map} +0 -0
- /package/dist/{chunk-7ETWIBTO.js.map → chunk-ADYP7HXE.js.map} +0 -0
- /package/dist/{chunk-FUDKGJDN.js.map → chunk-AVGDYYMA.js.map} +0 -0
- /package/dist/{chunk-ECF627KC.js.map → chunk-AYJQ644F.js.map} +0 -0
- /package/dist/{chunk-T22FBDG3.js.map → chunk-B3MWELZ3.js.map} +0 -0
- /package/dist/{chunk-DRTSPRWL.js.map → chunk-B4DXREWC.js.map} +0 -0
- /package/dist/{chunk-5UEGL5BF.js.map → chunk-CI3MAAIY.js.map} +0 -0
- /package/dist/{chunk-7JYK7NNY.js.map → chunk-CTH2CQCB.js.map} +0 -0
- /package/dist/{chunk-UVHXLVFJ.js.map → chunk-EURPSF4Y.js.map} +0 -0
- /package/dist/{chunk-VPEA63FC.js.map → chunk-EWJZZDRG.js.map} +0 -0
- /package/dist/{chunk-BOZQAUAJ.js.map → chunk-EXQJMFRF.js.map} +0 -0
- /package/dist/{chunk-UH6ROXFJ.js.map → chunk-GGD2YDS6.js.map} +0 -0
- /package/dist/{chunk-5JABRT5G.js.map → chunk-GHHQLSSY.js.map} +0 -0
- /package/dist/{chunk-N4T5FW6U.js.map → chunk-GJ4HU6LK.js.map} +0 -0
- /package/dist/{chunk-HRRAOTOQ.js.map → chunk-H5DIRCZP.js.map} +0 -0
- /package/dist/{chunk-434E4BTO.js.map → chunk-HH73M65H.js.map} +0 -0
- /package/dist/{chunk-LIGZO7XN.js.map → chunk-HPB5TF55.js.map} +0 -0
- /package/dist/{chunk-E4QIX2OB.js.map → chunk-IAGVM7EY.js.map} +0 -0
- /package/dist/{chunk-YJQJRXUI.js.map → chunk-IG3EZ3TF.js.map} +0 -0
- /package/dist/{chunk-KNMSD2MQ.js.map → chunk-IVUVQPTQ.js.map} +0 -0
- /package/dist/{chunk-XOFIJGB2.js.map → chunk-IZBIDPMY.js.map} +0 -0
- /package/dist/{chunk-HFEGRMFG.js.map → chunk-JLGBJ4AX.js.map} +0 -0
- /package/dist/{chunk-BBHKN2CN.js.map → chunk-JLMOH5JA.js.map} +0 -0
- /package/dist/{chunk-TPCRDPUY.js.map → chunk-KZSGBWOJ.js.map} +0 -0
- /package/dist/{chunk-SHHZWSSE.js.map → chunk-KZZ5EZ7O.js.map} +0 -0
- /package/dist/{chunk-FKGLJJVS.js.map → chunk-LN4X2NDA.js.map} +0 -0
- /package/dist/{chunk-5ZHFPUBC.js.map → chunk-MOIJWWNA.js.map} +0 -0
- /package/dist/{chunk-KO224R36.js.map → chunk-NCZGGGWI.js.map} +0 -0
- /package/dist/{chunk-7ZTGMEXF.js.map → chunk-O5ZINWW3.js.map} +0 -0
- /package/dist/{chunk-WWH7GJ42.js.map → chunk-OCK4D5PC.js.map} +0 -0
- /package/dist/{chunk-G6L3REL3.js.map → chunk-OPFVXM2D.js.map} +0 -0
- /package/dist/{chunk-FR7PK7ED.js.map → chunk-P4TV3TQ2.js.map} +0 -0
- /package/dist/{chunk-P2EM5LKH.js.map → chunk-PMDOGXA2.js.map} +0 -0
- /package/dist/{chunk-MRF5V5CD.js.map → chunk-QGFR73SN.js.map} +0 -0
- /package/dist/{chunk-HG3CG557.js.map → chunk-RLVI2M5Q.js.map} +0 -0
- /package/dist/{chunk-HHL4MX3W.js.map → chunk-SXTVZ6JL.js.map} +0 -0
- /package/dist/{chunk-CLSKGTAT.js.map → chunk-TECK5IVY.js.map} +0 -0
- /package/dist/{chunk-SNS3DWG6.js.map → chunk-TVE7W67N.js.map} +0 -0
- /package/dist/{chunk-KYSSUY66.js.map → chunk-U2CAGMUD.js.map} +0 -0
- /package/dist/{chunk-XLCEFUAU.js.map → chunk-UVVFPCPX.js.map} +0 -0
- /package/dist/{chunk-KQJUEQ2E.js.map → chunk-UW6LBFYN.js.map} +0 -0
- /package/dist/{chunk-JL5HXL25.js.map → chunk-V6SBA5O7.js.map} +0 -0
- /package/dist/{chunk-B7VD36TI.js.map → chunk-WHROVQ5Q.js.map} +0 -0
- /package/dist/{chunk-LDHR465K.js.map → chunk-Y3XPSGNF.js.map} +0 -0
- /package/dist/{chunk-JPY3RMG2.js.map → chunk-ZORS5BG5.js.map} +0 -0
- /package/dist/{chunk-KXY4HW2Y.js.map → chunk-ZXF3O7P4.js.map} +0 -0
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
ActivityStore,
|
|
15
15
|
MaintenanceScheduler
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-JLGBJ4AX.js";
|
|
17
17
|
import {
|
|
18
18
|
runPeerProfileReasoner
|
|
19
19
|
} from "./chunk-I74SUMNI.js";
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
import {
|
|
33
33
|
CompoundingEngine,
|
|
34
34
|
defaultTierMigrationCycleBudget
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-GHHQLSSY.js";
|
|
36
36
|
import {
|
|
37
37
|
SharedContextManager
|
|
38
38
|
} from "./chunk-5KBIOI4G.js";
|
|
@@ -175,7 +175,7 @@ import {
|
|
|
175
175
|
} from "./chunk-VA3GNAWQ.js";
|
|
176
176
|
import {
|
|
177
177
|
ExtractionEngine
|
|
178
|
-
} from "./chunk-
|
|
178
|
+
} from "./chunk-LN4X2NDA.js";
|
|
179
179
|
import {
|
|
180
180
|
parseMemoryActionEligibilityContext
|
|
181
181
|
} from "./chunk-JHU4EYDV.js";
|
|
@@ -210,7 +210,7 @@ import {
|
|
|
210
210
|
buildEntityRecallSection,
|
|
211
211
|
entityRecentTranscriptLookbackHours,
|
|
212
212
|
readRecentEntityTranscriptEntries
|
|
213
|
-
} from "./chunk-
|
|
213
|
+
} from "./chunk-NCZGGGWI.js";
|
|
214
214
|
import {
|
|
215
215
|
planEpisodeWindowsWithFallback
|
|
216
216
|
} from "./chunk-T3GIETKV.js";
|
|
@@ -225,7 +225,7 @@ import {
|
|
|
225
225
|
} from "./chunk-7G5NTS7F.js";
|
|
226
226
|
import {
|
|
227
227
|
refreshConvergedNamespaces
|
|
228
|
-
} from "./chunk-
|
|
228
|
+
} from "./chunk-OCK4D5PC.js";
|
|
229
229
|
import {
|
|
230
230
|
builtInConnectorPackageSpecifier,
|
|
231
231
|
ensureBuiltInWearableConnectors,
|
|
@@ -234,7 +234,7 @@ import {
|
|
|
234
234
|
runTimelinePublishCli,
|
|
235
235
|
screenCandidateFact,
|
|
236
236
|
summarizeVaultPublish
|
|
237
|
-
} from "./chunk-
|
|
237
|
+
} from "./chunk-75DCOS6I.js";
|
|
238
238
|
import {
|
|
239
239
|
normalizeReplaySessionKey
|
|
240
240
|
} from "./chunk-AJVLDJU6.js";
|
|
@@ -244,14 +244,14 @@ import {
|
|
|
244
244
|
import {
|
|
245
245
|
compareVerifiedEpisodeResults,
|
|
246
246
|
searchVerifiedEpisodes
|
|
247
|
-
} from "./chunk-
|
|
247
|
+
} from "./chunk-KZZ5EZ7O.js";
|
|
248
248
|
import {
|
|
249
249
|
ThreadingManager
|
|
250
|
-
} from "./chunk-
|
|
250
|
+
} from "./chunk-VHSQU3RO.js";
|
|
251
251
|
import {
|
|
252
252
|
compareVerifiedSemanticRuleResults,
|
|
253
253
|
searchVerifiedSemanticRules
|
|
254
|
-
} from "./chunk-
|
|
254
|
+
} from "./chunk-TVE7W67N.js";
|
|
255
255
|
import {
|
|
256
256
|
searchWorkProductLedgerEntries
|
|
257
257
|
} from "./chunk-B2NXOVZN.js";
|
|
@@ -264,10 +264,10 @@ import {
|
|
|
264
264
|
import {
|
|
265
265
|
runNamespaceMaintenanceFanout,
|
|
266
266
|
summarizeNamespaceMaintenanceHealth
|
|
267
|
-
} from "./chunk-
|
|
267
|
+
} from "./chunk-MOIJWWNA.js";
|
|
268
268
|
import {
|
|
269
269
|
planNamespaceMaintenance
|
|
270
|
-
} from "./chunk-
|
|
270
|
+
} from "./chunk-HH73M65H.js";
|
|
271
271
|
import {
|
|
272
272
|
isAboveImportanceThreshold,
|
|
273
273
|
scoreImportance
|
|
@@ -296,10 +296,10 @@ import {
|
|
|
296
296
|
materializeAfterSemanticConsolidation,
|
|
297
297
|
parseConsolidationResponse,
|
|
298
298
|
parseOperatorAwareConsolidationResponse
|
|
299
|
-
} from "./chunk-
|
|
299
|
+
} from "./chunk-AYJQ644F.js";
|
|
300
300
|
import {
|
|
301
301
|
SmartBuffer
|
|
302
|
-
} from "./chunk-
|
|
302
|
+
} from "./chunk-4MPAKYZU.js";
|
|
303
303
|
import {
|
|
304
304
|
semanticChunkContent
|
|
305
305
|
} from "./chunk-2GBFKHBZ.js";
|
|
@@ -335,7 +335,7 @@ import {
|
|
|
335
335
|
embeddingsFromCosineHits,
|
|
336
336
|
normalizeConnectorScope,
|
|
337
337
|
runSeedGraduationPass
|
|
338
|
-
} from "./chunk-
|
|
338
|
+
} from "./chunk-PRKNAIGZ.js";
|
|
339
339
|
import {
|
|
340
340
|
compileCorrectionRule,
|
|
341
341
|
correctionsFilePath,
|
|
@@ -373,7 +373,7 @@ import {
|
|
|
373
373
|
} from "./chunk-QW27DOHG.js";
|
|
374
374
|
import {
|
|
375
375
|
MeetingsInputError
|
|
376
|
-
} from "./chunk-
|
|
376
|
+
} from "./chunk-H5DIRCZP.js";
|
|
377
377
|
import {
|
|
378
378
|
WearablesInputError,
|
|
379
379
|
describeErrorForOperator
|
|
@@ -391,7 +391,7 @@ import {
|
|
|
391
391
|
} from "./chunk-W7K5BP3M.js";
|
|
392
392
|
import {
|
|
393
393
|
NamespaceCatalog
|
|
394
|
-
} from "./chunk-
|
|
394
|
+
} from "./chunk-CI3MAAIY.js";
|
|
395
395
|
import {
|
|
396
396
|
RecallResultFormatter,
|
|
397
397
|
SessionContextCoordinator,
|
|
@@ -400,7 +400,7 @@ import {
|
|
|
400
400
|
detectPassiveCorrections,
|
|
401
401
|
renderSessionExperiencePreview,
|
|
402
402
|
scoreSessionExperienceForPrompt
|
|
403
|
-
} from "./chunk-
|
|
403
|
+
} from "./chunk-6WKWL53V.js";
|
|
404
404
|
import {
|
|
405
405
|
importCapsule
|
|
406
406
|
} from "./chunk-QDZWQBLU.js";
|
|
@@ -429,7 +429,7 @@ import {
|
|
|
429
429
|
} from "./chunk-MUHGYV2V.js";
|
|
430
430
|
import {
|
|
431
431
|
buildXraySnapshot
|
|
432
|
-
} from "./chunk-
|
|
432
|
+
} from "./chunk-7O2MC42R.js";
|
|
433
433
|
import {
|
|
434
434
|
objectiveStateStoreOverrideForNamespace,
|
|
435
435
|
searchObjectiveStateSnapshots
|
|
@@ -443,7 +443,7 @@ import {
|
|
|
443
443
|
} from "./chunk-BJLCV2P3.js";
|
|
444
444
|
import {
|
|
445
445
|
searchHarmonicRetrieval
|
|
446
|
-
} from "./chunk-
|
|
446
|
+
} from "./chunk-EXQJMFRF.js";
|
|
447
447
|
import {
|
|
448
448
|
ProfilingCollector
|
|
449
449
|
} from "./chunk-DOWACHYO.js";
|
|
@@ -466,7 +466,7 @@ import {
|
|
|
466
466
|
} from "./chunk-NVKO5YKP.js";
|
|
467
467
|
import {
|
|
468
468
|
NamespaceStorageRouter
|
|
469
|
-
} from "./chunk-
|
|
469
|
+
} from "./chunk-5UM4H64E.js";
|
|
470
470
|
import {
|
|
471
471
|
pruneOrphanCueAnchors
|
|
472
472
|
} from "./chunk-LXATZLSC.js";
|
|
@@ -480,7 +480,7 @@ import {
|
|
|
480
480
|
ExtractionDeadlineError,
|
|
481
481
|
ExtractionRunCoordinator,
|
|
482
482
|
classifyExtractionOrigin
|
|
483
|
-
} from "./chunk-
|
|
483
|
+
} from "./chunk-R2BIVU2Z.js";
|
|
484
484
|
import {
|
|
485
485
|
ARTIFACT_STATUS_CACHE_TTL_MS,
|
|
486
486
|
BulkImportBatchPartialFailureError,
|
|
@@ -532,7 +532,7 @@ import {
|
|
|
532
532
|
} from "./chunk-74AY3S7U.js";
|
|
533
533
|
import {
|
|
534
534
|
buildChainFollowupGenerator
|
|
535
|
-
} from "./chunk-
|
|
535
|
+
} from "./chunk-IAGVM7EY.js";
|
|
536
536
|
import {
|
|
537
537
|
decideLifecycleTransition,
|
|
538
538
|
resolveLifecycleState
|
|
@@ -577,7 +577,7 @@ import {
|
|
|
577
577
|
reconstructFusionInputs,
|
|
578
578
|
selfDeps,
|
|
579
579
|
serializeFusionDay
|
|
580
|
-
} from "./chunk-
|
|
580
|
+
} from "./chunk-NHWDTOBN.js";
|
|
581
581
|
import {
|
|
582
582
|
bodyIsEscaped,
|
|
583
583
|
decodeTranscriptBody,
|
|
@@ -707,7 +707,7 @@ import {
|
|
|
707
707
|
} from "./chunk-PJKTFXE2.js";
|
|
708
708
|
import {
|
|
709
709
|
confidenceTier
|
|
710
|
-
} from "./chunk-
|
|
710
|
+
} from "./chunk-V4XE263I.js";
|
|
711
711
|
import {
|
|
712
712
|
extractJsonCandidates
|
|
713
713
|
} from "./chunk-YBA52OKG.js";
|
|
@@ -796,6 +796,7 @@ import {
|
|
|
796
796
|
assertRealpathInsideRoot
|
|
797
797
|
} from "./chunk-GCGJW34D.js";
|
|
798
798
|
import {
|
|
799
|
+
serializeMutations,
|
|
799
800
|
withHeldFileLock
|
|
800
801
|
} from "./chunk-EBV6VXKF.js";
|
|
801
802
|
import {
|
|
@@ -890,7 +891,7 @@ import {
|
|
|
890
891
|
} from "./chunk-3WCASNQZ.js";
|
|
891
892
|
|
|
892
893
|
// src/orchestrator.ts
|
|
893
|
-
import
|
|
894
|
+
import path24 from "path";
|
|
894
895
|
import { createHash as createHash10 } from "crypto";
|
|
895
896
|
|
|
896
897
|
// src/orchestration/buffer-swap.ts
|
|
@@ -1077,35 +1078,51 @@ var TierMigrationCoordinator = class {
|
|
|
1077
1078
|
|
|
1078
1079
|
// src/orchestration/extraction-queue-coordinator.ts
|
|
1079
1080
|
var ExtractionQueueCoordinator = class {
|
|
1081
|
+
/** Maximum tasks that run at the same time (config `extractionQueueConcurrency`). */
|
|
1082
|
+
concurrency;
|
|
1080
1083
|
/**
|
|
1081
|
-
* Background
|
|
1082
|
-
*
|
|
1084
|
+
* Background queue for extractions (agent_end optimization). Queue stores
|
|
1085
|
+
* tasks that resolve when extraction should run.
|
|
1083
1086
|
*/
|
|
1084
1087
|
queue = [];
|
|
1085
|
-
/** Whether the
|
|
1088
|
+
/** Whether the drain loop is currently running. */
|
|
1086
1089
|
processing = false;
|
|
1087
1090
|
accepting = true;
|
|
1088
|
-
|
|
1091
|
+
/** Buffer keys with a task currently running (per-key exclusion). */
|
|
1092
|
+
activeKeys = /* @__PURE__ */ new Set();
|
|
1093
|
+
/** Preempt slots of the currently running tasks, keyed by slot identity. */
|
|
1094
|
+
preemptSlots = /* @__PURE__ */ new Map();
|
|
1095
|
+
preemptSeq = 0;
|
|
1096
|
+
/** Resolves the processor's park while a new task arrives mid-drain. */
|
|
1097
|
+
wake;
|
|
1098
|
+
constructor(concurrency = 1) {
|
|
1099
|
+
this.concurrency = Number.isInteger(concurrency) && concurrency >= 1 ? concurrency : 1;
|
|
1100
|
+
}
|
|
1089
1101
|
/** Current queue depth (idle-wait + test seam). */
|
|
1090
1102
|
get length() {
|
|
1091
1103
|
return this.queue.length;
|
|
1092
1104
|
}
|
|
1093
|
-
/** Whether the
|
|
1105
|
+
/** Whether the drain loop is currently running (idle-wait + test seam). */
|
|
1094
1106
|
get isProcessing() {
|
|
1095
1107
|
return this.processing;
|
|
1096
1108
|
}
|
|
1109
|
+
/** How many tasks may run at once (test seam + diagnostics). */
|
|
1110
|
+
get maxConcurrency() {
|
|
1111
|
+
return this.concurrency;
|
|
1112
|
+
}
|
|
1097
1113
|
/**
|
|
1098
|
-
* Enqueue a task and start the
|
|
1114
|
+
* Enqueue a task and start the processor when capacity is free. This is
|
|
1099
1115
|
* the production entry point — the orchestrator's `queueBufferedExtraction`
|
|
1100
|
-
* builds each task closure and hands it here.
|
|
1116
|
+
* builds each task closure and hands it here with its buffer key.
|
|
1101
1117
|
*/
|
|
1102
1118
|
enqueue(task, options) {
|
|
1103
1119
|
if (!this.accepting) return false;
|
|
1120
|
+
const entry = { run: task, key: options?.key };
|
|
1104
1121
|
if (options?.front) {
|
|
1105
|
-
this.preemptRunning();
|
|
1106
|
-
this.queue.unshift(
|
|
1122
|
+
this.preemptRunning(options.key);
|
|
1123
|
+
this.queue.unshift(entry);
|
|
1107
1124
|
} else {
|
|
1108
|
-
this.queue.push(
|
|
1125
|
+
this.queue.push(entry);
|
|
1109
1126
|
}
|
|
1110
1127
|
if (!this.processing) {
|
|
1111
1128
|
this.processing = true;
|
|
@@ -1113,27 +1130,28 @@ var ExtractionQueueCoordinator = class {
|
|
|
1113
1130
|
this.logExtractionQueueFailure(err, "processor");
|
|
1114
1131
|
this.processing = false;
|
|
1115
1132
|
});
|
|
1133
|
+
} else {
|
|
1134
|
+
this.wake?.();
|
|
1116
1135
|
}
|
|
1117
1136
|
return true;
|
|
1118
1137
|
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
preemptRunning() {
|
|
1127
|
-
const abort = this.runningPreempt;
|
|
1128
|
-
this.runningPreempt = void 0;
|
|
1138
|
+
preemptRunning(preferredKey) {
|
|
1139
|
+
const armed = Array.from(this.preemptSlots.values()).filter((slot) => slot.armed !== void 0);
|
|
1140
|
+
if (armed.length === 0) return;
|
|
1141
|
+
const preferred = preferredKey !== void 0 ? armed.find((slot) => slot.key === preferredKey) : void 0;
|
|
1142
|
+
const chosen = preferred ?? armed.reduce((a, b) => (b.armed?.seq ?? -1) > (a.armed?.seq ?? -1) ? b : a);
|
|
1143
|
+
const abort = chosen.armed?.abort;
|
|
1144
|
+
chosen.armed = void 0;
|
|
1129
1145
|
abort?.();
|
|
1130
1146
|
}
|
|
1131
|
-
runPreemptable(preemptable, parent, run) {
|
|
1132
|
-
const
|
|
1133
|
-
if (preemptable
|
|
1134
|
-
|
|
1147
|
+
runPreemptable(preempt, preemptable, parent, run) {
|
|
1148
|
+
const preemptController = new AbortController();
|
|
1149
|
+
if (preemptable && preempt) {
|
|
1150
|
+
preempt.arm(() => preemptController.abort(preemptedExtractionError()));
|
|
1151
|
+
}
|
|
1152
|
+
const signal = parent ? AbortSignal.any([parent, preemptController.signal]) : preemptController.signal;
|
|
1135
1153
|
return Promise.resolve(run(signal)).finally(() => {
|
|
1136
|
-
if (preemptable)
|
|
1154
|
+
if (preemptable && preempt) preempt.disarm();
|
|
1137
1155
|
});
|
|
1138
1156
|
}
|
|
1139
1157
|
/** Stop new producers from entering the queue. */
|
|
@@ -1153,28 +1171,75 @@ var ExtractionQueueCoordinator = class {
|
|
|
1153
1171
|
return true;
|
|
1154
1172
|
}
|
|
1155
1173
|
/**
|
|
1156
|
-
* Background
|
|
1157
|
-
*
|
|
1158
|
-
*
|
|
1159
|
-
*
|
|
1160
|
-
* semantics directly.
|
|
1174
|
+
* Background queue processor. Runs up to `concurrency` tasks at a time,
|
|
1175
|
+
* never two tasks with the same entry key. Called automatically when items
|
|
1176
|
+
* are queued via `enqueue`; also exposed for the characterization tests
|
|
1177
|
+
* that push raw tasks and assert drain semantics directly.
|
|
1161
1178
|
*/
|
|
1162
1179
|
async processQueue() {
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1180
|
+
const inFlight = /* @__PURE__ */ new Set();
|
|
1181
|
+
try {
|
|
1182
|
+
while (this.queue.length > 0 || inFlight.size > 0) {
|
|
1183
|
+
while (inFlight.size < this.concurrency) {
|
|
1184
|
+
const entry = this.takeRunnable();
|
|
1185
|
+
if (!entry) break;
|
|
1186
|
+
const running = this.runEntry(entry).finally(() => {
|
|
1187
|
+
inFlight.delete(running);
|
|
1188
|
+
});
|
|
1189
|
+
inFlight.add(running);
|
|
1190
|
+
}
|
|
1191
|
+
if (inFlight.size === 0) break;
|
|
1192
|
+
const { promise: wakePromise, resolve: wake } = Promise.withResolvers();
|
|
1193
|
+
this.wake = wake;
|
|
1166
1194
|
try {
|
|
1167
|
-
await
|
|
1168
|
-
}
|
|
1169
|
-
this.
|
|
1195
|
+
await Promise.race([wakePromise, ...inFlight]);
|
|
1196
|
+
} finally {
|
|
1197
|
+
this.wake = void 0;
|
|
1170
1198
|
}
|
|
1171
1199
|
}
|
|
1200
|
+
} finally {
|
|
1201
|
+
this.processing = false;
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
/** Take the next queue entry whose key is not already running (FIFO within a key). */
|
|
1205
|
+
takeRunnable() {
|
|
1206
|
+
for (let index = 0; index < this.queue.length; index += 1) {
|
|
1207
|
+
const entry = this.queue[index];
|
|
1208
|
+
if (entry.key !== void 0 && this.activeKeys.has(entry.key)) continue;
|
|
1209
|
+
this.queue.splice(index, 1);
|
|
1210
|
+
if (entry.key !== void 0) this.activeKeys.add(entry.key);
|
|
1211
|
+
return entry;
|
|
1212
|
+
}
|
|
1213
|
+
return void 0;
|
|
1214
|
+
}
|
|
1215
|
+
/** Run one entry with its own preempt slot; failures are classified + logged. */
|
|
1216
|
+
async runEntry(entry) {
|
|
1217
|
+
const slot = {};
|
|
1218
|
+
this.preemptSlots.set(slot, { key: entry.key });
|
|
1219
|
+
try {
|
|
1220
|
+
await entry.run(this.createPreemptHandle(slot));
|
|
1221
|
+
} catch (err) {
|
|
1222
|
+
this.logExtractionQueueFailure(err, "task");
|
|
1223
|
+
} finally {
|
|
1224
|
+
this.preemptSlots.delete(slot);
|
|
1225
|
+
if (entry.key !== void 0) this.activeKeys.delete(entry.key);
|
|
1172
1226
|
}
|
|
1173
|
-
|
|
1227
|
+
}
|
|
1228
|
+
createPreemptHandle(slot) {
|
|
1229
|
+
return {
|
|
1230
|
+
arm: (abort) => {
|
|
1231
|
+
const state = this.preemptSlots.get(slot);
|
|
1232
|
+
if (state) state.armed = { abort, seq: this.preemptSeq++ };
|
|
1233
|
+
},
|
|
1234
|
+
disarm: () => {
|
|
1235
|
+
const state = this.preemptSlots.get(slot);
|
|
1236
|
+
if (state) state.armed = void 0;
|
|
1237
|
+
}
|
|
1238
|
+
};
|
|
1174
1239
|
}
|
|
1175
1240
|
/**
|
|
1176
1241
|
* Classify + log a failure from either the per-task catch inside
|
|
1177
|
-
* `
|
|
1242
|
+
* `runEntry` or the outer `processQueue().catch(...)` in
|
|
1178
1243
|
* `enqueue()`. Issue #549: `throwIfRecallAborted`
|
|
1179
1244
|
* (used throughout `runExtraction`) raises an Error whose `name` is
|
|
1180
1245
|
* `"AbortError"`. That path fires when `before_reset` aborts a
|
|
@@ -1227,12 +1292,13 @@ var ExtractionQueueCoordinator = class {
|
|
|
1227
1292
|
* pre-extraction `this.extractionQueue.push(...)` used by the
|
|
1228
1293
|
* characterization tests that drive the drain manually via `processQueue`.
|
|
1229
1294
|
*/
|
|
1230
|
-
pushRaw(task) {
|
|
1231
|
-
this.queue.push(task);
|
|
1295
|
+
pushRaw(task, options) {
|
|
1296
|
+
this.queue.push({ run: task, key: options?.key });
|
|
1297
|
+
this.wake?.();
|
|
1232
1298
|
}
|
|
1233
1299
|
/** Remove + return the front task (test seam for the flush deadline tests). */
|
|
1234
1300
|
shift() {
|
|
1235
|
-
return this.queue.shift();
|
|
1301
|
+
return this.queue.shift()?.run;
|
|
1236
1302
|
}
|
|
1237
1303
|
/**
|
|
1238
1304
|
* Force the processor-busy flag so `enqueue` does not auto-start the
|
|
@@ -2495,7 +2561,7 @@ var RecallRerankCoordinator = class _RecallRerankCoordinator {
|
|
|
2495
2561
|
namespaces,
|
|
2496
2562
|
{
|
|
2497
2563
|
readNamespaceMemories: async (ns) => (await this.getStorage(ns)).readAllMemories(),
|
|
2498
|
-
readMemoryFrontmatter: async (
|
|
2564
|
+
readMemoryFrontmatter: async (path42, preferredNamespace) => {
|
|
2499
2565
|
if (!fallbackReader) {
|
|
2500
2566
|
for (const ns of namespaces) {
|
|
2501
2567
|
try {
|
|
@@ -2507,7 +2573,7 @@ var RecallRerankCoordinator = class _RecallRerankCoordinator {
|
|
|
2507
2573
|
}
|
|
2508
2574
|
if (!fallbackReader) return null;
|
|
2509
2575
|
const memory = await this.readQmdResultMemory(
|
|
2510
|
-
|
|
2576
|
+
path42,
|
|
2511
2577
|
fallbackReader,
|
|
2512
2578
|
namespaces,
|
|
2513
2579
|
preferredNamespace
|
|
@@ -4798,11 +4864,20 @@ var ConsolidationRunCoordinator = class {
|
|
|
4798
4864
|
profileConsolidationTargetLines
|
|
4799
4865
|
);
|
|
4800
4866
|
if (profileResult) {
|
|
4801
|
-
await storage.
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
`profile.md consolidated: removed ${profileResult.removedCount} items \u2014 ${profileResult.summary}`
|
|
4867
|
+
const outcome = await storage.commitConsolidatedProfile(
|
|
4868
|
+
currentProfile,
|
|
4869
|
+
profileResult.consolidatedProfile
|
|
4805
4870
|
);
|
|
4871
|
+
if (outcome === "conflict") {
|
|
4872
|
+
log.info(
|
|
4873
|
+
"profile.md changed during consolidation \u2014 skipping stale rewrite (retries next pass)"
|
|
4874
|
+
);
|
|
4875
|
+
} else {
|
|
4876
|
+
memoryItemMutated = true;
|
|
4877
|
+
log.info(
|
|
4878
|
+
`profile.md consolidated: removed ${profileResult.removedCount} items \u2014 ${profileResult.summary}`
|
|
4879
|
+
);
|
|
4880
|
+
}
|
|
4806
4881
|
}
|
|
4807
4882
|
}
|
|
4808
4883
|
}
|
|
@@ -4895,6 +4970,78 @@ ${texts.map((t, i) => `[${i + 1}] ${t}`).join("\n\n")}`;
|
|
|
4895
4970
|
}
|
|
4896
4971
|
};
|
|
4897
4972
|
|
|
4973
|
+
// src/orchestration/fact-dedup-window.ts
|
|
4974
|
+
import path5 from "path";
|
|
4975
|
+
|
|
4976
|
+
// src/orchestration/extraction-persist-citation.ts
|
|
4977
|
+
function normalizeStoredHashSource(raw, citationEnabled, citationTemplate) {
|
|
4978
|
+
return ContentHashIndex.normalizeContent(
|
|
4979
|
+
sanitizeMemoryContent(
|
|
4980
|
+
citationEnabled && hasCitationForTemplate(raw, citationTemplate) ? stripCitationForTemplate(raw, citationTemplate) : raw
|
|
4981
|
+
).text
|
|
4982
|
+
);
|
|
4983
|
+
}
|
|
4984
|
+
function applyInlineCitation(content, citationEnabled, citationTemplate, citationContextBase) {
|
|
4985
|
+
if (!citationEnabled) return content;
|
|
4986
|
+
if (typeof content !== "string" || content.length === 0) return content;
|
|
4987
|
+
const citationContext = {
|
|
4988
|
+
...citationContextBase,
|
|
4989
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
4990
|
+
};
|
|
4991
|
+
return attachCitation(content, citationContext, citationTemplate);
|
|
4992
|
+
}
|
|
4993
|
+
|
|
4994
|
+
// src/orchestration/fact-dedup-window.ts
|
|
4995
|
+
function matchesActiveConnectorDuplicate(memory, opts) {
|
|
4996
|
+
if (memory.frontmatter.category !== opts.category) return false;
|
|
4997
|
+
if ((memory.frontmatter.status ?? "active") !== "active") return false;
|
|
4998
|
+
if (normalizeStoredHashSource(stripAttributesSuffix(memory.content ?? ""), opts.citationEnabled, opts.citationTemplate) !== ContentHashIndex.normalizeContent(opts.contentHashDedupKey)) return false;
|
|
4999
|
+
return (memory.frontmatter.sourceConnector?.trim() || void 0) === opts.connector;
|
|
5000
|
+
}
|
|
5001
|
+
async function confirmActiveFactDuplicate(probe, storage, opts) {
|
|
5002
|
+
let needsCorpusConfirm;
|
|
5003
|
+
try {
|
|
5004
|
+
if (!await probe.hasContentHashDedup(storage, opts.contentHashDedupKey)) {
|
|
5005
|
+
if (await storage.isFactContentHashAuthoritative()) return false;
|
|
5006
|
+
needsCorpusConfirm = true;
|
|
5007
|
+
} else {
|
|
5008
|
+
needsCorpusConfirm = true;
|
|
5009
|
+
}
|
|
5010
|
+
} catch {
|
|
5011
|
+
needsCorpusConfirm = true;
|
|
5012
|
+
}
|
|
5013
|
+
try {
|
|
5014
|
+
const [hotMems, coldMems] = await Promise.all([
|
|
5015
|
+
storage.readAllMemories(),
|
|
5016
|
+
storage.readAllColdMemories()
|
|
5017
|
+
]);
|
|
5018
|
+
return hotMems.some((m) => matchesActiveConnectorDuplicate(m, opts)) || coldMems.some((m) => matchesActiveConnectorDuplicate(m, opts));
|
|
5019
|
+
} catch (err) {
|
|
5020
|
+
log.warn(
|
|
5021
|
+
`connector-aware dedup scan failed for storage ${storage.dir}; writing fail-open: ${err instanceof Error ? err.message : String(err)}`
|
|
5022
|
+
);
|
|
5023
|
+
return false;
|
|
5024
|
+
}
|
|
5025
|
+
}
|
|
5026
|
+
async function persistUnderFactDedupWindow(storageDir, recheck, write) {
|
|
5027
|
+
return serializeMutations(
|
|
5028
|
+
`fact-dedup:${storageDir}`,
|
|
5029
|
+
() => withHeldFileLock(
|
|
5030
|
+
path5.join(storageDir, "fact-dedup.lock"),
|
|
5031
|
+
// Bounded: the window holds one corpus confirm + one memory write, not a
|
|
5032
|
+
// scan-length lock (catalog round 5 adoption note).
|
|
5033
|
+
{ staleMs: 5e3, maxWaitMs: 2e3, pollMs: 50 },
|
|
5034
|
+
async (acquired) => {
|
|
5035
|
+
if (!acquired) {
|
|
5036
|
+
throw new Error(`fact write skipped: fact-dedup.lock not acquired (${storageDir})`);
|
|
5037
|
+
}
|
|
5038
|
+
if (await recheck()) return { suppressed: true };
|
|
5039
|
+
return { suppressed: false, result: await write() };
|
|
5040
|
+
}
|
|
5041
|
+
)
|
|
5042
|
+
);
|
|
5043
|
+
}
|
|
5044
|
+
|
|
4898
5045
|
// src/orchestration/extraction-injection-gate.ts
|
|
4899
5046
|
function serializeInjectionScreenCandidate(candidate) {
|
|
4900
5047
|
const body = candidate.category === "procedure" ? buildProcedurePersistBody(candidate.content, candidate.procedureSteps) : candidate.content;
|
|
@@ -5571,7 +5718,7 @@ async function retireStaleMergedTargetPromotionCopies(args) {
|
|
|
5571
5718
|
}
|
|
5572
5719
|
|
|
5573
5720
|
// src/orchestration/semantic-merge-persist.ts
|
|
5574
|
-
import
|
|
5721
|
+
import path6 from "path";
|
|
5575
5722
|
|
|
5576
5723
|
// src/orchestration/semantic-merge-commit-effects.ts
|
|
5577
5724
|
import { readFile as readFile3 } from "fs/promises";
|
|
@@ -6291,11 +6438,11 @@ async function runMergedTargetPostEffects(deps, storage, merge, input) {
|
|
|
6291
6438
|
if (inferMemoryStatus(committed.frontmatter, committed.path) !== "active") return signals;
|
|
6292
6439
|
const entityRef = committed.frontmatter.entityRef;
|
|
6293
6440
|
const rawBody = rawPreCitationMergedBody(deps, merge.mergedContent);
|
|
6294
|
-
const memoryRelPath =
|
|
6441
|
+
const memoryRelPath = path6.relative(storage.dir, committed.path);
|
|
6295
6442
|
input.graphContext.memoryPathById.set(merge.targetId, memoryRelPath);
|
|
6296
6443
|
const all = input.graphContext.allMemsForGraph;
|
|
6297
6444
|
if (Array.isArray(all)) {
|
|
6298
|
-
const entry = all.find((m) =>
|
|
6445
|
+
const entry = all.find((m) => path6.relative(storage.dir, m.path) === memoryRelPath);
|
|
6299
6446
|
if (entry) entry.content = rawBody;
|
|
6300
6447
|
}
|
|
6301
6448
|
const rewriteTypes = [];
|
|
@@ -6339,7 +6486,7 @@ async function runMergedTargetPostEffects(deps, storage, merge, input) {
|
|
|
6339
6486
|
}
|
|
6340
6487
|
|
|
6341
6488
|
// src/orchestration/extraction-anchor-snapshot.ts
|
|
6342
|
-
import
|
|
6489
|
+
import path7 from "path";
|
|
6343
6490
|
var ExtractionAnchorSnapshot = class {
|
|
6344
6491
|
constructor(options = {}) {
|
|
6345
6492
|
this.options = options;
|
|
@@ -6377,7 +6524,7 @@ var ExtractionAnchorSnapshot = class {
|
|
|
6377
6524
|
if (!cached) return;
|
|
6378
6525
|
const snapshot = await cached;
|
|
6379
6526
|
const relativePath = resolvePersistedMemoryRelativePath({ memoryId, pathById, category });
|
|
6380
|
-
let memory = await storage.readMemoryByPath(
|
|
6527
|
+
let memory = await storage.readMemoryByPath(path7.join(storage.dir, relativePath));
|
|
6381
6528
|
if (!memory) memory = await storage.getMemoryByIdIncludingArchived(memoryId);
|
|
6382
6529
|
if (!memory) return;
|
|
6383
6530
|
const existingIndex = snapshot.findIndex((entry) => entry.frontmatter.id === memoryId);
|
|
@@ -6397,24 +6544,6 @@ var ExtractionAnchorSnapshot = class {
|
|
|
6397
6544
|
}
|
|
6398
6545
|
};
|
|
6399
6546
|
|
|
6400
|
-
// src/orchestration/extraction-persist-citation.ts
|
|
6401
|
-
function normalizeStoredHashSource(raw, citationEnabled, citationTemplate) {
|
|
6402
|
-
return ContentHashIndex.normalizeContent(
|
|
6403
|
-
sanitizeMemoryContent(
|
|
6404
|
-
citationEnabled && hasCitationForTemplate(raw, citationTemplate) ? stripCitationForTemplate(raw, citationTemplate) : raw
|
|
6405
|
-
).text
|
|
6406
|
-
);
|
|
6407
|
-
}
|
|
6408
|
-
function applyInlineCitation(content, citationEnabled, citationTemplate, citationContextBase) {
|
|
6409
|
-
if (!citationEnabled) return content;
|
|
6410
|
-
if (typeof content !== "string" || content.length === 0) return content;
|
|
6411
|
-
const citationContext = {
|
|
6412
|
-
...citationContextBase,
|
|
6413
|
-
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
6414
|
-
};
|
|
6415
|
-
return attachCitation(content, citationContext, citationTemplate);
|
|
6416
|
-
}
|
|
6417
|
-
|
|
6418
6547
|
// src/orchestration/extraction-persist.ts
|
|
6419
6548
|
var ExtractionPersistCoordinator = class {
|
|
6420
6549
|
constructor(deps) {
|
|
@@ -6454,6 +6583,7 @@ var ExtractionPersistCoordinator = class {
|
|
|
6454
6583
|
});
|
|
6455
6584
|
const supersessionOrderingAt = (validAt) => validAt && validAt.length > 0 ? validAt : (/* @__PURE__ */ new Date()).toISOString();
|
|
6456
6585
|
const pendingReviewPersistedIds = [];
|
|
6586
|
+
let deferredCount = 0;
|
|
6457
6587
|
const persistedIdsByStorage = /* @__PURE__ */ new Map();
|
|
6458
6588
|
const trackPersistedId = (targetStorage, id, options = {}) => {
|
|
6459
6589
|
if (options.includeReturnedIds !== false) {
|
|
@@ -6960,7 +7090,7 @@ var ExtractionPersistCoordinator = class {
|
|
|
6960
7090
|
"persistExtraction: result or result.facts is invalid, skipping",
|
|
6961
7091
|
{ resultType: typeof result, factsType: typeof result?.facts }
|
|
6962
7092
|
);
|
|
6963
|
-
return { persistedIds, memoryPathById };
|
|
7093
|
+
return { persistedIds, memoryPathById, deferredCount, pendingReviewIds: pendingReviewPersistedIds };
|
|
6964
7094
|
}
|
|
6965
7095
|
const chunkingConfig = {
|
|
6966
7096
|
targetTokens: this.deps.config.chunkingTargetTokens,
|
|
@@ -7067,7 +7197,6 @@ var ExtractionPersistCoordinator = class {
|
|
|
7067
7197
|
}
|
|
7068
7198
|
let judgeVerdictsByFactIndex = null;
|
|
7069
7199
|
let judgeGatedCount = 0;
|
|
7070
|
-
this.deps.setLastPersistExtractionDeferredCount(0);
|
|
7071
7200
|
if (lifecycleCaps.extractionJudge) {
|
|
7072
7201
|
let preJudgeRedactionRules = [];
|
|
7073
7202
|
try {
|
|
@@ -7195,7 +7324,7 @@ var ExtractionPersistCoordinator = class {
|
|
|
7195
7324
|
log.info(
|
|
7196
7325
|
`extraction-judge: ${judgeResult.verdicts.size}/${judgeCandidates.length} facts evaluated, ${judgeResult.cached} cached, ${judgeResult.judged} judged, ${judgeResult.deferred} deferred` + (judgeResult.deferredCappedToReject > 0 ? ` (${judgeResult.deferredCappedToReject} cap-rejected)` : "") + `, ${judgeResult.elapsed}ms`
|
|
7197
7326
|
);
|
|
7198
|
-
|
|
7327
|
+
deferredCount = judgeResult.deferred;
|
|
7199
7328
|
} catch (err) {
|
|
7200
7329
|
log.warn(
|
|
7201
7330
|
`extraction-judge: pipeline error, proceeding without filtering (fail-open): ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -7322,81 +7451,83 @@ var ExtractionPersistCoordinator = class {
|
|
|
7322
7451
|
fact.tags
|
|
7323
7452
|
);
|
|
7324
7453
|
let exactDuplicate = false;
|
|
7325
|
-
let needsCorpusConfirm = false;
|
|
7326
7454
|
try {
|
|
7327
7455
|
exactDuplicate = await this.deps.hasContentHashDedup(targetStorage, contentHashDedupKey);
|
|
7328
|
-
if (factDedupEnabled && !exactDuplicate) {
|
|
7329
|
-
if (await targetStorage.isFactContentHashAuthoritative()) {
|
|
7330
|
-
exactDuplicate = await this.deps.hasContentHashDedup(targetStorage, contentHashDedupKey);
|
|
7331
|
-
} else {
|
|
7332
|
-
needsCorpusConfirm = true;
|
|
7333
|
-
}
|
|
7334
|
-
}
|
|
7335
7456
|
} catch (err) {
|
|
7336
|
-
|
|
7457
|
+
exactDuplicate = false;
|
|
7337
7458
|
log.warn(
|
|
7338
7459
|
`content-hash dedup lookup unavailable for storage ${targetStorage.dir}; confirming against corpus: ${err}`
|
|
7339
7460
|
);
|
|
7340
7461
|
}
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7353
|
-
|
|
7354
|
-
exactDuplicate = hotMems.some(matchesActiveDuplicate) || coldMems.some(matchesActiveDuplicate);
|
|
7355
|
-
} catch (err) {
|
|
7356
|
-
log.warn(
|
|
7357
|
-
`connector-aware dedup scan failed for storage ${targetStorage.dir}; writing fail-open: ${err instanceof Error ? err.message : String(err)}`
|
|
7358
|
-
);
|
|
7359
|
-
exactDuplicate = false;
|
|
7360
|
-
}
|
|
7462
|
+
const raceDedupOpts = (key) => ({
|
|
7463
|
+
category: writeCategory,
|
|
7464
|
+
contentHashDedupKey: key,
|
|
7465
|
+
connector: sourceContext?.sourceConnector?.trim() || void 0,
|
|
7466
|
+
citationEnabled,
|
|
7467
|
+
citationTemplate
|
|
7468
|
+
});
|
|
7469
|
+
if (factDedupEnabled) {
|
|
7470
|
+
exactDuplicate = await confirmActiveFactDuplicate(
|
|
7471
|
+
{ hasContentHashDedup: (storage2, key) => this.deps.hasContentHashDedup(storage2, key) },
|
|
7472
|
+
targetStorage,
|
|
7473
|
+
raceDedupOpts(contentHashDedupKey)
|
|
7474
|
+
);
|
|
7361
7475
|
}
|
|
7362
|
-
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
|
|
7368
|
-
|
|
7369
|
-
|
|
7370
|
-
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
|
|
7377
|
-
|
|
7378
|
-
|
|
7379
|
-
|
|
7380
|
-
|
|
7381
|
-
|
|
7382
|
-
|
|
7383
|
-
|
|
7384
|
-
|
|
7385
|
-
content: fact.content,
|
|
7386
|
-
category: writeCategory,
|
|
7387
|
-
confidence: fact.confidence,
|
|
7388
|
-
entityRef: fact.entityRef,
|
|
7389
|
-
structuredAttributes: fact.structuredAttributes,
|
|
7390
|
-
sourceConnector: sourceContext?.sourceConnector,
|
|
7391
|
-
bounds: {
|
|
7392
|
-
invalidAt: biTemporal.validUntil,
|
|
7393
|
-
validFrom: biTemporal.validFrom,
|
|
7394
|
-
observedAt: biTemporal.observedAt,
|
|
7395
|
-
eventTimeSource: biTemporal.eventTimeSource
|
|
7396
|
-
}
|
|
7397
|
-
});
|
|
7398
|
-
}
|
|
7476
|
+
const finalizeOnWindowFailure = async (err) => {
|
|
7477
|
+
await finalizeCommittedWrites(true).catch(
|
|
7478
|
+
(finalizeErr) => log.warn(`committed-write finalization after fact-dedup window failure failed: ${finalizeErr}`)
|
|
7479
|
+
);
|
|
7480
|
+
throw err;
|
|
7481
|
+
};
|
|
7482
|
+
const raceRecheck = (storage2, key) => () => {
|
|
7483
|
+
if (!factDedupEnabled || injectionScreenStatus === "pending_review") return Promise.resolve(false);
|
|
7484
|
+
return confirmActiveFactDuplicate(
|
|
7485
|
+
{ hasContentHashDedup: (s, k) => this.deps.hasContentHashDedup(s, k) },
|
|
7486
|
+
storage2,
|
|
7487
|
+
raceDedupOpts(key)
|
|
7488
|
+
);
|
|
7489
|
+
};
|
|
7490
|
+
const backfillDuplicateTemporalBounds = async () => {
|
|
7491
|
+
if (!(biTemporal && writeCategory === "fact" && (biTemporal.validUntil || biTemporal.validFrom))) return;
|
|
7492
|
+
const fr = faithfulnessResultsByFactIndex?.get(factLoopIndex);
|
|
7493
|
+
const faithfulnessWouldPending = faithfulnessMode === "enforce" && fr?.ok === true && (fr.verdict === "unsupported" || fr.verdict === "contradicted");
|
|
7494
|
+
const requireSpansWouldPending = this.deps.config.provenance?.requireSpans === true && fact.requireSpansPending === true;
|
|
7495
|
+
const judgeVerdict = judgeVerdictsByFactIndex?.get(factLoopIndex);
|
|
7496
|
+
const judgeWouldGate = !this.deps.config.extractionJudgeShadow && judgeVerdict !== void 0 && !judgeVerdict.durable;
|
|
7497
|
+
if (!isAboveImportanceThreshold(importance.level, this.deps.config.extractionMinImportanceLevel) || faithfulnessWouldPending || requireSpansWouldPending || judgeWouldGate) {
|
|
7498
|
+
return;
|
|
7399
7499
|
}
|
|
7500
|
+
await this.deps.backfillTemporalBoundsOnDedupHit(
|
|
7501
|
+
targetStorage,
|
|
7502
|
+
contentHashDedupKey,
|
|
7503
|
+
{
|
|
7504
|
+
invalidAt: biTemporal.validUntil,
|
|
7505
|
+
// #1707 thread 2 — carry the corrected start bound too.
|
|
7506
|
+
validFrom: biTemporal.validFrom,
|
|
7507
|
+
observedAt: biTemporal.observedAt,
|
|
7508
|
+
eventTimeSource: biTemporal.eventTimeSource
|
|
7509
|
+
},
|
|
7510
|
+
fact.entityRef,
|
|
7511
|
+
sourceContext?.sourceConnector
|
|
7512
|
+
);
|
|
7513
|
+
await backfillTemporalBoundsOnPromotionCopies({
|
|
7514
|
+
sourceStorage: targetStorage,
|
|
7515
|
+
content: fact.content,
|
|
7516
|
+
category: writeCategory,
|
|
7517
|
+
confidence: fact.confidence,
|
|
7518
|
+
entityRef: fact.entityRef,
|
|
7519
|
+
structuredAttributes: fact.structuredAttributes,
|
|
7520
|
+
sourceConnector: sourceContext?.sourceConnector,
|
|
7521
|
+
bounds: {
|
|
7522
|
+
invalidAt: biTemporal.validUntil,
|
|
7523
|
+
validFrom: biTemporal.validFrom,
|
|
7524
|
+
observedAt: biTemporal.observedAt,
|
|
7525
|
+
eventTimeSource: biTemporal.eventTimeSource
|
|
7526
|
+
}
|
|
7527
|
+
});
|
|
7528
|
+
};
|
|
7529
|
+
if (exactDuplicate && injectionScreenStatus !== "pending_review") {
|
|
7530
|
+
await backfillDuplicateTemporalBounds();
|
|
7400
7531
|
log.debug(
|
|
7401
7532
|
`dedup: skipping duplicate fact "${fact.content.slice(0, 60)}\u2026" in storage ${targetStorage.dir}`
|
|
7402
7533
|
);
|
|
@@ -7605,27 +7736,38 @@ var ExtractionPersistCoordinator = class {
|
|
|
7605
7736
|
},
|
|
7606
7737
|
{ source: extractionWriteSource }
|
|
7607
7738
|
);
|
|
7608
|
-
const
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7739
|
+
const parentWriteOutcome = await persistUnderFactDedupWindow(
|
|
7740
|
+
targetStorage.dir,
|
|
7741
|
+
raceRecheck(targetStorage, contentHashDedupKey),
|
|
7742
|
+
async () => targetStorage.writeSealedMemory(parentWriteEnvelope, {
|
|
7743
|
+
importance,
|
|
7744
|
+
supersedes,
|
|
7745
|
+
links: links.length > 0 ? links : void 0,
|
|
7746
|
+
intentGoal: inferredIntent?.goal,
|
|
7747
|
+
intentActionType: inferredIntent?.actionType,
|
|
7748
|
+
intentEntityTypes: inferredIntent?.entityTypes,
|
|
7749
|
+
memoryKind: memoryKind2,
|
|
7750
|
+
...biTemporal ? { observedAt: biTemporal.observedAt, eventTimeSource: biTemporal.eventTimeSource, ...biTemporal.validUntil ? { invalidAt: biTemporal.validUntil } : {} } : {},
|
|
7751
|
+
contentHashSource: rawChunkedContent,
|
|
7752
|
+
// Faithfulness gate (issue #1576).
|
|
7753
|
+
...faithfulnessFm ? { faithfulness: faithfulnessFm } : {},
|
|
7754
|
+
...faithfulnessEnforceStatus ? { status: faithfulnessEnforceStatus } : {},
|
|
7755
|
+
// Claim-level provenance spans (issue #1575 PR 2).
|
|
7756
|
+
...fact.sources && fact.sources.length > 0 ? { sources: fact.sources } : {},
|
|
7757
|
+
...fact.provenance ? { provenance: fact.provenance } : {},
|
|
7758
|
+
// PR #2016: never defer here — fallible chunk/artifact writes follow this
|
|
7759
|
+
// durable parent .md; flush the hash now so a throw can't strand it (dup).
|
|
7760
|
+
deferHashIndexSave: false,
|
|
7761
|
+
...factToolScoped ? { toolScoped: true } : {}
|
|
7762
|
+
})
|
|
7763
|
+
).catch(finalizeOnWindowFailure);
|
|
7764
|
+
if (parentWriteOutcome.suppressed) {
|
|
7765
|
+
await backfillDuplicateTemporalBounds();
|
|
7766
|
+
log.info(`dedup: raced duplicate suppressed in fact-dedup window (chunked parent) for storage ${targetStorage.dir}`);
|
|
7767
|
+
dedupedCount++;
|
|
7768
|
+
continue;
|
|
7769
|
+
}
|
|
7770
|
+
const parentWrite = parentWriteOutcome.result;
|
|
7629
7771
|
const parentId = parentWrite.id;
|
|
7630
7772
|
const tombstoneBlocked2 = parentWrite.tombstoneBlocked;
|
|
7631
7773
|
const postWriteGuard2 = faithfulnessEnforceStatus === "pending_review" || tombstoneBlocked2;
|
|
@@ -7914,29 +8056,41 @@ var ExtractionPersistCoordinator = class {
|
|
|
7914
8056
|
},
|
|
7915
8057
|
{ source: extractionWriteSource }
|
|
7916
8058
|
);
|
|
7917
|
-
const
|
|
7918
|
-
|
|
7919
|
-
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
|
|
7926
|
-
|
|
7927
|
-
|
|
7928
|
-
|
|
7929
|
-
|
|
7930
|
-
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
|
|
7938
|
-
|
|
7939
|
-
|
|
8059
|
+
const factWriteOutcome = await persistUnderFactDedupWindow(
|
|
8060
|
+
targetStorage.dir,
|
|
8061
|
+
raceRecheck(targetStorage, contentHashDedupKey),
|
|
8062
|
+
async () => targetStorage.writeSealedMemory(factWriteEnvelope, {
|
|
8063
|
+
importance,
|
|
8064
|
+
supersedes,
|
|
8065
|
+
links: links.length > 0 ? links : void 0,
|
|
8066
|
+
intentGoal: inferredIntent?.goal,
|
|
8067
|
+
intentActionType: inferredIntent?.actionType,
|
|
8068
|
+
intentEntityTypes: inferredIntent?.entityTypes,
|
|
8069
|
+
memoryKind,
|
|
8070
|
+
...biTemporal ? { observedAt: biTemporal.observedAt, eventTimeSource: biTemporal.eventTimeSource, ...biTemporal.validUntil ? { invalidAt: biTemporal.validUntil } : {} } : {},
|
|
8071
|
+
contentHashSource: writeCategory === "fact" ? fact.content : void 0,
|
|
8072
|
+
// Faithfulness gate (issue #1576).
|
|
8073
|
+
...faithfulnessFm ? { faithfulness: faithfulnessFm } : {},
|
|
8074
|
+
...faithfulnessEnforceStatus ? { status: faithfulnessEnforceStatus } : {},
|
|
8075
|
+
// Claim-level provenance spans (issue #1575 PR 2). Carry verified
|
|
8076
|
+
// sources + the coarse strength tag from the extraction validator
|
|
8077
|
+
// through to frontmatter so they survive end-to-end.
|
|
8078
|
+
...fact.sources && fact.sources.length > 0 ? { sources: fact.sources } : {},
|
|
8079
|
+
...fact.provenance ? { provenance: fact.provenance } : {},
|
|
8080
|
+
// PR #2016: never defer inside the commit window (chunked-path
|
|
8081
|
+
// rule): a peer loading an authoritative index after the release
|
|
8082
|
+
// must see this hash, or its recheck misses and duplicates it.
|
|
8083
|
+
deferHashIndexSave: false,
|
|
8084
|
+
...factToolScoped ? { toolScoped: true } : {}
|
|
8085
|
+
})
|
|
8086
|
+
).catch(finalizeOnWindowFailure);
|
|
8087
|
+
if (factWriteOutcome.suppressed) {
|
|
8088
|
+
await backfillDuplicateTemporalBounds();
|
|
8089
|
+
log.info(`dedup: raced duplicate suppressed in fact-dedup window for storage ${targetStorage.dir}`);
|
|
8090
|
+
dedupedCount++;
|
|
8091
|
+
continue;
|
|
8092
|
+
}
|
|
8093
|
+
const factWrite = factWriteOutcome.result;
|
|
7940
8094
|
const memoryId = factWrite.id;
|
|
7941
8095
|
const tombstoneBlocked = factWrite.tombstoneBlocked;
|
|
7942
8096
|
const postWriteGuard = faithfulnessEnforceStatus === "pending_review" || tombstoneBlocked;
|
|
@@ -8226,8 +8380,7 @@ ${q.context ?? ""}`], entityScreenOn, entityScreenProfile);
|
|
|
8226
8380
|
log.info(
|
|
8227
8381
|
`persisted: ${facts.length - dedupedCount - importanceGatedCount - judgeGatedCount - redactionGatedCount - semanticMergedCount} facts${dedupSuffix}${gatedSuffix}${judgeSuffix}${redactionSuffix}, ${entities.length} entities, ${questions.length} questions, ${profileUpdates.length} profile updates`
|
|
8228
8382
|
);
|
|
8229
|
-
|
|
8230
|
-
return { persistedIds, memoryPathById };
|
|
8383
|
+
return { persistedIds, memoryPathById, deferredCount, pendingReviewIds: pendingReviewPersistedIds };
|
|
8231
8384
|
}
|
|
8232
8385
|
};
|
|
8233
8386
|
|
|
@@ -8252,7 +8405,7 @@ async function drainExtractionAndShutdownDependencyPropagation(extractionQueue,
|
|
|
8252
8405
|
// src/orchestration/dependency-propagation-delivery.ts
|
|
8253
8406
|
import { randomUUID } from "crypto";
|
|
8254
8407
|
import { readFile as readFile4, unlink } from "fs/promises";
|
|
8255
|
-
import
|
|
8408
|
+
import path8 from "path";
|
|
8256
8409
|
|
|
8257
8410
|
// src/orchestration/dependency-propagation-recovery-replay.ts
|
|
8258
8411
|
import { createHash as createHash4 } from "crypto";
|
|
@@ -8935,13 +9088,13 @@ var DependencyPropagationDelivery = class {
|
|
|
8935
9088
|
try {
|
|
8936
9089
|
const job = validateJob(JSON.parse(await this.readQueueFile(filePath)), status);
|
|
8937
9090
|
if (!job) {
|
|
8938
|
-
log.warn(`dependency propagation ignored invalid job file ${
|
|
9091
|
+
log.warn(`dependency propagation ignored invalid job file ${path8.basename(filePath)}`);
|
|
8939
9092
|
continue;
|
|
8940
9093
|
}
|
|
8941
9094
|
entries.push({ job, filePath });
|
|
8942
9095
|
} catch (error) {
|
|
8943
9096
|
if (error instanceof SyntaxError || isNotFound(error)) {
|
|
8944
|
-
log.warn(`dependency propagation ignored unreadable job file ${
|
|
9097
|
+
log.warn(`dependency propagation ignored unreadable job file ${path8.basename(filePath)}: ${error}`);
|
|
8945
9098
|
continue;
|
|
8946
9099
|
}
|
|
8947
9100
|
throw error;
|
|
@@ -9012,7 +9165,7 @@ var DependencyPropagationDelivery = class {
|
|
|
9012
9165
|
await this.writeQueueJob(targetPath, next);
|
|
9013
9166
|
const terminal = status === "completed" || status === "dead_letter" || status === "canceled";
|
|
9014
9167
|
for (const entry of entries) {
|
|
9015
|
-
if (
|
|
9168
|
+
if (path8.resolve(entry.filePath) === path8.resolve(targetPath)) continue;
|
|
9016
9169
|
await unlink(entry.filePath).catch((error) => {
|
|
9017
9170
|
if (isNotFound(error)) return;
|
|
9018
9171
|
if (terminal) {
|
|
@@ -9076,7 +9229,7 @@ var DependencyPropagationDelivery = class {
|
|
|
9076
9229
|
allowMissingDirectory: true
|
|
9077
9230
|
});
|
|
9078
9231
|
for (const filePath of files) {
|
|
9079
|
-
if (
|
|
9232
|
+
if (path8.basename(filePath, ".json") !== jobId) continue;
|
|
9080
9233
|
try {
|
|
9081
9234
|
await unlink(filePath);
|
|
9082
9235
|
} catch (error) {
|
|
@@ -9277,11 +9430,11 @@ function createDependencyPropagationReplayReconciliation(host) {
|
|
|
9277
9430
|
// src/orchestration/recall-internal.ts
|
|
9278
9431
|
import { createHash as createHash6 } from "crypto";
|
|
9279
9432
|
import { readFile as readFile5, stat, unlink as unlink2 } from "fs/promises";
|
|
9280
|
-
import
|
|
9433
|
+
import path13 from "path";
|
|
9281
9434
|
|
|
9282
9435
|
// src/orchestration/graph-path-state-loader.ts
|
|
9283
9436
|
import { lstat, opendir, realpath } from "fs/promises";
|
|
9284
|
-
import
|
|
9437
|
+
import path9 from "path";
|
|
9285
9438
|
function isArchivePathIndexUnavailable(index) {
|
|
9286
9439
|
return "unavailable" in index;
|
|
9287
9440
|
}
|
|
@@ -9300,11 +9453,11 @@ var GraphPathStateLoader = class {
|
|
|
9300
9453
|
openArchiveDirectory = opendir;
|
|
9301
9454
|
async readNode(storage, nodeId, deadlineAtMs, allowArchiveLookup) {
|
|
9302
9455
|
if (typeof deadlineAtMs === "number" && Date.now() >= deadlineAtMs) return null;
|
|
9303
|
-
const configuredStorageRoot =
|
|
9456
|
+
const configuredStorageRoot = path9.resolve(storage.dir);
|
|
9304
9457
|
const storageRoot = await realpath(configuredStorageRoot).catch(() => null);
|
|
9305
9458
|
if (!storageRoot || storageRoot !== configuredStorageRoot) return null;
|
|
9306
|
-
const logicalId =
|
|
9307
|
-
const directRelativePaths = [nodeId,
|
|
9459
|
+
const logicalId = path9.basename(nodeId, path9.extname(nodeId));
|
|
9460
|
+
const directRelativePaths = [nodeId, path9.join("cold", nodeId)];
|
|
9308
9461
|
let inactiveDirectMemory = null;
|
|
9309
9462
|
for (const relativePath of directRelativePaths) {
|
|
9310
9463
|
const safePath = await this.resolveContainedPath(storageRoot, relativePath);
|
|
@@ -9327,7 +9480,7 @@ var GraphPathStateLoader = class {
|
|
|
9327
9480
|
if (!archiveIndex || isArchivePathIndexUnavailable(archiveIndex) || typeof deadlineAtMs === "number" && Date.now() >= deadlineAtMs) {
|
|
9328
9481
|
return null;
|
|
9329
9482
|
}
|
|
9330
|
-
const archivePaths = archiveIndex.pathsByBasename.get(
|
|
9483
|
+
const archivePaths = archiveIndex.pathsByBasename.get(path9.basename(nodeId)) ?? [];
|
|
9331
9484
|
for (const archivePath of archivePaths) {
|
|
9332
9485
|
if (typeof deadlineAtMs === "number" && Date.now() >= deadlineAtMs) return null;
|
|
9333
9486
|
const memory = await storage.readMemoryByPath(archivePath);
|
|
@@ -9337,17 +9490,17 @@ var GraphPathStateLoader = class {
|
|
|
9337
9490
|
return null;
|
|
9338
9491
|
}
|
|
9339
9492
|
async resolveContainedPath(storageRoot, relativePath) {
|
|
9340
|
-
if (
|
|
9493
|
+
if (path9.isAbsolute(relativePath)) return null;
|
|
9341
9494
|
const rawSegments = relativePath.replace(/\\/g, "/").split("/");
|
|
9342
9495
|
if (rawSegments.includes("..")) return null;
|
|
9343
|
-
const candidate =
|
|
9344
|
-
const lexicalRelative =
|
|
9345
|
-
if (lexicalRelative.length > 0 && (lexicalRelative.startsWith("..") ||
|
|
9496
|
+
const candidate = path9.resolve(storageRoot, relativePath);
|
|
9497
|
+
const lexicalRelative = path9.relative(storageRoot, candidate);
|
|
9498
|
+
if (lexicalRelative.length > 0 && (lexicalRelative.startsWith("..") || path9.isAbsolute(lexicalRelative))) {
|
|
9346
9499
|
return null;
|
|
9347
9500
|
}
|
|
9348
9501
|
const canonical = await realpath(candidate).catch(() => candidate);
|
|
9349
|
-
const canonicalRelative =
|
|
9350
|
-
if (canonicalRelative.length > 0 && (canonicalRelative.startsWith("..") ||
|
|
9502
|
+
const canonicalRelative = path9.relative(storageRoot, canonical);
|
|
9503
|
+
if (canonicalRelative.length > 0 && (canonicalRelative.startsWith("..") || path9.isAbsolute(canonicalRelative))) {
|
|
9351
9504
|
return null;
|
|
9352
9505
|
}
|
|
9353
9506
|
return canonical;
|
|
@@ -9420,7 +9573,7 @@ var GraphPathStateLoader = class {
|
|
|
9420
9573
|
}
|
|
9421
9574
|
async buildArchivePathIndex(storageRoot, version) {
|
|
9422
9575
|
const pathsByBasename = /* @__PURE__ */ new Map();
|
|
9423
|
-
const archiveRoot =
|
|
9576
|
+
const archiveRoot = path9.join(storageRoot, "archive");
|
|
9424
9577
|
let archiveRootStatus;
|
|
9425
9578
|
try {
|
|
9426
9579
|
archiveRootStatus = await this.archiveLstat(archiveRoot);
|
|
@@ -9438,8 +9591,8 @@ var GraphPathStateLoader = class {
|
|
|
9438
9591
|
if (isArchiveScanAbsenceError(error)) return { version, pathsByBasename };
|
|
9439
9592
|
return null;
|
|
9440
9593
|
}
|
|
9441
|
-
const archiveRelative =
|
|
9442
|
-
if (archiveRelative.length > 0 && (archiveRelative.startsWith("..") ||
|
|
9594
|
+
const archiveRelative = path9.relative(storageRoot, canonicalArchiveRoot);
|
|
9595
|
+
if (archiveRelative.length > 0 && (archiveRelative.startsWith("..") || path9.isAbsolute(archiveRelative))) {
|
|
9443
9596
|
return { version, pathsByBasename };
|
|
9444
9597
|
}
|
|
9445
9598
|
const pending = [canonicalArchiveRoot];
|
|
@@ -9465,8 +9618,8 @@ var GraphPathStateLoader = class {
|
|
|
9465
9618
|
if (isArchiveScanAbsenceError(error)) continue;
|
|
9466
9619
|
return null;
|
|
9467
9620
|
}
|
|
9468
|
-
const currentRelative =
|
|
9469
|
-
if (currentRelative.length > 0 && (currentRelative.startsWith("..") ||
|
|
9621
|
+
const currentRelative = path9.relative(storageRoot, canonicalCurrent);
|
|
9622
|
+
if (currentRelative.length > 0 && (currentRelative.startsWith("..") || path9.isAbsolute(currentRelative))) {
|
|
9470
9623
|
continue;
|
|
9471
9624
|
}
|
|
9472
9625
|
let directory;
|
|
@@ -9483,7 +9636,7 @@ var GraphPathStateLoader = class {
|
|
|
9483
9636
|
return { version, unavailable: "oversized" };
|
|
9484
9637
|
}
|
|
9485
9638
|
if (entry.isSymbolicLink()) continue;
|
|
9486
|
-
const entryPath =
|
|
9639
|
+
const entryPath = path9.join(canonicalCurrent, entry.name);
|
|
9487
9640
|
if (entry.isDirectory()) {
|
|
9488
9641
|
pending.push(entryPath);
|
|
9489
9642
|
continue;
|
|
@@ -9499,8 +9652,8 @@ var GraphPathStateLoader = class {
|
|
|
9499
9652
|
if (isArchiveScanAbsenceError(error)) continue;
|
|
9500
9653
|
return null;
|
|
9501
9654
|
}
|
|
9502
|
-
const relative =
|
|
9503
|
-
if (relative.length > 0 && (relative.startsWith("..") ||
|
|
9655
|
+
const relative = path9.relative(storageRoot, canonical);
|
|
9656
|
+
if (relative.length > 0 && (relative.startsWith("..") || path9.isAbsolute(relative))) {
|
|
9504
9657
|
continue;
|
|
9505
9658
|
}
|
|
9506
9659
|
const paths = pathsByBasename.get(entry.name);
|
|
@@ -9526,7 +9679,7 @@ var GraphPathStateLoader = class {
|
|
|
9526
9679
|
// src/orchestration/graph-recall-coordinator.ts
|
|
9527
9680
|
import { createHash as createHash5 } from "crypto";
|
|
9528
9681
|
import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
|
|
9529
|
-
import
|
|
9682
|
+
import path10 from "path";
|
|
9530
9683
|
function mergeGraphExpandedResults(primary, expanded) {
|
|
9531
9684
|
const mergedByNamespaceAndPath = /* @__PURE__ */ new Map();
|
|
9532
9685
|
for (const item of [...primary, ...expanded]) {
|
|
@@ -9543,11 +9696,11 @@ function mergeGraphExpandedResults(primary, expanded) {
|
|
|
9543
9696
|
return Array.from(mergedByNamespaceAndPath.values());
|
|
9544
9697
|
}
|
|
9545
9698
|
function graphPathRelativeToStorage(storageDir, candidatePath) {
|
|
9546
|
-
const absolutePath =
|
|
9547
|
-
const rel =
|
|
9699
|
+
const absolutePath = path10.isAbsolute(candidatePath) ? candidatePath : path10.resolve(storageDir, candidatePath);
|
|
9700
|
+
const rel = path10.relative(storageDir, absolutePath);
|
|
9548
9701
|
if (!rel || rel === ".") return null;
|
|
9549
9702
|
if (rel.startsWith("..")) return null;
|
|
9550
|
-
return rel.split(
|
|
9703
|
+
return rel.split(path10.sep).join("/");
|
|
9551
9704
|
}
|
|
9552
9705
|
function normalizeGraphActivationScore(score) {
|
|
9553
9706
|
const bounded = Number.isFinite(score) && score > 0 ? score : 0;
|
|
@@ -9647,7 +9800,7 @@ var GraphRecallCoordinator = class {
|
|
|
9647
9800
|
resolvedPath = resolvedCold.result.path;
|
|
9648
9801
|
resolvedResult = resolvedCold.result;
|
|
9649
9802
|
}
|
|
9650
|
-
if (!
|
|
9803
|
+
if (!path10.isAbsolute(resolvedPath)) {
|
|
9651
9804
|
resolvedAmbiguousSeeds.set(result.path, null);
|
|
9652
9805
|
return null;
|
|
9653
9806
|
}
|
|
@@ -9672,7 +9825,7 @@ var GraphRecallCoordinator = class {
|
|
|
9672
9825
|
}
|
|
9673
9826
|
continue;
|
|
9674
9827
|
}
|
|
9675
|
-
if (
|
|
9828
|
+
if (path10.isAbsolute(result.path)) {
|
|
9676
9829
|
const resolved = await resolveAmbiguousSeedOwner(result, null);
|
|
9677
9830
|
if (resolved) {
|
|
9678
9831
|
addResultForNamespace(resolved.namespace, resolved.result);
|
|
@@ -9718,7 +9871,7 @@ var GraphRecallCoordinator = class {
|
|
|
9718
9871
|
0
|
|
9719
9872
|
);
|
|
9720
9873
|
seedPaths.push(
|
|
9721
|
-
...seedRelativePaths.map((rel) =>
|
|
9874
|
+
...seedRelativePaths.map((rel) => path10.join(storage.dir, rel))
|
|
9722
9875
|
);
|
|
9723
9876
|
const seedSet = new Set(seedRelativePaths);
|
|
9724
9877
|
const nodeMemoryCache = /* @__PURE__ */ new Map();
|
|
@@ -9773,7 +9926,7 @@ var GraphRecallCoordinator = class {
|
|
|
9773
9926
|
path: memory.path,
|
|
9774
9927
|
score,
|
|
9775
9928
|
namespace,
|
|
9776
|
-
seed:
|
|
9929
|
+
seed: path10.resolve(storage.dir, candidate.seed),
|
|
9777
9930
|
hopDepth: candidate.hopDepth,
|
|
9778
9931
|
decayedWeight: candidate.decayedWeight,
|
|
9779
9932
|
graphType: candidate.graphType,
|
|
@@ -9805,7 +9958,7 @@ var GraphRecallCoordinator = class {
|
|
|
9805
9958
|
add(memory.frontmatter.id);
|
|
9806
9959
|
if (relativePath) {
|
|
9807
9960
|
add(relativePath);
|
|
9808
|
-
if (relativePath.endsWith(".md")) add(
|
|
9961
|
+
if (relativePath.endsWith(".md")) add(path10.basename(relativePath, ".md"));
|
|
9809
9962
|
}
|
|
9810
9963
|
return state;
|
|
9811
9964
|
};
|
|
@@ -9852,7 +10005,7 @@ var GraphRecallCoordinator = class {
|
|
|
9852
10005
|
path: memory.path,
|
|
9853
10006
|
score,
|
|
9854
10007
|
namespace,
|
|
9855
|
-
seed:
|
|
10008
|
+
seed: path10.resolve(storage.dir, candidate.seed),
|
|
9856
10009
|
hopDepth: candidate.hopDepth,
|
|
9857
10010
|
decayedWeight: candidate.decayedWeight,
|
|
9858
10011
|
graphType: candidate.graphType,
|
|
@@ -9895,12 +10048,12 @@ var GraphRecallCoordinator = class {
|
|
|
9895
10048
|
}
|
|
9896
10049
|
async recordLastGraphRecallSnapshot(options) {
|
|
9897
10050
|
try {
|
|
9898
|
-
const snapshotPath =
|
|
10051
|
+
const snapshotPath = path10.join(
|
|
9899
10052
|
options.storage.dir,
|
|
9900
10053
|
"state",
|
|
9901
10054
|
"last_graph_recall.json"
|
|
9902
10055
|
);
|
|
9903
|
-
await mkdir3(
|
|
10056
|
+
await mkdir3(path10.dirname(snapshotPath), { recursive: true });
|
|
9904
10057
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
9905
10058
|
const totalSeedCount = options.seedPaths.length;
|
|
9906
10059
|
const totalExpandedCount = options.expandedPaths.length;
|
|
@@ -10200,11 +10353,11 @@ async function appendEpisodicContextSection(deps, options) {
|
|
|
10200
10353
|
}
|
|
10201
10354
|
|
|
10202
10355
|
// src/orchestration/recall-profile-storage.ts
|
|
10203
|
-
import
|
|
10356
|
+
import path11 from "path";
|
|
10204
10357
|
function resolveCompositeProfileStorage(options) {
|
|
10205
10358
|
const { profileStorages, memoryDir } = options;
|
|
10206
10359
|
const emptyProfileStorage = new Proxy(
|
|
10207
|
-
{ dir:
|
|
10360
|
+
{ dir: path11.join(memoryDir, ".empty-scope-profile") },
|
|
10208
10361
|
{
|
|
10209
10362
|
get(target, prop) {
|
|
10210
10363
|
if (prop in target) return Reflect.get(target, prop);
|
|
@@ -10352,7 +10505,7 @@ function resolveCompositeProfileStorage(options) {
|
|
|
10352
10505
|
}
|
|
10353
10506
|
|
|
10354
10507
|
// src/orchestration/recall-recognition-search.ts
|
|
10355
|
-
import
|
|
10508
|
+
import path12 from "path";
|
|
10356
10509
|
async function fetchQmdMemoryResultsWithRecognitionSwap(deps, prompt, qmdFetchLimit, qmdHybridFetchLimit, options) {
|
|
10357
10510
|
if (deps.config.recallRecognitionTier !== true || options.collection || options.namespacesEnabled !== true) {
|
|
10358
10511
|
return deps.fetchQmdMemoryResultsWithArtifactTopUp(
|
|
@@ -10439,7 +10592,7 @@ async function hitsFromIds(namespace, storage, index, ids) {
|
|
|
10439
10592
|
for (const [offset, id] of ids.entries()) {
|
|
10440
10593
|
const absPath = pathsById.get(id)?.[0];
|
|
10441
10594
|
if (!absPath) continue;
|
|
10442
|
-
const rel =
|
|
10595
|
+
const rel = path12.relative(storage.dir, absPath).split(path12.sep).join("/");
|
|
10443
10596
|
if (!rel || rel.startsWith("..")) continue;
|
|
10444
10597
|
hits.push({
|
|
10445
10598
|
docid: `${namespace}:${rel}`,
|
|
@@ -10687,7 +10840,7 @@ var RecallInternalCoordinator = class {
|
|
|
10687
10840
|
const graphExpandedResultPaths = /* @__PURE__ */ new Set();
|
|
10688
10841
|
const graphSourceLabelsForPath = (resultPath) => {
|
|
10689
10842
|
const labels = [];
|
|
10690
|
-
const normalizedPath = resultPath.split(
|
|
10843
|
+
const normalizedPath = resultPath.split(path13.sep).join("/");
|
|
10691
10844
|
const isEntityPath = normalizedPath.startsWith("entities/") || normalizedPath.includes("/entities/");
|
|
10692
10845
|
if (graphBaselinePaths.has(resultPath)) labels.push("baseline");
|
|
10693
10846
|
if (graphExpandedResultPaths.has(resultPath))
|
|
@@ -12224,11 +12377,11 @@ ${formatted}`;
|
|
|
12224
12377
|
if (!resolveRecallAuxiliaryCapabilities(this.deps.config).compactionReset) return null;
|
|
12225
12378
|
const workspaceDir = compactionWorkspaceDir || this.deps.config.workspaceDir || defaultWorkspaceDir();
|
|
12226
12379
|
const safeSessionKey = sanitizeSessionKeyForFilename(effectiveSessionKey);
|
|
12227
|
-
const signalPath =
|
|
12380
|
+
const signalPath = path13.join(
|
|
12228
12381
|
workspaceDir,
|
|
12229
12382
|
`.compaction-reset-signal-${safeSessionKey}`
|
|
12230
12383
|
);
|
|
12231
|
-
const bootPath =
|
|
12384
|
+
const bootPath = path13.join(workspaceDir, "BOOT.md");
|
|
12232
12385
|
try {
|
|
12233
12386
|
const signalStat = await stat(signalPath).catch(() => null);
|
|
12234
12387
|
if (!signalStat) return null;
|
|
@@ -14508,10 +14661,10 @@ ${tmtNode.summary}`
|
|
|
14508
14661
|
|
|
14509
14662
|
// src/orchestration/recall-search-pipeline.ts
|
|
14510
14663
|
import { createHash as createHash7 } from "crypto";
|
|
14511
|
-
import
|
|
14664
|
+
import path15 from "path";
|
|
14512
14665
|
|
|
14513
14666
|
// src/orchestration/recall-search-prefilter.ts
|
|
14514
|
-
import
|
|
14667
|
+
import path14 from "path";
|
|
14515
14668
|
async function fetchActiveArtifactsForNamespace(deps, namespace, prompt, targetCount, options = {}) {
|
|
14516
14669
|
const storage = await deps.storageRouter.storageFor(namespace);
|
|
14517
14670
|
let fetchLimit = computeArtifactCandidateFetchLimit(targetCount);
|
|
@@ -14640,7 +14793,7 @@ async function searchEmbeddingFallback(deps, query, limit) {
|
|
|
14640
14793
|
if (hits.length === 0) return [];
|
|
14641
14794
|
const results = [];
|
|
14642
14795
|
for (const hit of hits) {
|
|
14643
|
-
const fullPath =
|
|
14796
|
+
const fullPath = path14.isAbsolute(hit.path) ? hit.path : path14.join(deps.config.memoryDir, hit.path);
|
|
14644
14797
|
const memory = await deps.storage.readMemoryByPath(fullPath);
|
|
14645
14798
|
if (!memory) continue;
|
|
14646
14799
|
results.push({
|
|
@@ -15018,7 +15171,7 @@ var RecallSearchPipelineCoordinator = class {
|
|
|
15018
15171
|
const storage = await this.deps.storageRouter.storageFor(namespace);
|
|
15019
15172
|
const storageDir = typeof storage.dir === "string" && storage.dir ? storage.dir : null;
|
|
15020
15173
|
if (!storageDir) continue;
|
|
15021
|
-
const recallRoot =
|
|
15174
|
+
const recallRoot = path15.resolve(storageDir);
|
|
15022
15175
|
if (seenRecallRoots.has(recallRoot)) continue;
|
|
15023
15176
|
seenRecallRoots.add(recallRoot);
|
|
15024
15177
|
recallRoots.push(recallRoot);
|
|
@@ -15042,8 +15195,8 @@ var RecallSearchPipelineCoordinator = class {
|
|
|
15042
15195
|
if (resolvedCold) scopedResults.push(resolvedCold.result);
|
|
15043
15196
|
continue;
|
|
15044
15197
|
}
|
|
15045
|
-
if (
|
|
15046
|
-
if (recallRoots.some((recallRoot) => isPathInsideStorageRoot(recallRoot,
|
|
15198
|
+
if (path15.isAbsolute(result.path)) {
|
|
15199
|
+
if (recallRoots.some((recallRoot) => isPathInsideStorageRoot(recallRoot, path15.resolve(result.path)))) {
|
|
15047
15200
|
scopedResults.push(result);
|
|
15048
15201
|
}
|
|
15049
15202
|
continue;
|
|
@@ -15764,8 +15917,10 @@ var ExtractionDrain = class {
|
|
|
15764
15917
|
* persist step ends the host's preemption registration, so the drain registers
|
|
15765
15918
|
* it again before every later chunk; a fail-closed flush can then abort the
|
|
15766
15919
|
* next chunk's model request instead of waiting behind the whole window.
|
|
15920
|
+
* `preemptHandle`: the queue task's own preemption slot (per task, so two
|
|
15921
|
+
* concurrent automatic extractions cannot clobber each other's registration).
|
|
15767
15922
|
*/
|
|
15768
|
-
async run(turns, runOptions, preemptable = false) {
|
|
15923
|
+
async run(turns, runOptions, preemptable = false, preemptHandle) {
|
|
15769
15924
|
const budgetChars = this.deps.extractionWindowBudgetChars?.() ?? Number.POSITIVE_INFINITY;
|
|
15770
15925
|
const chunkable = runOptions.clearBufferAfterExtraction && !runOptions.forceExtractionAttempt && !runOptions.failOnExtractionFailure && !turns.some((turn) => turn.acceptedCapture === true) && Number.isFinite(budgetChars) && budgetChars > 0;
|
|
15771
15926
|
const chunks = chunkable ? chunkExtractionWindow(turns, budgetChars) : [];
|
|
@@ -15790,7 +15945,7 @@ var ExtractionDrain = class {
|
|
|
15790
15945
|
if (preemptable && position > 0) {
|
|
15791
15946
|
const local = new AbortController();
|
|
15792
15947
|
preempt = local;
|
|
15793
|
-
|
|
15948
|
+
preemptHandle?.arm(() => local.abort(preemptedExtractionError()));
|
|
15794
15949
|
chunkOptions = {
|
|
15795
15950
|
...chunkOptions,
|
|
15796
15951
|
abortSignal: runOptions.abortSignal ? AbortSignal.any([runOptions.abortSignal, local.signal]) : local.signal
|
|
@@ -15852,8 +16007,8 @@ var ExtractionDrain = class {
|
|
|
15852
16007
|
const reason = `dropped after ${dropAfter} repeated extraction failures (last result: status=${result.status} reason=${result.reason ?? "n/a"})`;
|
|
15853
16008
|
try {
|
|
15854
16009
|
const storage = await this.deps.getStorage();
|
|
15855
|
-
const
|
|
15856
|
-
log.warn(`buffer[${bufferKey}]: dropping ${chunk.length} turns \u2014 ${reason}; copy saved to ${
|
|
16010
|
+
const path42 = await storage.saveDroppedExtractionChunk(bufferKey, reason, chunk);
|
|
16011
|
+
log.warn(`buffer[${bufferKey}]: dropping ${chunk.length} turns \u2014 ${reason}; copy saved to ${path42}`);
|
|
15857
16012
|
} catch (err) {
|
|
15858
16013
|
log.warn(
|
|
15859
16014
|
`buffer[${bufferKey}]: could not save the dropped-chunk recovery copy; keeping the chunk in the buffer: ${describeError(err)}`
|
|
@@ -16421,8 +16576,8 @@ var TurnIngestionCoordinator = class {
|
|
|
16421
16576
|
}
|
|
16422
16577
|
if (settled) return;
|
|
16423
16578
|
const preemptable = options.preemptable === true && options.preemptRunning !== true;
|
|
16424
|
-
const accepted = this.deps.extractionQueueCoordinator.enqueue(async () => {
|
|
16425
|
-
await this.deps.extractionQueueCoordinator.runPreemptable(preemptable, options.abortSignal, async (abortSignal) => {
|
|
16579
|
+
const accepted = this.deps.extractionQueueCoordinator.enqueue(async (preemptHandle) => {
|
|
16580
|
+
await this.deps.extractionQueueCoordinator.runPreemptable(preemptHandle, preemptable, options.abortSignal, async (abortSignal) => {
|
|
16426
16581
|
if (settled) return;
|
|
16427
16582
|
if (typeof extractionDeadlineMs === "number" && extractionDeadlineMs <= Date.now()) {
|
|
16428
16583
|
settleTask(new ExtractionDeadlineError("queue_wait"));
|
|
@@ -16528,14 +16683,14 @@ var TurnIngestionCoordinator = class {
|
|
|
16528
16683
|
deadlineMs: extractionDeadlineMs,
|
|
16529
16684
|
bufferKey,
|
|
16530
16685
|
onDurableCommit: options.onDurableCommit,
|
|
16531
|
-
onBeforePersist: () =>
|
|
16686
|
+
onBeforePersist: () => preemptHandle?.disarm(),
|
|
16532
16687
|
abortSignal,
|
|
16533
16688
|
failOnExtractionFailure: options.failOnExtractionFailure === true,
|
|
16534
16689
|
writeNamespaceOverride: options.writeNamespaceOverride,
|
|
16535
16690
|
principalOverride: options.principalOverride,
|
|
16536
16691
|
scopeProfileWritePlan: effectiveScopePlan,
|
|
16537
16692
|
forceExtractionAttempt: options.forceExtractionAttempt === true
|
|
16538
|
-
}, preemptable);
|
|
16693
|
+
}, preemptable, preemptHandle);
|
|
16539
16694
|
settleTask(void 0, result);
|
|
16540
16695
|
} catch (err) {
|
|
16541
16696
|
const reason2 = abortSignal.reason;
|
|
@@ -16545,7 +16700,7 @@ var TurnIngestionCoordinator = class {
|
|
|
16545
16700
|
}
|
|
16546
16701
|
}
|
|
16547
16702
|
});
|
|
16548
|
-
}, { front: options.preemptRunning === true });
|
|
16703
|
+
}, { front: options.preemptRunning === true, key: bufferKey });
|
|
16549
16704
|
if (!accepted) {
|
|
16550
16705
|
settleTask(new Error("extraction queue is stopped"));
|
|
16551
16706
|
return;
|
|
@@ -16624,7 +16779,7 @@ var TurnIngestionCoordinator = class {
|
|
|
16624
16779
|
|
|
16625
16780
|
// src/orchestration/recall-introspection.ts
|
|
16626
16781
|
import { mkdir as mkdir5, readFile as readFile7, writeFile as writeFile5 } from "fs/promises";
|
|
16627
|
-
import
|
|
16782
|
+
import path17 from "path";
|
|
16628
16783
|
|
|
16629
16784
|
// src/taxonomy/default-taxonomy.ts
|
|
16630
16785
|
var DEFAULT_TAXONOMY = {
|
|
@@ -16747,7 +16902,7 @@ function generateResolverDocument(taxonomy) {
|
|
|
16747
16902
|
|
|
16748
16903
|
// src/taxonomy/taxonomy-loader.ts
|
|
16749
16904
|
import { readFile as readFile6, mkdir as mkdir4, writeFile as writeFile4 } from "fs/promises";
|
|
16750
|
-
import
|
|
16905
|
+
import path16 from "path";
|
|
16751
16906
|
var TAXONOMY_DIR = ".taxonomy";
|
|
16752
16907
|
var TAXONOMY_FILE = "taxonomy.json";
|
|
16753
16908
|
var MAX_SLUG_LENGTH = 32;
|
|
@@ -16845,7 +17000,7 @@ function validateTaxonomy(taxonomy) {
|
|
|
16845
17000
|
}
|
|
16846
17001
|
}
|
|
16847
17002
|
async function loadTaxonomy(memoryDir) {
|
|
16848
|
-
const taxonomyPath =
|
|
17003
|
+
const taxonomyPath = path16.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
|
|
16849
17004
|
let raw;
|
|
16850
17005
|
try {
|
|
16851
17006
|
raw = await readFile6(taxonomyPath, "utf-8");
|
|
@@ -16895,16 +17050,16 @@ async function loadTaxonomy(memoryDir) {
|
|
|
16895
17050
|
}
|
|
16896
17051
|
async function saveTaxonomy(memoryDir, taxonomy) {
|
|
16897
17052
|
validateTaxonomy(taxonomy);
|
|
16898
|
-
const dir =
|
|
17053
|
+
const dir = path16.join(memoryDir, TAXONOMY_DIR);
|
|
16899
17054
|
await mkdir4(dir, { recursive: true });
|
|
16900
|
-
const filePath =
|
|
17055
|
+
const filePath = path16.join(dir, TAXONOMY_FILE);
|
|
16901
17056
|
await writeFile4(filePath, JSON.stringify(taxonomy, null, 2) + "\n", "utf-8");
|
|
16902
17057
|
}
|
|
16903
17058
|
function getTaxonomyDir(memoryDir) {
|
|
16904
|
-
return
|
|
17059
|
+
return path16.join(memoryDir, TAXONOMY_DIR);
|
|
16905
17060
|
}
|
|
16906
17061
|
function getTaxonomyFilePath(memoryDir) {
|
|
16907
|
-
return
|
|
17062
|
+
return path16.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
|
|
16908
17063
|
}
|
|
16909
17064
|
|
|
16910
17065
|
// src/orchestration/recall-introspection.ts
|
|
@@ -16928,7 +17083,7 @@ var RecallIntrospectionCoordinator = class {
|
|
|
16928
17083
|
}
|
|
16929
17084
|
async getLastGraphRecallSnapshot(namespace) {
|
|
16930
17085
|
const storage = await this.deps.getStorage(namespace);
|
|
16931
|
-
const snapshotPath =
|
|
17086
|
+
const snapshotPath = path17.join(
|
|
16932
17087
|
storage.dir,
|
|
16933
17088
|
"state",
|
|
16934
17089
|
"last_graph_recall.json"
|
|
@@ -16967,7 +17122,7 @@ var RecallIntrospectionCoordinator = class {
|
|
|
16967
17122
|
}
|
|
16968
17123
|
async getLastIntentSnapshot(namespace) {
|
|
16969
17124
|
const storage = await this.deps.getStorage(namespace);
|
|
16970
|
-
const snapshotPath =
|
|
17125
|
+
const snapshotPath = path17.join(storage.dir, "state", "last_intent.json");
|
|
16971
17126
|
try {
|
|
16972
17127
|
const raw = await readFile7(snapshotPath, "utf-8");
|
|
16973
17128
|
const parsed = JSON.parse(raw);
|
|
@@ -17000,7 +17155,7 @@ var RecallIntrospectionCoordinator = class {
|
|
|
17000
17155
|
}
|
|
17001
17156
|
async getLastQmdRecallSnapshot(namespace) {
|
|
17002
17157
|
const storage = await this.deps.getStorage(namespace);
|
|
17003
|
-
const snapshotPath =
|
|
17158
|
+
const snapshotPath = path17.join(
|
|
17004
17159
|
storage.dir,
|
|
17005
17160
|
"state",
|
|
17006
17161
|
"last_qmd_recall.json"
|
|
@@ -17292,12 +17447,12 @@ var RecallIntrospectionCoordinator = class {
|
|
|
17292
17447
|
}
|
|
17293
17448
|
async recordLastIntentSnapshot(options) {
|
|
17294
17449
|
try {
|
|
17295
|
-
const snapshotPath =
|
|
17450
|
+
const snapshotPath = path17.join(
|
|
17296
17451
|
options.storage.dir,
|
|
17297
17452
|
"state",
|
|
17298
17453
|
"last_intent.json"
|
|
17299
17454
|
);
|
|
17300
|
-
await mkdir5(
|
|
17455
|
+
await mkdir5(path17.dirname(snapshotPath), { recursive: true });
|
|
17301
17456
|
await writeFile5(
|
|
17302
17457
|
snapshotPath,
|
|
17303
17458
|
JSON.stringify(options.snapshot, null, 2),
|
|
@@ -17309,12 +17464,12 @@ var RecallIntrospectionCoordinator = class {
|
|
|
17309
17464
|
}
|
|
17310
17465
|
async recordLastQmdRecallSnapshot(options) {
|
|
17311
17466
|
try {
|
|
17312
|
-
const snapshotPath =
|
|
17467
|
+
const snapshotPath = path17.join(
|
|
17313
17468
|
options.storage.dir,
|
|
17314
17469
|
"state",
|
|
17315
17470
|
"last_qmd_recall.json"
|
|
17316
17471
|
);
|
|
17317
|
-
await mkdir5(
|
|
17472
|
+
await mkdir5(path17.dirname(snapshotPath), { recursive: true });
|
|
17318
17473
|
await writeFile5(
|
|
17319
17474
|
snapshotPath,
|
|
17320
17475
|
JSON.stringify(options.snapshot, null, 2),
|
|
@@ -17329,8 +17484,8 @@ var RecallIntrospectionCoordinator = class {
|
|
|
17329
17484
|
const stateDir = await this.deps.resolveStateDirForNamespace(
|
|
17330
17485
|
options.namespace
|
|
17331
17486
|
);
|
|
17332
|
-
const snapshotPath =
|
|
17333
|
-
await mkdir5(
|
|
17487
|
+
const snapshotPath = path17.join(stateDir, "last_intent.json");
|
|
17488
|
+
await mkdir5(path17.dirname(snapshotPath), { recursive: true });
|
|
17334
17489
|
await writeFile5(
|
|
17335
17490
|
snapshotPath,
|
|
17336
17491
|
JSON.stringify(options.snapshot, null, 2),
|
|
@@ -17344,7 +17499,7 @@ var RecallIntrospectionCoordinator = class {
|
|
|
17344
17499
|
|
|
17345
17500
|
// src/orchestration/orchestrator-init.ts
|
|
17346
17501
|
import { readdir as readdir2, stat as stat2, unlink as unlink3 } from "fs/promises";
|
|
17347
|
-
import
|
|
17502
|
+
import path18 from "path";
|
|
17348
17503
|
|
|
17349
17504
|
// src/orchestration/startup-collection-checks.ts
|
|
17350
17505
|
async function startupDiscoveryWithTimeout(discover, configuredFallback, timeoutMs = qmdStartupCollectionCheckTimeoutMs()) {
|
|
@@ -17680,7 +17835,7 @@ var OrchestratorInitCoordinator = class {
|
|
|
17680
17835
|
const files = await readdir2(wsDir).catch(() => []);
|
|
17681
17836
|
for (const f of files) {
|
|
17682
17837
|
if (!f.startsWith(".compaction-reset-signal-")) continue;
|
|
17683
|
-
const fp =
|
|
17838
|
+
const fp = path18.join(wsDir, f);
|
|
17684
17839
|
const s = await stat2(fp).catch(() => null);
|
|
17685
17840
|
if (s && Date.now() - s.mtimeMs >= COMPACTION_SIGNAL_MAX_AGE_MS) {
|
|
17686
17841
|
await unlink3(fp).catch(() => {
|
|
@@ -18100,11 +18255,11 @@ var OrchestratorInitCoordinator = class {
|
|
|
18100
18255
|
};
|
|
18101
18256
|
|
|
18102
18257
|
// src/orchestration/persistence-index.ts
|
|
18103
|
-
import
|
|
18258
|
+
import path20 from "path";
|
|
18104
18259
|
|
|
18105
18260
|
// src/orchestration/recall-recognition-index.ts
|
|
18106
18261
|
import { promises as fsp } from "fs";
|
|
18107
|
-
import
|
|
18262
|
+
import path19 from "path";
|
|
18108
18263
|
import { setTimeout as delay } from "timers/promises";
|
|
18109
18264
|
var writeChains = /* @__PURE__ */ new Map();
|
|
18110
18265
|
var LOCK_POLL_MS = 10;
|
|
@@ -18155,7 +18310,7 @@ async function withRecognitionIndexLock(memoryDir, op) {
|
|
|
18155
18310
|
} catch (error) {
|
|
18156
18311
|
const code = error?.code;
|
|
18157
18312
|
if (code === "ENOENT") {
|
|
18158
|
-
await fsp.mkdir(
|
|
18313
|
+
await fsp.mkdir(path19.dirname(lockDir), { recursive: true }).catch(() => void 0);
|
|
18159
18314
|
continue;
|
|
18160
18315
|
}
|
|
18161
18316
|
if (code !== "EEXIST") throw error;
|
|
@@ -18406,7 +18561,7 @@ var PersistenceIndexCoordinator = class {
|
|
|
18406
18561
|
const allMems = allMemsForGraph ?? [];
|
|
18407
18562
|
for (const m of allMems) {
|
|
18408
18563
|
if (m.frontmatter.entityRef === entityRef) {
|
|
18409
|
-
const rel =
|
|
18564
|
+
const rel = path20.relative(storage.dir, m.path);
|
|
18410
18565
|
if (rel !== memoryRelPath) entitySiblings.push(rel);
|
|
18411
18566
|
}
|
|
18412
18567
|
}
|
|
@@ -18602,7 +18757,7 @@ var PersistenceIndexCoordinator = class {
|
|
|
18602
18757
|
|
|
18603
18758
|
// src/orchestration/workspace-ops.ts
|
|
18604
18759
|
import { lstat as lstat2, mkdir as mkdir6, readFile as readFile8, readdir as readdir3, realpath as realpath2, writeFile as writeFile6 } from "fs/promises";
|
|
18605
|
-
import
|
|
18760
|
+
import path21 from "path";
|
|
18606
18761
|
|
|
18607
18762
|
// src/maintenance/pattern-reinforcement.ts
|
|
18608
18763
|
function patternReinforcementKey(content) {
|
|
@@ -20506,8 +20661,8 @@ var MeetingsService = class {
|
|
|
20506
20661
|
// src/orchestration/workspace-ops.ts
|
|
20507
20662
|
var MEETINGS_BUILD_DEBOUNCE_MS = 5e3;
|
|
20508
20663
|
function matchesMemoryPath(candidatePath, requestedPath, memoryDir) {
|
|
20509
|
-
const normalizedCandidate =
|
|
20510
|
-
return normalizedCandidate ===
|
|
20664
|
+
const normalizedCandidate = path21.resolve(candidatePath);
|
|
20665
|
+
return normalizedCandidate === path21.resolve(requestedPath) || normalizedCandidate === path21.resolve(memoryDir, requestedPath);
|
|
20511
20666
|
}
|
|
20512
20667
|
function accessTrackingPathCandidates(storageDir, memoryPath) {
|
|
20513
20668
|
const candidates = qmdResultPathCandidates(storageDir, memoryPath);
|
|
@@ -20515,12 +20670,12 @@ function accessTrackingPathCandidates(storageDir, memoryPath) {
|
|
|
20515
20670
|
if (!parts) return candidates;
|
|
20516
20671
|
candidates.push(
|
|
20517
20672
|
...qmdResultPathCandidates(storageDir, parts.relativePath),
|
|
20518
|
-
...qmdResultPathCandidates(
|
|
20673
|
+
...qmdResultPathCandidates(path21.join(storageDir, "cold"), parts.relativePath)
|
|
20519
20674
|
);
|
|
20520
20675
|
return [...new Set(candidates)];
|
|
20521
20676
|
}
|
|
20522
20677
|
function canonicalMemoryPath(memoryPath, memoryDir) {
|
|
20523
|
-
return
|
|
20678
|
+
return path21.resolve(path21.isAbsolute(memoryPath) ? memoryPath : path21.resolve(memoryDir, memoryPath));
|
|
20524
20679
|
}
|
|
20525
20680
|
var WorkspaceOpsCoordinator = class {
|
|
20526
20681
|
constructor(deps) {
|
|
@@ -20602,15 +20757,15 @@ var WorkspaceOpsCoordinator = class {
|
|
|
20602
20757
|
this.deps.lastFileHygieneRunAtMs = now;
|
|
20603
20758
|
if (hygiene.rotateEnabled) {
|
|
20604
20759
|
for (const rel of hygiene.rotatePaths) {
|
|
20605
|
-
const abs =
|
|
20760
|
+
const abs = path21.isAbsolute(rel) ? rel : path21.join(this.deps.config.workspaceDir, rel);
|
|
20606
20761
|
try {
|
|
20607
20762
|
const raw = await readFile8(abs, "utf-8");
|
|
20608
20763
|
if (raw.length > hygiene.rotateMaxBytes) {
|
|
20609
|
-
const archiveDir =
|
|
20764
|
+
const archiveDir = path21.join(
|
|
20610
20765
|
this.deps.config.workspaceDir,
|
|
20611
20766
|
hygiene.archiveDir
|
|
20612
20767
|
);
|
|
20613
|
-
const base =
|
|
20768
|
+
const base = path21.basename(abs);
|
|
20614
20769
|
const prefix = base.toUpperCase().replace(/\.MD$/i, "").replace(/[^A-Z0-9]+/g, "-") || "FILE";
|
|
20615
20770
|
const { newContent } = await rotateMarkdownFileToArchive({
|
|
20616
20771
|
filePath: abs,
|
|
@@ -20635,8 +20790,8 @@ var WorkspaceOpsCoordinator = class {
|
|
|
20635
20790
|
log.warn(w.message);
|
|
20636
20791
|
}
|
|
20637
20792
|
if (hygiene.warningsLogEnabled && warnings.length > 0) {
|
|
20638
|
-
const fp =
|
|
20639
|
-
await mkdir6(
|
|
20793
|
+
const fp = path21.join(this.deps.config.memoryDir, hygiene.warningsLogPath);
|
|
20794
|
+
await mkdir6(path21.dirname(fp), { recursive: true });
|
|
20640
20795
|
const stamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
20641
20796
|
const block = `
|
|
20642
20797
|
|
|
@@ -20676,7 +20831,7 @@ var WorkspaceOpsCoordinator = class {
|
|
|
20676
20831
|
for (const categoryDir of RECALL_FALLBACK_DIRS) {
|
|
20677
20832
|
if (memoryRootReal === null) break;
|
|
20678
20833
|
for (const date of datesToScan) {
|
|
20679
|
-
const dateDir =
|
|
20834
|
+
const dateDir = path21.join(storage.dir, categoryDir, date);
|
|
20680
20835
|
try {
|
|
20681
20836
|
const dirStat = await lstat2(dateDir);
|
|
20682
20837
|
if (dirStat.isSymbolicLink() || !dirStat.isDirectory()) continue;
|
|
@@ -20685,7 +20840,7 @@ var WorkspaceOpsCoordinator = class {
|
|
|
20685
20840
|
for (const entry of entries) {
|
|
20686
20841
|
if (entry.isSymbolicLink()) continue;
|
|
20687
20842
|
if (!entry.name.endsWith(".md")) continue;
|
|
20688
|
-
const fullPath =
|
|
20843
|
+
const fullPath = path21.join(dateDir, entry.name);
|
|
20689
20844
|
try {
|
|
20690
20845
|
assertPathInsideRoot(memoryRootReal, await realpath2(fullPath), fullPath);
|
|
20691
20846
|
const memory = await storage.readMemoryByPath(fullPath);
|
|
@@ -20707,13 +20862,13 @@ var WorkspaceOpsCoordinator = class {
|
|
|
20707
20862
|
return a.frontmatter.created < b.frontmatter.created ? -1 : 1;
|
|
20708
20863
|
});
|
|
20709
20864
|
const hourlySummaries = [];
|
|
20710
|
-
const hourlyBaseDir =
|
|
20865
|
+
const hourlyBaseDir = path21.join(storage.dir, "summaries", "hourly");
|
|
20711
20866
|
try {
|
|
20712
20867
|
const sessionKeys = await readdir3(hourlyBaseDir, { withFileTypes: true });
|
|
20713
20868
|
for (const sk of sessionKeys) {
|
|
20714
20869
|
if (!sk.isDirectory()) continue;
|
|
20715
20870
|
for (const date of datesToScan) {
|
|
20716
|
-
const summaryFile =
|
|
20871
|
+
const summaryFile = path21.join(hourlyBaseDir, sk.name, `${date}.md`);
|
|
20717
20872
|
try {
|
|
20718
20873
|
const raw = await readFile8(summaryFile, "utf-8");
|
|
20719
20874
|
const filtered = filterHourlySummaryMarkdownForLocalDay(
|
|
@@ -21190,18 +21345,18 @@ ${reflectionsContent.trim()}
|
|
|
21190
21345
|
// src/orchestration/namespace-read-fanout.ts
|
|
21191
21346
|
import { existsSync, readFileSync } from "fs";
|
|
21192
21347
|
import { stat as stat3 } from "fs/promises";
|
|
21193
|
-
import
|
|
21348
|
+
import path23 from "path";
|
|
21194
21349
|
|
|
21195
21350
|
// src/orchestration/orchestrator-namespace-scope.ts
|
|
21196
|
-
import
|
|
21351
|
+
import path22 from "path";
|
|
21197
21352
|
function computeSemanticDedupScope(targetStorage, config) {
|
|
21198
21353
|
if (!resolveNamespaceCapabilities(config).namespaces) return {};
|
|
21199
|
-
const memoryDir =
|
|
21200
|
-
const storageDir =
|
|
21354
|
+
const memoryDir = path22.resolve(config.memoryDir);
|
|
21355
|
+
const storageDir = path22.resolve(targetStorage.dir);
|
|
21201
21356
|
if (storageDir === memoryDir) {
|
|
21202
21357
|
return { pathExcludePrefixes: ["namespaces/"] };
|
|
21203
21358
|
}
|
|
21204
|
-
let rel =
|
|
21359
|
+
let rel = path22.relative(memoryDir, storageDir);
|
|
21205
21360
|
if (!rel || rel.startsWith("..")) {
|
|
21206
21361
|
log.debug(
|
|
21207
21362
|
`semantic dedup: target storage dir ${storageDir} is outside memoryDir ${memoryDir}; scoping lookup to absolute path prefix`
|
|
@@ -21254,7 +21409,7 @@ var NamespaceReadFanoutCoordinator = class {
|
|
|
21254
21409
|
loadNamespaceStorageDirHintsFromCatalog() {
|
|
21255
21410
|
if (this.deps.namespaceStorageDirHintsLoaded || !this.deps.namespaceCatalog.enabled) return;
|
|
21256
21411
|
this.deps.namespaceStorageDirHintsLoaded = true;
|
|
21257
|
-
const catalogPath =
|
|
21412
|
+
const catalogPath = path23.join(this.deps.config.memoryDir, "state", "namespaces.jsonl");
|
|
21258
21413
|
if (!existsSync(catalogPath)) return;
|
|
21259
21414
|
let body;
|
|
21260
21415
|
try {
|
|
@@ -21291,7 +21446,7 @@ var NamespaceReadFanoutCoordinator = class {
|
|
|
21291
21446
|
if (!this.deps.storageDirMatchesNamespaceHint(record.namespace, record.storageDir)) {
|
|
21292
21447
|
continue;
|
|
21293
21448
|
}
|
|
21294
|
-
const resolvedStorageDir =
|
|
21449
|
+
const resolvedStorageDir = path23.resolve(record.storageDir);
|
|
21295
21450
|
const current = preferredByStorageDir.get(resolvedStorageDir);
|
|
21296
21451
|
preferredByStorageDir.set(
|
|
21297
21452
|
resolvedStorageDir,
|
|
@@ -21476,12 +21631,12 @@ var NamespaceReadFanoutCoordinator = class {
|
|
|
21476
21631
|
}
|
|
21477
21632
|
async resolveStateDirForNamespace(namespace) {
|
|
21478
21633
|
if (!resolveNamespaceCapabilities(this.deps.config).namespaces) {
|
|
21479
|
-
return
|
|
21634
|
+
return path23.join(this.deps.config.memoryDir, "state");
|
|
21480
21635
|
}
|
|
21481
21636
|
if (namespace !== this.deps.config.defaultNamespace) {
|
|
21482
|
-
return
|
|
21637
|
+
return path23.join(this.deps.config.memoryDir, "namespaces", namespace, "state");
|
|
21483
21638
|
}
|
|
21484
|
-
const candidate =
|
|
21639
|
+
const candidate = path23.join(
|
|
21485
21640
|
this.deps.config.memoryDir,
|
|
21486
21641
|
"namespaces",
|
|
21487
21642
|
this.deps.config.defaultNamespace
|
|
@@ -21489,11 +21644,11 @@ var NamespaceReadFanoutCoordinator = class {
|
|
|
21489
21644
|
try {
|
|
21490
21645
|
const candidateStat = await stat3(candidate);
|
|
21491
21646
|
if (candidateStat.isDirectory()) {
|
|
21492
|
-
return
|
|
21647
|
+
return path23.join(candidate, "state");
|
|
21493
21648
|
}
|
|
21494
21649
|
} catch {
|
|
21495
21650
|
}
|
|
21496
|
-
return
|
|
21651
|
+
return path23.join(this.deps.config.memoryDir, "state");
|
|
21497
21652
|
}
|
|
21498
21653
|
namespaceFromPath(p) {
|
|
21499
21654
|
if (!resolveNamespaceCapabilities(this.deps.config).namespaces) return this.deps.config.defaultNamespace;
|
|
@@ -21874,19 +22029,6 @@ var Orchestrator = class {
|
|
|
21874
22029
|
* (rule 11) — these hang off the orchestrator instance.
|
|
21875
22030
|
*/
|
|
21876
22031
|
faithfulnessCounters = createFaithfulnessCounters();
|
|
21877
|
-
/**
|
|
21878
|
-
* Side-channel: number of facts deferred in the most recent
|
|
21879
|
-
* `persistExtraction` call (issue #562, PR 2). The caller reads this after
|
|
21880
|
-
* `persistExtraction` returns to decide whether to retain buffer turns for
|
|
21881
|
-
* the next extraction pass. Not part of the return signature because many
|
|
21882
|
-
* callers already destructure `persistedIds` by position.
|
|
21883
|
-
*/
|
|
21884
|
-
lastPersistExtractionDeferredCount = 0;
|
|
21885
|
-
/**
|
|
21886
|
-
* Side-channel (#1635): pending_review persisted ids from the last
|
|
21887
|
-
* persistExtraction; runExtraction excludes them from the thread episode set.
|
|
21888
|
-
*/
|
|
21889
|
-
lastPersistExtractionPendingReviewIds = [];
|
|
21890
22032
|
_fastGatewayLlm;
|
|
21891
22033
|
get fastGatewayLlm() {
|
|
21892
22034
|
return this._fastGatewayLlm;
|
|
@@ -21986,7 +22128,7 @@ var Orchestrator = class {
|
|
|
21986
22128
|
if (this.destroyed) throw new Error("orchestrator has been destroyed");
|
|
21987
22129
|
if (!this._dependencyPropagationDelivery) {
|
|
21988
22130
|
this._dependencyPropagationDelivery = new DependencyPropagationDelivery({
|
|
21989
|
-
queueRoot:
|
|
22131
|
+
queueRoot: path24.join(this.config.memoryDir, "state", "dependency-propagation"),
|
|
21990
22132
|
config: this.config,
|
|
21991
22133
|
extraction: this.extraction,
|
|
21992
22134
|
getStorage: (namespace) => this.getStorage(namespace),
|
|
@@ -22014,11 +22156,10 @@ var Orchestrator = class {
|
|
|
22014
22156
|
getCodingContextForSession: (sessionKey) => this.getCodingContextForSession(sessionKey),
|
|
22015
22157
|
applyCodingNamespaceOverlay: (sessionKey, namespace) => this.applyCodingNamespaceOverlay(sessionKey, namespace),
|
|
22016
22158
|
boxBuilderFor: (storage) => this.boxBuilderFor(storage),
|
|
22017
|
-
appendPersistedThreadEpisodes: (threadId, ids) => this.appendPersistedThreadEpisodes(threadId, ids),
|
|
22159
|
+
appendPersistedThreadEpisodes: (threadId, ids, pendingReviewIds) => this.appendPersistedThreadEpisodes(threadId, ids, pendingReviewIds),
|
|
22018
22160
|
maybeScheduleConsolidation: (nonZero) => this.maybeScheduleConsolidation(nonZero),
|
|
22019
22161
|
requestQmdMaintenance: () => this.requestQmdMaintenance(),
|
|
22020
22162
|
runTierMigrationCycle: (storage, trigger, options) => this.runTierMigrationCycle(storage, trigger, options),
|
|
22021
|
-
getLastPersistExtractionDeferredCount: () => this.lastPersistExtractionDeferredCount,
|
|
22022
22163
|
recordProcessedExtractionFingerprint: (storage, fingerprint, preloadedMeta) => this.recordProcessedExtractionFingerprint(storage, fingerprint, preloadedMeta)
|
|
22023
22164
|
});
|
|
22024
22165
|
}
|
|
@@ -22067,12 +22208,6 @@ var Orchestrator = class {
|
|
|
22067
22208
|
getJudgeDeferCounts: () => this.judgeDeferCounts,
|
|
22068
22209
|
getFaithfulnessCounters: () => this.faithfulnessCounters,
|
|
22069
22210
|
getEmbeddingFallback: () => this.embeddingFallback,
|
|
22070
|
-
setLastPersistExtractionDeferredCount: (v) => {
|
|
22071
|
-
this.lastPersistExtractionDeferredCount = v;
|
|
22072
|
-
},
|
|
22073
|
-
setLastPersistExtractionPendingReviewIds: (ids) => {
|
|
22074
|
-
this.lastPersistExtractionPendingReviewIds = ids;
|
|
22075
|
-
},
|
|
22076
22211
|
addContentHashDedup: (targetStorage, content) => this.addContentHashDedup(targetStorage, content),
|
|
22077
22212
|
hasContentHashDedup: (targetStorage, content) => this.hasContentHashDedup(targetStorage, content),
|
|
22078
22213
|
backfillTemporalBoundsOnDedupHit: (targetStorage, dedupContent, bounds, entityRef, sourceConnector) => this.backfillTemporalBoundsOnDedupHit(targetStorage, dedupContent, bounds, entityRef, sourceConnector),
|
|
@@ -22344,7 +22479,7 @@ var Orchestrator = class {
|
|
|
22344
22479
|
const defaultNs = normalizeNamespaceIdentity(this.config.defaultNamespace);
|
|
22345
22480
|
if (ns !== defaultNs && !isSafeRouteNamespace(ns)) return;
|
|
22346
22481
|
if (!this.storageDirMatchesNamespaceHint(ns, storageDir)) return;
|
|
22347
|
-
const resolvedStorageDir =
|
|
22482
|
+
const resolvedStorageDir = path24.resolve(storageDir);
|
|
22348
22483
|
let hints = this.namespaceStorageDirHints.get(resolvedStorageDir);
|
|
22349
22484
|
if (!hints) {
|
|
22350
22485
|
hints = /* @__PURE__ */ new Set();
|
|
@@ -22355,21 +22490,21 @@ var Orchestrator = class {
|
|
|
22355
22490
|
storageDirMatchesNamespaceHint(namespace, storageDir) {
|
|
22356
22491
|
const ns = normalizeNamespaceIdentity(namespace);
|
|
22357
22492
|
if (!ns) return false;
|
|
22358
|
-
const resolvedStorageDir =
|
|
22359
|
-
const resolvedMemoryDir =
|
|
22493
|
+
const resolvedStorageDir = path24.resolve(storageDir);
|
|
22494
|
+
const resolvedMemoryDir = path24.resolve(this.config.memoryDir);
|
|
22360
22495
|
const defaultNs = normalizeNamespaceIdentity(this.config.defaultNamespace);
|
|
22361
22496
|
if (resolvedStorageDir === resolvedMemoryDir) return ns === defaultNs;
|
|
22362
|
-
const resolvedNamespacesDir =
|
|
22497
|
+
const resolvedNamespacesDir = path24.join(resolvedMemoryDir, "namespaces");
|
|
22363
22498
|
if (!isPathInsideStorageRoot(resolvedNamespacesDir, resolvedStorageDir)) return false;
|
|
22364
|
-
const rawRoot =
|
|
22365
|
-
const tokenRoot =
|
|
22499
|
+
const rawRoot = path24.resolve(resolvedNamespacesDir, ns);
|
|
22500
|
+
const tokenRoot = path24.resolve(resolvedNamespacesDir, namespaceIdentityToken(ns));
|
|
22366
22501
|
return resolvedStorageDir === rawRoot || resolvedStorageDir === tokenRoot;
|
|
22367
22502
|
}
|
|
22368
22503
|
namespaceStorageDirHintOwnershipRank(record, resolvedStorageDir, configured) {
|
|
22369
|
-
if (resolvedStorageDir ===
|
|
22504
|
+
if (resolvedStorageDir === path24.resolve(this.config.memoryDir)) {
|
|
22370
22505
|
return record.namespace === normalizeNamespaceIdentity(this.config.defaultNamespace) ? 0 : 3;
|
|
22371
22506
|
}
|
|
22372
|
-
const leaf =
|
|
22507
|
+
const leaf = path24.basename(resolvedStorageDir);
|
|
22373
22508
|
const tokenOwnsRoot = namespaceIdentityToken(record.namespace) === leaf;
|
|
22374
22509
|
if (tokenOwnsRoot && configured.has(record.namespace)) return 0;
|
|
22375
22510
|
if (record.namespace === leaf) return 1;
|
|
@@ -22510,7 +22645,7 @@ var Orchestrator = class {
|
|
|
22510
22645
|
StorageManager.setOkfConformanceDefault(config.memoryDir, config.okf?.conformanceEnabled);
|
|
22511
22646
|
this.profiler = new ProfilingCollector({
|
|
22512
22647
|
enabled: resolvePipelineProcessingCapabilities(this.config).profiling,
|
|
22513
|
-
storageDir: config.profilingStorageDir ||
|
|
22648
|
+
storageDir: config.profilingStorageDir || path24.join(config.memoryDir, "profiling"),
|
|
22514
22649
|
maxTraces: config.profilingMaxTraces
|
|
22515
22650
|
});
|
|
22516
22651
|
this.namespaceCatalog = new NamespaceCatalog(config);
|
|
@@ -22588,7 +22723,7 @@ var Orchestrator = class {
|
|
|
22588
22723
|
bindStorage(this.storage, this.config.defaultNamespace);
|
|
22589
22724
|
this.storageRouter.onStorageCreated = bindStorage;
|
|
22590
22725
|
this.storageRouter.forEachCachedStorage(bindStorage);
|
|
22591
|
-
this.extractionQueueCoordinator = new ExtractionQueueCoordinator();
|
|
22726
|
+
this.extractionQueueCoordinator = new ExtractionQueueCoordinator(config.extractionQueueConcurrency);
|
|
22592
22727
|
this.recallResultFormatter = new RecallResultFormatter(this.config);
|
|
22593
22728
|
const conversationIndexRuntime = createConversationIndexRuntime(config, {
|
|
22594
22729
|
getQmd: () => this.conversationQmd,
|
|
@@ -22601,7 +22736,7 @@ var Orchestrator = class {
|
|
|
22601
22736
|
this.compounding = resolveConsolidationCapabilities(config).compounding ? new CompoundingEngine(config, this.storage) : void 0;
|
|
22602
22737
|
this.buffer = new SmartBuffer(config, this.storage);
|
|
22603
22738
|
this.transcript = new TranscriptManager(config);
|
|
22604
|
-
this.conversationIndexDir =
|
|
22739
|
+
this.conversationIndexDir = path24.join(
|
|
22605
22740
|
config.memoryDir,
|
|
22606
22741
|
"conversation-index",
|
|
22607
22742
|
"chunks"
|
|
@@ -22752,7 +22887,7 @@ var Orchestrator = class {
|
|
|
22752
22887
|
getHandleHistory: () => this.handleHistory
|
|
22753
22888
|
});
|
|
22754
22889
|
this.threading = new ThreadingManager(
|
|
22755
|
-
|
|
22890
|
+
path24.join(config.memoryDir, "threads"),
|
|
22756
22891
|
config.threadingGapMinutes
|
|
22757
22892
|
);
|
|
22758
22893
|
const lifecycleCaps = resolveMemoryLifecycleCapabilities(config);
|
|
@@ -23712,7 +23847,7 @@ ${doc.content}` : doc.content,
|
|
|
23712
23847
|
this.maintenanceScheduler.requestQmdMaintenanceForTool(reason);
|
|
23713
23848
|
}
|
|
23714
23849
|
async persistExtraction(result, storage, threadIdForExtraction, sourceContext, baseNamespace, scopeProfileWritePlan, sourceText, graphCaps = resolveGraphConstructionCapabilities(this.config), lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config)) {
|
|
23715
|
-
|
|
23850
|
+
return await this.extractionPersistCoordinator.persistExtraction(
|
|
23716
23851
|
result,
|
|
23717
23852
|
storage,
|
|
23718
23853
|
threadIdForExtraction,
|
|
@@ -23723,15 +23858,13 @@ ${doc.content}` : doc.content,
|
|
|
23723
23858
|
graphCaps,
|
|
23724
23859
|
lifecycleCaps
|
|
23725
23860
|
);
|
|
23726
|
-
return { persistedIds, memoryPathById };
|
|
23727
23861
|
}
|
|
23728
23862
|
/**
|
|
23729
23863
|
* Append persisted ids to the thread episode set, excluding pending_review
|
|
23730
23864
|
* fact ids (#1635) so they don't re-seed predecessor edges. Fail-open like
|
|
23731
23865
|
* the raw appendEpisodeIds call it replaces.
|
|
23732
23866
|
*/
|
|
23733
|
-
async appendPersistedThreadEpisodes(threadId, persistedIds) {
|
|
23734
|
-
const pendingReviewIds = this.lastPersistExtractionPendingReviewIds ?? [];
|
|
23867
|
+
async appendPersistedThreadEpisodes(threadId, persistedIds, pendingReviewIds) {
|
|
23735
23868
|
const episodeIds = pendingReviewIds.length > 0 ? persistedIds.filter((id) => !pendingReviewIds.includes(id)) : persistedIds;
|
|
23736
23869
|
if (episodeIds.length === 0) return;
|
|
23737
23870
|
try {
|
|
@@ -24868,9 +25001,9 @@ function readStructuralSymbol(entry) {
|
|
|
24868
25001
|
const rec = entry;
|
|
24869
25002
|
const symbol = typeof rec.symbol === "string" ? rec.symbol.trim() : "";
|
|
24870
25003
|
if (!symbol) return null;
|
|
24871
|
-
const
|
|
25004
|
+
const path42 = typeof rec.path === "string" && rec.path.length > 0 ? rec.path : void 0;
|
|
24872
25005
|
const kind = typeof rec.kind === "string" && rec.kind.length > 0 ? rec.kind : void 0;
|
|
24873
|
-
const item =
|
|
25006
|
+
const item = path42 !== void 0 && kind !== void 0 ? { symbol, path: path42, kind } : path42 !== void 0 ? { symbol, path: path42 } : kind !== void 0 ? { symbol, kind } : { symbol };
|
|
24874
25007
|
return item;
|
|
24875
25008
|
}
|
|
24876
25009
|
function classifySpawnError(err) {
|
|
@@ -24944,7 +25077,7 @@ var DEFAULT_GRACE_PERIOD_DAYS = 7;
|
|
|
24944
25077
|
|
|
24945
25078
|
// src/binary-lifecycle/backend.ts
|
|
24946
25079
|
import fsp2 from "fs/promises";
|
|
24947
|
-
import
|
|
25080
|
+
import path25 from "path";
|
|
24948
25081
|
var FilesystemBackend = class {
|
|
24949
25082
|
type = "filesystem";
|
|
24950
25083
|
basePath;
|
|
@@ -24952,19 +25085,19 @@ var FilesystemBackend = class {
|
|
|
24952
25085
|
if (!basePath || basePath.trim().length === 0) {
|
|
24953
25086
|
throw new Error("FilesystemBackend requires a non-empty basePath");
|
|
24954
25087
|
}
|
|
24955
|
-
this.basePath =
|
|
25088
|
+
this.basePath = path25.resolve(basePath);
|
|
24956
25089
|
}
|
|
24957
25090
|
resolveRemotePath(remotePath) {
|
|
24958
|
-
const resolved =
|
|
24959
|
-
const relative =
|
|
24960
|
-
if (relative === ".." || relative.startsWith(`..${
|
|
25091
|
+
const resolved = path25.isAbsolute(remotePath) ? path25.resolve(remotePath) : path25.resolve(this.basePath, remotePath);
|
|
25092
|
+
const relative = path25.relative(this.basePath, resolved);
|
|
25093
|
+
if (relative === ".." || relative.startsWith(`..${path25.sep}`) || path25.isAbsolute(relative)) {
|
|
24961
25094
|
throw new Error(`FilesystemBackend remotePath escapes basePath: ${JSON.stringify(remotePath)}`);
|
|
24962
25095
|
}
|
|
24963
25096
|
return resolved;
|
|
24964
25097
|
}
|
|
24965
25098
|
isInsideBase(candidate, realBase) {
|
|
24966
|
-
const relative =
|
|
24967
|
-
return relative === "" || relative !== ".." && !relative.startsWith(`..${
|
|
25099
|
+
const relative = path25.relative(realBase, candidate);
|
|
25100
|
+
return relative === "" || relative !== ".." && !relative.startsWith(`..${path25.sep}`) && !path25.isAbsolute(relative);
|
|
24968
25101
|
}
|
|
24969
25102
|
async realBasePathIfExists() {
|
|
24970
25103
|
try {
|
|
@@ -24993,13 +25126,13 @@ var FilesystemBackend = class {
|
|
|
24993
25126
|
}
|
|
24994
25127
|
async ensureSafeParentDirectory(dest) {
|
|
24995
25128
|
const realBase = await this.ensureBaseDirectory();
|
|
24996
|
-
const destDir =
|
|
24997
|
-
const relativeDir =
|
|
24998
|
-
const segments = relativeDir === "" ? [] : relativeDir.split(
|
|
25129
|
+
const destDir = path25.dirname(dest);
|
|
25130
|
+
const relativeDir = path25.relative(this.basePath, destDir);
|
|
25131
|
+
const segments = relativeDir === "" ? [] : relativeDir.split(path25.sep);
|
|
24999
25132
|
let current = this.basePath;
|
|
25000
25133
|
for (const segment of segments) {
|
|
25001
25134
|
if (segment === "." || segment === "") continue;
|
|
25002
|
-
current =
|
|
25135
|
+
current = path25.join(current, segment);
|
|
25003
25136
|
try {
|
|
25004
25137
|
const stat5 = await fsp2.lstat(current);
|
|
25005
25138
|
if (stat5.isSymbolicLink()) {
|
|
@@ -25027,13 +25160,13 @@ var FilesystemBackend = class {
|
|
|
25027
25160
|
if (realBase === null) {
|
|
25028
25161
|
return null;
|
|
25029
25162
|
}
|
|
25030
|
-
const destDir =
|
|
25031
|
-
const relativeDir =
|
|
25032
|
-
const segments = relativeDir === "" ? [] : relativeDir.split(
|
|
25163
|
+
const destDir = path25.dirname(dest);
|
|
25164
|
+
const relativeDir = path25.relative(this.basePath, destDir);
|
|
25165
|
+
const segments = relativeDir === "" ? [] : relativeDir.split(path25.sep);
|
|
25033
25166
|
let current = this.basePath;
|
|
25034
25167
|
for (const segment of segments) {
|
|
25035
25168
|
if (segment === "." || segment === "") continue;
|
|
25036
|
-
current =
|
|
25169
|
+
current = path25.join(current, segment);
|
|
25037
25170
|
let stat5;
|
|
25038
25171
|
try {
|
|
25039
25172
|
stat5 = await fsp2.lstat(current);
|
|
@@ -25081,7 +25214,7 @@ var FilesystemBackend = class {
|
|
|
25081
25214
|
return dest;
|
|
25082
25215
|
}
|
|
25083
25216
|
async upload(localPath, remotePath) {
|
|
25084
|
-
if (
|
|
25217
|
+
if (path25.isAbsolute(remotePath)) {
|
|
25085
25218
|
throw new Error(`FilesystemBackend upload remotePath must be relative: ${JSON.stringify(remotePath)}`);
|
|
25086
25219
|
}
|
|
25087
25220
|
const dest = this.resolveRemotePath(remotePath);
|
|
@@ -25154,7 +25287,7 @@ function createBackend(cfg) {
|
|
|
25154
25287
|
|
|
25155
25288
|
// src/binary-lifecycle/scanner.ts
|
|
25156
25289
|
import fsp3 from "fs/promises";
|
|
25157
|
-
import
|
|
25290
|
+
import path26 from "path";
|
|
25158
25291
|
import crypto from "crypto";
|
|
25159
25292
|
function matchesPatterns(filename, patterns) {
|
|
25160
25293
|
const lower = filename.toLowerCase();
|
|
@@ -25179,8 +25312,8 @@ async function scanForBinaries(memoryDir, config, manifest) {
|
|
|
25179
25312
|
return;
|
|
25180
25313
|
}
|
|
25181
25314
|
for (const entry of entries) {
|
|
25182
|
-
const fullPath =
|
|
25183
|
-
const relativePath =
|
|
25315
|
+
const fullPath = path26.join(dir, entry.name);
|
|
25316
|
+
const relativePath = path26.relative(memoryDir, fullPath).split(path26.sep).join("/");
|
|
25184
25317
|
if (entry.isDirectory()) {
|
|
25185
25318
|
if (entry.name === ".binary-lifecycle") continue;
|
|
25186
25319
|
await walk(fullPath);
|
|
@@ -25220,15 +25353,15 @@ async function hashFile(filePath) {
|
|
|
25220
25353
|
|
|
25221
25354
|
// src/binary-lifecycle/manifest.ts
|
|
25222
25355
|
import fsp4 from "fs/promises";
|
|
25223
|
-
import
|
|
25356
|
+
import path27 from "path";
|
|
25224
25357
|
import crypto2 from "crypto";
|
|
25225
25358
|
var MANIFEST_DIR = ".binary-lifecycle";
|
|
25226
25359
|
var MANIFEST_FILE = "manifest.json";
|
|
25227
25360
|
function manifestDir(memoryDir) {
|
|
25228
|
-
return
|
|
25361
|
+
return path27.join(memoryDir, MANIFEST_DIR);
|
|
25229
25362
|
}
|
|
25230
25363
|
function manifestPath(memoryDir) {
|
|
25231
|
-
return
|
|
25364
|
+
return path27.join(memoryDir, MANIFEST_DIR, MANIFEST_FILE);
|
|
25232
25365
|
}
|
|
25233
25366
|
async function readManifest(memoryDir) {
|
|
25234
25367
|
const filePath = manifestPath(memoryDir);
|
|
@@ -25280,13 +25413,13 @@ function emptyManifest() {
|
|
|
25280
25413
|
|
|
25281
25414
|
// src/binary-lifecycle/pipeline.ts
|
|
25282
25415
|
import fsp5 from "fs/promises";
|
|
25283
|
-
import
|
|
25416
|
+
import path28 from "path";
|
|
25284
25417
|
import crypto3 from "crypto";
|
|
25285
25418
|
var historicalIdCache = new HistoricalEntityCanonicalIdCache();
|
|
25286
25419
|
function isRecallCorpusMarkdown(mdPath, memoryDir) {
|
|
25287
|
-
const rel =
|
|
25288
|
-
if (rel.startsWith("..") ||
|
|
25289
|
-
const top = rel.split(
|
|
25420
|
+
const rel = path28.relative(memoryDir, mdPath);
|
|
25421
|
+
if (rel.startsWith("..") || path28.isAbsolute(rel)) return false;
|
|
25422
|
+
const top = rel.split(path28.sep)[0];
|
|
25290
25423
|
return RECALL_FALLBACK_DIRS.includes(top);
|
|
25291
25424
|
}
|
|
25292
25425
|
async function hashFile2(filePath) {
|
|
@@ -25310,13 +25443,13 @@ function escapeRegex(s) {
|
|
|
25310
25443
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
25311
25444
|
}
|
|
25312
25445
|
function resolveManifestAssetPath(memoryDir, originalPath) {
|
|
25313
|
-
if (originalPath.length === 0 || originalPath.includes("\0") || originalPath.includes("\\") ||
|
|
25446
|
+
if (originalPath.length === 0 || originalPath.includes("\0") || originalPath.includes("\\") || path28.isAbsolute(originalPath) || path28.win32.isAbsolute(originalPath)) {
|
|
25314
25447
|
return null;
|
|
25315
25448
|
}
|
|
25316
|
-
const memoryRoot =
|
|
25317
|
-
const fullPath =
|
|
25318
|
-
const relative =
|
|
25319
|
-
if (relative === "" || relative === ".." || relative.startsWith(`..${
|
|
25449
|
+
const memoryRoot = path28.resolve(memoryDir);
|
|
25450
|
+
const fullPath = path28.resolve(memoryRoot, originalPath);
|
|
25451
|
+
const relative = path28.relative(memoryRoot, fullPath);
|
|
25452
|
+
if (relative === "" || relative === ".." || relative.startsWith(`..${path28.sep}`) || path28.isAbsolute(relative)) {
|
|
25320
25453
|
return null;
|
|
25321
25454
|
}
|
|
25322
25455
|
return fullPath;
|
|
@@ -25327,7 +25460,7 @@ function validateBinaryLifecycleConfig(config) {
|
|
|
25327
25460
|
}
|
|
25328
25461
|
}
|
|
25329
25462
|
function remotePathForAsset(backend, relPath) {
|
|
25330
|
-
const normalized = relPath.split(
|
|
25463
|
+
const normalized = relPath.split(path28.sep).join("/");
|
|
25331
25464
|
if (backend.type === "filesystem") {
|
|
25332
25465
|
return `.binary-lifecycle/mirrors/${normalized}`;
|
|
25333
25466
|
}
|
|
@@ -25340,11 +25473,11 @@ async function stageMirror(memoryDir, newPaths, backend, assets, log2, dryRun) {
|
|
|
25340
25473
|
let mirrored = 0;
|
|
25341
25474
|
const errors = [];
|
|
25342
25475
|
for (const relPath of newPaths) {
|
|
25343
|
-
const fullPath =
|
|
25476
|
+
const fullPath = path28.join(memoryDir, relPath);
|
|
25344
25477
|
try {
|
|
25345
25478
|
const stat5 = await fsp5.stat(fullPath);
|
|
25346
25479
|
const contentHash = await hashFile2(fullPath);
|
|
25347
|
-
const ext =
|
|
25480
|
+
const ext = path28.extname(relPath);
|
|
25348
25481
|
const mimeType = guessMimeType(ext);
|
|
25349
25482
|
const remotePath = remotePathForAsset(backend, relPath);
|
|
25350
25483
|
let backendLocation = remotePath;
|
|
@@ -25495,7 +25628,7 @@ async function stageRedirect(memoryDir, assets, log2, dryRun, readMarkdownFile,
|
|
|
25495
25628
|
for (const update of updates) {
|
|
25496
25629
|
try {
|
|
25497
25630
|
await withRawEntityPageMutation(memoryDir, update.mdPath, async () => {
|
|
25498
|
-
const stateDir =
|
|
25631
|
+
const stateDir = path28.join(memoryDir, "state");
|
|
25499
25632
|
const kind = classifyEntityRefWritePath(memoryDir, update.mdPath);
|
|
25500
25633
|
if (kind === "memory") {
|
|
25501
25634
|
const idsAtWrite = historicalIdCache.get(stateDir);
|
|
@@ -25588,10 +25721,10 @@ async function countRemainingLocalReferences(memoryDir, asset, assetAbsolute, md
|
|
|
25588
25721
|
return { remaining, errors };
|
|
25589
25722
|
}
|
|
25590
25723
|
function markdownReferencePattern(asset, assetAbsolute, mdPath) {
|
|
25591
|
-
const mdDir =
|
|
25724
|
+
const mdDir = path28.dirname(mdPath);
|
|
25592
25725
|
const candidates = /* @__PURE__ */ new Set();
|
|
25593
25726
|
const addCandidate = (candidate) => {
|
|
25594
|
-
const normalized = candidate.split(
|
|
25727
|
+
const normalized = candidate.split(path28.sep).join("/");
|
|
25595
25728
|
if (normalized.length === 0) return;
|
|
25596
25729
|
candidates.add(normalized);
|
|
25597
25730
|
const isParentTraversal = normalized === ".." || normalized.startsWith("../");
|
|
@@ -25599,10 +25732,10 @@ function markdownReferencePattern(asset, assetAbsolute, mdPath) {
|
|
|
25599
25732
|
candidates.add(`./${normalized}`);
|
|
25600
25733
|
}
|
|
25601
25734
|
};
|
|
25602
|
-
addCandidate(
|
|
25603
|
-
const originalPath = asset.originalPath.split(
|
|
25604
|
-
const originalAsFileRelative =
|
|
25605
|
-
if (
|
|
25735
|
+
addCandidate(path28.relative(mdDir, assetAbsolute));
|
|
25736
|
+
const originalPath = asset.originalPath.split(path28.sep).join("/");
|
|
25737
|
+
const originalAsFileRelative = path28.resolve(mdDir, ...originalPath.split("/"));
|
|
25738
|
+
if (path28.resolve(originalAsFileRelative) === path28.resolve(assetAbsolute)) {
|
|
25606
25739
|
addCandidate(originalPath);
|
|
25607
25740
|
}
|
|
25608
25741
|
addCandidate(`/${originalPath}`);
|
|
@@ -25698,7 +25831,7 @@ async function findMarkdownFiles(dir) {
|
|
|
25698
25831
|
return;
|
|
25699
25832
|
}
|
|
25700
25833
|
for (const entry of entries) {
|
|
25701
|
-
const full =
|
|
25834
|
+
const full = path28.join(current, entry.name);
|
|
25702
25835
|
if (entry.isDirectory()) {
|
|
25703
25836
|
if (entry.name === ".binary-lifecycle") continue;
|
|
25704
25837
|
await walk(full);
|
|
@@ -25773,7 +25906,7 @@ async function runBinaryLifecyclePipeline(memoryDir, config, backend, log2, opts
|
|
|
25773
25906
|
|
|
25774
25907
|
// src/projection/index.ts
|
|
25775
25908
|
import fs from "fs";
|
|
25776
|
-
import
|
|
25909
|
+
import path29 from "path";
|
|
25777
25910
|
var VALID_PROJECTION_CATEGORIES = new Set(ALL_CATEGORY_KEYS);
|
|
25778
25911
|
async function generateContextTree(options) {
|
|
25779
25912
|
const startTime = Date.now();
|
|
@@ -25788,8 +25921,8 @@ async function generateContextTree(options) {
|
|
|
25788
25921
|
let nodesGenerated = 0;
|
|
25789
25922
|
let nodesSkipped = 0;
|
|
25790
25923
|
const categoryCounts = {};
|
|
25791
|
-
const resolvedMemoryDir =
|
|
25792
|
-
const resolvedOutputDir =
|
|
25924
|
+
const resolvedMemoryDir = path29.resolve(memoryDir);
|
|
25925
|
+
const resolvedOutputDir = path29.resolve(outputDir);
|
|
25793
25926
|
const requestedCategories = validateProjectionCategories(filterCategories);
|
|
25794
25927
|
const realMemoryDir = assertSafeMemoryRoot(resolvedMemoryDir);
|
|
25795
25928
|
assertNotSymlink(resolvedOutputDir, "context tree outputDir");
|
|
@@ -25827,7 +25960,7 @@ async function generateContextTree(options) {
|
|
|
25827
25960
|
}
|
|
25828
25961
|
}
|
|
25829
25962
|
if (includeEntities) {
|
|
25830
|
-
const entitiesDir =
|
|
25963
|
+
const entitiesDir = path29.join(memoryDir, "entities");
|
|
25831
25964
|
if (fs.existsSync(entitiesDir)) {
|
|
25832
25965
|
assertSafeInputRoot(realMemoryDir, entitiesDir, "entities root");
|
|
25833
25966
|
categoryCounts["entity"] = 0;
|
|
@@ -25839,7 +25972,7 @@ async function generateContextTree(options) {
|
|
|
25839
25972
|
continue;
|
|
25840
25973
|
}
|
|
25841
25974
|
const content = fs.readFileSync(filePath, "utf8");
|
|
25842
|
-
const fileName =
|
|
25975
|
+
const fileName = path29.basename(filePath, ".md");
|
|
25843
25976
|
const node = projectEntityNode(fileName, content);
|
|
25844
25977
|
const outputPath = resolveContainedOutputPath(realOutputDir, "entities", `${fileName}.md`);
|
|
25845
25978
|
writeProjectedContent(realOutputDir, outputPath, node.content);
|
|
@@ -25851,7 +25984,7 @@ async function generateContextTree(options) {
|
|
|
25851
25984
|
}
|
|
25852
25985
|
const shouldIncludeQuestions = includeQuestions && (requestedCategories === void 0 || requestedCategories.includes("question"));
|
|
25853
25986
|
if (shouldIncludeQuestions) {
|
|
25854
|
-
const questionsDir =
|
|
25987
|
+
const questionsDir = path29.join(memoryDir, "questions");
|
|
25855
25988
|
if (fs.existsSync(questionsDir)) {
|
|
25856
25989
|
assertSafeInputRoot(realMemoryDir, questionsDir, "questions root");
|
|
25857
25990
|
categoryCounts["question"] = 0;
|
|
@@ -25892,8 +26025,8 @@ async function generateContextTree(options) {
|
|
|
25892
26025
|
};
|
|
25893
26026
|
}
|
|
25894
26027
|
function isPathInside(root, candidate) {
|
|
25895
|
-
const relative =
|
|
25896
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
26028
|
+
const relative = path29.relative(root, candidate);
|
|
26029
|
+
return relative === "" || !relative.startsWith("..") && !path29.isAbsolute(relative);
|
|
25897
26030
|
}
|
|
25898
26031
|
function assertNotSymlink(targetPath, label) {
|
|
25899
26032
|
try {
|
|
@@ -25930,12 +26063,12 @@ function assertSafeInputRoot(realMemoryDir, targetPath, label) {
|
|
|
25930
26063
|
}
|
|
25931
26064
|
function assertSafeOutputTarget(realOutputDir, outputPath) {
|
|
25932
26065
|
let current = realOutputDir;
|
|
25933
|
-
const relative =
|
|
25934
|
-
if (relative.startsWith("..") ||
|
|
26066
|
+
const relative = path29.relative(realOutputDir, outputPath);
|
|
26067
|
+
if (relative.startsWith("..") || path29.isAbsolute(relative)) {
|
|
25935
26068
|
throw new Error(`context tree output path escapes outputDir: ${outputPath}`);
|
|
25936
26069
|
}
|
|
25937
|
-
for (const segment of relative.split(
|
|
25938
|
-
current =
|
|
26070
|
+
for (const segment of relative.split(path29.sep).filter(Boolean)) {
|
|
26071
|
+
current = path29.join(current, segment);
|
|
25939
26072
|
try {
|
|
25940
26073
|
const stat5 = fs.lstatSync(current);
|
|
25941
26074
|
if (stat5.isSymbolicLink()) {
|
|
@@ -25965,17 +26098,17 @@ function validateProjectionCategories(categories) {
|
|
|
25965
26098
|
return validated;
|
|
25966
26099
|
}
|
|
25967
26100
|
function resolveContainedOutputPath(outputRoot, ...segments) {
|
|
25968
|
-
const resolved =
|
|
25969
|
-
const relative =
|
|
25970
|
-
if (relative === "" || !relative.startsWith("..") && !
|
|
26101
|
+
const resolved = path29.resolve(outputRoot, ...segments);
|
|
26102
|
+
const relative = path29.relative(outputRoot, resolved);
|
|
26103
|
+
if (relative === "" || !relative.startsWith("..") && !path29.isAbsolute(relative)) {
|
|
25971
26104
|
return resolved;
|
|
25972
26105
|
}
|
|
25973
26106
|
throw new Error(`context tree output path escapes outputDir: ${segments.join("/")}`);
|
|
25974
26107
|
}
|
|
25975
26108
|
function writeProjectedContent(realOutputDir, outputPath, generatedContent) {
|
|
25976
26109
|
assertSafeOutputTarget(realOutputDir, outputPath);
|
|
25977
|
-
fs.mkdirSync(
|
|
25978
|
-
const realParent = fs.realpathSync(
|
|
26110
|
+
fs.mkdirSync(path29.dirname(outputPath), { recursive: true });
|
|
26111
|
+
const realParent = fs.realpathSync(path29.dirname(outputPath));
|
|
25979
26112
|
if (!isPathInside(realOutputDir, realParent)) {
|
|
25980
26113
|
throw new Error(`context tree output path escapes outputDir: ${outputPath}`);
|
|
25981
26114
|
}
|
|
@@ -26014,7 +26147,7 @@ function walkR(dir, realMemoryDir) {
|
|
|
26014
26147
|
const results = [];
|
|
26015
26148
|
function walk(directory) {
|
|
26016
26149
|
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
26017
|
-
const fullPath =
|
|
26150
|
+
const fullPath = path29.join(directory, entry.name);
|
|
26018
26151
|
if (entry.isSymbolicLink()) {
|
|
26019
26152
|
throw new Error(`context tree input path contains symlink: ${fullPath}`);
|
|
26020
26153
|
}
|
|
@@ -26067,13 +26200,13 @@ function extractBody(content) {
|
|
|
26067
26200
|
}
|
|
26068
26201
|
function projectNode(filePath, category, fm, rawContent) {
|
|
26069
26202
|
const body = extractBody(rawContent);
|
|
26070
|
-
const fileName =
|
|
26071
|
-
const dateDir =
|
|
26203
|
+
const fileName = path29.basename(filePath, ".md");
|
|
26204
|
+
const dateDir = path29.basename(path29.dirname(filePath));
|
|
26072
26205
|
let relPath;
|
|
26073
26206
|
if (/^\d{4}-\d{2}-\d{2}$/.test(dateDir)) {
|
|
26074
|
-
relPath =
|
|
26207
|
+
relPath = path29.join(category, dateDir, `${fileName}.md`);
|
|
26075
26208
|
} else {
|
|
26076
|
-
relPath =
|
|
26209
|
+
relPath = path29.join(category, `${fileName}.md`);
|
|
26077
26210
|
}
|
|
26078
26211
|
const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
26079
26212
|
const md = `# ${fm.id}
|
|
@@ -26119,7 +26252,7 @@ function projectEntityNode(fileName, content) {
|
|
|
26119
26252
|
${content}
|
|
26120
26253
|
`;
|
|
26121
26254
|
return {
|
|
26122
|
-
path:
|
|
26255
|
+
path: path29.join("entities", `${fileName}.md`),
|
|
26123
26256
|
category: "entity",
|
|
26124
26257
|
title: fileName,
|
|
26125
26258
|
content: md,
|
|
@@ -26172,7 +26305,7 @@ function generateIndex(categoryCounts, outputDir) {
|
|
|
26172
26305
|
|
|
26173
26306
|
// src/onboarding/index.ts
|
|
26174
26307
|
import fs2 from "fs";
|
|
26175
|
-
import
|
|
26308
|
+
import path30 from "path";
|
|
26176
26309
|
var LANGUAGE_RULES = [
|
|
26177
26310
|
{
|
|
26178
26311
|
language: "TypeScript",
|
|
@@ -26274,7 +26407,7 @@ function onboard(options) {
|
|
|
26274
26407
|
maxDepth = 6,
|
|
26275
26408
|
excludeDirs = []
|
|
26276
26409
|
} = options;
|
|
26277
|
-
const directory =
|
|
26410
|
+
const directory = path30.resolve(options.directory ?? process.cwd());
|
|
26278
26411
|
let rootStat;
|
|
26279
26412
|
try {
|
|
26280
26413
|
rootStat = fs2.statSync(directory);
|
|
@@ -26316,7 +26449,7 @@ function walkDir(root, exclude, maxDepth) {
|
|
|
26316
26449
|
}
|
|
26317
26450
|
for (const entry of entries) {
|
|
26318
26451
|
if (exclude.has(entry.name)) continue;
|
|
26319
|
-
const fullPath =
|
|
26452
|
+
const fullPath = path30.join(dir, entry.name);
|
|
26320
26453
|
if (entry.isDirectory()) {
|
|
26321
26454
|
walk(fullPath, depth + 1);
|
|
26322
26455
|
} else if (entry.isFile()) {
|
|
@@ -26331,11 +26464,11 @@ function detectLanguages(files, root) {
|
|
|
26331
26464
|
const results = [];
|
|
26332
26465
|
const extCounts = /* @__PURE__ */ new Map();
|
|
26333
26466
|
for (const f of files) {
|
|
26334
|
-
const ext =
|
|
26467
|
+
const ext = path30.extname(f).toLowerCase();
|
|
26335
26468
|
if (ext) extCounts.set(ext, (extCounts.get(ext) ?? 0) + 1);
|
|
26336
26469
|
}
|
|
26337
26470
|
const rootFiles = new Set(
|
|
26338
|
-
files.filter((f) =>
|
|
26471
|
+
files.filter((f) => path30.dirname(f) === root).map((f) => path30.basename(f))
|
|
26339
26472
|
);
|
|
26340
26473
|
for (const rule of LANGUAGE_RULES) {
|
|
26341
26474
|
const evidence = [];
|
|
@@ -26379,7 +26512,7 @@ function detectLanguages(files, root) {
|
|
|
26379
26512
|
}
|
|
26380
26513
|
function detectShape(files, root) {
|
|
26381
26514
|
const rootFiles = new Set(
|
|
26382
|
-
files.filter((f) =>
|
|
26515
|
+
files.filter((f) => path30.dirname(f) === root).map((f) => path30.basename(f))
|
|
26383
26516
|
);
|
|
26384
26517
|
const rootDirs = /* @__PURE__ */ new Set();
|
|
26385
26518
|
try {
|
|
@@ -26390,7 +26523,7 @@ function detectShape(files, root) {
|
|
|
26390
26523
|
}
|
|
26391
26524
|
const evidence = [];
|
|
26392
26525
|
if (rootFiles.has("package.json")) {
|
|
26393
|
-
const pkg = readJsonSafe(
|
|
26526
|
+
const pkg = readJsonSafe(path30.join(root, "package.json"));
|
|
26394
26527
|
if (pkg?.workspaces) {
|
|
26395
26528
|
evidence.push("package.json has workspaces");
|
|
26396
26529
|
return { shape: "monorepo", evidence };
|
|
@@ -26404,13 +26537,13 @@ function detectShape(files, root) {
|
|
|
26404
26537
|
evidence.push("workspace manifest found");
|
|
26405
26538
|
return { shape: "workspace", evidence };
|
|
26406
26539
|
}
|
|
26407
|
-
const cargoToml = readTomlWorkspace(
|
|
26540
|
+
const cargoToml = readTomlWorkspace(path30.join(root, "Cargo.toml"));
|
|
26408
26541
|
if (cargoToml) {
|
|
26409
26542
|
evidence.push("Cargo.toml has workspace");
|
|
26410
26543
|
return { shape: "workspace", evidence };
|
|
26411
26544
|
}
|
|
26412
26545
|
if (rootFiles.has("package.json")) {
|
|
26413
|
-
const pkg = readJsonSafe(
|
|
26546
|
+
const pkg = readJsonSafe(path30.join(root, "package.json"));
|
|
26414
26547
|
if (pkg?.exports || pkg?.main) {
|
|
26415
26548
|
if (pkg?.bin) {
|
|
26416
26549
|
evidence.push("package.json has bin");
|
|
@@ -26444,8 +26577,8 @@ function discoverDocs(files, root) {
|
|
|
26444
26577
|
{ pattern: /^\.editorconfig$/i, kind: "config" }
|
|
26445
26578
|
];
|
|
26446
26579
|
for (const filePath of files) {
|
|
26447
|
-
const basename =
|
|
26448
|
-
const relPath =
|
|
26580
|
+
const basename = path30.basename(filePath).toLowerCase();
|
|
26581
|
+
const relPath = path30.relative(root, filePath);
|
|
26449
26582
|
let kind;
|
|
26450
26583
|
for (const { pattern, kind: k } of docPatterns) {
|
|
26451
26584
|
if (pattern.test(basename)) {
|
|
@@ -26457,7 +26590,7 @@ function discoverDocs(files, root) {
|
|
|
26457
26590
|
kind = "docs";
|
|
26458
26591
|
}
|
|
26459
26592
|
if (!kind && (basename.endsWith(".md") || basename.endsWith(".mdx"))) {
|
|
26460
|
-
if (
|
|
26593
|
+
if (path30.dirname(relPath) === "." || isUnderDocsDir(relPath)) {
|
|
26461
26594
|
kind = "docs";
|
|
26462
26595
|
}
|
|
26463
26596
|
}
|
|
@@ -26478,7 +26611,7 @@ function discoverDocs(files, root) {
|
|
|
26478
26611
|
return docs;
|
|
26479
26612
|
}
|
|
26480
26613
|
function isUnderDocsDir(relPath) {
|
|
26481
|
-
const parts = relPath.split(
|
|
26614
|
+
const parts = relPath.split(path30.sep);
|
|
26482
26615
|
return parts[0] === "docs" || parts[0] === "doc" || parts[0] === "documentation";
|
|
26483
26616
|
}
|
|
26484
26617
|
function buildPlan(languages, shape, docs, _root) {
|
|
@@ -26522,7 +26655,7 @@ function readTomlWorkspace(filePath) {
|
|
|
26522
26655
|
|
|
26523
26656
|
// src/curation/index.ts
|
|
26524
26657
|
import fs3 from "fs";
|
|
26525
|
-
import
|
|
26658
|
+
import path31 from "path";
|
|
26526
26659
|
import crypto4 from "crypto";
|
|
26527
26660
|
async function curate(options) {
|
|
26528
26661
|
const startTime = Date.now();
|
|
@@ -26613,12 +26746,12 @@ function resolveTargets(targetPath) {
|
|
|
26613
26746
|
const extensions = /* @__PURE__ */ new Set([".md", ".txt", ".mdx", ".rst"]);
|
|
26614
26747
|
function walk(dir) {
|
|
26615
26748
|
for (const entry of fs3.readdirSync(dir, { withFileTypes: true })) {
|
|
26616
|
-
const fullPath =
|
|
26749
|
+
const fullPath = path31.join(dir, entry.name);
|
|
26617
26750
|
if (entry.isDirectory()) {
|
|
26618
26751
|
if (entry.name !== "node_modules" && entry.name !== ".git") {
|
|
26619
26752
|
walk(fullPath);
|
|
26620
26753
|
}
|
|
26621
|
-
} else if (extensions.has(
|
|
26754
|
+
} else if (extensions.has(path31.extname(entry.name).toLowerCase())) {
|
|
26622
26755
|
results.push(fullPath);
|
|
26623
26756
|
}
|
|
26624
26757
|
}
|
|
@@ -26627,12 +26760,12 @@ function resolveTargets(targetPath) {
|
|
|
26627
26760
|
return results;
|
|
26628
26761
|
}
|
|
26629
26762
|
function resolveProvenanceRoot(targetPath) {
|
|
26630
|
-
const resolvedTarget =
|
|
26763
|
+
const resolvedTarget = path31.resolve(targetPath);
|
|
26631
26764
|
const stat5 = fs3.statSync(resolvedTarget);
|
|
26632
|
-
return stat5.isFile() ?
|
|
26765
|
+
return stat5.isFile() ? path31.dirname(resolvedTarget) : resolvedTarget;
|
|
26633
26766
|
}
|
|
26634
26767
|
function extractStatements(content, filePath, projectRoot, source, sourceFileHash, categoryOverride, confidence, entityRef, tags) {
|
|
26635
|
-
const relativePath =
|
|
26768
|
+
const relativePath = path31.relative(projectRoot, path31.resolve(filePath)) || path31.basename(filePath);
|
|
26636
26769
|
const statements = [];
|
|
26637
26770
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
26638
26771
|
const paragraphs = content.split(/\n{2,}/).map((p) => p.trim()).filter((p) => p.length > 20 && p.length < 2e3);
|
|
@@ -26726,7 +26859,7 @@ function loadExistingMemories(memoryDir) {
|
|
|
26726
26859
|
if (!fs3.existsSync(memoryDir)) return result;
|
|
26727
26860
|
const dirs = ALL_CATEGORY_DIRS;
|
|
26728
26861
|
for (const dir of dirs) {
|
|
26729
|
-
const fullDir =
|
|
26862
|
+
const fullDir = path31.join(memoryDir, dir);
|
|
26730
26863
|
if (!fs3.existsSync(fullDir)) continue;
|
|
26731
26864
|
walkFiles(fullDir, (filePath) => {
|
|
26732
26865
|
const content = readFileSafe(filePath);
|
|
@@ -26749,11 +26882,11 @@ function writeStatement(stmt, memoryDir) {
|
|
|
26749
26882
|
const now = /* @__PURE__ */ new Date();
|
|
26750
26883
|
const dateDir = now.toISOString().split("T")[0];
|
|
26751
26884
|
const categoryDir = getCategoryDir(memoryDir, stmt.category);
|
|
26752
|
-
const dir =
|
|
26885
|
+
const dir = path31.join(categoryDir, dateDir);
|
|
26753
26886
|
fs3.mkdirSync(dir, { recursive: true });
|
|
26754
26887
|
const fileName = `${stmt.category}-${Date.now()}-${stmt.id.slice(0, 8)}.md`;
|
|
26755
|
-
const filePath =
|
|
26756
|
-
const historicalIds = historicalIdCache2.get(
|
|
26888
|
+
const filePath = path31.join(dir, fileName);
|
|
26889
|
+
const historicalIds = historicalIdCache2.get(path31.join(memoryDir, "state"));
|
|
26757
26890
|
const rawBody = `${[
|
|
26758
26891
|
"---",
|
|
26759
26892
|
`id: ${stmt.id}`,
|
|
@@ -26776,7 +26909,7 @@ ${stmt.content}
|
|
|
26776
26909
|
fs3.writeFileSync(filePath, body);
|
|
26777
26910
|
try {
|
|
26778
26911
|
repairContentAfterJournalMoveSync({
|
|
26779
|
-
stateDir:
|
|
26912
|
+
stateDir: path31.join(memoryDir, "state"),
|
|
26780
26913
|
cache: historicalIdCache2,
|
|
26781
26914
|
idsAtWrite: historicalIds,
|
|
26782
26915
|
rawContent: rawBody,
|
|
@@ -26837,7 +26970,7 @@ function extractBody2(content) {
|
|
|
26837
26970
|
}
|
|
26838
26971
|
function walkFiles(dir, callback) {
|
|
26839
26972
|
for (const entry of fs3.readdirSync(dir, { withFileTypes: true })) {
|
|
26840
|
-
const fullPath =
|
|
26973
|
+
const fullPath = path31.join(dir, entry.name);
|
|
26841
26974
|
if (entry.isDirectory()) {
|
|
26842
26975
|
walkFiles(fullPath, callback);
|
|
26843
26976
|
} else if (entry.name.endsWith(".md")) {
|
|
@@ -26848,7 +26981,7 @@ function walkFiles(dir, callback) {
|
|
|
26848
26981
|
|
|
26849
26982
|
// src/sync/index.ts
|
|
26850
26983
|
import fs4 from "fs";
|
|
26851
|
-
import
|
|
26984
|
+
import path32 from "path";
|
|
26852
26985
|
import crypto5 from "crypto";
|
|
26853
26986
|
var DEFAULT_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".txt", ".mdx", ".rst"]);
|
|
26854
26987
|
var DEFAULT_EXCLUDE2 = /* @__PURE__ */ new Set([
|
|
@@ -26870,7 +27003,7 @@ function syncChanges(options) {
|
|
|
26870
27003
|
} = options;
|
|
26871
27004
|
const extSet = new Set(extensions);
|
|
26872
27005
|
const excludeSet = /* @__PURE__ */ new Set([...DEFAULT_EXCLUDE2, ...excludeDirs]);
|
|
26873
|
-
const stateFilePath = options.stateFile ??
|
|
27006
|
+
const stateFilePath = options.stateFile ?? path32.join(memoryDir, ".sync-state.json");
|
|
26874
27007
|
const prevState = loadState(stateFilePath);
|
|
26875
27008
|
const currentFiles = scanFiles(sourceDir, extSet, excludeSet);
|
|
26876
27009
|
const changes = computeDiff(currentFiles, prevState.fileHashes, sourceDir);
|
|
@@ -26886,7 +27019,7 @@ function syncChanges(options) {
|
|
|
26886
27019
|
for (const [relPath, hash] of Object.entries(currentFiles)) {
|
|
26887
27020
|
newState.fileHashes[relPath] = hash;
|
|
26888
27021
|
}
|
|
26889
|
-
fs4.mkdirSync(
|
|
27022
|
+
fs4.mkdirSync(path32.dirname(stateFilePath), { recursive: true });
|
|
26890
27023
|
fs4.writeFileSync(stateFilePath, JSON.stringify(newState, null, 2));
|
|
26891
27024
|
}
|
|
26892
27025
|
return {
|
|
@@ -26952,13 +27085,13 @@ function scanFiles(root, extensions, exclude) {
|
|
|
26952
27085
|
}
|
|
26953
27086
|
for (const entry of entries) {
|
|
26954
27087
|
if (exclude.has(entry.name)) continue;
|
|
26955
|
-
const fullPath =
|
|
27088
|
+
const fullPath = path32.join(dir, entry.name);
|
|
26956
27089
|
if (entry.isDirectory()) {
|
|
26957
27090
|
walk(fullPath);
|
|
26958
27091
|
} else if (entry.isFile()) {
|
|
26959
|
-
const ext =
|
|
27092
|
+
const ext = path32.extname(entry.name).toLowerCase();
|
|
26960
27093
|
if (!extensions.has(ext)) continue;
|
|
26961
|
-
const relPath =
|
|
27094
|
+
const relPath = path32.relative(root, fullPath);
|
|
26962
27095
|
try {
|
|
26963
27096
|
const content = fs4.readFileSync(fullPath, "utf8");
|
|
26964
27097
|
result[relPath] = hashContent2(content);
|
|
@@ -26973,7 +27106,7 @@ function scanFiles(root, extensions, exclude) {
|
|
|
26973
27106
|
function computeDiff(current, previous, sourceDir) {
|
|
26974
27107
|
const changes = [];
|
|
26975
27108
|
for (const [relPath, hash] of Object.entries(current)) {
|
|
26976
|
-
const fullPath =
|
|
27109
|
+
const fullPath = path32.join(sourceDir, relPath);
|
|
26977
27110
|
if (!(relPath in previous)) {
|
|
26978
27111
|
let size = 0;
|
|
26979
27112
|
try {
|
|
@@ -27006,7 +27139,7 @@ function computeDiff(current, previous, sourceDir) {
|
|
|
27006
27139
|
for (const relPath of Object.keys(previous)) {
|
|
27007
27140
|
if (!(relPath in current)) {
|
|
27008
27141
|
changes.push({
|
|
27009
|
-
filePath:
|
|
27142
|
+
filePath: path32.join(sourceDir, relPath),
|
|
27010
27143
|
relativePath: relPath,
|
|
27011
27144
|
type: "deleted",
|
|
27012
27145
|
currentHash: "",
|
|
@@ -27036,21 +27169,21 @@ function hashContent2(content) {
|
|
|
27036
27169
|
import { spawnSync } from "child_process";
|
|
27037
27170
|
import crypto6 from "crypto";
|
|
27038
27171
|
import fs5 from "fs";
|
|
27039
|
-
import
|
|
27172
|
+
import path33 from "path";
|
|
27040
27173
|
var historicalIdCache3 = new HistoricalEntityCanonicalIdCache();
|
|
27041
27174
|
var MANIFEST_VERSION = 1;
|
|
27042
27175
|
var MANIFEST_LOCK_STALE_MS = 3e4;
|
|
27043
27176
|
var MANIFEST_LOCK_TIMEOUT_MS = MANIFEST_LOCK_STALE_MS + 1e4;
|
|
27044
27177
|
var MANIFEST_LOCK_SLEEP_MS = 20;
|
|
27045
27178
|
function normalizeSpaceMemoryDir(memoryDir) {
|
|
27046
|
-
return
|
|
27179
|
+
return path33.resolve(memoryDir);
|
|
27047
27180
|
}
|
|
27048
27181
|
function getSpacesDir(baseDir) {
|
|
27049
27182
|
const homeDir = baseDir ?? resolveHomeDir();
|
|
27050
|
-
return
|
|
27183
|
+
return path33.join(homeDir, ".config", "engram", "spaces");
|
|
27051
27184
|
}
|
|
27052
27185
|
function getManifestPath(baseDir) {
|
|
27053
|
-
return
|
|
27186
|
+
return path33.join(getSpacesDir(baseDir), "manifest.json");
|
|
27054
27187
|
}
|
|
27055
27188
|
function loadManifest(baseDir, memoryDirOverride) {
|
|
27056
27189
|
if (fs5.existsSync(getManifestPath(baseDir))) {
|
|
@@ -27097,9 +27230,9 @@ function readManifestUnlocked(baseDir, memoryDirOverride, options = {}) {
|
|
|
27097
27230
|
}
|
|
27098
27231
|
function saveManifestUnlocked(manifest, baseDir) {
|
|
27099
27232
|
const manifestPath2 = getManifestPath(baseDir);
|
|
27100
|
-
const manifestDir2 =
|
|
27233
|
+
const manifestDir2 = path33.dirname(manifestPath2);
|
|
27101
27234
|
fs5.mkdirSync(manifestDir2, { recursive: true });
|
|
27102
|
-
const tempPath =
|
|
27235
|
+
const tempPath = path33.join(manifestDir2, `.manifest.${process.pid}.${Date.now()}.${crypto6.randomUUID()}.tmp`);
|
|
27103
27236
|
try {
|
|
27104
27237
|
fs5.writeFileSync(tempPath, `${JSON.stringify(manifest, null, 2)}
|
|
27105
27238
|
`, { flag: "wx" });
|
|
@@ -27114,7 +27247,7 @@ function saveManifestUnlocked(manifest, baseDir) {
|
|
|
27114
27247
|
}
|
|
27115
27248
|
function withManifestLock(baseDir, operation) {
|
|
27116
27249
|
const lockDir = `${getManifestPath(baseDir)}.lock`;
|
|
27117
|
-
fs5.mkdirSync(
|
|
27250
|
+
fs5.mkdirSync(path33.dirname(lockDir), { recursive: true });
|
|
27118
27251
|
const lockOwner = acquireManifestLock(lockDir);
|
|
27119
27252
|
try {
|
|
27120
27253
|
return operation();
|
|
@@ -27140,7 +27273,7 @@ function acquireManifestLock(lockDir) {
|
|
|
27140
27273
|
try {
|
|
27141
27274
|
fs5.mkdirSync(lockDir, { recursive: false });
|
|
27142
27275
|
try {
|
|
27143
|
-
fs5.writeFileSync(
|
|
27276
|
+
fs5.writeFileSync(path33.join(lockDir, "owner"), `${owner}
|
|
27144
27277
|
`, { flag: "wx" });
|
|
27145
27278
|
} catch (error) {
|
|
27146
27279
|
fs5.rmSync(lockDir, { recursive: true, force: true });
|
|
@@ -27170,7 +27303,7 @@ function acquireManifestLock(lockDir) {
|
|
|
27170
27303
|
}
|
|
27171
27304
|
function releaseManifestLock(lockDir, owner) {
|
|
27172
27305
|
try {
|
|
27173
|
-
const ownerPath =
|
|
27306
|
+
const ownerPath = path33.join(lockDir, "owner");
|
|
27174
27307
|
if (fs5.readFileSync(ownerPath, "utf8").trim() === owner) {
|
|
27175
27308
|
fs5.rmSync(lockDir, { recursive: true, force: true });
|
|
27176
27309
|
}
|
|
@@ -27186,7 +27319,7 @@ function removeStaleManifestLock(lockDir) {
|
|
|
27186
27319
|
try {
|
|
27187
27320
|
fs5.mkdirSync(reclaimDir, { recursive: false });
|
|
27188
27321
|
try {
|
|
27189
|
-
fs5.writeFileSync(
|
|
27322
|
+
fs5.writeFileSync(path33.join(reclaimDir, "owner"), `${reclaimOwner}
|
|
27190
27323
|
`, { flag: "wx" });
|
|
27191
27324
|
} catch (error) {
|
|
27192
27325
|
fs5.rmSync(reclaimDir, { recursive: true, force: true });
|
|
@@ -27261,7 +27394,7 @@ function readManifestLockSnapshot(lockDir) {
|
|
|
27261
27394
|
throw error;
|
|
27262
27395
|
}
|
|
27263
27396
|
try {
|
|
27264
|
-
const owner = fs5.readFileSync(
|
|
27397
|
+
const owner = fs5.readFileSync(path33.join(lockDir, "owner"), "utf8").trim();
|
|
27265
27398
|
return { mtimeMs: stat5.mtimeMs, owner };
|
|
27266
27399
|
} catch (error) {
|
|
27267
27400
|
if (error.code === "ENOENT") {
|
|
@@ -27333,8 +27466,8 @@ function sleepSync(ms) {
|
|
|
27333
27466
|
}
|
|
27334
27467
|
function createPersonalSpace(baseDir, memoryDirOverride) {
|
|
27335
27468
|
const homeDir = baseDir ?? resolveHomeDir();
|
|
27336
|
-
const standalonePath =
|
|
27337
|
-
const openclawPath =
|
|
27469
|
+
const standalonePath = path33.join(homeDir, ".engram", "memory");
|
|
27470
|
+
const openclawPath = path33.join(homeDir, ".openclaw", "workspace", "memory", "local");
|
|
27338
27471
|
const memoryDir = memoryDirOverride ?? readEnvVar("REMNIC_MEMORY_DIR") ?? readEnvVar("ENGRAM_MEMORY_DIR") ?? (fs5.existsSync(standalonePath) ? standalonePath : fs5.existsSync(openclawPath) ? openclawPath : standalonePath);
|
|
27339
27472
|
const normalizedMemoryDir = normalizeSpaceMemoryDir(memoryDir);
|
|
27340
27473
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -27363,7 +27496,7 @@ function createSpace(options) {
|
|
|
27363
27496
|
const id = options.name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-");
|
|
27364
27497
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
27365
27498
|
const memoryDir = normalizeSpaceMemoryDir(
|
|
27366
|
-
options.memoryDir ??
|
|
27499
|
+
options.memoryDir ?? path33.join(getSpacesDir(options.baseDir), id, "memory")
|
|
27367
27500
|
);
|
|
27368
27501
|
const space = updateManifest(options.baseDir, (manifest) => {
|
|
27369
27502
|
if (manifest.spaces.some((s) => s.id === id)) {
|
|
@@ -27609,14 +27742,14 @@ async function mergeSpaces(sourceSpaceId, targetSpaceId, options) {
|
|
|
27609
27742
|
};
|
|
27610
27743
|
}
|
|
27611
27744
|
function getAuditLog(baseDir) {
|
|
27612
|
-
const auditPath =
|
|
27745
|
+
const auditPath = path33.join(getSpacesDir(baseDir), "audit.jsonl");
|
|
27613
27746
|
if (!fs5.existsSync(auditPath)) return [];
|
|
27614
27747
|
const lines = fs5.readFileSync(auditPath, "utf8").trim().split("\n");
|
|
27615
27748
|
return lines.filter((l) => l.trim()).map((l) => JSON.parse(l));
|
|
27616
27749
|
}
|
|
27617
27750
|
function appendAudit(entry, baseDir) {
|
|
27618
|
-
const auditPath =
|
|
27619
|
-
fs5.mkdirSync(
|
|
27751
|
+
const auditPath = path33.join(getSpacesDir(baseDir), "audit.jsonl");
|
|
27752
|
+
fs5.mkdirSync(path33.dirname(auditPath), { recursive: true });
|
|
27620
27753
|
const full = {
|
|
27621
27754
|
id: crypto6.randomUUID(),
|
|
27622
27755
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -27637,11 +27770,11 @@ async function copyMemories(sourceDir, targetDir, options) {
|
|
|
27637
27770
|
sourceFiles.filter((p) => {
|
|
27638
27771
|
const rp = safeRealpath(p);
|
|
27639
27772
|
if (!rp || !isPathInsideRoot(rp, sourceRoot)) return false;
|
|
27640
|
-
const rel =
|
|
27641
|
-
const mapped =
|
|
27773
|
+
const rel = path33.relative(sourceRoot, rp);
|
|
27774
|
+
const mapped = path33.resolve(targetRoot, rel);
|
|
27642
27775
|
if (!isPathInsideRoot(mapped, targetRoot)) return false;
|
|
27643
27776
|
return classifyEntityRefWritePath(targetRoot, mapped) === "entity";
|
|
27644
|
-
}).map((p) =>
|
|
27777
|
+
}).map((p) => path33.basename(p, ".md"))
|
|
27645
27778
|
);
|
|
27646
27779
|
const firstEntityId = sourceEntityIds.values().next().value;
|
|
27647
27780
|
if (firstEntityId === void 0) {
|
|
@@ -27649,7 +27782,7 @@ async function copyMemories(sourceDir, targetDir, options) {
|
|
|
27649
27782
|
}
|
|
27650
27783
|
return withRawEntityPageMutation(
|
|
27651
27784
|
targetRoot,
|
|
27652
|
-
|
|
27785
|
+
path33.join(targetRoot, "entities", `${firstEntityId}.md`),
|
|
27653
27786
|
async () => copyPreparedMemories(
|
|
27654
27787
|
sourceFiles,
|
|
27655
27788
|
sourceRoot,
|
|
@@ -27676,14 +27809,14 @@ function copyPreparedMemories(sourceFiles, sourceRoot, targetRoot, sourceEntityI
|
|
|
27676
27809
|
continue;
|
|
27677
27810
|
}
|
|
27678
27811
|
const content = fs5.readFileSync(sourcePath, "utf8");
|
|
27679
|
-
const relativePath =
|
|
27680
|
-
const targetPath =
|
|
27812
|
+
const relativePath = path33.relative(sourceRoot, sourceRealPath);
|
|
27813
|
+
const targetPath = path33.resolve(targetRoot, relativePath);
|
|
27681
27814
|
if (!isPathInsideRoot(targetPath, targetRoot)) {
|
|
27682
27815
|
skipped++;
|
|
27683
27816
|
continue;
|
|
27684
27817
|
}
|
|
27685
27818
|
const targetKind = classifyEntityRefWritePath(targetRoot, targetPath);
|
|
27686
|
-
const idsAtCompare = historicalIdCache3.get(
|
|
27819
|
+
const idsAtCompare = historicalIdCache3.get(path33.join(targetRoot, "state"));
|
|
27687
27820
|
const sourceRef = targetKind === "memory" ? readEntityRefFromFrontmatter(content) : null;
|
|
27688
27821
|
const refHasSourceClaimant = sourceRef !== null && sourceEntityIds.has(sourceRef);
|
|
27689
27822
|
const canonicalContent = targetKind === "memory" && !refHasSourceClaimant ? canonicalizeEntityRefFrontmatter(content, idsAtCompare) : content;
|
|
@@ -27710,7 +27843,7 @@ function copyPreparedMemories(sourceFiles, sourceRoot, targetRoot, sourceEntityI
|
|
|
27710
27843
|
if (fs5.existsSync(targetPath) && !options?.force) {
|
|
27711
27844
|
const targetContent = fs5.readFileSync(targetPath, "utf8");
|
|
27712
27845
|
const targetHash = hashContent3(targetContent);
|
|
27713
|
-
if (hashContent3(canonicalContent) === targetHash && historicalIdCache3.get(
|
|
27846
|
+
if (hashContent3(canonicalContent) === targetHash && historicalIdCache3.get(path33.join(targetRoot, "state")) === idsAtCompare) {
|
|
27714
27847
|
skipped++;
|
|
27715
27848
|
continue;
|
|
27716
27849
|
}
|
|
@@ -27726,13 +27859,13 @@ function copyPreparedMemories(sourceFiles, sourceRoot, targetRoot, sourceEntityI
|
|
|
27726
27859
|
continue;
|
|
27727
27860
|
}
|
|
27728
27861
|
}
|
|
27729
|
-
fs5.mkdirSync(
|
|
27730
|
-
const targetParentRealPath = safeRealpath(
|
|
27862
|
+
fs5.mkdirSync(path33.dirname(targetPath), { recursive: true });
|
|
27863
|
+
const targetParentRealPath = safeRealpath(path33.dirname(targetPath));
|
|
27731
27864
|
if (!targetParentRealPath || !isPathInsideRoot(targetParentRealPath, targetRoot)) {
|
|
27732
27865
|
skipped++;
|
|
27733
27866
|
continue;
|
|
27734
27867
|
}
|
|
27735
|
-
const stateDir =
|
|
27868
|
+
const stateDir = path33.join(targetRoot, "state");
|
|
27736
27869
|
if (targetKind === "memory" && !refHasSourceClaimant) {
|
|
27737
27870
|
const idsAtWrite = historicalIdCache3.get(stateDir);
|
|
27738
27871
|
const written = canonicalizeEntityRefFrontmatter(content, idsAtWrite);
|
|
@@ -27776,7 +27909,7 @@ function copyPreparedMemories(sourceFiles, sourceRoot, targetRoot, sourceEntityI
|
|
|
27776
27909
|
bumpMemoryCorpusVersionForDir(targetRoot);
|
|
27777
27910
|
}
|
|
27778
27911
|
if (reconcileNeeded) {
|
|
27779
|
-
requestEntityCanonicalIdReconcileSync(
|
|
27912
|
+
requestEntityCanonicalIdReconcileSync(path33.join(targetRoot, "state"));
|
|
27780
27913
|
}
|
|
27781
27914
|
return { merged, conflicts, skipped };
|
|
27782
27915
|
}
|
|
@@ -27787,7 +27920,7 @@ function walkMd(dir) {
|
|
|
27787
27920
|
const results = [];
|
|
27788
27921
|
function walk(d) {
|
|
27789
27922
|
for (const entry of fs5.readdirSync(d, { withFileTypes: true })) {
|
|
27790
|
-
const fullPath =
|
|
27923
|
+
const fullPath = path33.join(d, entry.name);
|
|
27791
27924
|
if (entry.isSymbolicLink()) {
|
|
27792
27925
|
continue;
|
|
27793
27926
|
}
|
|
@@ -27816,8 +27949,8 @@ function safeRealpath(filePath) {
|
|
|
27816
27949
|
}
|
|
27817
27950
|
}
|
|
27818
27951
|
function isPathInsideRoot(candidatePath, rootPath) {
|
|
27819
|
-
const relative =
|
|
27820
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
27952
|
+
const relative = path33.relative(rootPath, candidatePath);
|
|
27953
|
+
return relative === "" || !relative.startsWith("..") && !path33.isAbsolute(relative);
|
|
27821
27954
|
}
|
|
27822
27955
|
function parseSimpleFrontmatter(content) {
|
|
27823
27956
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
@@ -27938,7 +28071,7 @@ var REMNIC_RECALL_DECISION_RULES = `## When to Use Recall vs Direct Read
|
|
|
27938
28071
|
// src/memory-extension/codex-publisher.ts
|
|
27939
28072
|
import fs6 from "fs";
|
|
27940
28073
|
import os from "os";
|
|
27941
|
-
import
|
|
28074
|
+
import path34 from "path";
|
|
27942
28075
|
var REMNIC_EXTENSION_DIR_NAME = "remnic";
|
|
27943
28076
|
function resolveEnvHome(env) {
|
|
27944
28077
|
if (env === void 0) return resolveHomeDir();
|
|
@@ -27947,12 +28080,12 @@ function resolveEnvHome(env) {
|
|
|
27947
28080
|
function expandTildeWithHome(input, homeDir) {
|
|
27948
28081
|
if (input === "~") return homeDir;
|
|
27949
28082
|
if (input.startsWith("~/") || input.startsWith("~\\")) {
|
|
27950
|
-
return
|
|
28083
|
+
return path34.join(homeDir, input.slice(2));
|
|
27951
28084
|
}
|
|
27952
28085
|
return input;
|
|
27953
28086
|
}
|
|
27954
28087
|
function normalizeHostRoot(input, homeDir) {
|
|
27955
|
-
return
|
|
28088
|
+
return path34.resolve(expandTildeWithHome(input.trim(), homeDir));
|
|
27956
28089
|
}
|
|
27957
28090
|
var CodexMemoryExtensionPublisher = class {
|
|
27958
28091
|
hostId = "codex";
|
|
@@ -27966,12 +28099,12 @@ var CodexMemoryExtensionPublisher = class {
|
|
|
27966
28099
|
async resolveExtensionRoot(env) {
|
|
27967
28100
|
const homeDir = resolveEnvHome(env);
|
|
27968
28101
|
const codexHomeInput = env === void 0 ? readEnvVar("CODEX_HOME")?.trim() : env.CODEX_HOME?.trim();
|
|
27969
|
-
const codexHome = codexHomeInput ? normalizeHostRoot(codexHomeInput, homeDir) :
|
|
27970
|
-
return
|
|
28102
|
+
const codexHome = codexHomeInput ? normalizeHostRoot(codexHomeInput, homeDir) : path34.resolve(homeDir, ".codex");
|
|
28103
|
+
return path34.join(codexHome, "memories_extensions", REMNIC_EXTENSION_DIR_NAME);
|
|
27971
28104
|
}
|
|
27972
28105
|
async isHostAvailable() {
|
|
27973
28106
|
try {
|
|
27974
|
-
const home = readEnvVar("CODEX_HOME")?.trim() ||
|
|
28107
|
+
const home = readEnvVar("CODEX_HOME")?.trim() || path34.join(resolveHomeDir(), ".codex");
|
|
27975
28108
|
return fs6.existsSync(home);
|
|
27976
28109
|
} catch {
|
|
27977
28110
|
return false;
|
|
@@ -28022,7 +28155,7 @@ When running inside the Codex phase-2 consolidation sandbox:
|
|
|
28022
28155
|
}
|
|
28023
28156
|
async publish(ctx) {
|
|
28024
28157
|
const extensionRoot = await this.resolveExtensionRoot();
|
|
28025
|
-
const instructionsPath =
|
|
28158
|
+
const instructionsPath = path34.join(extensionRoot, "instructions.md");
|
|
28026
28159
|
const filesWritten = [];
|
|
28027
28160
|
const skipped = [];
|
|
28028
28161
|
ctx.log.info(`Publishing Codex memory extension to ${extensionRoot}`);
|
|
@@ -28654,9 +28787,9 @@ function buildWeeklyActivitySummary(cards, options) {
|
|
|
28654
28787
|
// src/activity/timeline/weekly-persist.ts
|
|
28655
28788
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
28656
28789
|
import { mkdirSync, readFileSync as readFileSync2, renameSync, unlinkSync, writeFileSync } from "fs";
|
|
28657
|
-
import
|
|
28790
|
+
import path35 from "path";
|
|
28658
28791
|
var WEEKLY_SNAPSHOT_FORMAT_VERSION = 1;
|
|
28659
|
-
var WEEKLY_SNAPSHOT_DIR =
|
|
28792
|
+
var WEEKLY_SNAPSHOT_DIR = path35.join("activity", "weekly");
|
|
28660
28793
|
function requireToken(value, name) {
|
|
28661
28794
|
if (typeof value !== "string" || value.trim().length === 0) {
|
|
28662
28795
|
throw new TypeError(`${name} must be a non-empty string`);
|
|
@@ -28679,8 +28812,8 @@ function weeklySnapshotPath(input) {
|
|
|
28679
28812
|
const identity = hashActivityBody(
|
|
28680
28813
|
`${input.summary.weekStartUtc}\0${input.summary.weekEndUtc}\0${sourceRevision}\0${configHash}`
|
|
28681
28814
|
);
|
|
28682
|
-
return
|
|
28683
|
-
|
|
28815
|
+
return path35.join(
|
|
28816
|
+
path35.resolve(memoryDir),
|
|
28684
28817
|
WEEKLY_SNAPSHOT_DIR,
|
|
28685
28818
|
namespaceIdentityToken(namespace),
|
|
28686
28819
|
`${weekDate}--${identity}.json`
|
|
@@ -28710,7 +28843,7 @@ function persistWeeklySnapshot(input) {
|
|
|
28710
28843
|
throw error;
|
|
28711
28844
|
}
|
|
28712
28845
|
}
|
|
28713
|
-
mkdirSync(
|
|
28846
|
+
mkdirSync(path35.dirname(filePath), { recursive: true, mode: 448 });
|
|
28714
28847
|
const tmpPath = `${filePath}.${process.pid}.${randomBytes3(8).toString("hex")}.tmp`;
|
|
28715
28848
|
writeFileSync(tmpPath, text, { encoding: "utf8", mode: 384 });
|
|
28716
28849
|
try {
|
|
@@ -29362,7 +29495,7 @@ function selectRecapForDay(input) {
|
|
|
29362
29495
|
|
|
29363
29496
|
// src/activity/journal-read.ts
|
|
29364
29497
|
import { closeSync, constants as fsConstants, fstatSync, lstatSync, openSync, readFileSync as readFileSync3, realpathSync, statSync as statSync2 } from "fs";
|
|
29365
|
-
import
|
|
29498
|
+
import path36 from "path";
|
|
29366
29499
|
|
|
29367
29500
|
// src/activity/journal-section.ts
|
|
29368
29501
|
function parseAtxHeading(line) {
|
|
@@ -29553,8 +29686,8 @@ function readJournalForDate(input) {
|
|
|
29553
29686
|
const relative = resolveVaultNotePath(input.vault.dailyNotePath, input.date, {
|
|
29554
29687
|
timezone: input.timezone
|
|
29555
29688
|
});
|
|
29556
|
-
const root =
|
|
29557
|
-
const filePath =
|
|
29689
|
+
const root = path36.resolve(expandTildePath(input.vault.vaultPath));
|
|
29690
|
+
const filePath = path36.join(root, relative);
|
|
29558
29691
|
try {
|
|
29559
29692
|
const rootStat = lstatSync(root);
|
|
29560
29693
|
if (rootStat.isSymbolicLink() || !rootStat.isDirectory()) {
|
|
@@ -29563,8 +29696,8 @@ function readJournalForDate(input) {
|
|
|
29563
29696
|
} catch {
|
|
29564
29697
|
return { ok: true, exists: false, reason: "missing_file", filePath };
|
|
29565
29698
|
}
|
|
29566
|
-
const lexical =
|
|
29567
|
-
if (lexical.length === 0 || lexical === ".." || lexical.startsWith(`..${
|
|
29699
|
+
const lexical = path36.relative(root, filePath);
|
|
29700
|
+
if (lexical.length === 0 || lexical === ".." || lexical.startsWith(`..${path36.sep}`) || path36.isAbsolute(lexical)) {
|
|
29568
29701
|
return { ok: false, reason: "path_escape", filePath };
|
|
29569
29702
|
}
|
|
29570
29703
|
if (!containedBySymlinks(root, filePath)) {
|
|
@@ -29597,11 +29730,11 @@ function containedBySymlinks(root, dest) {
|
|
|
29597
29730
|
try {
|
|
29598
29731
|
if (statSync2(probe).isFile() || statSync2(probe).isDirectory()) {
|
|
29599
29732
|
const real = realpathSync(probe);
|
|
29600
|
-
return real === realRoot || real.startsWith(`${realRoot}${
|
|
29733
|
+
return real === realRoot || real.startsWith(`${realRoot}${path36.sep}`);
|
|
29601
29734
|
}
|
|
29602
29735
|
} catch {
|
|
29603
29736
|
}
|
|
29604
|
-
const parent =
|
|
29737
|
+
const parent = path36.dirname(probe);
|
|
29605
29738
|
if (parent === probe) return false;
|
|
29606
29739
|
probe = parent;
|
|
29607
29740
|
}
|
|
@@ -29612,15 +29745,15 @@ function symlinkRejected() {
|
|
|
29612
29745
|
return err;
|
|
29613
29746
|
}
|
|
29614
29747
|
function readVerifiedDailyNote(root, filePath) {
|
|
29615
|
-
const relative =
|
|
29616
|
-
const parts = relative.split(
|
|
29748
|
+
const relative = path36.relative(root, filePath);
|
|
29749
|
+
const parts = relative.split(path36.sep).filter((part) => part.length > 0 && part !== ".");
|
|
29617
29750
|
let cursor = root;
|
|
29618
29751
|
for (const part of parts) {
|
|
29619
|
-
cursor =
|
|
29752
|
+
cursor = path36.join(cursor, part);
|
|
29620
29753
|
const st = lstatSync(cursor);
|
|
29621
29754
|
if (st.isSymbolicLink()) throw symlinkRejected();
|
|
29622
29755
|
}
|
|
29623
|
-
const parent =
|
|
29756
|
+
const parent = path36.dirname(filePath);
|
|
29624
29757
|
const parentLstat = lstatSync(parent);
|
|
29625
29758
|
if (parentLstat.isSymbolicLink() || !parentLstat.isDirectory()) throw symlinkRejected();
|
|
29626
29759
|
const nofollow = fsConstants.O_NOFOLLOW ?? 0;
|
|
@@ -29644,7 +29777,7 @@ function readVerifiedDailyNote(root, filePath) {
|
|
|
29644
29777
|
try {
|
|
29645
29778
|
const fdPath = realpathSync(`/proc/self/fd/${fd}`);
|
|
29646
29779
|
const realRoot = realpathSync(root);
|
|
29647
|
-
if (fdPath !== realRoot && !fdPath.startsWith(`${realRoot}${
|
|
29780
|
+
if (fdPath !== realRoot && !fdPath.startsWith(`${realRoot}${path36.sep}`)) {
|
|
29648
29781
|
throw symlinkRejected();
|
|
29649
29782
|
}
|
|
29650
29783
|
} catch (err) {
|
|
@@ -29659,11 +29792,11 @@ function readVerifiedDailyNote(root, filePath) {
|
|
|
29659
29792
|
// src/activity/journal-state.ts
|
|
29660
29793
|
import { createHash as createHash11, randomBytes as randomBytes4 } from "crypto";
|
|
29661
29794
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
29662
|
-
import
|
|
29795
|
+
import path37 from "path";
|
|
29663
29796
|
var STATE_DIR_NAME = "state";
|
|
29664
29797
|
var STATE_FILE_NAME = "timeline.json";
|
|
29665
29798
|
function timelineStatePath(memoryDir) {
|
|
29666
|
-
return
|
|
29799
|
+
return path37.join(memoryDir, STATE_DIR_NAME, STATE_FILE_NAME);
|
|
29667
29800
|
}
|
|
29668
29801
|
function hashJournalText(text) {
|
|
29669
29802
|
return createHash11("sha256").update(text, "utf8").digest("hex");
|
|
@@ -29689,14 +29822,14 @@ function readTimelineState(memoryDir) {
|
|
|
29689
29822
|
}
|
|
29690
29823
|
function writeTimelineState(memoryDir, state) {
|
|
29691
29824
|
const filePath = timelineStatePath(memoryDir);
|
|
29692
|
-
mkdirSync2(
|
|
29825
|
+
mkdirSync2(path37.dirname(filePath), { recursive: true });
|
|
29693
29826
|
const tempPath = `${filePath}.${process.pid}.${randomBytes4(8).toString("hex")}.tmp`;
|
|
29694
29827
|
writeFileSync2(tempPath, `${JSON.stringify(state, null, 2)}
|
|
29695
29828
|
`);
|
|
29696
29829
|
renameSync2(tempPath, filePath);
|
|
29697
29830
|
}
|
|
29698
29831
|
function journalDateLockPath(memoryDir, date) {
|
|
29699
|
-
return
|
|
29832
|
+
return path37.join(memoryDir, STATE_DIR_NAME, `journal-extract-${date}.lock`);
|
|
29700
29833
|
}
|
|
29701
29834
|
function timelineStateLockPath(memoryDir) {
|
|
29702
29835
|
return `${timelineStatePath(memoryDir)}.lock`;
|
|
@@ -30404,7 +30537,7 @@ function normalizeDropKeys(keys) {
|
|
|
30404
30537
|
}
|
|
30405
30538
|
|
|
30406
30539
|
// src/activity/vault-wikilink.ts
|
|
30407
|
-
import
|
|
30540
|
+
import path38 from "path";
|
|
30408
30541
|
function formatVaultWikilink(notePath) {
|
|
30409
30542
|
if (typeof notePath !== "string" || notePath.trim().length === 0) {
|
|
30410
30543
|
throw new RangeError("Vault wikilink path must be a non-empty relative path.");
|
|
@@ -30412,7 +30545,7 @@ function formatVaultWikilink(notePath) {
|
|
|
30412
30545
|
if (notePath.includes("\n") || notePath.includes("\r")) {
|
|
30413
30546
|
throw new RangeError("Vault wikilink path must not contain newlines.");
|
|
30414
30547
|
}
|
|
30415
|
-
if (
|
|
30548
|
+
if (path38.posix.isAbsolute(notePath) || path38.win32.isAbsolute(notePath)) {
|
|
30416
30549
|
throw new RangeError("Vault wikilink path must be relative; absolute paths are rejected.");
|
|
30417
30550
|
}
|
|
30418
30551
|
if (notePath.split(/[\\/]/).some((segment) => segment === "..")) {
|
|
@@ -30434,7 +30567,7 @@ function stripVaultMdSuffix(notePath) {
|
|
|
30434
30567
|
}
|
|
30435
30568
|
|
|
30436
30569
|
// src/activity/vault-join.ts
|
|
30437
|
-
import
|
|
30570
|
+
import path39 from "path";
|
|
30438
30571
|
function joinVaultSegments(parts) {
|
|
30439
30572
|
if (parts.length === 0) {
|
|
30440
30573
|
throw new RangeError("Vault path parts must be a non-empty list.");
|
|
@@ -30449,7 +30582,7 @@ function joinVaultSegments(parts) {
|
|
|
30449
30582
|
if (part.includes("\n") || part.includes("\r")) {
|
|
30450
30583
|
throw new RangeError("Vault path part must not contain a newline.");
|
|
30451
30584
|
}
|
|
30452
|
-
if (
|
|
30585
|
+
if (path39.posix.isAbsolute(part) || path39.win32.isAbsolute(part)) {
|
|
30453
30586
|
throw new RangeError("Vault path part must be relative.");
|
|
30454
30587
|
}
|
|
30455
30588
|
if (part.split("/").includes("..")) {
|
|
@@ -30504,7 +30637,7 @@ function planVaultDryRun(inputs) {
|
|
|
30504
30637
|
// src/session-summaries/index.ts
|
|
30505
30638
|
import { createHash as createHash12 } from "crypto";
|
|
30506
30639
|
import { lstat as lstat3, mkdir as mkdir7, readFile as readFile9, readdir as readdir4, rename, rm, stat as stat4, writeFile as writeFile7 } from "fs/promises";
|
|
30507
|
-
import
|
|
30640
|
+
import path40 from "path";
|
|
30508
30641
|
|
|
30509
30642
|
// src/session-summaries/adapters.ts
|
|
30510
30643
|
var VALID_ROLES = /* @__PURE__ */ new Set(["user", "assistant", "tool", "system", "other"]);
|
|
@@ -31009,7 +31142,7 @@ function shortHash(value, length = 16) {
|
|
|
31009
31142
|
async function listTranscriptFiles(root, maxFiles) {
|
|
31010
31143
|
const out = [];
|
|
31011
31144
|
let truncated = false;
|
|
31012
|
-
const entrySortKey = (entryName, isDirectory) => isDirectory ? `${entryName}${
|
|
31145
|
+
const entrySortKey = (entryName, isDirectory) => isDirectory ? `${entryName}${path40.sep}` : entryName;
|
|
31013
31146
|
async function visit(dir) {
|
|
31014
31147
|
if (truncated) return;
|
|
31015
31148
|
const entries = (await readdir4(dir, { withFileTypes: true })).sort(
|
|
@@ -31019,13 +31152,13 @@ async function listTranscriptFiles(root, maxFiles) {
|
|
|
31019
31152
|
if (truncated) return;
|
|
31020
31153
|
if (entry.name.startsWith(".")) continue;
|
|
31021
31154
|
if (entry.isSymbolicLink()) continue;
|
|
31022
|
-
const fullPath =
|
|
31155
|
+
const fullPath = path40.join(dir, entry.name);
|
|
31023
31156
|
if (entry.isDirectory()) {
|
|
31024
31157
|
await visit(fullPath);
|
|
31025
31158
|
continue;
|
|
31026
31159
|
}
|
|
31027
31160
|
if (!entry.isFile()) continue;
|
|
31028
|
-
const ext =
|
|
31161
|
+
const ext = path40.extname(entry.name).toLowerCase();
|
|
31029
31162
|
if (!SUPPORTED_EXTENSIONS.has(ext)) continue;
|
|
31030
31163
|
out.push(fullPath);
|
|
31031
31164
|
if (out.length > maxFiles) {
|
|
@@ -31052,7 +31185,7 @@ function normalizeInputDir(inputDir) {
|
|
|
31052
31185
|
if (typeof inputDir !== "string" || inputDir.trim().length === 0) {
|
|
31053
31186
|
throw new Error("inputDir must be a non-empty string");
|
|
31054
31187
|
}
|
|
31055
|
-
return
|
|
31188
|
+
return path40.resolve(expandTildePath(inputDir.trim()));
|
|
31056
31189
|
}
|
|
31057
31190
|
function initRoleCounts() {
|
|
31058
31191
|
return {
|
|
@@ -31209,11 +31342,11 @@ async function collectLocalSessionSummaries(options) {
|
|
|
31209
31342
|
continue;
|
|
31210
31343
|
}
|
|
31211
31344
|
seenFileHashes.add(fileHash);
|
|
31212
|
-
const fileExtension =
|
|
31345
|
+
const fileExtension = path40.extname(filePath).toLowerCase();
|
|
31213
31346
|
const parsed = await adapter.parseFile(
|
|
31214
31347
|
{
|
|
31215
31348
|
content,
|
|
31216
|
-
fileName:
|
|
31349
|
+
fileName: path40.basename(filePath),
|
|
31217
31350
|
fileExtension,
|
|
31218
31351
|
fileRef: fileHash
|
|
31219
31352
|
},
|
|
@@ -31269,7 +31402,7 @@ async function collectLocalSessionSummaries(options) {
|
|
|
31269
31402
|
}
|
|
31270
31403
|
async function readRedactionConfig(pathLike) {
|
|
31271
31404
|
if (!pathLike) return void 0;
|
|
31272
|
-
const raw = await readFile9(
|
|
31405
|
+
const raw = await readFile9(path40.resolve(expandTildePath(pathLike)), "utf-8");
|
|
31273
31406
|
const parsed = JSON.parse(raw);
|
|
31274
31407
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
31275
31408
|
throw new Error("redaction config must be a JSON object");
|
|
@@ -31282,15 +31415,15 @@ function toJsonl(drafts) {
|
|
|
31282
31415
|
}
|
|
31283
31416
|
function defaultDraftOutputPath(memoryDir, generatedAt) {
|
|
31284
31417
|
const stamp = generatedAt.replace(/[:.]/g, "-");
|
|
31285
|
-
return
|
|
31286
|
-
|
|
31418
|
+
return path40.join(
|
|
31419
|
+
path40.resolve(expandTildePath(memoryDir)),
|
|
31287
31420
|
"state",
|
|
31288
31421
|
"session-summary-drafts",
|
|
31289
31422
|
`session-summaries-${stamp}.jsonl`
|
|
31290
31423
|
);
|
|
31291
31424
|
}
|
|
31292
31425
|
async function writeDrafts(filePath, drafts) {
|
|
31293
|
-
await mkdir7(
|
|
31426
|
+
await mkdir7(path40.dirname(filePath), { recursive: true });
|
|
31294
31427
|
const tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
31295
31428
|
try {
|
|
31296
31429
|
await writeFile7(tempPath, toJsonl(drafts), "utf-8");
|
|
@@ -31308,7 +31441,7 @@ async function runLocalSessionSummaryCliCommand(options) {
|
|
|
31308
31441
|
});
|
|
31309
31442
|
const wroteFiles = [];
|
|
31310
31443
|
if (options.output) {
|
|
31311
|
-
const outputPath =
|
|
31444
|
+
const outputPath = path40.resolve(expandTildePath(options.output));
|
|
31312
31445
|
await writeDrafts(outputPath, report.drafts);
|
|
31313
31446
|
wroteFiles.push(outputPath);
|
|
31314
31447
|
}
|
|
@@ -31343,19 +31476,19 @@ async function runLocalSessionSummaryCliCommand(options) {
|
|
|
31343
31476
|
|
|
31344
31477
|
// src/transfer/capsule-fork.ts
|
|
31345
31478
|
import { lstat as lstat4, mkdir as mkdir8, readFile as readFile10, realpath as realpath3, writeFile as writeFile8 } from "fs/promises";
|
|
31346
|
-
import
|
|
31479
|
+
import path41 from "path";
|
|
31347
31480
|
async function forkCapsule(opts) {
|
|
31348
31481
|
validateForkId(opts.forkId);
|
|
31349
|
-
const rootAbs =
|
|
31482
|
+
const rootAbs = path41.resolve(opts.targetRoot);
|
|
31350
31483
|
await assertIsDirectoryNotSymlink(rootAbs, "forkCapsule", "targetRoot");
|
|
31351
|
-
const forkDirAbs =
|
|
31484
|
+
const forkDirAbs = path41.join(rootAbs, "forks", opts.forkId);
|
|
31352
31485
|
const forkEntryExists = await pathEntryExists(forkDirAbs);
|
|
31353
31486
|
if (forkEntryExists) {
|
|
31354
31487
|
throw new Error(
|
|
31355
31488
|
`forkCapsule: fork path already exists \u2014 forkId "${opts.forkId}" is already in use at: ${forkDirAbs}`
|
|
31356
31489
|
);
|
|
31357
31490
|
}
|
|
31358
|
-
const archiveAbs =
|
|
31491
|
+
const archiveAbs = path41.resolve(opts.sourceArchive);
|
|
31359
31492
|
const importResult = await importCapsule({
|
|
31360
31493
|
archivePath: archiveAbs,
|
|
31361
31494
|
root: rootAbs,
|
|
@@ -31377,10 +31510,10 @@ async function forkCapsule(opts) {
|
|
|
31377
31510
|
importedRecords: importResult.imported.length,
|
|
31378
31511
|
skippedRecords: importResult.skipped.length
|
|
31379
31512
|
};
|
|
31380
|
-
const lineagePath =
|
|
31513
|
+
const lineagePath = path41.join(forkDirAbs, "lineage.json");
|
|
31381
31514
|
const rootReal = await realpath3(rootAbs);
|
|
31382
31515
|
await assertRealpathInsideRoot(rootReal, lineagePath, `forks/${opts.forkId}/lineage.json`, "forkCapsule");
|
|
31383
|
-
await mkdir8(
|
|
31516
|
+
await mkdir8(path41.dirname(lineagePath), { recursive: true });
|
|
31384
31517
|
await writeFile8(lineagePath, JSON.stringify(lineage, null, 2) + "\n", "utf-8");
|
|
31385
31518
|
return {
|
|
31386
31519
|
archivePath: archiveAbs,
|
|
@@ -31394,11 +31527,11 @@ async function readForkLineage(targetRoot, forkId) {
|
|
|
31394
31527
|
if (typeof forkId !== "string" || forkId.length === 0 || forkId.length > 64 || !CAPSULE_ID_PATTERN.test(forkId)) {
|
|
31395
31528
|
return null;
|
|
31396
31529
|
}
|
|
31397
|
-
const rootAbs =
|
|
31530
|
+
const rootAbs = path41.resolve(targetRoot);
|
|
31398
31531
|
const rootReal = await realpath3(rootAbs).catch(() => rootAbs);
|
|
31399
|
-
const lineagePath =
|
|
31400
|
-
const rel =
|
|
31401
|
-
if (rel.startsWith("..") ||
|
|
31532
|
+
const lineagePath = path41.join(rootReal, "forks", forkId, "lineage.json");
|
|
31533
|
+
const rel = path41.relative(rootReal, lineagePath);
|
|
31534
|
+
if (rel.startsWith("..") || path41.isAbsolute(rel)) {
|
|
31402
31535
|
return null;
|
|
31403
31536
|
}
|
|
31404
31537
|
if (!await isLineagePathContained(rootReal, lineagePath)) {
|
|
@@ -31439,19 +31572,19 @@ async function pathEntryExists(absPath) {
|
|
|
31439
31572
|
async function isLineagePathContained(rootReal, lineagePath) {
|
|
31440
31573
|
let existing = lineagePath;
|
|
31441
31574
|
const suffix = [];
|
|
31442
|
-
while (existing !==
|
|
31575
|
+
while (existing !== path41.dirname(existing)) {
|
|
31443
31576
|
const st = await lstat4(existing).catch(() => null);
|
|
31444
31577
|
if (st !== null) break;
|
|
31445
|
-
suffix.unshift(
|
|
31446
|
-
existing =
|
|
31578
|
+
suffix.unshift(path41.basename(existing));
|
|
31579
|
+
existing = path41.dirname(existing);
|
|
31447
31580
|
}
|
|
31448
31581
|
const existingReal = await realpath3(existing).catch(() => existing);
|
|
31449
|
-
const targetReal = suffix.length > 0 ?
|
|
31450
|
-
const rel =
|
|
31582
|
+
const targetReal = suffix.length > 0 ? path41.join(existingReal, ...suffix) : existingReal;
|
|
31583
|
+
const rel = path41.relative(rootReal, targetReal);
|
|
31451
31584
|
if (rel === "") return true;
|
|
31452
31585
|
if (rel === "..") return false;
|
|
31453
|
-
if (rel.startsWith(`..${
|
|
31454
|
-
if (
|
|
31586
|
+
if (rel.startsWith(`..${path41.sep}`)) return false;
|
|
31587
|
+
if (path41.isAbsolute(rel)) return false;
|
|
31455
31588
|
return true;
|
|
31456
31589
|
}
|
|
31457
31590
|
|
|
@@ -31644,4 +31777,4 @@ export {
|
|
|
31644
31777
|
qmdStartupCollectionChecksWithTimeout,
|
|
31645
31778
|
Orchestrator
|
|
31646
31779
|
};
|
|
31647
|
-
//# sourceMappingURL=chunk-
|
|
31780
|
+
//# sourceMappingURL=chunk-LFYEQK45.js.map
|