Phase 3: Gapped Integer Positions
Phase 3: Gapped Integer Positions
Goal: Eliminate cascading position shifts on block inserts by using gapped integers (spacing of 1000) with periodic rebalance.
Owner: Dev agent
Repo:
forgejo_admin/pal-e-docsDepends on: None (independent of phases 1-2)
Scope
- Block positions: New blocks get positions spaced by 1000 (0, 1000, 2000, ...). Insert between 19000 and 20000 → position 19500. No other rows touched.
- Rebalance endpoint:
POST /notes/{slug}/blocks/rebalancerenumbers all blocks to gapped positions preserving order. - Collision handling: Insert at occupied position shifts only the collider (+1). Gap exhaustion triggers automatic rebalance before insert.
- Delete preserves gaps: No more sequential reindexing on delete.
Deliverables
- PR #189 — merged 2026-03-17
POSITION_GAP = 1000constant inblocks/parser.py, exported fromblocks/__init__.py- Parser produces gapped positions (0, 1000, 2000...)
- Collision-only shift in
create_block(was: shift all blocks at position >= target) - Gap-preserving delete (was: reindex to sequential after every delete)
POST /notes/{slug}/blocks/rebalanceendpoint withRebalanceOutschema- 24 new tests in
test_gapped_positions.py, 4 existing test files updated - 631 total tests passing
Deferred Scope
- Note child positions — not needed (already gap-tolerant)
- BoardItem positions — not needed (already tolerate gaps/collisions)
- Data migration — not needed (old sequential positions still work)
QA Nits (non-blocking)
- Stale docstring in
parser.pylines 33/38 — still references "0-based ordering" and"paragraph-3"examples _seed_note_with_blocksintest_blocks_api.pycould use a comment clarifying intentional use of legacy sequential positions
Related
plan-2026-03-16-knowledge-architecture— parent plan- Forgejo issue #188 (closed)