@wowok/skills 1.2.4 → 1.2.5
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 +34 -16
- package/dist/cli.js +6 -2
- package/dist/cli.js.map +1 -1
- package/dist/skills.d.ts +32 -1
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +63 -0
- package/dist/skills.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/examples/Insurance/Insurance.md +543 -475
- package/examples/MyShop/MyShop.md +865 -746
- package/examples/MyShop_Advanced/MyShop_Advanced.md +1520 -1376
- package/examples/ThreeBody_Signature/ThreeBody_Signature.md +891 -651
- package/examples/Travel/Travel.md +952 -848
- package/package.json +2 -2
- package/scripts/install.js +3 -17
- package/wowok-arbitrator/SKILL.md +18 -57
- package/wowok-auditor/SKILL.md +16 -12
- package/wowok-distill/SKILL.md +237 -0
- package/wowok-guard/SKILL.md +40 -354
- package/wowok-machine/SKILL.md +21 -127
- package/wowok-messenger/SKILL.md +14 -59
- package/wowok-onboard/SKILL.md +42 -12
- package/wowok-order/SKILL.md +20 -169
- package/wowok-output/SKILL.md +0 -10
- package/wowok-planner/SKILL.md +28 -9
- package/wowok-provider/SKILL.md +72 -32
- package/wowok-safety/SKILL.md +8 -80
- package/wowok-scenario/SKILL.md +63 -98
- package/wowok-tools/SKILL.md +68 -107
- package/references/glossary.ts +0 -297
- package/references/guard-scenario-ledger.md +0 -353
- package/references/guard-template-library.md +0 -481
- package/references/machine-design-reference.md +0 -398
- package/references/machine-scenario-ledger.md +0 -227
- package/references/machine-template-library.md +0 -522
- package/references/merchant-scenario-coordination.md +0 -383
- package/references/object-collaboration.md +0 -362
- package/references/onchain-constants.md +0 -81
- package/wowok-arbitrator/APPENDIX.md +0 -545
- package/wowok-auditor/APPENDIX.md +0 -487
- package/wowok-guard/APPENDIX.md +0 -430
- package/wowok-machine/APPENDIX.md +0 -407
- package/wowok-messenger/APPENDIX.md +0 -550
- package/wowok-onboard/APPENDIX.md +0 -502
- package/wowok-order/APPENDIX.md +0 -777
- package/wowok-output/APPENDIX.md +0 -575
- package/wowok-planner/APPENDIX.md +0 -726
- package/wowok-provider/APPENDIX.md +0 -455
- package/wowok-safety/APPENDIX.md +0 -565
- package/wowok-scenario/APPENDIX.md +0 -97
- package/wowok-scenario/MODE-DETAILS.md +0 -275
- package/wowok-tools/APPENDIX.md +0 -394
package/wowok-guard/SKILL.md
CHANGED
|
@@ -49,11 +49,7 @@ Every Guard is built from three layers, each with a distinct role:
|
|
|
49
49
|
| **Computation** | `root` | A computational tree of GuardNode types that computes the final boolean result by combining data sources, comparisons, arithmetic, and logic | Yes |
|
|
50
50
|
| **Composition** | `rely` (optional) | References to other Guards; the current Guard's result is AND-ed or OR-ed with dependencies, enabling modular Guard composition | Yes |
|
|
51
51
|
|
|
52
|
-
**The table is the contract with callers**: It
|
|
53
|
-
|
|
54
|
-
**The root is the question**: It must return Bool. Intermediate nodes return numbers, strings, addresses, or vectors. Guard is **strongly typed** — the type system is strictly enforced at creation time. Type mismatches (e.g., passing a string to a numeric comparison node) will cause validation errors and prevent Guard creation.
|
|
55
|
-
|
|
56
|
-
**The rely is composition**: Up to 4 dependent Guards. When `rely.logic_or` is false (default), all dependencies must pass (AND). When true, any passing is sufficient (OR). A Guard can only depend on Guards with `rep: true` — `rep` indicates the Guard's `repository.data` queries (query 1167) do not depend on runtime submissions, so results are deterministic and the Guard can serve as a dependency. Guards with `rep: false` cannot appear in `rely` lists. Violations are caught by the contract layer at creation time.
|
|
52
|
+
**The table is the contract with callers**: It declares what data they must provide at runtime (`b_submission: true`) versus what the Guard already knows (`b_submission: false`). Every `identifier` node references exactly one table entry. **The root is the question**: It must return Bool; intermediate nodes return numbers/strings/addresses/vectors. Guard is **strongly typed** — type mismatches cause creation failure. **The rely is composition**: Up to 4 dependent Guards (AND by default, OR if `logic_or: true`). A Guard can only depend on Guards with `rep: true` (deterministic `repository.data` queries independent of runtime submissions). `rep: false` Guards cannot appear in `rely` lists — violations caught at creation time.
|
|
57
53
|
|
|
58
54
|
### Data Source 4 Classification — The Foundation of Guard Semantics
|
|
59
55
|
|
|
@@ -66,102 +62,32 @@ A Guard is fundamentally a **data computation tree**: deterministic data (on-cha
|
|
|
66
62
|
| **Type 3** | SubmittedObject | `query` + `identifier` (`b_submission: true`, no witness) | TYPE_QUERY + TYPE_CONSTANT | Medium (requires constraint rules) | User submits Order address for field query |
|
|
67
63
|
| **Type 4** | SystemContext | `context` (Signer/Clock/Guard) | TYPE_SIGNER / TYPE_CLOCK / TYPE_GUARD | Highest | Identity verification, time-locks |
|
|
68
64
|
|
|
69
|
-
**Key insights**:
|
|
70
|
-
1. **Type 1 and Type 3 are isomorphic at the native layer** — both use TYPE_QUERY+TYPE_CONSTANT; the only difference is the `b_submission` flag (false vs true)
|
|
71
|
-
2. **Type 2 can overlay on Type 1 or Type 3** — the source object can be a constant (Type 1) or a submission (Type 3), then witness derives the target object
|
|
72
|
-
3. **Type 4 is fully independent** — does not depend on the table
|
|
73
|
-
4. **Except for Type 4, all data must be declared in the table** — the table is the complete data contract between Guard and caller
|
|
65
|
+
**Key insights**: Type 1 and Type 3 are isomorphic at the native layer (both TYPE_QUERY+TYPE_CONSTANT; difference is `b_submission` flag). Type 2 overlays on Type 1 or Type 3 (source object can be constant or submission, then witness derives target). Type 4 is fully independent (no table dependency). Except for Type 4, all data must be declared in the table — the table is the complete data contract: deterministic data (`b_submission: false`, type+value baked at creation) + submitted data (`b_submission: true`, type only, value from caller at runtime — **must have constraint rules designed, otherwise empty data is meaningless**).
|
|
74
66
|
|
|
75
|
-
**
|
|
76
|
-
- **Deterministic data** (`b_submission: false`): type + value, baked at creation, immutable
|
|
77
|
-
- **Submitted data** (`b_submission: true`): type only (1-byte placeholder), value provided by caller at runtime — **must have constraint rules designed, otherwise empty data is meaningless**
|
|
78
|
-
|
|
79
|
-
**Guard essence**: A deterministic data set (Type 1 + Type 4) + submitted data (Type 3, must have constraint rules and defined types) → derived through finite operation rules → a single boolean result. The semantics are deterministic — you only need to fill in the "data object source meaning" and "field meaning" (e.g., "the permission address of service A", "the current node time of workflow B").
|
|
67
|
+
**Guard essence**: A deterministic data set (Type 1 + Type 4) + submitted data (Type 3, must have constraint rules and defined types) → derived through finite operation rules → a single boolean result. You only need to fill in the "data object source meaning" and "field meaning" (e.g., "the permission address of service A", "the current node time of workflow B").
|
|
80
68
|
|
|
81
69
|
### Verifier Constraint Levels — Designing Who Can Pass
|
|
82
70
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
#### Level 1 — Strict Single-Identity Binding (avoid unless justified)
|
|
86
|
-
|
|
87
|
-
**Pattern**: `logic_equal[context(Signer), identifier[N](fixed_address)]`
|
|
88
|
-
|
|
89
|
-
- **Maximally secure**: only ONE address can pass
|
|
90
|
-
- **Maximally inconvenient**: if that address is unavailable (key loss, personnel change, rotation), the Guard permanently blocks the operation — Guards are **immutable** after publish
|
|
91
|
-
- **Use only when**: the role is permanently tied to one address AND the designer explicitly accepts the lock-in risk
|
|
92
|
-
- **Risk rule**: `R-C4-04` (info) flags this pattern with a convenience reminder
|
|
93
|
-
- **Example**: `logic_equal[context(Signer), identifier[5](myshop_merchant)]`
|
|
94
|
-
|
|
95
|
-
> ⚠️ **Avoid Level 1 unless you understand the lock-in risk.** Prefer Level 2 (identity-set) or Level 3 (scene-combined) whenever possible.
|
|
96
|
-
|
|
97
|
-
#### Level 2 — Identity-Set Binding (recommended for role-based access)
|
|
98
|
-
|
|
99
|
-
**Pattern**: `logic_or` of multiple identity checks — Signer is ANY of a valid set.
|
|
100
|
-
|
|
101
|
-
**Key semantic insight — Address vs Bool return types**:
|
|
102
|
-
Guard queries that verify identity fall into two categories based on their return type, and this determines how they participate in a `logic_or`:
|
|
103
|
-
|
|
104
|
-
| Return Type | Query Examples | Construction in `logic_or` |
|
|
105
|
-
|-------------|---------------|---------------------------|
|
|
106
|
-
| **Address** | `1562 order.owner`, `1002 permission.owner`, `1488 service.permission` | Must wrap each in `logic_equal[query, context(Signer)]` to produce a Bool |
|
|
107
|
-
| **Bool** (suffix "has") | `1567 order.agent has`, `1004 permission.admin has`, `1006 permission.entity has` | Use **directly** as a `logic_or` child — they already return a verdict; pass `context(Signer)` as a parameter |
|
|
108
|
-
|
|
109
|
-
**Example — Order-holder identity set** (Signer is owner OR agent):
|
|
110
|
-
```json
|
|
111
|
-
{
|
|
112
|
-
"type": "logic_or",
|
|
113
|
-
"nodes": [
|
|
114
|
-
{
|
|
115
|
-
"type": "logic_equal",
|
|
116
|
-
"nodes": [
|
|
117
|
-
{"type": "query", "query": 1562, "object": {"identifier": 0}, "parameters": []},
|
|
118
|
-
{"type": "context", "context": "Signer"}
|
|
119
|
-
]
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
"type": "query",
|
|
123
|
-
"query": 1567,
|
|
124
|
-
"object": {"identifier": 0},
|
|
125
|
-
"parameters": [{"type": "context", "context": "Signer"}]
|
|
126
|
-
}
|
|
127
|
-
]
|
|
128
|
-
}
|
|
129
|
-
```
|
|
130
|
-
Here `1562` returns Address → wrapped in `logic_equal`; `1567` returns Bool → used directly with `context(Signer)` as its parameter.
|
|
131
|
-
|
|
132
|
-
**Example — Service-provider identity set** (Signer is permission.owner OR has admin):
|
|
133
|
-
|
|
134
|
-
Three sub-patterns with increasing flexibility:
|
|
135
|
-
|
|
136
|
-
1. **Static permission address** (simplest, breaks if Service rotates permission):
|
|
137
|
-
Query `1002`/`1004` against a table-constant permission address. If the Service changes its permission (like a company changing its board), the Guard must be rebuilt.
|
|
71
|
+
Three levels trade off **security** vs **convenience** when using `context(Signer)`:
|
|
138
72
|
|
|
139
|
-
|
|
140
|
-
The caller submits a permission address; the Guard verifies `query(1488: service.permission) == submitted_perm`, then checks `1002`/`1004` against the submitted permission. This survives permission rotation without rebuilding the Guard.
|
|
73
|
+
**Level 1 — Single-Identity** (`logic_equal[context(Signer), identifier[N](fixed_address)]`): Only ONE address passes. ⚠️ Avoid — if address unavailable (key loss, rotation), Guard permanently blocks. Risk rule `R-C4-04` flags this.
|
|
141
74
|
|
|
142
|
-
|
|
143
|
-
|
|
75
|
+
**Level 2 — Identity-Set** (recommended): `logic_or` of multiple identity checks. Key distinction:
|
|
76
|
+
- **Address-returning queries** (`order.owner`, `permission.owner`, `service.permission`): wrap in `logic_equal[query, context(Signer)]`
|
|
77
|
+
- **Bool-returning queries** (suffix "has": `order.agent has`, `permission.admin has`): use directly as `logic_or` child, pass `context(Signer)` as parameter
|
|
78
|
+
- **Dynamic permission** (RECOMMENDED): caller submits permission address; Guard verifies `service.permission == submitted_perm` then checks `permission.owner`/`permission.admin has`. Survives permission rotation.
|
|
144
79
|
|
|
145
|
-
|
|
80
|
+
**Level 3 — Scene-Combined** (verify if Signer binding is even needed):
|
|
146
81
|
|
|
147
|
-
|
|
82
|
+
| Scene | Signer needed? | Why |
|
|
83
|
+
|-------|---------------|-----|
|
|
84
|
+
| Allocators + `sharing.who=Entity` | NO | Funds to fixed recipient (R-C3-06 safe) |
|
|
85
|
+
| Allocators + `sharing.who=Signer` | YES (Level 2) | Funds to caller — must bind |
|
|
86
|
+
| Machine `forward` guard | MAYBE | `permissionIndex`/`namedOperator` may suffice |
|
|
87
|
+
| `buy_guard` | Usually NO | Customer is caller; whitelist/credentials suffice |
|
|
88
|
+
| `voting_guard` | NO | Weight from EntityRegistrar, not Signer (R-C3-02) |
|
|
148
89
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
| Scene | Is Signer binding needed? | Why |
|
|
152
|
-
|-------|--------------------------|-----|
|
|
153
|
-
| Service `order_allocators` + `sharing.who=Entity` | **NO** | Funds flow to a fixed Treasury/address regardless of caller — `sharing.who` already guarantees recipient safety (R-C3-06 safe) |
|
|
154
|
-
| Service `order_allocators` + `sharing.who=Signer` | **YES (Level 2 dynamic)** | Funds flow to caller — must bind Signer to authorized recipient (e.g., `order.owner`) |
|
|
155
|
-
| Machine `forward` guard | **MAYBE** | Forward's `permissionIndex`/`namedOperator` already verifies operator permission; Signer binding only needed if submitted data must belong to operator |
|
|
156
|
-
| Service `buy_guard` | **Usually NO** | The customer is the caller; identity checks via whitelist/credentials suffice |
|
|
157
|
-
| Reward `guard` | **Depends** | If claim is one-time (record count), no Signer binding needed; if claim amount is submitted, bind Signer |
|
|
158
|
-
| Arbitration `voting_guard` | **NO** (weight from query, not Signer) | Weight must come from on-chain EntityRegistrar, not submission (R-C3-02) |
|
|
159
|
-
|
|
160
|
-
**Decision flow**:
|
|
161
|
-
1. Does the scene's host object already verify the operator? (e.g., Machine forward) → Signer binding may be redundant
|
|
162
|
-
2. Does `sharing.who` route funds to a fixed recipient? → Signer binding unnecessary (R-C3-06 safe)
|
|
163
|
-
3. Does the resource flow matter more than who triggers it? → Focus on flow safety, not caller identity
|
|
164
|
-
4. Only if resources flow to the caller AND no other layer verifies identity → add Level 2 Signer binding
|
|
90
|
+
**Decision**: If host object already verifies operator OR `sharing.who` routes to fixed recipient → no Signer binding needed. Only add Level 2 when resources flow to caller AND no other layer verifies identity.
|
|
165
91
|
|
|
166
92
|
#### One Guard One Purpose Principle
|
|
167
93
|
|
|
@@ -318,20 +244,9 @@ The root tree is a computational expression whose terminal nodes read data and w
|
|
|
318
244
|
|
|
319
245
|
### Discovering Available Node Types
|
|
320
246
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
**Tool**: `wowok({ tool: "schema_query", data: { action: "get", name: "onchain_operations_guard" } })`
|
|
324
|
-
|
|
325
|
-
This returns the complete `GuardNodeSchema` definition — every node type, its required fields, input/output types, and validation rules. Node categories include:
|
|
326
|
-
|
|
327
|
-
- **Data source nodes**: `identifier`, `context`, `query` — read values from the Guard table, transaction context, or on-chain objects
|
|
328
|
-
- **Logic & Arithmetic nodes**: `logic_*`, `calc_number_*` — combine values into boolean decisions and compute numeric results
|
|
329
|
-
- **String, Conversion & Vector nodes**: `calc_string_*`, `convert_*`, `vec_*` — manipulate strings, transform types, search arrays
|
|
330
|
-
- **Record query nodes**: `query_reward_record_*`, `query_progress_history_*` — search on-chain historical data
|
|
331
|
-
|
|
332
|
-
**Key principle**: Every node declares its return type and the types it expects from children. The schema enforces these constraints at Guard creation time — type mismatches cause creation to fail. All numeric comparisons normalize to U256, enabling cross-type comparisons without explicit conversion.
|
|
247
|
+
Query the authoritative `GuardNodeSchema` via `schema_query` (name: `onchain_operations_guard`) — it returns every node type, required fields, input/output types, and validation rules. Categories include: data source nodes (`identifier`, `context`, `query`), logic/arithmetic nodes (`logic_*`, `calc_number_*`), string/conversion/vector nodes (`calc_string_*`, `convert_*`, `vec_*`), and record query nodes (`query_reward_record_*`, `query_progress_history_*`).
|
|
333
248
|
|
|
334
|
-
**
|
|
249
|
+
**Key principle**: Every node declares its return type and the types it expects from children. The schema enforces these constraints at Guard creation time — type mismatches cause creation to fail. All numeric comparisons normalize to U256, enabling cross-type comparisons without explicit conversion. For the `query` node, discover available instructions via `wowok_buildin_info` ("guard instructions") with `filter` to narrow by name/return type/parameter count/object type.
|
|
335
250
|
|
|
336
251
|
---
|
|
337
252
|
|
|
@@ -339,88 +254,23 @@ This returns the complete `GuardNodeSchema` definition — every node type, its
|
|
|
339
254
|
|
|
340
255
|
Guard creation is a **single atomic operation** — it either succeeds (the Guard is frozen on-chain) or fails (nothing is created). There is no intermediate draft state, no editing phase, and no deletion mechanism.
|
|
341
256
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
Use `onchain_operations` with `operation_type: "guard"`.
|
|
345
|
-
|
|
346
|
-
**Two creation modes**:
|
|
347
|
-
- `root.type: "node"` — build the computation tree directly in the operation payload.
|
|
348
|
-
- `root.type: "file"` — load the tree from a `guard2file`-exported JSON/Markdown file. Use this to iterate on existing Guards: export → edit file → create new Guard from file.
|
|
349
|
-
|
|
350
|
-
**Schema Reference**: `wowok({ tool: "schema_query", data: { action: "get", name: "onchain_operations_guard" } })`
|
|
257
|
+
Use `onchain_operations` (`operation_type: "guard"`) with `root.type: "node"` (inline tree) or `root.type: "file"` (load from `guard2file`-exported JSON/MD — use this to iterate on existing Guards: export → edit → create new).
|
|
351
258
|
|
|
352
259
|
---
|
|
353
260
|
|
|
354
261
|
## Phase 5: Test, Export, and Query
|
|
355
262
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
Before embedding a Guard into a live Machine, Service, or Arbitration, test it in isolation.
|
|
359
|
-
|
|
360
|
-
**Tool**: `onchain_operations` with `operation_type: "gen_passport"`
|
|
361
|
-
|
|
362
|
-
**Schema Reference**: `wowok({ tool: "schema_query", data: { action: "get", name: "onchain_operations_gen_passport" } })`
|
|
363
|
-
|
|
364
|
-
This tool verifies one or more Guards and, on success, generates an immutable Passport — a verified credential stored on-chain. Use it to:
|
|
365
|
-
|
|
366
|
-
- **Test edge cases**: What happens with empty submissions, boundary values, or unusual addresses?
|
|
367
|
-
- **Debug failures**: If the Guard rejects valid data, the error helps identify type mismatches or missing table entries.
|
|
368
|
-
|
|
369
|
-
The Passport itself is useful beyond testing — it serves as a reusable on-chain credential for offline verification, transaction condition checking, and multi-guard validation. A single Passport can satisfy multiple Guards in a single transaction.
|
|
370
|
-
|
|
371
|
-
**Multi-Guard behavior**: When verifying multiple Guards, they are AND-ed — all must pass for the Passport to be generated. Each Guard's submission is passed independently.
|
|
372
|
-
|
|
373
|
-
**Optional `info` field**: If you omit `info` (submission data), the system attempts to auto-fetch existing submissions from the Guard. Provide `info` explicitly when testing with custom inputs.
|
|
374
|
-
|
|
375
|
-
**Passport query**: Once generated, query the Passport object via `query_toolkit` → `onchain_objects` to inspect its data, validated Guards, and timestamp.
|
|
376
|
-
|
|
377
|
-
### Query On-Chain Guards
|
|
263
|
+
**Test**: `gen_passport` verifies one or more Guards (AND-ed) and generates an immutable Passport on success. Omit `info` to auto-fetch submissions, or provide explicitly for custom test inputs.
|
|
378
264
|
|
|
379
|
-
**
|
|
265
|
+
**Query**: `query_toolkit` → `onchain_objects` for any Guard. Results include `_guard_node_comments` (human-readable annotations per node). Guards are public consensus — all parties can inspect validation rules.
|
|
380
266
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
Query results include `_guard_node_comments` — human-readable annotations for each computation node automatically injected by the system. Use these to quickly verify that the Guard's logic matches the intended design without manually decoding the node tree.
|
|
384
|
-
|
|
385
|
-
### Guard Iteration Workflow
|
|
386
|
-
|
|
387
|
-
Guards are immutable but iterable. The full cycle:
|
|
388
|
-
|
|
389
|
-
```
|
|
390
|
-
1. guard2file <existing_guard> → JSON/Markdown file
|
|
391
|
-
2. Edit file (table, root tree, rely)
|
|
392
|
-
3. Review edited JSON with user → confirm
|
|
393
|
-
4. wowok({ tool: "onchain_operations", data: { operation_type: "guard", root: { type: "file", ... } } }) → new Guard created
|
|
394
|
-
5. Update all references (Machine forwards, Service buy_guard, Arbitration voting_guard, etc.)
|
|
395
|
-
```
|
|
267
|
+
**Iteration**: `guard2file` → edit JSON/MD → create new Guard via `root.type:"file"` → update all references.
|
|
396
268
|
|
|
397
269
|
---
|
|
398
270
|
|
|
399
271
|
## Guard Data Flow: How Objects Read Guard Data
|
|
400
272
|
|
|
401
|
-
Guards are
|
|
402
|
-
|
|
403
|
-
### Arbitration: Voting Weight from Guard
|
|
404
|
-
|
|
405
|
-
Arbitration uses `usage_guard` for eligibility (pass/fail) and `voting_guard` for vote weight — either fixed or dynamically read from a Guard table submission index (`GuardIdentifier`). Table must have a numeric entry at the `GuardIdentifier` index; the value becomes the voter's weight (cast to u32).
|
|
406
|
-
|
|
407
|
-
### Demand: ServiceGuard with Identifier Mapping
|
|
408
|
-
|
|
409
|
-
Demand's `ServiceGuard` validates recommendations. If `service_identifier` is set, the Guard submission value at that index is passed to the service for validation; if unset, only Guard pass/fail is checked.
|
|
410
|
-
|
|
411
|
-
### Machine: Forward Guard with Retained Submission
|
|
412
|
-
|
|
413
|
-
Machine's forward `guard` validates state transitions. If `retained_submission` is set, those submission values are stored in Progress for audit or subsequent validation.
|
|
414
|
-
|
|
415
|
-
### Repository: Policy Write Guard with Data Extraction
|
|
416
|
-
|
|
417
|
-
Repository's `write_guard` validates writes. If `id_from_submission` is set, reads entity ID from that submission index — **the index must be Address type**. If `data_from_submission` is set, reads data value from that index — **the value type must match the Repository's declared value_type**. Guard table must include entries for the data being extracted.
|
|
418
|
-
|
|
419
|
-
**Important — impack_list semantics in verify phase**: When a Guard queries Repository data (query 1167 `repository.data`) with a policy that has a `quote_guard` set, the verification checks whether the quote_guard address is in the `impack_list`. However, `impack_list` is **always empty during the `verify_guard` phase** — `Passport.new()` initializes `impack:vector[]` and the verify loop never modifies it; `impack` is only populated in `result_for_permission` (after verify completes). This means a Repository query with `quote_guard = Some(addr)` will always fail with `IMPACK_GUARD_NOT_FOUND` in the gen_passport flow; only `quote_guard = None` passes. Verify the quote_guard mechanism's design intent before relying on it.
|
|
420
|
-
|
|
421
|
-
---
|
|
422
|
-
|
|
423
|
-
**Key Principle**: Design your Guard table based on what data the target object needs to read. Objects don't just validate — they consume Guard submissions as structured data inputs.
|
|
273
|
+
Guards are validators AND data sources. When bound, objects read structured data for decisions. Design your Guard table based on what data the target object needs to read — objects don't just validate, they consume Guard submissions as structured data inputs.
|
|
424
274
|
|
|
425
275
|
### Type Requirements by Object
|
|
426
276
|
|
|
@@ -434,6 +284,10 @@ Each object extracts Guard data with precise type expectations. Mismatches cause
|
|
|
434
284
|
| **Repository** | `id_from_submission` | Index must be `b_submission: true` | **Must be Address** |
|
|
435
285
|
| **Repository** | `data_from_submission` | Index must be `b_submission: true` | **Must match Repository's value_type** |
|
|
436
286
|
|
|
287
|
+
**Notes**: Arbitration uses `usage_guard` for eligibility (pass/fail) and `voting_guard` for weight (fixed or dynamic via `GuardIdentifier`). Demand's `ServiceGuard` passes the submission value at `service_identifier` to the service for validation (if unset, only pass/fail checked). Machine's `retained_submission` stores submission values in Progress for audit. Repository's `id_from_submission`/`data_from_submission` extract structured data from Guard submissions.
|
|
288
|
+
|
|
289
|
+
**⚠️ Critical — impack_list semantics in verify phase**: When a Guard queries Repository data (query 1167 `repository.data`) with a policy that has a `quote_guard` set, the verification checks whether the quote_guard address is in the `impack_list`. However, `impack_list` is **always empty during the `verify_guard` phase** — `Passport.new()` initializes `impack:vector[]` and the verify loop never modifies it; `impack` is only populated in `result_for_permission` (after verify completes). This means a Repository query with `quote_guard = Some(addr)` will always fail with `IMPACK_GUARD_NOT_FOUND` in the gen_passport flow; only `quote_guard = None` passes. Verify the quote_guard mechanism's design intent before relying on it.
|
|
290
|
+
|
|
437
291
|
---
|
|
438
292
|
|
|
439
293
|
## Best Practices
|
|
@@ -442,67 +296,15 @@ Each object extracts Guard data with precise type expectations. Mismatches cause
|
|
|
442
296
|
|
|
443
297
|
> The full constraint system has **33 rules: 22 creation-phase + 11 runtime-phase**. The 22 creation-phase constraints below are all enforced by SDK + native `validate_guard_data`; runtime constraints are enforced by native `verify_guard`.
|
|
444
298
|
|
|
445
|
-
#### Creation-Phase Constraints (22
|
|
446
|
-
|
|
447
|
-
**Root (1 item)**
|
|
448
|
-
|
|
449
|
-
1. **ROOT_01 — Root must return Bool**: The outermost node of the tree must produce Bool. Logic and comparison nodes return Bool; arithmetic, conversion, and string operation nodes do not. Ensure your tree terminates at a logic or comparison node — the creation validation will reject non-Bool roots.
|
|
450
|
-
|
|
451
|
-
**Table (5 items)**
|
|
452
|
-
|
|
453
|
-
2. **TABLE_01 — Identifier uniqueness**: Every `identifier` in the table must be unique (0–255). Duplicate identifiers cause creation failure. SDK uses `lodash.groupBy` to detect duplicates.
|
|
454
|
-
|
|
455
|
-
3. **TABLE_02 — Identifier referential integrity**: Every `identifier` node in the computation tree must match an entry in the table. Missing entries cause creation failure — validate your tree against your table before submitting.
|
|
456
|
-
|
|
457
|
-
4. **TABLE_03 — Constant value non-empty**: When `b_submission=false`, the `value` field must be non-empty. These values are baked into the Guard immutably at creation time.
|
|
299
|
+
#### Creation-Phase Constraints (22 rules, all enforced by SDK + `validate_guard_data`)
|
|
458
300
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
**
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
8. **QUERY_02 — Parameter count matches**: The parameter count and types in your query node must match the instruction exactly — off-by-one parameter counts are a common failure.
|
|
468
|
-
|
|
469
|
-
9. **QUERY_03 — Return type compatible**: The query node's return type must be compatible with the parent node's expected input. A `logic_equal` comparing a String to a U64 fails validation. Use explicit conversion nodes (`convert_string_number`, `convert_number_string`) when types differ. Numeric comparisons use `logic_as_u256_*` variants which auto-widen to U256.
|
|
470
|
-
|
|
471
|
-
10. **QUERY_04 — Object identifier is Address type**: The table entry referenced by a query node's `object.identifier` must have `value_type: Address`. SDK `buildNode` validates this at L603-609.
|
|
472
|
-
|
|
473
|
-
**Witness (3 items)**
|
|
474
|
-
|
|
475
|
-
11. **WITNESS_01 — Witness type valid (100-108)**: The `convert_witness` value must be one of the 9 valid witness types (100-108). Invalid witness types cause creation failure.
|
|
476
|
-
|
|
477
|
-
12. **WITNESS_02 — Witness target matches query objectType**: The witness's target object type must match the query instruction's expected object type. For example, `TypeOrderProgress` (100) derives a Progress, so the query must target a Progress object. SDK `buildNode` validates this at L613-619.
|
|
478
|
-
|
|
479
|
-
13. **WITNESS_03 — Witness source matches table object_type**: If the table entry has an `object_type` declared (auto-filled by SDK), it must match the witness's source object type. For example, `TypeOrderProgress` (100) expects an Order source, so the table entry's `object_type` must be Order. SDK `buildNode` validates this at L622-631. **Missing convert_witness** is a related failure: when accessing Progress data from an Order ID, the query node needs `convert_witness` with the appropriate witness type. Without it, the runtime looks for a Progress at the Order's address — which does not exist as a Progress object.
|
|
480
|
-
|
|
481
|
-
**Rely (3 items)**
|
|
482
|
-
|
|
483
|
-
14. **RELY_01 — Dependency count ≤ 4**: A Guard can depend on at most 4 other Guards (`MAX_DEPENDED_COUNT`). SDK `reliesAdd` enforces this limit.
|
|
484
|
-
|
|
485
|
-
15. **RELY_02 — Dependencies must have rep=true**: A Guard's `rely` entries must reference Guards with `rep: true` — meaning their `repository.data` queries do not depend on runtime submissions. Guards that depend on a Repository via submitted addresses (`rep: false`) cannot serve as dependencies. Move `guard::relies_add` catches violations at creation time.
|
|
486
|
-
|
|
487
|
-
16. **RELY_03 — No self-reference**: A Guard cannot depend on itself. SDK `reliesAdd` prevents self-referential rely entries.
|
|
488
|
-
|
|
489
|
-
**Binding (3 items)**
|
|
490
|
-
|
|
491
|
-
17. **BINDING_01 — voting_guard GuardIdentifier must be numeric**: When using `GuardIdentifier` for Arbitration `voting_guard`, the referenced table entry must have a numeric `value_type` (U8–U256). The system checks this when the VotingGuard is added to the Arbitration — if the identifier does not exist or is non-numeric, the operation reverts with `E_GUARD_IDENTIFIER_NOT_NUMBER`.
|
|
492
|
-
|
|
493
|
-
18. **BINDING_02 — Repository id_from_submission must be Address**: When a Repository `write_guard` uses `id_from_submission`, the referenced table entry must have `value_type: Address`. Move Repository enforces this at binding time.
|
|
494
|
-
|
|
495
|
-
19. **BINDING_03 — Repository data_from_submission type must match**: When a Repository `write_guard` uses `data_from_submission`, the referenced table entry's `value_type` must match the Repository's declared `value_type`. Move Repository enforces this at binding time.
|
|
496
|
-
|
|
497
|
-
**Input (2 items)**
|
|
498
|
-
|
|
499
|
-
20. **INPUT_01 — Root bytecode non-empty**: The serialized root computation tree must not be empty. SDK `newGuard` validates this before submission.
|
|
500
|
-
|
|
501
|
-
21. **INPUT_02 — Root bytecode size ≤ MAX_INPUT_SIZE**: The serialized root computation tree must not exceed `MAX_INPUT_SIZE`. SDK `newGuard` validates this before submission.
|
|
502
|
-
|
|
503
|
-
**Immutable (1 item)**
|
|
504
|
-
|
|
505
|
-
22. **IMMUTABLE_01 — Guard becomes immutable after creation**: Once `guard::create` is called, the Guard's `immutable` flag is set to `true` and no further modifications are possible. This is the foundation of the immutability contract — to change a Guard, export via `guard2file`, create a new Guard, and update all references.
|
|
301
|
+
**Root**: Must return Bool (logic/comparison nodes only).
|
|
302
|
+
**Table**: Unique identifiers (0–255), tree-to-table referential integrity, non-empty constants, max 256 entries / 40KB BCS, submission entries = 1-byte type code.
|
|
303
|
+
**Query**: Discover valid IDs via `wowok_buildin_info` ("guard instructions"); parameter count/types must match; return type must be compatible with parent (use `convert_string_number`/`convert_number_string` for type mismatches; `logic_as_u256_*` for numeric comparisons); `object.identifier` must be Address type.
|
|
304
|
+
**Witness**: 100–108 only; target type must match query's expected object; source type must match table's `object_type`. **Missing `convert_witness`** when accessing Progress from Order ID = runtime failure (looks for Progress at Order's address).
|
|
305
|
+
**Rely**: Max 4; must have `rep:true`; no self-reference.
|
|
306
|
+
**Binding**: `voting_guard` identifier must be numeric (U8–U256); Repository `id_from_submission` must be Address; `data_from_submission` type must match Repository's `value_type`.
|
|
307
|
+
**Immutable**: Guard frozen after `guard::create` — to change, export via `guard2file` and create new.
|
|
506
308
|
|
|
507
309
|
#### Practical Tips (not strict constraints, but strongly recommended)
|
|
508
310
|
|
|
@@ -524,126 +326,10 @@ These constraints are checked at Guard verification time (gen_passport or actual
|
|
|
524
326
|
- **RUN_TX_01**: The Passport's `tx_hash` must match the current transaction.
|
|
525
327
|
- **RUN_RELY_01**: Rely guards must have been added to the passport.
|
|
526
328
|
|
|
527
|
-
### Readability
|
|
528
|
-
|
|
529
|
-
> **Built-in MCP convention**: Whenever the schema accepts BOTH a numeric ID and a human-readable string name for the same field, **always prefer the string name** in examples, documentation, and AI-generated JSON. Numeric IDs are accepted for backward compatibility and compact machine output, but string names are the canonical form for any human-readable artifact.
|
|
530
|
-
|
|
531
|
-
This convention is grounded in the user-experience principle: *"Wherever the interface supports it, optimize from the user's understanding as the starting point."* A reader who sees `"query": "order.service"` understands the intent immediately; `"query": 1563` requires an extra lookup against the `GUARDQUERY` registry.
|
|
532
|
-
|
|
533
|
-
#### Fields Affected
|
|
329
|
+
### Readability Convention — Prefer String Names
|
|
534
330
|
|
|
535
|
-
|
|
536
|
-
|-------|-------------------------|----------------------|-----------------|
|
|
537
|
-
| `query` | `"order.service"` | `1563` | `GUARDQUERY` registry (375 entries, exported by `@wowok/wowok`) |
|
|
538
|
-
| `value_type` | `"Address"`, `"U64"`, `"String"` | `1`, `6`, `2` | `ValueType` enum |
|
|
539
|
-
| `context` | `"Signer"`, `"Clock"`, `"Guard"` | (numeric not accepted) | `Context` enum |
|
|
540
|
-
| `convert_witness` | `"OrderProgress"`, `"OrderMachine"` | `100`, `101` | `WitnessType` enum (SDK `parseWitnessType` / `witnessTypeToString`) |
|
|
331
|
+
**Always use string names** (not numeric IDs) for `query` (`"order.service"` not `1563`), `value_type` (`"Address"` not `1`), `convert_witness` (`"OrderProgress"` not `100`), and `context` (`"Signer"`). Matching is case-insensitive. SDK deserialization (`guard2file`/`query_objects`) returns all constants as strings. Discover valid query names via `wowok_buildin_info` with info `"guard instructions"`.
|
|
541
332
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
1. **Self-documenting JSON** — `"query": "order.service"` reads as intent; `1563` is opaque.
|
|
545
|
-
2. **Stable across registry renumbering** — names are part of the public contract; numeric IDs are an implementation detail.
|
|
546
|
-
3. **Case-insensitive matching** — `isValidGuardQueryName` lowercases both sides, so `"Order.Service"` and `"order.service"` are equivalent. Use the canonical lowercase form in examples.
|
|
547
|
-
4. **Lint-friendly** — string names survive refactoring; numeric IDs silently rot when an ID is deprecated.
|
|
548
|
-
|
|
549
|
-
#### Canonical Name Examples
|
|
550
|
-
|
|
551
|
-
The most common queries used in allocator Guards (R-C3-05 / R-C3-06 protection):
|
|
552
|
-
|
|
553
|
-
| Numeric ID | Canonical name | Returns | Typical use |
|
|
554
|
-
|------------|----------------|---------|-------------|
|
|
555
|
-
| `1253` | `progress.current` | String | Verify order is at a named node (with `convert_witness: 100`) |
|
|
556
|
-
| `1563` | `order.service` | Address | Cross-service theft protection (R-C3-05) |
|
|
557
|
-
| `1562` | `order.owner` | Address | Signer binding for refunds (R-C3-06 Level 2 dynamic) |
|
|
558
|
-
| `1272` | `progress.current_time` | U64 | Time-lock comparisons |
|
|
559
|
-
| `1488` | `service.permission` | Address | Verify Service's Permission object |
|
|
560
|
-
| `1002` | `permission.owner` | Address | Signer == permission owner (Level 1 fixed) |
|
|
561
|
-
| `1004` | `permission.admin has` | Bool | Caller is in admin set (Level 2 identity-set) |
|
|
562
|
-
| `1567` | `order.agent has` | Bool | Verify caller is an order agent |
|
|
563
|
-
|
|
564
|
-
#### WitnessType String Names
|
|
565
|
-
|
|
566
|
-
The `convert_witness` field accepts both numeric IDs (100-108) and string names. String matching is case-insensitive and accepts both the full enum name (`"TypeOrderProgress"`) and the shortened form without the `"Type"` prefix (`"OrderProgress"`). The shortened form is preferred for readability.
|
|
567
|
-
|
|
568
|
-
| Numeric ID | Shortened name (preferred) | Full enum name | Source → Target |
|
|
569
|
-
|------------|----------------------------|----------------|-----------------|
|
|
570
|
-
| `100` | `"OrderProgress"` | `"TypeOrderProgress"` | Order → Progress |
|
|
571
|
-
| `101` | `"OrderMachine"` | `"TypeOrderMachine"` | Order → Machine |
|
|
572
|
-
| `102` | `"OrderService"` | `"TypeOrderService"` | Order → Service |
|
|
573
|
-
| `103` | `"ProgressMachine"` | `"TypeProgressMachine"` | Progress → Machine |
|
|
574
|
-
| `104` | `"ArbOrder"` | `"TypeArbOrder"` | Arb → Order |
|
|
575
|
-
| `105` | `"ArbArbitration"` | `"TypeArbArbitration"` | Arb → Arbitration |
|
|
576
|
-
| `106` | `"ArbProgress"` | `"TypeArbProgress"` | Arb → Progress |
|
|
577
|
-
| `107` | `"ArbMachine"` | `"TypeArbMachine"` | Arb → Machine |
|
|
578
|
-
| `108` | `"ArbService"` | `"TypeArbService"` | Arb → Service |
|
|
579
|
-
|
|
580
|
-
SDK functions: `parseWitnessType(input)` converts string→number; `witnessTypeToString(type)` converts number→string (returns the shortened form). The SDK's Guard deserialization (`parseQueryNode`) already returns `convert_witness` as a string name.
|
|
581
|
-
|
|
582
|
-
#### Deserialization Output — All Protocol Constants Return Strings
|
|
583
|
-
|
|
584
|
-
The SDK's Guard deserialization (`query_objects` / `guard2file`) returns ALL protocol constants as user-friendly strings, not numeric IDs:
|
|
585
|
-
|
|
586
|
-
| Field | Returned as | Example | Conversion function |
|
|
587
|
-
|-------|-------------|---------|---------------------|
|
|
588
|
-
| `query` | String name | `"order.service"` | `GUARDQUERY` registry lookup |
|
|
589
|
-
| `value_type` | String name | `"Address"`, `"U64"` | `valueTypeToString()` |
|
|
590
|
-
| `convert_witness` | String name | `"OrderProgress"` | `witnessTypeToString()` |
|
|
591
|
-
| `context` | String literal | `"Signer"`, `"Clock"`, `"Guard"` | Hardcoded string |
|
|
592
|
-
| `object_type` | String name | `"Order"`, `"Service"` | `numberToObjectType` mapping |
|
|
593
|
-
| `type` (node discriminator) | String literal | `"logic_and"`, `"query"` | Always string |
|
|
594
|
-
|
|
595
|
-
This means `guard2file` JSON/Markdown output and `query_objects` results are fully self-documenting without requiring numeric ID lookups.
|
|
596
|
-
|
|
597
|
-
#### Example — Before and After
|
|
598
|
-
|
|
599
|
-
**Before (numeric, opaque):**
|
|
600
|
-
```json
|
|
601
|
-
{
|
|
602
|
-
"type": "logic_equal",
|
|
603
|
-
"nodes": [
|
|
604
|
-
{"type": "query", "query": 1563, "object": {"identifier": 0, "convert_witness": 100}, "parameters": []},
|
|
605
|
-
{"type": "identifier", "identifier": 2}
|
|
606
|
-
]
|
|
607
|
-
}
|
|
608
|
-
```
|
|
609
|
-
|
|
610
|
-
**After (string, self-documenting):**
|
|
611
|
-
```json
|
|
612
|
-
{
|
|
613
|
-
"type": "logic_equal",
|
|
614
|
-
"nodes": [
|
|
615
|
-
{"type": "query", "query": "order.service", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
|
|
616
|
-
{"type": "identifier", "identifier": 2}
|
|
617
|
-
]
|
|
618
|
-
}
|
|
619
|
-
```
|
|
620
|
-
|
|
621
|
-
Both forms are schema-valid and produce identical on-chain behavior; the string form is preferred for all human-readable output.
|
|
333
|
+
Common allocator-guard queries: `order.service` (theft protection), `order.owner` (refund binding), `progress.current` (node check), `progress.current_time` (time-lock), `service.permission`, `permission.owner`, `permission.admin has` (identity-set).
|
|
622
334
|
|
|
623
335
|
---
|
|
624
|
-
|
|
625
|
-
## Tool Reference
|
|
626
|
-
|
|
627
|
-
| Tool | Purpose |
|
|
628
|
-
|------|---------|
|
|
629
|
-
| `wowok_buildin_info` (`info: "guard instructions"`) | Discover all available query instructions — their IDs, parameter types, return types, and target object types |
|
|
630
|
-
| `wowok_buildin_info` (`info: "value types"`) | Discover the numeric codes for all supported value types used in table entries |
|
|
631
|
-
| `wowok_buildin_info` (`info: "built-in permissions"`) | Discover all built-in permission index codes for use with `permission.entity.perm has` queries |
|
|
632
|
-
| `onchain_operations` (`operation_type: "gen_passport"`) | Test Guard validation with runtime submissions and generate a verified on-chain credential on success |
|
|
633
|
-
| `guard2file` | Export an existing Guard's complete definition (description, table, root tree, dependencies) to a local JSON or Markdown file |
|
|
634
|
-
| `query_toolkit` (`query_type: "onchain_objects"`) | Query any Guard object on-chain by name or address to inspect its full definition |
|
|
635
|
-
| `schema_query` (`name: "onchain_operations_guard"`) | Retrieve the complete Guard operation schema with all parameter definitions |
|
|
636
|
-
|
|
637
|
-
---
|
|
638
|
-
|
|
639
|
-
---
|
|
640
|
-
|
|
641
|
-
## Appendices (Progressive Disclosure)
|
|
642
|
-
|
|
643
|
-
> The following sections have been extracted to [APPENDIX.md](./APPENDIX.md) for on-demand loading:
|
|
644
|
-
> - Dialogue Scripts (R1-R10) — guided conversation scripts
|
|
645
|
-
> - Decision Trees — branching logic reference
|
|
646
|
-
> - Failure Playbooks — recovery scenarios
|
|
647
|
-
> - Tier Layering — expertise-tier based guidance
|
|
648
|
-
>
|
|
649
|
-
> Load APPENDIX.md when the user needs guided dialogue, recovery help, or tier-specific guidance.
|