Allocate Collision-Ledger Entries for Parallel Work

When two agents work in parallel, they need stable ids that do not collide. Each agent records a numbered entry in shared memory. If each agent writes its id straight onto a shared markdown page, the two writes collide at merge time, and one id overwrites the other without any warning.

The collision ledger removes that race. It allocates identity on an append-only issue thread. GitHub serializes every comment on that thread and assigns a monotonic id. The shared page is a projection that you rebuild from that thread.

This guide shows how to allocate an id at an anchor, how to rebuild the ledger page and the memory row from the anchor record, and how to verify that the projection still matches. It assumes that the wiki is already set up. See Set Up Persistent Memory and Metrics.

Prerequisites

  • Node.js 22+
  • The gemba-wiki command. Run it with npx gemba-wiki, or install the command family with npm install -g @forwardimpact/gemba
  • A wiki already initialized in your project
  • GITHUB_TOKEN or GH_TOKEN set, or a logged-in gh CLI. The ledger reads and writes an issue's comment thread over the GitHub API
  • One issue in your repository that holds the anchor thread. Pass its number with --issue

How allocation stays collision-free

Allocation only publishes an anchor and never writes the page. An anchor is one append-only comment on the anchor issue that contains a small fenced block:

kind: occ
ids: ["#97", "#98"]
event: 7d0f8bca
note: two sessions on one task

The durable key is event. It holds a commit SHA or a prior anchor id. The ids are display labels only, so a later relabel loses nothing. Because GitHub assigns each comment a monotonic id, the comment order is an allocation order that no merge can erase. When two sessions race for the same label, the lowest comment id wins, so the first published anchor keeps the label. The command writes nothing to the ledger page at allocation time, so the shared page never takes part in the race.

Each anchor has one of four kinds. The projection groups the ids under one heading per kind:

Kind Projection heading Used for
occ Occurrences One occurrence of the tracked event.
nm Near-misses A near-miss.
fold Folds A fold of prior allocations into one id.
meta Meta-instances An allocation about the practice itself.

The ledger allocates ids but does not define what each kind means. That meaning belongs to the practice your team runs on the platform. Kata is the reference tenant, and its improvement practice defines an occurrence, a near-miss, and a fold. See Kata.

Allocate an id

Mint the next free id of a kind, keyed to a durable event:

npx gemba-wiki ledger allocate --kind occ --issue 42 --event 7d0f8bca --note "two sessions on one task"
#97

The command prints the provisional id it minted. To allocate several at once:

npx gemba-wiki ledger allocate --kind occ --count 2 --issue 42 --event 7d0f8bca
#97 #98

The printed ids are provisional. A later rebuild over the published comment sequence is authoritative. It resolves any concurrent interleave in first-published-wins order, so two racing allocations never keep the same label.

Backfill an id that predates the ledger

Some ids already exist in history and have no anchor. Do not mint new ones for them. Register them explicitly:

npx gemba-wiki ledger allocate --kind occ --ids "#42,#43" --issue 42 --event a1b2c3d4

If any of these ids already has an anchor, the command refuses, so no id is registered twice.

Allocation options

Flag Required Description
--kind Yes occ, nm, fold, or meta.
--event Yes Durable key for the allocation (a SHA or a prior anchor id).
--count No How many ids to mint (default 1).
--ids No Comma-separated ids to backfill, instead of --count.
--note No Free-text note recorded on the anchor.
--issue No Anchor issue number.

If you omit --issue, the command falls back to a single built-in issue number, which is the reference tenant's own anchor thread. In your own project, pass --issue on every ledger subcommand.

Rebuild the projection

The ledger page and the memory row are projections of the anchor record. After you publish new anchors, rebuild them from the authoritative thread:

npx gemba-wiki ledger rebuild --issue 42
rebuilt: 12 ids, 0 double-allocation(s)

rebuild reads the full anchor sequence, folds it, and resolves any double allocation in first-published-wins order. It then writes the result to the ledger page and the memory row. It preserves any prose you wrote against an anchor. If the prose cites an anchor that no longer exists, the command warns:

warning: prose cites missing anchors: #44

By default, rebuild renumbers a double-allocation loser. Pass --gapped to render it as a gap instead. A gap keeps the original numbers visible.

Verify

Confirm that the projection matches the anchor record. This check writes nothing:

npx gemba-wiki ledger verify --issue 42
verify: clean

verify re-projects the anchor record and compares the result against the ledger page and the memory row. When they differ, it lists the problems and exits non-zero:

verify: ledger page diverges from the anchor record; MEMORY row diverges from the anchor record

Run rebuild to fix this, because rebuild re-projects both surfaces. Then run verify again to confirm that they agree.

What's next