@wowok/skills 1.1.9 → 1.1.11

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.
Files changed (40) hide show
  1. package/LICENSE +36 -0
  2. package/README.md +1 -8
  3. package/dist/cli.js +4 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/skills.d.ts.map +1 -1
  6. package/dist/skills.js +33 -0
  7. package/dist/skills.js.map +1 -1
  8. package/examples/Insurance/Insurance.md +218 -90
  9. package/examples/MyShop/MyShop.md +513 -245
  10. package/examples/MyShop/myshop_machine_nodes.json +87 -0
  11. package/examples/MyShop_Advanced/MyShop_Advanced.md +633 -228
  12. package/examples/ThreeBody_Signature/ThreeBody_Signature.md +195 -202
  13. package/examples/Travel/Travel.md +775 -487
  14. package/examples/Travel/calc-weather-timestamps.js +9 -5
  15. package/package.json +8 -3
  16. package/scripts/install.js +4 -0
  17. package/wowok-arbitrator/SKILL.md +542 -1
  18. package/wowok-auditor/SKILL.md +581 -0
  19. package/wowok-guard/SKILL.md +425 -1
  20. package/wowok-machine/SKILL.md +404 -1
  21. package/wowok-messenger/SKILL.md +551 -1
  22. package/wowok-onboard/SKILL.md +520 -0
  23. package/wowok-order/SKILL.md +528 -1
  24. package/wowok-output/SKILL.md +571 -0
  25. package/wowok-planner/SKILL.md +757 -0
  26. package/wowok-provider/SKILL.md +455 -1
  27. package/wowok-safety/SKILL.md +557 -0
  28. package/wowok-scenario/SKILL.md +585 -0
  29. package/wowok-tools/SKILL.md +423 -1
  30. package/examples/Insurance/Insurance_TestResults.md +0 -481
  31. package/examples/Insurance/insurance_complete_guard_v1.json +0 -50
  32. package/examples/MyShop/MyShop_TestResults.md +0 -1003
  33. package/examples/MyShop_Advanced/MyShop_Advanced_MerchantSystem_TestResults.md +0 -1297
  34. package/examples/MyShop_Advanced/MyShop_Advanced_OrderFlow_TestResults.md +0 -743
  35. package/examples/MyShop_Advanced/machine_nodes.json +0 -222
  36. package/examples/MyShop_Advanced/three_body_signature.wip +0 -30
  37. package/examples/ThreeBody_Signature/ThreeBody_Signature_TestResults.md +0 -599
  38. package/examples/Travel/Travel_TestResults.md +0 -743
  39. package/examples/Travel/travel_machine_v2_export.json +0 -104
  40. package/examples/Travel/weather_check_guard_v1.json +0 -51
@@ -2,108 +2,18 @@
2
2
 
3
3
  A complete example demonstrating how to create an Iceland travel service using WoWok protocol. This service integrates weather-dependent activities, insurance sub-orders, and multi-node workflow management.
4
4
 
5
- > **View Actual Execution Results**: See [Travel_TestResults.md](Travel_TestResults.md) for real testnet execution results with actual object addresses and transaction outputs.
6
-
7
5
  ---
8
6
 
9
7
  ## Core Requirements & Features
10
8
 
11
9
  | Requirement | Description | Implementation |
12
10
  |-------------|-------------|----------------|
13
- | **Weather-Dependent Activities** | Ice scooting requires sunny weather | Guard queries weather Repository for the activity date |
14
- | **Insurance Sub-Order** | Travel provider purchases insurance as supply chain sub-order | Machine forward creates insurance Order via Progress |
11
+ | **Weather Data Query** | Demonstrate querying weather Repository | Guard checks if weather data exists for a given date |
15
12
  | **Multi-Node Workflow** | Start -> Buy Insurance -> SPA -> Ice Scooting -> Complete | Machine with 5 nodes and conditional paths |
16
13
  | **Time-Lock Completion** | Prevent premature order completion | Guard using Order + convert_witness(TypeOrderProgress) |
17
- | **Cancellation Support** | Allow order cancellation before completion | Cancel forward with permission-based access |
14
+ | **Cancellation Support** | Allow order cancellation from Ice Scooting node | Cancel forward with permission-based access |
18
15
  | **Arbitration** | Dispute resolution for order conflicts | Arbitration object bound to Service |
19
-
20
- ### Key Design Decisions
21
-
22
- 1. **Weather Data via Repository**: Weather conditions are stored in a Repository object with policy "Condition". Each day's weather is keyed by UTC timestamp (converted to Address via `convert_number_address`).
23
- 2. **Insurance as Sub-Order**: The "Buy Insurance" node creates a sub-order on the insurance service, linking the two workflows.
24
- 3. **Time-Lock via Witness Conversion**: The Complete node Guard uses `convert_witness: 100` (TypeOrderProgress) to access Progress data from the submitted Order.
25
- 4. **Dynamic Time Calculation**: Weather data timestamps are calculated dynamically based on current time, ensuring the example is always testable.
26
-
27
- ---
28
-
29
- ## Overview
30
-
31
- This example demonstrates:
32
-
33
- - **Travel Service Setup**: Permission, Arbitration, Guards, Machine, and Service creation
34
- - **Weather Data Management**: Repository with weather conditions for activity validation
35
- - **Insurance Integration**: Supply chain sub-order for insurance purchase
36
- - **Multi-Node Workflow**: Complex workflow with weather-dependent paths
37
- - **Time-Lock Guards**: Using Order + convert_witness for Progress data access
38
-
39
- ---
40
-
41
- ## Architecture
42
-
43
- ### System Components
44
-
45
- ```
46
- +--------------------------------------------------------------------------+
47
- | Iceland Travel Service System |
48
- +--------------------------------------------------------------------------+
49
- | |
50
- | +--------------+ +--------------+ +--------------+ +--------------+ |
51
- | | Permission | | Arbitration | | Guards | | Repository | |
52
- | | (travel_ | | (travel_ | | (weather_ | | (weather_ | |
53
- | | permission)| | arbitration)| | check, | | repo) | |
54
- | +------+-------+ +------+-------+ | complete, | +------+-------+ |
55
- | | | | cancel) | | |
56
- | v v +------+-------+ | |
57
- | +--------------+ +--------------+ | | |
58
- | | Machine | | Service | | | |
59
- | | (travel_ |<-| (travel_ | | | |
60
- | | machine) | | service) | | | |
61
- | +--------------+ +--------------+ | | |
62
- | | | |
63
- | Workflow: | | |
64
- | Start -> Buy Insurance -> SPA -> Ice Scooting | | |
65
- | | | | |
66
- | +----------+---------+----------+ | |
67
- | | | | |
68
- | v v | |
69
- | +----------+ +----------+ | |
70
- | | Complete | | Cancel | | |
71
- | |(TimeLock)| | | | |
72
- | +----------+ +----------+ | |
73
- | |
74
- +--------------------------------------------------------------------------+
75
- ```
76
-
77
- ### Workflow Diagram
78
-
79
- ```
80
- +-------------+
81
- | Start |
82
- +------+------+
83
- |
84
- v
85
- +-------------+
86
- |Buy Insurance| ---> Creates sub-order on insurance service
87
- +------+------+
88
- |
89
- v
90
- +-------------+
91
- | SPA |
92
- +------+------+
93
- |
94
- v
95
- +-------------+
96
- |Ice Scooting | ---> Weather check Guard (sunny required)
97
- +------+------+
98
- |
99
- +-----------+-----------+
100
- | |
101
- v v
102
- +-------------+ +-------------+
103
- | Complete | | Cancel |
104
- | (Time-Lock) | | |
105
- +-------------+ +-------------+
106
- ```
16
+ | **Revenue Allocation** | Distribute funds based on progress state | Three allocation Guards for different refund scenarios |
107
17
 
108
18
  ---
109
19
 
@@ -111,11 +21,10 @@ This example demonstrates:
111
21
 
112
22
  Before running this example, ensure you have:
113
23
 
114
- 1. An account named `travel_provider_v1` with sufficient WOW tokens
115
- 2. An account named `weather_provider_v1` with sufficient WOW tokens
116
- 3. An account named `alice_v1` (test customer) with sufficient WOW tokens
117
- 4. The Insurance service from [Insurance/Insurance.md](../Insurance/Insurance.md) already deployed
118
- 5. Access to the WoWok MCP server
24
+ 1. An account named `travel_provider` with sufficient WOW tokens
25
+ 2. An account named `weather_provider` with sufficient WOW tokens
26
+ 3. An account named `alice` (test customer) with sufficient WOW tokens
27
+ 4. Access to the WoWok MCP server
119
28
 
120
29
  ### Create Accounts
121
30
 
@@ -124,7 +33,7 @@ Before running this example, ensure you have:
124
33
  ```json
125
34
  {
126
35
  "gen": {
127
- "name": "travel_provider_v1",
36
+ "name": "travel_provider",
128
37
  "replaceExistName": true
129
38
  }
130
39
  }
@@ -133,7 +42,7 @@ Before running this example, ensure you have:
133
42
  ```json
134
43
  {
135
44
  "gen": {
136
- "name": "weather_provider_v1",
45
+ "name": "weather_provider",
137
46
  "replaceExistName": true
138
47
  }
139
48
  }
@@ -142,7 +51,7 @@ Before running this example, ensure you have:
142
51
  ```json
143
52
  {
144
53
  "gen": {
145
- "name": "alice_v1",
54
+ "name": "alice",
146
55
  "replaceExistName": true
147
56
  }
148
57
  }
@@ -156,7 +65,7 @@ Before running this example, ensure you have:
156
65
  {
157
66
  "faucet": {
158
67
  "network": "testnet",
159
- "name_or_address": "travel_provider_v1"
68
+ "name_or_address": "travel_provider"
160
69
  }
161
70
  }
162
71
  ```
