docs(memhub): define SDK data-plane migration contract

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
alvinfeiandCursor committed 2026-10-21 16:59:13 +08:00
1 parent d96dd1c79e
commit 2e1237f29f
3 files changed
+229

No files matched your search

+1
View File
@@ -3,6 +3,7 @@
更新:2026-10-21
权威细则:[`memhub/docs/ARCHITECTURE.md`](memhub/docs/ARCHITECTURE.md)(~~旧删线~~ + 新并列)
配套:[`memhub/MEMORY.md`](memhub/MEMORY.md);其余 docs 已打「架构变更」条,冲突以 ARCHITECTURE Top Rules 为准。
旧用户迁移:[`memhub/docs/contracts/sdk-data-plane-migration-v1.md`](memhub/docs/contracts/sdk-data-plane-migration-v1.md)。
> 根目录原先无有效 `HANDSOFF` 文件;本文件为清空后重写,只保留本次架构改造交接。
+5
View File
@@ -369,3 +369,8 @@ Test entry points: [`../CONTRIBUTING.md`](../CONTRIBUTING.md).
3. 导入/同步改为 SDK raw/write;退役 Evidence 权威。
4. 删除或清空镜像台账;队列改为纯调度。
5. 缺的 SDK API 开 SDK PR,而不是在 Core 里补影子表。
Released installations require the offline, resumable compatibility protocol in
[`contracts/sdk-data-plane-migration-v1.md`](contracts/sdk-data-plane-migration-v1.md).
Do not cut over an existing home with a SQLite-only backup or by replaying
Evidence through extraction.
@@ -0,0 +1,223 @@
# SDK Data Plane Migration v1
Updated: 2026-10-21.
This contract migrates released MemHub installations from the historical
Evidence/Governance authority to the Hy Memory SDK data plane defined by
[`../ARCHITECTURE.md`](../ARCHITECTURE.md).
It is an offline, resumable migration. It is not a permanent dual-read or
dual-write design.
## 1. Authority before and after cutover
Before the cutover marker is committed:
- `evidence*` and `governed_*` remain the product read authority;
- SDK stores are inspected and backfilled, but are not merged into live search;
- new imports, writes, queue drains, corrections, deletes, Matters generation,
and session delivery are paused.
After the cutover marker is committed:
- SDK memory/raw/vector/graph/coding stores are the only memory data authority;
- MemHub stores management state and `memory_id` / raw references only;
- legacy Evidence/Governance tables are read-only compatibility data;
- startup must not fall back to legacy authority because an SDK read failed.
The marker, not table existence, selects the authority.
## 2. Supported source state
The migration preflight records and validates:
- MemHub Runtime build and management schema version;
- installed `hy-memory` version and SDK store-format version;
- SDK namespace, vector/graph/cache/history/coding providers and locations;
- embedding model identity and dimensions;
- source grants, model profiles, config, queue leases, and pending operations.
The migration fails closed when the installed SDK lacks:
- complete lifecycle/raw inventory;
- exact raw and exact memory import;
- durable request outcome lookup;
- consistent snapshot/export and restore.
`hy-memory==2.0.4` does not satisfy all of these requirements and cannot perform
the final cutover.
## 3. Legacy-state classification
While Core and Runtime writers are stopped, build four inventories:
- `E`: Evidence rows and revisions;
- `G`: current Governance rows, statuses, supersession links, and latest content;
- `M`: task-output mappings from legacy `memory_id` to SDK `hy_memory_id`;
- `S`: complete SDK inventory, including raw and non-active lifecycle records.
Every item must end in exactly one class:
| Class | Meaning | Required action |
| --- | --- | --- |
| matched | Governance/mapping and SDK identity, content, owner, scope and lifecycle agree | verify only |
| mapped mismatch | legacy ID maps to a different existing SDK ID | keep SDK ID; record alias |
| Governance-only | current legacy memory has no SDK entity | exact import without extraction |
| SDK-only | SDK entity has no legacy mirror | retain and adopt |
| divergent | both exist but content, owner, scope or lifecycle differs | reconcile explicit user intent or quarantine |
| raw-only | Evidence has no SDK raw receipt | exact raw import |
| unknown outcome | a task may have reached SDK without a confirmed result | SDK outcome inquiry; never blind retry |
An unclassified item blocks cutover.
## 4. User edits, deletion and supersession
The target product has no MemHub revision history or Undo.
- The latest non-deleted user correction is imported as the current SDK body.
- Historical `governed_memory_versions` remain in the compatibility backup, but
are not recreated as product-visible SDK versions.
- A legacy user deletion is applied as an SDK physical delete. Deleted
Governance tombstones are not imported and no deleted-list UI survives.
- SDK supersession remains an SDK lifecycle relationship. Existing SDK chains
are retained. Governance links are used only to repair a missing SDK chain
during exact import.
- Pending correction/delete records are settled before ordinary backfill.
`update(memory_id, content)` modifies the same SDK ID. There is no product CAS,
revision number, or restore operation.
## 5. Evidence to SDK raw
Evidence must not be replayed through ordinary `add()`: doing so would extract
and reconcile again, changing semantic memories.
The SDK exact-raw import preserves:
- source, conversation/session, workspace, role and author;
- original event time and stable source ordering;
- verbatim content and source identity;
- a deterministic migration key.
The operation is idempotent and returns an SDK raw ID. Evidence revisions and
repairs are preserved in the migration bundle for audit; only the current
accepted raw record becomes the normal product read.
## 6. Full migration bundle
A successful preflight creates one versioned bundle containing:
- an online backup of `one-memory.sqlite3`;
- an SDK-consistent export/snapshot of raw, vector, graph, cache, history and
coding stores;
- `config.json` and non-secret configuration needed to locate those stores;
- Runtime, SDK, schema, namespace, backend and embedding fingerprints;
- object/file hashes, row counts, object counts and creation time;
- migration ledger version and bundle ID.
Secrets are not copied into a plaintext manifest. The bundle records only
secret references and the secure-store identity required for restore.
The bundle is published only after an isolated restore verifies hashes, counts
and SDK reads. A remote backend without a supported snapshot/export mechanism
blocks migration; SQLite-only backup is not reported as success.
## 7. Durable migration ledger
The MemHub management database owns operational migration tables:
- `sdk_data_plane_migrations`: one run, source/target fingerprints, bundle,
phase, cutover state and reconciliation digest;
- `sdk_data_plane_migration_items`: source identity/revision/hash, target SDK
identity/hash, deterministic operation key, state, attempts and error code;
- `memory_id_aliases`: historical ID to canonical SDK ID for old Matters,
call-events, task receipts and links.
Progress is committed only after SDK verification. Retrying an item uses the
same deterministic SDK operation key and must not create another memory.
## 8. Queue and unknown outcomes
Queue rows and leases remain MemHub management state.
- `hy_invoked=0` may be safely retried after normal lease recovery.
- `hy_invoked=1`, `memory_tasks.status=unknown`, or any non-terminal SDK outcome
must use `get_write_outcome(request_id)`.
- `running`/`unknown` is not absence and must not be replayed.
- confirmed SDK IDs become task receipts; Governance publication is not part of
completion after cutover.
## 9. Matters, call events and session delivery
- Matters retain organization and canonical `memory_id` / SDK raw references.
- Embedded memory bodies are replaced by read-time SDK resolution.
- Historical IDs remain resolvable through `memory_id_aliases`.
- `call_events` remains metadata-only; reference titles/content resolve through
SDK APIs.
- Evidence-based session inbox/outbox is disabled at cutover unless replaced by
a management-event or SDK-event contract. It must not send shadow memory
bodies.
## 10. Cutover
Cutover requires:
- no unclassified or quarantined item;
- complete raw coverage;
- no unsafe unknown task;
- pending corrections and deletions settled;
- Matters/call-event references resolvable;
- exact counts and hashes reconciled;
- deterministic full-ID get verification;
- a verified full migration bundle.
The final transaction writes an immutable marker with migration ID, SDK/store
version, namespace/backend fingerprint, bundle ID, digest and completion time.
After that transaction, legacy memory/raw writes are rejected.
## 11. Rollback and version skew
Before cutover, a failed run resumes from the ledger or restores the full
bundle.
After cutover but before any SDK-only write, rollback restores the full bundle
and matching old Runtime together.
After an SDK-only write:
- automatic binary-only rollback is forbidden;
- operators either forward-fix, or explicitly restore the pre-cutover bundle
while acknowledging loss of post-cutover writes;
- an old Runtime must fail closed on the post-cutover marker/schema.
Changing only the Runtime `current` symlink is not data rollback.
## 12. Legacy retention and cleanup
For at least one compatibility release:
- keep legacy tables read-only;
- keep the verified migration bundle;
- expose diagnostics for migration ID, phase, counts and last stable error code;
- do not silently delete old Evidence/Governance content.
Cleanup is a separate explicit operation after retention expires. It requires a
verified bundle and no unresolved alias/reference.
## 13. Acceptance matrix
The release gate covers:
- a clean install with no legacy rows;
- Governance-only, SDK-only, mapped-ID and divergent fixtures;
- Evidence/raw-only content;
- pending correction and physical deletion;
- unknown SDK outcome and crash after SDK commit;
- interruption before/after each ledger transition;
- full bundle restore and hash/count mismatch;
- Matters/call-event alias preservation;
- old Runtime against a post-cutover home;
- local and supported remote backend snapshot behavior.
No narrow unit test may be used as evidence that the full migration is safe.