Files
alkblobs/tasks/c1-adr-git-object-family.md
T
glm-5.3-flash 5a347594ab docs(adr): 018 — the git-object derivation family (review-002 C-1's decision half, wave 13)
OQ-15 opened and resolved by ADR-018: the hash registry extends with
the single git-object derivation family — registry bytes 0x03/0x04,
preimage-identity hashing over git's loose-object form as the stored
preimage; the digest byte-identical to git's oid, every kind included.

- The five prototype-uncarried decisions owned: the ops kind question
  (family explicit everywhere; from_git_oid_hex pinned blob-family;
  the ops surface blob-family in 0.1; a family-explicit wire form is
  a named-consumer + new-ADR door), the per-family stat semantic (the
  stored-preimage length), ADR-002's annotated exception (the
  invariants surviving verbatim), the namespace posture (ADR-017's
  caveat stated for the family), and the public put shape
  (put_git_object — known-length only, family members only).
- Fleet threading fixed as part of the family's contract (Decision 7)
  — the derivation-parameterized sites + fleet forms land in
  c1-git-object-family-impl, which this ADR gates.
- The prototype branch's deviations enumerated for the implementation:
  fleet threading, the kind-decision delta, the stat-semantic record,
  the fuzz-seed disposition (0x03 is a committed invalid-tag seed —
  regeneration is expected), the derive-len inertness documented.

Spec updates with dated notes: hashing-and-keys.md (the
derivation-family section, the extended registry, the
from_git_oid_hex contract), store-api.md (the put_git_object seam,
the stat semantic), ops-surface.md (the digest wire form's posture),
ADR-002 (the annotation + registry note), the README ADR index;
open-questions.md register fully resolved; AGENTS.md status
parenthetical updated. No code changes.

Verification: cargo test (default, 209 passed), cargo clippy
--all-targets -- -D warnings, cargo fmt --check — all green (docs/ADR
only; the impl task runs the full block incl. --all-features + the
pg harness and the fuzz gate).
2026-10-17 23:43:30 +00:00

9.4 KiB

id, name, status, depends_on, scope, risk, impact, level, tags
id name status depends_on scope risk impact level tags
c1-adr-git-object-family C-1 (decision half) — the git-object derivation family: OQ-15 resolved to ADR-018 completed
moderate medium project implementation
wave-13
review-002
hashing
adr
one-way-door

Description

Review-002 C-1's decision half (docs/reviews/ 002-first-consumer-review.md): the hash registry extends to non-blob git derivations — the single git-object derivation family (alkgit's DQ-1a, validated by POC-O). The shape on the table: registry bytes 0x03 (git-object-sha-1) / 0x04 (git-object-sha-256); the derivation is preimage-identity — the stored preimage is git's own loose-object form ("<type> <len>\0" + content, the preamble inside the value), so the digest is the plain hash over it, byte-identical to git's oid of the object, every kind included. Read-side verification re-derives with key.algorithm() over the stored preimage byte-identically, so verification-on-get, dedup-by-construction, and external-oid addressing (key = tag + oid, no map) survive unbroken.

