Repository navigation
In Container Version Lineage
Status: the appendix is a working, tested feature of the container: append-only records, a SHA-256 parent chain, listing, and truncating rollback. It is a record-keeping mechanism. The inference engine does not read or apply appendix records (a model runs from its base tensors only), and the chain is not a signature: it detects accidental or partial edits to the appendix, not a determined attacker.
Binary layout of records is in Format Specification section 8.
Records are appended after the base tensors; the base weights are never rewritten. Each record carries a name, a target (for example the tensor an adapter applies to), a generation number, a timestamp, four metrics (loss, accuracy, pass_rate, custom), a payload, and the SHA-256 of the previous record's name ‖ target ‖ data. Adding a record costs a write of that record's size, not of the model: appendRecordToFile writes at end of file and patches the header only for the first record.
Entry types: lora_adapter, delta_patch, new_layer, code_eval, kv_cache_sink, topology_head. The training tools in python/hk/adaptive/ write lora_adapter/code_eval/topology_head records; see Training and Fine-Tuning.
hk appendix model.hk # list records and report whether the lineage chain verifies
hk rollback model.hk 2 # drop all records with generation > 2hk appendix prints the entry count, Cryptographic Lineage Valid: true|false, and a table with index, type, generation, name, target, accuracy and pass rate per record.
rollbackToFile scans records in order, keeps those with generation <= N, and truncates the file after the last kept record (with N = 0 it also clears appendix_offset and the HAS_APPENDIX flag). Consequences:
- It is fast (a truncate, no data copy) and does not touch the base weights.
- It is destructive: the removed records are gone and cannot be restored from the file. Copy the file first if you may want them back.
- It assumes records are stored in increasing generation order and stops at the first record above the target.
AppendixReader.verifyLineage() (also shown by hk appendix) checks, for each record after the first, that its parent_hash equals SHA-256 of the previous record's name ‖ target ‖ data (the payload-only hash used by older files is also accepted). It reports a bool; it does not say which record failed.
What this does and does not protect:
- Detects: edits to an earlier record's name, target or payload; deleted or reordered middle records.
- Does not cover: the base tensors, the header, or metadata. Changing weights does not invalidate the chain.
- Does not authenticate: anyone who can rewrite the file can recompute the hashes. There are no signatures.
- The per-record
data_crc32field is reserved and currently always0.
from hk.adaptive.appendix import AppendixManager, read_appendix
mgr = AppendixManager("model.hk")
mgr.append_lora_checkpoint(
name="math-lora-v1", target="blk.0.attn_q.weight", generation=1,
adapter_bytes=blob, metrics={"loss": 1.42, "accuracy": 0.485},
)
for r in mgr.get_records():
print(r.generation, r.entry_type.name, r.name, r.metrics.loss)
print("chain valid:", mgr.verify())
mgr.rollback(1) # same truncating semantics as `hk rollback`Module-level helpers: read_appendix, append_record, rollback_appendix, verify_lineage, compute_parent_hash. The adaptive training loops (HKTrainer, the self-training pipeline) call append_record with metrics at checkpoints.
- No tool applies appended adapters or deltas to produce a merged model for the engine; merging is up to your own code.
- Appending is not atomic. A crash mid-append can leave a truncated final record, which readers report as
TruncatedRecord. -
hk metadata setrefuses to move metadata to the end of a file that has an appendix (the appendix runs to EOF); it succeeds only when the new metadata fits in the existing padding.
HK Neural Tensor Framework | Licensed under Apache 2.0 | GitHub Repository