Binary DB v0: Payloads, Indexes, and Encodings
Expand every typed payload family, rebuildable index record, metadata bit assignment, enum, and reserved-value rule.
Audience: Codec, validator, and migration implementers
Fixed records frequently point into typed payload files and use compact metadata fields. This chapter gives the complete byte layouts, lookup records, bit assignments, enums, and validation rules needed to decode those values without inventing a generic string or payload format.
Typed Payload Files#
The format defines no shared strings.bin, strings.idx, or strings.hash. Variable-length bytes are owned by a typed domain payload file.
TaskPayload — task_payload.bin:
u16 title_len
u8 title_bytes[title_len]
u8 intent_bytes[payload_len - 2 - title_len]
ChangePayload — change_payload.bin:
u8 title_bytes[payload_len]
PatchsetSummaryPayload — patchset_summary_payload.bin:
u8 summary_bytes[summary_len]
SnapshotPayload — snapshot_payload.bin:
u16 message_len
u8 message_bytes[message_len]
u8 line_name_bytes[payload_len - 2 - message_len]
TagPayload — tag_payload.bin:
u16 tag_name_len
u8 tag_name_bytes[tag_name_len]
u8 message_bytes[payload_len - 2 - tag_name_len]SnapshotLinkPayload — snapshot_link_payload.bin:
u16 worktree_name_len
u16 line_name_len
u16 task_id_len
u16 change_id_len
u16 author_mode_len
u8 worktree_name_bytes[worktree_name_len]
u8 line_name_bytes[line_name_len]
u8 task_id_bytes[task_id_len]
u8 change_id_bytes[change_id_len]
u8 author_mode_bytes[author_mode_len]
u8 model_name_bytes[
payload_len - 10 - worktree_name_len - line_name_len - task_id_len
- change_id_len - author_mode_len
]ActorPayload — actor_payload.bin:
u8 user_name_len
u8 user_id_len
u8 email_len
u8 user_name_bytes[user_name_len]
u8 user_id_bytes[user_id_len]
u8 email_bytes[email_len]
u8 memo_bytes[payload_len - 3 - user_name_len - user_id_len - email_len]
ReviewPayload — review_payload.bin:
u8 message_bytes[payload_len]
WaiverPayload — waiver_payload.bin:
u8 reason_bytes[payload_len]
PlanPayload — plan_payload.bin:
u8 title_bytes[payload_len]PlanRevisionPayload — plan_revision_payload.bin:
u16 title_snapshot_len
u16 summary_len
u16 artifact_path_len
u16 artifact_selector_len
u16 artifact_heading_len
u8 title_snapshot_bytes[title_snapshot_len]
u8 summary_bytes[summary_len]
u8 artifact_path_bytes[artifact_path_len]
u8 artifact_selector_bytes[artifact_selector_len]
u8 artifact_heading_bytes[artifact_heading_len]
u8 artifact_blob_id_bytes[
payload_len - 10 - title_snapshot_len - summary_len - artifact_path_len
- artifact_selector_len - artifact_heading_len
]PlanItemPayload — plan_item_payload.bin:
u16 plan_item_ref_len
u16 text_len
u8 plan_item_ref_bytes[plan_item_ref_len]
u8 text_bytes[text_len]
u8 heading_path_bytes[payload_len - 4 - plan_item_ref_len - text_len]GitRepositoryPayload — git_repository_payload.bin:
u8 identity_bytes[identity_len]
GitIdentityPayload — git_identity_payload.bin:
u32 raw_len
u32 name_len
u8 raw_identity_bytes[raw_len]
u8 name_bytes[name_len]
u8 email_bytes[payload_len - 8 - raw_len - name_len]
GitCommitMappingPayload — git_commit_mapping_payload.bin:
u32 message_len
u8 message_bytes[message_len]
u8 raw_commit_bytes[payload_len - 4 - message_len]
GitFileMappingPayload — git_file_mapping_payload.bin:
u8 path_bytes[path_len]
GitRefMappingPayload — git_ref_mapping_payload.bin:
u8 ref_name_bytes[ref_name_len]
GitTagMappingPayload — git_tag_mapping_payload.bin:
u32 message_len
u8 message_bytes[message_len]
u8 raw_tag_bytes[payload_len - 4 - message_len]heading_path_bytes requires a stable schema-defined encoding. Layout v0 does not choose a new canonical representation. A writer must therefore preserve an already admitted layout-1 encoding or fail closed.
Single-field payloads do not repeat an inner length. Their length comes from the owning record's payload_len or, for Patchset summary only, summary_len. Multi-field payloads store lengths for every variable field except the last; the last length is derived from the owning record's payload_len. Underflow, empty required textual fields, and invalid UTF-8 in fields declared as UTF-8 are rejected. Fields explicitly declared as opaque Git bytes are not UTF-8 decoded.
Actor, Task, Change, Snapshot, Snapshot Link, Tag, Review, Waiver, and Plan-family records use u16 payload_len, limiting one payload to 65535 bytes. Patchset summary uses u16 summary_len, requires 1..65535 bytes, and has the same upper bound without becoming a generic Patchset payload. Actor component lengths and Tree path-segment lengths use u8, limiting each to 255 bytes. Git identity, commit, and Tag-mapping payloads use u32 payload_len; Git repository identity, file path, and ref-name lengths are also u32. A value that exceeds u32 is rejected before writing. line_name_payload.bin, tree_name_payload.bin, and optional snapshot_path_payload.bin store their owning record's normalized UTF-8 bytes.
AIT Tag name/message, Git repository identity, Git identity components, Git file path, and Git ref name must be valid UTF-8 under the current command contract. Git commit message, raw commit, Git Tag message, and raw annotated-Tag bytes are length-bounded opaque bytes and are never Base64-encoded in Binary DB. An identity authored by AIT may use raw_len = 0; an identity preserved from Git must retain its raw bytes. Lightweight Git Tags have empty raw Tag bytes.
Attestation, Policy Decision, and Land records own no payload file. Patchset owns only patchset_summary_payload.bin; patchset_payload.bin is not a v0 file.
Rebuildable Indexes#
.idx files are lookup accelerators, never identity or authority. They may be absent or rebuilt. A hit is accepted only after comparing the referenced authoritative record or payload bytes. Persistent rows are sorted by lookup-key bytes and then target index.
SNAPSHOT_ID_INDEX_RECORD_SIZE = 12
SnapshotIdIndexRecord — snapshot_id.idx:
u64 snapshot_hash48
u32 content_snapshot_index_plus1
SNAPSHOT_PARENT_CHILD_INDEX_RECORD_SIZE = 8
SnapshotParentChildIndexRecord — snapshot_parent_child.idx:
u32 child_snapshot_index
u32 parent_edge_index_plus1
TREE_ID_INDEX_RECORD_SIZE = 14
TreeIdIndexRecord — tree_id.idx:
u8 tree_hash80[10]
u32 tree_index_plus1
TREE_PACK_ID_INDEX_RECORD_SIZE = 12
TreePackIdIndexRecord — tree_pack_id.idx:
u64 pack_hash48
u32 tree_pack_index_plus1BLOB_ID_INDEX_RECORD_SIZE = 14
BlobIdIndexRecord — blob_id.idx:
u8 blob_hash80[10]
u32 blob_index_plus1
OBJECT_PACK_ID_INDEX_RECORD_SIZE = 12
ObjectPackIdIndexRecord — object_pack_id.idx:
u64 pack_hash48
u32 object_pack_index_plus1
MANIFEST_HASH_INDEX_RECORD_SIZE = 36
ManifestHashIndexRecord — manifest_hash.idx:
u8 manifest_hash[32]
u32 content_snapshot_index_plus1ACTOR_LOOKUP_INDEX_RECORD_SIZE = 12
ActorLookupIndexRecord — actor_lookup.idx:
u64 actor_key_hash
u32 actor_index_plus1
LINE_NAME_INDEX_RECORD_SIZE = 12
LineNameIndexRecord — line_name.idx:
u64 line_name_hash64
u32 line_index
TAG_NAME_INDEX_RECORD_SIZE = 12
TagNameIndexRecord — tag_name.idx:
u64 tag_name_hash64
u32 tag_indexGIT_REPOSITORY_FINGERPRINT_INDEX_RECORD_SIZE = 16
GitRepositoryFingerprintIndexRecord — git_repository_fingerprint.idx:
u8 fingerprint96[12]
u32 repository_index_plus1
GIT_GENERATION_ID_INDEX_RECORD_SIZE = 12
GitGenerationIdIndexRecord — git_generation_id.idx:
u8 generation_hash64[8]
u32 generation_index_plus1
GIT_COMMIT_OBJECT_INDEX_RECORD_SIZE = 28
GitCommitObjectIndexRecord — git_commit_object.idx:
u32 generation_index
u8 git_object_id[20]
u32 commit_mapping_index_plus1
GIT_COMMIT_SNAPSHOT_INDEX_RECORD_SIZE = 8
GitCommitSnapshotIndexRecord — git_commit_snapshot.idx:
u32 snapshot_index
u32 commit_mapping_index_plus1GIT_REF_LOOKUP_INDEX_RECORD_SIZE = 16
GitRefLookupIndexRecord — git_ref_lookup.idx:
u32 repository_index
u64 ref_name_hash64
u32 ref_mapping_index_plus1
GIT_TAG_REF_INDEX_RECORD_SIZE = 8
GitTagRefIndexRecord — git_tag_ref.idx:
u32 git_ref_mapping_index
u32 git_tag_mapping_index_plus1
GIT_OPERATION_ID_INDEX_RECORD_SIZE = 12
GitOperationIdIndexRecord — git_operation_id.idx:
u8 operation_hash64[8]
u32 checkpoint_index_plus1Snapshot parent-child keys admit duplicate candidates and return edge indexes in ascending order; authoritative edge ordinals are verified after lookup. Git ref lookup uses the import source repository index or export target repository index. Hash hits for Tag and Git ref names are accepted only after exact typed payload comparison. Commit-by-Snapshot lookup may return both import and export candidates; generation direction, mapping flags, object format, and recorded order select the landed preference of unchanged import before deterministic export.
Plan Item refs are resolved through a revision's item range and exact payload comparison. Layout v0 defines no persistent Plan Item ref hash index.
Metadata Encodings#
All bits and values not assigned below are reserved and must be written as zero.
TaskRecord.task_meta:
bit 0 planned
bit 1 snapshotted
bit 2 review_pending
bit 3 validation_pending
bit 4 blocked
bit 5 ready_to_land
bit 6 completed
bit 7 canceled
LocalTaskRecord.local_meta:
bit 0 published
bit 1 abandoned
bit 2 later_promotion_excluded
Remote task/change/mirror remote_meta:
bit 0 tombstone
bit 1 partial
bit 2 conflict
bit 3 staleChangeRecord.change_meta:
bits 0..1 lifecycle: 00 draft, 01 active, 10 landed, 11 archived
bit 2 has_patchsets
bit 3 review_pending
bit 4 validation_pending
bit 5 ready_to_land
bit 6 blocked
bit 7 superseded; valid only with lifecycle 11
ChangeRecord.change_state:
bit 0 canceled; valid only with lifecycle 11
bits 1..7 reserved = 0
LocalChangeRecord.local_meta:
bit 0 published
WorktreeCursorRecord.cursor_meta:
bit 0 has_selected_change
bit 1 has_pending_pre_land_target_snapshot
bit 2 has_pending_landed_snapshotFor a Local Change, local_meta bit 0 and published_remote_change_ordinal_plus1 obey the presence and owning-Task invariants in the Change Records section. The four-byte publication slot never stores a global Remote Change index.
LineRecord.line_meta:
bit 0 archived
bit 1 tombstone
TagRecord.tag_meta:
bit 7 tombstone
StashRecord.stash_meta:
bit 0 workspace_cleared
bit 7 tombstone
LandRecord.land_meta:
bits 0..2 status_kind:
000 queued
001 running
010 succeeded
011 blocked
100 failed
101 canceled
110 updating
111 reserved
bit 3 has_pre_land_target_snapshot
bit 4 has_landed_snapshot
bits 5..6 mode_kind:
00 direct
01 merge
10 ff_only
11 reserved
bit 7 tombstone
LandRecord.failure_kind:
0 none
1 base_stale
2 policy_blocked
3 review_blocked
4 ci_blocked
5 conflict
6 target_update_failed
7 internal_errorContentSnapshotRecord.snapshot_meta:
bits 0..1 snapshot_kind: 00 line, 01 stash
bit 2 has_message
bit 3 has_line_name_payload
bit 4 parent_edges_authority
bit 5 has_root_locator
bit 7 tombstone
ContentSnapshotRecord.history_flags:
bit 0 remote_head_history_boundary
bits 1..7 reserved = 0
SnapshotLinkRecord.link_meta:
bit 0 has_change
bit 1 has_session
bit 2 has_checkpoint
bit 3 has_worktree_name
bit 4 has_line_name
bit 5 has_author_or_model
bit 7 tombstoneGitRepositoryRecord.repository_meta bits 0..1:
00 Git import source; public prefix GSR
01 Git export target; public prefix GTR
10 AIT export source; public prefix ASR
11 reserved
GitRepositoryRecord.object_format_kind:
0 not_applicable for an AIT repository
1 sha1
GitGenerationRecord.generation_meta bits 0..1:
00 import; public prefix GIT-IMP
01 export; public prefix GIT-EXP
10..11 reserved
GitIdentityRecord.identity_meta:
bit 0 has_raw_identity
GitCommitMappingRecord.mapping_meta:
bit 0 signed
bit 1 imported_unchanged
bit 2 deterministicGitRefMappingRecord.ref_meta:
bits 0..1 ref_kind: 00 branch, 01 tag, 10 symbolic_ref, 11 reserved
bit 2 has_snapshot
bit 3 has_target
bit 4 has_expected_previous_git_object_id
GitTagMappingRecord.tag_mapping_meta:
bit 0 signed
bit 1 deterministic
bit 2 has_raw_tag
GitOperationCheckpointRecord.checkpoint_meta bits 0..1:
00 running
01 completed
10..11 reserved
Git git_object_type_kind:
0 commit
1 tree
2 blob
3 tagPlanRecord.plan_meta:
bits 0..1 plan_state: 00 draft, 01 archived, 10 superseded
bit 2 published
bit 3 stale
bit 4 conflict
bit 5 tombstone
PlanRevisionRecord.revision_meta:
bit 0 published
bit 1 stale
bit 2 conflict
bit 3 has_items
bit 4 tombstone
PlanItemRecord.item_meta:
bits 0..1 checkbox_state: 00 none, 01 open, 10 done
bit 2 has_item_ref
bit 3 taskableTreePackRecord.pack_meta:
bit 0 ready
bit 1 corrupt
bit 2 sparse_physical_ordinals
bit 7 tombstone
TreePackRecord.pack_format_kind:
0 zip_deflate_tree_v1
1 zstd_chunked_tree_v1
TreeRecord.tree_meta:
bit 7 tombstone
TreeEntryRecord.entry_meta bits 0..1:
00 blob
01 treeObjectPackRecord.pack_meta:
bit 0 ready
bit 1 corrupt
bit 2 pruned
bit 7 tombstone
ObjectPackRecord.pack_format_kind:
0 zip_deflate_v2
1 zstd_chunked_v1
ObjectPackMemberRecord.member_meta:
bits 0..1 entry_kind: 00 full, 01 delta
bits 2..3 compression_kind: 00 none, 01 deflate, 10 zstd
bit 7 tombstone
BlobRecord.blob_meta:
bit 0 has_pack_member
bit 1 pruned
bit 7 tombstone
BlobRecord.hash_kind:
0 sha256PatchsetRecord.patchset_meta:
bit 0 withdrawn
bit 1 invalidated
bits 2..4 author_mode_kind:
000 human_only
001 human_with_ai_assist
010 ai_with_human_review
011 ai_only_experimental
100 agent (legacy conversion only)
101 codex (legacy conversion only)
110 xhigh (legacy conversion only)
111 reserved
bits 5..6 publish_state_kind:
00 published
01 reserved
10 superseded
11 reserved
bit 7 evaluation_pending
AttestationRecord.attest_meta:
bits 0..1 verification_state: 00 unknown, 01 pending, 10 pass, 11 fail
bit 2 revoked
bit 3 require_tests_pass
bit 4 require_human_review
bit 5 require_lint_pass
bit 6 ci_backed
bit 7 tombstone
ActorRecord.actor_meta:
bits 0..2 actor_kind:
000 user
001 team
010 bot
011 service_account
100 automation
101 unknown
bit 3 has_user_id
bit 4 has_email
bit 5 has_memo
bit 7 tombstoneNative v0 Patchset writers emit only the four non-legacy author modes. The three legacy codes exist solely to preserve exact admitted source rows during conversion; unknown author text fails closed. Native v0 Patchset writers emit only published or superseded publish state. A legacy source Patchset state selected_for_landing is a non-authoritative projection and normalizes to published; it is never written as 01, used to infer selection, or allowed to override RemoteChangeRecord.selected_patchset_index_plus1. If a valid source Change selected pointer disagrees with stale Patchset projections, the Change pointer is authoritative and conversion does not fail solely for that projection disagreement. A missing, invalid, or ambiguous source Change pointer still fails whenever source selection is required. The selected pointer may reference a published or superseded legacy row only when the source Change pointer explicitly does so and all ownership and liveness rules otherwise pass.
When evaluation_pending is set, public Patchset evaluation_state is pending even if an older Policy Decision exists. When it is clear, a latest live non-pending Policy Decision is required and supplies the exact pass, soft_fail, hard_fail, or waived value. New Patchsets and any review, attestation, waiver, or policy-input mutation that invalidates cached policy set this bit as the status-last commit marker; a completed non-pending Policy evaluation appends its decision before clearing the bit.
ReviewRecord.review_meta:
bits 0..2 action_kind:
000 request
001 comment
010 approve
011 request_changes
100 dismiss
bit 3 blocking
bit 4 task_lane
bit 5 code_review_summary
bit 6 defer
bit 7 tombstone
PolicyDecisionRecord.policy_meta:
bits 0..2 decision_kind:
000 pending
001 pass
010 soft_fail
011 hard_fail
100 waived
bit 7 tombstone
WaiverRecord.waiver_meta:
bit 0 revoked
bit 7 tombstonePolicyCheckRecord.check_kind:
0 require_attestation
1 ai_provenance
2 code_review_summary
3 tests
4 lint
5 security_scan
6 license_scan
7 required_human_review
8 ci_rollout_phase
9 ci_patchset_suite
PolicyCheckRecord.check_status:
0 absent
1 not_required
2 pending
3 pass
4 hard_fail
5 soft_fail
6 waived
7 optional_fail