Skip to content

osm/lance lifecycle Phase A: three clocks, one lineage per region - #133

Merged
AdaWorldAPI merged 2 commits into
mainfrom
claude/q2-osm-lifecycle-phase-a
Aug 15, 2026
Merged

AdaWorldAPI merged 2 commits into
mainfrom
claude/q2-osm-lifecycle-phase-a

Conversation

@AdaWorldAPI

Copy link
Copy Markdown
Owner

Summary

Phase A of the OSM/Lance lifecycle redesign (plan:
claude-notes/plans/2026-08-15-osm-lance-lifecycle.md), correcting the
current code's failure mode: a full SHA-256 re-hash of every artifact on
every boot (even warm cache hits), which is the measured cause of RAM
climbing back to ~4 GB after a restart with no map traffic.

Core idea — three clocks, never conflated:

  1. Semantic import identity — RegionId/SourceBakeId/SourceManifestSha256
    (all validated/canonical, path-traversal-safe), ImportIdentity,
    OriginSeal, ImportSeal, FNV-1a/64 ImportId as a fast idempotency
    marker with a full-tuple reconcile() behind it (a marker match is a
    candidate, never proof).
  2. Physical Lance history — publication_version is Some only on a
    fresh commit, never invented on a reconciled retry; HeadDecision
    separates head-drift (later, unexplained) from head-behind
    (replica truncated/stale) — two different failures, two different
    recoveries (recover_behind).
  3. Replica progress — StorageRoot (5-candidate ordered policy; only
    RAILWAY_VOL and a probed /volume01 are intrinsically volume storage,
    everything else needs an explicit durability declaration), ActivationPolicy.

Lifecycle is a product, not a sum: serving: Option<ServingSet> beside
operation: Operation, fenced by a monotonic Generation so a stale
completion for a superseded import can never activate or fail the wrong
candidate. An earlier draft made this one enum and a failed import had
nothing to restore to — caught by a failing contract probe and fixed by
the product-state redesign (see the plan's "Correction pass" section for
the full nine-point review this went through).

Retention specifies intent only in Phases A–C: GcAuthority::None means
no code path here can return a non-empty deletion set, regardless of grace
period or inventory completeness, until Phase D ships a real Lance-native
reachability mechanism.

Also included: crates/stubs/notebook-query had a stale direct
datafusion = "53" dependency that nothing in its source actually
referenced — it forced cargo to build an entire duplicate
datafusion-53/arrow-57 subtree (~26 duplicate datafusion-* crates)
alongside the one lance-graph already requires at 54. Removed; Cargo.lock
now carries a single datafusion (54.1.0) and arrow (58.3.0) workspace-wide.

What's NOT in this PR

Per the plan, this session is scoped to Phase A only (pure types, no
I/O/async/Lance calls). Phase B (OsmArtifactManager, /api/osm/status,
memory telemetry) and beyond are explicitly deferred — every test here is a
contract probe (proves a decision function), not yet a system
falsifier
(proves the running system obeys it); the plan's falsifier table
tracks which phase owes each one.

Test plan

  • cargo test -p cockpit-server osm_lifecycle — 29/29 new tests pass
  • cargo test -p cockpit-server — 149/149 pass (0 regressions)
  • cargo build --workspace — clean (warnings only, pre-existing)
  • cargo clippy -p cockpit-server --no-deps --all-targets -- -D warnings
    — 52 pre-existing findings unchanged (verified via stash against
    unmodified origin/main); this PR's new code contributes zero
  • cargo fmt — osm_lifecycle.rs and the one-line main.rs diff are
    clean (ran rustfmt on the leaf module directly to avoid the
    environmental full-crate reformat this repo's toolchain triggers —
    see plan notes)
  • cargo nextest run --workspace / cargo xtask verify --skip-hub-build
    — blocked by pre-existing debt unrelated to this diff, not by
    anything in this PR:
    - 3 deterministic, reproducible failures in
    crates/stubs/notebook-query/src/orchestrator.rs
    (test_graph_sensorium_stagnant, test_restore_on_high_efficiency,
    test_temperature_rises_on_stagnation) — pure state-machine logic,
    no timing/randomness, no reference to datafusion anywhere in that
    crate's source, so there is no causal path from this PR's dependency
    cleanup to these results. Confirmed unrelated: git diff touches
    zero files under crates/stubs/notebook-query/src/.
    - 3 pre-existing clippy -D warnings findings in crates/aiwar-ingest
    (collapsible-if / implicit-clone), also untouched by this diff.

