Skip to content
Closed
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
98 changes: 98 additions & 0 deletions docs/architecture/gitoxide-accepted-tree-data-plane-v1.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->

# Gitoxide candidate and accepted-tree read data plane v1

状态:建立在 Gitoxide repository admission/source import 之上的 enabling infrastructure。

## 1. 主要不变量

本切片只证明:

> owner-bound accepted-repository capability 只能读取被冻结的 exact accepted SHA-1 commit/tree,或
> 从该 exact base 生成 operation-bound immutable candidate proof。candidate 不能推进 accepted ref,
> 也不能签发新的 accepted capability。

SQLite accepted head 仍由后续 mutation authority 拥有。本切片不提供 filesystem projection;projection
必须由 storage-root owner 在后续 PR 中以独立 destination capability 和 crash protocol 实现。

## 2. Owner、原子边界与能力

- import authority 在任何 destination side effect 前验证 helper 的 operation feature attestation;导入成功
后只在固定 `refs/maka/accepted` namespace 捕获 helper capability、managed repository path、accepted
commit、tree 与 policy v3,并签发
opaque accepted-repository capability;
- candidate helper 同时绑定 exact base commit/tree、accepted ref、operation-specific candidate ref、path
与 result bytes;完整 verified walk 后,tree editor 仍只通过 checksum-verifying finder 加载 owned tree,
禁止重新信任未验证 ODB bytes;
- published 与 no-change 都创建包含 request digest 的 deterministic candidate receipt commit,并以同一个
operation-specific ref 作为线性化点;两种成功都返回 owner-bound candidate-outcome capability;
- accepted ref 与 candidate ref 都必须是直接指向 exact commit object 的 direct ref;symbolic ref 与
annotated tag 不得通过 peel 后的语义相等冒充 receipt identity;
- candidate outcome 私下绑定 exact accepted capability identity、repository/ref、helper artifact、policy、
request digest、result SHA-256 与 Git identities;验证时必须同时出示原 accepted capability;
- direct read 沿 accepted tree 的 exact path 加载并重验 tree/blob object identity,只返回最多 8 MiB 的
UTF-8 内容;它不读取 projection filesystem;
- 每个公开入口都复用 admission 时捕获的 helper capability,并在短生命周期 helper 启动前重新验证
artifact identity。

## 3. 失败与回滚

| 状态 | 处理 |
| --- | --- |
| accepted ref 在初次检查时不等于 capability base | 写 object 前返回 `base_commit_mismatch`,candidate ref 不存在 |
| accepted/candidate ref 是 symbolic ref 或指向 tag/非 commit object | 稳定返回 direct-ref/target-invalid 错误 |
| base commit/tree identity 不一致 | 写 object 前 fail closed |
| candidate 违反 policy v3 | candidate ref CAS 前 fail closed |
| candidate ref 已存在且 request digest 不同 | 写 object 前返回 `candidate_request_conflict`,不覆盖已有 candidate |
| result 与 base tree 相同 | 写入 same-tree receipt commit 并 CAS operation ref,返回 `candidate_no_change` outcome capability |
| 同一 operation 后续给出不同 path/content/disposition | deterministic commit 不同,稳定 conflict |
| direct read 路径、类型、大小、UTF-8 或 object identity 不合法 | fail closed,不读取 filesystem |
| helper 超时、中断或输出不匹配 | 不签发新 capability;由调用者重试 exact operation 或 park |

candidate outcome 的线性化点是 operation-specific direct candidate ref 的 `MustNotExist` CAS。任何 object
write 前先检查既有 direct receipt:request digest 相同则完整重验 receipt/tree/result 后 exact retry,request
不同则稳定 conflict。CAS 竞争失败后再次重读 direct ref:相同 deterministic commit 视为 exact retry,不同
commit 视为 conflict;无法证明 publication 状态时返回 `candidate_publication_indeterminate`。

accepted ref 在本切片中只读,并与 `refs/maka/candidates/<operation-hash>` namespace 不重叠。第二次 accepted
ref 检查与 candidate CAS 不是一个跨 ref transaction:二者之间的 accepted drift 可能留下绑定旧 base 的
stale candidate evidence,但不能推进 accepted truth。后续 SQLite acceptance 必须重新验证 canonical head 并
拒绝 stale candidate。direct read 是 observation,不发布持久事实。

## 4. 平台与资源边界

