Operator review of ADR-012's fork design re-litigated §1's crate identity. alkstore-substrate misdescribed what the code is (unpublished, path-dep-only, one consumer, SQLite-only — not a family-wide substrate); the mechanical-diff hope was gone at fork time regardless (port deltas, renames, re-derived half); and the alksocks F-1 lesson applies — a vendored region under a second, weaker instruction set is a defect seam. The fork folds into alkstore-sqlite as a bounded module subtree (src/substrate/); ADR-012 §3–§6 retained verbatim, §2 retained with its enforcement re-sited from the crate graph to diff fence + review + contract-suite equivalence pins. OQ-11 item (1) dissolved.
143 lines
7.3 KiB
Markdown
143 lines
7.3 KiB
Markdown
# ADR-011: SQLite substrate — fork honker-core into owned code
|
|
|
|
## Status
|
|
|
|
Accepted (2026-10-05, Phase 1 — OQ-06's resolution; the fork trigger
|
|
ADR-005 named, fired)
|
|
|
|
## Context
|
|
|
|
ADR-005 fixed the dependency posture: published honker-core 0.5 by
|
|
default, with the fork trigger being the Phase 1 quality read finding a
|
|
defect the POCs wouldn't surface. ADR-010 handed the read two concrete
|
|
fork candidates (the expired-processing-row zombie hole; dead-row
|
|
`get_job` visibility) and made the SQLite realization of contract v1's
|
|
queue depth contingent on it. OQ-06 is the tracked assessment; the
|
|
evidence is `docs/research/quality-read-honker-core.md` (full read of
|
|
all five honker-core sources at the reference revision, cross-checked
|
|
against the published crates.io artifact).
|
|
|
|
Three facts drive this decision:
|
|
|
|
1. **The published artifact carries confirmed silent-job-loss defects.**
|
|
crates.io's newest honker-core is 0.5.0 (2026-08-23). The upstream
|
|
fix train for its own documented defect class — issue #133's
|
|
savepoint hardening of the DELETE→INSERT dead-letter paths (a job
|
|
stranded in neither table on mid-flight error = silent job loss) and
|
|
the five `.ok()` error-swallows that map every SQLite error to "no
|
|
row"/"not our claim"/"lock held" — sits in the repository
|
|
*unreleased*, alongside `claimed_at` and six weeks of hardening. The
|
|
ride posture's core value ("defects inherited for free" cuts both
|
|
ways: fixes do too) currently inherits the defects, not the fixes.
|
|
2. **Contract v1 requires re-deriving the queue-op surface in any
|
|
posture.** Per-job option stamps (ADR-010 §3a — visibility/backoff/
|
|
retention stamped at enqueue, honored per-row in the claim
|
|
statement), the no-stranded-rows sweep (§5), and dead-visible
|
|
`get_job` with stamps (§1) all mean the engine owns enqueue / claim
|
|
/ retry / fail / sweep / get_job SQL whether riding or forking. The
|
|
post-fork ride would cover only ack/heartbeat/cancel, locks,
|
|
streams, notify transport, scheduler storage, and the watcher/
|
|
connection plumbing — the minority of what the engine touches, dual-
|
|
owning the `_honker_*` schema with our migrations in the complement
|
|
posture.
|
|
3. **The read's original target — the watcher/transactional core — is
|
|
clean.** Writer, Readers, and the polling watcher's three-layer
|
|
failure handling (transient-BUSY-vs-fatal classification, conservative
|
|
wakes, re-baseline discipline, the stat-identity dead-man's switch)
|
|
and `WatcherDeathGuard`'s death-closes-subscribers property all
|
|
verified in source, present in 0.5.0. This fact steers the fork's
|
|
*scope* (inherit that machinery almost verbatim), not the posture.
|
|
|
|
## Decision
|
|
|
|
**The fork trigger fires.** The SQLite engine's substrate becomes owned
|
|
code: fork honker-core at the reference revision
|
|
(`/workspace/honker` @ `f4e53c6`, MIT OR Apache-2.0, provenance
|
|
recorded per AGENTS.md §3) into the alkstore family, ported to the
|
|
family standard (the discipline deltas — no comments discipline,
|
|
panics out of library code — with tokio-facing consumers at the engine
|
|
seam above; per [ADR-012](012-forked-substrate-design.md) §4 the
|
|
substrate itself stays sync), re-derived on contract v1 where ADR-010
|
|
pinned semantics honker's functions don't provide.
|
|
|
|
Per-scope (the full register with keeps/re-derivations/drops is
|
|
`docs/research/quality-read-honker-core.md` §6):
|
|
|
|
- **Inherited near-verbatim:** the PRAGMA/WAL open posture,
|
|
`Writer`, `Readers`, the polling watcher + `SharedUpdateWatcher` +
|
|
`WatcherDeathGuard` + dead-man's switch (with three port deltas the
|
|
read named / ADR-012 decided: reconnect backoff, fallible watcher
|
|
spawn, and the dead-man's-switch panic replaced by a deliberate
|
|
watcher-fatal death — [ADR-012](012-forked-substrate-design.md) §4),
|
|
the
|
|
`in_savepoint` mutation-discipline machinery, arg-coercion helpers,
|
|
the notify scalar + notifications table (renamed, with engine-
|
|
internal hygiene per ADR-010 §6), streams, locks.
|
|
- **Re-derived on contract v1:** enqueue + opt stamping; single-
|
|
statement claim with per-row visibility from the job's stamps;
|
|
savepoint-guarded retry/fail/dead-letter; the both-states
|
|
no-stranded-rows `sweep_expired` with retention deletion; dead-
|
|
visible `get_job`; scheduler tick with `@every` boundary math.
|
|
- **Dropped:** cron parsing (ADR-009 rejects cron strings), the
|
|
experimental watcher backends and their optional deps, the rate-limit
|
|
and result tables (cut-flags), the superseded queue functions.
|
|
- **Table naming:** `_honker_*` → `__alkstore_*` — storage-internal
|
|
(ADR-008 §4); ADR-010 §8 pre-authorized the fork re-owning names.
|
|
- **Tests:** honker-core's suites inherited as the floor (watcher
|
|
lifecycle/failure, savepoint, multiprocess pressure) + the contract-
|
|
property tests (no-stranded-rows, dead-visible `get_job`, stamps).
|
|
|
|
Packaging follows ADR-001's split: the forked substrate is the SQLite
|
|
engine crate's dependency — vendored as a workspace-family crate
|
|
(provenance + license recorded), not re-published. *(Packaging amended
|
|
2026-10-05 by [ADR-013](013-fold-substrate-into-sqlite.md): the fork
|
|
folds into `alkstore-sqlite` as a bounded module subtree — no fourth
|
|
crate; ADR-001's three-crate shape stands.)*
|
|
|
|
## Consequences
|
|
|
|
**Positive**
|
|
|
|
- The confirmed defect class (D-1..D-5) is owned, fixed, and testable
|
|
in-tree; no release cadence gates correctness we already know how to
|
|
fix.
|
|
- Contract v1's queue depth realizes directly in owned SQL — no
|
|
two-statement re-stamp bridge, no engine migrations over a
|
|
dual-owned `_honker_*` table family.
|
|
- The fork inherits ~4,000 lines of upstream hardening tests plus the
|
|
watcher machinery the POCs measured as the quality win of the ride
|
|
posture — most of the fork cost is pre-paid.
|
|
|
|
**Negative**
|
|
|
|
- We own the SQLite machinery's future: upstream fixes (rare and
|
|
incremental, but real — the #80/#133 train proves the stream is
|
|
alive) must be deliberately cherry-picked rather than inherited by
|
|
`cargo update`.
|
|
- Vendored forked code in the tree breaks "zero vendored code in the
|
|
tree by default" (ADR-005's positive consequence) — this is the
|
|
exception the posture always named, not a renegotiation. *(Packaging
|
|
since amended by [ADR-013](013-fold-substrate-into-sqlite.md): the
|
|
vendored code is carried in-tree inside `alkstore-sqlite`, not as a
|
|
workspace-family crate.)*
|
|
|
|
## References
|
|
|
|
- OQ-06 (`docs/architecture/open-questions.md`) — the resolved
|
|
assessment; `docs/research/quality-read-honker-core.md` — the
|
|
evidence (published-artifact fact, watcher-core verdict, defect
|
|
register, fork calculus and scope).
|
|
- [ADR-005](005-dependency-ownership.md) — the posture and trigger this
|
|
ADR fires; fork-is-normal-work applies.
|
|
- [ADR-003](003-sqlite-driver.md) — driver, seam, and watcher
|
|
architecture (unchanged in ownership; the fork inherits the measured
|
|
machinery).
|
|
- [ADR-010](010-queue-semantics-depth.md) — §3a/§5/§1's realization
|
|
is now owned-code work; §8's naming authorization applies.
|
|
- [ADR-001](001-crate-split.md) — packaging (engine crate's
|
|
single-driver substrate).
|
|
- [engine-sqlite.md](../engine-sqlite.md) — the living spec, updated
|
|
to the forked substrate.
|
|
- [ADR-012](012-forked-substrate-design.md) — the fork's design
|
|
decisions (crate identity, contract-blind boundary, fidelity
|
|
posture, port deltas, bootstrap machinery, upstream tracking). |