Skip to content

freeze path_grouping remainder rule in spec §6.1#127

Merged
espg merged 1 commit into
mainfrom
claude/124-path-grouping-remainder
Jul 21, 2026
Merged

freeze path_grouping remainder rule in spec §6.1#127
espg merged 1 commit into
mainfrom
claude/124-path-grouping-remainder

Conversation

@espg

@espg espg commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Closes #124

What

The v1.0 spec page §6.1 declared path_grouping but never stated which component absorbs the remainder when order % path_grouping != 0. Three implementations (gridlook TS hive.ts, moczarr group_digits in espg/moczarr#17, and the pg3 fixture layout) all independently chose leading-full-width / remainder-last by convergent judgment, not by contract — a fourth implementation could legally pick remainder-first and produce disjoint trees.

This PR freezes that rule as normative.

Approach

  • docs/specification.md §6.1 — added one normative "Grouping remainder (contract)" bullet plus one worked example (fenced, wrapped in <!-- example:path_grouping:begin/end --> drift markers matching the existing table:order2res pattern). It states:

    • the {sign+base} component stands alone and never participates in groupingpath_grouping chunks only the order-digit string;
    • leading digit components are full-width; the final component carries the remainder (never remainder-first), with the rationale that it is the only split preserving shared ancestor directories across mixed shard orders;
    • worked example: order 8 at path_grouping: 33+3+24/331/422/41/433142241.zarr.
  • mortie/tests/test_spec_page.py — added TestPathGroupingRemainder, a drift-pin that parses the worked example out of the doc and anchors it against the real hive_path code path:

    • {sign+base} component, per-order digit sequence, and full-id leaf must match exactly what MortonIndexArray.from_hive_path(...).hive_path() produces for that id (this pins the {sign+base}-stands-alone rule and that the grouped components partition exactly mortie's order-digit string);
    • the documented grouped widths must equal a leading-full-width / remainder-last partition (flipping the example remainder-first fails here).

Scope note on the drift-pin

mortie itself only ships path_grouping: 1hive_path emits one digit per level and has no grouping>1 code surface. So the grouped split cannot be produced by mortie code, and the remainder placement is prose-normative (the freeze that #124 asks for). The test pins everything mortie can produce (the example's skeleton against hive_path) and enforces the remainder-last arithmetic on the documented example, rather than adding a hollow test or inventing a new grouping API. Per the issue this is the right call: the rule is a cross-implementation contract for gridlook/moczarr, not new mortie behavior.

How tested

  • flake8 mortie --select=E9,F63,F7,F82 — clean; test file also clean at --max-line-length=88.
  • pytest -q685 passed, 11 skipped, 1 failed. The single failure is the pre-existing red-main test_spec_page.py::TestDecimalParseTieBreak::test_order29_string_parses_to_area_word (tracked as main is red: test_spec_page tie-break test predates #120's p-suffix rendering #123, fixed in a separate PR); this change does not touch that code. Both new TestPathGroupingRemainder cases pass.

Questions for review

  • Pre-existing failure: main is red from main is red: test_spec_page tie-break test predates #120's p-suffix rendering #123 (test_order29_string_parses_to_area_word), excluded above as out of scope. Flag if you'd rather I not open on red main.
  • Drift-pin depth: I anchored the example skeleton to hive_path (grouping=1) and checked the split arithmetic, but the remainder placement has no grouping>1 code to pin against. If you'd prefer this stay purely prose (no test), say so and I'll drop TestPathGroupingRemainder.
  • Example id: used the issue's 433142241 (order 8, path_grouping: 3, split 3+3+2) verbatim; it round-trips through from_hive_path. Confirm the notation matches your intent for the frozen example.

🤖 Generated with Claude Code


Generated by Claude Code

@espg espg added the implement label Jul 21, 2026

@espg espg left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

🤖 from Claude (review)

Adversarial review of the §6.1 path_grouping remainder freeze against issue #124's acceptance and CLAUDE.md. Net: the contract is correct and the drift-pin is honest — no blocking findings. Details below.

Digit-math verification (checked against the real code path): CORRECT.

  • Full id 433142241, order 8, path_grouping: 3.
  • {sign+base} = 4 (leading [1-4], no sign), stands alone.
  • Order-digits = 33142241 (8 digits = order 8). ✓
  • Chunk 3+3+2331 / 422 / 41; concatenation 331+422+41 = 33142241. ✓
  • Leaf 433142241 = 4 + 33142241. ✓
  • Rendered path 4/331/422/41/433142241.zarr matches. ✓
  • I traced MortonIndexArray.from_hive_path(["433142241.zarr"]).hive_path()[0]4/3/3/1/4/2/2/4/1/433142241.zarr, so the skeleton test's {sign+base}, per-order digit sequence, and full-id leaf all match real code. The .zarr leaf is passed through from_hive_path (suffix-stripped, single-component → digit-chain check skipped) and round-trips cleanly.

Drift-pin is non-hollow (not vacuous).

  • _doc_example asserts both markers are present ("example markers missing"), so deleting the markers fails loudly rather than silently no-op'ing — the specific failure mode to watch for is handled.
  • test_example_skeleton_matches_hive_path pins the leaf/sign-base/order-digit concatenation to what hive_path actually emits, so an incoherent edit to the example fails.
  • The concatenation check alone is order-invariant (remainder-first 4/33/142/241/... would also concat to 33142241), but test_example_split_is_remainder_last closes that gap by pinning the widths to [3,3,2] — flipping remainder-first yields [2,3,3] and fails. The two tests are complementary and together cover the freeze. Judged honest given mortie ships only path_grouping: 1 and has no grouping>1 surface to pin against; not overreaching, and correctly avoids inventing a grouping API.

Acceptance / convention checks — all pass.

  • Rationale ("only split that keeps a coarser shard's grouped prefix a directory-prefix of its finer descendants") is sound: leading full-width groups are a function of digit position only, independent of total order, so they align across mixed shard orders; remainder-first makes leading boundaries order-dependent and produces disjoint trees. Matches moczarr's recorded justification.
  • Explicitly states {sign+base} stands alone and does not participate in grouping — both in the prose bullet and in the worked example. ✓
  • Markers mirror the existing table:order2res drift-pin pattern (<!-- example:path_grouping:begin/end -->). ✓
  • Commit is title-only (freeze path_grouping remainder rule in spec §6.1 (issue #124)), no long body, no attribution line in the message. ✓
  • No @-mentions anywhere in the diff, PR body, or commit. ✓
  • Test/prose style matches the surrounding file; line lengths within --max-line-length=88. ✓
  • Pre-existing #123 red-main failure is correctly excluded and flagged under "Questions for review" rather than "fixed." ✓

Minor (non-blocking, take-or-leave):

  1. test_example_skeleton_matches_hive_path unpacks path, grouping = self._doc_example() but never uses grouping — could be path, _ = .... Harmless (pyflakes doesn't flag F841 on tuple unpacking, and F841 isn't in the E9/F63/F7/F82 blocking select anyway); purely cosmetic.
  2. Issue #124 phrased the ask as "one sentence + one worked example"; the bullet spans a few sentences (contract + remainder + rationale). The content is accurate and terse — noting only for literal fidelity to the wording, not a defect.

Nothing here needs to block the freeze. Answering the PR's three open questions is an @espg call, not something this review resolves.


Generated by Claude Code

@codspeed-hq

codspeed-hq Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 67 untouched benchmarks
⏩ 1 skipped benchmark1


Comparing claude/124-path-grouping-remainder (e5a054f) with main (4b57a1f)

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

@espg espg left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

🤖 from Claude (review)

Adversarial review of the §6.1 grouping-remainder freeze (issue #124). Verified against the issue's normative rule and the real hive_path code path — clean, no blocking defects.

Checks performed:

  • Normative rule matches the issue exactly. Prose reads "the leading digit components are full-width and the final component carries the remainder (never remainder-first)" — verbatim to the issue's "leading components full-width, last component carries the remainder."
  • {sign+base}-stands-alone statement present and correct. "the {sign+base} component stands alone and never participates in grouping — path_grouping chunks only the order-digit string that follows it." Consistent with §6.1's constant-width {sign+base} and §2 notation.
  • Worked example is arithmetically correct and consistent with page notation. 433142241head=1 in hive_path (morton_index.py:586-588) → {sign+base}=4, eight order-digits 33142241, leaf 433142241.zarr. At path_grouping: 3: 8 = 3+3+2 leading-full-width → 331/422/41, giving the documented 4/331/422/41/433142241.zarr. Order digits all in [1-4], base 4 in [1-6] — both valid.
  • Justification matches the recorded cross-impl rationale (coarser shard's grouped prefix stays a directory-prefix of finer descendants → shared ancestors survive across mixed orders).
  • Drift-pin test hits real code, not an invented API. MortonIndexArray.from_hive_path / hive_path both exist (morton_index.py:563, 592) and are exported from mortie. test_example_skeleton_matches_hive_path reconstructs the canonical grouping=1 decomposition from the live code and asserts {sign+base}, leaf, and concatenated order-digits all match — so editing the example incoherent fails. test_example_split_is_remainder_last independently pins [3,3,2] (remainder-last); a remainder-first edit ([2,3,3]) fails. Both pass under the decomposition above.
  • Prose-normative scope is honestly stated: mortie ships only path_grouping: 1 (hive_path emits one digit/level, no grouping param), so the split has no executable surface — the test pins the example's skeleton against real code and the partition shape in prose, which is the right seam.

No contradictions with §2 or §6.2. Terse and well-scoped.

Minor non-blocking nit (optional): in test_example_skeleton_matches_hive_path, grouping is unpacked from _doc_example() but unused in that method; harmless (not in the CI-blocking flake8 set), drop it if convenient.


Generated by Claude Code

@espg espg added the waiting label Jul 21, 2026
@espg espg mentioned this pull request Jul 21, 2026
@espg
espg marked this pull request as ready for review July 21, 2026 16:07
@espg
espg merged commit 8a67647 into main Jul 21, 2026
16 of 19 checks passed
@espg
espg deleted the claude/124-path-grouping-remainder branch July 21, 2026 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Spec §6: freeze the path_grouping remainder rule (currently implementation-convergent, not normative)

2 participants