Binary DB v0:payload、索引与编码
展开每一类带类型的 payload、可重建索引记录、元数据位分配、enum 以及保留值规则。
适用人群: 编解码、校验与迁移实现者
定长记录经常指向带类型的 payload 文件,并使用紧凑的元数据字段。本章给出完整的字节布局、查找记录、位分配、枚举和校验规则,让你不必自行发明通用字符串或 payload 格式就能解码这些值。
带类型的 Payload 文件#
本格式没有定义共享的 strings.bin、strings.idx 或 strings.hash。 变长字节由某个带类型的领域 payload 文件持有。
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 需要一种由 schema 定义的稳定编码。布局 v0 没有 选定新的规范表示。因此写入方必须保留已被接纳的 layout-1 编码, 否则就要 fail closed。
单字段 payload 不会重复内层长度。它们的长度来自所属记录的 payload_len,只有 Patchset summary 例外,用的是 summary_len。多字段 payload 为除最后一个之外的每个变长字段存储长度; 最后一个字段的长度由所属记录的 payload_len 推导得出。下溢、必填文本字段 为空,以及声明为 UTF-8 的字段中出现非法 UTF-8,都会被拒绝。明确声明为 不透明 Git 字节的字段不做 UTF-8 解码。
Actor、Task、Change、Snapshot、Snapshot Link、Tag、Review、Waiver 以及 Plan 家族的记录使用 u16 payload_len,因此单个 payload 上限为 65535 字节。 Patchset summary 使用 u16 summary_len,要求 1..65535 字节,上界相同, 但并不因此变成通用的 Patchset payload。 Actor 各组成部分的长度和 Tree 路径段长度使用 u8,因此各自上限为 255 字节。 Git identity、commit 和 Tag 映射 payload 使用 u32 payload_len;Git repository identity、文件路径和 ref 名称长度同样是 u32。超出 u32 的值在写入之前就会被拒绝。line_name_payload.bin、 tree_name_payload.bin 以及可选的 snapshot_path_payload.bin 存放所属记录 归一化后的 UTF-8 字节。
在当前命令契约下,AIT Tag 名称/消息、Git repository identity、Git identity 各组成部分、Git 文件路径和 Git ref 名称必须是合法 UTF-8。Git commit 消息、 原始 commit、Git Tag 消息以及带注解 Tag 的原始字节都是有长度上界的不透明 字节,在 Binary DB 中绝不做 Base64 编码。由 AIT 生成的 identity 可以用 raw_len = 0;从 Git 保留下来的 identity 必须保留其原始字节。轻量 Git Tag 的原始 Tag 字节为空。
Attestation、Policy Decision 和 Land 记录不持有 payload 文件。Patchset 只持有 patchset_summary_payload.bin;patchset_payload.bin 不是 v0 的文件。
可重建索引#
.idx 文件是查找加速器,绝不是身份或权威。它们可以缺失,也可以重建。 命中只有在比对过所引用的权威记录或 payload 字节之后才被接受。持久化的行 先按查找键字节排序,再按目标索引排序。
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 父子键允许出现重复候选,并按升序返回边索引;权威的边序号在查找 之后再做校验。Git ref 查找使用导入源 repository 索引或导出目标 repository 索引。Tag 名称和 Git ref 名称的哈希命中,只有在做过精确的带类型 payload 比对之后才被接受。按 Snapshot 查 commit 可能同时返回导入和导出候选;由 generation 方向、映射标志位、对象格式和记录顺序共同决定 landed 优先级—— 未改动的导入优先于确定性导出。
Plan Item 的 ref 通过某个 revision 的条目区间加精确 payload 比对来解析。 布局 v0 没有定义持久化的 Plan Item ref 哈希索引。
元数据编码#
下面未分配的所有位和值都是保留的,必须写为零。
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_snapshot对于 Local Change,local_meta 的 bit 0 和 published_remote_change_ordinal_plus1 遵守 Change 记录一节里的存在性与 所属 Task 不变式。这个四字节的发布槽位绝不存放全局 Remote Change 索引。
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 tombstone原生 v0 的 Patchset 写入方只会写出四种非遗留的 author mode。那三个遗留 编码存在的唯一目的,是在转换过程中原样保留已被接纳的源行;无法识别的 author 文本会 fail closed。原生 v0 的 Patchset 写入方只会写出 published 或 superseded 发布状态。遗留源里的 Patchset 状态 selected_for_landing 是非权威投影,会归一化为 published;它绝不会被写成 01,不会被用来推断选择结果,也不允许覆盖 RemoteChangeRecord.selected_patchset_index_plus1。如果一个有效的源 Change 选中指针与陈旧的 Patchset 投影不一致,以 Change 指针为准,转换不会仅仅因为 这种投影不一致而失败。但只要需要源端的选择结果,缺失、无效或有歧义的源 Change 指针依然会导致失败。只有当源 Change 指针明确这么指、并且所有权和 存活规则也全部通过时,选中指针才可以引用 published 或 superseded 的 遗留行。
当 evaluation_pending 置位时,即便存在更早的 Policy Decision,对外暴露的 Patchset evaluation_state 也是 pending。当它清零时,必须有一条最新的、 存活的非 pending Policy Decision,由它提供确切的 pass、soft_fail、 hard_fail 或 waived 值。新建 Patchset,以及任何会让缓存策略失效的 review、attestation、waiver 或策略输入变更,都会把这一位置位,作为状态最后 提交的标记;一次完成的非 pending Policy 评估会先追加其决定,再清除该位。
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