@wowok/skills 1.3.2 → 1.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wowok/skills",
3
- "version": "1.3.2",
3
+ "version": "1.3.4",
4
4
  "description": "WoWok AI Skills for Claude and other AI assistants - Helping AI use WoWok MCP tools correctly",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -129,6 +129,8 @@ Customer dispute creates Arb directly at (1). State (0) entered only via `reset`
129
129
 
130
130
  **⚠️ Guard Immutability**: Once a Guard is created, its rules **cannot be modified**. If your `voting_guard` design is wrong, you must create a replacement Guard and reconfigure the Arbitration — wasteful but not fatal. Test with `gen_passport` before finalizing.
131
131
 
132
+ **⚠️ Permission Isolation from Service** (CRITICAL for mainnet trust): The Arbitration's Permission object MUST be separate from the Service's Permission object. Sharing the same Permission — or having overlapping owner/admin addresses — breaks dispute fairness because the merchant can control arbitration operations (vote, confirm, execute rulings). For mainnet deployment, use a completely independent third-party Permission with a different owner and admin list. The evaluation engine deducts risk scores significantly for Permission overlap (-30 for same Permission, -20 for owner/admin overlap). Testnet may tolerate shared Permission for simplicity, but mainnet users should treat this as a critical trust factor.
133
+
132
134
  ### Voting Modes
133
135
 
134
136
  **1. Open Voting** (`voting_guard: []`)
@@ -249,6 +249,7 @@ Before `publish: true`, verify:
249
249
  - [ ] All Guards exist on-chain and tested (use `gen_passport`)
250
250
  - [ ] `namedOperator` vs `permissionIndex` correct per Forward
251
251
  - [ ] Every Forward has at least one of `namedOperator` or `permissionIndex`
252
+ - [ ] **⚠ Permission indexes authorized** (P0): every `permissionIndex` used in forwards MUST have at least one entity granted in the Permission object. Call `permission.op="add perm by index"` for each custom index (≥1000) BEFORE publishing. Un-granted indexes = forward can NEVER execute = Progress permanently stuck. The MCP handler auto-checks this and warns on missing grants.
252
253
  - [ ] Terminal nodes mapped to Allocator entries for fund distribution
253
254
  - [ ] Tested end-to-end on testnet via a test Progress
254
255
  - [ ] Current state exported via `machineNode2file` as backup
@@ -137,7 +137,7 @@ STEP 3: Business Logic (MODIFY)
137
137
  │ Tool: "onchain_operations" (service) | Fields: order_allocators
138
138
  ├── Arbitrations (optional) — REUSE existing Arb services
139
139
  │ Tool: "onchain_operations" (service) | Fields: arbitrations.list
140
- ├── Compensation Fund (optional): compensation_fund_add + setting_locked_time_add (default 30 days, configurable)
140
+ ├── Compensation Fund (optional): compensation_fund_add + setting_lock_duration_add (default 30 days, configurable)
141
141
  │ Tool: "onchain_operations" (service)
142
142
  └── Reward (optional) — incentive pools
143
143
 
@@ -154,7 +154,9 @@ STEP 4: Publication
154
154
  2. guard2file export Guards → review
155
155
  3. machineNode2file export Machine → review
156
156
  4. Allocator splits match user's stated model?
