Adding Mutation Strategies¶
GGUF strategies implement a small interface, but a useful strategy needs more than code that changes bytes. It needs a source-derived invariant, deterministic tests, linkage coverage, and a target experiment showing that the intended field changed.
Interface¶
The package uses math/rand/v2. Names are unique dot-separated identifiers such as metadata.alignment_poison.
Implementation sequence¶
- Write the invariant. Name the target field, the consumer, and the relationship being broken.
- Choose the category. Header 10%, metadata 35%, tensor info 35%, alignment 5%, data 5%, or consistency 10%. Model-loader strategies share the metadata budget.
- Implement with the supplied RNG. Do not use global randomness.
- Preserve intentional corruption. Implement
CountKeeperwhen declared counts must disagree with slice lengths, orPaddingSkipperwhen missing padding is the mutation. - Register it in the matching
*Strategies()factory. - Add a negative control proving an unrelated field or valid seed is not changed.
- Round-trip the bytes and assert the intended on-wire difference, not only the in-memory field.
Minimal shape:
type metadataBoundaryMutator struct{}
func (*metadataBoundaryMutator) Name() string {
return "metadata.boundary"
}
func (*metadataBoundaryMutator) Mutate(f *gguf.File, rng *rand.Rand) {
idx := randMetadataIdx(f, rng)
choices := []uint64{0, 1, math.MaxUint32, math.MaxUint64}
f.Metadata[idx].Value = choices[rng.IntN(len(choices))]
}
Registration:
func MetadataStrategies() []Strategy {
return []Strategy{
// existing strategies
&metadataBoundaryMutator{},
}
}
Tests that discriminate¶
A test should fail if the strategy becomes a no-op or mutates the wrong field.
func TestMetadataBoundaryChangesOnlyTarget(t *testing.T) {
f := createTestFile()
before := f.Clone()
rng := rand.New(rand.NewPCG(42, 42))
(&metadataBoundaryMutator{}).Mutate(f, rng)
if reflect.DeepEqual(f.Metadata, before.Metadata) {
t.Fatal("strategy did not change metadata")
}
if !reflect.DeepEqual(f.Tensors, before.Tensors) {
t.Fatal("strategy changed unrelated tensor descriptors")
}
}
Also assert serialization when the mutation is supposed to produce bytes. A marshal error may be an intentional test case, but logging it and passing proves nothing.
End-to-end validation¶
After package tests:
- build the matching custom-mutator archive;
- build a real target harness and run the mutator-linkage gate;
- bank the target commit, binary hash, environment, control, and mutated input;
- use
harness-smokeandpreflight; - run a matched byte-only control arm if making an effectiveness claim; and
- replay any result and inspect the source before naming a finding.
A strategy test proves the input generator. It does not prove the target is vulnerable or that the mutator improves yield.