Binary DB v0:服務端與策略記錄
展開 Patchset、attestation、Actor、評審、策略、豁免、Plan、Repository 登錄檔與 Worker Job 權威。
適用對象: 服務端、runner、策略與恢復實作者
本章講的是以儲存庫為作用域的遠端工作流程權威,以及獨立的、以安裝為作用域的 Repository 登錄檔。數值索引只在各自宣告的根裡才有意義;Worker Job 的身份和引用都留在路由到的那個 Repository 權威內部。
服務端 Patchset 記錄#
TASK_PATCHSET_INDEX_RECORD_SIZE = 8
TaskPatchsetIndexRecord — task_patchset_index.bin:
u32 latest_patchset_index_plus1
u16 patchset_count
u16 reserved0
CHANGE_PATCHSET_INDEX_RECORD_SIZE = 8
ChangePatchsetIndexRecord — change_patchset_index.bin:
u32 latest_patchset_index_plus1
u16 patchset_count
u8 next_patch_ordinal
u8 reserved0SERVER_PATCHSET_RECORD_SIZE = 65
ServerPatchsetRecord — patchset.bin:
u8 patchset_meta
u8 patch_ordinal
u8 change_ordinal
u8 reserved0
u32 change_index
u32 previous_task_patchset_index_plus1
u32 previous_change_patchset_index_plus1
u32 base_snapshot_index
u32 revision_snapshot_index
u64 created_at_s
u64 ci_completed_at_s
u32 ci_run_seq
u16 ci_selected_suite_count
u16 ci_suite_result_count
u16 ci_blocking_failure_count
u8 ci_status_bits
u64 summary_offset
u16 summary_len
u32 ci_worker_job_index_plus1前 51 位元組是完整的定長 Patchset/緊湊 CI 區域:其中前 32 位元組是加寬後的 Patchset 身份字首,修正後的緊湊 CI 尾部恰好是 19 位元組。這兩個區域分別是 u32-time-v0 前身那 28 位元組身份字首和 15 位元組緊湊 CI 尾部的零擴充套件形式。追加的 summary 定位符恰好是 10 位元組。最後的 Worker Job 定位符恰好是 4 位元組,合起來構成完整的 65 位元組記錄。這些區域 都沒有隱式填充。summary_len 的取值範圍是 1..65535, summary_offset 指向 patchset_summary_payload.bin 中恰好這麼多個 非空 UTF-8 位元組。Patchset summary 是這個可評審 Patchset 由人撰寫的描述;它不是 Task intent、不是 Snapshot 訊息、不是 Tree 差異統計、不是 Review 文字,也不是 Policy 輸出。
patch_ordinal 在 (change_index, patch_ordinal) 上唯一。取值 0..63 在完整的所屬 Change 身份之下渲染為 P-01..P-64。 ChangePatchsetIndexRecord.next_patch_ordinal 是已分配序號的最大值加一, 超過 64 之後就拒絕分配;刪除或省略絕不會複用一個序號。 ChangePatchsetIndexRecord.latest_patchset_index_plus1 和 previous_change_patchset_index_plus1 遵循以 Change 為作用域的 Patchset 序號。 TaskPatchsetIndexRecord 只表示物理清單:它的 latest 指標和 每一個 previous_task_patchset_index_plus1 都遵循已提交的物理 Patchset 記錄順序,既不分配、也不暗示以 Task 為作用域的 Patchset 序號。 恢復過程從已提交的記錄順序重建 Task 清單,並從以 Change 為作用域的身份 重建每條 Change 鏈、計數和 next 序號。
Patchset 建立時先追加 summary 位元組並 fsync,之後才追加 定長的 Patchset 提交記錄。Patchset 的身份、屬主、序號、Snapshot 引用、建立時間以及 summary 定位符/位元組都是不可變的。緊湊 CI 欄位和 ci_worker_job_index_plus1 只能在宣告的 Worker Job 變更邊界之下, 透過整條記錄替換來改變。被打斷的追加可能只留下未被引用的尾部 summary 位元組,恢復時會忽略它們。已提交但缺失、為空、重疊或包含非法 UTF-8 的 summary 區間屬於損壞。
ci_completed_at_s 是非負的 u64 Unix 秒時間戳。 ci_run_seq = 0 表示還沒有 CI 執行啟動過。ci_run_seq 非零而 ci_completed_at_s = 0 表示一次進行中的執行,此時要求所有狀態 和計數字段都為零。完整的證據要求完成時間非零、 執行序列非零,且整體狀態不是 none。
ci_worker_job_index_plus1 = 0 表示該 Patchset 沒有選中任何由 Worker Job 支撐的 CI 執行;這包括遺留的緊湊 CI 證據和 內聯 CI 執行。非零值在與該 Patchset 同屬一個服務端 Repository 權威的 worker_job.bin 中解析為 index + 1。它必須指向一個 未被墓碑標記、型別恰好是 patchset.ci 的 Job,且該 Job 定長的 patchset_index_plus1 要能解析回這個確切的 Patchset。這條同根關係裡不涉及任何 Repository ID 或 Repository 索引。
該定位符選中的是這個 Patchset 已提交的最大 worker_job_index。之後 重跑會追加一個新 Job,並用那個新的本地索引替換整條 Patchset 記錄;更早的 Job 仍然是 Job 歷史,但在被取代之後就不能再覆寫緊湊 CI 證據。 在終態完成時,只有在重新確認那個完成的 Job 仍是定位符選中的目標之後, 才可以用 Job 結果替換緊湊 CI 欄位。
ServerPatchsetRecord.ci_status_bits:
bits 0..1 overall_status
bits 2..3 tests_status
bits 4..5 lint_status
bits 6..7 reserved = 0
Each two-bit status:
00 none
01 pass
10 fail
11 errorci_suite_result_count 不得超過 ci_selected_suite_count, ci_blocking_failure_count 也不得超過 ci_suite_result_count。各分項 狀態要求整體證據已完成。這些欄位只存放緊湊的 Patchset CI 證據。佇列狀態、嘗試次數、固定的結果和重試錯誤 類別都留在同一個 Repository 的定長 Worker Job 家族裡。lease 憑據、請求物化、詳細結果、日誌、製品和排程器設定都在 Binary DB v0 之外。
源端的 author_mode、publish_state 中 published/superseded 的那部分,以及 pending/非 pending 的 Policy 快取狀態,都按下文定義編碼進 patchset_meta。 源端的 selected-for-landing 投影會按 Remote Change 指標規則歸一化, 它不是 Patchset 狀態。源端的 diff_stats 不做儲存:它是透過精確比較 base 和 revision Snapshot 的 Tree 重新算出來的。除了"bin 到 bin 的轉換接納條件"一節裡那個 確切具名的遺留全零閘門之外,轉換器必須拒絕與該比較結果不一致的 給定值。非 pending 的 evaluation_state 就是最新存活的 Policy Decision 類別;Patchset 上的 pending 位用來區分新建或已失效的快取 和一個更早的非 pending 決定。任何 Patchset JSON payload 都不具備權威性。
Patchset 儲存由服務端權威負責。本地工作流程權威不定義任何 Patchset 檔案。
服務端 Attestation 記錄#
TASK_ATTEST_INDEX_RECORD_SIZE = 8
TaskAttestIndexRecord — task_attest_index.bin:
u32 latest_attest_index_plus1
u16 attest_count
u8 next_attest_ordinal
u8 reserved0
PATCHSET_ATTEST_INDEX_RECORD_SIZE = 8
PatchsetAttestIndexRecord — patchset_attest_index.bin:
u32 latest_attest_index_plus1
u16 attest_count
u16 reserved0SERVER_ATTEST_RECORD_SIZE = 24
ServerAttestationRecord — attest.bin:
u8 attest_meta
u8 attest_ordinal
u8 patch_ordinal
u8 change_ordinal
u32 patchset_index
u32 previous_task_attest_index_plus1
u32 previous_patchset_attest_index_plus1
u64 created_at_sAttestation 那四個有限的要求值存放在 attest_meta 的第 3 到第 6 位,絕不放進 payload。如果源端某條緊湊 Attestation 的時間和要求位全為零,就視為不存在,不寫出 v0 記錄。 存在的源端緊湊 Attestation 是以 Change 為作用域的可變源狀態; 遺留格式並不會把選中 Patchset 的歷史持久化到 attested_at_s。在持有一份一致的鎖定源快照期間,轉換 會透過所屬 Change 權威的目前 selected_patchset_number 解析該行, 並寫出一條 v0 Attestation,其 patchset_index 指向那個確切的 Patchset。序號到目標索引的查詢屬於 轉換器本地狀態,不會產生任何歷史選擇欄位、記錄、bin 或 payload。這個查詢不會讓目前 Change 的選擇變成臨時的:同一個源指標 會獨立地填充上文定義的既有 RemoteChangeRecord.selected_patchset_index_plus1 權威。目前 selected 指標缺失、無效、不屬於該屬主或不唯一,都會 fail closed。源端 Attestation 的任何 author mode 都必須等於所繫結 Patchset 的 author mode,因為 v0 不會把它複製一份。
Actor 與 Review 記錄#
ACTOR_RECORD_SIZE = 36
ActorRecord — actor.bin:
u8 actor_meta
u8 reserved0
u16 payload_len
u64 payload_offset
u64 actor_key_hash
u64 created_at_s
u64 last_seen_at_s對 bin 到 bin 的轉換而言,這條既有的定長記錄加上既有的 ActorPayload 就是完整的 Actor schema;不存在僅用於轉換的 Actor bin 或 通用 payload。源端每一個互不相同的非空評審者身份,都會逐位元組 存為 ActorPayload.user_name_bytes,同時 user_id_len = 0、 email_len = 0、memo 為空。轉換器不會去裁剪、摺疊大小寫,也不會把 Name <email> 這類展示字串解析成臆造的組成部分。除非有結構化的源欄位能 證明是別的類別,否則 Actor 類別就是 unknown。 透過 requested_groups 提供的非空身份屬於結構化的團隊 證據,使用 team 類別。類別相同且身份位元組相同的會複用同一個 Actor;位元組不同則仍是不同的 Actor。
這份必填 payload 是身份權威和衝突證據,不是 可選的 Review 註解。它的長度必須放得進既有的 u8 user_name_len 和 u16 payload_len;溢位或非法 UTF-8 會 fail closed。 actor_key_hash 是對確切的 user_name_bytes 計算的 FNV-1a-64:
actor_key_hash = fnv1a64(user_name_bytes)
offset_basis = 0xcbf29ce484222325
prime = 0x00000100000001b3ActorLookupIndexRecord 可能傳回雜湊衝突的候選。查詢 只有在 actor_kind 和 ActorPayload 位元組都精確比對透過之後才接受某個候選; 僅憑雜湊絕不會合並身份。created_at_s 是引用該 Actor 的源端 ReviewRecord.created_at_s 的最小值, last_seen_at_s 是最大值。當被接納的遺留源格式沒有 Review 時間時,這兩個欄位都為零,表示歷史時間未知。 提供的有效時間會在推導中保留,提供的無效時間會 fail closed;絕不會拿轉換時間來頂替。
TASK_REVIEW_INDEX_RECORD_SIZE = 8
TaskReviewIndexRecord — task_review_index.bin:
u32 latest_review_index_plus1
u16 review_count
u16 reserved0
PATCHSET_REVIEW_INDEX_RECORD_SIZE = 8
PatchsetReviewIndexRecord — patchset_review_index.bin:
u32 latest_review_index_plus1
u16 review_count
u8 next_review_ordinal
u8 reserved0SERVER_REVIEW_RECORD_SIZE = 40
ServerReviewRecord — review.bin:
u8 review_meta
u8 review_ordinal
u8 patch_ordinal
u8 change_ordinal
u32 actor_index_plus1
u32 patchset_index
u32 previous_task_review_index_plus1
u32 previous_patchset_review_index_plus1
u64 payload_offset
u16 payload_len
u16 reserved0
u64 created_at_sReview 的各種動作變體,都由一個基礎動作加上 review_meta 裡的固定修飾位 組成。確切的源端對映如下:
request -> request
comment -> comment
task_comment -> comment + task_lane
code_review_summary -> comment + code_review_summary
approve -> approve
task_approve -> approve + task_lane
request_changes -> request_changes
task_request_changes -> request_changes + task_lane
defer -> comment + defer
task_defer -> comment + task_lane + defer
dismiss -> dismiss其他任何寫法,或者非法的基礎動作/修飾位組合,都會 fail closed。 獨立的 blocking 位在每一種對映中都會被保留。普通 Review 的 actor_index_plus1 指向它的評審者 Actor。恰好帶一個 requested_groups 值的評審請求使用 request 動作,並指向對應的團隊 Actor; 活躍的 v0 schema 無法在一條 Review 裡編碼多個組。它源端的 reviewer 可以缺失,也可以包含與那唯一一個非空組完全相同的 UTF-8 位元組。相同的情況下它只是一份冗餘的遺留投影:轉換會建立或複用那一個團隊 Actor 並存下一個 actor_index_plus1;它不會建立第二個 Actor 或 Review。如果轉換器遇到不同的評審者、空身份、 零個組,或一個請求裡超過一個 requested group,它會 fail closed, 而不是憑空造出 Review 行或 payload。Review 的評論或請求備註 文字仍留在 ReviewPayload 裡。
review_ordinal 在 (patchset_index, review_ordinal) 上唯一。取值 0..63 在完整的所屬 Patchset 身份之下渲染為 R-01..R-64。被 接納的、以 Change 為作用域的遺留 Review ID,在挪到該 Review 確切的 Patchset 之下時會保留其確切的數字字尾;同一個 Patchset 內允許存在空檔, 但不允許序號重複。PatchsetReviewIndexRecord 負責 next 序號分配,其 latest/previous 連結遵循以 Patchset 為作用域的 Review 序號。TaskReviewIndexRecord 和 previous_task_review_index_plus1 只保留 Task 的物理清單。 恢復過程重建每條 Patchset 鏈、計數和 next 序號,同時不會 給源端的 Review 身份重新編號。
Policy 與 Waiver 記錄#
TASK_POLICY_INDEX_RECORD_SIZE = 8
TaskPolicyIndexRecord — task_policy_index.bin:
u32 latest_policy_index_plus1
u16 policy_count
u16 reserved0
PATCHSET_POLICY_INDEX_RECORD_SIZE = 8
PatchsetPolicyIndexRecord — patchset_policy_index.bin:
u32 latest_policy_index_plus1
u16 policy_count
u8 next_policy_ordinal
u8 reserved0POLICY_DECISION_RECORD_SIZE = 32
PolicyDecisionRecord — policy.bin:
u8 policy_meta
u8 policy_ordinal
u8 patch_ordinal
u8 change_ordinal
u32 patchset_index
u32 previous_task_policy_index_plus1
u32 previous_patchset_policy_index_plus1
u32 first_check_index_plus1
u16 check_count
u16 reserved0
u64 created_at_spolicy_ordinal 在 (patchset_index, policy_ordinal) 上唯一,而不是在 所屬 Task 內唯一。取值 0..63 在完整的所屬 Patchset 身份之下渲染為 K-01..K-64。PatchsetPolicyIndexRecord.next_policy_ordinal 是 已分配序號的最大值加一,超過 64 之後就拒絕分配;刪除 或墓碑標記絕不會複用一個序號。因此一個 Task 跨多個 Patchset 可以擁有超過 64 條 Policy Decision,只要不超過它 u16 policy_count 的 容量即可,而每個 Patchset 仍然以 64 為上限。
PatchsetPolicyIndexRecord.latest_policy_index_plus1 和 previous_patchset_policy_index_plus1 遵循以 Patchset 為作用域的 Policy 序號。 TaskPolicyIndexRecord 只保留完整的 Task 清單:它的 latest 指標和每一個 previous_task_policy_index_plus1 都遵循已提交的物理 Policy 記錄順序,既不分配、也不暗示以 Task 為作用域的 Policy 序號。 恢復過程從已提交的記錄順序重建 Task 清單,並從以 Patchset 為作用域的身份 重建每條 Patchset 鏈、計數和 next 序號。
POLICY_CHECK_RECORD_SIZE = 8
PolicyCheckRecord — policy_check.bin:
u8 check_kind
u8 check_status
u16 subject_ordinal
u32 detail_flags從 first_check_index_plus1 開始的那些行保留源端的檢查順序, 並且是完整的定長 Policy 檢查權威。subject_ordinal 和 detail_flags 的確切含義如下:
check_kind 0..7:
subject_ordinal = 0
detail_flags = 0
check_kind 8 ci_rollout_phase:
subject_ordinal = exact rollout phase in 0..65535
detail_flags = 0
check_kind 9 ci_patchset_suite:
subject_ordinal = one-based position of the exact suite ID in the
normalized UTF-8-byte-sorted exact Policy tuple catalog
detail_flags bit 0 = blocking suite
detail_flags bit 1 = informational suite
detail_flags bits 2..31 = 0ci_rollout_phase 是 CI 強制策略的數值 rollout 階段。它 不是 Task、Change、Patchset 或 Land 的生命週期狀態,它本身也不 指代某個 CI 套件。對於每一個被接納的遺留 phase-0 投影,源端的檢查 名稱恰好是 ci_rollout_phase;轉換會寫入 check_kind = 8, 保留源端的檢查狀態,寫入 subject_ordinal = 0,並寫入 detail_flags = 0。
遺留轉換隻接受下列確切的 (catalog, blocking set, informational set, phase message) 元組。 目錄比較使用歸一化後的 UTF-8 位元組序。位於 blocking 集合中的套件獲得 detail 位 0;位於 informational 集合中的套件獲得 detail 位 1。
catalog = [rust_core]
blocking = [rust_core]
informational = []
message = CI rollout phase 0 blocks `rust_core` and keeps none visible as non-blocking surfaces.
catalog = [full_repo_contract]
blocking = [full_repo_contract]
informational = []
message = CI rollout phase 0 blocks `full_repo_contract` and keeps none visible as non-blocking surfaces.
catalog = [full_repo_contract]
blocking = [full_repo_contract]
informational = []
message = CI rollout phase 0 blocks `full_repo_contract` and keeps none visible as non-blocking surfaces. Future promotions are modeled as phase1: `full_repo`.
catalog = [package_smoke, preflight, recent_regression, stable_smoke]
blocking = [package_smoke, preflight, stable_smoke]
informational = [recent_regression]
message = CI rollout phase 0 blocks `package_smoke`, `preflight`, `stable_smoke` and keeps `recent_regression` visible as non-blocking surfaces.
catalog = [package_smoke, preflight, recent_regression, stable_smoke, task_batch]
blocking = [package_smoke, preflight, stable_smoke]
informational = [recent_regression, task_batch]
message = CI rollout phase 0 blocks `preflight`, `stable_smoke`, `package_smoke` and keeps `recent_regression`, `task_batch` visible as non-blocking surfaces. Future promotions are modeled as phase1: `recent_regression`, `task_batch`, phase2: `full_repo`.
catalog = [package_smoke, preflight, recent_regression, stable_smoke, task_batch, tg1_required]
blocking = [package_smoke, preflight, stable_smoke, tg1_required]
informational = [recent_regression, task_batch]
message = CI rollout phase 0 blocks `preflight`, `stable_smoke`, `package_smoke`, `tg1_required` and keeps `recent_regression`, `task_batch` visible as non-blocking surfaces. Future promotions are modeled as phase1: `recent_regression`, `task_batch`, phase2: `full_repo`.
catalog = [package_smoke, preflight, recent_regression, stable_smoke, task_batch, tg1_required]
blocking = [package_smoke, preflight, stable_smoke]
informational = [recent_regression, task_batch, tg1_required]
message = CI rollout phase 0 blocks `preflight`, `stable_smoke`, `package_smoke` and keeps `recent_regression`, `task_batch`, `tg1_required` visible as non-blocking surfaces. Future promotions are modeled as phase1: `recent_regression`, `task_batch`, phase2: `full_repo`.
catalog = [package_smoke, preflight, recent_regression, stable_smoke, task_batch, tg1_required]
blocking = [package_smoke, preflight, stable_smoke]
informational = [recent_regression, task_batch, tg1_required]
message = CI rollout phase 0 blocks `preflight`, `stable_smoke`, `package_smoke` and keeps `tg1_required`, `recent_regression`, `task_batch` visible as non-blocking surfaces. Future promotions are modeled as phase1: `recent_regression`, `task_batch`, phase2: `full_repo`.
catalog = [package_smoke, preflight, recent_regression, stable_smoke, tg1_required]
blocking = [package_smoke, preflight, stable_smoke]
informational = [recent_regression, tg1_required]
message = CI rollout phase 0 blocks `package_smoke`, `preflight`, `stable_smoke` and keeps `recent_regression`, `tg1_required` visible as non-blocking surfaces. Future promotions are modeled as phase1: `recent_regression`, `task_batch`, phase2: `full_repo`.
catalog = [package_smoke, preflight, recent_regression, stable_smoke, tg1_required]
blocking = [package_smoke, preflight, stable_smoke, tg1_required]
informational = [recent_regression]
message = CI rollout phase 0 blocks `package_smoke`, `preflight`, `stable_smoke`, `tg1_required` and keeps `recent_regression` visible as non-blocking surfaces. Future promotions are modeled as phase1: `recent_regression`, `task_batch`, phase2: `full_repo`.階段檢查、確切的套件名檢查、目錄、blocking/informational 劃分以及訊息,必須與其中某一個元組一致。標籤屬於推匯出來的 展示內容,不做持久化。不同的或有歧義的表示會 fail closed;轉換器絕不會從自由文字裡解析出階段編號或套件分配。 原生 v0 寫入方只有在顯式的 Policy 設定直接提供了這些定長欄位時,才可以使用 另一個數值階段。
對 check_kind = 9,兩個套件 detail 位中恰好置位一個。在 同一條 Policy 內,套件序號非零、唯一、完整,且不超過 該 Policy 確切元組目錄的長度。它們並不受所屬 Patchset 的 ci_selected_suite_count 約束:Patchset 那個欄位是某一次 CI 執行的緊湊 證據,而不可變的 Policy 行保留的是歷史評估結果,這些結果可能早於 那份證據,也可能使用了另一種被接納的 blocking/informational 投影。轉換會把源端的 ci_patchset_suite_<suite-id> 名稱對照確切的 Policy 元組目錄做解析; 套件身份缺失、重複、不完整或有歧義都會 fail closed。 Policy 檢查的 label 和 message 是展示投影,不做 儲存。未知的檢查名稱/狀態會 fail closed,而不是變成文字 payload。源端的 input_fingerprint 是快取後設資料,不是 Policy 權威; v0 會從定長的 Patchset、Attestation、Review、Waiver、CI 和 Policy 輸入重新計算它,並不持久化源端的快取鍵。
TASK_WAIVER_INDEX_RECORD_SIZE = 8
TaskWaiverIndexRecord — task_waiver_index.bin:
u32 latest_waiver_index_plus1
u16 waiver_count
u8 next_waiver_ordinal
u8 reserved0
PATCHSET_WAIVER_INDEX_RECORD_SIZE = 8
PatchsetWaiverIndexRecord — patchset_waiver_index.bin:
u32 latest_waiver_index_plus1
u16 waiver_count
u16 reserved0WAIVER_RECORD_SIZE = 44
WaiverRecord — waiver.bin:
u8 waiver_meta
u8 waiver_ordinal
u8 patch_ordinal
u8 change_ordinal
u32 patchset_index
u32 previous_task_waiver_index_plus1
u32 previous_patchset_waiver_index_plus1
u64 payload_offset
u16 payload_len
u16 rule_code
u64 created_at_s
u64 expires_at_sPlan 記錄#
PLAN_RECORD_SIZE = 48
PlanRecord — plan.bin:
u8 plan_meta
u8 reserved0
u16 payload_len
u64 payload_offset
u32 latest_revision_index_plus1
u32 published_plan_index_plus1
u32 published_latest_revision_index_plus1
u64 created_at_s
u64 updated_at_s
u64 published_at_sPLAN_REVISION_RECORD_SIZE = 56
PlanRevisionRecord — plan_revision.bin:
u8 revision_meta
u8 reserved0
u16 payload_len
u16 revision_number
u16 item_count
u64 payload_offset
u32 plan_index
u32 previous_revision_index_plus1
u32 item_start_index
u32 published_revision_index_plus1
u32 root_tree_pack_index_plus1
u32 root_entry_ordinal
u64 created_at_s
u64 published_at_sPLAN_ITEM_RECORD_SIZE = 16
PlanItemRecord — plan_item.bin:
u8 item_meta
u8 reserved0
u16 payload_len
u64 payload_offset
u32 line_numberPlan 的 revision 歷史是一條線性鏈:
PlanRecord.latest_revision_index_plus1
-> PlanRevisionRecord.previous_revision_index_plus1
-> ...
-> 0Task 到 Plan 的繫結使用 Task 記錄裡數值形式的 revision 和 item 索引。 要確定是否真的可開成 Task,仍然需要與 PlanItemPayload.plan_item_ref_bytes 做比較。
服務端全域性 Repository 登錄檔權威#
服務端全域性的 Repository 登錄檔是一個以安裝為作用域的 Binary DB 根。它絕不會巢狀在某個儲存庫權威內部,也絕不會被複制 進本地儲存庫。明確劃歸這個根的每一個檔案,都使用 全域性的四位元組 layout_id = 1 頭部。必需但為空的家族就是一個 只有頭部的檔案。這個根裡的物理索引和另一個權威 根裡數值相同的索引之間沒有任何關係。
下文每一個 repository_index 都是直接指向這個根的 repository.bin 的稠密索引,也是該 Repository 唯一的主鍵。索引零是 合法的。Repository 記錄只追加:已分配的索引絕不會被重新編號、移除、 複用或轉移給另一個 Repository。*_index_plus1 使用全域性的"預設"編碼。這個根絕不持久化任何指向儲存庫工作流程、Worker Job 或共享內容 權威的數值索引。
前四個 Repository 索引是固定的:
0 ait-core
1 ait-server
2 ait-python
3 ait-node之後每一個 Repository 都從 4 開始,按下一個記錄序號追加。 所有服務端路由、設定和執行期關係,都透過 repository_index 標識一個 Repository,絕不透過 Repository 名稱。
活躍的服務端全域性定長家族清單恰好只有 repository.bin。 它活躍的帶型別 payload 清單恰好只有 repository_payload.bin, 它唯一活躍的索引是 repository_namespace.idx。 operational_public_sequence.bin、任何 Worker Job 定長檔案,以及任何 Worker Job 索引,在這個全域性根裡都是禁止的。Worker Job 檔案必須按下文宣告的方式, 存在於每一個數值形式的服務端 Repository 權威中。任何 其他的執行期 .bin、payload 或 .idx 檔案都會導致啟用失敗。
執行期時間戳是非負的 u64 Unix 秒。必填的 時間戳非零。可選的時間戳在預設時為零,否則 非零。被接納的 RFC 3339 時間戳會 歸一化為 UTC;對非負值而言,小數秒會在整秒值做範圍檢查並 儲存之前被有意丟棄。早於 Unix 紀元的值、大於 u64::MAX 的 整秒值,或無法解析的文字,都會 fail closed。Repository 和 Job 的 updated_at_s 不早於各自的 created_at_s。當某個 Job 被加鎖時, created_at_s <= locked_at_s <= updated_at_s。
Repository 登錄檔記錄#
登錄檔是以安裝為作用域的權威,負責 Repository 身份和 路由後設資料。它獨立於每一個以儲存庫為作用域的工作流程和 內容根。
OPERATIONAL_REPOSITORY_RECORD_SIZE = 33
OperationalRepositoryRecord — repository.bin:
u8 repository_meta
u8 lifecycle_kind
u8 namespace_ascii[2]
u8 policy_flags
u32 payload_len
u64 payload_offset
u64 created_at_s
u64 updated_at_sRepository 的主鍵是該記錄的物理 repository_index;它 不會在記錄或 payload 內部再複製一份。Repository 名稱是非空、 不可變的 UTF-8 展示後設資料,可以無限制地重複。名稱絕不會被 當作身份或路由權威。非空的 namespace_ascii 值 在 active 和 retiring 記錄之間唯一;為空是合法的,且沒有 名稱空間索引行。歷史上的 purged 身份可能與後來某個存活的 Repository 共用一個名稱空間,因此名稱空間查詢可能傳回多個候選,必須 校驗生命週期加上那確切的兩個定長位元組。repo_name 和 created_at_s 在建立之後不可變。策略、名稱空間、生命週期 和 updated_at_s 只能在登錄檔鎖之下透過整條記錄替換來變更。
已啟用的根至少有四條 Repository 記錄。第零到第 三條記錄的 payload 名稱分別恰好是 ait-core、ait-server、ait-python 和 ait-node,且絕不會被墓碑標記;退役改用保留的 lifecycle_kind = purged 記錄來表示。後來的記錄可以重複其中任何一個 名稱,但不會因此獲得那條保留記錄的身份。
邏輯上的 Repository 預設 Line 始終是確切的 UTF-8 main。它是 schema 常量,沒有對應的定長或 payload 欄位,會在暴露預設 Line 值的 API 邊界上合成出來。原生建立流程無法選擇 別的預設 Line。
Repository 權威目錄路由#
設定好的服務端 Repository 權威父目錄,用規範的無符號 十進位制 repository_index 作為每個 Repository 的目錄名:
<server-repository-authority-parent>/
0/ # ait-core
1/ # ait-server
2/ # ait-python
3/ # ait-node
4/
...零恰好寫作 0;其他每一個目錄名都不帶前導零、 符號、空白、字尾、字首或其他數字寫法。Repository 名稱絕不出現在權威目錄名中。該目錄是那個 Repository 的 工作流程、內容、Plan 和 Worker Job 權威家族的路由容器。目錄 本身不增加任何 .bin 記錄;Worker Job 子佈局在下文宣告。
活躍的父目錄裡,為每一條未被墓碑標記的 Repository 記錄恰好包含一個真實的、 非符號連結的目錄,且沒有任何文字別名目錄。解析一個目錄時,會把它的目錄名 按 u32 解析,核實對應的 repository.bin 記錄存在且未被墓碑標記,絕不按 Repository 名稱掃描。壓實過程保留每一個 Repository 目錄名, 因為它保留了每一個 repository_index。
以 Repository 為作用域的 Worker Job 記錄#
每一個規範的數值形式服務端 Repository 權威,都恰好包含一個 worker_job.bin 執行期佇列權威。必需但為空的檔案就是隻有頭部的檔案。這個檔案是那一個 Repository 的 Remote Binary 輸入:它 不會被複制進本地 Repository,不是被排除在外的通用 job.bin,不是 Patchset 的緊湊 CI 證據,也不是佇列投影。活躍的 v0 不定義任何 Worker Job payload 檔案。
SERVER_WORKER_JOB_RECORD_SIZE = 52
ServerWorkerJobRecord — worker_job.bin:
u8 job_meta
u8 job_kind
u8 state_kind
u8 outcome_kind
u16 attempt_count
u16 max_attempts
u16 error_kind
u16 reserved0
u32 patchset_index_plus1
u32 snapshot_index_plus1
u64 available_at_s
u64 locked_at_s
u64 created_at_s
u64 updated_at_s所屬的 Repository 隱含在規範的數值權威 目錄裡。Repository ID 和 repository_index 都不會在 定長記錄裡複製一份。物理上直接的 worker_job_index 記錄序號,就是那個 Repository 內部 Worker Job 唯一的主鍵。記錄只追加: 已分配的索引絕不會被重新編號、移除、複用或轉移。 墓碑標記會保留它確切的槽位。
完整的安裝級身份是 (repository_index, worker_job_index)。單獨一個 worker_job_index 在它所路由到的 Repository 權威之外沒有任何 含義,且 v0 不儲存任何獨立的公開或全域性 Job ID。attempt_count <= max_attempts;兩者都必須放得進 u16, 且 max_attempts 非零。job_kind 是定長權威;API 的 job_type 字串是由它合成的,絕不會作為 Job 位元組持久化。 available_at_s、created_at_s 和 updated_at_s 是必填的。只有 running 才有非零的 locked_at_s;其他每種狀態都是 locked_at_s = 0。
那兩個定長的領域引用欄位有下面這套確切的、按 Job kind 區分的解釋。 +1 保留零表示預設。每一個非零引用都在 與該 Job 相同的數值 Repository 權威內部解析:
job_kind | API job_type | patchset_index_plus1 | snapshot_index_plus1 |
|---|---|---|---|
| 2 | content.gc | 零 | 零 |
| 3 | content.optimize | 零 | 零 |
| 4 | content.pack | 零 | 零 |
| 5 | land.process | 所屬 Patchset | 零 |
| 6 | main-seed.refresh | 所屬 Patchset | 先前 Snapshot 或零 |
| 7 | patchset.ci | 所屬 Patchset | 零 |
| 8 | patchset.ci.aggregate | 所屬 Patchset | 零 |
| 9 | policy.evaluate | 所屬 Patchset | 零 |
| 10 | reconcile.repo | 零 | 零 |
| 11 | repo.ci | 零 | 選中的 Snapshot |
job_kind = 1 在活躍的 v0 中未分配。agent.turn.submit 需要一份 不透明的 turn 請求,它無法由既有的 Repository 領域權威表示, 因此在有帶型別的 agent-turn schema 之前,它不是持久化的 Worker Job。其他任何 job_kind、本表未 分配卻非零的欄位、家族錯誤的目標、跨 Repository 的目標,或 被墓碑標記的目標,都會 fail closed。 land.process 從解析出的 Patchset 推導它的 Change 和 revision Snapshot。Job 在任何 Land 存在之前就已提交;執行時會針對邏輯上的 main、以固定的服務端預設 direct 模式建立 Land。 Patchset 相關的 Change 和 Snapshot 資料在其餘情況下都從解析出的 Patchset 閉包推導。main-seed.refresh 使用邏輯上的 main,且只凍結 一個獨立要求的先前 Snapshot。原生 repo.ci 會在提交 Job 之前凍結它選中的 Snapshot,同樣在邏輯上的 main 上操作;這兩種 kind 都不會持久化 Line 索引,也不會把 Snapshot 身份推遲給一個可變的 Repository head。
不存在變長的 Worker Job 請求或輸入位元組。job_kind 和那兩個 定長引用就是完整的持久化執行選擇器。只有當每一個影響執行的選擇都已經提交到那些欄位、或提交到被引用的既有領域權威之後, 寫入方才可以提交一個 Job。觸發 標籤、傳輸標籤、排程器資源鍵、優先順序、重試延遲、 runner 上下文和物化出來的執行期 payload,都是重建出來的執行期 資料,不能改變那份持久化的選擇。內容維護和 Repository 對賬這兩種 kind 會呼叫它們那一個由服務端擁有的 kind 級 操作,不帶任何按 Job 的覆蓋引數。Patchset CI 和聚合從 選中的 Patchset 及其經過校驗的 Policy/CI 權威推匯出套件 閉包。Repository CI 使用服務端擁有的 Repository CI 契約,在選中的 Snapshot 和邏輯上的 main 上操作。如果某個被請求的操作 無法在這些規則之下被精確重建,入隊會在 分配 worker_job_index 之前失敗。
執行期 Repository payload 檔案#
服務端全域性根和每一個服務端 Repository 權威都沒有共享的 字串池,也沒有 operational_payload.bin。Repository 登錄檔的定位符 指向全域性的 repository_payload.bin。Worker Job 沒有 payload 定位符,也沒有 payload 檔案。
OperationalRepositoryPayload — repository_payload.bin:
u16 repo_name_len
u8 repo_name_bytes[repo_name_len]Repository 的 payload_len 非零,payload_offset 位於 BIN_HEADER_SIZE 或其之後;它恰好是 2 + repo_name_len,沒有填充也沒有 尾部欄位。Repository 名稱是精確合法的 UTF-8。完整的 Repository payload 最多 65,537 位元組。
可重建的登錄檔與 Worker Job 索引#
本小節裡的所有索引都是可選的可重建加速器。一個檔案 使用的權威根和目標家族,恰好由它的檔名隱含決定。 repository_namespace.idx 屬於服務端全域性登錄檔。那兩個 Worker Job 索引分別屬於每一個數值形式的服務端 Repository 權威。持久化的行按宣告順序對所有欄位排序。
OPERATIONAL_NAMESPACE_INDEX_RECORD_SIZE = 8
OperationalNamespaceIndexRecord — repository_namespace.idx:
u8 namespace_ascii[2]
u16 reserved0
u32 repository_index_plus1空名稱空間位元組 [0x00, 0x00] 沒有索引行。非空且位元組精確匹配的 名稱空間候選,可能包含多個歷史 purged 身份, 但最多隻有一個 active 或 retiring 身份。
SERVER_WORKER_READY_INDEX_RECORD_SIZE = 12
ServerWorkerReadyIndexRecord — worker_ready.idx:
u64 available_at_s
u32 worker_job_index_plus1
SERVER_WORKER_STATE_INDEX_RECORD_SIZE = 8
ServerWorkerStateIndexRecord — worker_state.idx:
u8 state_kind
u8 reserved0
u16 reserved1
u32 worker_job_index_plus1worker_ready.idx 只包含存活的 queued 行。佇列認領會在查詢之後校驗 本地 Job 索引、權威狀態、確切的 available_at_s、嘗試 預算,以及不存在存活的執行期 lease。worker_state.idx 包含每一個存活的 Job。在這兩個檔案裡,worker_job_index_plus1 只在 持有該索引的同一個 Repository 權威內部解析。
不會為被墓碑標記的記錄寫 .idx 行。缺失、陳舊、重複 或損壞的索引會被丟棄,並從該權威的 worker_job.bin 重建。索引絕不會修復或覆蓋定長記錄。
安裝範圍的排程器會從登錄檔列舉 active 和 retiring 的 Repository 索引,從各個本地 worker_ready.idx 讀取經過精確校驗的候選,並在記憶體裡按 (available_at_s, repository_index, worker_job_index) 歸併它們。那次記憶體歸併 是一次性的,絕不會作為全域性 Job 索引、序列或 身份權威持久化。
執行期後設資料與狀態編碼#
除非下文另有覆蓋,可變的執行期 *_meta 位元組使用:
bits 0..6 reserved = 0
bit 7 tombstoned被墓碑標記的記錄屬於保留下來的歷史,不會出現在索引中,也不能 成為存活關係的目標。源轉換不會寫入任何墓碑標記。
Repository 後設資料是:
repository_meta:
bits 0..6 reserved = 0
bit 7 tombstoned
lifecycle_kind:
1 active
2 retiring
3 purged
namespace_ascii[2]:
[0x00, 0x00] empty
[x, 0x00] one-byte namespace
[x, y ] two-byte namespace
policy_flags:
bit 0 require_attestation
bit 1 require_tests
bit 2 require_lint
bit 3 require_security_scan
bit 4 require_license_scan
bit 5 require_ai_provenance
bit 6 require_code_review_summary
bit 7 docs_only_relaxed_checks每個 x 或 y 都是一個非零的 ASCII 字母數字、_ 或 - 位元組。 [0x00, y]、內嵌的零位元組、控制/非 ASCII 位元組,以及長度超過 兩位元組的輸入,都是非法的。大小寫和位元組都是精確的;讀取方不做任何 裁剪、摺疊或 Unicode 歸一化。邏輯上的名稱空間長度 由尾部的零推導得出,絕不儲存。
第 0 到第 6 位是該 Repository 的預設要求。當第 7 位置位、 且有效的內容類別是 docs_only 時,測試、lint、安全掃描和 授權條款掃描全都不做要求;attestation、AI 溯源和程式碼評審 摘要保持它們的預設位。邏輯上的策略 ID 和版本固定 為 prototype 和 1,不做持久化。暴露 Repository 策略 JSON 的 API 會從 policy_flags 合成出規範的邏輯物件。
每一個未被墓碑標記的 Repository 都要求有非空的名稱、一個合法的 namespace_ascii[2] 值,以及一個 policy_flags 位元組。名稱重複是 合法的。 active -> retiring -> purged 和 retiring -> active 是僅有的生命週期 轉換。purged 的 Repository 沒有存活的 Worker Job,也不能成為 新 Job 的屬主。已 purge 的身份、Repository payload 位元組,以及保留下來的 Repository 本地 Job 歷史,在離線壓實之前都保持精確不變;它們 絕不會從另一個領域重建出來。
Worker Job 狀態是:
state_kind:
1 queued
2 running
3 succeeded
4 failed
outcome_kind:
0 none
1 completed
2 skipped
3 attached
4 superseded
5 failed
error_kind:
0 none
1 retryable_execution
2 terminal_execution
3 lease_expired每一個存活的 Job 都存放在某個 active 或 retiring Repository 的數值權威 目錄之下。queued 和 running 要求 outcome_kind = none;succeeded 要求 completed、skipped、attached 或 superseded;failed 要求 outcome_kind = failed。新入隊的 Job 是 error_kind = none。排隊重試或執行中重試可以保留 retryable_execution 或 lease_expired。succeeded 要求 error_kind = none;failed 要求 terminal_execution 或 lease_expired。
attached 和 superseded 只保留"這個 Job 為什麼沒有獨立完成 成功工作"這一資訊。它們不標識另一個 Job。去重時用到的任何 等價活躍 Job 或後來成功 Job 的身份,都屬於執行期/投影 資料,不是 Worker Job 權威。
lease 憑據不是 Binary DB 權威。認領時服務端會生成一個 密碼學隨機的 16 位元組 lease_token,把存活條目儲存在 記憶體中,並把它映象到一個用於崩潰恢復的臨時 Binary,該 Binary 位於所有 已啟用的全域性或 Repository 權威根之外。執行期條目以 (repository_index, worker_job_index, attempt_count) 為鍵,攜帶令牌、 最近一次心跳時間、過期時間和撕裂寫檢測。只有當定長的 Job 處於 running、其 attempt_count 精確匹配、 出示的令牌精確匹配,且執行期過期時間尚未到達時,它才有效。
那個臨時 Binary 是一次性的執行期副本,不是 layout-1 的檔案 家族。它被排除在權威清單、轉換輸出、Remote Binary 傳輸、離線壓實和領域恢復之外。它不能把 排隊中的 Job 變成執行中、不能修復 worker_job.bin,也不能提供 Job 身份。條目缺失、 損壞、陳舊、不匹配或過期,都會讓 lease 失效;在 Repository 佇列鎖之下,服務端會按其嘗試預算把該 Job 重新入隊或判定為 終態失敗,清除 locked_at_s,並記錄 lease_expired。只有在執行中的 Job 記錄和執行期映象都已持久化之後, 認領才會傳回令牌。心跳、完成和失敗在持有佇列鎖期間都要求 同一個令牌。Worker 身份屬於診斷用的執行期 資料,既不存進 Worker Job 權威,也不存進 lease 令牌。
這裡未分配的每一個數值狀態、結果或錯誤值都是保留的, 會 fail closed。完整的成功結果物件歸屬於它們所變更的領域記錄。 完整的失敗訊息歸屬於被排除在外的追蹤/日誌或診斷 投影邊界。兩者都不是 Worker Job 權威。
執行期變更與恢復邊界#
這些全域性和以 Repository 為作用域的執行期家族,不增加任何權威的 WAL、journal、事務 ID 或通用 generation 記錄。鎖檔案、 臨時替換檔案和 fsync 記賬都屬於執行期檔案系統 後設資料,不是 .bin 權威。如果一次變更需要多個領域 鎖,寫入方先獲取服務端全域性登錄檔鎖,然後按 repository_index 升序獲取各個 Repository 本地佇列鎖,並按相反順序 釋放:
<server-global-registry-root>/01-registry.lock
<server-repository-authority-parent>/<repository_index>/worker-queue.lock獲取鎖時會拒絕符號連結,也會拒絕歸屬於另一個已啟用根的鎖。 需要檢查或墓碑標記 Job 的 Repository 生命週期轉換,會按宣告的順序獲取 登錄檔鎖和它自己的 Repository 佇列鎖。Job 變更只獲取其所屬 Repository 的佇列鎖。那把本地鎖負責給 Worker Job 定長家族、非權威的執行期 lease 副本、兩個本地 Job 索引,以及每一次 Patchset ci_worker_job_index_plus1 或緊湊 CI 替換排序。讀取方在解析定長記錄期間持有 對應的共享鎖;寫入方則一直獨佔持有到領域提交點。
對於追加式建立,會先追加完整的定長明細記錄並 fsync。 定長記錄就是提交點。可重建索引最後寫。 已提交記錄的物理序號成為它永久的 worker_job_index;不存在獨立的分配器、序列頭、預留記錄、 payload 追加或可複用的未提交身份。
覆寫沿用既有的 v0 事務層契約:把 完整的前像保留在非權威的恢復儲存中,寫入一條完整的 定長記錄(保留位元組置零),fsync,然後丟棄前像。 除非那次替換抵達了它的領域提交點,否則恢復會還原完整的前像。同一條定長記錄內部的欄位絕不會被獨立 觀測到。
其他的領域提交規則是:
- Repository 建立會在下一個從未使用過的
repository_index上暫存並 fsync 真實的數值權威目錄,然後追加 Repository 記錄 並在repository.bin上提交。被打斷的、提交前的目錄屬於 不可達的暫存內容,絕不會按名稱被啟用。策略標誌位、名稱空間 位元組、生命週期和更新時間的變更,都透過替換完整的 Repository 記錄來提交。 - Job 建立從已提交記錄的完整計數推匯出下一個
worker_job_index, 並在所屬數值 Repository 權威內部的worker_job.bin上提交。 非patchset.ci的 Job 到此就完成了。對於patchset.ci,同一次持有佇列鎖的變更接著會替換完整的 所屬 Patchset 記錄,以選中那個新的worker_job_index;那次 Patchset 替換就是關係的提交點。在此之前被打斷,可能 留下一個合法但未被選中的 Job,它無法提供緊湊 CI 證據。 - 認領會遞增
attempt_count,建立新的執行期 lease 條目, 寫入state_kind = running和locked_at_s,並透過替換完整的 Job 記錄來提交權威。提交前的執行期條目會被忽略, 除非定長的狀態和嘗試計數與它精確匹配。已提交的 執行中 Job 若缺少其有效的執行期條目,即為 lease 丟失,會按嘗試規則重新入隊或 判定失敗。只有在兩次寫入都完成 fsync 之後才會傳回令牌。心跳會精確比對令牌和嘗試計數,持久化 更新後的執行期心跳/過期時間,並用同一個更新後的locked_at_s替換完整的定長 Job 記錄。失敗會讓執行期條目失效、 清除locked_at_s、記錄定長的錯誤類別,並選擇 重新入隊或寫入終態失敗結果。 - 一次成功的執行會先把結果提交到既有的所屬領域 權威,然後再把 Job 替換為
state_kind = succeeded、寫入其 定長結果和locked_at_s = 0,最後讓執行期 lease 條目失效。因此被選中的patchset.ci緊湊證據,是在那個 Job 仍處於選中狀態、 且 Job 成功標記尚未寫入之前,透過整條 Patchset 替換提交的。領域優先的完成過程若被打斷,會以冪等方式重試。attached和superseded只提交那個終態結果; 不會持久化第二個 Job 身份。陳舊的執行期條目無法讓 終態 Job 復活。佇列索引和排程檢視都是可修復的。 - Repository 轉為
purged時,會先在保留緊湊 CI 證據的前提下,透過整條記錄替換清除每一個 Patchset 的ci_worker_job_index_plus1,然後墓碑標記它擁有的每一個存活 Job,最後 提交完整的 Repository 生命週期替換。在最後那次替換之前被打斷, 會同時還原 Patchset 和 Job 的前像。
恢復過程首先校驗頭部、記錄的精確整除關係、保留位為零、 那四個固定的 Repository 槽位、Repository 的 UTF-8、名稱空間位元組、策略 標誌位、時間戳、結果、錯誤,以及所有定長引用不變式。它會 在開啟每一個以儲存庫為作用域的 Worker Job 權威之前,精確校驗數值 Repository 目錄閉包。隨後它會建置完整的源索引 圖,並拒絕任何指向不存在、已被墓碑標記或屬主錯誤 記錄的存活引用;拒絕互相沖突的存活非空名稱空間;也拒絕任何非零的 Patchset Job 定位符——如果它無法精確校驗出一個同根、job_kind = 7、其 patchset_index_plus1 選中該 Patchset 的 Job。重複的 Repository 名稱, 以及不同 Repository 根中數值相同的本地 Worker Job 索引,絕不構成 恢復衝突。
只有在權威校驗透過之後,恢復才可以重建登錄檔名稱空間 索引和各個 Repository 的本地 Job 索引。可變的 Repository 後設資料、 Patchset 選擇和 Job 狀態,絕不會從後面的行或某個 索引推斷出來。隨後恢復會載入執行期 lease 副本;副本缺失就當作 空副本。每個條目都必須與某一個執行中的 Job 及其嘗試 計數精確匹配,且未過期;否則該條目會被丟棄,且該 Job 按 lease 丟失規則處理。 不完整的尾部定長記錄屬於損壞,除非事務層 能證明它是唯一一次被打斷的追加。中間位置的畸形位元組絕不會 被截斷修復。
執行期容量與壓實#
每一個定長家族和可重建索引,其存活目標索引都以 u32::MAX - 1 為上限,因為非零的 *_index_plus1 必須保持可表示。 這個定長家族上限對每個 Repository 裡的 worker_job.bin 獨立生效; 不存在任何持久化的全域性 Job 家族,會額外施加一個 安裝範圍的 Job 數量上限。由於 Worker Job 的墓碑標記會保留其 主鍵槽位,它的容量檢查用的是已提交記錄總數,而不是存活 Job 數。直接的 u32 源值和計數在寫入前都會預檢。Repository 的 payload 偏移和檔案大小必須放得進 u64;每一處 offset + length 計算都使用帶檢查的算術。
離線壓實會寫出一個新的、非啟用的登錄檔根和 Repository generation,保留每一個確切的 repository_index 和 worker_job_index、Repository 名稱、名稱空間位元組、策略標誌位、狀態、 kind、定長引用、結果、錯誤和時間。它絕不會重排、 移除或重新編號 repository.bin 或 worker_job.bin 的記錄; Repository 和 Worker Job 的墓碑標記都保留其槽位,之後的任何身份 都不得複用它們。其他物理家族只有在改寫完它們完整的引用和索引閉包之後,才可以被稠密重編號。壓實會重建 那兩個本地 Job 索引,同時不改變 Job 記錄順序和 Patchset 定位符。 它不會讀取、複製或建立那個臨時的執行期 lease 副本, 並且會在原子啟用之前校驗完整的目標。
改變定長寬度、狀態分配、payload 語法、檔案家族、 主鍵規則、轉換源邊界或容量,都需要一次新的 佈局轉換,以及相容的讀寫方。layout_id 沒有變化 並不構成做出這些改變的許可。