Metadata-Version: 2.4
Name: worktree-runtime
Version: 0.1.0
Classifier: Development Status :: 5 - Production/Stable
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Rust
Classifier: Typing :: Typed
Requires-Dist: pytest>=8.0 ; extra == 'dev'
Requires-Dist: pyyaml>=6.0 ; extra == 'dev'
Requires-Dist: mypy>=1.14 ; extra == 'dev'
Provides-Extra: dev
License-File: LICENSE
Summary: Worktree identity, binding persistence, and checkout substrate
Author: bamboocity
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Changelog, https://github.com/bamboocity/worktree-runtime/blob/main/CHANGELOG.md
Project-URL: Repository, https://github.com/bamboocity/worktree-runtime

# worktree-runtime

Library for worktree **identity**, **binding persistence**, **checkout
validation**, and **path resolution**.

Consumers (adaptive-task / Noveler) call this so they do not each invent
project id, session↔worktree binding, main-vs-linked checks, or
state / shared paths. The public symbol list is
[`src/worktree_runtime/SURFACE.yaml`](src/worktree_runtime/SURFACE.yaml).

Binding store API: `register_binding`, `load_binding`, `recover_binding`,
`list_bindings`, and `remove_binding`. `git worktree remove` and vanish stay
in the consumer.

Rust is the implementation SSOT. Python is a shim, typing stubs, contract tests,
and a thin audit CLI. Missing native support is an install error; there is no
silent Python fallback in this project.

## Scope

This crate answers four questions and records consumer mutations:

| Responsibility | What the library does |
| --- | --- |
| Identity | Resolve project id, main branches, GitHub policy, and the `NOVELER_*` / location env catalog from cwd, env, git, and project config. |
| Binding | Persist, load, recover, and validate a session↔worktree record (`WorktreeBinding`). Reject before treating a cwd as bound. |
| Checkout | Resolve a `GitWorktree` (`rev-parse`), classify main vs linked, list porcelain entries, emit reason codes. |
| Path | Resolve worktree base / dir / state dir / known bases with fixed precedence. `NOVELER_WORKTREE_BASE` and `config/worktree.yaml` overrides apply only when `CI` / `GITHUB_ACTIONS` is set; elsewhere the base is `~/.adaptive-task/worktrees/<project_id>`. Normalize and fingerprint paths. |

Audit (`record_event` / `read_records` / rotation, plus
`presentation/audit_cli.py`) is append-only logging of consumer git
mutations (`worktree_remove`, `branch_delete`). It is not a session log.

### Out of scope

- **Agent isolation.** Codex Desktop, Cursor, and Claude Code create a
  worktree (or checkout) so one chat does not dirty the user's main tree.
  That sandbox is a different layer. This package does not replace it.
- **Session orchestration.** `adaptive-task init` / `next` / `report` stay
  in the consumer.
- **Prep / vanish / cleanup hooks.** Detecting a disappeared worktree,
  refusing cleanup, and running merge-cleanup tooling stay in adaptive-task.
- **`git worktree add` / `remove` as a product operation.** This crate
  resolves locations and validates state. The consumer mutates git.

Using Codex Desktop only as an editor does not require importing this
package. Running adaptive-task identity, binding, or path policy still does.
Agent isolation worktrees and session worktrees can nest. Config may move
the session base when `CODEX_CLI` or `CLAUDE_CODE` is set. That override
exists because the two layers meet; it does not make this library redundant.

## Architecture

```mermaid
flowchart LR
    callers["consumers"] -->|"worktree_runtime.api"| shim["Python shim and stubs"]
    shim --> pyo3["PyO3 binding"]
    pyo3 --> core["Rust core"]
    contract["contract pytest"] -->|"black-box"| shim
    cargo["cargo test"] --> core
    release["maturin wheels"] --> callers
```

## Layout

Layout rationale is in [DESIGN.md](DESIGN.md).

- `crates/worktree_runtime_core/` — behavior SSOT
- `crates/worktree_runtime_pyo3/` — Python C-API translation only
- `src/worktree_runtime/` — `api` re-export, `.pyi`, `SURFACE.yaml`, `presentation/audit_cli.py`
- `src/_worktree_runtime_rust/` — placeholder package that hosts the cdylib built by maturin (`python-source = "src"`)
- `tests/contract/` — `from worktree_runtime.api import ...` only; `tests/cli/` — audit CLI exit codes

Distribution name is `worktree-runtime`. Import name is `worktree_runtime`.
`pyproject.toml` version and `Cargo.toml` `workspace.package.version` must match.
The crate is proprietary (`LICENSE`; all rights reserved). CI uses the `stable` toolchain with rustfmt and clippy.

## Change protocol

Multi-file, refactor, behavior, or core+pyo3+facade+contract work: run
`adaptive-gate` first ([AGENTS.md](AGENTS.md) Routing). Testing policy:
`.cursor/rules/testing.mdc`.

1. Behavior: add a failing cargo execution test, then implement in
   `worktree_runtime_core` and run `cargo test`.
2. Public-surface shape only: update `SURFACE.yaml` and `.pyi`, plus a thin
   contract assertion under `tests/contract/`. Do not put behavior suites in
   pytest.
3. Export through PyO3; keep the shim as a re-export.
4. When the public surface changed, build a wheel and run the contract and
   CLI pytest. `cargo fmt --check` and `clippy -D warnings` are required.

The verify loop (commands, hook setup, release steps) is defined once in
[BUILD.md](BUILD.md).

## Build

See [BUILD.md](BUILD.md). CI always runs fmt, clippy, cargo test, maturin,
contract+CLI pytest, `mypy.stubtest`, and an MSRV check, through
`.github/actions/rust-checks`.
Wheels are `abi3-py310` (CPython 3.10+) for Windows amd64, macOS x86_64 and
arm64, and manylinux x86_64 / aarch64. Pure-Python wheels are not published.

