Skip to content

Commit 0c5beef

Browse files
committed
feat: US-094 - Clean up docs and static terminology checks
1 parent b397dd7 commit 0c5beef

6 files changed

Lines changed: 105 additions & 130 deletions

File tree

.agent/specs/depot-dual-purpose-shards.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ Current restore point code:
295295
- `MAX_BUCKET_DEPTH` -> `MAX_BUCKET_DEPTH`.
296296
- `MAX_RESTORE_POINTS_PER_BUCKET` -> `MAX_RESTORE_POINTS_PER_BUCKET`.
297297

298-
Migration rule: this has not shipped, so do clean renames with no compatibility wrappers or dead Depot-local bucket APIs inside Depot. Remove old Depot-local bucket names from storage, API, tests, docs, metrics, and debug output in the same change.
298+
Migration rule: this has not shipped, so do clean renames with no old-name shims or dead Depot-local bucket APIs inside Depot. Remove old Depot-local bucket names from storage, API, tests, docs, metrics, and debug output in the same change.
299299

300300
## API Shape
301301

docs-internal/engine/depot.md

Lines changed: 50 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,83 @@
11
# Depot crash course
22

3-
How the v2 Depot engine reads, writes, compacts, and fences. Read this before changing anything in `engine/packages/depot/`.
3+
How the Depot SQLite backend reads, writes, compacts, and fences branchable database storage. Read this before changing anything in `engine/packages/depot/`.
44

5-
For VFS-side parity rules (native Rust ↔ WASM TS), see [sqlite-vfs.md](sqlite-vfs.md). This doc is about the storage backend that the VFS talks to.
5+
For VFS-side parity rules, see [sqlite-vfs.md](sqlite-vfs.md). For exact key formats, see [sqlite/storage-structure.md](sqlite/storage-structure.md).
66

7-
## Storage layout
7+
## Storage model
88

9-
Every actor's data lives in UDB under per-actor prefix `[0x02][actor_id]` and four kinds of suffix keys:
9+
Depot stores SQLite pages in UDB first. S3 is optional cold storage for workflow-published shard objects.
1010

11-
| Suffix | Holds | Role |
11+
| Row family | Holds | Owner |
1212
|---|---|---|
13-
| `META` | `DBHead` blob (vbare-encoded) | Per-actor header. Single key. |
14-
| `PIDX/delta/{pgno: u32 BE}` | `txid: u64 BE` | Page index. Routes pgno → which DELTA owns it. |
15-
| `DELTA/{txid: u64 BE}/{chunk_idx: u32 BE}` | LTX blob chunks | Per-commit page payloads. Multi-chunk because UDB chunks values internally past ~10 KB. |
16-
| `SHARD/{shard_id: u32 BE}` | LTX blob | Cold compacted state. 64 pages per shard. |
17-
18-
Page bytes for any pgno live in **exactly one of two places**: a DELTA blob (recent commit, not yet compacted) or a SHARD blob (compacted cold state).
19-
20-
`DBHead` (`engine/packages/depot/src/types.rs`) load-bearing fields:
21-
22-
- `generation` — fence. Bumps on takeover.
23-
- `head_txid` — last committed txid.
24-
- `next_txid` — reserved-but-not-yet-committed counter. `next_txid > head_txid` always.
25-
- `materialized_txid` — last compaction watermark. `head_txid - materialized_txid` is delta lag.
26-
- `db_size_pages` — current DB EOF in pages.
27-
- `depot_used` / `sqlite_max_storage` — quota.
28-
- `page_size`, `shard_size` — fixed at 4096 and 64 respectively.
13+
| `DBPTR` / `BUCKET_PTR` | Current database and bucket branch pointers | Conveyer branch APIs |
14+
| `BUCKET_CATALOG` | Database membership facts in bucket branches | Conveyer branch APIs |
15+
| `BRANCHES` / `BUCKET_BRANCH` | Branch records, refcounts, pin floors, lifecycle generations | Conveyer, GC, workflow checks |
16+
| `BR/{branch}/META/head` | Current database head | Commit path |
17+
| `BR/{branch}/COMMITS` and `BR/{branch}/VTX` | Commit metadata and versionstamp-to-txid lookup | Commit path |
18+
| `BR/{branch}/PIDX` and `BR/{branch}/DELTA` | Recent page-owner index and LTX delta chunks | Commit path |
19+
| `BR/{branch}/SHARD` | Reader-visible hot shard versions and cold-backed shard-cache rows | Workflow manager, cache fill, reclaimer |
20+
| `BR/{branch}/CMP/*` | Workflow manifest, cold refs, retired cold objects, staged hot output | Workflow manager and companions |
21+
| `BR/{branch}/PITR_INTERVAL` | Automatic PITR interval coverage rows | Workflow hot install and reclaim |
22+
| `RESTORE_POINT` and `DB_PIN` | User retained restore points and exact history pins | Restore point APIs and workflow proof |
23+
24+
The main invariant is simple: **commits write deltas directly to UDB; workflow compaction is the only publish/delete authority for compaction output.**
2925

