Skip to content

Boot config at .config/<repo>/config.yaml, deployment docs, natural-alignment pin - #908

Merged
AdaWorldAPI merged 2 commits into
mainfrom
claude/q2-osm-map-reencoding-56p5e2
Aug 7, 2026
Merged

Boot config at .config/<repo>/config.yaml, deployment docs, natural-alignment pin#908
AdaWorldAPI merged 2 commits into
mainfrom
claude/q2-osm-map-reencoding-56p5e2

Conversation

@AdaWorldAPI

Copy link
Copy Markdown
Owner

Follow-up to #907, completing the deployment story around the SoA→Lance path.

1. soa_config — the config IS the pointer

A deployment reads one YAML object from its own bucket at .config/<repo-name>/config.yaml declaring which bakes exist and which hydrate to local disk. Same binary behaves identically in a dev container and on Railway because both read the same object. Read once at boot — explicitly documented as not a hot-path serialization surface (same category as the contract crate's build.rs manifest parse), so a future session doesn't "fix" it.

Overwrite doctrine: OnExisting::Refuse (default) — an existing table is never silently overwritten. NewVersion — a refresh writes a new timestamped table and flips one YAML line. Why not rename-to-OLD: S3 has no atomic rename; renaming an N-object Lance dataset is N copies + N deletes, non-atomic, and a crash mid-rename leaves the dataset split across two prefixes with no valid pointer. Flipping the config line is O(1) and reader-atomic.

16 unit tests — every validation rule has a genuine can-fire case — plus the_shipped_example_config_parses_through_this_parser (include_str!), so the example and the schema cannot drift apart silently.

2. Deployment docs

  • docs/SOA_BAKE_DEPLOYMENT.md — bake → soa_to_lance → header contract → the corrected verbatim causality (stride > 256-byte mini-block cutoff ⇒ full-zip; the compression metadata is a backstop, not the cause) → the two serving patterns with measured, scope-limited numbers → an honest "what is NOT measured" section (request count; P-CACHE-1).
  • docs/S3_LAYOUT.md — the bucket map: .config/<repo>/, per-repo ledger prefixes, _tests/ scratch, the AWS_ENDPOINT vs AWS_ENDPOINT_URL trap, refresh/purge lifecycle (purge is the only destructive op and never automatic).
  • examples/soa-config.example.yaml — heavily commented; uses real minted geo classids (0x0F01..03). An earlier draft invented "0x0D01 ontology" — which is actually hr_employee in the HR domain. The near-miss is recorded in the example itself as the justification for the never-invent-a-classid rule.

3. Alignment pinned at NATURAL (512), up from 64

The 64 came from align_of::<NodeRow>() — sufficient for the cast, silent about straddling. Natural alignment is the stronger claim the measurement (offset 0 on the Iceland bake) already supports, and the one that matters operationally: a 512-aligned 512-byte row arithmetically cannot straddle a 128-bit SIMD lane, a 128-byte cache line (Apple M-series), or a 4 KiB page/NVMe sector — 8 whole rows per page, zero padding, no half-lanes ever. Alignment constrains the run's start only; each row stays one contiguous unit.

Gate

soa_config 16/16 · soa_verbatim 6/6 (both S3 arms live against the real endpoint) · clippy clean · fmt clean · example YAML validated through both the Rust parser and an independent YAML load. Key names only in every committed file; values come from the deployment environment.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NMeiLmtDKhomJNSo2ecbJw


Generated by Claude Code

…cs + natural-alignment pin

Three deliverables, one arc:

1. `soa_config` module — a deployment reads ONE YAML object from its own
   bucket at `.config/<repo-name>/config.yaml` declaring which bakes exist
   and which hydrate to local disk. Same binary, same behaviour, dev
   container and Railway alike, because both read the same object. Boot
   config read once at startup — NOT a hot-path serialization surface, and
   documented as such so nobody "fixes" it. The overwrite doctrine is
   config-as-pointer: an existing table is never silently overwritten
   (OnExisting::Refuse default); a refresh writes a NEW timestamped table
   and flips one YAML line, because S3 has no atomic rename — renaming an
   N-object Lance dataset is N copies + N deletes, non-atomic, and a crash
   mid-rename leaves the dataset split with no valid pointer. 16 unit
   tests, each validation rule with a genuine can-fire case, plus a test
   that the SHIPPED example parses through the REAL parser (include_str!),
   so example and schema cannot drift apart silently.

2. Deployment docs — docs/SOA_BAKE_DEPLOYMENT.md (bake -> soa_to_lance ->
   table header contract -> the stride/full-zip verbatim mechanism with
   the corrected causality -> the two serving patterns with measured,
   scope-limited numbers -> what is still NOT measured) and
   docs/S3_LAYOUT.md (the bucket map: .config/<repo>/, ledger prefixes,
   _tests/ scratch, the AWS_ENDPOINT vs AWS_ENDPOINT_URL trap, the
   refresh/purge lifecycle). Example config uses REAL minted geo classids
   (0x0F01..03) — an earlier draft invented "0x0D01 ontology", which is
   actually hr_employee in the HR domain; the near-miss is recorded in the
   example itself as the reason for the never-invent-a-classid rule.

3. soa_verbatim alignment tightened 64 -> NATURAL (off % 512 == 0).
   The 64 came from align_of::<NodeRow>(); natural alignment is the
   stronger claim the measurement (offset 0 on the Iceland bake) already
   supports, and it is the one that matters operationally: a 512-aligned
   512-byte row arithmetically cannot straddle a 128-bit SIMD lane, a
   128-byte cache line, or a 4 KiB page/NVMe sector — 8 whole rows per
   page, zero padding, no half-lanes ever. Alignment constrains the run's
   START only; each row stays one contiguous unit (that is assertion 1).

Gate: soa_config 16/16, soa_verbatim 6/6 (both S3 arms live against the
real endpoint), clippy clean, fmt clean, example YAML validated through
both the Rust parser and an independent YAML load.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NMeiLmtDKhomJNSo2ecbJw
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@AdaWorldAPI, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 56 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 51f0c323-f0d5-4706-9bdd-91d8f2ecfe42

📥 Commits

Reviewing files that changed from the base of the PR and between dc65d60 and 87526f8.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • crates/lance-graph/Cargo.toml
  • crates/lance-graph/examples/soa-config.example.yaml
  • crates/lance-graph/src/lib.rs
  • crates/lance-graph/src/soa_config.rs
  • crates/lance-graph/tests/soa_verbatim.rs
  • docs/ALIGNMENT_PRIMER.md
  • docs/S3_LAYOUT.md
  • docs/SOA_BAKE_DEPLOYMENT.md
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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 7, 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_b9ee2b47-7d2e-4c72-bb62-04b8802e8f88)