The working reference is the prototype branch poc-o-git-objects (f0b045c) — re-derive from it, do not merge it (review-002's own framing; the branch also predates the review-doc commit 714d539, so its deletion of docs/reviews/002 in its diff is branch-divergence noise). This task is docs/ADR only — no code changes; the implementation is the follow-on task c1-git-object-family-impl.

Open OQ-15 in docs/architecture/open-questions.md and resolve it by writing ADR-018. The ADR owns the five decisions the prototype deliberately does not carry:

  1. The ops kind question. Digest::from_git_oid_hex exists on main (40/64-hex → the blob family) and is the ops wire ingress (src/ops/wire.rs digest_ingress; the section doc at src/ops/ mod.rs names "the algorithm lengths' disambiguation"). Once non-blob forms share the digest space, 40-hex is ambiguous across families (GitBlobSha1 vs GitObjectSha1) and 64-hex likewise. The ADR decides what the ingress accepts post-extension, what from_git_oid_hex's contract becomes, and whether the ops surface carries the family at all in 0.1. Input to re-derive, not adopt (the prior session's lean, recorded): the family explicit everywhere; no length-based family guessing — 20-hex is ambiguous across families and git's sha1/sha256 repos differ; the ops surface likely stays blob-family in 0.1 with the family explicit at the store API. Whatever is decided, the schema gate and the ingress must not disagree silently (the S-5 discipline).
  2. The stat semantic. In the extended registry, stat returns the stored preimage length (the loose form, preamble included), not the content length — a deliberate, documented difference from the blob family. Pin it in the ADR and in store-api.md.
  3. ADR-002's domain-separation invariant. This family is preimage-identity hashing — no store-added separation; git's own header is the separation, inside the preimage. It fits ADR-002 only as an annotated exception, written explicitly in the ADR text (and ADR-002 gains the annotation or a pointer), never a silently bent invariant. The invariants surviving verbatim: digest length fixed per algorithm, rejects-never-guesses key decode, total order (0x03/0x04 sort after the blob members), verification-on-get.
  4. The namespace posture. Git oids are global by nature; ADR-017's global-pool caveat applies unchanged. The consumer accepted that posture for git objects on the same terms as its LFS acceptance; the ADR states it for the family explicitly.
  5. The public put shape. put_git_object(algorithm, len, stream) — known-length only (a git object's length is always known up front; the pack-entry and loose-file forms both carry it); kv-only over-threshold rejection inherited from the known-length path. The name, signature, and error mapping are the ADR's to pin.

Spec updates ride the ADR (dated notes; the specs are stable since wave 12): hashing-and-keys.md (the hash family gains the derivation-family section; the key encoding's registry table), store-api.md (the put seam's family form; the stat semantic), ops-surface.md (the digest wire form's posture per the kind decision), ADR-002 (the annotated exception). open-questions.md: OQ-15 opened and resolved.

Acceptance Criteria

  • OQ-15 opened and resolved in open-questions.md; ADR-018 written and accepted
  • All five decisions above explicitly owned — each decided, with the rejected alternatives named (the ADR's Consequences carry them)
  • Specs updated with dated notes: hashing-and-keys.md, store-api.md, ops-surface.md (as applicable), ADR-002's annotation
  • The prototype branch's deviations from the ADR named (what the implementation task must do differently — at minimum the fleet threading and the kind-decision delta)
  • No code changes in this task (docs/ADR only)

References

  • docs/reviews/002-first-consumer-review.md (C-1 — the finding, the not-carried list, the decision framing)
  • branch poc-o-git-objects (f0b045c) — src/hashing.rs, src/keys.rs, src/store/put.rs, tests/git_interop.rs
  • /workspace/@alkdev/alkgit/docs/research/substrate-recomposition.md (§Upstream-push candidates, ask 1) and poco-findings.md (DQ-1a's found consequences)
  • docs/architecture/decisions/002-canonical-hash-and-key-encoding.md (the registry, the preamble-as-abstraction, the one-way door)
  • docs/architecture/hashing-and-keys.md; store-api.md (put/stat); ops-surface.md (the digest wire form); ADR-017 (the global pool)
  • src/ops/wire.rs (digest_ingress); src/ops/mod.rs (the section doc's digest-wire-form paragraph)

Notes

  • Decision-shaping inputs re-verified this session: review-002 C-1 in full; the prototype branch's four files (src/hashing.rs, src/keys.rs, src/store/put.rs, tests/git_interop.rs); alkgit's substrate-recomposition.md (§Upstream-push candidates, ask 1) and poco-findings.md (DQ-1a's found consequences — the loose-form value, preimage-identity, the stat note, the fleet gap, the ops kind question's record); ADR-002/017; the current-tree anchors (src/store/read.rs:48 — the derivation-parameterized verification-on-get site; src/ops/wire.rs digest_ingress + the schema pattern; src/ops/put.rs:333 — the put handler's hardcoded canonical derivation; the fleet put sites src/store/fleet.rs:512/591/627). The review's "src/local.rs:899" anchor is a test helper (the live large-tier derive site is the facade's; the conformance point is unchanged).
  • The five decisions, as ADR-018 pins them: (1) the ops kind question — family explicit everywhere, no length-based family guessing, the ops surface blob-family in 0.1 (from_git_oid_hex's contract pinned blob-family-only; family-explicit oid-bytes construction rides Key::from_bytes over the physical encoding; a family-explicit wire form is a named-consumer + new-ADR door); (2) the stat semantic — the stored-preimage length for family entries, deliberate and per-family; (3) ADR-002's annotated exception — preimage-identity hashing, the invariants surviving verbatim, the annotation written into ADR-002's text; (4) the namespace posture — git oids are global, ADR-017's caveat stated unchanged; (5) the public put shape — put_git_object(algorithm, len, stream), known-length only, family members only, error mapping inherited. Fleet threading is additionally fixed as part of the family's contract (§Decision 7).
  • Rejected alternatives named in the ADR: the oid-to-key map (DQ-1b), a kind-x-hash matrix, length-based family guessing, an unknown-length family arm, deferring the sha-256 sibling byte.
  • Prototype deviations named (the impl task's contract): the fleet threading; the kind-decision delta (behavior already matches the decision — the from_git_oid_hex contract doc, the ops module doc's digest-wire-form paragraph, and ops-surface.md become honest); the stat-semantic record (docs/conformance rows); the fuzz-seed disposition (the committed seeds encode 0x03 as an invalid tag — a no-op regeneration is NOT the expected outcome); the derive-len inertness documented and test-pinned.

Summary

OQ-15 opened and resolved; ADR-018 written and accepted (docs/architecture/decisions/018-git-object-derivation-family.md): the hash registry extends with the single git-object derivation family (bytes 0x03/0x04, preimage-identity over git's loose-object form as the stored preimage — the digest byte-identical to git's oid, every kind included). All five prototype-uncarried decisions owned with rejected alternatives named; fleet threading fixed as part of the family's contract; the prototype branch's deviations enumerated for the implementation task (c1-git-object-family-impl, which this ADR gates). Specs updated with dated notes: hashing-and-keys.md (the derivation-family section, the extended registry, the from_git_oid_hex contract), store-api.md (the put_git_object seam, the per-family stat semantic), ops-surface.md (the digest wire form's blob-family posture, the S-5 discipline satisfied by construction), ADR-002 (the annotated exception + the registry note), the architecture README's ADR index; open-questions.md register fully resolved (OQ-15 → ADR-018; no active OQs remain). AGENTS.md's status parenthetical updated (ADR-018 accepted). No code changes.