@wowok/skills 2.2.2 → 2.2.4
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/README.md +2 -2
- package/dist/skills.d.ts +3 -3
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +182 -10
- package/dist/skills.js.map +1 -1
- package/examples/Insurance/Insurance.md +77 -5
- package/examples/MyShop/MyShop.md +72 -35
- package/examples/ThreeBody_Signature/ThreeBody_Signature.md +91 -18
- package/examples/Travel/Travel.md +17 -25
- package/package.json +1 -1
- package/scripts/install.js +2 -2
- package/wowok-arbitrator/SKILL.md +4 -4
- package/wowok-auditor/SKILL.md +3 -3
- package/wowok-collaborator/SKILL.md +2 -2
- package/wowok-machine/SKILL.md +9 -9
- package/wowok-messenger/SKILL.md +1 -1
- package/wowok-onboard/SKILL.md +13 -13
- package/wowok-order/SKILL.md +4 -4
- package/wowok-output/SKILL.md +74 -33
- package/wowok-planner/SKILL.md +2 -2
- package/wowok-provider/SKILL.md +21 -21
- package/wowok-supplier/SKILL.md +4 -4
|
@@ -8,7 +8,7 @@ A complete e-commerce example demonstrating how to build an online store using W
|
|
|
8
8
|
|
|
9
9
|
> **Run the example in full every time (repeatable).** This example uses `replaceExistName: true` on all object creations — each run generates new objects with new addresses. If you skip build steps, operations may silently act on orphaned objects from previous runs, producing incorrect results. Old objects' configurations do not reflect the current document version.
|
|
10
10
|
|
|
11
|
-
- **Execution order**: Part 1 (Merchant Setup, Steps 1–
|
|
11
|
+
- **Execution order**: Part 1 (Merchant Setup, Steps 1–8) → Part 2 (Customer Flow, Steps 1–9). Run all build steps in sequence before testing any customer flow. Do not skip steps — each depends on objects created by prior steps.
|
|
12
12
|
- **Prerequisites**: `myshop_merchant` with sufficient WOW for gas and order operations. All on-chain operations require `env.confirmed: true`.
|
|
13
13
|
|
|
14
14
|
> **💡 Call Format**: All WoWok operations go through a single unified `wowok` tool. The AI calls `wowok({ tool: "<sub-tool>", data: {<params>} })`. If parameters don't match the schema, the response includes the correct schema for self-correction. See [Response Format](../../docs/response-format.md) for details.
|
|
@@ -426,6 +426,8 @@ Create a Contact object to enable encrypted communication between customers and
|
|
|
426
426
|
}
|
|
427
427
|
```
|
|
428
428
|
|
|
429
|
+
> **Note**: Enabling messenger now registers the account on the messenger server **immediately and synchronously** — each account registers itself (its own identity, its own keys). The result includes `registered: true` on success, or `registered: false` with `registerError` if the server is unreachable (the background refresh retries automatically every 60s). If the operation result shows `registered: false`, retry the enable operation before proceeding — otherwise the counterpart's first message will fail with "Recipient not registered".
|
|
430
|
+
|
|
429
431
|
#### 4.2 Create After-Sales Contact Object
|
|
430
432
|
|
|
431
433
|
**Prompt**: Create a Contact object named "myshop_aftersales_contact_v2" with permission "myshop_permission_v2" for after-sales support.
|
|
@@ -465,11 +467,53 @@ Create a Contact object to enable encrypted communication between customers and
|
|
|
465
467
|
|
|
466
468
|
---
|
|
467
469
|
|
|
468
|
-
### Step 5: Create
|
|
470
|
+
### Step 5: Create Service (Store) DRAFT
|
|
471
|
+
|
|
472
|
+
> **⚠️ Order matters — Service DRAFT must be created BEFORE the Guards.** The Guards in Step 6 reference the Service by name (`myshop_service_v2` as an Address table value). The SDK resolves the name to the on-chain address AT Guard creation time. If the Service does not exist yet, Guard creation aborts with:
|
|
473
|
+
> ```
|
|
474
|
+
> Error: invalid parameter:BCS serialization failed: ... failed to resolve string: myshop_service_v2. Address may not exist in local accounts or marks.
|
|
475
|
+
> ```
|
|
476
|
+
> Create the Service as an unpublished DRAFT here so the name resolves, then bind machine/allocators/sales and publish it in Step 7.
|
|
477
|
+
|
|
478
|
+
**Prompt**: Create an unpublished Service DRAFT named "myshop_service_v2" (no `publish` field — it stays a DRAFT so Guards can reference it and the mutable fields can still be configured).
|
|
479
|
+
|
|
480
|
+
```json
|
|
481
|
+
{
|
|
482
|
+
"tool": "onchain_operations",
|
|
483
|
+
"data": {
|
|
484
|
+
"operation_type": "service",
|
|
485
|
+
"data": {
|
|
486
|
+
"object": {
|
|
487
|
+
"name": "myshop_service_v2",
|
|
488
|
+
"type_parameter": "0x2::wow::WOW",
|
|
489
|
+
"permission": "myshop_permission_v2",
|
|
490
|
+
"tags": ["ecommerce", "toys", "store"],
|
|
491
|
+
"onChain": false,
|
|
492
|
+
"replaceExistName": true
|
|
493
|
+
},
|
|
494
|
+
"description": "MyShop - Top quality toys for children",
|
|
495
|
+
"location": "Online Store"
|
|
496
|
+
},
|
|
497
|
+
"env": {
|
|
498
|
+
"account": "myshop_merchant",
|
|
499
|
+
"network": "mainnet",
|
|
500
|
+
"confirmed": true
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
> **Note**: After publishing, `machine`, `order_allocators`, and `arbitrations` become **immutable**. Creating the draft first lets the Guards resolve the Service name while the Service is still configurable.
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
### Step 6: Create Guards for Fund Allocation
|
|
511
|
+
|
|
512
|
+
Before publishing the Service, create Guards that validate fund allocation conditions. These Guards ensure funds are only released when specific conditions are met. The Guards reference the Service DRAFT by name (`myshop_service_v2`), which now resolves to the draft's on-chain address (the address does NOT change when the draft is later published).
|
|
469
513
|
|
|
470
|
-
|
|
514
|
+
> **Note**: Guard table item `name` must be ≤ 64 characters (`MAX_NAME_LENGTH`) and must NOT start with `0x`. Descriptive names with spaces/parentheses (e.g. `order_address (Order object submitted at runtime)`) exceed the limit and abort with `invalid parameter:table.name`. Use short identifiers like `order_address`.
|
|
471
515
|
|
|
472
|
-
####
|
|
516
|
+
#### 6.1 Create Withdraw Guard (Merchant Withdrawal)
|
|
473
517
|
|
|
474
518
|
Create a Guard that validates the order's Progress has reached the "Completed" node. This Guard uses `convert_witness: "OrderProgress"` (TypeOrderProgress) to query the Order's associated Progress object.
|
|
475
519
|
|
|
@@ -493,28 +537,28 @@ Create a Guard that validates the order's Progress has reached the "Completed" n
|
|
|
493
537
|
"identifier": 0,
|
|
494
538
|
"b_submission": true,
|
|
495
539
|
"value_type": "Address",
|
|
496
|
-
"name": "order_address
|
|
540
|
+
"name": "order_address"
|
|
497
541
|
},
|
|
498
542
|
{
|
|
499
543
|
"identifier": 1,
|
|
500
544
|
"b_submission": false,
|
|
501
545
|
"value_type": "String",
|
|
502
546
|
"value": "Completed",
|
|
503
|
-
"name": "
|
|
547
|
+
"name": "expected_node"
|
|
504
548
|
},
|
|
505
549
|
{
|
|
506
550
|
"identifier": 2,
|
|
507
551
|
"b_submission": false,
|
|
508
552
|
"value_type": "Address",
|
|
509
553
|
"value": "myshop_merchant",
|
|
510
|
-
"name": "
|
|
554
|
+
"name": "merchant_address"
|
|
511
555
|
},
|
|
512
556
|
{
|
|
513
557
|
"identifier": 3,
|
|
514
558
|
"b_submission": false,
|
|
515
559
|
"value_type": "Address",
|
|
516
560
|
"value": "myshop_service_v2",
|
|
517
|
-
"name": "
|
|
561
|
+
"name": "service_address"
|
|
518
562
|
}
|
|
519
563
|
],
|
|
520
564
|
"root": {
|
|
@@ -594,7 +638,7 @@ Create a Guard that validates the order's Progress has reached the "Completed" n
|
|
|
594
638
|
>
|
|
595
639
|
> **Note**: The Guard `root` field directly specifies the GuardNode (e.g., `type: "logic_and"`), not wrapped in a `type: "node"` object.
|
|
596
640
|
|
|
597
|
-
####
|
|
641
|
+
#### 6.2 Create Refund Guard (Customer Refund)
|
|
598
642
|
|
|
599
643
|
Create a Guard for customer refunds when order is cancelled.
|
|
600
644
|
|
|
@@ -618,21 +662,21 @@ Create a Guard for customer refunds when order is cancelled.
|
|
|
618
662
|
"identifier": 0,
|
|
619
663
|
"b_submission": true,
|
|
620
664
|
"value_type": "Address",
|
|
621
|
-
"name": "order_address
|
|
665
|
+
"name": "order_address"
|
|
622
666
|
},
|
|
623
667
|
{
|
|
624
668
|
"identifier": 1,
|
|
625
669
|
"b_submission": false,
|
|
626
670
|
"value_type": "String",
|
|
627
671
|
"value": "Cancelled",
|
|
628
|
-
"name": "
|
|
672
|
+
"name": "expected_node"
|
|
629
673
|
},
|
|
630
674
|
{
|
|
631
675
|
"identifier": 2,
|
|
632
676
|
"b_submission": false,
|
|
633
677
|
"value_type": "Address",
|
|
634
678
|
"value": "myshop_service_v2",
|
|
635
|
-
"name": "
|
|
679
|
+
"name": "service_address"
|
|
636
680
|
}
|
|
637
681
|
],
|
|
638
682
|
"root": {
|
|
@@ -717,13 +761,13 @@ Create a Guard for customer refunds when order is cancelled.
|
|
|
717
761
|
|
|
718
762
|
---
|
|
719
763
|
|
|
720
|
-
### Step
|
|
764
|
+
### Step 7: Publish Service (Store)
|
|
721
765
|
|
|
722
|
-
|
|
766
|
+
Bind all previously created components (machine, Guards, products, after-sales contact) to the Service DRAFT created in Step 5, then publish it. The Service address stays the same as the DRAFT, so the Guards' `service_address` table values remain valid.
|
|
723
767
|
|
|
724
|
-
> **Important**:
|
|
768
|
+
> **Important**: Provide a complete configuration including machine, order_allocators with Guards, and products. The Service is published in a single transaction. After publish, `machine`, `order_allocators`, and `arbitrations` become immutable.
|
|
725
769
|
|
|
726
|
-
####
|
|
770
|
+
#### 7.1 Understanding Order Allocators
|
|
727
771
|
|
|
728
772
|
The `order_allocators` configuration defines how order payments are distributed:
|
|
729
773
|
|
|
@@ -747,9 +791,9 @@ The `order_allocators` configuration defines how order payments are distributed:
|
|
|
747
791
|
|
|
748
792
|
> **Design Decision — Refund Recipient**: When using `{ "GuardIdentifier": 0 }` in the refund allocation, the refund is sent to the **Order object's on-chain address** (not the customer's wallet address). This is by design: the Order object acts as an escrow holding the refunded payment at its own address. The customer subsequently claims the refund from the Order object via a separate withdraw operation. This two-step design ensures the refund is traceable on-chain and tied to the specific order, providing better dispute resolution and audit trail.
|
|
749
793
|
|
|
750
|
-
####
|
|
794
|
+
#### 7.2 Publish Service (bind machine + allocators + sales + um)
|
|
751
795
|
|
|
752
|
-
**Prompt**:
|
|
796
|
+
**Prompt**: Publish the Service DRAFT "myshop_service_v2" (created in Step 5) by binding machine "myshop_machine_v2", order allocation using the Guards, after-sales contact, and toy products. Note `object` is now a STRING reference to the existing draft, and `publish: true` is set.
|
|
753
797
|
|
|
754
798
|
```json
|
|
755
799
|
{
|
|
@@ -757,16 +801,7 @@ The `order_allocators` configuration defines how order payments are distributed:
|
|
|
757
801
|
"data": {
|
|
758
802
|
"operation_type": "service",
|
|
759
803
|
"data": {
|
|
760
|
-
"object":
|
|
761
|
-
"name": "myshop_service_v2",
|
|
762
|
-
"type_parameter": "0x2::wow::WOW",
|
|
763
|
-
"permission": "myshop_permission_v2",
|
|
764
|
-
"tags": ["ecommerce", "toys", "store"],
|
|
765
|
-
"onChain": false,
|
|
766
|
-
"replaceExistName": true
|
|
767
|
-
},
|
|
768
|
-
"description": "MyShop - Top quality toys for children",
|
|
769
|
-
"location": "Online Store",
|
|
804
|
+
"object": "myshop_service_v2",
|
|
770
805
|
"machine": "myshop_machine_v2",
|
|
771
806
|
"order_allocators": {
|
|
772
807
|
"description": "Order revenue allocation - merchant withdraw after completion",
|
|
@@ -802,7 +837,7 @@ The `order_allocators` configuration defines how order payments are distributed:
|
|
|
802
837
|
"price": 50000000,
|
|
803
838
|
"stock": 100,
|
|
804
839
|
"suspension": false,
|
|
805
|
-
"wip": "https://
|
|
840
|
+
"wip": "https://raw.githubusercontent.com/wowok-ai/docs/main/wip-examples/three_body.wip",
|
|
806
841
|
"wip_hash": ""
|
|
807
842
|
},
|
|
808
843
|
{
|
|
@@ -810,7 +845,7 @@ The `order_allocators` configuration defines how order payments are distributed:
|
|
|
810
845
|
"price": 50000000,
|
|
811
846
|
"stock": 50,
|
|
812
847
|
"suspension": false,
|
|
813
|
-
"wip": "https://
|
|
848
|
+
"wip": "https://raw.githubusercontent.com/wowok-ai/docs/main/wip-examples/three_body.wip",
|
|
814
849
|
"wip_hash": ""
|
|
815
850
|
},
|
|
816
851
|
{
|
|
@@ -818,7 +853,7 @@ The `order_allocators` configuration defines how order payments are distributed:
|
|
|
818
853
|
"price": 30000000,
|
|
819
854
|
"stock": 75,
|
|
820
855
|
"suspension": false,
|
|
821
|
-
"wip": "https://
|
|
856
|
+
"wip": "https://raw.githubusercontent.com/wowok-ai/docs/main/wip-examples/three_body.wip",
|
|
822
857
|
"wip_hash": ""
|
|
823
858
|
}
|
|
824
859
|
]
|
|
@@ -842,7 +877,7 @@ The `order_allocators` configuration defines how order payments are distributed:
|
|
|
842
877
|
|
|
843
878
|
---
|
|
844
879
|
|
|
845
|
-
### Step
|
|
880
|
+
### Step 8: Update Product Pricing (Optional)
|
|
846
881
|
|
|
847
882
|
To offer promotional pricing, update product prices using the `sales` operation with `op: "set"`:
|
|
848
883
|
|
|
@@ -863,7 +898,7 @@ To offer promotional pricing, update product prices using the `sales` operation
|
|
|
863
898
|
"price": 40000000,
|
|
864
899
|
"stock": 100,
|
|
865
900
|
"suspension": false,
|
|
866
|
-
"wip": "https://
|
|
901
|
+
"wip": "https://raw.githubusercontent.com/wowok-ai/docs/main/wip-examples/three_body.wip",
|
|
867
902
|
"wip_hash": ""
|
|
868
903
|
}
|
|
869
904
|
]
|
|
@@ -963,7 +998,7 @@ Customer creates an order by purchasing products from the Service.
|
|
|
963
998
|
{
|
|
964
999
|
"name": "Play Purse Set 35PCS",
|
|
965
1000
|
"stock": 1,
|
|
966
|
-
"wip_hash": "
|
|
1001
|
+
"wip_hash": "<wip_hash captured from Step 1 query>"
|
|
967
1002
|
}
|
|
968
1003
|
],
|
|
969
1004
|
"total_pay": {
|
|
@@ -1053,6 +1088,8 @@ After creating the order, the customer sends their shipping address and contact
|
|
|
1053
1088
|
}
|
|
1054
1089
|
```
|
|
1055
1090
|
|
|
1091
|
+
> **Note**: Same as merchant enable (Step 4.1): registration on the messenger server happens synchronously with the enable. Each party must enable messenger **in its own environment with its own account** — one side can never register the other.
|
|
1092
|
+
|
|
1056
1093
|
#### 2.1.2 Customer Sends Shipping Information
|
|
1057
1094
|
|
|
1058
1095
|
**Prompt**: Customer "myshop_customer" sends shipping address and contact information to merchant "myshop_merchant" via encrypted messenger.
|
|
@@ -1691,7 +1728,7 @@ Create a new order for testing the arbitration flow (if you don't have one alrea
|
|
|
1691
1728
|
{
|
|
1692
1729
|
"name": "Tree House Building Set",
|
|
1693
1730
|
"stock": 1,
|
|
1694
|
-
"wip_hash": "
|
|
1731
|
+
"wip_hash": "<wip_hash captured from Step 1 query>"
|
|
1695
1732
|
}
|
|
1696
1733
|
],
|
|
1697
1734
|
"total_pay": {"balance": 30000000}
|
|
@@ -18,7 +18,7 @@ This example sets `env.confirmed: true` on irreversible operations (e.g., `publi
|
|
|
18
18
|
1. **Phase 1 — Preview**: Call the tool **without** `env.confirmed`. The server returns `{ status: "pending_confirmation", confirmation_text: "..." }` containing the full operation summary, risk assessment, and irreversible-action warnings.
|
|
19
19
|
2. **Phase 2 — Confirm**: Review `confirmation_text` with the user. Only after explicit user approval, call the tool again **with** `env.confirmed: true` to actually execute the on-chain transaction.
|
|
20
20
|
|
|
21
|
-
> Skipping Phase 1 means the user never sees the risk summary before gas is spent. Always preview first, then confirm. This is especially critical for the two `publish: true` steps in this doc: the Machine publish (**Step 3**), which irreversibly locks the workflow definition (`nodes`/`pairs`/`forwards`), and the Service publish (**Step
|
|
21
|
+
> Skipping Phase 1 means the user never sees the risk summary before gas is spent. Always preview first, then confirm. This is especially critical for the two `publish: true` steps in this doc: the Machine publish (**Step 3**), which irreversibly locks the workflow definition (`nodes`/`pairs`/`forwards`), and the Service publish (**Step 11**), which irreversibly locks the `machine` and `order_allocators` fields.
|
|
22
22
|
|
|
23
23
|
> **💡 Call Format**: All WoWok operations go through a single unified `wowok` tool. The AI calls `wowok({ tool: "<sub-tool>", data: {<params>} })`. If parameters don't match the schema, the response includes the correct schema for self-correction. See [Response Format](../../docs/response-format.md) for details.
|
|
24
24
|
>
|
|
@@ -719,7 +719,70 @@ Create a Treasury object to aggregate signature service revenue (public funds fo
|
|
|
719
719
|
|
|
720
720
|
---
|
|
721
721
|
|
|
722
|
-
## Step 8: Create
|
|
722
|
+
## Step 8: Create Contact Object (Customer-Service Channel)
|
|
723
|
+
|
|
724
|
+
Create a Contact object to serve as the Service's encrypted customer-service channel. **Whenever `customer_required` is set (e.g. phone/email/shipping address), a Contact MUST be bound via the `um` field** — the customer's private information is delivered exclusively through end-to-end encrypted Messenger, which routes messages to the Contact bound as `um`. Without `um`, there is no channel to receive the customer's privacy-sensitive input and the SDK blocks the call with an invalid parameter error. The Contact uses the same Permission as the Service (`three_body_permission`) for unified governance.
|
|
725
|
+
|
|
726
|
+
**Request**:
|
|
727
|
+
```json
|
|
728
|
+
{
|
|
729
|
+
"tool": "onchain_operations",
|
|
730
|
+
"data": {
|
|
731
|
+
"operation_type": "contact",
|
|
732
|
+
"data": {
|
|
733
|
+
"object": {
|
|
734
|
+
"name": "three_body_contact",
|
|
735
|
+
"permission": "three_body_permission",
|
|
736
|
+
"replaceExistName": true
|
|
737
|
+
},
|
|
738
|
+
"description": "Contact for Three-Body signature service customer info — end-to-end encrypted Messenger channel for delivery of phone/email/shipping_address collected via customer_required."
|
|
739
|
+
},
|
|
740
|
+
"env": {
|
|
741
|
+
"account": "three_body_author",
|
|
742
|
+
"network": "testnet",
|
|
743
|
+
"confirmed": true
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
> **Why a Contact is required with customer_required (SDK-enforced hard linkage)**:
|
|
750
|
+
> - `customer_required` tells the order flow which private-info labels to collect from the buyer (phone, email, shipping_address, etc.)
|
|
751
|
+
> - Those labels are delivered to the merchant ONLY through the end-to-end encrypted Messenger protocol
|
|
752
|
+
> - Messenger routes messages to the Service's bound Contact object (the `um` field)
|
|
753
|
+
> - Without `um`, the collected private information would be silently dropped — there is no other delivery path
|
|
754
|
+
> - The SDK's `checkCustomerRequiredNeedsUm()` validator in `service.ts` (L1226) runs on EVERY service operation that touches `customer_required` AND on `publish: true`, so the constraint cannot be bypassed by splitting into two calls
|
|
755
|
+
|
|
756
|
+
> **Important**: `env.confirmed: true` is required because `replaceExistName: true` triggers a confirmation prompt.
|
|
757
|
+
|
|
758
|
+
**Expected Result**:
|
|
759
|
+
```json
|
|
760
|
+
{
|
|
761
|
+
"result": {
|
|
762
|
+
"status": "success",
|
|
763
|
+
"data": {
|
|
764
|
+
"result": {
|
|
765
|
+
"type": "transaction",
|
|
766
|
+
"objectChanges": [
|
|
767
|
+
{
|
|
768
|
+
"type": "Contact",
|
|
769
|
+
"type_raw": "0x2::contact::Contact",
|
|
770
|
+
"object": "0x...",
|
|
771
|
+
"version": "...",
|
|
772
|
+
"owner": {"Shared": {"initial_shared_version": "..."}},
|
|
773
|
+
"change": "created"
|
|
774
|
+
}
|
|
775
|
+
]
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
},
|
|
779
|
+
"schema": null
|
|
780
|
+
}
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
---
|
|
784
|
+
|
|
785
|
+
## Step 9: Create Allocator Guard
|
|
723
786
|
|
|
724
787
|
Create a dedicated Guard for the order allocator that verifies the order belongs to this service. This is a **Level 3 scene-combined** Guard: no Signer binding is needed because the allocator uses `sharing.who=Entity(three_body_treasury)` — funds always flow to the fixed Treasury regardless of who triggers the allocation.
|
|
725
788
|
|
|
@@ -819,9 +882,9 @@ order.service == three_body_signature_service
|
|
|
819
882
|
|
|
820
883
|
---
|
|
821
884
|
|
|
822
|
-
## Step
|
|
885
|
+
## Step 10: Configure Order Allocators
|
|
823
886
|
|
|
824
|
-
Set up fund allocation: 100% to the author's Treasury upon order completion.
|
|
887
|
+
Set up fund allocation: 100% to the author's Treasury upon order completion. Also bind the Contact (Step 8) as `um` to enable the `customer_required` private-info delivery channel — the SDK blocks `customer_required` without a matching `um` (see Step 8 for the rationale).
|
|
825
888
|
|
|
826
889
|
**Request**:
|
|
827
890
|
```json
|
|
@@ -849,7 +912,8 @@ Set up fund allocation: 100% to the author's Treasury upon order completion.
|
|
|
849
912
|
}
|
|
850
913
|
]
|
|
851
914
|
},
|
|
852
|
-
"customer_required": ["phone", "email", "shipping_address"]
|
|
915
|
+
"customer_required": ["phone", "email", "shipping_address"],
|
|
916
|
+
"um": "three_body_contact"
|
|
853
917
|
},
|
|
854
918
|
"env": {
|
|
855
919
|
"account": "three_body_author",
|
|
@@ -860,9 +924,10 @@ Set up fund allocation: 100% to the author's Treasury upon order completion.
|
|
|
860
924
|
```
|
|
861
925
|
|
|
862
926
|
> **⚠️ Risk Elimination — Why this configuration is safe**:
|
|
863
|
-
> - **R-C3-05 (Cross-service theft)**: Eliminated by `three_body_allocator_guard` (Step
|
|
927
|
+
> - **R-C3-05 (Cross-service theft)**: Eliminated by `three_body_allocator_guard` (Step 9), which verifies `order.service == three_body_signature_service` before allocation proceeds.
|
|
864
928
|
> - **R-C3-06 (Fund theft via Signer)**: Eliminated by `sharing.who = {"Entity": {"name_or_address": "three_body_treasury"}}` — funds always flow to the fixed Treasury address regardless of who triggers the allocation. An attacker cannot redirect funds to themselves even if they somehow bypass the Guard.
|
|
865
929
|
> - **Previous unsafe pattern (DO NOT USE)**: The original design used `guard: "three_body_buy_guard"` (no `order.service` check) with `sharing.who = {"Signer": "signer"}` — this allowed anyone to trigger allocation of any order's funds to themselves.
|
|
930
|
+
> - **SDK-enforced constraint (customer_required ⟶ um)**: `"customer_required"` is set alongside `"um": "three_body_contact"` in the SAME call. The SDK validator `checkCustomerRequiredNeedsUm()` in `service.ts` L1226 also runs on publish (L314), so splitting into two calls (e.g. `customer_required` now, `um` later) would still fail at publish time — they are both required before the Service goes live.
|
|
866
931
|
|
|
867
932
|
**Expected Result**:
|
|
868
933
|
```json
|
|
@@ -891,7 +956,7 @@ Set up fund allocation: 100% to the author's Treasury upon order completion.
|
|
|
891
956
|
|
|
892
957
|
---
|
|
893
958
|
|
|
894
|
-
## Step
|
|
959
|
+
## Step 11: Add Sales and Publish Service
|
|
895
960
|
|
|
896
961
|
Add sales items and publish the service to make it available for orders.
|
|
897
962
|
|
|
@@ -956,7 +1021,7 @@ Add sales items and publish the service to make it available for orders.
|
|
|
956
1021
|
|
|
957
1022
|
---
|
|
958
1023
|
|
|
959
|
-
## Step
|
|
1024
|
+
## Step 12: Unpause Service
|
|
960
1025
|
|
|
961
1026
|
Unpause the service to allow order creation.
|
|
962
1027
|
|
|
@@ -1005,7 +1070,7 @@ Unpause the service to allow order creation.
|
|
|
1005
1070
|
|
|
1006
1071
|
---
|
|
1007
1072
|
|
|
1008
|
-
## Step
|
|
1073
|
+
## Step 13: Verify Service Configuration
|
|
1009
1074
|
|
|
1010
1075
|
Query the service to verify all configurations.
|
|
1011
1076
|
|
|
@@ -1080,7 +1145,7 @@ Query the service to verify all configurations.
|
|
|
1080
1145
|
]
|
|
1081
1146
|
},
|
|
1082
1147
|
"rewards": [],
|
|
1083
|
-
"um":
|
|
1148
|
+
"um": "0x...",
|
|
1084
1149
|
"permission": "0x...",
|
|
1085
1150
|
"cache_expire": 1234567890,
|
|
1086
1151
|
"query_name": "three_body_signature_service"
|
|
@@ -1095,9 +1160,10 @@ Query the service to verify all configurations.
|
|
|
1095
1160
|
```
|
|
1096
1161
|
|
|
1097
1162
|
> **Field Reference**:
|
|
1098
|
-
> - **`buy_guard`**, **`machine`**, **`permission`**: Return **on-chain object IDs** (not names). The on-chain data stores raw object IDs; resolving them back to local mark names requires a separate reverse lookup that is not performed by `onchain_objects` queries.
|
|
1163
|
+
> - **`buy_guard`**, **`machine`**, **`permission`**, **`um`**: Return **on-chain object IDs** (not names). The on-chain data stores raw object IDs; resolving them back to local mark names requires a separate reverse lookup that is not performed by `onchain_objects` queries.
|
|
1099
1164
|
> - **`query_name`**: The original name string passed in the query request (here, `"three_body_signature_service"`). This is automatically populated by the SDK from the input `objects` array, so you can identify which queried name corresponds to which returned object.
|
|
1100
|
-
> - **`
|
|
1165
|
+
> - **`um`**: The on-chain object ID of `three_body_contact` (created in Step 8). The SDK validator `checkCustomerRequiredNeedsUm()` requires this whenever `customer_required` is non-empty — without a Contact the Service has no encrypted channel to receive customer private info.
|
|
1166
|
+
> - **`order_allocators.allocators[].guard`**: Returns the on-chain object ID of `three_body_allocator_guard` (created in Step 9). This Guard verifies `order.service == three_body_signature_service` (R-C3-05 protection).
|
|
1101
1167
|
> - **`order_allocators.allocators[].sharing[].who`**: `{"Entity": "0x..."}` indicates funds flow to the fixed Treasury object (`three_body_treasury` from Step 7). The address is the Treasury's on-chain object ID. This eliminates R-C3-06 (fund theft via Signer) because the recipient is fixed regardless of caller.
|
|
1102
1168
|
> - **`order_allocators.allocators[].sharing[].mode`**: `1` is the numeric enum for `Rate` mode (input accepts the string `"Rate"`, output returns the numeric `1`).
|
|
1103
1169
|
> - **`order_allocators.allocators[].fix`** and **`max`**: Additional fields returned on-chain (default `"0"` and `null` respectively) that are not part of the input schema but are present in the on-chain data structure.
|
|
@@ -1154,7 +1220,7 @@ The author (`three_body_author`) should be able to purchase the service.
|
|
|
1154
1220
|
}
|
|
1155
1221
|
```
|
|
1156
1222
|
|
|
1157
|
-
> **Amount Format**: `"888WOW"` is the display format — the Fund Processing Layer converts it to `888000000000` smallest units (WOW has 9 decimals) before submission. The raw integer `888000000000` is equally valid. The order pays exactly the sale price set in Step
|
|
1223
|
+
> **Amount Format**: `"888WOW"` is the display format — the Fund Processing Layer converts it to `888000000000` smallest units (WOW has 9 decimals) before submission. The raw integer `888000000000` is equally valid. The order pays exactly the sale price set in Step 11.
|
|
1158
1224
|
|
|
1159
1225
|
**Expected Result**:
|
|
1160
1226
|
```json
|
|
@@ -1435,7 +1501,7 @@ The author completes the signature.
|
|
|
1435
1501
|
|
|
1436
1502
|
### Fund Allocation: Release the 888 WOW Payment to the Treasury
|
|
1437
1503
|
|
|
1438
|
-
Once the Progress reaches the final node (`Signature Completed`), the order is fulfilled and the 888 WOW payment held by `three_body_allocation` can be distributed. The Service's `order_allocators` (Step
|
|
1504
|
+
Once the Progress reaches the final node (`Signature Completed`), the order is fulfilled and the 888 WOW payment held by `three_body_allocation` can be distributed. The Service's `order_allocators` (Step 10) routes 100% to `three_body_treasury` when `three_body_allocator_guard` (Step 9) verifies `order.service == three_body_signature_service`.
|
|
1439
1505
|
|
|
1440
1506
|
#### (a) Trigger the Allocation (`alloc_by_guard`)
|
|
1441
1507
|
|
|
@@ -1690,6 +1756,7 @@ This example demonstrates:
|
|
|
1690
1756
|
| Machine | three_body_machine |
|
|
1691
1757
|
| Service | three_body_signature_service |
|
|
1692
1758
|
| Treasury | three_body_treasury |
|
|
1759
|
+
| Contact (um) | three_body_contact (required for customer_required — SDK-enforced customer_required ⟶ um linkage) |
|
|
1693
1760
|
| Allocator Guard | three_body_allocator_guard (Level 3 scene-combined, R-C3-05/R-C3-06 safe) |
|
|
1694
1761
|
| Order | three_body_order |
|
|
1695
1762
|
| Allocation | three_body_allocation |
|
|
@@ -1739,7 +1806,8 @@ Each node transition requires the author's confirmation, ensuring accountability
|
|
|
1739
1806
|
- Service (unpublished)
|
|
1740
1807
|
- Guards (Buy Guard for purchase control; Allocator Guard needs Service address for `order.service` verification)
|
|
1741
1808
|
- Treasury (uses same Permission as Service for unified governance)
|
|
1742
|
-
-
|
|
1809
|
+
- Contact (um) — REQUIRED before setting customer_required (SDK-enforced: customer_required ⟶ um hard linkage; validator also re-runs at publish time)
|
|
1810
|
+
- Configure Service (add machine, buy_guard, order_allocators with allocator guard + Entity(Treasury); set customer_required **together with** um in the same or prior call)
|
|
1743
1811
|
- Publish Service (LAST - once published, many changes are blocked)
|
|
1744
1812
|
|
|
1745
1813
|
3. **Treasury-First Fund Flow**: Always route merchant revenue through a Treasury object using `sharing.who = {"Entity": {"name_or_address": "treasury_name"}}` instead of `{"Signer": "signer"}`. This eliminates R-C3-06 (critical fund theft via Signer) because funds flow to a fixed recipient regardless of who triggers the allocation. Combined with an allocator Guard that verifies `order.service == this_service` (R-C3-05 protection), the fund allocation becomes inherently safe.
|
|
@@ -1751,8 +1819,13 @@ Each node transition requires the author's confirmation, ensuring accountability
|
|
|
1751
1819
|
|
|
1752
1820
|
5. **Use `no_cache: true` for Sequential Operations**: When performing multiple operations on the same object in sequence (especially Progress workflow advancement), always set `no_cache: true` in the `env` to ensure the SDK reads the latest on-chain state.
|
|
1753
1821
|
|
|
1754
|
-
6. **
|
|
1822
|
+
6. **customer_required ⟶ um (Contact) Hard Linkage (SDK-enforced)**: Whenever you set `customer_required` (e.g. `["phone", "email", "shipping_address"]`), you MUST also bind a Contact object via `um` in the SAME or a prior Service call. The SDK's `checkCustomerRequiredNeedsUm()` validator in `ts-sdk/packages/wowok/src/w/call/service.ts` (L1226) runs at TWO points:
|
|
1823
|
+
- When `customer_required` is present in the current operation `data` (immediate block, L307)
|
|
1824
|
+
- When `publish: true` is set (re-verifies against the accumulated Service state, L314)
|
|
1825
|
+
This means splitting the two calls (set `customer_required` first, add `um` later) is NOT safe — the publish-time re-check would still block. Always create the Contact first, then set both `customer_required` and `um` together.
|
|
1826
|
+
|
|
1827
|
+
7. **Query Toolkit is Your Best Friend**: Use queries constantly to verify objects exist, check configurations, debug issues, and confirm state changes.
|
|
1755
1828
|
|
|
1756
|
-
|
|
1829
|
+
8. **Object IDs vs Names in Responses**: On-chain query responses return **object IDs** (e.g., `0x8202...`) for cross-object references like `buy_guard`, `machine`, `permission`, `um`. The `query_name` field in the response echoes back the original query input name. To resolve object IDs back to local mark names, use `query_toolkit` with `query_type: "local_names"`.
|
|
1757
1830
|
|
|
1758
|
-
|
|
1831
|
+
9. **Information Injection in Transaction Responses**: Mutation/creation operations return ALL objects affected by the transaction (including side effects like `TableItem_EntityLinker` and `TableItem_ProgressHistory`), not just the primary target. This is a deliberate design for transparency. The return order reflects the transaction's execution order.
|
|
@@ -225,7 +225,7 @@ Day 5: 1783900800000 (2026-07-13T00:00:00.000Z)
|
|
|
225
225
|
{
|
|
226
226
|
"name": "Condition",
|
|
227
227
|
"description": "Weather condition policy for activity dates",
|
|
228
|
-
"write_guard": [],
|
|
228
|
+
"write_guard": [{ "guard": "weather_write_guard" }],
|
|
229
229
|
"id_from": "None",
|
|
230
230
|
"value_type": "String"
|
|
231
231
|
}
|
|
@@ -243,6 +243,8 @@ Day 5: 1783900800000 (2026-07-13T00:00:00.000Z)
|
|
|
243
243
|
```
|
|
244
244
|
|
|
245
245
|
> **Note**: `onChain: true` is required here because `weather_repo` is created by the `weather_provider` account, but its name will be referenced in the Guard table (Step 3.1) by the `travel_provider` account. Without `onChain: true`, the name is stored locally only on `weather_provider`'s device and cannot be resolved by `travel_provider`. When `onChain: true` is set, the name is published on-chain and becomes publicly visible, allowing cross-account name resolution.
|
|
246
|
+
>
|
|
247
|
+
> The `write_guard` in the "Condition" policy points to `weather_write_guard` (created above). Because `id_from: "None"` lets the writer choose data ids, the contract mandates a Guard to authorize writes. `data_add` in Step 0.4 needs no Guard submission — the Guard is always-true with no submission fields.
|
|
246
248
|
|
|
247
249
|
### 0.4 Add Weather Data
|
|
248
250
|
|
|
@@ -1117,11 +1119,7 @@ Configure the travel service (created unpublished in Step 2.5) with all bindings
|
|
|
1117
1119
|
"data": {
|
|
1118
1120
|
"operation_type": "service",
|
|
1119
1121
|
"data": {
|
|
1120
|
-
"object":
|
|
1121
|
-
"name": "travel_service",
|
|
1122
|
-
"permission": "travel_permission",
|
|
1123
|
-
"replaceExistName": true
|
|
1124
|
-
},
|
|
1122
|
+
"object": "travel_service",
|
|
1125
1123
|
"description": "Iceland travel service: Blue Lagoon SPA + Glacier Ice Scooting.",
|
|
1126
1124
|
"machine": "travel_machine",
|
|
1127
1125
|
"sales": {
|
|
@@ -1200,6 +1198,8 @@ Configure the travel service (created unpublished in Step 2.5) with all bindings
|
|
|
1200
1198
|
}
|
|
1201
1199
|
```
|
|
1202
1200
|
|
|
1201
|
+
> **Note**: `object` uses a plain string reference (`"travel_service"`) so this call **configures the draft Service created in Step 2.5**. Passing a full object definition block (`{name, permission, replaceExistName}`) here would create a brand-new Service object instead — orders and allocator Guard bindings pointing at the old draft would then fail validation.
|
|
1202
|
+
|
|
1203
1203
|
**order_allocators Field Reference**:
|
|
1204
1204
|
|
|
1205
1205
|
| Field | Type | Description |
|
|
@@ -1542,21 +1542,17 @@ The allocation Guard requires the Order ID as a submission (identifier: 0). Quer
|
|
|
1542
1542
|
|
|
1543
1543
|
```json
|
|
1544
1544
|
{
|
|
1545
|
-
"tool": "
|
|
1545
|
+
"tool": "query_toolkit",
|
|
1546
1546
|
"data": {
|
|
1547
|
-
"
|
|
1548
|
-
"
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
"env": {
|
|
1552
|
-
"network": "testnet",
|
|
1553
|
-
"no_cache": true
|
|
1554
|
-
}
|
|
1547
|
+
"query_type": "onchain_objects",
|
|
1548
|
+
"objects": ["alice_travel_progress"],
|
|
1549
|
+
"network": "testnet",
|
|
1550
|
+
"no_cache": true
|
|
1555
1551
|
}
|
|
1556
1552
|
}
|
|
1557
1553
|
```
|
|
1558
1554
|
|
|
1559
|
-
> **Note**: The response includes a `task` field containing the Order object ID. Copy this value for the allocation submission.
|
|
1555
|
+
> **Note**: Use `query_toolkit` (not `onchain_operations`) for read-only lookups — queries consume no gas and never mutate state. The response includes a `task` field containing the Order object ID. Copy this value for the allocation submission.
|
|
1560
1556
|
|
|
1561
1557
|
### 8.2 Execute Allocation (Merchant Victory Path)
|
|
1562
1558
|
|
|
@@ -1669,16 +1665,12 @@ After allocation, query the Allocation and Payment objects to verify the fund di
|
|
|
1669
1665
|
|
|
1670
1666
|
```json
|
|
1671
1667
|
{
|
|
1672
|
-
"tool": "
|
|
1668
|
+
"tool": "query_toolkit",
|
|
1673
1669
|
"data": {
|
|
1674
|
-
"
|
|
1675
|
-
"
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
"env": {
|
|
1679
|
-
"network": "testnet",
|
|
1680
|
-
"no_cache": true
|
|
1681
|
-
}
|
|
1670
|
+
"query_type": "onchain_objects",
|
|
1671
|
+
"objects": ["alice_travel_allocation"],
|
|
1672
|
+
"network": "testnet",
|
|
1673
|
+
"no_cache": true
|
|
1682
1674
|
}
|
|
1683
1675
|
}
|
|
1684
1676
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wowok/skills",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.4",
|
|
4
4
|
"description": "WoWok AI Skills for Claude and other AI assistants - Dialogue orchestration layer on top of the WoWok MCP server (rules/reference knowledge is served by MCP directly since v2.0.0)",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
package/scripts/install.js
CHANGED
|
@@ -25,7 +25,7 @@ const { execSync } = require('child_process');
|
|
|
25
25
|
* into the MCP knowledge layer and are served by the MCP server directly:
|
|
26
26
|
* - wowok-safety → schema_query action='get_safety_rules'
|
|
27
27
|
* - wowok-tools → schema_query action='get_tool_reference'
|
|
28
|
-
* - wowok-scenario →
|
|
28
|
+
* - wowok-scenario → industry_pack_operation recommend_industry / list_modes
|
|
29
29
|
* - wowok-guard → schema_query action='get_guard_design_patterns'
|
|
30
30
|
*/
|
|
31
31
|
const SKILL_DIRS = [
|
|
@@ -59,7 +59,7 @@ const LEGACY_SKILL_DIRS = [
|
|
|
59
59
|
const SKILL_MIGRATION_MAP = {
|
|
60
60
|
'wowok-safety': "MCP schema_query action='get_safety_rules'",
|
|
61
61
|
'wowok-tools': "MCP schema_query action='get_tool_reference'",
|
|
62
|
-
'wowok-scenario': "MCP
|
|
62
|
+
'wowok-scenario': "MCP industry_pack_operation action='recommend_industry' / 'list_modes'",
|
|
63
63
|
'wowok-guard': "MCP schema_query action='get_guard_design_patterns'",
|
|
64
64
|
};
|
|
65
65
|
|
|
@@ -28,9 +28,9 @@ The following content has been pushed down to the MCP knowledge layer and is app
|
|
|
28
28
|
|
|
29
29
|
| Content | Access via (MCP action) | Applied Via |
|
|
30
30
|
|---------|--------------------------|-------------|
|
|
31
|
-
| Guard design rules (structural layers, data source classification, voting_guard table design) | `schema_query` action='get_guard_design_patterns' | `
|
|
32
|
-
| Safety rules (confirmation levels, immutability, object reuse) | `schema_query` action='get_safety_rules' | Pre-publish checks + `
|
|
33
|
-
| Arbitration-specific risks | auto-applied | `
|
|
31
|
+
| Guard design rules (structural layers, data source classification, voting_guard table design) | `schema_query` action='get_guard_design_patterns' | `goal_operation` action='aggregate_risks' |
|
|
32
|
+
| Safety rules (confirmation levels, immutability, object reuse) | `schema_query` action='get_safety_rules' | Pre-publish checks + `goal_operation` action='aggregate_risks' |
|
|
33
|
+
| Arbitration-specific risks | auto-applied | `goal_operation` action='aggregate_risks' |
|
|
34
34
|
|
|
35
35
|
This Skill keeps the arbitration **conversation flow**, **evidence collection** scripts, and **dispute resolution** guidance — the MCP layer handles the rule evaluation.
|
|
36
36
|
|
|
@@ -42,7 +42,7 @@ These four principles govern every arbitration build/handle step. They mirror th
|
|
|
42
42
|
|
|
43
43
|
1. **Review-first**: State (a) what the AI understood about the arbitration, (b) the dependency order to build, and (c) the interaction contract — before the first choice.
|
|
44
44
|
2. **User-driven**: Every step is an explicit user decision; the AI provides a `recommend` but never auto-advances.
|
|
45
|
-
3. **Reuse / Customize / Discover (
|
|
45
|
+
3. **Reuse / Customize / Discover (choose one of three)**: For every component (Permission, Voting/Usage Guards, Contact), surface all three avenues — reuse an existing object, customize a new one, or discover from other projects / the system.
|
|
46
46
|
4. **Default-config disclosure**: Disclose a new object's default config + important info + caveats BEFORE the user decides. No silent defaults.
|
|
47
47
|
|
|
48
48
|
---
|
package/wowok-auditor/SKILL.md
CHANGED
|
@@ -38,9 +38,9 @@ The following content has been pushed down to the MCP knowledge layer and is app
|
|
|
38
38
|
|
|
39
39
|
| Content | Access via (MCP action) | Applied Via |
|
|
40
40
|
|---------|--------------------------|-------------|
|
|
41
|
-
| Safety rules (confirmation levels, immutability rules, object reuse rules) | `schema_query` action='get_safety_rules' | Pre-publish checks + `
|
|
42
|
-
| Machine-executable audit rules | auto-applied (not queryable) | `
|
|
43
|
-
| Guard completeness / Machine soundness / fund-flow risks | auto-applied (not queryable) | `
|
|
41
|
+
| Safety rules (confirmation levels, immutability rules, object reuse rules) | `schema_query` action='get_safety_rules' | Pre-publish checks + `goal_operation` action='aggregate_risks' |
|
|
42
|
+
| Machine-executable audit rules | auto-applied (not queryable) | `goal_operation` action='aggregate_risks' |
|
|
43
|
+
| Guard completeness / Machine soundness / fund-flow risks | auto-applied (not queryable) | `goal_operation` action='aggregate_risks' |
|
|
44
44
|
|
|
45
45
|
This Skill keeps the **audit flow**, the **4 audit dimensions** (Guard completeness, Machine soundness, fund flow, publish readiness), and the **checklist structure** as the human-readable knowledge base for the L4 Harness Verify Loop. The MCP layer runs the machine-executable rule evaluation.
|
|
46
46
|
|