Files
alkstore/docs/architecture/open-questions.md
T
glm-5.3-flash 2949612e2c ADR-012: forked-substrate design — contract-blind boundary, fidelity posture, port deltas
Follow-through on OQ-06/ADR-011: pin the fork's structural decisions
(alkstore-substrate as a vendored path-dep crate, contract-blind API
boundary with contract formulas computed engine-side and pinned
equivalent by the contract suite, keep-the-kept-half API fidelity for
cheap cherry-picks, the W-1/W-2/dead-man's-switch/W-4 port deltas
decided per item, bootstrap re-keying off error-string matching, no
rename migration, deliberate upstream tracking).

Consistency sweep across the doc set for the fork: annotate ADR-003/
005/009/010 and core-contract for superseded ownership facts, fix
schedule-storage table naming (ADR-009 §5, queues.md), re-key ADR-010
§6's notifications hygiene to the at-attach cap the fork scope
realizes, add OQ-11 (scaffold-time residue), and complete both ADR
indexes. Independent review: 0 critical, warnings addressed.
2026-10-05 05:00:55 +00:00

16 KiB

status, last_updated
status last_updated
draft 2026-10-05

alkstore — Open Questions

Centralized tracker. IDs OQ-NN are stable — never renumber; append. Promoted, one-to-one, from Phase 0's OQ-ST register. Resolution order so far: OQ-04 resolved (2026-10-05, ADR-008 — the contract surface everything else hangs off); OQ-09 + OQ-05 resolved (2026-10-05, ADR-009 and ADR-010 — the queue semantics track and the scheduler collapse/guarantee row); OQ-06 resolved (2026-10-05, ADR-011 — the fork trigger fired on the published-artifact facts); the fork design follow-through (2026-10-05, ADR-012 — substrate boundaries, fidelity posture, port deltas; its substrate-side residue is OQ-11). Next: OQ-08 (rides the now-pinned trait shape and the ADR-011 substrate fork), OQ-10 (versioning discipline for contract extensions; note ADR-011 changes its substrate-side facts for SQLite — the forked crate is versioned in this repository's Cargo workspace, so the engine/core contract pairing is what the discipline must track), and OQ-11 (fork follow-through items — substrate-side, non-consumer-facing).

Resolved questions stay listed with their resolution; they are not deleted.

Theme: Scope

OQ-01: Scope boundary — which honker features are in-scope? (== OQ-ST-01)

  • Origin: consumer-inventory.md, ADR-002
  • Status: resolved (2026-10-04, Phase 0)
  • Priority: medium
  • Resolution: Answered by the consumer inventory — scope votes shrink to named rows, not the whole honker feature list. First-class: notify/listen (pinned), streams (operator-authority record). In scope: named locks, queues + outbox (documented), scheduler (documented-thin). Cut-flags: rate limits, result storage. Out: honker's exclusion lines. Decision recorded in ADR-002.
  • Cross-references: OQ-07, OQ-04.

OQ-02: Crate scope — one store crate, or reactive-core + engines? (== OQ-ST-02)

  • Origin: overview.md
  • Status: resolved (2026-10-04, operator decision; Phase 0)
  • Priority: medium
  • Resolution: Reactive-core crate + per-engine engine crates; the split isolates the engines' asymmetry of work and keeps engine binaries single-driver (which the libsqlite3-sys collision effectively requires). Decision recorded in ADR-001 — including the reasoning that superseded the inventory's single-crate lean.
  • Cross-references: OQ-03, OQ-10.

OQ-03: Driver story — sqlx, tokio-postgres, or per-engine drivers? (== OQ-ST-03)

  • Origin: overview.md
  • Status: resolved (2026-10-04, POC-backed both engines; Phase 0)
  • Priority: medium
  • Resolution: Per-engine drivers — rusqlite + honker-core 0.5.0 (SQLite; bridged seam), tokio-postgres 0.7.18 + deadpool-postgres 0.14.2 (Postgres), under OQ-02's crate split. Decisions recorded in ADR-003 and ADR-004; measurements in docs/research/poc-sqlite-posture-findings.md and docs/research/poc-pg-posture-findings.md.
  • Cross-references: OQ-02, OQ-05, OQ-06.

OQ-07: SQLite-side scope — loadable extension? (== OQ-ST-07)

  • Origin: ADR-002
  • Status: resolved (cut-only, 2026-10-04; Phase 0)
  • Priority: low
  • Resolution: The loadable-extension surface is out: every identified consumer is in-process Rust attaching to its own connection (the honker-core attach_honker_functions shape). Folded into OQ-01's scope resolution and ADR-002 (explicitly, so the slot's disposition is visible — the Phase 0 register carried it as its own entry).
  • Cross-references: OQ-01.

Theme: Core contract

OQ-04: Contract pinning — the exact trait surface and its semantics (== OQ-ST-04) — RESOLVED