3026
## Read path
3127

32-
When SQLite asks the VFS for page N, the VFS calls `get_pages(actor_id, generation, [pgno])` (`engine/packages/depot/src/read.rs`).
28+
Reads resolve the database pointer to a database branch, build a branch-aware read plan, and fetch each page through the hot path first:
3329

30+
```text
31+
1. Read branch head or fork head metadata.
32+
2. Return missing for pages above EOF.
33+
3. Check PIDX and DELTA first.
34+
4. If the DELTA is absent or reclaimed, fall back to the newest SHARD at or below the read cap.
35+
5. If no FDB SHARD covers the page, locate a matching workflow CMP/cold_shard ref and read the cold object.
36+
6. If the cold read succeeds, enqueue a bounded background fill to restore the matching FDB SHARD cache row.
3437
```
35-
1. Read META in-tx → fence + db_size_pages + shard_size
36-
2. If N > db_size_pages → return missing (above EOF)
37-
3. Look up N in PIDX:
38-
- Hit (txid T) → page N is in DELTA T
39-
- Miss → page N is in SHARD (N / 64)
40-
4. Read the chosen blob, decode LTX, extract page N's bytes
41-
5. Stale-PIDX fallback: if PIDX said DELTA T but DELTA T is missing
42-
(compaction deleted it), fall back to SHARD (N / 64)
43-
```
4438

45-
PIDX is the **routing table**. Without it, you'd scan every DELTA blob to find each pgno. With it, page N → one PIDX lookup → one blob read.
39+
Cold storage is optional. If only cold coverage can satisfy a page and the `Db` has no configured cold tier, reads fail with `ShardCoverageMissing` instead of inventing zero-filled bytes.
40+
41+
The in-process PIDX, branch-id, ancestry, and shard-cache fill queues are perf caches only. Correctness comes from UDB rows and workflow revalidation.
4642

4743
## Write path
4844

49-
When SQLite commits a transaction with N dirty pages, the VFS calls `commit(actor_id, generation, head_txid, dirty_pages, ...)` (`engine/packages/depot/src/commit.rs`).
45+
SQLite commits call Depot through the conveyer path:
5046

47+
```text
48+
1. Resolve DBPTR and read the current branch head in the UDB transaction.
49+
2. Encode dirty pages into LTX DELTA chunks.
50+
3. Write COMMITS, VTX, DELTA, and PIDX rows.
51+
4. Update META/head and quota counters.
52+
5. After commit, update SQLITE_CMP_DIRTY and send a throttled DeltasAvailable wake when lag crosses thresholds.
5153
```
52-
1. Read META in-tx → fence (generation + head_txid) + allocate txid T
53-
2. Encode all dirty pages into one LTX blob
54-
→ write to DELTA/{T}/0, DELTA/{T}/1, ...
55-
3. For each dirty page N: write PIDX/delta/{N} = T (overwrites prior owner)
56-
4. Update META: head_txid=T, next_txid=T+1, db_size_pages, depot_used
57-
5. Commit UDB tx
58-
```
59-
60-
The PIDX writes are how a commit "claims" pages. Most-recent PIDX entry wins the read.
61-
62-
After commit succeeds, prior owners of those pgnos are now orphaned in their old DELTAs (no PIDX entry references them anymore). Compaction will eventually fold the orphans into shards.
6354