@@ -165,7 +74,7 @@ Before running this example, ensure you have:
165
74
  {
166
75
  "faucet": {
167
76
  "network": "testnet",
168
- "name_or_address": "weather_provider_v1"
77
+ "name_or_address": "weather_provider"
169
78
  }
170
79
  }
171
80
  ```
@@ -174,7 +83,7 @@ Before running this example, ensure you have:
174
83
  {
175
84
  "faucet": {
176
85
  "network": "testnet",
177
- "name_or_address": "alice_v1"
86
+ "name_or_address": "alice"
178
87
  }
179
88
  }
180
89
  ```
@@ -183,41 +92,53 @@ Before running this example, ensure you have:
183
92
 
184
93
  ## Step 0: Setup Weather Data
185
94
 
186
- Before creating the travel service, set up the weather Repository with recent 5-day weather data.
95
+ Before creating the travel service, set up the weather Repository with the next 5 days of weather data. The weather data is keyed by timestamp, and the `weather_check_guard` (Step 3.1) will query this repository at runtime when the customer enters the "Ice Scooting" node (Step 7.3). You must use timestamps that are valid at the time you run this example.
187
96
 
188
97
  ### 0.1 Calculate Weather Timestamps
189
98
 
190
- Use the following JavaScript to calculate recent 5-day UTC timestamps:
99
+ The weather record `id` is a UTC timestamp (in milliseconds). It must be **aligned to UTC 00:00:00** so that the same timestamp can be reproduced and submitted later in Step 7.3. Run the following JavaScript (also available as `calc-weather-timestamps.js` in this example folder):
191
100
 
192
101
  ```js
193
- const DAY_MS = 86400000;
102
+ const DAY_MS = 86400000; // 24 * 60 * 60 * 1000
194
103
  const now = Date.now();
104
+ // Align to UTC 00:00:00 of today, then compute the next 5 days.
105
+ // Repository data is keyed by timestamp, so the submitted activity date
106
+ // must match exactly the id used when adding weather data.
195
107
  const todayStart = Math.floor(now / DAY_MS) * DAY_MS;
196
- // Recent 5 days UTC day start timestamps (from 4 days ago to today)
197
- for (let i = 4; i >= 0; i--) {
198
- const ts = todayStart - i * DAY_MS;
199
- console.log(`Day ${5-i}: ${ts} (${new Date(ts).toISOString()})`);
108
+ for (let i = 1; i <= 5; i++) {
109
+ const ts = todayStart + i * DAY_MS;
110
+ console.log(`Day ${i}: ${ts} (${new Date(ts).toISOString()})`);
200
111
  }
201
112
  ```
202
113
 
203
- ### 0.2 Create Weather Permission
114
+ **Sample output** (run on 2026-07-08 — re-run the script to get current values for your test time):
204
115
 
205
- First, create a Permission object for the weather repository.
116
+ ```
117
+ Day 1: 1783555200000 (2026-07-09T00:00:00.000Z)
118
+ Day 2: 1783641600000 (2026-07-10T00:00:00.000Z)
119
+ Day 3: 1783728000000 (2026-07-11T00:00:00.000Z)
120
+ Day 4: 1783814400000 (2026-07-12T00:00:00.000Z)
121
+ Day 5: 1783900800000 (2026-07-13T00:00:00.000Z)
122
+ ```
206
123
 
207
- **Prompt**: Create a Permission object named "weather_permission_v1".
124
+ > **Important**: Always re-run the script at test time — the timestamps depend on the current date. Copy the 5 printed values; they will be used in Step 0.4 (as repository data `id`) and Step 7.3 (as the submitted `activity_date`). The two must match exactly, otherwise the Guard query `repository.data has("Condition", convert_number_address(activity_date))` will return false.
125
+
126
+ ### 0.2 Create Weather Permission
127
+
128
+ **Prompt**: Create a Permission object named "weather_permission".
208
129
 
209
130
  ```json
210
131
  {
211
132
  "operation_type": "permission",
212
133
  "data": {
213
134
  "object": {
214
- "name": "weather_permission_v1",
135
+ "name": "weather_permission",
215
136
  "replaceExistName": true
216
137
  },
217
138
  "description": "Weather repository permission"
218
139
  },
219
140
  "env": {
220
- "account": "weather_provider_v1",
141
+ "account": "weather_provider",
221
142
  "network": "testnet"
222
143
  }
223
144
  }
@@ -225,17 +146,15 @@ First, create a Permission object for the weather repository.
225
146
 
226
147
  ### 0.3 Create Weather Repository with Policies
227
148
 
228
- Create the weather repository with the "Condition" policy included during creation (this avoids the need to add policies later, which had issues in testing).
229
-
230
- **Prompt**: Create a Repository named "weather_repo_v2" with "Condition" policy.
149
+ **Prompt**: Create a Repository named "weather_repo" with "Condition" policy.
231
150
 
232
151
  ```json
233
152
  {
234
153
  "operation_type": "repository",
235
154
  "data": {
236
155
  "object": {
237
- "name": "weather_repo_v2",
238
- "permission": "weather_permission_v1",
156
+ "name": "weather_repo",
157
+ "permission": "weather_permission",
239
158
  "replaceExistName": true
240
159
  },
241
160
  "description": "Weather data repository for Iceland travel activities",
@@ -253,7 +172,7 @@ Create the weather repository with the "Condition" policy included during creati
253
172
  }
254
173
  },
255
174
  "env": {
256
- "account": "weather_provider_v1",
175
+ "account": "weather_provider",
257
176
  "network": "testnet"
258
177
  }
259
178
  }
@@ -261,90 +180,93 @@ Create the weather repository with the "Condition" policy included during creati
261
180
 
262
181
  ### 0.4 Add Weather Data
263
182
 
264
- Add 5 days of weather data. The last day is "rainy" to test the weather check Guard's rejection behavior.
183
+ Add 5 days of weather data. The `weather_check_guard` (Step 3.1) only verifies that a record **exists** for the activity date (via `repository.data has`), so all 5 days will pass the Guard regardless of the condition value. The "rainy" value on Day 5 is informational only — to actually reject based on weather condition, you would need a Guard that queries `repository.data` and compares the value, which is more complex and not used in this example.
265
184
 
266
- **Prompt**: Add weather data to "weather_repo_v2" with policy "Condition". Use the timestamps calculated in step 0.1.
185
+ **Prompt**: Add weather data to "weather_repo" with policy "Condition".
267
186
 
268
187
  ```json
269
188
  {
270
189
  "operation_type": "repository",
271
190
  "data": {
272
- "object": "weather_repo_v2",
191
+ "object": "weather_repo",
273
192
  "data_add": {
274
193
  "name": "Condition",
275
194
  "items": [
276
195
  {
277
196
  "data": [
278
- {"id": 1777334400000, "data": "sunny"},
279
- {"id": 1777420800000, "data": "sunny"},
280
- {"id": 1777507200000, "data": "sunny"},
281
- {"id": 1777593600000, "data": "sunny"},
282
- {"id": 1777680000000, "data": "rainy"}
197
+ {"id": <DAY1_TIMESTAMP>, "data": "sunny"},
198
+ {"id": <DAY2_TIMESTAMP>, "data": "sunny"},
199
+ {"id": <DAY3_TIMESTAMP>, "data": "sunny"},
200
+ {"id": <DAY4_TIMESTAMP>, "data": "sunny"},
201
+ {"id": <DAY5_TIMESTAMP>, "data": "rainy"}
283
202
  ]
284
203
  }
285
204
  ]
286
205
  }
287
206
  },
288
207
  "env": {
289
- "account": "weather_provider_v1",
208
+ "account": "weather_provider",
290
209
  "network": "testnet"
291
210
  }
292
211
  }
293
212
  ```
294
213
 
295
- > **Note**: Replace the timestamps with actual values from step 0.1. The last day is "rainy" to demonstrate weather-dependent activity rejection.
214
+ > **Note**: Replace `<DAY1_TIMESTAMP>` through `<DAY5_TIMESTAMP>` with the actual values from Step 0.1. The `id` field is the timestamp (as a number) that keys the weather record — it must **exactly match** the timestamp you submit later in Step 7.3.
296
215
 
297
216
  ---
298
217
 
299
218
  ## Step 1: Create Permission Object
300
219
 
301
- Create a Permission object to manage access control for the travel service.
220
+ Create a Permission object to manage access control for the travel service. Add permission indices for the travel_provider account.
302
221
 
303
- **Prompt**: Create a Permission object named "travel_permission_v1" for the travel service.
222
+ **Prompt**: Create a Permission object named "travel_permission" for the travel service.
304
223
 
305
224
  ```json
306
225
  {
307
226
  "operation_type": "permission",
308
227
  "data": {
309
228
  "object": {
310
- "name": "travel_permission_v1",
229
+ "name": "travel_permission",
230
+ "tags": ["travel", "iceland", "tourism"],
311
231
  "replaceExistName": true
312
232
  },
313
233
  "description": "Permission for Iceland travel service",
314
234
  "table": {
315
235
  "op": "add perm by entity",
316
- "entity": {"name_or_address": "travel_provider_v1"},
317
- "index": [1000, 1001, 1002, 1003, 1004, 1005]
236
+ "entity": {"name_or_address": "travel_provider"},
237
+ "index": [1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 306]
318
238
  }
319
239
  },
320
240
  "env": {
321
- "account": "travel_provider_v1",
241
+ "account": "travel_provider",
322
242
  "network": "testnet"
323
243
  }
324
244
  }
325
245
  ```
326
246
 
247
+ > **Note**: Permission indices 1000-1009 are used for different workflow forwards. Index 306 is a reserved administrative permission. The travel_provider account is granted all these permissions.
248
+
327
249
  ---
328
250
 
329
251
  ## Step 2: Create Arbitration Object
330
252
 
331
253
  Create an Arbitration object for dispute resolution.
