Skip to content
Open
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
1 change: 1 addition & 0 deletions COMPATIBILITY.md

Large diffs are not rendered by default.

415 changes: 396 additions & 19 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ categories = ["command-line-utilities", "development-tools"]
readme = "README.md"

[features]
default = []
default = ["scorpiofs-direct"]
scorpiofs-direct = ["dep:scorpiofs"]
worktree-fuse = [] # Unix FUSE-backed worktree commands (optional)
test-network = [] # L2: tests requiring outbound network but no secrets
test-live-ai = [] # L3: tests calling real LLM APIs
Expand Down Expand Up @@ -70,6 +71,7 @@ sea-orm = { version = "2.0.0", features = [
]}
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
fs2 = "0.4.3"
sha1 = "0.11.0"
sha2 = "0.10"
thiserror = "2.0.18"
Expand Down Expand Up @@ -158,6 +160,7 @@ rfuse3 = { version = "0.0.8", features = ["tokio-runtime", "unprivileged"] }

[target.'cfg(target_os = "linux")'.dependencies] # Linux-only seccomp BPF compiler
seccompiler = { version = "0.5.0", features = ["json"] }
scorpiofs = { version = "=0.4.0", optional = true }

[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.61.2", features = ["Win32_Storage_FileSystem"] }
Expand Down
38 changes: 38 additions & 0 deletions docs/commands/worktree.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Manage multiple working trees attached to this repository.

```
libra worktree add <path>
libra worktree scorpiofs attach --remote-path <mega-path> --job-id <id>
libra worktree scorpiofs detach <mountpoint>
libra worktree list
libra worktree doctor
libra worktree lock <path> [--reason <text>]
Expand All @@ -26,6 +28,12 @@ libra worktree doctor [<workspace-id>] [--limit <n>] [--cursor <cursor>]

`libra worktree` manages multiple working trees that share a single repository database and object store. This allows you to have several checkouts of the same repository simultaneously, which is useful for working on multiple branches at once, running builds while editing code, or testing changes in isolation.

Mounted worktrees use the backend-neutral architecture documented in
[`worktree-storage-backends.md`](../development/integration/worktree-storage-backends.md).
ScorpioFS is a remote-revision projection backend; BrewFS is modeled as a
persistent distributed-volume backend. Git objects, refs, index state, and
authoritative backend lifecycle state remain owned by Libra.

Each linked worktree is a directory containing its own real `.libra` gitdir — a local directory (not a symlink) that holds the worktree's private `HEAD`, index, and `HEAD` reflog, plus a `commondir` pointer to the shared storage and a stable `worktree_id`. The main worktree is the original repository directory. All worktrees share the same SQLite database, object store, branch/tag/remote refs, and configuration, but each keeps its own checked-out branch and staging state. (A worktree created by an older Libra version may still use the legacy shared-`.libra` symlink layout; `libra worktree doctor` reports it, and `libra worktree repair --migrate-layout --dry-run` previews the migration read-only.) The registry file `worktrees.json` is versioned (`schema_version: 3`; v2 since v0.19.57): each linked entry persists its stable `worktree_id`, a legacy v1 file is upgraded in place by the first mutating worktree command (ids backfilled from each worktree's gitdir; lockless readers like `worktree list` read a v1 file without rewriting it), and older binaries are refused at the database layer before they can misread or rewrite the file. v3 adds a durable registration GENERATION — `epoch_counter` on the registry and `epoch` on each entry, reported by `worktree list`. Instance ids are path-derived, so a worktree removed and re-added in the same place has the same id and path as its predecessor; the generation is what tells the two registrations apart, and the `libra service` dirty-mark endpoint requires it as a fence. A v2-era binary would parse a v3 file and drop the generations on rewrite, so the v3 capability marker refuses those binaries at connect time; for the same reason this migration does not roll back while any generation is live.

**Resolving an ambiguous registry.** A registry written by an older binary can end up with two entries claiming one path-derived identity (`add A` → `move A B` → `add A`). Every worktree MUTATION is refused while that holds — including the `remove` that would fix it, because it goes through the same loader. `libra worktree doctor` names the colliding entries, and `libra worktree repair <path> --resolve-identity --yes` is the one action that runs against the ambiguous registry: it DETACHES the named entry (files and scoped state kept, every command inside that directory fails closed) so the remaining claimant owns the identity again. Finish with `worktree remove --delete-dir <path>`, or `worktree add <path>` to re-attach it.
Expand Down Expand Up @@ -67,6 +75,36 @@ libra worktree add --detach ../probe v1.2.0
libra worktree add -b topic ../topic main
```

### Subcommand: `scorpiofs attach`

Creates or recovers an idempotent Antares mount, waits for readiness, and
attaches persistent Libra linked-worktree metadata to the returned mountpoint.
By default on Linux, Libra starts a resident worker that links the ScorpioFS
crate directly. Libra owns the worker and desired mount state in
`.libra/scorpiofs/state.json`; ScorpioFS owns only live filesystem
materialization. Libra also continues to own the index, objects, commits,
refs, fetch, and push.

```bash
libra worktree scorpiofs attach \
--config-path scorpio.toml \
--remote-path /project/aardvark-dns \
--job-id dev-aardvark
```

Pass `--endpoint http://127.0.0.1:2725/antares` to use an externally managed
ScorpioFS daemon as a compatibility transport instead.

### Subcommand: `scorpiofs detach`

Refuses to detach a dirty worktree, removes its persistent linked-worktree
metadata, and asks Antares to delete the mount by job ID. Repeated remote
cleanup is idempotent.

```bash
libra worktree scorpiofs detach /var/lib/antares/mounts/<mount-id>
```

### Subcommand: `list`

List all registered worktrees and their state. `--porcelain` emits a stable,
Expand Down
1 change: 1 addition & 0 deletions docs/development/commands/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
| [`credential`](credential.md) | `partial` | Vault-backed Git credential helper `fill`/`store`/`erase`; AES-256-GCM-encrypted, keyed by a digest of protocol/host/path; side-channel-free `fill` (hit/miss both exit 0); expiry (default 30d); secrets never logged/echoed. `credential-cache`, multi-username, and the consumer-side helper chain deferred |
| [`describe`](describe.md) | `partial` | basic describe, `--tags`, `--always`, `--abbrev`, `--exact-match`, `--long`, `--dirty[=<mark>]`, `--first-parent`, `--match`, `--exclude`, `--candidates` (0 ⇒ exact-match), `--all` (any ref, prefixed), and `--contains` (git name-rev: nearest descendant tag, `<tag>~<n>^<m>` form) supported |
| [`service`](service.md) | `intentionally-different` | 无头本地服务(lore.md 1.11):notification v1 总线 + 令牌门 dirty 标记摄入;双重环回强制,绝不开对外端口 |
| [`scorpiofs-worker`](scorpiofs-worker.md) | `intentionally-different` | 隐藏的 Libra 自有 ScorpioFS 常驻 worker,非 Git 命令:由 `worktree scorpiofs attach` 从 Libra 自身可执行文件拉起,直连 ScorpioFS crate(Linux + `scorpiofs-direct` feature),只暴露环回控制端点;内嵌服务不持久化、不自恢复状态,权威状态留在 Libra 侧 |
| [`auth`](auth.md) | `intentionally-different` | 主机作用域 HTTP 令牌 v1(lore.md 1.6):加密落盘、过期检测、免解密撤销、降级重定向拒绝 |
| [`commit-tree`](commit-tree.md) | `partial` | 低层修订组合(lore.md 1.15):tree+parents+message→commit 对象,零副作用;配合 --index-file scratch 索引 |
| [`revision`](revision.md) | `intentionally-different` | 修订序号索引(lore.md 1.16):逐 ref first-parent 链 1..N,tip+replace 指纹每读校验,快进追加/重写重建 |
Expand Down
44 changes: 44 additions & 0 deletions docs/development/commands/scorpiofs-worker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# `libra scorpiofs-worker` 开发设计

## 命令实现目标

`libra scorpiofs-worker` 是隐藏的常驻 worker(`hide = true`),不面向用户直接调用。它存在的唯一理由是生命周期不匹配:Libra 的公开 CLI 是短命进程,而一次 FUSE 挂载必须在 `libra worktree scorpiofs attach` 返回之后继续存活。因此 attach 从 Libra 自己的可执行文件(`std::env::current_exe()`)拉起这个子命令,由它持有 FUSE 会话。

worker 直连 ScorpioFS crate,只监听一个环回控制端点(`--bind 127.0.0.1:<port>`,端口由 attach 预留后传入)。内嵌的 ScorpioFS 服务被显式配置为**不持久化、不自恢复**状态:权威的期望状态始终留在 Libra 侧(`.libra/scorpiofs/` 下的 `LibraScorpioFsState`),worker 崩溃后由下一次 attach 重建,而不是由 ScorpioFS 自己恢复。

## 对比 Git 与兼容性

- 兼容级别:`intentionally-different`。Git 没有对应命令。
- 平台/特性门:仅在 `target_os = "linux"` 且启用 `scorpiofs-direct` feature 时可用。其他组合下命令本身仍然存在(保持 CLI 表面稳定),但立刻以 `LBR-UNSUPPORTED` 拒绝,并提示改用 `worktree scorpiofs attach --endpoint <url>` 的兼容 HTTP 模式。
- 参数全部是必填的内部契约,不做用户级校验糖:`--config-path`、`--bind`、`--upper-root`、`--cl-root`、`--mount-root`、`--runtime-state-file`。
- 命令作用域(`src/cli.rs::command_scope`)登记为 `Repository`——与 `libra service` 同形态:按写者归类以免作用域被低估;同时它被列入 `command_holds_shared_maintenance_lock` 的长驻豁免名单,否则挂载存活期间会一直持有共享 maintenance 锁,饿死每一个删除阶段。

## 设计方案

- 入口与分发:`src/cli.rs::Commands::ScorpiofsWorker`(`hide = true`)→ `command::scorpiofs_worker::execute_safe`。
- 源码分层:`src/command/scorpiofs_worker.rs` 只做参数转译与错误包装;挂载编排、期望状态与回滚都在 `src/internal/scorpiofs_backend.rs`,后者实现 `src/internal/worktree_backend.rs` 定义的后端中立接口。
- 配置优先级:路径类参数经 `scorpiofs::cli::antares_overrides` 转成 config override map 后交给 `util::config::init_config_with`,以保持 ScorpioFS 文档承诺的 `CLI > env > file > default` 次序,而不是事后改写 `AntaresPaths`。
- 日志:attach 侧把 worker 的 stdout/stderr 追加重定向到 `.libra/scorpiofs/worker.log`,worker 自身不另开日志文件。

```mermaid
flowchart TD
A["worktree scorpiofs attach"] --> B["预留环回端口 + 建运行目录"]
B --> C["spawn current_exe() scorpiofs-worker<br/>stdout/stderr → .libra/scorpiofs/worker.log"]
C --> D["scorpiofs_worker::execute_safe"]
D --> E["cli::antares_overrides → config::init_config_with"]
E --> F["AntaresServiceImpl::new_external_state(None)"]
F --> G["AntaresDaemon::serve(127.0.0.1:port)"]
A --> H["HttpScorpioFsClient 轮询 /health 直到 ready"]
H --> G
```

## 当前状态

- 已实现:托管 worker 的拉起、健康探测、失活检测(worker 消失时把 `ManagedCrate` 传输的挂载标记为 `RecoverableError` 并要求重新 attach)、detach 时在最后一个挂载消失后停止 worker。
- 依赖:`scorpiofs = "=0.4.0"`(Linux-only、optional)。

## 还未实现的功能

- worker 自身没有重启/看门狗:进程消失后由下一次 attach 重建,期间已挂载路径不可用。
- 没有多仓库共享 worker:运行目录按 storage 路径哈希隔离,每个仓库一个 worker。
- 非 Linux 平台没有直连模式,只能走 `--endpoint` 兼容 HTTP 模式。
Loading
Loading