(Retitled in promotion: OQ-ST-04's framing — "the reactive abstraction — what does the unified notify surface look like?" — narrowed to the pinning work its own record already scoped.)

  • Origin: core-contract.md, ADR-006, ADR-007
  • Status: resolved (2026-10-05, Phase 1 — ADR-008)
  • Priority: high
  • Resolution: Pinned as contract v1 by ADR-008: (1) the v1 surface partition — notify/streams/queue-skeleton/locks/outbox/tx seam are contract; queue depth rides OQ-05, scheduler shape rides OQ-09, capabilities ride OQ-08, claim_waker stays engine-internal, cut-flag rows stay out. (2) TxHandle: the *_tx methods live on the handle trait — boxed dyn handle, no downcast, no enum (the enum would invert ADR-001's dependency direction); the POCs' as_any_mut friction dissolves by construction. (3) listen() returns a WakeReceiver delivering opaque Wake { channel } — honker's payload transport is not surfaced (uniformity with the opaque contract, ADR-006). (4) Reserved prefix __alkstore_, with __alkstore_listener_reconnected__ as the one v1-reserved string (the POC's ad-hoc __listener_reconnected__ renamed at implementation). (5) Error taxonomy: PayloadTooLarge / ReservedName / InvalidName / Closed / Codec / Database, pinned by the act-differently rule. (6) Store::open is engine-crate surface; the contract is the trait it returns. (7) Locks guarantee row added to ADR-006's table (TTL-bounded mutual exclusion, silent expiry); the scheduler row is explicitly transferred to OQ-09's resolution. A verification backlog (core-contract.md §Verification backlog) tracks the one-engine-pinned properties.
  • Cross-references: OQ-01, OQ-10, OQ-09, OQ-08.

Theme: Queues and scheduling

OQ-05: Queue semantics depth — retry/backoff/dead-letter/sweep design (== OQ-ST-05) — RESOLVED

  • Origin: queues.md
  • Status: resolved (2026-10-05, Phase 1 — ADR-010)
  • Priority: high
  • Resolution: Pinned by ADR-010: (1) job state machine — three states (pending/processing/dead), delete-on-ack, move-to-dead (honker's model, pg-boss's seven-state enum not inherited), get_job sees dead rows (last_error/died_at — post-mortem by API; cancel unconditional, not an interrupt). (2) Visibility/heartbeat — renewal semantics (absolute reset), late-heartbeat refusal (dual-execution window is contract-honest), reclaim-consumes-an-attempt stated as contract text. (3) Retry/backoff — retry(err, None) computes the queue's equal-jitter exponential curve (range definitionally pinned, not a labeled distribution; base backoff_base_s, cap 1 h, attempt index = row attempts at retry), Some(d) overrides; queue-level QueueOpts { visibility_timeout_s, max_attempts, backoff_base_s, dead_letter_retention_s } stamped onto each job row at enqueue (§3a — no per-queue registry; two handles with different opts for one queue name don't fight). (4) Dead-letter — move-to-table, retention forever by default, no redrive API (recipe: get_job + fresh enqueue). (5) sweep_expired — the no-stranded-rows property (every past-expiry row in any state moves to dead; honker's expired-processing zombie hole fails this — fixed at contract level, SQLite-side realization rides OQ-06). (6) Sweep cadence — no ambient sweeper; the recipe is the collapse machinery (schedule + runner). (7) Result-storage cut-flag reconsidered and stands (delete-on-ack; pg-boss's completed-row model is result storage under another name). (8) Table layout — pg engine-owned schema (alkstore default), queues are rows not tables; SQLite rides _honker_*. (Item 8's SQLite half superseded 2026-10-05: the _honker_* family is re-owned as __alkstore_* by the fork — ADR-011, designed per ADR-012.) No new error variants (ADR-008 §5's rule).
  • Cross-references: OQ-09, OQ-06.

OQ-09: Is the scheduler a first-class mechanism, or queues + schedule()? — RESOLVED

  • Origin: queues.md (spin-out of OQ-05's Phase 0 framing, where the scheduler's boundary question lived)
  • Status: resolved (2026-10-05, Phase 1 — ADR-009)
  • Priority: medium
  • Resolution: Collapse confirmed, decided against the inventory rows (alkblobs sweep cadence, alkfs orphan reaping — both intervals; no row names schedule objects or wall-clock cron): the contract surface is schedule(name, spec, queue, payload, opts) (upsert by name), unschedule(name), and the opt-in run_schedules(stop) runner — no Scheduler handle, no schedule objects; update = re-register, pause = unregister + re-register. Spec grammar v1: @every <n><unit> only — cron strings rejected (InvalidSpec), dissolving the timezone question honker's local-time cron brittleness poses (extension path requires a consumer-inventory row). Boundary guarantee row pinned (the transfer from ADR-008 §7 resolved): at-least-once per elapsed boundary while a leader runs, fire+advance commit atomically under a row lock on the schedule row (engine-generic no-double-fire floor; the leadership lock is the efficiency layer), bounded catch-up (fixed contract-constant cap 64) with skip-forward; leadership lock is the reserved __alkstore_scheduler name; run_schedules returns Err(LeadershipLost) on lock loss, Ok(()) on clean stop. Schedule storage engine-internal; schedules never fire without a runner (no ambient timers).
  • Cross-references: OQ-05, OQ-04.

