Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

#46

Number issues and change requests for human references

merged · by keenan 13d ago · merged into main at e05f1c48 by keenan 13d ago

keenan opened this 13d ago

What

Issues and change requests get a shared, gap-free sequence — [#1](/vole/n/1), [#42](/vole/n/42) — that people can read, remember and type. The ULID stays the identity.

The number is derived, not stored: it is the 1-based rank of the entity’s creation commit in the linear vole branch history, counted over issues/*/issue.md and requests/*/request.md together. Nothing is added to a file, no counter or ledger exists, and a repository needs no backfill: this one numbers 1–44 from history alone, and the issue this change closes is [#45](/vole/n/45).

Consequences of deriving it:

  • Nothing is written when an entity is created, so there is no second serialized commit on the one linear branch and no window where an entity exists without a number.
  • The same history gives the same numbers on every clone and every instance, so a number is not instance-local.
  • A deleted entity keeps its number, because its creation commit stays in history. A path deleted and re-added keeps its first number.
  • Editing, labelling or closing an entity never moves its number.
  • vole admin index rebuild reproduces the mapping from git.

The trade-off, documented rather than hidden: the number comes from history, so an admin redaction force-push that rewrites vole renumbers everything after the rewritten commit. That is why the docs keep calling the ULID the durable reference and [#42](/vole/n/42) a convenience, and why closes: still stores ULIDs.

Where it lives

One implementation, two callers, so the CLI and the web cannot disagree:

  • metadata/number.go — LoadNumbers (one git log --reverse --diff-filter=A walk, via the new git.AddedPathsPerCommit) and RankAdditions, the pure rule: commit order across the history, ULID order within one commit, first number wins for a re-added path.
  • forge/index — an entity_numbers table, refreshed in the same transaction as the issue rows and dropped by the same schema-version mechanism, so a page render never walks history. Issues() joins it so the list shows [#42](/vole/n/42) without a second query.
  • client.Branch.Numbers, metadata.FindRequest — the CLI path, which walks the local branch and therefore works offline and with --no-push.

Surfaces:

  • vole issue list --format '%(number) ...', and numbers in the default list, show, issue new and change new confirmations, change list (text and json), change show.
  • Every id-taking command accepts 42 or [#42](/vole/n/42); asking an issue command for a change request’s number says so instead of guessing.
  • --closes 42 on the CLI and [#42](/vole/n/42) in the browser’s Closes field resolve to the ULID before the link is written, so request.md still stores ids.
  • [#42](/vole/n/42) in a body links through the kind-agnostic GET /r/{name}/n/{num}, which redirects to whichever of the two kinds holds the number. #<ulid> still links by id.
  • Issue and request pages and lists show [#42](/vole/n/42) where they used to show the 8-character ULID slice. %(shortid) remains for compatibility.

Review notes

  • The numbering rule is the thing to check: metadata/number_test.go covers the shared sequence, ULID ordering inside a bulk commit, comment/approval/run paths being ignored, re-added paths keeping their number, and an edit or a deletion not moving it. TestLoadNumbersFollowsHistory does the same against a real repository.
  • The integration test now proves the loop end to end: issue list shows [#1](/vole/n/1), issue comment ... '[#1](/vole/n/1)' resolves it, the issue page renders [#1](/vole/n/1), and /r/<repo>/n/1 lands on that issue.
  • schemaVersion goes to 3 so existing instances rebuild their derived rows once instead of serving an empty numbering.

Checks

  • vole workflow check — ok, 2 workflows.
  • vole workflow run verify — ok, 1 job (formatting, vet, build, packaging, link checks, race tests).

Closes #45

Discussion (0)

No discussion yet.