@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review August 7, 2026 21:38
…evel

The same three questions recurred across this arc (64 bit or 64 byte?
does align(64) fragment the row? do half-lanes exist?), and three separate
AI research dumps each answered them partially wrong in a DIFFERENT way.
This primer settles the questions once, names the specific errors so the
next person consulting the same tools can grade them, and labels every
claim [MEASURED] / [SOURCE file:line] / [ARITHMETIC].

Core content: the three-numbers table (64-bit metadata word vs 64-byte
cache line/type alignment vs 512-byte natural row alignment); alignment
constrains the START address, never granularity; the straddle arithmetic
(a 512-aligned 512-byte row cannot cross a 16 B lane, 64/128 B line, or
4 KiB sector — and alignment of row 0 propagates through the stride to
every row forever); why Lance versioning cannot shift data bytes
(immutable data files, separate manifest objects — both measured); the
per-file-not-per-row cost bound; and the table mapping each property to
the red-turning assertion in tests/soa_verbatim.rs that keeps it true.

Deliberately shipped THROUGH the PR review loop: if any claim is wrong,
CodeRabbit/Codex attack it here — the same loop that produced eight real
findings on #907. A claim in a reviewed doc beats a claim in a chat.

Cross-linked from docs/SOA_BAKE_DEPLOYMENT.md header.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NMeiLmtDKhomJNSo2ecbJw

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 53e3aad363

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

# two entries pointing at one table means one
# of them is either reading garbage or racing
# the other's writes.
classid: "0x0F01" # Hex classid (0x-prefixed) identifying this

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use full u32 classids in the shipped config

