Skip to content

Commit 3b58d49

Browse files
frf12cursoragentclaude
authored
feat(artifacts): share merge and restoration across families (#1880)
* docs(rfc): propose atomic memory as independent artifacts * feat(memory): implement independent atomic memory * fix(memory): repair migration receipts and normalize writes * fix(memory): preserve history when NFC expands text * fix(atomic-memory): resolve runtime and transport regressions * fix(atomic-memory): keep short reads on a consistent snapshot * test(zcode): verify atomic memory source lineage * test(dream): make superseded worker recovery deterministic * fix(atomic-memory): align reconciliation and host contracts * fix(ci): update atomic memory integration contracts * fix(atomic-memory): preserve authorization and evidence boundaries * test(atomic-memory): cover supervisor generation and automatic merge * test(oceanbase): isolate HTTP databases and enable CI coverage * test(memory): add live temporal conflict coverage Exclude detailed design documents from the PR while keeping local copies. * fix(memory): tolerate candidate drift during context preparation * feat(artifacts): share merge and restoration across families * fix(artifacts): append revisions when restoring merge groups * fix(memory): clarify temporal fact reconciliation * fix(memory): reconcile against current published content * chore: add missing test license headers * fix(memory): keep creation metadata out of model output * fix(atomic-memory): restore scope retrieval authorization * fix(desktop): repair atomic memory integration * fix(server): advertise atomic memory capabilities * fix(desktop): qualify atomic memory protocol * docs(memory): add atomic memory clean migration design Co-authored-by: Cursor <cursoragent@cursor.com> * test(dify): exercise the Atomic search hit schema in contract regeneration Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(atomic-memory): use shared access control instead of a family-specific policy Atomic Memory now applies the common access service with the shared execution context: no policy-head lock, no implicit local-runtime Owner, and no Owner prefilter for extraction candidates. Unauthenticated deployments keep memories without Owners; the current projection no longer stores Owner columns, and enforced collection reads use the common Owner readiness check. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(desktop): report the fixture contract digest from the real-Server probe Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(memory): serve legacy Memory routes from Atomic Memory at the API layer Remove the runtime ScopedMemoryApplication. The Server translates remember, search, list, get-by-target, and flush onto ScopedAtomicMemoryApplication, which gains create, flush, and cursor. Citation reads, capacity, changes, entry tags, and memory access targets are rejected before any work. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(desktop): keep contract digest in compatibility selection Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(atomic-memory): import entries with their direct evidence Imported revisions carry the entry's own Sources and Artifact references instead of a collection anchor and predecessor, so the evidence resolver no longer reads legacy entry tables. Apply rewrites the anchored lineage left by the earlier import. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(tags): drop legacy Memory entry tag targets Runtime and persistence tags only address Artifacts; the deterministic legacy identity mapping stays in the server get_memory_entry adapter. The server rejects legacy collection tags and tag queries that select the memory family or memory_entry targets, and default tag queries exclude legacy Memory. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(atomic-memory): archive legacy Memory and convert references Co-authored-by: Cursor <cursoragent@cursor.com> * fix(atomic-memory): close migration gaps found in review - Archive and remove whole-collection citations in Handoffs and Work, blocking when a claim loses its required evidence. - Remove all collection-owned lineage before deleting collections. - Let an applied decision file be reused on rerun. - Block unfinished Dream runs whose pinned Artifacts or Sources change. - Accept import, references and projection before removal; startup runs only a light residual check. - Recreate development current-projection layouts during apply. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(atomic-memory): remove legacy Memory from the runtime and contract The runtime, public models, OpenAPI contract, SDK, dashboard and integrations no longer know the legacy Memory collection: MemoryService, its persistence and indexes, MemoryCitation, memory_citations fields and Handoff memory citations are removed. ArtifactRef rejects family=memory, so new requests cannot reintroduce collection references; generic reads and tag queries of family=memory are unsupported. atomic-memory-migrate gains the remaining data steps and stays repeatable: - Handoff receipt evidence citing a whole collection moves to the receipt's historical_data; - unfinished Dream runs drop the empty entry citation fields, and request digests are recomputed so identical retries still replay; - Task Outcome item digests are recomputed from frozen legacy decoders; - the emptied memory_citations columns are dropped last, and startup refuses while they exist. The legacy write gate stays rejected at configuration time. The legacy collection capacity benchmark is removed. Desktop reads only Atomic Memory references and no longer bundles citation-only Server profiles. Co-Authored-By: Claude Code <noreply@anthropic.com> * test: sync integration fixtures with atomic memory contract * chore(skill-up): refresh tool contract fixtures without legacy Memory citations Co-Authored-By: Claude Code <noreply@anthropic.com> * fix(atomic-memory): finish clean migration and receipt compatibility * fix(atomic-memory): close migration boundary and validation gaps * chore(skill-up): refresh migrated memory guidance pin * chore(desktop): refresh generated migration contract * ci: serialize atomic memory migration acceptance * fix(memory): support long SQLite full-text queries --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Claude Code <noreply@anthropic.com>
1 parent 7dfa903 commit 3b58d49

56 files changed

Lines changed: 4969 additions & 1314 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎docs/en/docs/operate/atomic-memory-migration.md‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ Validation requires versions continuous from 1, consistent predecessor IDs, cont
5959
manifest references. The current manifest pointer, or the last pointer before compaction, must identify
6060
that entry's chain tail. Unexplained absence, missing changes, duplicate identities, skipped versions and
6161
lagging heads block conversion. Legacy active, inactive and compacted entries become active, forgotten and
62-
retired respectively. Family state versions and common head governance summaries agree.
62+
retired respectively. Lifecycle is authoritative in `pc_artifact_heads`: these states use `lifecycle_state`
63+
values `active`, `deprecated` and `retired`, respectively, and newly imported heads have no `merged_into_id`.
64+
Atomic Memory reads the head's `governance_generation` as its `state_version`.
6365

6466
A formal Owner on an exact legacy entry resource becomes the new memory's Owner. Without enforced access,
6567
an entry without an Owner migrates without one. Several Owners on one entry or an invalid Owner block
@@ -177,9 +179,9 @@ Cursors, CAS generations, high-water marks, pending/flush requests, accepted tas
177179
unchanged. Family `memory` and binding `memory-source-window` remain scheduling aliases. Old leases are
178180
invalidated and their fences advance before maintenance completes. Consumed Sources are not extracted again.
179181

180-
Each entry's history, head, state, Owner, tags, grant conversion and current projection commit together.
182+
Each entry's history, head, Owner, tags, grant conversion and current projection commit together.
181183
Embedding preparation occurs outside the transaction. Repeat apply with the same configuration after an
182-
interruption. Existing targets must match the exact imported history; differing data or orphan content/state
184+
interruption. Existing targets must match the exact imported history; differing data or orphan content
183185
is rejected without overwriting authority. Subsequent revisions or lifecycle changes never cause the task
184186
to reset a target's head, state or tags.
185187

@@ -207,7 +209,7 @@ powercontext server atomic-memory-rebuild-projection --env-file .env --maintenan
207209
```
208210

209211
This command checks that legacy objects, columns and foreign keys have been removed from public storage and
210-
that Atomic heads, content and states are valid. It rebuilds only active current rows and removes nonactive
212+
that Atomic heads, content revisions and head lifecycle data are valid. It rebuilds only active current rows and removes nonactive
211213
or orphan current rows. Heads, content revisions, lifecycle states, retained history and Source/processing
212214
progress keep their exact identities and values. Rebuilding reads neither the archive nor legacy entry tables.
213215
The offline migration `verify` command checks whether legacy history was imported completely; projection
@@ -254,4 +256,4 @@ A current table created during development of this branch (with copied read gran
254256
to no release and is rejected at initialization. Before migration completes, apply drops and recreates that
255257
derived table and its report asks for a projection rebuild; after migration, stop writers and run the
256258
projection rebuild command above. Either way only that derived table is rebuilt from retained authority;
257-
Artifact history, Family state and grant records are unchanged.
259+
Artifact history, head lifecycle data and grant records are unchanged.

‎docs/en/docs/workflows/atomic-memory.md‎

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,14 @@ Restore directly through `POST /v1/atomic-memory/restorations`:
136136
{"scope_id": "S", "target": {"artifact_id": "B"}}
137137
```
138138

139-
Restoring forgotten content makes it active. Restoring an already active memory without a revision returns unchanged.
139+
Restoring forgotten content makes it active. Restoring an already active memory without a selected revision returns
140+
`changed: false` and appends no revision.
140141
Restoring a merged input undoes the later merges that froze it. For A+B→C followed by C+D→E, restoring B makes
141142
A, B and D active and retires C and E. Ordinary downstream Artifacts and Source cursors are not rolled back.
142-
Supplying `target.revision` saves that historical content as a new revision of the target.
143+
Every memory actually restored or retired appends a revision under its existing Artifact identity, numbered as its current
144+
revision plus one. Restored inputs use their frozen content; supplying `target.revision` uses that historical content for the
145+
target's new revision. Existing revisions and the original merge relationships remain intact, and exact historical reads
146+
continue to return the original content. Current reads and search follow the restored revisions.
143147

144148
Inspect the impact first through `POST /v1/atomic-memory/restoration-previews`:
145149

@@ -161,9 +165,20 @@ After inspecting it, send the original token to restorations with the same princ
161165
```
162166

163167
Success returns `changed`, exact resulting `restored` references, `retired` and `undo_merge_results`.
168+
When `changed: true`, both `restored` and `retired` reference the newly appended revisions of the objects actually changed.
169+
A no-op returns `changed: false` and retains the current primary Artifact reference in `restored`, without appending a revision.
164170
To undo the merge that created C, use `operation: "undo_merge"` and `target: {"artifact_id": "C"}`.
165171
That operation cannot also select a content revision.
166172

173+
The public Python runtime can read the exact historical group result using the operation's primary new revision:
174+
175+
```python
176+
outcome = await runtime.artifact_merge.for_scope("S", "atomic-memory").restoration_outcome("B", revision=2)
177+
```
178+
179+
Replace `2` with the primary revision produced by that operation. The method returns `None` if that revision has no stored
180+
restoration outcome and requires read permission for every affected Artifact.
181+
167182
| Error | HTTP status | Action |
168183
| --- | --- | --- |
169184
| `invalid_preview` | 422 | Check the token, principal, Scope, operation, target and shared signing configuration |
@@ -173,7 +188,7 @@ That operation cannot also select a content revision.
173188
| `atomic_memory_changed` | 409 | Read the changed content/state before deciding to retry |
174189
| `invalid_memory_relation` | 409 | Investigate inconsistent stored relationships |
175190

176-
Restore and merge have no `idempotency_key` or durable receipt for replaying an earlier response. A direct restoration
191+
Restore and merge have no `idempotency_key` and do not automatically replay an earlier response. A direct restoration
177192
interprets the relationships current on each invocation; repeating it after another merge can undo that newer merge.
178193
Replaying a successful request with a token can return `preview_stale`. If the connection fails during commit, inspect
179194
current states before deciding to preview again. The Python SDK does not blindly retry writes with an unknown outcome.

‎docs/zh/docs/operate/atomic-memory-migration.md‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ revision 不会产生该条记忆的新 revision。
5353
当前 manifest 或 compact 前最后一次出现的指针必须指向本 entry 的版本链末端。
5454
缺失变化记录、无法解释的缺席、重复身份、跳过版本或落后的 head 都会阻断;迁移不会选取最大版本
5555
来掩盖不一致。旧 active、inactive、compact 分别成为 active、forgotten、retired。
56-
状态版本计数与公共 head 的治理摘要同步。
56+
生命周期以 `pc_artifact_heads` 为权威:这三种状态分别使用 `lifecycle_state` 值 `active`、`deprecated`、
57+
`retired`,新导入的 head 不设置 `merged_into_id`。Atomic Memory 的 `state_version` 读取 head 的
58+
`governance_generation`。
5759

5860
旧 entry 的精确资源身份上有正式 Owner 时,它迁为新记忆的 Owner;未启用鉴权的部署中没有 Owner 的
5961
entry 迁移后同样没有 Owner。同一 entry 有多个 Owner 或 Owner 不合法时会阻断,集合 Owner 不会分配给
@@ -156,9 +158,9 @@ Source Cursor、CAS generation、高水位、pending/flush 请求、已接受任
156158
`memory` Family 与 `memory-source-window` binding 继续作为调度兼容身份。
157159
迁移完成前失效旧 Lease 并推进 fence,已消费的 Source 不重新抽取。
158160

159-
每条记忆的历史、head、状态、Owner、标签、授权转换与当前投影在同一个事务提交。
161+
每条记忆的历史、head、Owner、标签、授权转换与当前投影在同一个事务提交。
160162
向量准备在事务外完成。中途退出后,可以使用相同配置重复 apply;已提交对象先核验精确导入历史。
161-
与确定性身份对应的内容不同、存在孤立状态或历史时明确报错,不覆盖目标数据。
163+
与确定性身份对应的内容不同或存在孤立正文历史时明确报错,不覆盖目标数据。
162164
已经导入的对象后续产生新 revision 或生命周期变化时,迁移不回退其 head、状态或标签。
163165

164166
如果已转换的授权仍保留旧资源摘要,plan 和 verify 会返回 `ready: false`,并在
@@ -179,7 +181,7 @@ API、宿主、Worker、自动重启和输入写入,然后使用目标部署
179181
powercontext server atomic-memory-rebuild-projection --env-file .env --maintenance-confirmed
180182
```
181183

182-
命令检查公共表中的旧对象、旧列和外键已清理,且 Atomic 的 head、正文和状态有效。它只重建 active 的
184+
命令检查公共表中的旧对象、旧列和外键已清理,且 Atomic 的 head、正文 revision 和 head 生命周期数据有效。它只重建 active 的
183185
current 行,清除非 active 或孤立的 current 行;head、正文 revision、生命周期状态、保留历史及
184186
Source/处理进度保持原身份和原值。重建不读取归档或旧 entry 表;旧历史是否已完整导入,由停服迁移的
185187
`verify` 负责核验,投影重建不能补做缺失的历史导入。
@@ -219,4 +221,4 @@ plan、apply 和 verify 读取保留的全部旧历史和 Source/任务快照,
219221
本分支开发过程中创建的 current 表(含读取授权副本或 Owner 列)不属于任何发布版本,初始化时会被
220222
明确拒绝。迁移尚未完成时,apply 会删除并重建这张派生表,结果报告提示随后执行投影重建;迁移已完成
221223
时,停服后直接执行上述投影重建命令。两种方式都只重建这张派生表,并从正式记录恢复活跃记忆,
222-
不改变 Artifact 历史、Family 状态和授权记录。
224+
不改变 Artifact 历史、head 的生命周期数据和授权记录。

‎docs/zh/docs/workflows/atomic-memory.md‎

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,11 @@ Atomic Memory 将每条事实、偏好或决策保存为独立的 `atomic-memory
131131
{"scope_id": "S", "target": {"artifact_id": "B"}}
132132
```
133133

134-
恢复 forgotten 使其重新在役;恢复已经 active 且未指定 revision 的记忆返回未变化。
134+
恢复 forgotten 使其重新在役;恢复已经 active 且未指定 revision 的记忆返回 `changed: false`,不追加版本。
135135
恢复 merged 会撤销冻结该目标的后续合并。例如 A+B→C、C+D→E,恢复 B 会让 A、B、D 在役,C、E 退役。
136-
普通下游 Artifact 和 Source cursor 不随之回滚。指定 `target.revision` 时,将所选历史正文保存为目标的新 revision。
136+
普通下游 Artifact 和 Source cursor 不随之回滚。每个实际恢复或退役的记忆均在原 Artifact 身份下追加新 revision,
137+
版本号为其当前 revision 加一。恢复输入使用被冻结时的正文;指定 `target.revision` 时,目标的新版本使用所选历史正文。
138+
旧版本和原始合并关系保留,精确历史读取仍返回原内容;当前读取和检索跟随恢复后的新版本。
137139

138140
先查看影响范围可调用 `POST /v1/atomic-memory/restoration-previews`:
139141

@@ -155,9 +157,19 @@ operation 和 target 向 restorations 提交原 token:
155157
```
156158

157159
成功响应返回 `changed`、恢复后的精确 `restored` 引用、`retired` 和 `undo_merge_results`。
160+
`changed: true` 时,`restored` 和 `retired` 均引用实际变化对象所追加的新版本。
161+
no-op 返回 `changed: false`,`restored` 保留当前主制品的引用,不追加版本。
158162
若要撤销创建结果 C 的合并,改用 `operation: "undo_merge"`、`target: {"artifact_id": "C"}`;
159163
该操作不能同时指定内容 revision。
160164

165+
公共 Python runtime 可以按本次操作的主新版本查询精确的整组历史结果:
166+
167+
```python
168+
outcome = await runtime.artifact_merge.for_scope("S", "atomic-memory").restoration_outcome("B", revision=2)
169+
```
170+
171+
将 `2` 替换为本次操作产生的主版本。该版本没有保存恢复结果时返回 `None`;读取需要所有受影响制品的读取权限。
172+
161173
| 错误 | HTTP 状态 | 处理 |
162174
| --- | --- | --- |
163175
| `invalid_preview` | 422 | 检查 token、主体、Scope、operation、target 及共享签名配置 |
@@ -167,7 +179,7 @@ operation 和 target 向 restorations 提交原 token:
167179
| `atomic_memory_changed` | 409 | 当前内容或状态已变,重新读取后决定是否重试 |
168180
| `invalid_memory_relation` | 409 | 关系数据不一致,需要排查存储数据 |
169181

170-
恢复与合并没有 `idempotency_key`,不返回某次旧请求的持久回执。不带 token 的恢复按每次调用时的当前关系解释;
182+
恢复与合并没有 `idempotency_key`,不会自动重放某次旧请求的响应。不带 token 的恢复按每次调用时的当前关系解释;
171183
目标后来又被合并,重复请求可能撤销新的合并。携带 token 的成功请求重发也可能返回 `preview_stale`。
172184
连接在提交时中断,应先读取各对象状态确认结果,再决定是否重新预览。Python SDK 不盲目重试结果未知的写入。
173185
签名密钥、有效期及直接恢复重试预算见[配置](../operate/configuration.md#atomic-memory)。

0 commit comments

Comments
 (0)