Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions docs/en/rfcs/1859_artifact_merge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
- Proposal Name: `artifact_merge`
- Start Date: 2026-10-07
- RFC PR: [oceanbase/powercontext#1859](https://github.com/oceanbase/powercontext/pull/1859)

# Summary

Extract Atomic Memory's merge and undo into shared operations backed by one common set of database tables for merge state,
input-to-result relationships, and undo records. Every Artifact Family can integrate with and reuse these operations and tables
without creating its own merge, relationship, or undo tables. All Artifact creation and revision use the common write layer
(`ArtifactRepository` and its shared persistence implementation), with content and revisions remaining in existing Artifact storage.
Each Artifact's business logic decides whether to initiate a merge.

# Motivation

[RFC #1809](https://github.com/oceanbase/powercontext/pull/1809) defines new merge results, frozen inputs, preserved history,
and undo. The implementation branch in [PR #1857](https://github.com/oceanbase/powercontext/pull/1857) stores related state in an
Atomic Memory-specific table and determines input revisions from merge information in the result's first revision and lineage.

Other Artifacts need the same information when merging: which inputs were used, which result was created, when inputs became
frozen, and which objects undo should restore. Common Artifact identities and revisions can express this information without
separate tables and repeated relationship-management and undo implementations for each Family.

This proposal moves those capabilities into the shared layer. Atomic Memory also uses the same operations and tables for merge
and undo.

# Guide-level explanation

## Merge

A caller supplies exact revisions of at least two distinct Artifacts in the same Scope and Family, plus the merged content.
The shared operation creates a new Artifact C, records the relationships from A and B to C, and freezes A and B.
A and B leave normal use while their content and history remain readable through exact revisions. Subsequent revisions affect C.

The caller decides how to produce the result content. Whether initiated by a user or an automatic task, merging uses the same
shared operation and writes to the same common tables.

## Undo

To undo the merge that created C, the shared operation reads its inputs from the merge record and restores A and B to their
pre-merge states. Each restored input appends a revision under its existing Artifact identity, using its frozen content.
An explicit `restore` may select a historical revision only for its target; `undo_merge` does not accept a historical revision.
C also appends a revision under its existing identity to record retirement. Each new
revision is the Artifact's current revision plus one; existing revisions and the original merge relationships remain intact.
Later revisions of C are not automatically distributed back to A and B. C's history remains readable, and its retired identity
cannot be reactivated. Default effective reads follow the new revisions.

Successive merges follow currently effective relationships. If A and B form C, and C and D form E, restoring B undoes E and then C,
restores A, B, and D, and retires C and E. Undoing only E restores C and D while A and B remain frozen.
Ordinary evidence references do not trigger cascading undo, and external operations that used a result are not rolled back.

A caller can preview the impact before undo or request undo directly, letting the server calculate and return the actual impact.
Execution based on a preview must reject it if relevant revisions, states, or relationships have changed rather than expanding
the confirmed scope.

If no state changes are needed and no historical revision is selected, the operation is a no-op and does not append revisions.

# Reference-level explanation

## One common set of tables

Common tables store merge information for Artifacts, identifying objects by Scope, Family, Artifact identity, and exact revision.
They are not tied to any Family's content format. Shared storage must represent:

- The inputs, result, and exact revisions used by each merge.
- Input freezing, pre-merge states, and each input's current merge destination.
- Whether merge relationships remain effective and how successive merges are connected.
- Undo records with exact references to the revisions actually restored or retired and the frozen or selected historical
revisions used for restoration. Existing revision and provenance records can retain these references without a separate
operation ledger. The actual group result remains queryable by the operation's primary exact revision, subject to read
permission checks on the affected Artifacts.

The shared layer maintains these authoritative records for merge and undo. Content stays in existing Artifact revisions and is
not duplicated in the common tables. Ordinary lineage continues to record evidence; it cannot replace merge records or establish
that an Artifact has been merged.

Integrating a new Family requires neither Family-specific merge-state, relationship, or undo tables nor changes to the common
table structure. Families must not maintain another independent authoritative set of merge records. Derived state used for
retrieval must remain consistent with the common records. The number of tables, fields, indexes, and physical layout belong to
subsequent implementation design.

## Shared operations and integration

All Artifact creation and revision ultimately pass through the common Artifact write layer, which maintains revisions and
checks shared merge state. Families can retain their business entry points but cannot bypass the common write layer to modify

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 Nit: common write layer is load-bearing but never defined

grep -rln "common write layer\|公共写入层" docs/{en,zh}/rfcs/ matches this RFC only — no other RFC in the library uses the term, and neither does the rest of docs/. The English and Chinese versions are consistent with each other (3 occurrences each, at :9, :74, :84 ↔ :9, :66, :73).

Worth a definition because line 74 makes it a binding constraint rather than a description:

Families can retain their business entry points but cannot bypass the common write layer to modify [...]

A reader who does not already know which code that is cannot check that constraint, and the sentence reads as if it names something established. The implementation it corresponds to is builtin/persistence/artifacts.py:71 ArtifactRepository plus the builtin/records.py changes — both of which are named elsewhere in the proposal but never tied to this phrase.

Either way works, and neither blocks anything:

  • define it once at first use (:9), e.g. "the common write layer (builtin/persistence/artifacts.py ArtifactRepository and the record helpers behind it)", or
  • drop the coinage and reuse ArtifactRepository, which 5 other RFCs already use by name.

Not a correctness issue — the intent is clear from context, and the rest of the proposal holds up. The six references this RFC makes to already-merged material (RFC 1809's merge/undo semantics via the PR link, the dedicated pc_atomic_memory_states table with its four-value state check constraint, restoration.py's first-revision-plus-lineage input resolution, and RFC 1549's "no branches keyed on Family name" principle) all check out against the actual sources.

One thing that will need attention later, not now: #1809 and #1857 are both still open, and :15-16, :124 depend on them. The file-path-vs-PR-link convention is correct today; it just needs revisiting when those land.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defined common write layer at first use in both the English and Chinese RFCs in a49e7b2 as ArtifactRepository and its shared persistence implementation. Families retain their business entry points and decide whether to merge; this clarification does not introduce another abstraction.

This PR must not be merged until both #1809 and #1857 have been merged. The merge order is #1809 and #1857 first, then #1859; the references should be checked against their merged versions before #1859 is merged.

Artifact content, revisions, or merge state.

The shared layer also provides merge, relationship queries, undo preview, and undo execution. It owns freezing, restoration,
relationship traversal, and concurrency checks. Each Artifact's business logic decides whether and when to merge, which inputs
to select, and how to generate the result. When a merge is needed, the caller explicitly submits input references and result
content. The shared merge operation reuses the same write foundation and updates the associated states and relationships.
A new Family does not copy the merge algorithm, implement dedicated merge storage, or add name-based branches to the shared entry
point.

The common write layer does not search for similar Artifacts, decide to merge, or create merge relationships on an ordinary
create or revise operation. Ordinary revision centrally rejects changes to frozen inputs; only explicit merge or undo operations
perform the corresponding relationship and state transitions. Default reads and search also honor merge state: frozen inputs and
retired results cannot be used as current effective Artifacts. Authorized exact historical reads always return the original revision
without redirecting to the merge result. Integration does not require enabling automatic retrieval, content generation, or merging.

## Consistency

Merge and undo check permissions, revisions, states, and relationships for every affected Artifact. Reads during content generation
do not replace publication-time checks. Result publication, input freezing, common relationships, and associated current state
become effective together. Undo is also effective as a group; failure must not leave partially frozen or restored inputs.
The revisions appended for restoration and retirement and their current state become effective in the same transaction.
An input can belong to only one currently effective merge result. Concurrent operations cannot merge the same input into two
simultaneously effective results.

## Integration and acceptance

Atomic Memory's merge capability uses shared operations and common tables from its initial delivery, implementing the merge and
undo behavior of RFC #1809. Common records are authoritative for merge and undo. Undo does not rewind Source consumption progress.

Acceptance should cover Atomic Memory and another Family, confirming that both use the same operations and common tables without
adding dedicated merge tables. It should also verify that ordinary writes do not trigger merges, that business entry points
cannot bypass freeze checks, and that successive merges, cascading undo, stale previews, concurrent competition, group failure,
and exact historical reads behave as specified. Restoration and retirement must append the next revision under each existing
identity, preserve exact undo references, and leave unchanged requests without a selected historical revision as no-ops.

# Drawbacks

Extracting shared operations from Atomic Memory requires separating the parts tied to that Artifact type and verifying that
multiple callers can reuse the same behavior. Once operations and tables become shared dependencies, subsequent changes require
validation across all integrated callers.

# Rationale and alternatives

- **Shared operations and common tables.** Maintain merge and undo together and let subsequent Families reuse storage without
repeating table definitions.
- **A common interface with separate Family tables.** Standardizes calls but still duplicates relationship storage and undo logic,
failing this proposal's reuse objective.
- **Lineage alone.** Records evidence but cannot distinguish references from merges or determine effective relationships and undo scope.

# Prior art

RFC #1809 and PR #1857 provide the behavioral basis for merge and undo, which this proposal makes shared.
[RFC #1549](1549_artifact_family_unification.md) provides a direction for Family capability registration that can support
integration with the shared operations.

# Unresolved questions

Implementation design will determine the common table structure, reuse of existing common storage, and operation parameters.
These choices must satisfy the requirement that a new Family does not need its own merge tables.

This proposal excludes cross-Scope or cross-Family merging, physical deletion, and rollback of external effects.

# Future possibilities

Common merge records can support shared relationship graphs, operation history, and undo impact views without separate implementations
for each Artifact type.
129 changes: 129 additions & 0 deletions docs/zh/rfcs/1859_artifact_merge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
- Proposal Name: `artifact_merge`
- Start Date: 2026-10-07
- RFC PR: [oceanbase/powercontext#1859](https://github.com/oceanbase/powercontext/pull/1859)

# Summary

将 Atomic Memory 的合并与撤销提取为统一方法,并用一套公共数据库表保存合并状态、输入与结果关系及撤销记录。
所有 Artifact Family 都可以接入并直接复用这套方法和表,不需要为各类制品分别建立合并、关系或撤销表。
所有制品的新增和修订统一经过公共写入层(`ArtifactRepository` 及其共享持久化实现),
正文及版本继续使用已有 Artifact 存储;是否发起合并由各制品业务决定。

# Motivation

[RFC #1809](https://github.com/oceanbase/powercontext/pull/1809) 定义了“新建合并结果、冻结输入、保留历史、
支持撤销”的方式。[PR #1857](https://github.com/oceanbase/powercontext/pull/1857) 的实现分支将相关状态保存在
Atomic Memory 专用表中,并结合结果首版正文中的合并信息和 lineage 确定输入版本。

其他制品需要合并时,也需要记录用了哪些输入、生成了哪个结果、输入何时被冻结,以及撤销时恢复哪些对象。
这些信息可以用通用制品身份和版本表达,无需每个 Family 单独建表、重复实现关系维护和撤销流程。

本提案将这些能力下沉到公共层,Atomic Memory 也通过同一套方法和公共表完成合并与撤销。

# Guide-level explanation

## 合并

调用方提供同一 Scope、同一 Family 内至少两个不同制品的精确版本,以及合并后的内容。
公共方法创建新制品 C,记录 A、B 到 C 的合并关系,并冻结 A、B。
A、B 退出正常使用,正文和历史仍可按精确版本读取;后续修订继续作用于 C。

合并后的内容如何产生由调用方决定。无论来自用户操作还是自动任务,最终都调用同一个公共方法,写入同一套公共表。

## 撤销

撤销产生 C 的合并时,公共方法从合并记录中找到输入,将 A、B 恢复到合并前状态。
每个实际恢复的输入都在原制品身份下追加新版本,正文来自冻结版本。
只有显式 `restore` 可以为其目标选择历史正文;`undo_merge` 不接受历史版本选择。
C 也在原身份下追加新版本记录退役。新版本号均为该制品当前版本加一,旧版本和原始合并关系保留。
C 的后续修订不会自动拆分回 A、B,C 的历史仍可读取,退役身份不重新启用。默认有效读取跟随新版本。

连续合并沿当前仍生效的关系处理。例如 A、B 合并为 C,C 与 D 合并为 E:
恢复 B 时,依次撤销 E、C,恢复 A、B、D,退役 C、E;只撤销 E 时,恢复 C、D,A、B 仍被冻结。
普通证据引用不会触发级联撤销,也不会回滚已使用结果的外部操作。

调用方可以先预览影响,再执行撤销;也可以直接请求撤销,由服务端计算并返回实际影响。
按预览执行时,若相关版本、状态或关系发生变化,应拒绝过期预览,不能扩大已确认的范围。

若无需改变状态,且没有指定历史版本,操作仍为 no-op,不追加版本。

# Reference-level explanation

## 一套公共表

公共表面向 Artifact 保存合并信息,通过 Scope、Family、制品身份和精确版本定位对象,不绑定某一种制品的正文格式。
公共存储需要表达:

- 一次合并的输入、结果及其精确版本。
- 输入的冻结状态、合并前状态,以及当前所属的合并结果。
- 合并关系是否仍然生效,及连续合并之间的关联。
- 撤销记录中实际恢复、退役对象的新版本精确引用,以及恢复所用的冻结版本或指定历史版本。
这些引用可以由既有版本和来源记录保存,不要求另建操作账本。
实际整组结果可按本次操作的主版本精确引用查询,读取时检查受影响制品的权限。

这些信息由公共层统一维护,是合并与撤销的权威记录。制品正文仍保存在原有 Artifact 版本中,公共表不复制正文。
普通 lineage 继续记录证据关系,不能代替合并记录,也不能据此推断某个制品已经被合并。

接入新 Family 不新增该 Family 专属的合并状态表、关系表或撤销表,也不要求修改公共表结构。
各 Family 不再保存另一套独立的权威合并记录;需要用于检索的派生状态应与公共记录保持一致。
具体表数量、字段、索引和物理布局由后续实现设计确定。

## 统一方法与接入方式

所有制品的新增和修订最终经过公共 Artifact 写入层,统一维护版本并检查公共合并状态。
各制品可以保留自己的业务入口,但不能绕过公共写入层修改制品正文、版本或合并状态。

公共层同时提供合并、合并关系查询、撤销预览和撤销执行,统一维护冻结、恢复、关系遍历及并发检查。
是否合并、何时合并、选择哪些输入以及如何生成结果,由各制品业务决定。需要合并时,调用方显式提交输入引用和结果内容,
公共合并方法复用同一写入基础,并完成相关状态和关系更新。
新增 Family 无需复制合并算法、编写专属合并存储,或在公共入口增加按 Family 名称判断的分支。

公共写入层不会因为一次普通新增或修订而自动检索相似制品、决定合并或创建合并关系。
普通修订统一检查并拒绝修改被冻结的输入;只有显式合并或撤销操作才执行相应的关系和状态变更。
默认读取和检索同样遵守合并状态,冻结输入和退役结果不能作为当前有效制品使用。
有权限的精确历史读取始终返回原版本,不自动跳转到合并结果。
本提案只提供公共合并能力,不要求同时启用自动检索、内容生成或自动合并。

## 一致性

合并和撤销检查全部受影响制品的权限、版本、状态及合并关系;生成内容期间的读取不能替代提交时检查。
结果发布、输入冻结、公共关系和相关当前状态一起生效,撤销也整组生效。失败不能留下部分冻结或部分恢复。
恢复、退役所追加的版本和对应当前状态在同一事务中生效。
一个输入只能属于一个仍生效的合并结果,并发操作不能将同一输入合并到两个同时有效的结果。

## 接入与验收

Atomic Memory 的合并能力从首次落地起直接使用公共方法和公共表,实现 RFC #1809 中的合并与撤销行为。
公共记录是合并与撤销的权威来源,撤销不回退 Source 消费进度。

验收应覆盖 Atomic Memory 和另一个 Family,确认两者使用相同公共方法和公共表,接入时无需新增专属合并表。
同时验证普通写入不会触发合并、各业务入口不能绕过冻结检查,以及连续合并、级联撤销、预览失效、并发竞争、
整组失败和精确历史读取。恢复、退役应在各自原身份下追加下一版本,保留撤销的精确引用;
无变化且未指定历史版本的请求仍为 no-op。

# Drawbacks

将 Atomic Memory 的实现提取为公共方法,需要拆分其中与具体制品绑定的部分,并验证多个调用方可以复用同一套行为。
公共方法和表结构成为共同依赖后,后续修改需要验证所有已接入的调用方。

# Rationale and alternatives

- **统一方法和公共表。** 共同维护合并与撤销,后续制品接入时复用相同存储,不再重复建表。
- **只统一接口,各 Family 分别建表。** 调用形式一致,但关系存储和撤销逻辑仍重复,不满足本提案的复用目标。
- **只记录 lineage。** 可以表达证据来源,但不能区分普通引用与合并,也不足以确定当前有效关系和撤销范围。

# Prior art

RFC #1809 和 PR #1857 提供合并与撤销的行为基础;本提案将其公共化。
[RFC #1549](1549_artifact_family_unification.md) 提供 Family 能力注册方向,可用于接入统一方法。

# Unresolved questions

公共表的具体结构、已有公共存储的复用方式及方法参数,在实现设计中确定。
这些选择应满足“新增 Family 无需另建合并表”的要求。

本提案不包含跨 Scope 或跨 Family 合并、物理删除和外部副作用回滚。

# Future possibilities

基于公共合并记录,可以统一展示合并关系图、查询操作历史和预览撤销影响,无需为每种制品分别实现。
Loading