Skip to content

docs: document the library API and karet integration contract - #108

Merged
justin13888 merged 3 commits into
masterfrom
docs/101-library-api
Aug 29, 2026
Merged

justin13888 merged 3 commits into
masterfrom
docs/101-library-api

Conversation

@justin13888

Copy link
Copy Markdown
Contributor

Documents the surface karet consumes, and closes two holes in it that
writing the documentation exposed.

Closes #101

Why there was nothing to point karet at

The embedding surface exists — feature gates (#94), the stateless Workspace
API (#95), wt.schema and the advisory lock (#99) — but it was never written
down anywhere a consumer would look. The README's 295 lines never mentioned
cargo features, default-features = false, Workspace, the wt.<branch>.*
keys, SCHEMA_VERSION or locking. The only records were comments in
Cargo.toml and rustdoc on individual items.

What is documented

A new ## Using wt as a library README section covering #101's six topics, and
rustdoc on the items themselves so the README is not the only source:

Topic Where
Consuming with default-features = false; wt::… despite the kono-wt package README, src/lib.rs
Workspace, and the no-prompting/no-stdout contract that makes it embeddable README, src/worktree/mod.rs
Resolving paths through the template rather than reimplementing the layout README, src/template.rs
The wt.<branch>.* keys, what is additive-safe, and the wt.schema gate README, src/config/wtconfig.rs
Locking: what takes it, what a caller must not hold it across, signal handling README, RepoLock
The generation/work split README

Two API holes this turned up

SubmoduleSeeding was unnameable. CreatedWorktree::submodule_seeding is
a public field, but its type lived in the private service module and was
never re-exported — an embedder could read the field and had no way to name
what it got back. Proved from outside the crate before fixing:

error[E0425]: cannot find type `SubmoduleSeeding` in module `wt::worktree`

No crate-internal test can catch this, because service is visible in-crate.
The guard is therefore a doctest, which compiles as its own crate — it
fails exactly when an outcome struct exposes a type the public API does not
export. Verified it has teeth by reverting the export: the doctest fails with
the same unresolved import.

RemovedWorktree was not #[non_exhaustive], unlike its siblings
CreatedWorktree and SubmoduleSeeding. Sealing it is safe now and not
later: neither type is in v1.5.0 and the v1.6.0 release PR (#103) is still
open, so no published consumer can break — whereas leaving it open makes every
field added afterwards a breaking change.

The example is compiled, not written

The worked example is extracted from the README, compiled against this branch
as an external crate with default-features = false, and then run against a
real repository. It creates a worktree at the template path and records
metadata:

main	…/embedrun/demo
…/embedrun/demo.worktrees/demo-feat-login
wt.feat/login.baseref main
wt.feat/login.createdbywt true

That is what caught the one defect in the prose: Worktree::branch is
Option<String>, so the obvious listing loop does not compile. A README
snippet nothing builds is how documentation rots, and this section is the one
karet will follow literally.

The same scratch crate also confirms every type the prose names is reachable
with the default features off.

Also: rustdoc is now warning-free

cargo doc --no-deps emitted 5 warnings on master, three of them broken links
in the public API being documented here (worktree linked to the private
service and rows modules; JobKey linked to a private field). All 5 are
fixed; the command is clean.

Validation

gate result
mise run test 878 passed + 1 doctest, 0 failed
mise run lint clean (-D warnings)
mise run format-check clean
mise run check-core 361 (--no-default-features) + 621 (--features cli) passed
mise run coverage 92.65% lines (gate: 80%)
cargo doc --no-deps 0 warnings (was 5)
external crate, default-features = false builds and runs

Note for the reviewer

The #[non_exhaustive] addition is only non-breaking while #103 is unmerged.
If #103 lands before this does, that one line needs revisiting — the rest of
the PR is unaffected.

`CreatedWorktree::submodule_seeding` is a public field, but its type lived in
the private `service` module and was never re-exported — so an embedder could
read the field and had no way to name what it got back. A crate-internal test
cannot catch that, since `service` is visible in-crate, so the regression guard
is a doctest: it compiles as its own crate and fails exactly when an outcome
struct exposes a type the public API does not export.

`RemovedWorktree` gains `#[non_exhaustive]`, matching `CreatedWorktree` and
`SubmoduleSeeding`. Both types are unreleased — neither is in v1.5.0 and the
v1.6.0 release PR is still open — so sealing it now costs no consumer a break,
whereas leaving it open makes every field added later a breaking change.

The module doc also stops linking to the private `service` and `rows` modules,
which rustdoc could not resolve.

Claude-Session: https://claude.ai/code/session_014ce9P64RKbVU6kj3GmA1mo
An embedder reading the signatures cannot see the rules that matter most:
which module owns path resolution and why reimplementing it is a bug, what
each `wt.<branch>.*` key means and which changes to the namespace are safe
without a schema bump, and how the crate splits into an application surface
and an engine.

Documents that on the items themselves, so the README is not the only source.

Also clears the remaining rustdoc warnings, leaving `cargo doc --no-deps`
clean: two redundant explicit link targets and a link to a private field.

Claude-Session: https://claude.ai/code/session_014ce9P64RKbVU6kj3GmA1mo
The README covered only the CLI, so the embedding surface existed solely as
Cargo.toml comments and rustdoc — nothing a consumer would find before
depending on the crate.

Adds a "Using wt as a library" section covering what karet depends on:
consuming the crate with `default-features = false` and what that drops, the
`Workspace` API and the no-prompting/no-stdout contract that makes it
embeddable, resolving worktree paths through the template module rather than
reimplementing the layout, the `wt.<branch>.*` metadata contract and the
`wt.schema` gate, the locking rules (including what a caller must not hold a
lock across), and the generation/work split.

The worked example is extracted from the README and compiled against the
library with `default-features = false`, then run against a real repository,
rather than written by hand — which is how the `Option<String>` branch field
got caught.

Claude-Session: https://claude.ai/code/session_014ce9P64RKbVU6kj3GmA1mo
@justin13888
justin13888 merged commit 30c3efb into master Aug 29, 2026
3 checks passed
@justin13888
justin13888 deleted the docs/101-library-api branch August 29, 2026 06:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: library API and karet integration contract

1 participant