157
- 5. Warn: publish = immutable. Proceed?
157
+ 5. Permission indexes: every permissionIndex in Machine forwards has entities granted? (call permission "add perm by index" for missing ones)
158
+ 6. Arbitration Permission isolation: Arbitration uses a SEPARATE Permission object (not the Service's Permission)? Different owner/admin? (critical for mainnet trust)
159
+ 7. Warn: publish = immutable. Proceed?
158
160
 
159
161
  STEP 5: Post-Publish (MODIFY Service — mutable after publish)
160
162
  ├── description, location
@@ -320,7 +322,7 @@ Attach: wowok({ tool: "onchain_operations", data: { operation_type: "service", .
320
322
 
321
323
  ### Compensation Fund (Optional but Recommended)
322
324
 
323
- - Add: `compensation_fund_add` | Lock: `setting_locked_time_add` (default 30 days = 2592000000ms, configurable via `setting_lock_duration_add`)
325
+ - Add: `compensation_fund_add` | Lock: `setting_lock_duration_add` (default 30 days = 2592000000ms, configurable via `setting_lock_duration_add`)
324
326
  - **Withdraw**: Pause Service → Wait lock duration → `compensation_fund_receive`
325
327
 
326
328
  ---
@@ -166,6 +166,59 @@ Controls name collision behavior. **DISCOURAGED** — prefer versioned names (`_
166
166
 
167
167
  Use `Payment` objects for commercial transfers when possible — they offer Guard validation and purpose tracking beyond a simple `account_operation (transfer)`.
168
168
 
169
+ ### 5.3 Cross-Network Switching (testnet → mainnet)
170
+
171
+ WoWok objects are network-specific — the same object name resolves to different addresses on testnet vs mainnet. The `local_mark` system manages this mapping automatically.
172
+
173
+ **Prerequisites**:
174
+ - testnet deployment verified (all objects created, order lifecycle tested)
175
+ - Record all object names (query `local_mark_list` for the full list)
176
+ - mainnet account has sufficient WOW balance (faucet is testnet-only; use `account_operation transfer` from a funded mainnet account)
177
+
178
+ **Switching Steps**:
179
+ 1. Change `env.network` from `"testnet"` to `"mainnet"` in all MCP calls
180
+ 2. Re-create all objects on mainnet with `replaceExistName: true` (names stay the same, addresses change)
181
+ 3. Order matters — follow the dependency chain: Permission → Machine → Guards → Contact → Service → (Order/Progress/Allocation are created at purchase time)
182
+ 4. Verify each object creation succeeds and `local_mark` is updated
183
+ 5. Test the critical path: place a test order → advance Progress → verify Allocation
184
+
185
+ **Key Mechanism**:
186
+ ```
187
+ testnet: local_mark["my_service"] = 0x867a... (testnet address)
188
+ mainnet: local_mark["my_service"] = 0xdef0... (mainnet address, auto-overwritten)
189
+ ```
190
+ - All object references in Guard tables, Service bindings, and Machine forwards use NAMES (not addresses)
191
+ - SDK's `GetObjectExisted()` resolves names to the current network's address at transaction build time
192
+ - `replaceExistName: true` ensures the name mapping is overwritten for the new network
193
+
194
+ **Important Notes**:
195
+ - testnet objects remain on testnet (they don't disappear) — mainnet is a completely fresh deployment
196
+ - Guard tables that reference other objects by NAME will auto-resolve to mainnet addresses
197
+ - Service.order_allocators and Machine nodes are immutable after publish — verify design before mainnet publish
198
+ - mainnet has no faucet — fund accounts via `account_operation` with `transfer` from an existing funded account
199
+
200
+ ### 5.4 Publish Pre-Check Checklist
201
+
202
+ Before calling `publish: true` on a Service or Machine, verify:
203
+
204
+ **Service Publish Checklist**:
205
+ - [ ] `order_allocators` is set and design is verified (PERMANENTLY immutable after publish)
206
+ - [ ] `machine` is bound and already published
207
+ - [ ] `buy_guard` is bound (if purchase validation is needed)
208
+ - [ ] `permission` is bound with all required indexes granted
209
+ - [ ] If `compensation_fund > 0`: `arbitrations` MUST be bound (contract enforces: `E_ARBITRATION_NOT_SET_WITH_COMPENSATION_FUND`)
210
+ - [ ] All Guard names in `order_allocators` resolve correctly
211
+ - [ ] All sharing amounts and recipient types (Entity/Signer/GuardIdentifier) are intended
212
+ - [ ] Use `dry_run: true` first to simulate the publish transaction
213
+
214
+ **Machine Publish Checklist**:
215
+ - [ ] All nodes have at least one forward (except terminal nodes)
216
+ - [ ] Each forward has `namedOperator` or `permissionIndex` (or both = OR semantic)
217
+ - [ ] `namedOperator: ""` means OrderHolder (customer), NOT "anyone"
218
+ - [ ] All `permissionIndex` values are granted in the bound Permission object
219
+ - [ ] Entry node has `prev_node: ""` and `threshold: 0`
220
+ - [ ] Terminal nodes have empty `pairs: []`
221
+
169
222
  ---
170
223
 
171
224
  ## 6. Query-First Pattern
@@ -151,7 +151,7 @@ Step 3: MODIFY reward { object: "reward_v1", guard_add: [...] } // bind guard
151
151
 
152
152
  | `operation_type` | Key Constraints (not in schema) |
153
153
  |-----------------|----------------------------------|
154
- | `service` | `machine` must be **published**. Allocators: array order = priority (first-Guard-wins). **Publish locks 3 fields (SDK-level)**: `machine`/`order_allocators`/`arbitrations` — MUST be set BEFORE `publish:true`. **buy_guard is MUTABLE after publish** (no SDK/Move lock). `setting_locked_time_add` is extendable. TIME-LOCKED (need pause + setting_lock_duration): `rewards` remove/clear. REMAIN MUTABLE: `sales`/`discount`/`description`/`location`/`pause`/`repositories`/`rewards`(add)/`compensation_fund_add`/`customer_required`/`um`/`buy_guard`. To change locked fields after publish, clone a new Service. |
154
+ | `service` | `machine` must be **published**. Allocators: array order = priority (first-Guard-wins). **Publish locks 2 fields (L1 absolute)**: `machine`/`order_allocators` — MUST be set BEFORE `publish:true`. **TIME-LOCKED (L2, need pause + setting_lock_duration)**: `arbitrations` remove/clear, `rewards` remove/clear, `compensation_fund_withdraw`. **REMAIN MUTABLE (L3)**: `arbitrations`(add)/`rewards`(add)/`sales`/`discount`/`description`/`location`/`pause`/`repositories`/`compensation_fund_add`/`setting_lock_duration_add`/`customer_required`/`um`/`buy_guard`. To change L1-locked fields after publish, clone a new Service. |
155
155
  | `machine` | Nodes immutable after publish. Forward needs ≥1 of `namedOperator`/`permissionIndex` (both empty = SDK error). `""` = entry node. → [wowok-machine](../wowok-machine/SKILL.md) |
156
156
  | `progress` | CANONICAL form: `operate: {operation: {next_node_name, forward}, op: "next"\|"hold"\|"unhold"\|"adminUnhold", message?}`. LEGACY `hold: boolean` is auto-converted (`hold:true`→`op:'hold'`, `hold:false`→`op:'next'`). SDK auto-fetches Machine when resolving `object_address`. **⚠ Routing rule**: Use `progress.operate` ONLY for forwards with non-empty `namedOperator` or `permissionIndex`-only. For forwards with `namedOperator=""` (OrderHolder), use `order.progress` instead — direct `progress::next` aborts with Permission denied (code 5). |
157
157
  | `arbitration` | MAX 20 propositions, 520 voters. Verdict (2→3) **irreversible** — only customer can `order.arb_objection`. Non-Finished withdrawal = 30-day wait. → [wowok-arbitrator](../wowok-arbitrator/SKILL.md) |