- Linux/macOS/Windows 使用同一 Gitoxide protocol;本切片不写工作区 filesystem;
- policy v3 的 path、Unicode fold、tree/blob、`.gitattributes` 和 object identity 规则只由 Rust helper
判定;TypeScript 只负责 transport byte bound,避免复制一份会漂移的 path policy;
- candidate 和 direct read 的绝对 deadline 为 10 分钟;
- candidate content 通过 bounded Base64 field 传输,64 MiB 业务上限与 JSON escaping 无关;
- direct read 单文件最多 8 MiB,helper stdout 以 JSON worst-case escaping 设置固定上限。

## 5. 后续依赖

后续 mutation lifecycle 把 accepted capability 与 SQLite T1 reservation 绑定;SQLite 原子接受 candidate
后,单独的 promotion/reconcile owner 才能更新 accepted-ref projection 并签发新 accepted capability。
Desktop/CLI 消费者不得绕过 capability 直接传 repository path、helper path 或 accepted commit。

当前 accepted/candidate capability 是进程内 opaque authority。Git candidate ref/receipt commit 跨进程耐久,
但 Host crash 后重新签发 capability 需要后续 durable workspace receipt owner:它必须重开 exact repository、
持有 storage-root lease,重验 direct accepted/candidate ref、receipt commit checksum、request digest、base
parent、candidate tree 与 path/result blob,再允许 SQLite 接受。本切片的 exact retry 承诺覆盖同一进程及
helper process response loss;不把尚未接线的 cross-Host reopen 或 candidate GC 宣称为已完成能力。
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ capability 表示一次明确线性化点上的 immutable Git commit/tree snapsh
6. exact commit/tree/blob checksum verification、atomic destination claim 与 deterministic zero-parent
baseline publication。

`managedTreePolicyVersion: 2` 是当前唯一的 **portable lexical materialization policy**,而不只是 Git
`managedTreePolicyVersion: 3` 是当前唯一的 **portable lexical materialization policy**,而不只是 Git
object import policy。未发布的 policy v1 已删除;helper、Host capability 和 import response 都拒绝把
version 1 重新解释成当前语义。v2 只证明 Git tree 的词法身份和受支持 attributes 满足同一套保守规则,
不宣称已证明某个真实 Windows volume 上的 path-length、8.3 alias、ACL 或大小写能力。
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ hook/filter/submodule/LFS,也不接入 T1/T2。
process-crash 自动恢复或断电恢复;
- Windows 保留 Git tree 中的 executable bit,不把它映射成 ACL 权威。

上述规则是 portable lexical materialization policy v2。它不证明 Windows path-length、8.3 alias 或
上述规则是 portable lexical materialization policy v3。它不证明 Windows path-length、8.3 alias 或
目标 volume 的大小写行为;这些能力必须由未来 projection owner 的
`FilesystemMaterializationProfileV1` 在 fresh destination 上独立验证。v2 import 只验证 attributes
语义并复制 immutable objects;真正 materialize 和 candidate 写回必须消费同一 policy,并对受支持文本
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ manifest 以 Buffer 读取 Git `ls-tree -r -z`,按 Git canonical 顺序记录
拒绝不能无损解码并 round-trip 的非 UTF-8 path;不会把 replacement character 写进摘要。M0 只接受
普通 blob mode `100644` / `100755`;symlink、submodule、special mode 与 case collision 继续由 Git
Workspace Service 在 receipt 生成前拒绝。现有 Git CLI adapter 仍拒绝 `.gitattributes`;替代它的
Gitoxide data plane 只接受 managed tree policy v2 已验证的确定性 attributes 子集,不能把两条路径的
Gitoxide data plane 只接受 managed tree policy v3 已验证的确定性 attributes 子集,不能把两条路径的
receipt 或 materialization profile 混用。

该摘要证明的是 Git object delta,不是 checkout 文件字节扫描,也不把 ignored/untracked 内容纳入
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->

# Managed Mutation Lifecycle Authority v1

## 1. 交付边界

本切片只证明一个主要不变量:

> 从 managed Write/Edit 的 T1 持久化开始,到可信 terminal state 为止,同一个 workspace instance
> 只能存在一个 durable mutation owner;成功 outcome、successor workspace version 与 canonical head
> 必须同时可见或同时不可见;T1 以后 Runtime 不得静默回退到 generic T2。
本切片是后续 Git candidate 与 Write/Edit 生产接线的 persistence/runtime authority。它不创建 managed
worktree、不执行文件写入、不引入 Git 或 npm 数据面,也不向 Desktop/CLI 开放新模式。没有直接产品消费者
不是本切片的 correctness 缺陷;后续消费者必须通过这里的 internal capability,而不能复制写入逻辑。

