@fairfox/polly 0.1.5 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/polly.js +75 -220
- package/dist/cli/polly.js.map +5 -4
- package/dist/cli/template-utils.js +81 -0
- package/dist/cli/template-utils.js.map +10 -0
- package/dist/vendor/verify/specs/Dockerfile +13 -0
- package/dist/vendor/verify/specs/README.md +37 -0
- package/dist/vendor/verify/specs/docker-compose.yml +9 -0
- package/dist/vendor/verify/specs/tla/MessageRouter.cfg +24 -0
- package/dist/vendor/verify/specs/tla/MessageRouter.tla +221 -0
- package/dist/vendor/verify/specs/tla/README.md +179 -0
- package/dist/vendor/verify/specs/verification.config.ts +61 -0
- package/dist/vendor/verify/src/cli.js +22 -19
- package/dist/vendor/verify/src/cli.js.map +5 -5
- package/dist/vendor/visualize/src/cli.js +379 -61
- package/dist/vendor/visualize/src/cli.js.map +11 -10
- package/package.json +2 -2
- package/templates/pwa/.gitignore.template +4 -0
- package/templates/pwa/README.md.template +144 -0
- package/templates/pwa/build.ts.template +56 -0
- package/templates/pwa/index.html.template +127 -0
- package/templates/pwa/package.json.template +19 -0
- package/templates/pwa/public/manifest.json.template +21 -0
- package/templates/pwa/server.ts.template +58 -0
- package/templates/pwa/src/main.ts.template +133 -0
- package/templates/pwa/src/service-worker.ts.template +161 -0
- package/templates/pwa/src/shared-worker.ts.template +135 -0
- package/templates/pwa/tsconfig.json.template +18 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
------------------------- MODULE MessageRouter -------------------------
|
|
2
|
+
(*
|
|
3
|
+
Formal specification of the web extension MessageRouter.
|
|
4
|
+
|
|
5
|
+
This spec models the core message routing behavior across extension contexts:
|
|
6
|
+
- Background service worker (central hub)
|
|
7
|
+
- Content scripts (one per tab)
|
|
8
|
+
- DevTools, Popup, Options (UI contexts)
|
|
9
|
+
|
|
10
|
+
Key properties verified:
|
|
11
|
+
1. No routing loops
|
|
12
|
+
2. Messages eventually deliver (if port connected)
|
|
13
|
+
3. All pending requests eventually resolve (success/timeout/disconnect)
|
|
14
|
+
4. Port cleanup is complete
|
|
15
|
+
*)
|
|
16
|
+
|
|
17
|
+
EXTENDS Integers, Sequences, FiniteSets, TLC
|
|
18
|
+
|
|
19
|
+
CONSTANTS
|
|
20
|
+
Contexts, \* Set of all contexts: {"background", "content", "popup", ...}
|
|
21
|
+
MaxMessages, \* Bound on number of messages (for model checking)
|
|
22
|
+
MaxTabId, \* Maximum tab ID
|
|
23
|
+
TimeoutLimit \* Message timeout threshold
|
|
24
|
+
|
|
25
|
+
VARIABLES
|
|
26
|
+
ports, \* Port state: [context -> "connected" | "disconnected"]
|
|
27
|
+
messages, \* Sequence of messages in flight
|
|
28
|
+
pendingRequests, \* Map: messageId -> {sender, target, timestamp}
|
|
29
|
+
delivered, \* Set of delivered message IDs
|
|
30
|
+
routingDepth, \* Current routing depth (for loop detection)
|
|
31
|
+
time \* Logical clock
|
|
32
|
+
|
|
33
|
+
vars == <<ports, messages, pendingRequests, delivered, routingDepth, time>>
|
|
34
|
+
|
|
35
|
+
-----------------------------------------------------------------------------
|
|
36
|
+
|
|
37
|
+
(* Type definitions *)
|
|
38
|
+
|
|
39
|
+
ContextType == {"background", "content", "popup", "devtools", "options", "offscreen"}
|
|
40
|
+
PortState == {"connected", "disconnected"}
|
|
41
|
+
MessageStatus == {"pending", "routing", "delivered", "failed", "timeout"}
|
|
42
|
+
|
|
43
|
+
Message == [
|
|
44
|
+
id: Nat,
|
|
45
|
+
source: ContextType,
|
|
46
|
+
targets: SUBSET ContextType, \* Set of target contexts (can be multiple)
|
|
47
|
+
tabId: Nat,
|
|
48
|
+
msgType: STRING, \* Message type for handler dispatch
|
|
49
|
+
status: MessageStatus,
|
|
50
|
+
timestamp: Nat
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
-----------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
(* Initial state *)
|
|
56
|
+
|
|
57
|
+
Init ==
|
|
58
|
+
/\ ports = [c \in Contexts |-> "disconnected"]
|
|
59
|
+
/\ messages = <<>>
|
|
60
|
+
/\ pendingRequests = [id \in {} |-> {}]
|
|
61
|
+
/\ delivered = {}
|
|
62
|
+
/\ routingDepth = 0
|
|
63
|
+
/\ time = 0
|
|
64
|
+
|
|
65
|
+
-----------------------------------------------------------------------------
|
|
66
|
+
|
|
67
|
+
(* Actions *)
|
|
68
|
+
|
|
69
|
+
(* A context connects a port *)
|
|
70
|
+
ConnectPort(context) ==
|
|
71
|
+
/\ ports[context] = "disconnected"
|
|
72
|
+
/\ ports' = [ports EXCEPT ![context] = "connected"]
|
|
73
|
+
/\ UNCHANGED <<messages, pendingRequests, delivered, routingDepth, time>>
|
|
74
|
+
|
|
75
|
+
(* A context disconnects *)
|
|
76
|
+
DisconnectPort(context) ==
|
|
77
|
+
/\ ports[context] = "connected"
|
|
78
|
+
/\ ports' = [ports EXCEPT ![context] = "disconnected"]
|
|
79
|
+
\* Clean up pending requests that target this context
|
|
80
|
+
/\ LET failedRequests == {id \in DOMAIN pendingRequests :
|
|
81
|
+
context \in pendingRequests[id].targets}
|
|
82
|
+
IN pendingRequests' = [id \in DOMAIN pendingRequests \ failedRequests |->
|
|
83
|
+
pendingRequests[id]]
|
|
84
|
+
/\ UNCHANGED <<messages, delivered, routingDepth, time>>
|
|
85
|
+
|
|
86
|
+
(* Send a message from source to one or more targets *)
|
|
87
|
+
SendMessage(source, targetSet, tabId, messageType) ==
|
|
88
|
+
/\ ports[source] = "connected"
|
|
89
|
+
/\ Len(messages) < MaxMessages
|
|
90
|
+
/\ routingDepth = 0 \* Only send at top level (no recursive sends)
|
|
91
|
+
/\ targetSet # {} \* Must have at least one target
|
|
92
|
+
/\ LET newId == Len(messages) + 1
|
|
93
|
+
newMsg == [
|
|
94
|
+
id |-> newId,
|
|
95
|
+
source |-> source,
|
|
96
|
+
targets |-> targetSet,
|
|
97
|
+
tabId |-> tabId,
|
|
98
|
+
msgType |-> messageType,
|
|
99
|
+
status |-> "pending",
|
|
100
|
+
timestamp |-> time
|
|
101
|
+
]
|
|
102
|
+
IN /\ messages' = Append(messages, newMsg)
|
|
103
|
+
/\ pendingRequests' = pendingRequests @@
|
|
104
|
+
(newId :> [sender |-> source,
|
|
105
|
+
targets |-> targetSet,
|
|
106
|
+
timestamp |-> time])
|
|
107
|
+
/\ time' = time + 1
|
|
108
|
+
/\ UNCHANGED <<ports, delivered, routingDepth>>
|
|
109
|
+
|
|
110
|
+
(* Route a message to one of its targets *)
|
|
111
|
+
RouteMessage(msgIndex) ==
|
|
112
|
+
/\ msgIndex \in 1..Len(messages)
|
|
113
|
+
/\ LET msg == messages[msgIndex]
|
|
114
|
+
IN /\ msg.status = "pending"
|
|
115
|
+
/\ routingDepth' = routingDepth + 1
|
|
116
|
+
/\ routingDepth < 5 \* Safety bound: detect loops
|
|
117
|
+
/\ \* Non-deterministically choose a target from the targets set
|
|
118
|
+
\E target \in msg.targets :
|
|
119
|
+
/\ IF target \in Contexts /\ ports[target] = "connected"
|
|
120
|
+
THEN \* Successful delivery to this target
|
|
121
|
+
/\ messages' = [messages EXCEPT ![msgIndex].status = "delivered"]
|
|
122
|
+
/\ delivered' = delivered \union {msg.id}
|
|
123
|
+
/\ pendingRequests' = [id \in DOMAIN pendingRequests \ {msg.id} |->
|
|
124
|
+
pendingRequests[id]]
|
|
125
|
+
/\ time' = time + 1
|
|
126
|
+
ELSE \* Port not connected or invalid target, message fails
|
|
127
|
+
/\ messages' = [messages EXCEPT ![msgIndex].status = "failed"]
|
|
128
|
+
/\ pendingRequests' = [id \in DOMAIN pendingRequests \ {msg.id} |->
|
|
129
|
+
pendingRequests[id]]
|
|
130
|
+
/\ time' = time + 1
|
|
131
|
+
/\ UNCHANGED delivered
|
|
132
|
+
/\ UNCHANGED ports
|
|
133
|
+
|
|
134
|
+
(* Complete routing (reset depth) *)
|
|
135
|
+
CompleteRouting ==
|
|
136
|
+
/\ routingDepth > 0
|
|
137
|
+
/\ routingDepth' = 0
|
|
138
|
+
/\ UNCHANGED <<ports, messages, pendingRequests, delivered, time>>
|
|
139
|
+
|
|
140
|
+
(* Handle message timeout *)
|
|
141
|
+
TimeoutMessage(msgIndex) ==
|
|
142
|
+
/\ msgIndex \in 1..Len(messages)
|
|
143
|
+
/\ LET msg == messages[msgIndex]
|
|
144
|
+
IN /\ msg.status = "pending"
|
|
145
|
+
/\ time - msg.timestamp > TimeoutLimit
|
|
146
|
+
/\ messages' = [messages EXCEPT ![msgIndex].status = "timeout"]
|
|
147
|
+
/\ pendingRequests' = [id \in DOMAIN pendingRequests \ {msg.id} |->
|
|
148
|
+
pendingRequests[id]]
|
|
149
|
+
/\ time' = time + 1
|
|
150
|
+
/\ UNCHANGED <<ports, delivered, routingDepth>>
|
|
151
|
+
|
|
152
|
+
-----------------------------------------------------------------------------
|
|
153
|
+
|
|
154
|
+
(* Next state relation *)
|
|
155
|
+
|
|
156
|
+
Next ==
|
|
157
|
+
\/ \E c \in Contexts : ConnectPort(c)
|
|
158
|
+
\/ \E c \in Contexts : DisconnectPort(c)
|
|
159
|
+
\/ \E src \in Contexts : \E targetSet \in (SUBSET Contexts \ {{}}) : \E tab \in 0..MaxTabId : \E msgType \in {"msg1", "msg2"} : SendMessage(src, targetSet, tab, msgType)
|
|
160
|
+
\/ \E i \in 1..Len(messages) : RouteMessage(i)
|
|
161
|
+
\/ CompleteRouting
|
|
162
|
+
\/ \E i \in 1..Len(messages) : TimeoutMessage(i)
|
|
163
|
+
|
|
164
|
+
Spec == Init /\ [][Next]_vars /\ WF_vars(Next)
|
|
165
|
+
|
|
166
|
+
-----------------------------------------------------------------------------
|
|
167
|
+
|
|
168
|
+
(* Invariants *)
|
|
169
|
+
|
|
170
|
+
(* CRITICAL: No infinite routing loops *)
|
|
171
|
+
NoRoutingLoops ==
|
|
172
|
+
routingDepth < 3
|
|
173
|
+
|
|
174
|
+
(* All delivered messages were actually pending *)
|
|
175
|
+
DeliveredWerePending ==
|
|
176
|
+
\A msgId \in delivered :
|
|
177
|
+
\E i \in 1..Len(messages) : messages[i].id = msgId
|
|
178
|
+
|
|
179
|
+
(* No orphaned pending requests - every pending request has a corresponding message *)
|
|
180
|
+
NoOrphanedRequests ==
|
|
181
|
+
\A reqId \in DOMAIN pendingRequests :
|
|
182
|
+
\E i \in 1..Len(messages) :
|
|
183
|
+
/\ messages[i].id = reqId
|
|
184
|
+
/\ messages[i].status \in {"pending", "routing"}
|
|
185
|
+
|
|
186
|
+
(* Messages to disconnected ports eventually fail *)
|
|
187
|
+
DisconnectedPortsFail ==
|
|
188
|
+
\A i \in 1..Len(messages) :
|
|
189
|
+
LET msg == messages[i]
|
|
190
|
+
IN (msg.status = "pending" /\ \A target \in msg.targets : ports[target] = "disconnected")
|
|
191
|
+
=> (time - msg.timestamp > TimeoutLimit => msg.status \in {"failed", "timeout"})
|
|
192
|
+
|
|
193
|
+
(* Type invariant *)
|
|
194
|
+
TypeOK ==
|
|
195
|
+
/\ ports \in [Contexts -> PortState]
|
|
196
|
+
/\ \A i \in 1..Len(messages) :
|
|
197
|
+
/\ messages[i].source \in Contexts
|
|
198
|
+
/\ messages[i].targets \subseteq Contexts
|
|
199
|
+
/\ messages[i].targets # {}
|
|
200
|
+
/\ messages[i].status \in MessageStatus
|
|
201
|
+
/\ routingDepth >= 0
|
|
202
|
+
/\ time >= 0
|
|
203
|
+
|
|
204
|
+
-----------------------------------------------------------------------------
|
|
205
|
+
|
|
206
|
+
(* Temporal properties *)
|
|
207
|
+
|
|
208
|
+
(* Eventually, all messages resolve (deliver, fail, or timeout) *)
|
|
209
|
+
EventualResolution ==
|
|
210
|
+
\A i \in 1..Len(messages) :
|
|
211
|
+
messages[i].status = "pending"
|
|
212
|
+
~> messages[i].status \in {"delivered", "failed", "timeout"}
|
|
213
|
+
|
|
214
|
+
(* If ports are connected and message is sent to them, message eventually delivers *)
|
|
215
|
+
ConnectedEventuallyDelivers ==
|
|
216
|
+
\A i \in 1..Len(messages) :
|
|
217
|
+
LET msg == messages[i]
|
|
218
|
+
IN (msg.status = "pending" /\ \A target \in msg.targets : ports[target] = "connected")
|
|
219
|
+
~> (msg.status = "delivered")
|
|
220
|
+
|
|
221
|
+
=============================================================================
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# TLA+ Formal Specification for MessageRouter
|
|
2
|
+
|
|
3
|
+
This directory contains formal specifications for the web extension's message routing system using TLA+ (Temporal Logic of Actions).
|
|
4
|
+
|
|
5
|
+
## What is This?
|
|
6
|
+
|
|
7
|
+
TLA+ is a formal specification language for concurrent and distributed systems. It allows us to:
|
|
8
|
+
- **Model** the message routing logic mathematically
|
|
9
|
+
- **Verify** properties like "no routing loops" or "messages eventually deliver"
|
|
10
|
+
- **Find edge cases** that are hard to catch with traditional testing
|
|
11
|
+
- **Document** the system behavior precisely
|
|
12
|
+
|
|
13
|
+
## What We're Verifying
|
|
14
|
+
|
|
15
|
+
### Core Properties
|
|
16
|
+
|
|
17
|
+
1. **NoRoutingLoops** - Messages never create infinite routing cycles
|
|
18
|
+
2. **EventualResolution** - Every message eventually resolves (delivers, fails, or times out)
|
|
19
|
+
3. **ConnectedEventuallyDelivers** - Messages to connected ports eventually deliver
|
|
20
|
+
4. **NoOrphanedRequests** - Pending requests always have corresponding messages
|
|
21
|
+
5. **TypeOK** - All data structures maintain correct types
|
|
22
|
+
|
|
23
|
+
### System Model
|
|
24
|
+
|
|
25
|
+
The spec models:
|
|
26
|
+
- **Contexts**: background, content, popup, devtools, options, offscreen
|
|
27
|
+
- **Port lifecycle**: disconnected ⇒ connected ⇒ disconnected
|
|
28
|
+
- **Message states**: pending → routing → delivered/failed/timeout
|
|
29
|
+
- **Routing depth tracking** (for loop detection)
|
|
30
|
+
- **Timeout handling**
|
|
31
|
+
- **Broadcast semantics**
|
|
32
|
+
|
|
33
|
+
## Running the Model Checker
|
|
34
|
+
|
|
35
|
+
### Prerequisites
|
|
36
|
+
|
|
37
|
+
Docker must be running. The TLA+ toolchain runs in a container.
|
|
38
|
+
|
|
39
|
+
### Quick Start
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# From project root
|
|
43
|
+
bun run tla:up # Start container
|
|
44
|
+
bun run tla:check # Run model checker
|
|
45
|
+
bun run tla:down # Stop container
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Manual Commands
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Start the TLA+ container
|
|
52
|
+
docker-compose -f specs/docker-compose.yml up -d
|
|
53
|
+
|
|
54
|
+
# Run the model checker
|
|
55
|
+
docker-compose -f specs/docker-compose.yml exec tla tlc MessageRouter.tla
|
|
56
|
+
|
|
57
|
+
# Interactive shell (for exploring)
|
|
58
|
+
docker-compose -f specs/docker-compose.yml exec tla sh
|
|
59
|
+
|
|
60
|
+
# Stop the container
|
|
61
|
+
docker-compose -f specs/docker-compose.yml down
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Understanding the Output
|
|
65
|
+
|
|
66
|
+
### Success
|
|
67
|
+
```
|
|
68
|
+
TLC2 Version X.X.X
|
|
69
|
+
...
|
|
70
|
+
Model checking completed. No error has been found.
|
|
71
|
+
Estimates of the probability that TLC did not check all reachable states
|
|
72
|
+
because two distinct states had the same fingerprint:
|
|
73
|
+
calculated (optimistic): val = X.X%
|
|
74
|
+
...
|
|
75
|
+
Finished in XXms at (YYYY-MM-DD HH:MM:SS)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Violation Found
|
|
79
|
+
TLC will print:
|
|
80
|
+
- **Which invariant was violated**
|
|
81
|
+
- **The execution trace** (sequence of states) leading to the violation
|
|
82
|
+
- Each state shows the values of all variables
|
|
83
|
+
|
|
84
|
+
Example:
|
|
85
|
+
```
|
|
86
|
+
Error: Invariant NoRoutingLoops is violated.
|
|
87
|
+
|
|
88
|
+
State 1: <Initial State>
|
|
89
|
+
/\ ports = ...
|
|
90
|
+
/\ routingDepth = 0
|
|
91
|
+
...
|
|
92
|
+
|
|
93
|
+
State 2: <ConnectPort("background")>
|
|
94
|
+
/\ ports = [background |-> "connected", ...]
|
|
95
|
+
...
|
|
96
|
+
|
|
97
|
+
State 3: <SendMessage("background", "content", 1)>
|
|
98
|
+
...
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Editing the Spec
|
|
102
|
+
|
|
103
|
+
### Files
|
|
104
|
+
|
|
105
|
+
- **MessageRouter.tla** - Main specification (edit this)
|
|
106
|
+
- **MessageRouter.cfg** - Model configuration (constants, invariants to check)
|
|
107
|
+
|
|
108
|
+
### Workflow
|
|
109
|
+
|
|
110
|
+
1. Edit `.tla` file locally (syntax highlighting via VSCode TLA+ extension)
|
|
111
|
+
2. Save changes (files are volume-mounted into container)
|
|
112
|
+
3. Run `bun run tla:check`
|
|
113
|
+
4. Iterate on violations
|
|
114
|
+
|
|
115
|
+
### Expanding the Model
|
|
116
|
+
|
|
117
|
+
Current model is intentionally simple (3 contexts, 4 messages max). To expand:
|
|
118
|
+
|
|
119
|
+
1. **Add more contexts**: Edit `MessageRouter.cfg`:
|
|
120
|
+
```
|
|
121
|
+
Contexts = {background, content, popup, devtools, options}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
2. **Increase message limit**: (Warning: state space grows exponentially!)
|
|
125
|
+
```
|
|
126
|
+
MaxMessages = 6
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
3. **Add new properties**: Define in `.tla`, add to `.cfg` under `INVARIANTS` or `PROPERTIES`
|
|
130
|
+
|
|
131
|
+
4. **Model request/response pairing**: Extend `Message` type with response IDs
|
|
132
|
+
|
|
133
|
+
## Performance Notes
|
|
134
|
+
|
|
135
|
+
Model checking explores **all possible states**. State space grows exponentially with:
|
|
136
|
+
- Number of contexts
|
|
137
|
+
- Number of messages
|
|
138
|
+
- Number of tabs
|
|
139
|
+
|
|
140
|
+
Current settings (3 contexts, 4 messages) check ~10,000 states in <1 second.
|
|
141
|
+
|
|
142
|
+
Increasing to 5 contexts + 6 messages = ~1 million states = ~10 seconds.
|
|
143
|
+
|
|
144
|
+
## Relationship to Code
|
|
145
|
+
|
|
146
|
+
The spec is **not** the implementation - it's a mathematical model.
|
|
147
|
+
|
|
148
|
+
**Code → Spec mapping:**
|
|
149
|
+
- `MessageRouter.routeMessage()` → `RouteMessage` action
|
|
150
|
+
- `port.onDisconnect()` → `DisconnectPort` action
|
|
151
|
+
- `pendingRequests` Map → `pendingRequests` variable
|
|
152
|
+
- "no loops" tests → `NoRoutingLoops` invariant
|
|
153
|
+
|
|
154
|
+
**Use TLA+ to:**
|
|
155
|
+
1. Find edge cases → Add as unit tests
|
|
156
|
+
2. Verify design before implementing
|
|
157
|
+
3. Document complex concurrent behavior
|
|
158
|
+
|
|
159
|
+
**Don't use TLA+ for:**
|
|
160
|
+
- Testing implementation details (use bun test)
|
|
161
|
+
- Performance testing
|
|
162
|
+
- Browser API quirks
|
|
163
|
+
|
|
164
|
+
## Learning Resources
|
|
165
|
+
|
|
166
|
+
- [TLA+ Home](https://lamport.azurewebsites.net/tla/tla.html)
|
|
167
|
+
- [Learn TLA+](https://learntla.com/)
|
|
168
|
+
- [Practical TLA+](https://www.apress.com/gp/book/9781484238288) (book)
|
|
169
|
+
- [TLA+ Video Course](https://lamport.azurewebsites.net/video/videos.html)
|
|
170
|
+
|
|
171
|
+
## Next Steps
|
|
172
|
+
|
|
173
|
+
Potential expansions:
|
|
174
|
+
- [ ] Model request/response pairing with IDs
|
|
175
|
+
- [ ] Model port reconnection scenarios
|
|
176
|
+
- [ ] Add tabId-specific routing
|
|
177
|
+
- [ ] Model MessageBus interaction
|
|
178
|
+
- [ ] Verify broadcast reaches all ports exactly once
|
|
179
|
+
- [ ] Model race conditions during port disconnect
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════════════════════════
|
|
2
|
+
// Verification Configuration
|
|
3
|
+
// ═══════════════════════════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// This file configures TLA+ verification for your extension.
|
|
6
|
+
// Some values are auto-configured, others need your input.
|
|
7
|
+
//
|
|
8
|
+
// Look for:
|
|
9
|
+
// • /* CONFIGURE */ - Replace with your value
|
|
10
|
+
// • /* REVIEW */ - Check the auto-generated value
|
|
11
|
+
// • null - Must be replaced with a concrete value
|
|
12
|
+
//
|
|
13
|
+
// Run 'bun verify' to check for incomplete configuration.
|
|
14
|
+
// Run 'bun verify --setup' for interactive help.
|
|
15
|
+
//
|
|
16
|
+
|
|
17
|
+
import { defineVerification } from '../src/index'
|
|
18
|
+
|
|
19
|
+
export default defineVerification({
|
|
20
|
+
state: {
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
messages: {
|
|
24
|
+
// Maximum messages in flight simultaneously across all contexts.
|
|
25
|
+
// Higher = more realistic concurrency, but exponentially slower.
|
|
26
|
+
//
|
|
27
|
+
// Recommended values:
|
|
28
|
+
// • 2-3: Fast verification (< 10 seconds)
|
|
29
|
+
// • 4-6: Balanced (10-60 seconds)
|
|
30
|
+
// • 8+: Thorough but slow (minutes)
|
|
31
|
+
//
|
|
32
|
+
// WARNING: State space grows exponentially! Start small.
|
|
33
|
+
maxInFlight: 3,
|
|
34
|
+
|
|
35
|
+
// Maximum tab IDs to model (content scripts are per-tab).
|
|
36
|
+
//
|
|
37
|
+
// Recommended:
|
|
38
|
+
// • 0-1: Most extensions (single tab or tab-agnostic)
|
|
39
|
+
// • 2-3: Multi-tab coordination
|
|
40
|
+
//
|
|
41
|
+
// Start with 0 or 1 for faster verification.
|
|
42
|
+
maxTabs: 1,
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
// Verification behavior
|
|
46
|
+
// ─────────────────────
|
|
47
|
+
//
|
|
48
|
+
// onBuild: What to do during development builds
|
|
49
|
+
// • 'warn' - Show warnings but don't fail (recommended)
|
|
50
|
+
// • 'error' - Fail the build on violations
|
|
51
|
+
// • 'off' - Skip verification
|
|
52
|
+
//
|
|
53
|
+
onBuild: 'warn',
|
|
54
|
+
|
|
55
|
+
// onRelease: What to do during production builds
|
|
56
|
+
// • 'error' - Fail the build on violations (recommended)
|
|
57
|
+
// • 'warn' - Show warnings but don't fail
|
|
58
|
+
// • 'off' - Skip verification
|
|
59
|
+
//
|
|
60
|
+
onRelease: 'error',
|
|
61
|
+
})
|
|
@@ -1,21 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
5
3
|
var __defProp = Object.defineProperty;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __toESM = (mod, isNodeMode, target) => {
|
|
9
|
-
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
10
|
-
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
11
|
-
for (let key of __getOwnPropNames(mod))
|
|
12
|
-
if (!__hasOwnProp.call(to, key))
|
|
13
|
-
__defProp(to, key, {
|
|
14
|
-
get: () => mod[key],
|
|
15
|
-
enumerable: true
|
|
16
|
-
});
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
4
|
var __export = (target, all) => {
|
|
20
5
|
for (var name in all)
|
|
21
6
|
__defProp(target, name, {
|
|
@@ -1187,7 +1172,6 @@ async function analyzeCodebase(options) {
|
|
|
1187
1172
|
const extractor = new TypeExtractor(options.tsConfigPath);
|
|
1188
1173
|
return extractor.analyzeCodebase(options.stateFilePath);
|
|
1189
1174
|
}
|
|
1190
|
-
|
|
1191
1175
|
// vendor/verify/src/codegen/config.ts
|
|
1192
1176
|
class ConfigGenerator {
|
|
1193
1177
|
lines = [];
|
|
@@ -1736,6 +1720,7 @@ function validateConfig(configPath) {
|
|
|
1736
1720
|
}
|
|
1737
1721
|
|
|
1738
1722
|
// vendor/verify/src/cli.ts
|
|
1723
|
+
var __dirname = "/Users/AJT/projects/polly/packages/polly/vendor/verify/src";
|
|
1739
1724
|
var COLORS = {
|
|
1740
1725
|
reset: "\x1B[0m",
|
|
1741
1726
|
red: "\x1B[31m",
|
|
@@ -1950,12 +1935,30 @@ async function runFullVerification(configPath) {
|
|
|
1950
1935
|
const cfgPath = path3.join(specDir, "UserApp.cfg");
|
|
1951
1936
|
fs3.writeFileSync(specPath, spec);
|
|
1952
1937
|
fs3.writeFileSync(cfgPath, cfg);
|
|
1953
|
-
const
|
|
1954
|
-
|
|
1938
|
+
const possiblePaths = [
|
|
1939
|
+
path3.join(process.cwd(), "specs", "tla", "MessageRouter.tla"),
|
|
1940
|
+
path3.join(__dirname, "..", "specs", "tla", "MessageRouter.tla"),
|
|
1941
|
+
path3.join(__dirname, "..", "..", "specs", "tla", "MessageRouter.tla"),
|
|
1942
|
+
path3.join(process.cwd(), "external", "polly", "packages", "verify", "specs", "tla", "MessageRouter.tla"),
|
|
1943
|
+
path3.join(process.cwd(), "node_modules", "@fairfox", "polly-verify", "specs", "tla", "MessageRouter.tla")
|
|
1944
|
+
];
|
|
1945
|
+
let baseSpecPath = null;
|
|
1946
|
+
for (const candidatePath of possiblePaths) {
|
|
1947
|
+
if (fs3.existsSync(candidatePath)) {
|
|
1948
|
+
baseSpecPath = candidatePath;
|
|
1949
|
+
break;
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
if (baseSpecPath) {
|
|
1955
1953
|
const destSpecPath = path3.join(specDir, "MessageRouter.tla");
|
|
1956
1954
|
fs3.copyFileSync(baseSpecPath, destSpecPath);
|
|
1955
|
+
console.log(color("✓ Copied MessageRouter.tla", COLORS.green));
|
|
1957
1956
|
} else {
|
|
1958
1957
|
console.log(color("⚠️ Warning: MessageRouter.tla not found, verification may fail", COLORS.yellow));
|
|
1958
|
+
console.log(color(` Searched in:`, COLORS.gray));
|
|
1959
|
+
for (const searchPath of possiblePaths) {
|
|
1960
|
+
console.log(color(` - ${searchPath}`, COLORS.gray));
|
|
1961
|
+
}
|
|
1959
1962
|
}
|
|
1960
1963
|
console.log(color("✓ Specification generated", COLORS.green));
|
|
1961
1964
|
console.log(color(` ${specPath}`, COLORS.gray));
|
|
@@ -2086,4 +2089,4 @@ Stack trace:`, COLORS.gray));
|
|
|
2086
2089
|
process.exit(1);
|
|
2087
2090
|
});
|
|
2088
2091
|
|
|
2089
|
-
//# debugId=
|
|
2092
|
+
//# debugId=F6E692DF29A2A67064756E2164756E21
|