FEAT: Always recompute ComponentIdentifier hashes#2050
Merged
rlundeen2 merged 5 commits intoJun 20, 2026
Conversation
Since identifiers now live only on AttackResult and are much smaller, remove the logic that stores and reloads the content hash and the value-truncation machinery. The content hash is always recomputed on validation, and full param values (system prompts, configs, etc.) are stored. eval_hash stays persisted for DB-level filtering but is recomputed on every reload rather than trusted from storage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix broken import of removed MAX_IDENTIFIER_VALUE_LENGTH in atomic_attack.py - Remove max_value_length param from ComponentIdentifier.to_dict shim - Make eval_hash stamping unconditional (always recompute, never trust stored) at scorer and all memory write sites Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Drop any supplied hash before validation so it can only be computed from content; document the hash/eval_hash asymmetry (eval_hash is set solely via with_eval_hash). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
_dump_identifier/_dump_identifiers existed only to inject the now-removed truncation context. With truncation gone they were trivial model_dump() wrappers, so inline them at the call sites. Load helpers keep their real work (version injection + eval_hash re-stamping). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
behnam-o
approved these changes
Jun 18, 2026
Contributor
There was a problem hiding this comment.
looks good. just 1 comment on computed_field
also, we don't need to worry about existing data in the DB, right? no need to over them and recompute all their hashes? (with a migration script) - I think that's an overkill even if alters anything ... [actually, maybe we can't even do that, becase some stuff might be truncated with ... and not parsable to a dict]
Replaces the nullable hash pseudo-field (settable-but-ignored, str | None) with a @computed_field backed by a PrivateAttr cache, per PR review. The hash is now a read-only computed field: assignment raises (frozen), the type is a non-optional str, and it is computed once in the after-validator (no per-access recompute, so no perf regression on __hash__/__eq__/dedup). Incoming hash values are still dropped before validation so extra=forbid round-trips storage. Removes the now-unreachable hash-is-None guards in short_hash and compute_eval_hash. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Since identifiers now live only on AttackResult and are much smaller, remove the logic that stores and reloads the content hash and the value-truncation machinery. The content hash is always recomputed on validation, and full param values (system prompts, configs, etc.) are stored. eval_hash stays persisted for DB-level filtering but is recomputed on every reload rather than trusted from storage.
This simplifies storage, and allows us to see full identities, making the identifiers truly serializable/deserializable from the database