## 2. Owner

| 事实或能力 | 唯一 owner | 代码约束 |
| --- | --- | --- |
| immutable T1 与 managed mutation identity | `SqliteRuntimeStore.commitToolPrepared()` | T1 与 reservation 在同一 SQLite transaction 中提交 |
| active mutation ownership | SQLite reservation projection | `workspace_instance_id` 主键跨进程仲裁;投影可从 RuntimeEvents 重建 |
| accepted successor 与 canonical head | workspace successor authority writer | 只消费 repository owner 验证后的 opaque candidate capability;generic writer 不能写 reserved fact |
| live provider result | `ToolRuntime` | 在 operation 返回边界生成 bounded strict-JSON immutable snapshot |
| terminal durable proof | managed admission owner | Runtime 只 adopt 已提交的 exact outcome envelope,不代写 managed T2 |

`RuntimeEvents` 是 durable truth;workspace head 与 reservation 表只是可删除、可重建的投影。internal writer
通过未导出的 registration/capability seam 暴露,不能依靠注释约束调用者。

当前切片没有生产消费者,在线 authority 校验继续直接读取 immutable RuntimeEvents,避免为了尚未确定的
生产查询形状提前增加 SQLite schema/index 合同。接入真实 Write/Edit consumer 前,必须基于实际访问模式
引入不依赖可重建 projection 的有界索引读取;完整 rebuild 仍以 RuntimeEvents 为唯一事实源。

## 3. T1 冻结内容

`toolDispatch.managedMutation` 在 T1 前一次性冻结:

- repository/workspace/epoch/instance identity;
- base workspace version、accepted event、head revision、commit/tree;
- 与 durable Write/Edit `args.path` 完全相同的单一 canonical path;
- Gitoxide path policy v3;
- Runtime 固定的 managed transform/profile digest;
- v2 当前唯一支持的 SHA-1 object format。

Storage 在同一个 T1 transaction 内重新比较 function call path 与授权 path,caller 不能自报另一组路径。
完整路径语义由 Gitoxide policy v3 owner 在后续组合层签发;本切片只持久化其版本和 canonical 结果,不复制
另一套 Git path parser。durable mode 在 T1 前确定;如果 admission 不可用,必须在 T1 前拒绝。T1 后缺失
terminal proof、proof 畸形或 owner 异常一律 fail-stop,禁止 generic fallback。

## 4. 原子性边界

### 4.1 T1 与 reservation

单个 `BEGIN IMMEDIATE` transaction 完成:

1. 校验 immutable function call 与 dispatch;
2. 校验 T1 所引用的 workspace base 正是当前 canonical head;
3. 写入 call/dispatch RuntimeEvents;
4. 写入 tool projection;
5. 获取 `workspace_instance_id` 的唯一 reservation。

冲突 transaction 不产生部分 T1,也不会覆盖已有 owner。

### 4.2 terminal successor

单个 SQLite transaction 完成:

1. 验证 success `function_response` 与原 operation identity;
2. 通过注册的一次性 verifier 消费 opaque candidate capability;raw commit/tree/path 描述没有提交权限;
3. 验证 successor 的 parent/base/path/profile 与 T1 完全一致;
4. 写入 outcome RuntimeEvent;
5. 写入 successor workspace fact;
6. 更新 disposable version/head projections;
7. 释放 durable reservation。

任一步失败则整组 rollback。失败 outcome 不得推进 head。旧 operation 的 exact retry 根据 immutable
successor 返回原结果,不要求它仍是当前最新 head。

### 4.3 no-effect terminal

`no_workspace_change` 与 `operation_failed_no_effect` 各自拥有明确的 terminal kind。专用 writer 在一个
transaction 中写入 function response + reserved terminal action,并释放 reservation;workspace head 保持
不变。generic T2 无权写该 action。projection rebuild 根据 immutable terminal 判断 reservation 已结束,
不会把它重新激活。

## 5. Runtime 线性状态机

managed operation capability 由 Runtime 持有,生命周期为:

```text
open -> running -> settled -> closed
```