332
254
 
333
- **Prompt**: Create an Arbitration named "travel_arbitration_v1".
255
+ **Prompt**: Create an Arbitration named "travel_arbitration".
334
256
 
335
257
  ```json
336
258
  {
337
259
  "operation_type": "arbitration",
338
260
  "data": {
339
261
  "object": {
340
- "name": "travel_arbitration_v1",
341
- "permission": "travel_permission_v1",
262
+ "name": "travel_arbitration",
263
+ "permission": "travel_permission",
342
264
  "replaceExistName": true
343
265
  },
344
266
  "description": "Arbitration for Iceland travel service disputes"
345
267
  },
346
268
  "env": {
347
- "account": "travel_provider_v1",
269
+ "account": "travel_provider",
348
270
  "network": "testnet"
349
271
  }
350
272
  }
@@ -354,17 +276,15 @@ Create an Arbitration object for dispute resolution.
354
276
 
355
277
  ## Step 3: Create Guards
356
278
 
357
- ### 3.1 Weather Check Guard
358
-
359
- > **Note**: This guard demonstrates how to query repository data using a timestamp converted to an address. You can test it using `gen_passport` with a timestamp from step 0.1.
279
+ Create all Guards needed for the workflow and fund allocation. Guards are immutable once created, so create them before the Machine and Service.
360
280
 
361
- **Prompt**: Create a Guard named "weather_check_guard_v1" for weather condition verification.
281
+ ### 3.1 Weather Check Guard
362
282
 
363
- Creates a Guard that verifies weather conditions for a given date. Queries the weather Repository for the specified date and checks if the condition matches the expected value.
283
+ Creates a Guard that verifies weather data exists for a given date. This Guard is bound to the "go_ice_scooting" forward (entering the weather-dependent Ice Scooting activity) to ensure the activity date has a weather record in the repository.
364
284
 
365
285
  **Guard Logic**:
366
286
  ```
367
- repository.data("Condition", convert_number_address(activity_date)) == expected_weather
287
+ repository.data has("Condition", convert_number_address(activity_date))
368
288
  ```
369
289
 
370
290
  **Prompt**: Create a Guard named "weather_check_guard" for weather condition verification.
@@ -374,17 +294,17 @@ repository.data("Condition", convert_number_address(activity_date)) == expected_
374
294
  "operation_type": "guard",
375
295
  "data": {
376
296
  "namedNew": {
377
- "name": "weather_check_guard_v1",
297
+ "name": "weather_check_guard",
378
298
  "tags": ["weather", "check", "travel"],
379
299
  "replaceExistName": true
380
300
  },
381
- "description": "Weather check guard for ice scooting activity. Queries weather Repository for the activity date and verifies the condition is 'sunny'. The activity date is submitted at runtime.",
301
+ "description": "Weather check guard for ice scooting activity. Checks if weather data exists for the activity date.",
382
302
  "table": [
383
303
  {
384
304
  "identifier": 0,
385
305
  "b_submission": false,
386
306
  "value_type": "Address",
387
- "value": "weather_repo_v2",
307
+ "value": "weather_repo",
388
308
  "name": "Weather Repository address"
389
309
  },
390
310
  {
@@ -400,65 +320,35 @@ repository.data("Condition", convert_number_address(activity_date)) == expected_
400
320
  "value_type": "U64",
401
321
  "value": 0,
402
322
  "name": "Activity date timestamp (submitted at runtime)"
403
- },
404
- {
405
- "identifier": 3,
406
- "b_submission": false,
407
- "value_type": "String",
408
- "value": "sunny",
409
- "name": "Expected weather condition"
410
323
  }
411
324
  ],
412
325
  "root": {
413
- "type": "node",
414
- "node": {
415
- "type": "logic_equal",
416
- "nodes": [
417
- {
418
- "type": "query",
419
- "query": "repository.data",
420
- "object": {
421
- "identifier": 0
422
- },
423
- "parameters": [
424
- {
425
- "type": "identifier",
426
- "identifier": 1
427
- },
428
- {
429
- "type": "convert_number_address",
430
- "node": {
431
- "type": "identifier",
432
- "identifier": 2
433
- }
434
- }
435
- ]
436
- },
437
- {
438
- "type": "identifier",
439
- "identifier": 3
440
- }
441
- ]
442
- }
326
+ "type": "query",
327
+ "query": "repository.data has",
328
+ "object": {"identifier": 0},
329
+ "parameters": [
330
+ {"type": "identifier", "identifier": 1},
331
+ {
332
+ "type": "convert_number_address",
333
+ "node": {"type": "identifier", "identifier": 2}
334
+ }
335
+ ]
443
336
  }
444
337
  },
445
338
  "env": {
446
- "account": "travel_provider_v1",
339
+ "account": "travel_provider",
447
340
  "network": "testnet"
448
341
  }
449
342
  }
450
343
  ```
451
344
 
452
- > **Note**: We use the repository name "weather_repo_v2" directly (the MCP server resolves names to addresses automatically). If you need the raw address, you can query it using `onchain_objects` with the name.
453
-
454
345
  **Guard Table**:
455
346
 
456
347
  | identifier | b_submission | value_type | value | Purpose |
457
348
  |------------|-------------|-----------|-------|---------|
458
- | 0 | false | Address | weather_repo address | Weather Repository to query |
349
+ | 0 | false | Address | weather_repo | Weather Repository to query |
459
350
  | 1 | false | String | "Condition" | Repository policy name |
460
351
  | 2 | **true** | U64 | 0 (placeholder) | Activity date timestamp, submitted at runtime |
461
- | 3 | false | String | "sunny" | Expected weather condition |
462
352
 
463
353
  ### 3.2 Travel Complete Guard (Time-Lock)
464
354
 
@@ -477,11 +367,11 @@ clock > progress.current_time + 1000
477
367
  "operation_type": "guard",
478
368
  "data": {
479
369
  "namedNew": {
480
- "name": "travel_complete_guard_v1",
370
+ "name": "travel_complete_guard",
481
371
  "tags": ["travel", "time-lock", "complete"],
482
372
  "replaceExistName": true
483
373
  },
484
- "description": "Time-lock guard for travel order completion. Requires current clock > progress.current_time + 1000ms (1 second for TESTING; in production set to reasonable duration like 8 hours). Progress is accessed via Order with convert_witness=TypeOrderProgress(100).",
374
+ "description": "Time-lock guard for travel order completion. Requires current clock > progress.current_time + 1000ms.",
485
375
  "table": [
486
376
  {
487
377
  "identifier": 0,
@@ -494,42 +384,31 @@ clock > progress.current_time + 1000
494
384
  "identifier": 1,
495
385
  "b_submission": false,
496
386
  "value_type": "U64",
497
- "value": 1000
387
+ "value": 1000,
388
+ "name": "Time-lock duration in ms"
498
389
  }
499
390
  ],
500
391
  "root": {
501
- "type": "node",
502
- "node": {
503
- "type": "logic_as_u256_greater",
504
- "nodes": [
505
- {
506
- "type": "context",
507
- "context": "Clock"
508
- },
509
- {
510
- "type": "calc_number_add",
511
- "nodes": [
512
- {
513
- "type": "query",
514
- "query": "progress.current_time",
515
- "object": {
516
- "identifier": 0,
517
- "convert_witness": 100
518
- },
519
- "parameters": []
520
- },
521
- {
522
- "type": "identifier",
523
- "identifier": 1
524
- }
525
- ]
526
- }
527
- ]
528
- }
392
+ "type": "logic_as_u256_greater",
393
+ "nodes": [
394
+ {"type": "context", "context": "Clock"},
395
+ {
396
+ "type": "calc_number_add",
397
+ "nodes": [
398
+ {
399
+ "type": "query",
400
+ "query": "progress.current_time",
401
+ "object": {"identifier": 0, "convert_witness": 100},
402
+ "parameters": []
403
+ },
404
+ {"type": "identifier", "identifier": 1}
405
+ ]
406
+ }
407
+ ]
529
408
  }
530
409
  },
531
410
  "env": {
532
- "account": "travel_provider_v1",
411
+ "account": "travel_provider",
533
412
  "network": "testnet"
534
413
  }
535
414
  }