64-
## Compaction (the janitor's job)
55+
The commit path does **not** publish SHARD rows, upload cold objects, or delete old history. It only records new committed history and wakes workflow compaction.
6556

66-
```
67-
1. Read META in-tx, PIDX, and the K oldest unmaterialized DELTAs
68-
2. Group their pages by shard_id (= pgno / 64)
69-
3. For each affected shard:
70-
- Read existing SHARD blob, merge in newer page versions, rewrite SHARD
71-
- Delete PIDX entries for pages that just got folded
72-
4. Delete the K old DELTA blobs (no PIDX still references them)
73-
5. Update META: materialized_txid = highest folded txid,
74-
depot_used adjusted for bytes freed
75-
```
57+
## Workflow compaction
7658

77-
After compaction, those pages are no longer in PIDX → reads fall through to the shard.
59+
Each active database branch has one DB manager workflow plus hot, cold, and reclaimer companions, all unique by database branch id.
7860

79-
## Where PIDX is used
61+
The manager owns planning and durable publication:
8062

81-
Three paths:
63+
- Hot jobs stage LTX shard blobs under `CMP/stage/{job_id}/hot_shard`; the manager validates the active job, copies output to reader-visible `SHARD`, advances `CMP/root`, writes selected `PITR_INTERVAL` rows, and compare-clears matching PIDX.
64+
- Cold jobs upload deterministic objects at `db/{branch}/shard/{shard_id}/{txid}-{job_id}-{hash}.ltx`; the manager publishes `CMP/cold_shard` refs only after revalidating branch lifecycle, manifest generation, pins, proof state, and covered inputs.
65+
- Reclaim jobs delete hot rows only after the manager proves replacement coverage. They also retire cold refs, wait the grace window, mark deletes issued, delete exact S3 keys, and leave completed retired records so object keys are not republished.
66+
- Shard-cache eviction is a reclaimer lane. It clears only FDB `SHARD` rows that have matching `CMP/cold_shard` refs and are not retained by restore points, forks, or unexpired PITR interval coverage.
8267

83-
1. **Reads** — routing table. Every `get_pages` consults PIDX.
84-
2. **Commits** — every dirty page writes a new PIDX row, overwriting the prior owner.
85-
3. **Compaction** — reads PIDX to find what to fold, deletes PIDX rows for folded pages.
68+
`CMP/root` watermarks are scheduling summaries, not deletion proof by themselves. Deletes re-read the exact pins, PIDX dependencies, SHARD coverage, lifecycle generation, and manifest generation inside the delete transaction.
8669

87-
### The in-RAM PIDX cache
70+
## PITR and restore
8871

89-
`SqliteEngine.page_indices: scc::HashMap<actor_id, DeltaPageIndex>` (`engine/packages/depot/src/page_index.rs`) is a RAM snapshot of the `PIDX/delta/*` prefix.
72+
Automatic timestamp restore coverage is stored as `PITR_INTERVAL` rows selected during hot compaction from commit wall-clock timestamps and the effective bucket/database PITR policy. Expired interval rows are soft pins until reclaim compare-clears them.
9073