- capability 只能执行一次;terminal settlement 后 retained callback 失效;
- detached operation 必须 join,不能先结算再产生副作用;
- Runtime 只执行工具单独提供的 pure managed transform;普通可变 `tool.impl` 在该路径永远不会调用;
- Runtime 在一次有界 strict-JSON traversal 中复制并冻结结果;默认上限为 1 MiB、64 层、65,536 nodes、
65,536 properties 和 65,536 array items;caller 只能进一步收紧,不能放宽;
- `undefined`、稀疏数组、非有限数字、原型污染形状和超出 byte budget 的结果在 durable publication 前拒绝;
- live provider result、message、telemetry 与 durable envelope 都读取同一个 snapshot;
- successor success、no-change success、failed-no-effect 与 unsettled 都不能触发 generic `commitOutcome()`。

## 6. 失败状态与回滚

| 失败点 | durable 状态 | 行为 |
| --- | --- | --- |
| T1 transaction 前或内部 | 无 managed T1/reservation | rollback;允许重新 admission |
| T1 commit 后、terminal 前 | prepared + active reservation | fail-stop;禁止另一 mutation 获得 ownership |
| terminal transaction 内 | prepared + active reservation | rollback;不发布 provider result |
| terminal commit 后响应丢失 | immutable outcome + successor + released reservation | exact retry/adoption,不重写 generic T2 |
| no-effect terminal commit 后响应丢失 | immutable outcome + terminal + released reservation | exact retry/adoption;head 不变 |
| projection 缺失 | immutable facts 保留 | 从 RuntimeEvents rebuild |
| projection 与 facts 不一致 | corruption | fail closed,不猜测修复 |

本切片不定义文件副作用恢复;当 T1 已提交但外部 execution/candidate owner无法证明 terminal 时,reservation
保留是有意的 parked 状态,交由后续 recovery owner 处理。

## 7. 平台能力矩阵

本切片只依赖 SQLite transaction、WAL 与进程间数据库锁,不执行平台文件 mutation。

| 能力 | Linux | macOS | Windows |
| --- | --- | --- | --- |
| T1 + reservation 原子提交 | 承诺;Linux storage stress lane | 实现预期;当前 PR 无独立 macOS recovery gate | 承诺;Windows recovery lane |
| 同 workspace instance 多进程唯一 owner | 承诺;真实双进程测试 | 实现预期;发布证据待补 | 承诺;真实双进程测试 |
| terminal successor bundle 原子提交 | 承诺 | 实现预期;发布证据待补 | 承诺 |
| process-crash 后从 facts 重建 | 承诺;真实 child process | 实现预期;发布证据待补 | 承诺;真实 child process |
| power-loss 后硬件级持久顺序 | 继承 SQLite/OS 合同,不额外扩大承诺 | 同左 | 同左 |

这里不把“代码跨平台”冒充“平台恢复证据”。macOS 在加入独立 recovery gate 前不构成发布承诺;普通单元
测试也不能替代真实 child-process kill/reopen 与双进程竞争。

## 8. Production-shaped evidence

当前测试覆盖:

- child process 在 T1 transaction 内退出:整组 rollback;
- child process 在 T1 commit 后退出:reservation 保留;
- 两个真实进程竞争同一 workspace instance:只有一个获得 reservation;
- child process 在 successor transaction 内退出:outcome/successor/head 全部 rollback;
- child process 在 successor commit 后退出:exact retry 返回已接受结果;
- child process 在 no-effect terminal transaction 内/commit 后退出:分别 rollback 或保留 terminal 并释放 reservation;
- 删除 projection 后从 immutable RuntimeEvents 重建 head 与 reservation;
- Runtime owner 的 retained callback、detached operation、mutable result、oversized/non-JSON result 对抗测试;
- managed T1 后所有异常路径的 generic T2 调用次数为零。

## 9. 后续消费者合同

后续 Git candidate/Write/Edit PR 必须:

1. 在 T1 前取得并冻结 Gitoxide policy v3 path admission,并提供独立 pure Write/Edit transform;
2. 只通过本 authority 提交 terminal successor;
3. 对 T1 后的不确定 effect 返回 unsettled,不能自行清理 reservation;
4. 用 production-shaped Host/worker crash test 证明不会重放副作用;
5. 不把本切片的 internal writer 提升为通用 public append API。

## 10. 回滚方式

在尚无 production consumer 时,代码回滚可整体移除 managed dispatch extension、reservation projection 与
Runtime settlement seam;schema migration 保持 append-only,不复用版本号。若已有数据库升级,降级 binary
必须按既有 newer-schema 防护 fail closed,不能尝试写入未知 schema。
Loading