@@ -555,11 +434,11 @@ Creates a Guard that allows order cancellation. This Guard always passes (return
555
434
  "operation_type": "guard",
556
435
  "data": {
557
436
  "namedNew": {
558
- "name": "travel_cancel_guard_v1",
437
+ "name": "travel_cancel_guard",
559
438
  "tags": ["travel", "cancel"],
560
439
  "replaceExistName": true
561
440
  },
562
- "description": "Cancel guard for travel orders. Always passes - cancellation is controlled by permission-based access (only authorized operators can execute the cancel forward).",
441
+ "description": "Cancel guard for travel orders. Always passes - cancellation is controlled by permission-based access.",
563
442
  "table": [
564
443
  {
565
444
  "identifier": 0,
@@ -570,15 +449,192 @@ Creates a Guard that allows order cancellation. This Guard always passes (return
570
449
  }
571
450
  ],
572
451
  "root": {
573
- "type": "node",
574
- "node": {
575
- "type": "identifier",
576
- "identifier": 0
452
+ "type": "identifier",
453
+ "identifier": 0
454
+ }
455
+ },
456
+ "env": {
457
+ "account": "travel_provider",
458
+ "network": "testnet"
459
+ }
460
+ }
461
+ ```
462
+
463
+ ### 3.4 Merchant Victory Guard (100% to Service)
464
+
465
+ Checks if order progress current node is "Complete". If passed, merchant receives 100% of funds.
466
+
467
+ **Prompt**: Create Guard "merchant_victory_guard".
468
+
469
+ ```json
470
+ {
471
+ "operation_type": "guard",
472
+ "data": {
473
+ "namedNew": {
474
+ "name": "merchant_victory_guard",
475
+ "tags": ["merchant", "victory", "complete"],
476
+ "replaceExistName": true
477
+ },
478
+ "description": "Guard for merchant victory: checks if order progress current node is Complete. If passed, merchant receives 100% of funds.",
479
+ "table": [
480
+ {
481
+ "identifier": 0,
482
+ "b_submission": true,
483
+ "value_type": "Address",
484
+ "value": "0x0000000000000000000000000000000000000000000000000000000000000000",
485
+ "name": "Order ID (submitted at runtime)"
486
+ },
487
+ {
488
+ "identifier": 1,
489
+ "b_submission": false,
490
+ "value_type": "String",
491
+ "value": "Complete",
492
+ "name": "Complete node name"
493
+ }
494
+ ],
495
+ "root": {
496
+ "type": "logic_equal",
497
+ "nodes": [
498
+ {
499
+ "type": "query",
500
+ "query": "progress.current",
501
+ "object": {"identifier": 0, "convert_witness": 100},
502
+ "parameters": []
503
+ },
504
+ {"type": "identifier", "identifier": 1}
505
+ ]
506
+ }
507
+ },
508
+ "env": {
509
+ "account": "travel_provider",
510
+ "network": "testnet"
511
+ }
512
+ }
513
+ ```
514
+
515
+ ### 3.5 No Ice Scooting Guard (80% Service, 20% Refund)
516
+
517
+ Checks if progress current is "Cancel" or "Ice Scooting". If passed, merchant gets 80%, user gets 20% refund.
518
+
519
+ **Prompt**: Create Guard "no_ice_scooting_guard".
520
+
521
+ ```json
522
+ {
523
+ "operation_type": "guard",
524
+ "data": {
525
+ "namedNew": {
526
+ "name": "no_ice_scooting_guard",
527
+ "tags": ["user", "cancel", "ice_scooting"],
528
+ "replaceExistName": true
529
+ },
530
+ "description": "Guard for user not participating in ice scooting: checks if progress current is Cancel or Ice Scooting. If passed, merchant gets 80%, user gets 20% refund.",
531
+ "table": [
532
+ {
533
+ "identifier": 0,
534
+ "b_submission": true,
535
+ "value_type": "Address",
536
+ "value": "0x0000000000000000000000000000000000000000000000000000000000000000",
537
+ "name": "Order ID (submitted at runtime)"
538
+ },
539
+ {
540
+ "identifier": 1,
541
+ "b_submission": false,
542
+ "value_type": "String",
543
+ "value": "Cancel",
544
+ "name": "Cancel node name"
545
+ },
546
+ {
547
+ "identifier": 2,
548
+ "b_submission": false,
549
+ "value_type": "String",
550
+ "value": "Ice Scooting",
551
+ "name": "Ice Scooting node name"
552
+ }
553
+ ],
554
+ "root": {
555
+ "type": "logic_or",
556
+ "nodes": [
557
+ {
558
+ "type": "logic_equal",
559
+ "nodes": [
560
+ {
561
+ "type": "query",
562
+ "query": "progress.current",
563
+ "object": {"identifier": 0, "convert_witness": 100},
564
+ "parameters": []
565
+ },
566
+ {"type": "identifier", "identifier": 1}
567
+ ]
568
+ },
569
+ {
570
+ "type": "logic_equal",
571
+ "nodes": [
572
+ {
573
+ "type": "query",
574
+ "query": "progress.current",
575
+ "object": {"identifier": 0, "convert_witness": 100},
576
+ "parameters": []
577
+ },
578
+ {"type": "identifier", "identifier": 2}
579
+ ]
580
+ }
581
+ ]
582
+ }
583
+ },
584
+ "env": {
585
+ "account": "travel_provider",
586
+ "network": "testnet"
587
+ }
588
+ }
589
+ ```
590
+
591
+ ### 3.6 No SPA Guard (5% Service, 95% Refund)
592
+
593
+ Checks if progress current is "SPA". If passed, merchant gets 5%, user gets 95% refund.
594
+
595
+ **Prompt**: Create Guard "no_spa_guard".
596
+
597
+ ```json
598
+ {
599
+ "operation_type": "guard",
600
+ "data": {
601
+ "namedNew": {
602
+ "name": "no_spa_guard",
603
+ "tags": ["user", "cancel", "spa"],
604
+ "replaceExistName": true
605
+ },
606
+ "description": "Guard for user not participating in SPA: checks if progress current is SPA. If passed, merchant gets 5%, user gets 95% refund.",
607
+ "table": [
608
+ {
609
+ "identifier": 0,
610
+ "b_submission": true,
611
+ "value_type": "Address",
612
+ "value": "0x0000000000000000000000000000000000000000000000000000000000000000",
613
+ "name": "Order ID (submitted at runtime)"
614
+ },
615
+ {
616
+ "identifier": 1,
617
+ "b_submission": false,
618
+ "value_type": "String",
619
+ "value": "SPA",
620
+ "name": "SPA node name"
577
621
  }
622
+ ],
623
+ "root": {
624
+ "type": "logic_equal",
625
+ "nodes": [
626
+ {
627
+ "type": "query",
628
+ "query": "progress.current",
629
+ "object": {"identifier": 0, "convert_witness": 100},
630
+ "parameters": []
631
+ },
632
+ {"type": "identifier", "identifier": 1}
633
+ ]
578
634
  }
579
635
  },
580
636
  "env": {
581
- "account": "travel_provider_v1",
637
+ "account": "travel_provider",
582
638
  "network": "testnet"
583
639
  }
584
640
  }
@@ -586,52 +642,39 @@ Creates a Guard that allows order cancellation. This Guard always passes (return
586
642
 
587
643
  ---
588
644
 
589
- ## Step 4: Create Machine with Workflow
645
+ ## Step 4: Create and Publish Machine
646
+
647
+ Create a Machine to define the travel service workflow with all nodes and forwards. The Machine must be published before it can be bound to a Service.
590
648
 
591
- Create a Machine to define the travel service workflow with all nodes and forwards.
649
+ > **Important**: In the Machine node structure, each node's `pairs` define how to ENTER that node. The `prev_node` specifies the source node, and `forwards` are the operation names used to advance from `prev_node` to this node.
592
650
 
593
- **Prompt**: Create a Machine named "travel_machine" with the complete travel workflow.
651
+ **Prompt**: Create and publish a Machine named "travel_machine" with the complete travel workflow.
594
652
 
595
653
  ```json
596
654
  {
597
655
  "operation_type": "machine",
598
656
  "data": {
599
657
  "object": {
600
- "name": "travel_machine_v1",
601
- "permission": "travel_permission_v1",
658
+ "name": "travel_machine",
659
+ "permission": "travel_permission",
602
660
  "replaceExistName": true
603
661
  },
604
- "description": "Iceland travel service workflow: Start -> Buy Insurance -> SPA -> Ice Scooting -> Complete/Cancel",
662
+ "description": "Iceland travel service workflow: (init) -> Buy Insurance -> SPA -> Ice Scooting -> Complete/Cancel",
605
663
  "node": {
606
664
  "op": "add",
665
+ "bReplace": true,
607
666
  "nodes": [
608
- {
609
- "name": "Start",
610
- "pairs": [
611
- {
612
- "prev_node": "",
613
- "threshold": 0,
614
- "forwards": [
615
- {
616
- "name": "buy_insurance",
617
- "permissionIndex": 1000,
618
- "weight": 1
619
- }
620
- ]
621
- }
622
- ]
623
- },
624
667
  {
625
668
  "name": "Buy Insurance",
626
669
  "pairs": [
627
670
  {
628
- "prev_node": "Start",
671
+ "prev_node": "",
629
672
  "threshold": 1,
630
673
  "forwards": [
631
674
  {
632
- "name": "go_ice_scooting",
633
- "permissionIndex": 1001,
634
- "weight": 1
675
+ "name": "buy_insurance",
676
+ "weight": 1,
677
+ "permissionIndex": 1000
635
678
  }
636
679
  ]
637
680
  }
@@ -645,9 +688,9 @@ Create a Machine to define the travel service workflow with all nodes and forwar
645
688
  "threshold": 1,
646
689
  "forwards": [
647
690
  {
648
- "name": "go_ice_scooting",
649
- "permissionIndex": 1002,
650
- "weight": 1
691
+ "name": "go_spa",
692
+ "weight": 1,
693
+ "permissionIndex": 1001
651
694
  }
652
695
  ]
653
696
  }
@@ -661,19 +704,12 @@ Create a Machine to define the travel service workflow with all nodes and forwar
661
704
  "threshold": 1,
662
705
  "forwards": [
663
706
  {
664
- "name": "complete_trip",
665
- "permissionIndex": 1003,
707
+ "name": "go_ice_scooting",
666
708
  "weight": 1,
667
- "guard": {
668
- "guard": "travel_complete_guard_v1"
669
- }
670
- },
671
- {
672
- "name": "cancel_trip",
673
709
  "permissionIndex": 1004,
674
- "weight": 1,
675
710
  "guard": {
676
- "guard": "travel_cancel_guard_v1"
711
+ "guard": "weather_check_guard",
712
+ "retained_submission": []
677
713
  }
678
714
  }
679
715
  ]
@@ -686,7 +722,17 @@ Create a Machine to define the travel service workflow with all nodes and forwar
686
722
  {
687
723
  "prev_node": "Ice Scooting",
688
724
  "threshold": 1,
689
- "forwards": []
725
+ "forwards": [
726
+ {
727
+ "name": "complete_trip",
728
+ "weight": 1,
729
+ "permissionIndex": 1002,
730
+ "guard": {
731
+ "guard": "travel_complete_guard",
732
+ "retained_submission": []
733
+ }
734
+ }
735
+ ]
690
736
  }
691
737
  ]
692
738
  },
@@ -696,7 +742,17 @@ Create a Machine to define the travel service workflow with all nodes and forwar
696
742
  {
697
743
  "prev_node": "Ice Scooting",
698
744
  "threshold": 1,
699
- "forwards": []
745
+ "forwards": [
746
+ {
747
+ "name": "cancel_trip",
748
+ "weight": 1,
749
+ "permissionIndex": 1003,
750
+ "guard": {
751
+ "guard": "travel_cancel_guard",
752
+ "retained_submission": []
753
+ }
754
+ }
755
+ ]
700
756
  }
701
757
  ]
702
758
  }
@@ -705,136 +761,172 @@ Create a Machine to define the travel service workflow with all nodes and forwar
705
761
  "publish": true
706
762
  },
707
763
  "env": {
708
- "account": "travel_provider_v1",
764
+ "account": "travel_provider",
709
765
  "network": "testnet"
710
766
  }
711
767
  }
712
768
  ```
713
769
 
714
- **Workflow Nodes**:
770
+ **Machine Workflow Diagram**:
771
+
772
+ ```
773
+ ("") --buy_insurance--> [Buy Insurance] --go_spa--> [SPA] --go_ice_scooting--[weather_check]--> [Ice Scooting]
774
+ |
775
+ +--complete_trip--[time-lock]--> [Complete]
776
+ +--cancel_trip-------------> [Cancel]
777
+ ```
778
+
779
+ **Node Pair Structure**:
780
+
781
+ | Node | prev_node | Forward | Permission Index | Guard |
782
+ |------|-----------|---------|-----------------|-------|
783
+ | Buy Insurance | "" (entry) | buy_insurance | 1000 | - |
784
+ | SPA | Buy Insurance | go_spa | 1001 | - |
785
+ | Ice Scooting | SPA | go_ice_scooting | 1004 | weather_check_guard |
786
+ | Complete | Ice Scooting | complete_trip | 1002 | travel_complete_guard |
787
+ | Cancel | Ice Scooting | cancel_trip | 1003 | travel_cancel_guard |
715
788
 
716
- | Node | Forward | Guard | PermissionIndex | Description |
717
- |------|---------|-------|-----------------|-------------|
718
- | Start | buy_insurance -> Buy Insurance | - | 1000 | Enter Start node from initial state |
719
- | Buy Insurance | go_ice_scooting -> SPA | - | 1001 | Proceed to SPA |
720
- | SPA | go_ice_scooting -> Ice Scooting | - | 1002 | Proceed to ice scooting |
721
- | Ice Scooting | complete_trip -> Complete | travel_complete_guard_v1 | 1003 | Complete trip (time-lock) |
722
- | Ice Scooting | cancel_trip -> Cancel | travel_cancel_guard_v1 | 1004 | Cancel trip |
723
- | Complete | (endpoint) | - | - | Final state |
724
- | Cancel | (endpoint) | - | - | Cancelled state |
789
+ > **Note**: The `prev_node` field uses an empty string `""` to denote the entry point. Each node defines how to enter it from a previous node. The `threshold` field (required) specifies the minimum forward weight needed to trigger node advancement.
725
790
 
726
791
  ---
727
792
 
728
793
  ## Step 5: Create and Publish Service
729
794
 
730
- Create the travel service with Machine, Arbitration, sales, and order_allocators, then publish in a single transaction.
795
+ Create the travel service with all configurations and publish it in one operation. The Service requires:
796
+ - Machine binding (must be published first)
797
+ - Sales items (product listing)
798
+ - Arbitration binding
799
+ - Order allocators (fund distribution rules)
800
+ - `pause: false` and `publish: true` to make it active
731
801
 
732
- **Prompt**: Create and publish "travel_service" with all bindings and sales.
802
+ **Prompt**: Create and publish a Service named "travel_service".
733
803
 
734
804
  ```json
735
805
  {
736
806
  "operation_type": "service",
737
807
  "data": {
738
808
  "object": {
739
- "name": "travel_service_v1",
740
- "type_parameter": "0x2::wow::WOW",
741
- "permission": "travel_permission_v1",
809
+ "name": "travel_service",
810
+ "permission": "travel_permission",
742
811
  "replaceExistName": true
743
812
  },
744
- "description": "Iceland travel service: Blue Lagoon SPA + Glacier Ice Scooting. Includes outdoor accident insurance.",
745
- "machine": "travel_machine_v1",
746
- "arbitrations": {
747
- "op": "add",
748
- "objects": ["travel_arbitration_v1"]
749
- },
813
+ "description": "Iceland travel service: Blue Lagoon SPA + Glacier Ice Scooting.",
814
+ "machine": "travel_machine",
750
815
  "sales": {
751
816
  "op": "add",
752
817
  "sales": [
753
818
  {
754
819
  "name": "Iceland Travel Package",
755
- "price": 500000000,
756
- "stock": 100,
820
+ "price": "500000000",
821
+ "stock": "99",
757
822
  "suspension": false,
758
823
  "wip": "",
759
824
  "wip_hash": ""
760
825
  }
761
826
  ]
762
827
  },
828
+ "arbitrations": {
829
+ "op": "add",
830
+ "objects": ["travel_arbitration"]
831
+ },
763
832
  "order_allocators": {
764
- "description": "Travel order revenue allocation",
833
+ "description": "Travel order revenue allocation based on progress state",
765
834
  "threshold": 0,
766
835
  "allocators": [
767
836
  {
768
- "guard": "travel_complete_guard_v1",
837
+ "guard": "merchant_victory_guard",
838
+ "fix": "0",
769
839
  "sharing": [
770
840
  {
771
- "who": {"Signer": "signer"},
841
+ "who": {"Entity": {"name_or_address": "travel_service"}},
772
842
  "sharing": 10000,
773
843
  "mode": "Rate"
774
844
  }
775
845
  ]
846
+ },
847
+ {
848
+ "guard": "no_ice_scooting_guard",
849
+ "fix": "0",
850
+ "sharing": [
851
+ {
852
+ "who": {"Entity": {"name_or_address": "travel_service"}},
853
+ "sharing": 8000,
854
+ "mode": "Rate"
855
+ },
856
+ {
857
+ "who": {"GuardIdentifier": 0},
858
+ "sharing": 2000,
859
+ "mode": "Rate"
860
+ }
861
+ ]
862
+ },
863
+ {
864
+ "guard": "no_spa_guard",
865
+ "fix": "0",
866
+ "sharing": [
867
+ {
868
+ "who": {"Entity": {"name_or_address": "travel_service"}},
869
+ "sharing": 500,
870
+ "mode": "Rate"
871
+ },
872
+ {
873
+ "who": {"GuardIdentifier": 0},
874
+ "sharing": 9500,
875
+ "mode": "Rate"
876
+ }
877
+ ]
776
878
  }
777
879
  ]
778
880
  },
881
+ "pause": false,
779
882
  "publish": true
780
883
  },
781
884
  "env": {
782
- "account": "travel_provider_v1",
885
+ "account": "travel_provider",
783
886
  "network": "testnet"
784
887
  }
785
888
  }
786
889
  ```
787
890
 
788
- > **Note**: The `order_allocators` field is required for publishing a Service. It defines how order revenue is allocated. In this example, we use a simple allocator with the travel_complete_guard.
789
-
790
- ---
791
-
792
- ## Step 6: Unpause Service
793
-
794
- Unpause the service to allow order creation.
891
+ **order_allocators Field Reference**:
795
892
 
796
- **Prompt**: Unpause "travel_service".
797
-
798
- ```json
799
- {
800
- "operation_type": "service",
801
- "data": {
802
- "object": "travel_service",
803
- "pause": false
804
- },
805
- "env": {
806
- "account": "travel_provider_v1",
807
- "network": "testnet"
808
- }
809
- }
810
- ```
893
+ | Field | Type | Description |
894
+ |-------|------|-------------|
895
+ | `description` | string | Description of the allocation strategy |
896
+ | `threshold` | number | Minimum threshold for allocation (0 = no minimum) |
897
+ | `allocators` | array | Array of allocator configurations |
898
+ | `allocators[].guard` | string | Guard name/ID that must pass for this allocation |
899
+ | `allocators[].fix` | string | Fixed amount per recipient ("0" = none) |
900
+ | `allocators[].sharing` | array | Array of sharing rules |
901
+ | `allocators[].sharing[].who` | object | Recipient: `{"Entity": {...}}` for fixed address, `{"GuardIdentifier": N}` for Guard table index, `{"Signer": "signer"}` for caller |
902
+ | `allocators[].sharing[].sharing` | number | Amount in basis points (10000 = 100%) |
903
+ | `allocators[].sharing[].mode` | string | Allocation mode ("Rate" or "Amount") |
811
904
 
812
- ---
905
+ **Recipient Types**:
813
906
 
814
- ## Step 7: Verify Service Configuration
907
+ | Type | Syntax | Resolves To | Use Case |
908
+ |------|--------|-------------|----------|
909
+ | `Entity` | `{"Entity": {"name_or_address": "travel_service"}}` | The named address | Merchant receipts (Service object) |
910
+ | `GuardIdentifier` | `{"GuardIdentifier": 0}` | Address from Guard table index 0 (submitted at runtime) | Customer refunds (Order ID submitted to Guard) |
911
+ | `Signer` | `{"Signer": "signer"}` | The caller of `alloc_by_guard` | When caller should receive all funds |
815
912
 
816
- Query the service to verify all configurations are correct.
913
+ > **Important**: All allocation Guards (merchant_victory_guard, no_ice_scooting_guard, no_spa_guard) have `identifier: 0` as a submission field accepting the Order ID at runtime. `{"GuardIdentifier": 0}` resolves to this submitted Order ID, so funds are sent to the Order object — the customer (Order builder) can then withdraw.
817
914
 
818
- **Prompt**: Query "travel_service" to verify configuration.
915
+ **Allocation Logic**:
819
916
 
820
- ```json
821
- {
822
- "query_type": "onchain_objects",
823
- "objects": ["travel_service"],
824
- "no_cache": true,
825
- "network": "testnet"
826
- }
827
- ```
917
+ | Guard | Condition | Service Receives | Customer Receives |
918
+ |-------|-----------|-----------------|-------------------|
919
+ | merchant_victory_guard | Progress is "Complete" | 100% (Entity → travel_service) | 0% |
920
+ | no_ice_scooting_guard | Progress is "Cancel" or "Ice Scooting" | 80% (Entity → travel_service) | 20% (GuardIdentifier: 0 → Order) |
921
+ | no_spa_guard | Progress is "SPA" | 5% (Entity → travel_service) | 95% (GuardIdentifier: 0 → Order) |
828
922
 
829
923
  ---
830
924
 
831
- ## Step 8: Test Order Creation and Progress
925
+ ## Step 6: Place Order (Customer Purchase)
832
926
 
833
- ### 8.1 Create Travel Order (as Customer Alice)
927
+ The customer (Alice) purchases the travel package. This creates an Order, a Progress (initialized at the entry node ""), and an Allocation object automatically.
834
928
 
835
- Create an order on the travel service as the test customer.
836
-
837
- **Prompt**: Create an order on "travel_service" using account "alice".
929
+ **Prompt**: Alice purchases the Iceland Travel Package from the service.
838
930
 
839
931
  ```json
840
932
  {
@@ -846,312 +938,508 @@ Create an order on the travel service as the test customer.
846
938
  "items": [
847
939
  {
848
940
  "name": "Iceland Travel Package",
849
- "stock": 1,
941
+ "stock": "1",
850
942
  "wip_hash": ""
851
943
  }
852
944
  ],
853
- "total_pay": {
854
- "balance": 500000000
855
- }
945
+ "total_pay": {"balance": "500000000"}
856
946
  },
857
947
  "namedNewOrder": {
858
- "name": "test_travel_order_v1",
948
+ "name": "alice_travel_order",
949
+ "replaceExistName": true
950
+ },
951
+ "namedNewProgress": {
952
+ "name": "alice_travel_progress",
953
+ "replaceExistName": true
954
+ },
955
+ "namedNewAllocation": {
956
+ "name": "alice_travel_allocation",
859
957
  "replaceExistName": true
860
958
  }
861
959
  }
862
960
  },
863
961
  "env": {
864
- "account": "alice_v1",
962
+ "account": "alice",
865
963
  "network": "testnet"
866
964
  }
867
965
  }
868
966
  ```
869
967
 
870
- > **Note**: This creates an Order, Progress, and Allocation. Save the returned object IDs for the next steps.
968
+ > **Note**: The `total_pay.balance` of `500000000` equals 0.5 WOW (1 WOW = 10^9 base units). The customer account must have sufficient balance. The operation creates three named objects: Order, Progress, and Allocation.
969
+
970
+ ---
971
+
972
+ ## Step 7: Progress Operations (Order Workflow)
871
973
 
872
- ### 8.2 Advance Progress: Initial -> Start
974
+ The service provider advances the Progress through the workflow nodes. Each operation moves the Progress from the current node to the next node via a specified forward.
873
975
 
874
- First, advance the progress from initial state to Start node.
976
+ > **Important**: Add `"no_cache": true` to the `env` field for all Progress operations to avoid stale cache issues.
875
977
 
876
- **Prompt**: Advance progress to Start node.
978
+ ### 7.1 Progress to Buy Insurance
979
+
980
+ Move from initial node ("") to "Buy Insurance" node.
981
+
982
+ **Prompt**: Operate progress to move to Buy Insurance node.
877
983
 
878
984
  ```json
879
985
  {
880
986
  "operation_type": "progress",
881
987
  "data": {
882
- "object": "<travel_progress_id>",
988
+ "object": "alice_travel_progress",
883
989
  "operate": {
884
990
  "operation": {
885
- "next_node_name": "Start",
991
+ "next_node_name": "Buy Insurance",
886
992
  "forward": "buy_insurance"
887
993
  }
888
994
  }
889
995
  },
890
996
  "env": {
891
- "account": "travel_provider_v1",
892
- "network": "testnet"
997
+ "account": "travel_provider",
998
+ "network": "testnet",
999
+ "no_cache": true
893
1000
  }
894
1001
  }
895
1002
  ```
896
1003
 
897
- ### 8.3 Advance Progress: Start -> Buy Insurance
1004
+ ### 7.2 Progress to SPA
1005
+
1006
+ Move from "Buy Insurance" to "SPA" node.
898
1007
 
899
- **Prompt**: Advance progress from Start to Buy Insurance.
1008
+ **Prompt**: Operate progress to move to SPA node.
900
1009
 
901
1010
  ```json
902
1011
  {
903
1012
  "operation_type": "progress",
904
1013
  "data": {
905
- "object": "<travel_progress_id>",
1014
+ "object": "alice_travel_progress",
906
1015
  "operate": {
907
1016
  "operation": {
908
- "next_node_name": "Buy Insurance",
909
- "forward": "buy_insurance"
1017
+ "next_node_name": "SPA",
1018
+ "forward": "go_spa"
910
1019
  }
911
1020
  }
912
1021
  },
913
1022
  "env": {
914
- "account": "travel_provider_v1",
915
- "network": "testnet"
1023
+ "account": "travel_provider",
1024
+ "network": "testnet",
1025
+ "no_cache": true
916
1026
  }
917
1027
  }
918
1028
  ```
919
1029
 
920
- ### 8.4 Advance Progress: Buy Insurance -> SPA
1030
+ ### 7.3 Progress to Ice Scooting (with Weather Guard Submission)
921
1031
 
922
- **Prompt**: Advance progress from Buy Insurance to SPA.
1032
+ Move from "SPA" to "Ice Scooting" node. This forward has a Guard (`weather_check_guard`) that verifies weather data exists in the repository for the activity date. You must submit the activity date timestamp (one of the sunny-day timestamps from Step 0.1) at runtime.
1033
+
1034
+ **Prompt**: Operate progress to move to Ice Scooting node with weather Guard submission.
923
1035
 
924
1036
  ```json
925
1037
  {
926
1038
  "operation_type": "progress",
927
1039
  "data": {
928
- "object": "<travel_progress_id>",
1040
+ "object": "alice_travel_progress",
929
1041
  "operate": {
930
1042
  "operation": {
931
- "next_node_name": "SPA",
1043
+ "next_node_name": "Ice Scooting",
932
1044
  "forward": "go_ice_scooting"
933
1045
  }
934
1046
  }
935
1047
  },
1048
+ "submission": {
1049
+ "type": "submission",
1050
+ "guard": [
1051
+ {
1052
+ "object": "weather_check_guard",
1053
+ "impack": true
1054
+ }
1055
+ ],
1056
+ "submission": [
1057
+ {
1058
+ "guard": "weather_check_guard",
1059
+ "submission": [
1060
+ {
1061
+ "identifier": 2,
1062
+ "b_submission": true,
1063
+ "value_type": "U64",
1064
+ "value": <ACTIVITY_DATE_TIMESTAMP>,
1065
+ "name": "Activity date timestamp"
1066
+ }
1067
+ ]
1068
+ }
1069
+ ]
1070
+ },
936
1071
  "env": {
937
- "account": "travel_provider_v1",
938
- "network": "testnet"
1072
+ "account": "travel_provider",
1073
+ "network": "testnet",
1074
+ "no_cache": true
939
1075
  }
940
1076
  }
941
1077
  ```
942
1078
 
943
- ### 8.5 Advance Progress: SPA -> Ice Scooting
1079
+ > **Note**: Replace `<ACTIVITY_DATE_TIMESTAMP>` with one of the sunny-day timestamps from Step 0.1 (e.g., `1783555200000` for Day 1). The timestamp **must exactly match** the `id` used when adding weather data to the repository in Step 0.4 — Repository data is keyed by timestamp, and the Guard queries `repository.data has("Condition", convert_number_address(activity_date))`.
1080
+ >
1081
+ > **Key**: Only `identifier: 2` (the activity date) is submitted at runtime. Identifiers 0 (weather_repo) and 1 ("Condition") are fixed in the Guard table and do not need to be submitted. The `submission` field is at the **top level** of the input (alongside `data` and `env`), NOT inside `data`.
1082
+
1083
+ ### 7.4 Complete Trip (with Guard Submission)
944
1084
 
945
- **Prompt**: Advance progress from SPA to Ice Scooting.
1085
+ Move from "Ice Scooting" to "Complete" node. This forward has a Guard (`travel_complete_guard`) that requires the Order ID to be submitted for time-lock verification.
1086
+
1087
+ **Prompt**: Operate progress to complete the trip with Guard submission.
946
1088
 
947
1089
  ```json
948
1090
  {
949
1091
  "operation_type": "progress",
950
1092
  "data": {
951
- "object": "<travel_progress_id>",
1093
+ "object": "alice_travel_progress",
952
1094
  "operate": {
953
1095
  "operation": {
954
- "next_node_name": "Ice Scooting",
955
- "forward": "go_ice_scooting"
1096
+ "next_node_name": "Complete",
1097
+ "forward": "complete_trip"
956
1098
  }
957
1099
  }
958
1100
  },
1101
+ "submission": {
1102
+ "type": "submission",
1103
+ "guard": [
1104
+ {
1105
+ "object": "travel_complete_guard",
1106
+ "impack": true
1107
+ }
1108
+ ],
1109
+ "submission": [
1110
+ {
1111
+ "guard": "travel_complete_guard",
1112
+ "submission": [
1113
+ {
1114
+ "identifier": 0,
1115
+ "b_submission": true,
1116
+ "value_type": "Address",
1117
+ "value": "<ORDER_OBJECT_ID>",
1118
+ "name": "Order ID"
1119
+ }
1120
+ ]
1121
+ }
1122
+ ]
1123
+ },
959
1124
  "env": {
960
- "account": "travel_provider_v1",
961
- "network": "testnet"
1125
+ "account": "travel_provider",
1126
+ "network": "testnet",
1127
+ "no_cache": true
962
1128
  }
963
1129
  }
964
1130
  ```
965
1131
 
966
- ### 8.6 Advance Progress: Ice Scooting -> Complete (Time-Lock)
1132
+ > **Note**: Replace `<ORDER_OBJECT_ID>` with the actual Order object ID (e.g., `0x7cc9f2228e130c2f6b585bb9c4666fd4d03252d38048355678f46e31b682eb38`). You can query the Progress object to find the `task` field which contains the Order ID.
1133
+ >
1134
+ > **Key**: The `submission` field is at the **top level** of the input (alongside `data` and `env`), NOT inside `data`. The `impack: true` means the Guard verification result affects the final outcome.
967
1135
 
968
- Wait at least 1 second after the last progress update, then advance to Complete with the Order ID as submission.
1136
+ ### 7.5 Cancel Trip (Alternative Path)
969
1137
 
970
- **Prompt**: Advance progress to Complete, submitting the Order ID. Wait 1 second before executing.
1138
+ > **Note**: This is an **alternative** to Step 7.4. Once the trip is Completed, it cannot be Cancelled (and vice versa). Use this path only if cancelling from the "Ice Scooting" node.
1139
+
1140
+ **Prompt**: Operate progress to cancel the trip with Guard submission.
971
1141
 
972
1142
  ```json
973
1143
  {
974
1144
  "operation_type": "progress",
975
1145
  "data": {
976
- "object": "<travel_progress_id>",
1146
+ "object": "alice_travel_progress",
977
1147
  "operate": {
978
1148
  "operation": {
979
- "next_node_name": "Complete",
980
- "forward": "complete_trip"
1149
+ "next_node_name": "Cancel",
1150
+ "forward": "cancel_trip"
981
1151
  }
982
1152
  }
983
1153
  },
1154
+ "submission": {
1155
+ "type": "submission",
1156
+ "guard": [
1157
+ {
1158
+ "object": "travel_cancel_guard",
1159
+ "impack": true
1160
+ }
1161
+ ],
1162
+ "submission": [
1163
+ {
1164
+ "guard": "travel_cancel_guard",
1165
+ "submission": []
1166
+ }
1167
+ ]
1168
+ },
984
1169
  "env": {
985
- "account": "travel_provider_v1",
986
- "network": "testnet"
1170
+ "account": "travel_provider",
1171
+ "network": "testnet",
1172
+ "no_cache": true
1173
+ }
1174
+ }
1175
+ ```
1176
+
1177
+ > **Note**: The `travel_cancel_guard` always passes (returns true), so no submission data is needed. The empty `submission: []` is sufficient.
1178
+
1179
+ **Progress Operation Structure**:
1180
+
1181
+ | Field | Type | Description |
1182
+ |-------|------|-------------|
1183
+ | `data.object` | string | Progress object name/ID |
1184
+ | `data.operate.operation.next_node_name` | string | Target node name to move to |
1185
+ | `data.operate.operation.forward` | string | Forward name defined in Machine |
1186
+ | `submission` | object | Guard verification data (top-level, required when forward has Guard) |
1187
+ | `env.no_cache` | boolean | Set to `true` to avoid stale cache issues |
1188
+
1189
+ ---
1190
+
1191
+ ## Step 8: Execute Fund Allocation
1192
+
1193
+ After the Progress reaches a terminal state (Complete or Cancel), execute the fund allocation. This operation verifies the allocation Guard and distributes funds according to the `order_allocators` configured in Step 5.
1194
+
1195
+ **Anyone can call this operation** — the caller does not need to be the merchant or the customer. The Guard verification determines which allocator's sharing rules apply, and funds are distributed to the recipients defined in those rules.
1196
+
1197
+ ### 8.1 Query the Order ID
1198
+
1199
+ The allocation Guard requires the Order ID as a submission (identifier: 0). Query the Progress object to find the `task` field, which contains the Order ID.
1200
+
1201
+ **Prompt**: Query the Progress object to get the Order ID.
1202
+
1203
+ ```json
1204
+ {
1205
+ "operation_type": "progress",
1206
+ "data": {
1207
+ "object": "alice_travel_progress"
1208
+ },
1209
+ "env": {
1210
+ "network": "testnet",
1211
+ "no_cache": true
1212
+ }
1213
+ }
1214
+ ```
1215
+
1216
+ > **Note**: The response includes a `task` field containing the Order object ID. Copy this value for the allocation submission.
1217
+
1218
+ ### 8.2 Execute Allocation (Merchant Victory Path)
1219
+
1220
+ When the Progress is "Complete", the `merchant_victory_guard` passes, and 100% of funds go to the Service object.
1221
+
1222
+ **Prompt**: Execute fund allocation with the merchant_victory_guard, submitting the Order ID.
1223
+
1224
+ ```json
1225
+ {
1226
+ "operation_type": "allocation",
1227
+ "data": {
1228
+ "object": "alice_travel_allocation",
1229
+ "alloc_by_guard": "merchant_victory_guard"
987
1230
  },
988
1231
  "submission": {
989
1232
  "type": "submission",
990
1233
  "guard": [
991
1234
  {
992
- "object": "travel_complete_guard_v1",
1235
+ "object": "merchant_victory_guard",
993
1236
  "impack": true
994
1237
  }
995
1238
  ],
996
1239
  "submission": [
997
1240
  {
998
- "guard": "travel_complete_guard_v1",
1241
+ "guard": "merchant_victory_guard",
999
1242
  "submission": [
1000
1243
  {
1001
1244
  "identifier": 0,
1002
1245
  "b_submission": true,
1003
1246
  "value_type": "Address",
1004
- "value": "<travel_order_id>"
1247
+ "value": "<ORDER_OBJECT_ID>",
1248
+ "name": "Order ID"
1005
1249
  }
1006
1250
  ]
1007
1251
  }
1008
1252
  ]
1253
+ },
1254
+ "env": {
1255
+ "account": "travel_provider",
1256
+ "network": "testnet",
1257
+ "no_cache": true
1009
1258
  }
1010
1259
  }
1011
1260
  ```
1012
1261
 
1013
- > **Note**: Replace `<travel_progress_id>` and `<travel_order_id>` with actual values from step 8.1.
1262
+ > **Note**: Replace `<ORDER_OBJECT_ID>` with the actual Order object ID from Step 8.1.
1263
+ >
1264
+ > **Two-phase submission**: If the first call returns a submission prompt (without executing), re-call with the `submission` field populated as shown above.
1014
1265
 
1015
- ---
1266
+ ### 8.3 Execute Allocation (Refund Paths)
1016
1267
 
1017
- ## Step 9: Test Weather Check Guard (Optional)
1268
+ For refund scenarios (Cancel or SPA), use the corresponding Guard. The same submission structure applies — the Order ID is submitted to identifier 0.
1018
1269
 
1019
- Test the weather check Guard independently to verify weather data is correctly stored.
1270
+ **Cancel/Ice Scooting path** (80% Service, 20% Order):
1020
1271
 
1021
- **Prompt**: Test "weather_check_guard" with a sunny day timestamp.
1272
+ ```json
1273
+ {
1274
+ "operation_type": "allocation",
1275
+ "data": {
1276
+ "object": "alice_travel_allocation",
1277
+ "alloc_by_guard": "no_ice_scooting_guard"
1278
+ },
1279
+ "submission": {
1280
+ "type": "submission",
1281
+ "guard": [{"object": "no_ice_scooting_guard", "impack": true}],
1282
+ "submission": [{
1283
+ "guard": "no_ice_scooting_guard",
1284
+ "submission": [{"identifier": 0, "b_submission": true, "value_type": "Address", "value": "<ORDER_OBJECT_ID>", "name": "Order ID"}]
1285
+ }]
1286
+ },
1287
+ "env": {"account": "travel_provider", "network": "testnet", "no_cache": true}
1288
+ }
1289
+ ```
1290
+
1291
+ **SPA path** (5% Service, 95% Order):
1022
1292
 
1023
1293
  ```json
1024
1294
  {
1025
- "operation_type": "gen_passport",
1295
+ "operation_type": "allocation",
1026
1296
  "data": {
1027
- "guard": "weather_check_guard",
1028
- "info": {
1029
- "type": "submission",
1030
- "guard": [
1031
- {
1032
- "object": "weather_check_guard",
1033
- "impack": true
1034
- }
1035
- ],
1036
- "submission": [
1037
- {
1038
- "guard": "weather_check_guard",
1039
- "submission": [
1040
- {
1041
- "identifier": 2,
1042
- "b_submission": true,
1043
- "value_type": "U64",
1044
- "value": 1745884800000
1045
- }
1046
- ]
1047
- }
1048
- ]
1049
- }
1297
+ "object": "alice_travel_allocation",
1298
+ "alloc_by_guard": "no_spa_guard"
1050
1299
  },
1051
- "env": {
1052
- "account": "travel_provider_v1",
1053
- "network": "testnet"
1054
- }
1300
+ "submission": {
1301
+ "type": "submission",
1302
+ "guard": [{"object": "no_spa_guard", "impack": true}],
1303
+ "submission": [{
1304
+ "guard": "no_spa_guard",
1305
+ "submission": [{"identifier": 0, "b_submission": true, "value_type": "Address", "value": "<ORDER_OBJECT_ID>", "name": "Order ID"}]
1306
+ }]
1307
+ },
1308
+ "env": {"account": "travel_provider", "network": "testnet", "no_cache": true}
1055
1309
  }
1056
1310
  ```
1057
1311
 
1058
- > **Note**: Replace the timestamp with one of the sunny day timestamps from step 0.1 (DAY1-DAY4). This should pass.
1312
+ ### 8.4 Verify Allocation Result
1059
1313
 
1060
- Test with a rainy day to verify rejection:
1314
+ After allocation, query the Allocation and Payment objects to verify the fund distribution.
1061
1315
 
1062
- **Prompt**: Test "weather_check_guard" with a rainy day timestamp.
1316
+ **Prompt**: Query the Allocation object to verify the balance and payment records.
1063
1317
 
1064
1318
  ```json
1065
1319
  {
1066
- "operation_type": "gen_passport",
1320
+ "operation_type": "allocation",
1067
1321
  "data": {
1068
- "guard": "weather_check_guard",
1069
- "info": {
1070
- "type": "submission",
1071
- "guard": [
1072
- {
1073
- "object": "weather_check_guard",
1074
- "impack": true
1075
- }
1076
- ],
1077
- "submission": [
1078
- {
1079
- "guard": "weather_check_guard",
1080
- "submission": [
1081
- {
1082
- "identifier": 2,
1083
- "b_submission": true,
1084
- "value_type": "U64",
1085
- "value": 1746230400000
1086
- }
1087
- ]
1088
- }
1089
- ]
1090
- }
1322
+ "object": "alice_travel_allocation"
1091
1323
  },
1092
1324
  "env": {
1093
- "account": "travel_provider_v1",
1094
- "network": "testnet"
1325
+ "network": "testnet",
1326
+ "no_cache": true
1095
1327
  }
1096
1328
  }
1097
1329
  ```
1098
1330
 
1099
- > **Note**: Replace the timestamp with the rainy day timestamp (DAY5). This should fail because the weather is "rainy", not "sunny".
1331
+ > **Expected result**: The Allocation `balance` should be 0 (all funds distributed), and the `payment` array should contain the Payment object ID(s) created by the allocation.
1100
1332
 
1101
- ---
1333
+ **Allocation Operation Structure**:
1334
+
1335
+ | Field | Type | Description |
1336
+ |-------|------|-------------|
1337
+ | `data.object` | string | Allocation object name/ID |
1338
+ | `data.alloc_by_guard` | string | Guard name/ID to verify (determines which allocator's rules apply) |
1339
+ | `submission` | object | Guard submission data (Order ID at identifier 0) |
1340
+ | `env.no_cache` | boolean | Set to `true` to avoid stale cache issues |
1102
1341
 
1103
- ## Execution Checklist
1104
-
1105
- - [ ] Create `travel_provider`, `weather_provider`, `alice` accounts
1106
- - [ ] Get test tokens for all accounts
1107
- - [ ] Step 0.1: Calculate weather timestamps
1108
- - [ ] Step 0.2: Create `weather_repo` Repository
1109
- - [ ] Step 0.3: Add "Condition" policy to repository
1110
- - [ ] Step 0.4: Add weather data (5 days)
1111
- - [ ] Step 1: Create `travel_permission`
1112
- - [ ] Step 2: Create `travel_arbitration`
1113
- - [ ] Step 3.1: Create `weather_check_guard` (update weather_repo address)
1114
- - [ ] Step 3.2: Create `travel_complete_guard`
1115
- - [ ] Step 3.3: Create `travel_cancel_guard`
1116
- - [ ] Step 4: Create `travel_machine` (with nodes including Complete/Cancel, published)
1117
- - [ ] Step 5: Create and publish `travel_service` (with machine, arbitration, sales, order_allocators)
1118
- - [ ] Step 6: Unpause Service
1119
- - [ ] Step 7: Verify Service configuration
1120
- - [ ] Step 8.1: Create test travel order (as alice)
1121
- - [ ] Step 8.2: Advance Initial -> Start
1122
- - [ ] Step 8.3: Advance Start -> Buy Insurance
1123
- - [ ] Step 8.4: Advance Buy Insurance -> SPA
1124
- - [ ] Step 8.5: Advance SPA -> Ice Scooting
1125
- - [ ] Step 8.6: Wait 1s, advance Ice Scooting -> Complete
1126
- - [ ] Step 9: Test weather check Guard (sunny passes, rainy fails)
1342
+ > **Important**: `alloc_by_guard` accepts Guard names (e.g., `"merchant_victory_guard"`) or Guard object IDs. The Guard must exist in the Allocation's `allocators` list. Only the first Guard that passes (first-Guard-wins) triggers fund distribution.
1127
1343
 
1128
1344
  ---
1129
1345
 
1130
1346
  ## Best Practices
1131
1347
 
1132
- ### 1. Machine Node Configuration
1348
+ ### 1. Guard Root Format
1133
1349
 
1134
- Ensure at least one node has a pair with `prev_node: ""` (empty string). This defines the entry point from the initial state where Progress starts with `current: ""`.
1350
+ Guards use a direct GuardNode as the `root` field no wrapper needed:
1351
+ ```json
1352
+ "root": {
1353
+ "type": "logic_equal",
1354
+ "nodes": [...]
1355
+ }
1356
+ ```
1135
1357
 
1136
- ### 2. Service Publish Requires order_allocators
1358
+ ### 2. Machine Node Structure
1137
1359
 
1138
- Always include the `order_allocators` field when publishing a Service. This defines how order revenue is distributed.
1360
+ Each node's `pairs` define how to **enter** that node. The `prev_node` specifies the source, and `forwards` are the operations to advance:
1361
+ ```json
1362
+ {
1363
+ "name": "TargetNode",
1364
+ "pairs": [{
1365
+ "prev_node": "SourceNode",
1366
+ "threshold": 1,
1367
+ "forwards": [{"name": "forward_name", "weight": 1, "permissionIndex": 1000}]
1368
+ }]
1369
+ }
1370
+ ```
1139
1371
 
1140
- ### 3. Progress Operation Format
1372
+ - Use `prev_node` (not `prior_node`)
1373
+ - `threshold` is required for every pair
1374
+ - Consolidate forwards with the same `prev_node` into one pair
1141
1375
 
1142
- Use the `operate` field with `operation` object containing `next_node_name` and `forward`, not the `task` field.
1376
+ ### 3. Machine Publish Before Service
1143
1377
 
1144
- ### 4. Repository Data Policy
1378
+ The Machine must be published (`"publish": true`) before binding it to a Service. Unpublished Machines cannot be referenced by Services.
1145
1379
 
1146
- When creating a Repository, include policies in the initial `policies` field instead of adding them later (this avoids "Invalid policy name" errors).
1380
+ ### 4. Service Creation in One Step
1147
1381
 
1148
- ### 5. Submission Format
1382
+ Create the Service with all configurations — including `pause: false` and `publish: true` — in a single operation:
1383
+ ```json
1384
+ {
1385
+ "pause": false,
1386
+ "publish": true,
1387
+ "order_allocators": {...},
1388
+ "sales": {...},
1389
+ "machine": "...",
1390
+ "arbitrations": {...}
1391
+ }
1392
+ ```
1149
1393
 
1150
- Ensure submission items include `b_submission: true` for values submitted at runtime during progress advancement.
1394
+ ### 5. Guard Submission for Progress
1151
1395
 
1152
- ---
1396
+ When a forward has a Guard, the Progress operation requires a `submission` field at the **top level** (not inside `data`):
1397
+ ```json
1398
+ {
1399
+ "operation_type": "progress",
1400
+ "data": {...},
1401
+ "submission": {
1402
+ "type": "submission",
1403
+ "guard": [{"object": "guard_name", "impack": true}],
1404
+ "submission": [{
1405
+ "guard": "guard_name",
1406
+ "submission": [{"identifier": 0, "b_submission": true, "value_type": "Address", "value": "0x...", "name": "Order ID"}]
1407
+ }]
1408
+ },
1409
+ "env": {"no_cache": true, ...}
1410
+ }
1411
+ ```
1412
+
1413
+ ### 6. Cache Management
1414
+
1415
+ Add `"no_cache": true` to the `env` field for all Progress operations and queries after mutations to avoid stale cache issues.
1153
1416
 
1154
- ## See Also
1417
+ ### 7. Weather Data Timestamps
1155
1418
 
1156
- - [Insurance Example](../Insurance/Insurance.md) - The insurance service used as sub-order
1157
- - [WOWOK Documentation](../../skills/WOWOK.md) - Core WoWok protocol documentation
1419
+ Weather data in the Repository is keyed by timestamp (`id`). The `weather_check_guard` queries `repository.data has("Condition", convert_number_address(activity_date))` the `activity_date` submitted at runtime in Step 7.3 **must exactly match** the `id` used when adding data in Step 0.4.
1420
+
1421
+ - Always align timestamps to UTC 00:00:00 (`Math.floor(now / DAY_MS) * DAY_MS`) so they are reproducible.
1422
+ - Re-run `calc-weather-timestamps.js` at test time — the values depend on the current date.
1423
+ - The Guard only checks data **existence**, not the condition value. A "rainy" day will still pass. To reject by condition value, use a Guard querying `repository.data` with a value comparison.
1424
+
1425
+ ### 8. Order Placement
1426
+
1427
+ Customers place orders using the `order_new` field in the Service operation. This automatically creates Order, Progress, and Allocation objects:
1428
+ ```json
1429
+ {
1430
+ "operation_type": "service",
1431
+ "data": {
1432
+ "object": "service_name",
1433
+ "order_new": {
1434
+ "buy": {
1435
+ "items": [{"name": "Product", "stock": "1", "wip_hash": ""}],
1436
+ "total_pay": {"balance": "price_amount"}
1437
+ },
1438
+ "namedNewOrder": {"name": "order_name", "replaceExistName": true},
1439
+ "namedNewProgress": {"name": "progress_name", "replaceExistName": true},
1440
+ "namedNewAllocation": {"name": "allocation_name", "replaceExistName": true}
1441
+ }
1442
+ },
1443
+ "env": {"account": "customer", "network": "testnet"}
1444
+ }
1445
+ ```