91-
- **Cold cache:** on `get_pages`, scan PIDX prefix in-tx, populate cache for next time.
92-
- **Warm cache:** skip the scan, look up in RAM.
93-
- **Commit:** update cache after the UDB write succeeds (add/overwrite the new pgno → txid mappings).
94-
- **Stale entry:** cache says DELTA T owns pgno N but compaction deleted T. The read misses the DELTA blob, falls back to SHARD (`read.rs:144-150`), evicts the stale row.
74+
Restore points are retained user tokens. Creating a restore point resolves a `SnapshotSelector` to exact branch, txid, versionstamp, and wall-clock metadata, then writes a `RestorePointRecord` and `DB_PIN(kind=RestorePoint)`. Deleting it removes that hard pin and recomputes branch pin floors.
9575

96-
The cache is **safe to be stale** because PIDX→DELTA misses always fall back to SHARD, and shards are the long-term home. Correctness lives in UDB; the cache is perf only.
76+
Fork and restore use the same primitive: resolve a snapshot selector, derive a branch at that exact point, and let the caller decide whether to keep a fork or move the database pointer.
9777

9878
## Cross-references
9979

80+
- Key layout: [sqlite/storage-structure.md](sqlite/storage-structure.md)
81+
- Component ownership: [sqlite/components.md](sqlite/components.md)
10082
- VFS parity rules: [sqlite-vfs.md](sqlite-vfs.md)
10183
- Storage metrics: [SQLITE_METRICS.md](SQLITE_METRICS.md)
102-
- Engine-wide CLAUDE notes on SQLite quirks: `engine/CLAUDE.md` `## Depot tests` and `## Pegboard Envoy`

docs-internal/engine/sqlite/components.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SQLite Storage Components
22

3-
Depot is split into the conveyer hot path plus workflow compaction. The old standalone hot/cold/eviction compactor modules remain only as legacy test/support code and are not runtime storage authorities.
3+
Depot is split into the conveyer hot path plus workflow compaction. Workflow compaction is the only compaction publish/delete authority.
44

55
## Conveyer
66

@@ -31,7 +31,9 @@ Responsibilities:
3131
- Have the hot companion write staged shard blobs under `CMP/stage/{job_id}/hot_shard`.
3232
- Install matching hot job output by copying staged blobs to reader-visible `SHARD`, advancing `CMP/root`, and compare-and-clearing expected PIDX rows.
3333
- Have the cold companion upload deterministic cold shard objects, then publish `CMP/cold_shard` refs only through the manager.
34-
- Have the reclaimer delete only manager-authorized FDB rows, staged output, and retired cold objects.
34+
- Have the reclaimer delete only manager-authorized FDB rows, staged output, orphan cold objects, and retired cold objects.
35+
- Evict cold-backed FDB `SHARD` rows as shard-cache entries without clearing the matching `CMP/cold_shard` refs.
36+
- Keep automatic PITR interval coverage and retained restore point pins live until reclaim can prove they are no longer needed.
3537
- Stop the manager and companion workflows through `DestroyDatabaseBranch` when a database branch is no longer live.
3638

3739
Lease ownership: none. Gasoline workflow uniqueness uses only the database branch id tag.
@@ -41,7 +43,7 @@ Lease ownership: none. Gasoline workflow uniqueness uses only the database branc
4143
| Component | Main writes | Lease |
4244
|---|---|---|
4345
| Conveyer | `META/head`, `COMMITS`, `VTX`, `PIDX`, `DELTA`, branch records, restore points | None |
44-
| Workflow DB manager | `CMP/root`, live `SHARD`, `CMP/cold_shard`, retire records, matching PIDX clears | None |
45-
| Workflow companions | Staged hot output, cold object uploads, manager-authorized deletes | None |
46+
| Workflow DB manager | `CMP/root`, live `SHARD`, `PITR_INTERVAL`, `CMP/cold_shard`, retire records, matching PIDX clears | None |
47+
| Workflow companions | Staged hot output, cold object uploads, manager-authorized deletes and cleanup | None |
4648

4749
The components share branch metadata and pin counters, but each mutable manifest field has one owner.

0 commit comments

Comments
 (0)