I am modeling a Google Docs-like inline commenting system in Alloy. Specifically, I'm modeling the UI interactions that the user can do. The constraints, in English, are that:
- users can have any number of comments
- users can have any number of comments composing at once
- comments can be either composing or editing, not both
- (eventually) users can expand one comment at a time to view it—text is truncated otherwise.
so far I have only modeled adding a new comment—or so I think! When I run the model below, I expect to see that Alloy cannot find any counterexamples, but it finds one where a comment is in both the composed
and composing
relations at a single time.
I think there may be something off in my mental model of how Alloy works in this case. I can't see how a comment would possibly be added to the composed
relation here: I think init
would set all the drafts to have empty relations there, and that the actions in Traces
would preclude a comment ever being added to composed
. BUT! I'm clearly wrong, since Alloy finds an example where composed
is non-empty. Does anyone know what's actually happening here?
module inlineComments
open util/ordering [Time] as TimeOrdering
sig Time {}
sig Draft {
composing: set Comment -> Time,
composed: set Comment -> Time,
-- expanded: lone Comment -> Time,
}
sig Comment {}
-- What can we do with these?
pred newComment (t, t': Time, c: Comment, d: Draft) {
-- comment is not already known to us
c not in d.composing.t
c not in d.composed.t
-- start composing the comment
d.composing.t' = d.composing.t + c
}
pred init (t: Time) {
all d: Draft, c: Comment | c not in d.composing.t
all d: Draft, c: Comment | c not in d.composed.t
}
fact Traces {
init[TimeOrdering/first]
all t: Time - TimeOrdering/last |
let t' = TimeOrdering/next[t] |
some d: Draft, c: Comment |
newComment [t, t', c, d]
}
-- Is the world how we expect it to be?
assert validState {
-- comments cannot be composing and composed at the same time
all t: Time, d: Draft | d.composing.t & d.composed.t = none
}
check validState for 3 but 1 Draft