mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-04 12:07:09 +00:00
docs(verifier): document extractor advancement and refresh invariants
Extractor previous/current advance only on PushSnapshot, never per thunk-call. refreshPredicateErrors depends on this for safe re-entry. Also flags that re-invoked predicates run outside their LTL gate, so they must be side-effect-free reads.
This commit is contained in:
1 parent
5932dc7e77
commit
569e0c818e
1 file changed
+10
@@ -216,6 +216,10 @@ func (v *Verifier) PushSnapshot(input SnapshotInput) error {
|
|||||||
if err := v.runtime.GlobalObject().Set("state", state); err != nil {
|
if err := v.runtime.GlobalObject().Set("state", state); err != nil {
|
||||||
return fmt.Errorf("set state: %w", err)
|
return fmt.Errorf("set state: %w", err)
|
||||||
}
|
}
|
||||||
|
// Extractor previous/current advance exactly once per PushSnapshot.
|
||||||
|
// Predicate thunks read these slots but never trigger advancement, so
|
||||||
|
// invoking a thunk multiple times between snapshots is value-stable.
|
||||||
|
// refreshPredicateErrors relies on this to safely re-call predicates.
|
||||||
for index, extractor := range v.extractors {
|
for index, extractor := range v.extractors {
|
||||||
previous := extractor.handle.Get("current")
|
previous := extractor.handle.Get("current")
|
||||||
_ = extractor.handle.Set("previous", previous)
|
_ = extractor.handle.Set("previous", previous)
|
||||||
@@ -317,6 +321,12 @@ func (v *Verifier) formulaThunk(index int) func() bool {
|
|||||||
// violated, so without this refresh the runner's per-step "predicate error"
|
// violated, so without this refresh the runner's per-step "predicate error"
|
||||||
// log freezes on whatever the predicate threw at step 1. The refreshed errors
|
// log freezes on whatever the predicate threw at step 1. The refreshed errors
|
||||||
// have no effect on verdicts.
|
// have no effect on verdicts.
|
||||||
|
//
|
||||||
|
// Invariant: predicates may be re-invoked here outside the LTL gate that
|
||||||
|
// would normally skip them (e.g. an `implies` consequent whose antecedent is
|
||||||
|
// false). They must therefore be side-effect-free reads of extractor state;
|
||||||
|
// any spec that asserts internal preconditions inside a predicate could
|
||||||
|
// surface a spurious error in the inspect UI without affecting verdicts.
|
||||||
func (v *Verifier) refreshPredicateErrors() {
|
func (v *Verifier) refreshPredicateErrors() {
|
||||||
for _, formula := range v.formulas {
|
for _, formula := range v.formulas {
|
||||||
result, err := formula.predicate(goja.Undefined())
|
result, err := formula.predicate(goja.Undefined())
|
||||||
|
|||||||
Reference in new issue
Block a user