Skip to content

Fix index sort order for IDs with differing digit counts - #22

Merged
linyows merged 1 commit into
mainfrom
fix/index-sort-natural-order
Sep 9, 2026
Merged

linyows merged 1 commit into
mainfrom
fix/index-sort-natural-order

Conversation

@linyows

@linyows linyows commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Problem

draft <template> index could place 0010 before 0009. Two defects caused this.

1. The sort field was compared byte by byte. sortDocuments used mem.order(u8, ...), so IDs written with different digit counts were ordered as text: "10" sorts before "9", and "1000" before "999".

2. The ID taken from a filename was truncated to three characters. extractDocumentMeta read filename[0..3], but the default filename_format for the adr template is {{@id{4}}}-{{@title{kebab}}}.md. A document without an - ID: line therefore got "000" from 0009-foo.md and "010" from 0100-foo.md, which is both a wrong value in the ID column and a wrong sort key.

Observed before the fix, for filenames without an - ID: line:

0009-a.md -> id='000'
0010-b.md -> id='001'
0100-c.md -> id='010'

and for IDs 9 and 10 taken from the document body, 0010-b.md sorted ahead of 0009-a.md.

Changes

  • Added compareNatural, which compares runs of digits by numeric value and the surrounding text byte by byte. Values that are numerically equal but written differently ("9" and "009") fall back to a byte comparison so the ordering stays total. It is used for every string sort field, so @date and @title benefit as well.
  • extractDocumentMeta now takes all leading digits of the filename as the ID, whatever the width.
  • Documents whose sort field is equal are ordered by filename. Previously ties kept the directory iteration order, which is not stable across machines, so the generated index could differ between runs.

Result

With IDs 8, 9, 10, 11, 100 in the document bodies and one document that has no - ID: line (0012-no-id-line.md):

| ID | Title | Status |
|------|------|------|
| [8](./0008-doc-8.md) | Doc 8 | Proposed |
| [9](./0009-doc-9.md) | Doc 9 | Proposed |
| [10](./0010-doc-10.md) | Doc 10 | Proposed |
| [11](./0011-doc-11.md) | Doc 11 | Proposed |
| [0012](./0012-no-id-line.md) | No Id Line |  |
| [100](./0100-doc-100.md) | Doc 100 | Proposed |

Testing

  • Four tests added: ID extraction from a 4-digit filename, compareNatural across digit widths and zero padding, numeric ordering in sortDocuments, and the filename tiebreaker.
  • zig build test --summary all: 64/64 tests passed
  • zig fmt --check reports no differences
  • Manual run of the built binary on the fixture above

README documents the natural ordering and the filename tiebreaker in the index sorting section.

🤖 Generated with Claude Code

https://claude.ai/code/session_017bJFwP1iT8PKTQMWuMAYkZ

Documents were ordered by a byte comparison of the sort field, so IDs
whose digit counts differ were placed in the wrong order: "10" sorts
before "9". Digit runs are now compared by numeric value, and values
that are numerically equal but written differently keep a byte
comparison so the order stays total.

The ID taken from a filename was also limited to the first three
characters, so the default 4-digit filename format produced "000" for
0009-*.md and "0100-*.md" was read as "010". All leading digits are now
used, whatever the width.

Documents whose sort field is equal are ordered by filename, so the
generated index no longer depends on the order the directory happens to
be iterated in.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017bJFwP1iT8PKTQMWuMAYkZ
@linyows
linyows merged commit 71a39dc into main Sep 9, 2026
3 checks passed
@linyows
linyows deleted the fix/index-sort-natural-order branch September 9, 2026 05:13
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.

1 participant