Both are out of scope for this PR (different subsystems, "fix one bug at a
time"); flagging them here rather than silently working around them.

🤖 Generated with Claude Code


Generated by Claude Code

claude added 2 commits August 15, 2026 14:22
notebook-query pinned `datafusion = "53"` directly even though nothing in
its source references `datafusion::` at all (lance-graph itself already
depends on it at 54, matching the lance-9 family: lance 9, lancedb 0.33,
datafusion 54, arrow 58). The stale pin forced cargo to build an entire
second datafusion-53 + arrow-57 dependency subtree (~26 duplicate
datafusion-* crates) alongside the one already required transitively,
for a dependency that was never used.

Removed rather than bumped: if this crate ever needs datafusion types
directly, it should track whatever lance-graph pins at that time, not a
hardcoded major version that can silently drift again.

Verified: Cargo.lock now carries a single datafusion (54.1.0) and a
single arrow (58.3.0) across the whole workspace.
…gion

Pure decision layer for the OSM/Lance lifecycle redesign: a live Lance
dataset is a versioned lineage, not an immutable directory, so nothing
here hashes a whole dataset directory or compares its changing object
inventory to a static checksum. No I/O, no async, no Lance calls — that
is what makes "the S3 pointer is written last" and "a warm boot reads
no map data" testable as decisions before any wiring exists.

Three clocks, never conflated:
- semantic import identity (RegionId/SourceBakeId/SourceManifestSha256,
  ImportIdentity, OriginSeal, ImportSeal, FNV-1a/64 ImportId as an
  idempotency marker with tuple-level reconcile() behind it)
- physical Lance history (publication_version vs observed_head,
  head-drift vs head-behind, HeadDecision/recover_behind)
- replica progress (StorageRoot resolution, ActivationPolicy)

Lifecycle is a PRODUCT of serving state and import-operation state
(Lifecycle{serving: Option<ServingSet>, operation: Operation}, fenced
by Generation) rather than one sum type — an earlier draft folded them
together and a failed import had nothing to restore to; a stale
completion for a superseded candidate is now structurally rejected
rather than able to activate or fail the wrong candidate.

Retention specifies intent only: GcAuthority::None in Phases A-C means
no code path here can return a non-empty deletion set, regardless of
grace period or inventory completeness, until Phase D's Lance-native
reachability mechanism lands.

62 tests (29 in osm_lifecycle + the pre-existing 120), each a Phase-A
CONTRACT PROBE proving a decision function, not yet a system falsifier
— the module doc and the plan file both track which system-level
falsifier each probe still owes to a later phase.

Plan: claude-notes/plans/2026-08-15-osm-lance-lifecycle.md
@coderabbitai

coderabbitai Bot commented Aug 15, 2026 •

Copy link
Copy Markdown

Important

Review available on request

  • 🔍 Trigger review

Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment @coderabbitai review to review the latest changes. For a full review, comment @coderabbitai full review.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 62d6e3f8-ef45-493b-9f30-89325c0a424a


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cursor

cursor Bot commented Aug 15, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_d5cec63a-fcce-419d-b7bd-09c59e0230ea)

@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review August 15, 2026 14:41
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@AdaWorldAPI
AdaWorldAPI merged commit 740edf0 into main Aug 15, 2026
5 checks passed
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.

2 participants