Expand description
The identities of the session domain: six things that the stores spell as three words.
§The defect this module exists for
A forensic read of the writers on 2026-09-11 found one word covering two values in three separate places, and in every case both spellings are durable, both are written by Majordomus, and neither is wrong on its own terms:
| The word | One writer says | Another writer says |
|---|---|---|
| the repository | mj_git_repo_id — the absolute path of the shared git directory | mj_repository_id — the remote URL, or local:<hash of the worktree path> |
| the worktree | mj_record_front_matter — worktree:, an absolute path | mj_session_close — worktree_id:, sixteen hex digits of that path’s digest |
| the session | the episode’s own session_id: s-20260910205542-e2a6 | provider_session:, the provider’s own opaque identity, which is also the key the open record is stored under |
A reader that compares a local record’s repository against a shared record’s compares a
path with a URL and concludes the two records are about different repositories. A reader
that takes provider_session for the session identity attributes an episode to whichever
window of the provider reconnected last. Both are the same mistake — treating a value as
interchangeable with one that means something else — and prose has already failed to
prevent it twice.
So the six are six types here. There is deliberately no From between any two of
them, no shared trait that would accept one where another is wanted, and no
as_str()-to-new() round trip that would launder one into another: every constructor
takes the value’s own spelling and says which store it came from. The compiler refuses
the comparison the audit found.
§What is reused rather than reinvented
RepositoryId and CheckoutId wrap the digests this executable already computes —
crate::repository::git_identity and crate::repository::identity — which are the
same values its server lease, its index cache and its worktree topology are keyed by.
A seventh notion of “which repository” would be exactly the defect above with one more
row. What this module adds is the typing and the record of each store’s own spelling
beside the canonical value, so that a reader can recognise a store’s string without
having to choose which of the two spellings is the real one.
use majordomus_cli::session::{CheckoutId, EpisodeId, ProviderSessionId, TaskId};
use std::path::Path;
let checkout = CheckoutId::of(Path::new("/src/repo-wt/feature/y"));
let episode = EpisodeId::parse("s-20260910205542-e2a6").expect("an episode id");
let provider = ProviderSessionId::new("01Bv2gJsfAoYrXnpfC9uJ4uv");
assert_ne!(checkout.as_str(), episode.as_str());
assert_ne!(episode.as_str(), provider.as_str());
// and an id of one kind never parses as another, whatever it looks like
assert!(TaskId::parse(episode.as_str()).is_none());
assert!(EpisodeId::parse("t-20260905034523-a9f1").is_none());Structs§
- Checkout
Id - One checkout of a repository: the primary one, or one linked worktree of it.
- Episode
Id - An episode’s own identity:
s-<YYYYMMDDHHMMSS>-<4 hex>. - Identity
Facet - One identity of this checkout, as this executable computes it and as each store spells
it. What
session.identityanswers, and the direct projection of the audit’s table. - Provider
Session Id - A provider’s own name for its conversation — an external correlation id, never the episode’s identity.
- Recorded
Spelling - One store’s spelling of one subject. Which half of the layer wrote it, what wrote it, and the value it would have here.
- Repository
Id - A git repository, named without naming a disk.
- TaskId
- A unit of intended work that a person opens and closes:
t-<YYYYMMDDHHMMSS>-<4 hex>. - Worker
Id - Who is working: a worker identity somebody supplied, never one inferred.
Enums§
- Spelling
- Which store a recorded identity was read from, kept beside the value.