Theme: Engines and dependencies

OQ-06: honker-core quality read — does the default posture hold? (== OQ-ST-06) — RESOLVED

  • Origin: ADR-005, engine-sqlite.md
  • Status: resolved (2026-10-05, Phase 1 — ADR-011)
  • Priority: high (fork trigger is a gate on the SQLite engine's dependency posture)
  • Resolution: The fork trigger fires. Evidence: quality-read-honker-core.md. The read's original target is clean (Writer/Readers, the polling watcher's three-layer failure handling, WatcherDeathGuard — all verified in source, present in 0.5.0; schema migrations minor). But the published artifact is materially behind the reference revision: crates.io's honker-core 0.5.0 predates upstream's own fix train for its documented defect class (issue #133's savepoint hardening — silent job loss on mid-flight errors in the dead-letter paths; five .ok() error-swallows mapping every SQLite error to "no row"/"lock held"), stranded unreleased with no announced date. And contract v1's queue depth (ADR-010 §3a/§5) requires engine-owned enqueue/claim/sweep/get_job SQL in any posture — making a post-fix ride a minority-shape, dual-owning the schema. Resolution: fork honker-core at the reference revision into owned code, inherit the clean watcher/transactional core + test suites, re-derive the queue ops on contract v1, drop cron/experimental backends, rename _honker_* → __alkstore_*. Recorded in ADR-011; ADR-005's posture calculus applied, not renegotiated.

Theme: Deployment and capabilities

OQ-08: Where does the honest single-host/multi-host boundary live in the trait surface? (== OQ-ST-08)

  • Origin: deployment.md
  • Status: open
  • Priority: medium
  • Resolution: open. The pg engine is natively multi-host (POC #2 verified — no single-host assumption to remove); SQLite is single-machine by nature (file-backed, NFS-two-writers unsupported — honker's honesty posture, inherited by the forked substrate). The unified surface must not pretend SQLite is multi-host. Options: per-engine capability flags (Store::capabilities()), a documented deployment matrix only (deployment.md carries the facts), or compile-time knowledge only (a consumer choosing the SQLite engine knows). Rides the now-pinned contract shape (ADR-008): the trait constrains where capability differences can surface.
  • Cross-references: OQ-04, ADR-006, ADR-012 (the substrate inherits the honesty posture).

OQ-10: How do engine crates track core-contract version changes?

  • Origin: overview.md, ADR-001
  • Status: open
  • Priority: medium
  • Resolution: open. The core crate's trait surface is a contract the engine crates must track (ADR-001 negative consequence). What is the versioning/sync discipline — semver-bump-only-when- contract-changes, engines pin core ranges, a contract-compatibility test suite the engines run against the core's trait definitions? What happens to a released engine crate when core makes a contract breaking change?
  • Cross-references: OQ-04 (the contract being versioned — now including its first post-v1 extensions, ADR-009/ADR-010), OQ-02.

OQ-11: Forked-substrate follow-through — scaffold, provenance register, and cherry-pick discipline

  • Origin: ADR-012 (the fork design; substrate-side residue), ADR-011
  • Status: open
  • Priority: medium (nothing consumer-facing rides on it; it resolves within the fork-scaffold task, which it does not gate)
  • Resolution: open. ADR-012 fixed the design (contract-blind boundary, fidelity posture, port deltas, bootstrap machinery, upstream-tracking stance) and also pinned the provenance register's location, timing, and initial contents (§1). The residue is: (1) the exact Cargo-workspace layout and build wiring of alkstore-substrate in this repository (crate location, feature gating of the bundled-sqlite interplay with the engine crate's own rusqlite dependency); (2) the provenance register's format and delta-list granularity (per-commit entries vs per-delta-class; whether cherry-pick records append at adoption time — location, timing, and initial contents are ADR-012 §1's, not re-opened here); (3) the cherry-pick procedure in practice — how a candidate upstream fix is evaluated, applied, and recorded so ADR-012 §6's deliberate-work posture stays auditable. These resolve within the fork-scaffold task (its opening section), not before it and not as a gate on writing it; the scaffold's build wiring depends on (1)'s outcome.
  • Cross-references: OQ-08 (the contract surface the engine maps the substrate under), OQ-10 (the substrate is a crate in this repository's Cargo workspace — its versioning interacts with the discipline), ADR-011, ADR-012.

Deferred / Blocked

None currently. Every open OQ above is actionable Phase 1 work (capability-surface shape, versioning discipline, fork-scaffold follow-through) with its evidence base complete — no external arrivals are being waited on.