When an operator copies this example, 0x0F01 is interpreted as the complete classid even though the active contract stores the canonical 0xDDCC half in the high 16 bits (compose_classid(0x0F01, 0) is 0x0F01_0000; see crates/lance-graph-contract/src/ogar_codebook.rs). With the value shown here, classid_canon(0x0000_0F01) returns zero, so a reader routes the Geo bake as Reserved/default and may select the wrong ClassView—the exact failure the adjacent comment warns about. Supply the composed eight-digit classids, or explicitly model and name this field as a u16 concept ID rather than a classid.

Useful? React with 👍 / 👎.

Comment on lines +93 to +94
#[derive(Debug, Clone, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct BakeEntry {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject unknown bake keys during boot parsing

When a deployment config contains a typo such as slab_digset or hydarte, Serde silently ignores it because BakeEntry does not use deny_unknown_fields; the corresponding default then turns the digest into None or hydration into false. That makes a supposedly validated boot config silently drop its slab/sidecar integrity pin or change serving behavior instead of failing loudly, so unknown entry fields should be rejected during parsing.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

@coderabbitai review

(Head moved mid-review — 87526f8d added docs/ALIGNMENT_PRIMER.md plus a cross-link; please review the full set including it.)


Generated by Claude Code

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

@AdaWorldAPI I will review the complete current pull request, including docs/ALIGNMENT_PRIMER.md and its cross-link.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@AdaWorldAPI AdaWorldAPI changed the title Boot config at .config/&lt;repo&gt;/config.yaml, deployment docs, natural-alignment pin Boot config at .config/<repo>/config.yaml, deployment docs, natural-alignment pin Aug 7, 2026
@AdaWorldAPI
AdaWorldAPI merged commit adf5870 into main Aug 7, 2026
5 checks passed
AdaWorldAPI pushed a commit that referenced this pull request Aug 7, 2026
…2 on #908)

Two P1s from Codex, both real, both now enforced invariants rather than
comments — this field had ALREADY been corrected once in #908 (for naming
the wrong domain) and still shipped wrong in WIDTH, so a doc-comment
warning has demonstrably not been sufficient.

P1-1 — concept id written where a u32 classid belongs. CLASSID_ORDER is
CanonHigh, so a classid is compose_classid(canon, custom): canon (the
minted concept 0xDDCC — domain in the MOST-SIGNIFICANT byte, which is what
makes classids sort/prefix-search hierarchically) in the HIGH half, the
app render prefix in the LOW half. The example config carried the bare
concept "0x0F01", which lands it in the LOW half — classid_canon() then
returns 0 and every reader routes the bake as Reserved/default, the exact
"total class collapse" that function's own doc warns about. Verified from
source, not taken on the reviewer's word.

  Fix: parse() now parses the classid as a real u32 and rejects a zero
  canon half with ConceptIdAsClassid { found, suggestion }, where the
  suggestion is the composed form (0x0F01 -> "0x0F010000") so the operator
  is told what to write, not merely that they were wrong. New
  BakeEntry::classid_u32() so callers stop re-parsing the string and
  re-deciding what a malformed one means. Example config and every test
  fixture moved to composed 8-hex classids.

P1-2 — unknown keys silently ignored. A typo'd `slab_digset` or `hydarte`
was dropped by serde and the field defaulted: digest pin gone, hydration
silently off, in a config whose entire purpose is failing loudly at boot.
Fix: #[serde(deny_unknown_fields)] on BakeEntry and SoaConfig.

Both falsifiers verified by the disable-the-fix run: with the canon check
stubbed to `if false` and both deny_unknown_fields removed, exactly the
two new tests go red (16 passed / 2 failed) and no others — so neither is
passing for an unrelated reason. Each is two-sided: the bad shape is
rejected AND the good shape is accepted with its value intact, so the
rules cannot pass by rejecting everything.

Note the cross-check earned its keep: the_shipped_example_config_parses_
through_this_parser stayed green only because the example was corrected
alongside the parser — fixing one without the other would have gone red.

18/18 soa_config, clippy clean, fmt clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NMeiLmtDKhomJNSo2ecbJw
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