@graphorin/memory 0.5.0
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/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/README.md +401 -0
- package/dist/conflict/index.d.ts +3 -0
- package/dist/conflict/index.js +7 -0
- package/dist/conflict/locale-packs/en.js +262 -0
- package/dist/conflict/locale-packs/en.js.map +1 -0
- package/dist/conflict/locale-packs/index.js +4 -0
- package/dist/conflict/locale-packs/types.d.ts +103 -0
- package/dist/conflict/locale-packs/types.d.ts.map +1 -0
- package/dist/conflict/locale-packs/types.js +55 -0
- package/dist/conflict/locale-packs/types.js.map +1 -0
- package/dist/conflict/pipeline.d.ts +35 -0
- package/dist/conflict/pipeline.d.ts.map +1 -0
- package/dist/conflict/pipeline.js +257 -0
- package/dist/conflict/pipeline.js.map +1 -0
- package/dist/conflict/stages/helpers.js +66 -0
- package/dist/conflict/stages/helpers.js.map +1 -0
- package/dist/conflict/stages/stage1-exact-dedup.js +21 -0
- package/dist/conflict/stages/stage1-exact-dedup.js.map +1 -0
- package/dist/conflict/stages/stage2-embedding-three-zone.js +37 -0
- package/dist/conflict/stages/stage2-embedding-three-zone.js.map +1 -0
- package/dist/conflict/stages/stage3-heuristic-regex.js +45 -0
- package/dist/conflict/stages/stage3-heuristic-regex.js.map +1 -0
- package/dist/conflict/stages/stage4-subject-predicate.js +31 -0
- package/dist/conflict/stages/stage4-subject-predicate.js.map +1 -0
- package/dist/conflict/stages/stage5-defer-to-deep.js +22 -0
- package/dist/conflict/stages/stage5-defer-to-deep.js.map +1 -0
- package/dist/conflict/types.d.ts +222 -0
- package/dist/conflict/types.d.ts.map +1 -0
- package/dist/conflict/types.js +50 -0
- package/dist/conflict/types.js.map +1 -0
- package/dist/consolidator/budget.d.ts +1 -0
- package/dist/consolidator/budget.js +214 -0
- package/dist/consolidator/budget.js.map +1 -0
- package/dist/consolidator/decay.d.ts +35 -0
- package/dist/consolidator/decay.d.ts.map +1 -0
- package/dist/consolidator/decay.js +91 -0
- package/dist/consolidator/decay.js.map +1 -0
- package/dist/consolidator/dlq.js +58 -0
- package/dist/consolidator/dlq.js.map +1 -0
- package/dist/consolidator/errors.d.ts +54 -0
- package/dist/consolidator/errors.d.ts.map +1 -0
- package/dist/consolidator/errors.js +67 -0
- package/dist/consolidator/errors.js.map +1 -0
- package/dist/consolidator/idempotency.d.ts +1 -0
- package/dist/consolidator/idempotency.js +22 -0
- package/dist/consolidator/idempotency.js.map +1 -0
- package/dist/consolidator/index.d.ts +34 -0
- package/dist/consolidator/index.d.ts.map +1 -0
- package/dist/consolidator/index.js +163 -0
- package/dist/consolidator/index.js.map +1 -0
- package/dist/consolidator/lock.d.ts +2 -0
- package/dist/consolidator/lock.js +89 -0
- package/dist/consolidator/lock.js.map +1 -0
- package/dist/consolidator/noise-filter.d.ts +2 -0
- package/dist/consolidator/noise-filter.js +173 -0
- package/dist/consolidator/noise-filter.js.map +1 -0
- package/dist/consolidator/phases/deep.d.ts +4 -0
- package/dist/consolidator/phases/deep.js +198 -0
- package/dist/consolidator/phases/deep.js.map +1 -0
- package/dist/consolidator/phases/induce.d.ts +154 -0
- package/dist/consolidator/phases/induce.d.ts.map +1 -0
- package/dist/consolidator/phases/induce.js +253 -0
- package/dist/consolidator/phases/induce.js.map +1 -0
- package/dist/consolidator/phases/light.d.ts +4 -0
- package/dist/consolidator/phases/light.js +99 -0
- package/dist/consolidator/phases/light.js.map +1 -0
- package/dist/consolidator/phases/reflect.js +287 -0
- package/dist/consolidator/phases/reflect.js.map +1 -0
- package/dist/consolidator/phases/standard.d.ts +8 -0
- package/dist/consolidator/phases/standard.js +499 -0
- package/dist/consolidator/phases/standard.js.map +1 -0
- package/dist/consolidator/reconcile.js +192 -0
- package/dist/consolidator/reconcile.js.map +1 -0
- package/dist/consolidator/runtime.d.ts +62 -0
- package/dist/consolidator/runtime.d.ts.map +1 -0
- package/dist/consolidator/runtime.js +580 -0
- package/dist/consolidator/runtime.js.map +1 -0
- package/dist/consolidator/scheduler.d.ts +111 -0
- package/dist/consolidator/scheduler.d.ts.map +1 -0
- package/dist/consolidator/scheduler.js +71 -0
- package/dist/consolidator/scheduler.js.map +1 -0
- package/dist/consolidator/triggers.d.ts +40 -0
- package/dist/consolidator/triggers.d.ts.map +1 -0
- package/dist/consolidator/triggers.js +94 -0
- package/dist/consolidator/triggers.js.map +1 -0
- package/dist/consolidator/types.d.ts +397 -0
- package/dist/consolidator/types.d.ts.map +1 -0
- package/dist/consolidator/types.js +117 -0
- package/dist/consolidator/types.js.map +1 -0
- package/dist/context-engine/annotations.d.ts +118 -0
- package/dist/context-engine/annotations.d.ts.map +1 -0
- package/dist/context-engine/annotations.js +102 -0
- package/dist/context-engine/annotations.js.map +1 -0
- package/dist/context-engine/auto-recall.d.ts +52 -0
- package/dist/context-engine/auto-recall.d.ts.map +1 -0
- package/dist/context-engine/auto-recall.js +41 -0
- package/dist/context-engine/auto-recall.js.map +1 -0
- package/dist/context-engine/compaction/clear-tool-results.d.ts +55 -0
- package/dist/context-engine/compaction/clear-tool-results.d.ts.map +1 -0
- package/dist/context-engine/compaction/clear-tool-results.js +97 -0
- package/dist/context-engine/compaction/clear-tool-results.js.map +1 -0
- package/dist/context-engine/compaction/compactor.d.ts +52 -0
- package/dist/context-engine/compaction/compactor.d.ts.map +1 -0
- package/dist/context-engine/compaction/compactor.js +196 -0
- package/dist/context-engine/compaction/compactor.js.map +1 -0
- package/dist/context-engine/compaction/hooks/reanchor-persona-block.d.ts +15 -0
- package/dist/context-engine/compaction/hooks/reanchor-persona-block.d.ts.map +1 -0
- package/dist/context-engine/compaction/hooks/reanchor-persona-block.js +27 -0
- package/dist/context-engine/compaction/hooks/reanchor-persona-block.js.map +1 -0
- package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.d.ts +18 -0
- package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.d.ts.map +1 -0
- package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.js +47 -0
- package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.js.map +1 -0
- package/dist/context-engine/compaction/hooks/reanchor-project-rules.d.ts +15 -0
- package/dist/context-engine/compaction/hooks/reanchor-project-rules.d.ts.map +1 -0
- package/dist/context-engine/compaction/hooks/reanchor-project-rules.js +32 -0
- package/dist/context-engine/compaction/hooks/reanchor-project-rules.js.map +1 -0
- package/dist/context-engine/compaction/hooks/types.d.ts +42 -0
- package/dist/context-engine/compaction/hooks/types.d.ts.map +1 -0
- package/dist/context-engine/compaction/index.d.ts +9 -0
- package/dist/context-engine/compaction/index.js +9 -0
- package/dist/context-engine/compaction/templates/summary-9-section.d.ts +84 -0
- package/dist/context-engine/compaction/templates/summary-9-section.d.ts.map +1 -0
- package/dist/context-engine/compaction/templates/summary-9-section.js +84 -0
- package/dist/context-engine/compaction/templates/summary-9-section.js.map +1 -0
- package/dist/context-engine/compaction/thresholds.d.ts +68 -0
- package/dist/context-engine/compaction/thresholds.d.ts.map +1 -0
- package/dist/context-engine/compaction/thresholds.js +63 -0
- package/dist/context-engine/compaction/thresholds.js.map +1 -0
- package/dist/context-engine/compaction/types.d.ts +202 -0
- package/dist/context-engine/compaction/types.d.ts.map +1 -0
- package/dist/context-engine/engine.d.ts +258 -0
- package/dist/context-engine/engine.d.ts.map +1 -0
- package/dist/context-engine/engine.js +424 -0
- package/dist/context-engine/engine.js.map +1 -0
- package/dist/context-engine/index.d.ts +68 -0
- package/dist/context-engine/index.d.ts.map +1 -0
- package/dist/context-engine/index.js +24 -0
- package/dist/context-engine/locale-packs/en.d.ts +14 -0
- package/dist/context-engine/locale-packs/en.d.ts.map +1 -0
- package/dist/context-engine/locale-packs/en.js +87 -0
- package/dist/context-engine/locale-packs/en.js.map +1 -0
- package/dist/context-engine/locale-packs/index.js +4 -0
- package/dist/context-engine/locale-packs/resolver.d.ts +41 -0
- package/dist/context-engine/locale-packs/resolver.d.ts.map +1 -0
- package/dist/context-engine/locale-packs/resolver.js +119 -0
- package/dist/context-engine/locale-packs/resolver.js.map +1 -0
- package/dist/context-engine/locale-packs/types.d.ts +119 -0
- package/dist/context-engine/locale-packs/types.d.ts.map +1 -0
- package/dist/context-engine/locale-packs/types.js +24 -0
- package/dist/context-engine/locale-packs/types.js.map +1 -0
- package/dist/context-engine/metadata.d.ts +40 -0
- package/dist/context-engine/metadata.d.ts.map +1 -0
- package/dist/context-engine/metadata.js +66 -0
- package/dist/context-engine/metadata.js.map +1 -0
- package/dist/context-engine/preambles/inbound-en.d.ts +20 -0
- package/dist/context-engine/preambles/inbound-en.d.ts.map +1 -0
- package/dist/context-engine/preambles/inbound-en.js +23 -0
- package/dist/context-engine/preambles/inbound-en.js.map +1 -0
- package/dist/context-engine/privacy-filter.d.ts +108 -0
- package/dist/context-engine/privacy-filter.d.ts.map +1 -0
- package/dist/context-engine/privacy-filter.js +113 -0
- package/dist/context-engine/privacy-filter.js.map +1 -0
- package/dist/context-engine/templates/base-en.d.ts +19 -0
- package/dist/context-engine/templates/base-en.d.ts.map +1 -0
- package/dist/context-engine/templates/base-en.js +22 -0
- package/dist/context-engine/templates/base-en.js.map +1 -0
- package/dist/context-engine/templates/composer.d.ts +55 -0
- package/dist/context-engine/templates/composer.d.ts.map +1 -0
- package/dist/context-engine/templates/composer.js +51 -0
- package/dist/context-engine/templates/composer.js.map +1 -0
- package/dist/context-engine/token-budget.d.ts +99 -0
- package/dist/context-engine/token-budget.d.ts.map +1 -0
- package/dist/context-engine/token-budget.js +211 -0
- package/dist/context-engine/token-budget.js.map +1 -0
- package/dist/context-engine/token-counter.d.ts +54 -0
- package/dist/context-engine/token-counter.d.ts.map +1 -0
- package/dist/context-engine/token-counter.js +81 -0
- package/dist/context-engine/token-counter.js.map +1 -0
- package/dist/errors/index.d.ts +171 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +206 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/facade.d.ts +278 -0
- package/dist/facade.d.ts.map +1 -0
- package/dist/facade.js +265 -0
- package/dist/facade.js.map +1 -0
- package/dist/graph/entity-resolver.d.ts +135 -0
- package/dist/graph/entity-resolver.d.ts.map +1 -0
- package/dist/graph/entity-resolver.js +202 -0
- package/dist/graph/entity-resolver.js.map +1 -0
- package/dist/graph/index.d.ts +1 -0
- package/dist/index.d.ts +103 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/contextualize.d.ts +14 -0
- package/dist/internal/contextualize.d.ts.map +1 -0
- package/dist/internal/contextualize.js +110 -0
- package/dist/internal/contextualize.js.map +1 -0
- package/dist/internal/embedder-binding.js +50 -0
- package/dist/internal/embedder-binding.js.map +1 -0
- package/dist/internal/id.js +24 -0
- package/dist/internal/id.js.map +1 -0
- package/dist/internal/injection-heuristics.js +64 -0
- package/dist/internal/injection-heuristics.js.map +1 -0
- package/dist/internal/spans.js +35 -0
- package/dist/internal/spans.js.map +1 -0
- package/dist/internal/storage-adapter.d.ts +742 -0
- package/dist/internal/storage-adapter.d.ts.map +1 -0
- package/dist/migration/embedder-migration.d.ts +124 -0
- package/dist/migration/embedder-migration.d.ts.map +1 -0
- package/dist/migration/embedder-migration.js +109 -0
- package/dist/migration/embedder-migration.js.map +1 -0
- package/dist/migration/index.d.ts +2 -0
- package/dist/migration/index.js +3 -0
- package/dist/search/explain.d.ts +74 -0
- package/dist/search/explain.d.ts.map +1 -0
- package/dist/search/explain.js +50 -0
- package/dist/search/explain.js.map +1 -0
- package/dist/search/index.d.ts +6 -0
- package/dist/search/index.js +6 -0
- package/dist/search/iterative.d.ts +223 -0
- package/dist/search/iterative.d.ts.map +1 -0
- package/dist/search/iterative.js +330 -0
- package/dist/search/iterative.js.map +1 -0
- package/dist/search/query-transform.d.ts +112 -0
- package/dist/search/query-transform.d.ts.map +1 -0
- package/dist/search/query-transform.js +184 -0
- package/dist/search/query-transform.js.map +1 -0
- package/dist/search/rrf.d.ts +95 -0
- package/dist/search/rrf.d.ts.map +1 -0
- package/dist/search/rrf.js +166 -0
- package/dist/search/rrf.js.map +1 -0
- package/dist/search/types.d.ts +50 -0
- package/dist/search/types.d.ts.map +1 -0
- package/dist/tiers/episodic-memory.d.ts +142 -0
- package/dist/tiers/episodic-memory.d.ts.map +1 -0
- package/dist/tiers/episodic-memory.js +254 -0
- package/dist/tiers/episodic-memory.js.map +1 -0
- package/dist/tiers/index.d.ts +8 -0
- package/dist/tiers/index.js +9 -0
- package/dist/tiers/insight-memory.d.ts +71 -0
- package/dist/tiers/insight-memory.d.ts.map +1 -0
- package/dist/tiers/insight-memory.js +133 -0
- package/dist/tiers/insight-memory.js.map +1 -0
- package/dist/tiers/procedural-memory.d.ts +147 -0
- package/dist/tiers/procedural-memory.d.ts.map +1 -0
- package/dist/tiers/procedural-memory.js +267 -0
- package/dist/tiers/procedural-memory.js.map +1 -0
- package/dist/tiers/semantic-memory.d.ts +461 -0
- package/dist/tiers/semantic-memory.d.ts.map +1 -0
- package/dist/tiers/semantic-memory.js +631 -0
- package/dist/tiers/semantic-memory.js.map +1 -0
- package/dist/tiers/session-memory.d.ts +117 -0
- package/dist/tiers/session-memory.d.ts.map +1 -0
- package/dist/tiers/session-memory.js +163 -0
- package/dist/tiers/session-memory.js.map +1 -0
- package/dist/tiers/shared-memory.d.ts +29 -0
- package/dist/tiers/shared-memory.d.ts.map +1 -0
- package/dist/tiers/shared-memory.js +58 -0
- package/dist/tiers/shared-memory.js.map +1 -0
- package/dist/tiers/working-memory.d.ts +129 -0
- package/dist/tiers/working-memory.d.ts.map +1 -0
- package/dist/tiers/working-memory.js +229 -0
- package/dist/tiers/working-memory.js.map +1 -0
- package/dist/tools/block-tools.d.ts +98 -0
- package/dist/tools/block-tools.d.ts.map +1 -0
- package/dist/tools/block-tools.js +114 -0
- package/dist/tools/block-tools.js.map +1 -0
- package/dist/tools/fact-tools.d.ts +294 -0
- package/dist/tools/fact-tools.d.ts.map +1 -0
- package/dist/tools/fact-tools.js +293 -0
- package/dist/tools/fact-tools.js.map +1 -0
- package/dist/tools/index.d.ts +35 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +36 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/recall-tools.d.ts +209 -0
- package/dist/tools/recall-tools.d.ts.map +1 -0
- package/dist/tools/recall-tools.js +170 -0
- package/dist/tools/recall-tools.js.map +1 -0
- package/dist/tools/types.d.ts +40 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/package.json +119 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# @graphorin/memory
|
|
2
|
+
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Phase 10a — initial release of `@graphorin/memory`. Ships the
|
|
8
|
+
`createMemory()` facade with six tier sub-modules (working,
|
|
9
|
+
session, episodic, semantic, procedural, shared), nine memory
|
|
10
|
+
tools registered through `@graphorin/tools`, the built-in
|
|
11
|
+
`RRFReranker` with a pluggable `setReranker(...)` hook, the
|
|
12
|
+
embedder migration runner with `lock-on-first` / `multi-active` /
|
|
13
|
+
`auto-migrate` strategies, and the `compile()` / `metadata()` /
|
|
14
|
+
`consolidator` interface stubs picked up by Phases 10b / 10c /
|
|
15
|
+
10d.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Oleksiy Stepurenko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
# @graphorin/memory
|
|
2
|
+
|
|
3
|
+
> Six-tier memory system for the Graphorin framework — the heart of any
|
|
4
|
+
> long-living personal AI assistant built on top of Graphorin.
|
|
5
|
+
|
|
6
|
+
`@graphorin/memory` ships the `createMemory()` facade, the six tier
|
|
7
|
+
sub-modules (working, session, episodic, semantic, procedural, shared),
|
|
8
|
+
the eleven memory tools that the agent runtime registers with
|
|
9
|
+
`@graphorin/tools`, the built-in Reciprocal Rank Fusion reranker (k=60),
|
|
10
|
+
the embedder migration runner, and the interface stubs picked up later
|
|
11
|
+
by the conflict-resolution pipeline, the consolidator, and the context
|
|
12
|
+
engine.
|
|
13
|
+
|
|
14
|
+
The package depends on:
|
|
15
|
+
|
|
16
|
+
- `@graphorin/core` — typed contracts (`MemoryStore`, `EmbedderProvider`,
|
|
17
|
+
`Tool`, `Tracer`, `Sensitivity`, …).
|
|
18
|
+
- `@graphorin/observability` — the `Tracer` used to emit one `AISpan`
|
|
19
|
+
per memory operation.
|
|
20
|
+
- `@graphorin/security` — the memory-modification guard (`MemoryGuardTier`)
|
|
21
|
+
every memory tool is wired against.
|
|
22
|
+
- `@graphorin/tools` — the `tool({...})` builder used to declare the
|
|
23
|
+
ten memory tools.
|
|
24
|
+
- `zod` (peer) — schema typing for the memory tools.
|
|
25
|
+
|
|
26
|
+
Storage is provided by any `MemoryStore` implementation; the default
|
|
27
|
+
production adapter is `@graphorin/store-sqlite` (built on
|
|
28
|
+
`better-sqlite3@^12.9.0` + `sqlite-vec@~0.1.9`). Embeddings come from
|
|
29
|
+
any `EmbedderProvider`; the default is
|
|
30
|
+
`@graphorin/embedder-transformersjs` (multilingual e5 base, 768-dim).
|
|
31
|
+
|
|
32
|
+
## Highlights
|
|
33
|
+
|
|
34
|
+
- **`createMemory({ store, embedder, ...})` facade.** Wires the six
|
|
35
|
+
tiers + the tools array + the `compile()` / `metadata()` /
|
|
36
|
+
`consolidator` interface stubs in one call.
|
|
37
|
+
- **Six tier sub-modules.** Every tier exposes a typed CRUD surface and
|
|
38
|
+
emits one `AISpan` per operation. Writes are append-only (soft-delete
|
|
39
|
+
via `deletedAt` / `validTo`); supersede chains are first-class.
|
|
40
|
+
- **Hybrid search.** Semantic memory composes vector + FTS5 results
|
|
41
|
+
through the built-in `RRFReranker` (k=60 default). The
|
|
42
|
+
`setReranker(custom)` hook accepts any `ReRanker` implementation
|
|
43
|
+
(cross-encoder, LLM judge, custom).
|
|
44
|
+
- **Eleven memory tools.** `block_append`, `block_replace`,
|
|
45
|
+
`block_rethink`, `fact_remember`, `fact_search`, `fact_supersede`,
|
|
46
|
+
`fact_forget`, `recall_episodes`, `conversation_search`,
|
|
47
|
+
`fact_history`, `fact_validate` — every tool is a typed `Tool` with
|
|
48
|
+
`inputSchema` + `outputSchema`, the appropriate `memoryGuardTier`, and
|
|
49
|
+
the right `sideEffectClass`. `fact_search` accepts an `asOf` instant
|
|
50
|
+
for point-in-time reads; `fact_history` returns a fact's bi-temporal
|
|
51
|
+
supersede chain; `fact_validate` promotes a quarantined fact to active.
|
|
52
|
+
- **Provenance + quarantine (memory-safety gate).** Every fact carries
|
|
53
|
+
a `provenance` tag (`user` / `tool` / `extraction` / `reflection` /
|
|
54
|
+
`imported`) and a retrieval-trust `status`. *Derived* writes
|
|
55
|
+
(consolidator extraction, future reflection) and candidates that trip
|
|
56
|
+
the offline injection heuristics (`ignore previous instructions`,
|
|
57
|
+
role-markup smuggling, secrecy / exfiltration directives) land
|
|
58
|
+
`status: 'quarantined'` and are **excluded from default recall** until
|
|
59
|
+
a human promotes them via `fact_validate`. Quarantine is a retrieval
|
|
60
|
+
gate, never a delete — quarantined rows stay fully auditable, and the
|
|
61
|
+
`includeQuarantined` search option surfaces them for the validation
|
|
62
|
+
UI. This is the precondition for safely shipping synthesized memory
|
|
63
|
+
(reflection / reconciliation / induction) against memory-poisoning
|
|
64
|
+
(MINJA, MemoryGraft).
|
|
65
|
+
- **Multi-stage conflict resolution pipeline.** Every
|
|
66
|
+
`SemanticMemory.remember(...)` call now flows through a five-stage
|
|
67
|
+
pipeline (exact dedup → embedding three-zone → heuristic regex →
|
|
68
|
+
subject/predicate → defer-to-deep). Decisions are recorded into
|
|
69
|
+
`fact_conflicts`; ambiguous cases land in the `conflict_check_pending`
|
|
70
|
+
queue for the consolidator's deep phase. The English locale pack
|
|
71
|
+
ships by default; additional locales plug in via
|
|
72
|
+
`defineLocalePack({...})`. Operators can disable the pipeline with
|
|
73
|
+
`createMemory({ conflictPipeline: { mode: 'off' } })` (a one-shot
|
|
74
|
+
WARN surfaces so the regression risk is visible).
|
|
75
|
+
- **Neighbour-aware write reconciliation** (consolidator standard phase).
|
|
76
|
+
Extracted facts are reconciled against their nearest neighbours via an
|
|
77
|
+
extract→reconcile loop: a cheap pre-filter (the pipeline's exact-dedup +
|
|
78
|
+
embedding zones over `SemanticMemory.neighbors(...)`) resolves clear
|
|
79
|
+
duplicates / independents with no LLM call, and only the ambiguous mid-zone
|
|
80
|
+
spends one reconcile pass choosing add / update / noop / conflict. Updates
|
|
81
|
+
and conflicts route through the bi-temporal supersede (never a delete);
|
|
82
|
+
every decision is audited in `fact_conflicts` and new facts inherit the
|
|
83
|
+
`extraction` provenance gate.
|
|
84
|
+
- **Auto-importance + episode formation** (consolidator standard phase).
|
|
85
|
+
Each processed slice is summarized into one episode via a single budgeted
|
|
86
|
+
LLM call that also rates its importance `1–10` (normalized to `[0, 1]`),
|
|
87
|
+
so episodic triple-signal retrieval (recency × relevance × importance) finally
|
|
88
|
+
runs on all three signals. Auto-formed episodes carry `provenance: 'extraction'`
|
|
89
|
+
+ `status: 'quarantined'` (P1-4) — surfaced for review via
|
|
90
|
+
`episodic.search(..., { includeQuarantined: true })`. Importance is a *soft*
|
|
91
|
+
signal (never a retention gate). Controlled by the per-tier `formEpisodes` /
|
|
92
|
+
`importanceScoring` flags (on at `standard` / `full`); budget-aware
|
|
93
|
+
(an exhausted budget degrades to fact-only).
|
|
94
|
+
- **Reflection + insight synthesis** (consolidator deep phase). When the
|
|
95
|
+
accumulated importance of recent episodes crosses `importanceThreshold`, the
|
|
96
|
+
deep phase asks the model for the few most salient questions, retrieves
|
|
97
|
+
evidence for each, and synthesizes a higher-order **insight** (Generative
|
|
98
|
+
Agents). Insights are a distinct memory type (`memory.insights`:
|
|
99
|
+
`search` / `list`) that land `provenance: 'reflection'` +
|
|
100
|
+
`status: 'quarantined'`, carry **mandatory citations set from the retrieved
|
|
101
|
+
evidence** (never hallucinated), and are **rank-capped below the facts they
|
|
102
|
+
cite** (`capInsightsBelowFacts`). An ExpeL salience counter (start `2`,
|
|
103
|
+
pruned at `0`) manages the set. Off by default except at the `full` tier;
|
|
104
|
+
budget-aware and a no-op without an episodic tier + insight-capable store.
|
|
105
|
+
- **Contextual retrieval** (write path). Before a fact is embedded + FTS-indexed
|
|
106
|
+
the framework prepends a short **situating context** (entities / timeframe /
|
|
107
|
+
topics, Anthropic's Contextual Retrieval) so a terse fact stays findable; the
|
|
108
|
+
canonical `text` is preserved. The offline default `'late-chunk'`
|
|
109
|
+
(`createMemory({ contextualRetrieval })`) derives the context deterministically
|
|
110
|
+
from the fact's own structured signals with **no extra LLM call** — a no-op for
|
|
111
|
+
plain-text writes. An opt-in, **consolidator-only** `'llm'` mode
|
|
112
|
+
(`consolidator: { contextualRetrieval: 'llm' }`) spends one budgeted cheap-model
|
|
113
|
+
call per write to author the prefix, degrading to late-chunk on any failure.
|
|
114
|
+
- **Recall explainability** ("why was this recalled?"). `explainRecall(hits, {
|
|
115
|
+
query, rerankerId })` decomposes a `search(...)` result into the per-memory
|
|
116
|
+
signals that drove its score (`bm25` / `vector` / fused `rrf` / `decay`), in
|
|
117
|
+
final-rank order; `formatRecallExplanation(...)` renders it. `search` also
|
|
118
|
+
records the decay multiplier as a `decay` signal and attaches the breakdown
|
|
119
|
+
(ids + scores + signals, never the query text) to the `memory.search.semantic`
|
|
120
|
+
span. Operators inspect the rest via `graphorin memory inspect <factId>`
|
|
121
|
+
(supersede chain / quarantine / conflicts / citing insights) and
|
|
122
|
+
`graphorin memory activity` (consolidator / reflection activity).
|
|
123
|
+
- **Multi-signal forgetting** (cost / staleness control, *not* an accuracy
|
|
124
|
+
lever). The light phase scores each fact with `salience(...)` — the Ebbinghaus
|
|
125
|
+
`retention` curve (recency + access frequency) combined with the `importance`
|
|
126
|
+
hint and a security-risk negative term (a quarantined fact is evicted first, a
|
|
127
|
+
foreign-provenance one slightly sooner). With neutral importance + an active,
|
|
128
|
+
first-party fact, `salience === retention`. Setting `decayCapacity`
|
|
129
|
+
(`createMemory({ consolidator: { decayCapacity } })`, default unbounded)
|
|
130
|
+
bounds storage: the lowest-salience facts are **soft-archived** (recoverable —
|
|
131
|
+
`archived = 1`, never deleted) until the window fits.
|
|
132
|
+
- **Query transformation** (read path; multi-query / RAG-Fusion + opt-in HyDE).
|
|
133
|
+
`search(scope, query, { multiQuery: N })` fans the query into up to `N - 1`
|
|
134
|
+
reworded variants via one cheap LLM call, retrieves each, and fuses every list
|
|
135
|
+
through the same RRF reranker — recovering memories whose stored wording
|
|
136
|
+
differs from the question. `{ hyde: true }` additionally embeds a hypothetical
|
|
137
|
+
answer (arXiv:2212.10496) and fuses its neighbours. Both are **opt-in**, wired
|
|
138
|
+
by `createMemory({ queryTransform: { provider } })`; with no transformer (the
|
|
139
|
+
default) search stays **offline + single-shot** and these options are silent
|
|
140
|
+
no-ops. Reserve it for retrieval-heavy recall — it adds provider latency.
|
|
141
|
+
- **Weighted fusion + reranker guidance** (search quality, opt-in). RRF is a
|
|
142
|
+
good zero-tuning default, but once you have labels (the `@graphorin/evals`
|
|
143
|
+
harness) a calibrated weight can do better. `search(scope, query, { fusion: {
|
|
144
|
+
strategy: 'weighted', weights: { vector: 3, fts: 1 } } })` fuses through
|
|
145
|
+
`WeightedRRFReranker`, scaling each candidate list's reciprocal-rank
|
|
146
|
+
contribution by its retriever *kind* (FTS vs vector; the HyDE list counts as
|
|
147
|
+
vector). **RRF stays the default** — omit `fusion` (or pass `{ strategy:
|
|
148
|
+
'rrf' }`) and behaviour is unchanged; equal weights reproduce RRF exactly. The
|
|
149
|
+
pure `fuseWeighted(lists, weights, k)` is exported for offline weight tuning
|
|
150
|
+
against the eval harness. For a further precision lift, install a cross-encoder
|
|
151
|
+
reranker (`@graphorin/reranker-transformersjs` / `-llm`) via
|
|
152
|
+
`createMemory({ reranker })` or `setReranker(...)` and raise `candidateTopK` —
|
|
153
|
+
reranking pays off **only on an already-high-recall candidate set**, so fix
|
|
154
|
+
recall first (contextual retrieval / multi-query) before reaching for it.
|
|
155
|
+
- **Relation graph + one-hop expansion** (new capability, opt-in). Activates the
|
|
156
|
+
dormant `(subject, predicate, object)` substrate: facts now carry s/p/o, and an
|
|
157
|
+
**entity resolver** folds the subject/object strings into canonical entities
|
|
158
|
+
("Anna", "Anna S.", "my sister" → one entity) via lexical + embedding dedup —
|
|
159
|
+
with **auditable, reversible merges** (an append-only ledger; `merged_into` is
|
|
160
|
+
single-level). At read time `search(scope, query, { expandHops: 1 })` seeds on
|
|
161
|
+
the candidates and fuses in facts sharing an entity through a recursive CTE,
|
|
162
|
+
answering "what did the person I met in Tbilisi recommend?" without leaving
|
|
163
|
+
SQLite. Enable linking with `createMemory({ graph: { entityResolution: true } })`
|
|
164
|
+
(offline; lexical + embedding). The ambiguous-similarity band mints a *new*
|
|
165
|
+
entity by default — it never auto-merges on weak evidence; opt into LLM
|
|
166
|
+
adjudication (`graph: { llmAdjudication: true, provider }`) to resolve that band.
|
|
167
|
+
Omit it all and the default path is unchanged + fully offline (`expandHops`
|
|
168
|
+
defaults to `0`).
|
|
169
|
+
- **Agentic / iterative retrieval** (search quality, gated + opt-in). A
|
|
170
|
+
CRAG/Self-RAG-style grade-then-reformulate loop for hard multi-hop / temporal
|
|
171
|
+
questions one pass can't answer. A cheap **local difficulty gate**
|
|
172
|
+
(`assessQueryDifficulty`) keeps simple lookups single-shot; only a query judged
|
|
173
|
+
hard *and* with a grader configured (`createMemory({ iterativeRetrieval: {
|
|
174
|
+
provider } })`) is graded for sufficiency and, when weak, reformulated +
|
|
175
|
+
retrieved again — **widening to one-hop graph expansion** on each reformulation —
|
|
176
|
+
up to a hard-capped `maxIterations` (≤ 5), then **abstaining**
|
|
177
|
+
(`result.abstained === true`) rather than confabulating. Exposed as
|
|
178
|
+
`SemanticMemory.searchIterative(...)` and the gated **`deep_recall`** tool (a
|
|
179
|
+
twelfth tool, registered only when `iterativeRetrieval` is configured). Omit it
|
|
180
|
+
and `searchIterative` degrades to one difficulty-gated pass with **no provider
|
|
181
|
+
call**; the tool surface stays at the canonical eleven.
|
|
182
|
+
- **Procedural memory extraction** (new capability, gated + opt-in). AWM-style
|
|
183
|
+
workflow induction: from a **successful** agent trajectory,
|
|
184
|
+
`ProceduralMemory.induce(scope, trajectory)` distils a reusable procedure —
|
|
185
|
+
goal + value-abstracted steps (`"search for {product}"`) + the variable names
|
|
186
|
+
+ Voyager-style success criteria for self-verification on reuse
|
|
187
|
+
(`checkSuccessCriteria`). Induction fires on **success only** (a failed run
|
|
188
|
+
never calls the inducer), and the result lands **quarantined** +
|
|
189
|
+
`provenance: 'induction'` (P1-4) — procedures drive *actions*, so this is the
|
|
190
|
+
highest-poisoning-risk write and is excluded from `activate()` until validated.
|
|
191
|
+
`trajectoryFromRunState(runState)` distils the agent's already-emitted run
|
|
192
|
+
state, so capture needs **no agent change**. Wire it with
|
|
193
|
+
`createMemory({ procedureInduction: { provider } })`; omit it and `induce(...)`
|
|
194
|
+
throws `ProcedureInductionNotConfiguredError` — the procedural tier stays pure
|
|
195
|
+
offline CRUD with no provider call.
|
|
196
|
+
- **Per-record `embedder_id` enforced.** Every embedded write registers
|
|
197
|
+
the embedder via the storage layer's `EmbeddingMetaRepository` and
|
|
198
|
+
records the canonical id (`'<provider>:<model>@<dim>'`); attempts to
|
|
199
|
+
silently swap embedders fail-fast under the default `lock-on-first`
|
|
200
|
+
policy.
|
|
201
|
+
- **Embedder migration runner** (`migrateEmbedder`). Three strategies:
|
|
202
|
+
`lock-on-first` (default; refuses silent swap), `multi-active` (read
|
|
203
|
+
union, write to active), `auto-migrate` (re-embeds existing rows in
|
|
204
|
+
resumable batches; checkpointed via the `migration_state` table; can
|
|
205
|
+
be aborted with `AbortSignal`).
|
|
206
|
+
- **Multi-agent attribution.** Every session message carries an
|
|
207
|
+
optional `agentId`; `Session.list({ agentId })` filters per-agent;
|
|
208
|
+
`Session.attributedFor(...)` exposes the registry; episodes can be
|
|
209
|
+
recorded `'merged'` / `'per-agent'` (the rendering mode is consumed
|
|
210
|
+
by the consolidator in Phase 10c).
|
|
211
|
+
- **Default-on bi-temporal storage.** Fact writes set `validFrom = now`
|
|
212
|
+
and leave `validTo = null`; a supersede closes the old fact's `validTo`
|
|
213
|
+
(so `as_of` queries reflect the change) and keeps the chain intact for
|
|
214
|
+
later replay. The advanced `as_of_date` query API is opt-in
|
|
215
|
+
(post-MVP).
|
|
216
|
+
- **`memory.compile(scope)` + `memory.metadata(scope)`.** The
|
|
217
|
+
interface used by the context engine (Phase 10d) to assemble the
|
|
218
|
+
six-layer memory-aware system prompt; `@graphorin/memory@0.5.0`
|
|
219
|
+
ships the deterministic minimum-viable rendering so the agent
|
|
220
|
+
runtime in Phase 12 can already exercise the surface.
|
|
221
|
+
- **Memory-modification guard wiring.** Every tool's
|
|
222
|
+
`memoryGuardTier` is annotated per `DEC-153`; the executor in
|
|
223
|
+
`@graphorin/tools` honours the tier through the `createGuard(...)`
|
|
224
|
+
helper from `@graphorin/security/guard`.
|
|
225
|
+
|
|
226
|
+
## Stable sub-paths
|
|
227
|
+
|
|
228
|
+
```ts
|
|
229
|
+
import { createMemory } from '@graphorin/memory';
|
|
230
|
+
import { RRFReranker } from '@graphorin/memory/search';
|
|
231
|
+
import { migrateEmbedder } from '@graphorin/memory/migration';
|
|
232
|
+
import {
|
|
233
|
+
blockAppendTool,
|
|
234
|
+
factRememberTool,
|
|
235
|
+
} from '@graphorin/memory/tools';
|
|
236
|
+
import {
|
|
237
|
+
EmbedderRegistrationError,
|
|
238
|
+
MemoryToolDeniedError,
|
|
239
|
+
} from '@graphorin/memory/errors';
|
|
240
|
+
import {
|
|
241
|
+
createConflictPipeline,
|
|
242
|
+
defineLocalePack,
|
|
243
|
+
enLocalePack,
|
|
244
|
+
DEFAULT_CONFLICT_THRESHOLDS,
|
|
245
|
+
} from '@graphorin/memory/conflict';
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Quick start
|
|
249
|
+
|
|
250
|
+
```ts
|
|
251
|
+
import { createSqliteStore } from '@graphorin/store-sqlite';
|
|
252
|
+
import { createTransformersJsEmbedder } from '@graphorin/embedder-transformersjs';
|
|
253
|
+
import { createMemory } from '@graphorin/memory';
|
|
254
|
+
|
|
255
|
+
const sqlite = await createSqliteStore({ path: './assistant.db' });
|
|
256
|
+
await sqlite.init();
|
|
257
|
+
|
|
258
|
+
const memory = createMemory({
|
|
259
|
+
store: sqlite.memory,
|
|
260
|
+
embeddings: sqlite.embeddings,
|
|
261
|
+
embedder: createTransformersJsEmbedder(),
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
await memory.semantic.remember(
|
|
265
|
+
{ userId: 'alex' },
|
|
266
|
+
{ text: 'Loves mountain hiking and fresh espresso.' },
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
const hits = await memory.semantic.search(
|
|
270
|
+
{ userId: 'alex' },
|
|
271
|
+
'mountain trip ideas',
|
|
272
|
+
);
|
|
273
|
+
console.log(hits[0]?.record.text);
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Tier overview
|
|
277
|
+
|
|
278
|
+
| Tier | Surface (read) | Surface (write) |
|
|
279
|
+
|-------------|-----------------------------------------------|-------------------------------------------------------------|
|
|
280
|
+
| working | `list`, `read`, `compile` | `define`, `write`, `patch`, `attach`, `detach` |
|
|
281
|
+
| session | `list`, `search`, `attributedFor` | `push`, `flushImportant`, `compact` |
|
|
282
|
+
| episodic | `recent`, `search` | `record` |
|
|
283
|
+
| semantic | `search` | `remember`, `supersede`, `forget` |
|
|
284
|
+
| procedural | `list`, `activate` | `define`, `remove` |
|
|
285
|
+
| shared | `listFor` | `attach`, `detach` |
|
|
286
|
+
|
|
287
|
+
## Memory tools (registered with `@graphorin/tools`)
|
|
288
|
+
|
|
289
|
+
`memory.tools` is a typed `Tool[]`. Pass it through to
|
|
290
|
+
`createToolRegistry({ ... })` (Phase 12) so the agent loop sees every
|
|
291
|
+
tool exactly once:
|
|
292
|
+
|
|
293
|
+
| Tool name | Tier | Purpose |
|
|
294
|
+
|----------------------|------------|--------------------------------------------------------|
|
|
295
|
+
| `block_append` | working | Append text to a working memory block. |
|
|
296
|
+
| `block_replace` | working | Replace a unique substring inside a block. |
|
|
297
|
+
| `block_rethink` | working | Replace a block's value entirely. |
|
|
298
|
+
| `fact_remember` | semantic | Persist a new fact through the multi-stage conflict pipeline. |
|
|
299
|
+
| `fact_search` | semantic | Hybrid (vector + FTS5 + RRF) search over facts. |
|
|
300
|
+
| `fact_supersede` | semantic | Mark an old fact superseded by a new one. |
|
|
301
|
+
| `fact_forget` | semantic | Soft-delete a fact (kept for replay). |
|
|
302
|
+
| `recall_episodes` | episodic | Triple-signal episode retrieval. |
|
|
303
|
+
| `conversation_search`| session | FTS5 search over the active session messages. |
|
|
304
|
+
| `fact_history` | semantic | Trace a fact's bi-temporal supersede chain. |
|
|
305
|
+
| `fact_validate` | semantic | Promote a quarantined fact to active (audited). |
|
|
306
|
+
|
|
307
|
+
## Embedder migration
|
|
308
|
+
|
|
309
|
+
```ts
|
|
310
|
+
import { migrateEmbedder } from '@graphorin/memory/migration';
|
|
311
|
+
import { createTransformersJsEmbedder } from '@graphorin/embedder-transformersjs';
|
|
312
|
+
|
|
313
|
+
const target = createTransformersJsEmbedder({ model: 'Xenova/multilingual-e5-large' });
|
|
314
|
+
|
|
315
|
+
for await (const progress of migrateEmbedder({
|
|
316
|
+
store: sqlite,
|
|
317
|
+
embeddings: sqlite.embeddings,
|
|
318
|
+
source: memory.embedder,
|
|
319
|
+
target,
|
|
320
|
+
strategy: 'auto-migrate',
|
|
321
|
+
})) {
|
|
322
|
+
console.log(`${progress.processed}/${progress.total} (${progress.kind})`);
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
`lock-on-first` (default) refuses any silent embedder swap with an
|
|
327
|
+
actionable error pointing at the planned migration. `multi-active`
|
|
328
|
+
keeps both vec0 tables alive (reads union, writes to active).
|
|
329
|
+
`auto-migrate` re-embeds rows in resumable batches (checkpointed
|
|
330
|
+
via the storage layer's `migration_state` table; can be aborted
|
|
331
|
+
with `AbortSignal`).
|
|
332
|
+
|
|
333
|
+
## Conflict pipeline (Phase 10b)
|
|
334
|
+
|
|
335
|
+
```ts
|
|
336
|
+
import { createMemory, defineLocalePack } from '@graphorin/memory';
|
|
337
|
+
|
|
338
|
+
const memory = createMemory({
|
|
339
|
+
store: sqlite.memory,
|
|
340
|
+
embeddings: sqlite.embeddings,
|
|
341
|
+
embedder: createTransformersJsEmbedder(),
|
|
342
|
+
conflictPipeline: {
|
|
343
|
+
mode: 'on', // default
|
|
344
|
+
thresholds: { hot: 0.95, nearDup: 0.85, cold: 0.4 },
|
|
345
|
+
localePack: defineLocalePack({ id: 'fr', /* ... */ }),
|
|
346
|
+
},
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
const outcome = await memory.semantic.rememberWithDecision(scope, {
|
|
350
|
+
text: 'I just moved to Tbilisi for the new gig.',
|
|
351
|
+
});
|
|
352
|
+
console.log(outcome.decision.kind); // 'supersede' | 'dedup' | 'pending' | 'admit'
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
The pipeline visits five stages in order:
|
|
356
|
+
|
|
357
|
+
1. **Exact dedup** — MD5 hash on the canonical (lowercase + collapsed-
|
|
358
|
+
whitespace + trimmed) candidate body short-circuits on a hit.
|
|
359
|
+
2. **Embedding three-zone** — top-K neighbours from `searchVector`
|
|
360
|
+
classify the candidate into HOT (`>= 0.95`), NEAR-DUP
|
|
361
|
+
(`>= 0.85`), CONFLICT-CHECK (`> 0.4`), or COLD. HOT zone always
|
|
362
|
+
dedups (semantic identity outranks every other signal).
|
|
363
|
+
3. **Heuristic regex** — the active locale pack's supersede +
|
|
364
|
+
negation markers fire when the candidate has an explicit
|
|
365
|
+
change signal (`moved to`, `no longer`, `got promoted`, …) and
|
|
366
|
+
there is at least one existing candidate.
|
|
367
|
+
4. **Subject / predicate** — naive `(subject, predicate, object)`
|
|
368
|
+
split using the locale pack's predicate normalisers; matching
|
|
369
|
+
subject + predicate with a different object is a strong supersede
|
|
370
|
+
signal.
|
|
371
|
+
5. **Defer to deep LLM judge** — Stages 1–4 yielded no decision but
|
|
372
|
+
the candidate sits in CONFLICT-CHECK zone — the row is admitted
|
|
373
|
+
`pending` and queued in `conflict_check_pending` for the
|
|
374
|
+
consolidator's deep phase (Phase 10c).
|
|
375
|
+
|
|
376
|
+
Every decision lands one row in `fact_conflicts` with the producing
|
|
377
|
+
stage, the detection zone, the cosine similarity (where applicable),
|
|
378
|
+
and a reason string for replay/debug. A `memory.conflict` AISpan is
|
|
379
|
+
emitted per call.
|
|
380
|
+
|
|
381
|
+
`createMemory({ conflictPipeline: { mode: 'off' } })` falls back to the
|
|
382
|
+
10a straight-through write path; a single per-process WARN surfaces so
|
|
383
|
+
operators notice that bi-temporal supersede / dedup will not fire.
|
|
384
|
+
|
|
385
|
+
## Forward links
|
|
386
|
+
|
|
387
|
+
| Surface | Owned by |
|
|
388
|
+
|--------------------------------------|------------|
|
|
389
|
+
| Background `Consolidator` (triggers + 3 phases + DLQ + cost budget) | Phase 10c |
|
|
390
|
+
| Six-layer memory-aware system prompt + locale-aware base templates | Phase 10d |
|
|
391
|
+
| `@graphorin/sessions` hybrid facade wrapping `memory.session.*` | Phase 11 |
|
|
392
|
+
| `@graphorin/agent` wiring `memory.tools` into the tool registry | Phase 12 |
|
|
393
|
+
| `/v1/memory` REST + `graphorin memory migrate` CLI | Phases 14 / 15 |
|
|
394
|
+
|
|
395
|
+
## License
|
|
396
|
+
|
|
397
|
+
MIT © 2026 Oleksiy Stepurenko.
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
**Project Graphorin** · v0.5.0 · MIT License · © 2026 Oleksiy Stepurenko · <https://github.com/o-stepper/graphorin>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { LocaleMatch, LocalePack, LocalePatternEntry, LocaleSupersedeKind, defineLocalePack, evaluateMarkers } from "./locale-packs/types.js";
|
|
2
|
+
import { ConflictDecision, ConflictPipeline, ConflictPipelineDeps, ConflictPipelineOptions, ConflictStage, ConflictThresholds, DEFAULT_CONFLICT_THRESHOLDS, PipelineStage, ReconcileAction, ReconcileDecision, StageContext, StageOutcome, reconcileToConflictDecision } from "./types.js";
|
|
3
|
+
import { _resetBypassWarningForTesting, createConflictPipeline, runConflictPipeline } from "./pipeline.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { defineLocalePack, evaluateMarkers } from "./locale-packs/types.js";
|
|
2
|
+
import { enLocalePack } from "./locale-packs/en.js";
|
|
3
|
+
import "./locale-packs/index.js";
|
|
4
|
+
import { DEFAULT_CONFLICT_THRESHOLDS, reconcileToConflictDecision } from "./types.js";
|
|
5
|
+
import { _resetBypassWarningForTesting, createConflictPipeline, runConflictPipeline } from "./pipeline.js";
|
|
6
|
+
|
|
7
|
+
export { };
|