@wowok/skills 1.1.11 → 1.1.13

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.
@@ -53,7 +53,30 @@ Every Guard is built from three layers, each with a distinct role:
53
53
 
54
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
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` is the Guard's internal flag indicating it has no external Repository dependency and can serve as a dependency. Guards with `rep: false` cannot appear in `rely` lists. Violations are caught by the contract layer at creation time.
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.
57
+
58
+ ### Data Source 4 Classification — The Foundation of Guard Semantics
59
+
60
+ A Guard is fundamentally a **data computation tree**: deterministic data (on-chain constants + system context) + submitted data (runtime, semi-open) → derived through finite operation rules → a single boolean result. Every leaf node in the computation tree draws data from one of **4 data source classifications**. Understanding these 4 classifications is essential for designing and interpreting Guards.
61
+
62
+ | Type | Name | SDK Manifestation | Native Opcode | Trust Level | Typical Scenario |
63
+ |------|------|-------------------|---------------|-------------|------------------|
64
+ | **Type 1** | OnChainConstant | `query` + `identifier` (`b_submission: false`, no witness) | TYPE_QUERY + TYPE_CONSTANT | Highest | Query fields of already-published Service/Machine/Reward objects |
65
+ | **Type 2** | WitnessDerived | `query` + `identifier` + `convert_witness` (100-108) | TYPE_QUERY + witness_byte | High (source trusted + deterministic derivation) | Order → Progress query via witness=100 |
66
+ | **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
+ | **Type 4** | SystemContext | `context` (Signer/Clock/Guard) | TYPE_SIGNER / TYPE_CLOCK / TYPE_GUARD | Highest | Identity verification, time-locks |
68
+
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
74
+
75
+ **The table as data contract**: The table declares:
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").
57
80
 
58
81
  ### Where Guards Attach in the Ecosystem
59
82
 
@@ -148,26 +171,43 @@ The Guard table is the **complete declaration of information** the Guard consume
148
171
  - **No duplicate identifiers.** Each index number must appear exactly once.
149
172
  - **Non-submission entries must have a value.** These are baked into the Guard immutably.
150
173
  - **Submission entries use placeholder values.** The actual value is provided by the caller at runtime.
151
- - **Query target objects must be of type Address in the table.** Their `object_type` field should match the expected query target type (Progress, Order, Machine, Reward, etc.).
174
+ - **Query target objects must be of type Address in the table.** The `object_type` field is **automatically filled by the SDK** based on the first query node referencing this identifier (it is NOT a user-provided field). The SDK infers the object type from the query instruction's target object type (Progress, Order, Machine, Reward, etc.).
152
175
  - **Querying EntityRegistrar or EntityLinker requires system address table entries.** Add entries for `ENTITY_REGISTRAR_ADDRESS` (`0xaab`) or `ENTITY_LINKER_ADDRESS` (`0xaaa`) to the table as Address-type constants when your query instruction targets these global registries. Without them, creation fails.
153
176
  - **Maximum 256 table entries** (identifiers 0–255). The total serialized table size must not exceed 40000 bytes.
154
177
  - **Submission entries must have descriptive `name` values.** For `b_submission: true` entries, `name` is the contract between Guard and caller — it tells callers what data they must provide. Use natural language that explains the purpose and necessity: "The order ID that identifies the target Order for verification" not `"order_id"`, "The signer's account address that will be compared against the authorized list" not `"addr"`. This is critical because callers see only this name when submitting data.
155
178
 
156
179
  ### The convert_witness Mechanism
157
180
 
158
- `convert_witness` transforms a submitted object ID into its associated object — enabling queries across object relationships without requiring the caller to submit multiple IDs.
181
+ `convert_witness` transforms a source object ID into its associated target object — enabling queries across object relationships without requiring the caller to submit multiple IDs. This is the **Type 2 (WitnessDerived)** data source.
159
182
 
160
- **Core principle**: Caller submits what they have (e.g., Order ID); Guard queries what it needs (e.g., Progress state) via witness conversion.
183
+ **Core principle**: Witness is a "read the source object's associated field" mechanism (not a lookup table, not an independent index). It is a one-to-one deterministic derivation of object relationships with only 9 derivation types. Caller submits what they have (e.g., Order ID); Guard queries what it needs (e.g., Progress state) via witness conversion.
161
184
 
162
185
  **Rules**:
163
186
  - Witness type encodes source→target transformation
164
- - Table entry's `object_type` must match witness source type
187
+ - Table entry's `object_type` (auto-filled by SDK) must match witness source type
165
188
  - Query instruction's object type must match witness target type
166
189
  - Type mismatches cause Guard creation to fail
167
-
168
- **Available witness types** are defined in the schema — query `wowok_buildin_info` with info `"guard instructions"` for the complete list with use cases.
169
-
170
- **Notable**: `TypeArbArbitration (105)`: Arb and Arbitration are **different on-chain objects**. The witness queries the Arbitration (parent service) from an Arb (case) address — the binding is set when Arbitration creates the Arb. Schema describes this as "access arbitration configuration or fee settings."
190
+ - Multi-hop witnesses (106-108) require intermediate objects to exist
191
+
192
+ **Complete 9 witness types** (defined in `guard.rs#L34-L65`):
193
+
194
+ | Code | Name | Source → Target | Derivation | Hops |
195
+ |------|------|-----------------|------------|------|
196
+ | 100 | TypeOrderProgress | Order → Progress | read order.progress field | 1 |
197
+ | 101 | TypeOrderMachine | Order → Machine | read order.machine field | 1 |
198
+ | 102 | TypeOrderService | Order → Service | read order.service field | 1 |
199
+ | 103 | TypeProgressMachine | Progress → Machine | read progress.machine field | 1 |
200
+ | 104 | TypeArbOrder | Arb → Order | read arb.order field | 1 |
201
+ | 105 | TypeArbArbitration | Arb → Arbitration | read arb.arbitration field | 1 |
202
+ | 106 | TypeArbProgress | Arb → Progress | arb.order → order.progress | 2 (multi-hop) |
203
+ | 107 | TypeArbMachine | Arb → Machine | arb.order → order.machine | 2 (multi-hop) |
204
+ | 108 | TypeArbService | Arb → Service | arb.order → order.service | 2 (multi-hop) |
205
+
206
+ **Key notes**:
207
+ - **Type 2 can overlay on Type 1 or Type 3**: The source object can be a constant (Type 1, `b_submission: false`) or a submission (Type 3, `b_submission: true`). The witness then derives the target object.
208
+ - **Multi-hop witnesses (106-108)**: Arb → Progress/Machine/Service uses two hops (Arb → Order → target). The intermediate Order object must exist for the derivation to succeed.
209
+ - **TypeArbArbitration (105)**: Arb and Arbitration are **different on-chain objects**. The witness queries the Arbitration (parent service) from an Arb (case) address — the binding is set when Arbitration creates the Arb.
210
+ - **Available witness types** are also discoverable via `wowok_buildin_info` with info `"guard instructions"`.
171
211
 
172
212
  ---
173
213
 
@@ -281,6 +321,8 @@ Machine's forward `guard` validates state transitions. If `retained_submission`
281
321
 
282
322
  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.
283
323
 
324
+ **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.
325
+
284
326
  ---
285
327
 
286
328
  **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.
@@ -303,460 +345,114 @@ Each object extracts Guard data with precise type expectations. Mismatches cause
303
345
 
304
346
  ### Common Pitfalls
305
347
 
306
- 1. **Undefined table identifiers**: Every `identifier` node in the tree must match an entry in the table. Missing entries cause creation failure validate your tree against your table before submitting.
307
-
308
- 2. **Type mismatches in comparison nodes**: 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.
309
-
310
- 3. **Wrong query instruction IDs or parameter counts**: Query instructions are system-defined. Always discover them through `wowok_buildin_info` with info `"guard instructions"`. The parameter count and types in your query node must match the instruction exactly — off-by-one parameter counts are a common failure.
311
-
312
- 4. **Missing convert_witness**: When accessing Progress data from an Order ID in the table, 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. The creation-time validation catches this mismatch.
313
-
314
- 5. **Testing with production durations**: Set time-lock durations to small values (e.g., 1000 milliseconds) during testing. Increase to production values only after verifying the logic works correctly. A Guard with a 30-day lock tested with real durations cannot produce results for a month.
315
-
316
- 6. **Forgetting to export before recreating**: Guards are immutable. If you need to change one, export it first with `guard2file` so you have the exact on-chain definition as a reference. Then create a new Guard with a versioned name and update all references.
317
-
318
- 7. **Root not returning 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.
319
-
320
- 8. **Dependency on non-standalone Guards**: A Guard's `rely` entries must reference Guards with `rep: true` — meaning they have no external Repository dependency. Guards that depend on a Repository (`rep: false`) cannot serve as dependencies. The contract layer catches violations at creation time.
321
-
322
- 9. **Forgetting voting_guard weight type validation**: When using `GuardIdentifier`, the referenced identifier must exist in the guard's table and its value type must be numeric. 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`.
323
-
324
- 10. **Not checking Arbitration pause state**: Even with a valid usage_guard Passport, the dispute fails if the Arbitration is paused (`bPaused: true`). The pause check happens before the guard check — advise customers to verify the Arbitration is active before generating Passports.
325
-
326
- ---
327
-
328
- ## Tool Reference
329
-
330
- | Tool | Purpose |
331
- |------|---------|
332
- | `wowok_buildin_info` (`info: "guard instructions"`) | Discover all available query instructions — their IDs, parameter types, return types, and target object types |
333
- | `wowok_buildin_info` (`info: "value types"`) | Discover the numeric codes for all supported value types used in table entries |
334
- | `wowok_buildin_info` (`info: "built-in permissions"`) | Discover all built-in permission index codes for use with `permission.entity.perm has` queries |
335
- | `onchain_operations` (`operation_type: "gen_passport"`) | Test Guard validation with runtime submissions and generate a verified on-chain credential on success |
336
- | `guard2file` | Export an existing Guard's complete definition (description, table, root tree, dependencies) to a local JSON or Markdown file |
337
- | `query_toolkit` (`query_type: "onchain_objects"`) | Query any Guard object on-chain by name or address to inspect its full definition |
338
- | `schema_query` (`name: "onchain_operations_guard"`) | Retrieve the complete Guard operation schema with all parameter definitions |
339
-
340
- ---
341
-
342
- ## Dialogue Scripts (R1-R10)
343
-
344
- A 10-round dialogue for the Guard authoring journey: from "I need a validation rule" through "tested, bound, and live". Guards are CREATE-only and immutable — this dialogue is deliberately heavy on design (R1-R6) before any on-chain write (R7), because there is no edit phase after creation. The sequence covers the four canonical Guard contexts (buy_guard, machine Forward guard, Allocator guard, Arbitration voting_guard) but the same shape applies to reward, repository, and demand Guards.
345
-
346
- ### R1: Validation Intent Capture
347
-
348
- **AI Goal**: Articulate the business requirement the Guard will enforce, in plain language, before any technical design. Identify which of the §Quick Decision patterns fits.
349
-
350
- **Key Questions**:
351
- - What action is being protected? (Buying, advancing a node, releasing funds, voting, filing a dispute, claiming a reward, writing to a repository?)
352
- - What single sentence describes the rule? (e.g., "Only the author can purchase this service", "Customer must wait 8 hours before completing", "Only sunny weather on the activity date".)
353
- - What should cause the Guard to FAIL? (Listing the failure conditions often clarifies the logic more than listing success conditions.)
354
-
355
- **Tool Calls**:
356
- 1. `wowok_buildin_info` → `info: "guard instructions"` — pre-fetch the full query instruction catalog so R3's design references real IDs.
357
- 2. `wowok_buildin_info` → `info: "value types"` — pre-fetch the type code mapping so R2's table uses correct `value_type` strings.
358
- 3. (Internal) Map the user's intent to one of the §Quick Decision patterns: identity check, time-lock, external data, progress state, one-time claim, dynamic weight, repository data, entity reputation.
359
-
360
- **Success Criteria**: AI restates the validation intent as "The Guard passes when X, Y, Z are all true; otherwise it fails." The user confirms.
361
-
362
- **Fallback**: User's intent doesn't fit any pattern → treat as a multi-condition Guard (combine multiple `query` nodes with `logic_and`). User's intent is genuinely unclear → ask for a concrete scenario: "Walk me through a case where the Guard should pass, and a case where it should fail."
363
-
364
- **Checkpoint**: Persist `{ round: R1, intent: <sentence>, pattern: <name>, host_object: <Service|Machine|Arbitration|...> }` via `local_info_operation`.
365
-
366
- ### R2: Table Declaration
367
-
368
- **AI Goal**: Define every piece of data the Guard touches — constants (`b_submission: false`) and runtime submissions (`b_submission: true`) — each with a unique `identifier` (0–255) and a `value_type`.
369
-
370
- **Key Questions**:
371
- - For each piece of data: is it a constant baked in at creation, or a value the caller submits at runtime?
372
- - For each submission entry: what is its `value_type`? (Bool, Address, String, U8–U256, or vector types — confirm codes via `wowok_buildin_info`.)
373
- - For each submission entry: what should its `name` field say? (The `name` is the contract with callers — natural language describing what they must provide.)
374
- - Will the Guard query EntityRegistrar (`0xaab`) or EntityLinker (`0xaaa`)? If yes, add Address-type constant entries for these system addresses.
375
-
376
- **Tool Calls**:
377
- 1. (Internal) Build the table: `[{identifier, b_submission, value_type, value?, name, object_type?}]`.
378
- 2. Validate: no duplicate identifiers; every non-submission entry has a `value`; query target objects are Address-type with correct `object_type`; max 256 entries; total serialized size ≤ 40000 bytes.
379
- 3. For submission entries, draft the `name` in natural language (per §Design Rules): e.g., "The order ID that identifies the target Order for verification", not "order_id".
380
-
381
- **Success Criteria**: AI presents the full table with all fields populated. The user confirms each submission entry's `name` is clear enough that a caller would know what to provide.
382
-
383
- **Fallback**: User wants more than 256 entries → decompose into multiple Guards composed via `rely`. User wants to query an object whose type is ambiguous → confirm the `object_type` field per §Design Rules. User submits a Value type 19 → block, cite [wowok-safety](../wowok-safety/SKILL.md) §8.1 ("Never use Value type 19").
384
-
385
- **Checkpoint**: Persist `{ round: R2, table: [...], submission_count, constant_count }`.
386
-
387
- ### R3: Computation Tree Sketch
388
-
389
- **AI Goal**: Sketch the root computation tree that produces the final Bool verdict. Identify each node's type and return type before writing any JSON.
390
-
391
- **Key Questions**:
392
- - What is the root node? (Must return Bool — typically `logic_and`, `logic_or`, `logic_equal`, or a comparison.)
393
- - What are the data source nodes? (`identifier` for table values, `context` for Clock/Signer/self-ID, `query` for on-chain objects.)
394
- - What are the intermediate transformation nodes? (`calc_number_*` for arithmetic, `convert_*` for type transformations, `vec_*` for vector operations, `query_progress_history_*` / `query_reward_record_*` for historical data.)
395
- - Are there cross-object queries? If yes, which `convert_witness` type derives the target from a submitted ID?
396
-
397
- **Tool Calls**:
398
- 1. `schema_query` → `get` for `onchain_operations_guard` — retrieve the complete `GuardNodeSchema` with every node type, its required fields, and input/output types.
399
- 2. `wowok_buildin_info` → `info: "guard instructions"` (filtered by `name`, `return_type`, `param_count`, or `object_type`) — confirm each `query` node's instruction ID and parameter count.
400
- 3. (Internal) Walk the tree: every `identifier` index exists in the table; every comparison receives compatible operand types; every `query` node's parameter count matches the instruction; the root returns Bool.
401
-
402
- **Success Criteria**: AI presents the tree as an indented outline showing each node's type and the data flow. The user confirms the logic matches their R1 intent.
403
-
404
- **Fallback**: Type mismatch at a comparison node → insert an explicit `convert_*` node (e.g., `convert_string_number`, `convert_number_string`) or use `logic_as_u256_*` variants for cross-width numeric comparisons. Root returns non-Bool → wrap with a final `logic_equal` or `logic_and` that produces Bool. `query` node parameter count off-by-one → re-check the instruction definition, fix the parameter list.
405
-
406
- **Checkpoint**: Persist `{ round: R3, root_node_type, tree_depth, query_nodes: [{instruction_id, param_count, convert_witness?}] }`.
407
-
408
- ### R4: `rely` Composition (Optional)
409
-
410
- **AI Goal**: Decide whether the Guard depends on other Guards via `rely` (up to 4 dependencies, AND/OR logic). Use composition to avoid monolithic trees.
411
-
412
- **Key Questions**:
413
- - Does this Guard's logic naturally decompose into independent sub-rules? (e.g., " KYC verified AND amount within cap AND not blacklisted" = 3 sub-Guards.)
414
- - For each candidate dependency: does it have `rep: true`? (Guards with `rep: false` — those depending on a Repository — cannot serve as dependencies.)
415
- - AND or OR logic? (Default AND — all must pass. OR — any passing is sufficient.)
416
-
417
- **Tool Calls**:
418
- 1. `query_toolkit` → `onchain_objects` for each candidate dependency Guard — confirm it exists and inspect its `rep` field.
419
- 2. (Internal) Validate: max 4 dependencies; all dependencies have `rep: true`; logic_or flag set correctly.
420
-
421
- **Success Criteria**: Either: the Guard has no dependencies (skip R4), OR the `rely` list is finalized with verified `rep: true` Guards and the AND/OR logic is set.
422
-
423
- **Fallback**: A desired dependency has `rep: false` → either inline its logic into the current Guard's tree, or create a new standalone Guard with `rep: true` that captures the same logic. User wants more than 4 dependencies → consolidate by combining related sub-rules into fewer Guards.
424
-
425
- **Checkpoint**: Persist `{ round: R4, rely: [{guard_id, guard_name}], logic_or: bool }`.
426
-
427
- ### R5: Host Object & Binding Plan
428
-
429
- **AI Goal**: Decide where the Guard attaches and confirm the binding pattern (especially the circular reference pattern for object-Guard mutual references).
348
+ > 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`.
430
349
 
431
- **Key Questions**:
432
- - Which host object will this Guard bind to? (Service `buy_guard`, Service `order_allocators[].guard`, Machine Forward `guard`, Arbitration `usage_guard` / `voting_guard[]`, Reward `guard`, Repository `write_guard`, Demand `ServiceGuard`.)
433
- - Does the Guard reference the object it protects? (If yes, use the circular reference pattern: CREATE object without Guard → CREATE Guard referencing object by NAME → MODIFY object to bind Guard.)
434
- - For Arbitration `voting_guard` with `GuardIdentifier`: is the referenced table entry numeric (U8–U256)? (Required — the value is cast to u32 as vote weight.)
435
- - For Repository `write_guard`: are `id_from_submission` entries Address-type and `data_from_submission` entries matching the Repository's `value_type`?
350
+ #### Creation-Phase Constraints (22 items, enforced by SDK + native `validate_guard_data`)
436
351
 
437
- **Tool Calls**:
438
- 1. (Internal) Classify the binding target per the §Where Guards Attach table.
439
- 2. For circular references: confirm the object's NAME (string) is used in the Guard table, NOT the object's address (which doesn't exist yet at Guard creation time). The SDK resolves the name at runtime.
440
- 3. For Arbitration `voting_guard`: validate the `GuardIdentifier` index points to a numeric table entry.
441
- 4. For Repository `write_guard`: validate `id_from_submission` and `data_from_submission` index types.
352
+ **Root (1 item)**
442
353
 
443
- **Success Criteria**: The binding plan is documented: Guard name, host object, binding field, circular-reference steps (if applicable), type constraints satisfied.
354
+ 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.
444
355
 
445
- **Fallback**: User wants to bind to a Machine that's already published → impossible to attach new Guards (immutable). Must create a new Machine. User wants `voting_guard` weight from a non-numeric submission → re-design the table to use a numeric type (U8/U16/U32/U64/U128/U256).
356
+ **Table (5 items)**
446
357
 
447
- **Checkpoint**: Persist `{ round: R5, host_object, binding_field, circular_reference: bool, type_constraints_verified: true }`.
358
+ 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.
448
359
 
449
- ### R6: Pre-Create Review
360
+ 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.
450
361
 
451
- **AI Goal**: Walk through the full Guard definition one final time before the irreversible CREATE. Cross-reference the §10 Common Pitfalls traps.
362
+ 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.
452
363
 
453
- **Key Questions**:
454
- - Confirm: every `identifier` in the tree exists in the table? (Trap 1.)
455
- - Confirm: every comparison node receives compatible operand types? (Trap 2 — use explicit `convert_*` nodes where types differ.)
456
- - Confirm: every `query` node's instruction ID and parameter count match the spec from `wowok_buildin_info`? (Trap 3.)
457
- - Confirm: every cross-object query has the correct `convert_witness`? (Trap 4 — e.g., `TypeOrderProgress` = 100 to query Progress from an Order ID.)
458
- - Confirm: time-lock durations are small (e.g., 1000ms) for testing, not production values? (Trap 5.)
459
- - Confirm: root returns Bool? (Trap 7.)
460
- - Confirm: all `rely` dependencies have `rep: true`? (Trap 8.)
364
+ 5. **TABLE_04 — Table size limits**: Maximum 256 table entries (identifiers 0–255), and the total serialized table size must not exceed 40000 bytes (BCS). Enforced by Move `guard::new`.
461
365
 
462
- **Tool Calls**:
463
- 1. (Internal) Run the §10 Common Pitfalls checklist.
464
- 2. `guard2file` → (if iterating on an existing Guard) export the previous version as a reference. The new Guard will be a fresh CREATE with a versioned name.
465
- 3. (Optional) Write the full Guard definition to a local scratch file via `local_info_operation` for the user to review before CREATE.
366
+ 6. **TABLE_05 — Submission value is 1-byte type code**: When `b_submission=true`, the `value` field is only a 1-byte type code placeholder (the actual value is provided at runtime). Enforced by native `deserialize_constants`.
466
367
 
467
- **Success Criteria**: All 10 pitfalls pass. AI presents the final Guard definition (table + tree + rely) and the user explicitly confirms "create it".
368
+ **Query (4 items)**
468
369
 
469
- **Fallback**: Any pitfall fails return to R2/R3/R4 and fix. User hesitates offer to export the design as a scratch file for offline review. Never CREATE without explicit confirmation.
370
+ 7. **QUERY_01 Query instruction ID valid**: Query instruction IDs are system-defined. Always discover them through `wowok_buildin_info` with info `"guard instructions"`. Invalid IDs cause creation failure.
470
371
 
471
- **Checkpoint**: Persist `{ round: R6, audit_pass: true, user_confirmed: true, design_frozen: true }`.
372
+ 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.
472
373
 
473
- ### R7: CREATE the Guard
374
+ 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.
474
375
 
475
- **AI Goal**: Execute the single atomic `onchain_operations` `operation_type: "guard"` CREATE. There is no draft state, no editing, no deletion this either succeeds (Guard frozen on-chain) or fails (nothing created).
376
+ 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.
476
377
 
477
- **Key Questions**:
478
- - Confirm the Guard name (versioned: `<project>_guard_<purpose>_v1` per [wowok-safety](../wowok-safety/SKILL.md) §4).
479
- - Confirm `root.type`: `"node"` (inline tree) or `"file"` (from a `guard2file` export).
480
- - Confirm the operating account and `env.no_cache: true`.
378
+ **Witness (3 items)**
481
379
 
482
- **Tool Calls**:
483
- 1. `onchain_operations` → `operation_type: "guard"` CREATE with the full `data`: `name`, `description`, `table`, `root`, `rely` (if any).
484
- 2. If CREATE succeeds: `query_toolkit` → `onchain_objects` for the new `guard_id` — verify the table and tree are present and `rep` is set correctly.
485
- 3. `local_mark_operation` → tag the Guard (e.g., `freelance_buy_guard_v1`).
380
+ 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.
486
381
 
487
- **Success Criteria**: Guard created on-chain. Query confirms table, root tree, and `rely` are all present. Local mark persisted.
382
+ 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.
488
383
 
489
- **Fallback**: CREATE fails with type-validation error return to R3, inspect the error message (usually names the offending node and expected vs actual types), fix the tree, re-attempt CREATE. CREATE fails with "identifier not in table" return to R2/R3, fix the missing entry. CREATE fails with "rely references non-standalone Guard" return to R4, replace the `rep: false` dependency. Name collision append `_v1`/`_v2`.
384
+ 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.
490
385
 
491
- **Checkpoint**: Persist `{ round: R7, guard_id, guard_name, created: true, rep: bool }`.
386
+ **Rely (3 items)**
492
387
 
493
- ### R8: `gen_passport` Static Test
388
+ 14. **RELY_01 — Dependency count ≤ 4**: A Guard can depend on at most 4 other Guards (`MAX_DEPENDED_COUNT`). SDK `reliesAdd` enforces this limit.
494
389
 
495
- **AI Goal**: Verify the Guard's logic with mock submissions via `gen_passport`. This is the only way to test a Guard in isolation before binding it to a live object.
390
+ 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.
496
391
 
497
- **Key Questions**:
498
- - For each submission entry, what test value should I use? (Use edge cases: empty, boundary values, unusual addresses per [wowok-guard](../wowok-guard/SKILL.md) §Phase 5.)
499
- - Should I test multiple scenarios? (Pass case, fail case, edge case.)
500
- - For time-lock Guards: is the test duration small (1000ms)? (Production durations like 30 days cannot produce results for a month — trap 5.)
392
+ 16. **RELY_03 — No self-reference**: A Guard cannot depend on itself. SDK `reliesAdd` prevents self-referential rely entries.
501
393
 
502
- **Tool Calls**:
503
- 1. `onchain_operations` → `operation_type: "gen_passport"` with the Guard ID and mock `info` submissions. (Each Guard's submission is passed independently via `info` — NOT via `data.submission`.)
504
- 2. Omit `info` to auto-fetch existing submissions from the Guard (if any) — useful for re-testing with the same data.
505
- 3. Capture the result: PASS (Passport generated) or FAIL (which logic/query node returned false).
506
- 4. On PASS: `query_toolkit` → `onchain_objects` for the new Passport — inspect its data, validated Guards, and timestamp.
394
+ **Binding (3 items)**
507
395
 
508
- **Success Criteria**: `gen_passport` returns PASS for the expected-pass scenario. (Optional but recommended: also test the expected-fail scenario and confirm it fails for the right reason.)
396
+ 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`.
509
397
 
510
- **Fallback**: `gen_passport` fails inspect the error to identify which node returned false. Use `guard2file` to export the Guard, walk the tree manually, identify the logic gap. If the Guard logic is genuinely wrong → CREATE a new Guard with corrected logic (immutable — cannot edit), re-test. Do NOT bind a failing Guard to a host object.
398
+ 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.
511
399
 
512
- **Checkpoint**: Persist `{ round: R8, passport_id, test_result: pass, scenarios_tested: [...] }`.
400
+ 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.
513
401
 
514
- ### R9: Bind to Host Object
402
+ **Input (2 items)**
515
403
 
516
- **AI Goal**: Attach the tested Guard to its host object per the R5 binding plan. Use the circular reference pattern where applicable.
404
+ 20. **INPUT_01 Root bytecode non-empty**: The serialized root computation tree must not be empty. SDK `newGuard` validates this before submission.
517
405
 
518
- **Key Questions**:
519
- - Confirm the host object exists and is in the right state (e.g., Machine unpublished for Forward Guards, Arbitration paused for voting_guard).
520
- - For circular references: is the host object's NAME used in the Guard table? (The SDK resolves it at runtime — the address didn't exist when the Guard was created.)
406
+ 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.
521
407
 
522
- **Tool Calls**:
523
- 1. For Machine Forward binding: `onchain_operations` → `operation_type: "machine"` MODIFY, using `node` operations (`add forward` or `set` with `bReplace: false`) to set the Forward's `guard` field (with optional `retained_submission`).
524
- 2. For Service `buy_guard`: `onchain_operations` → `operation_type: "service"` MODIFY to set `buy_guard`.
525
- 3. For Service `order_allocators[].guard`: `onchain_operations` → `operation_type: "service"` MODIFY to set the Allocator's `guard`.
526
- 4. For Arbitration `voting_guard` / `usage_guard`: `onchain_operations` → `operation_type: "arbitration"` MODIFY.
527
- 5. For Reward `guard_add`: `onchain_operations` → `operation_type: "reward"` MODIFY.
528
- 6. For Repository `write_guard`: `onchain_operations` → `operation_type: "repository"` MODIFY.
529
- 7. `guard2file` → export the bound Guard for the audit trail.
408
+ **Immutable (1 item)**
530
409
 
531
- **Success Criteria**: Guard is bound to the host object. Querying the host object (via `query_toolkit` `onchain_objects`) shows the Guard reference in the correct field.
410
+ 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.
532
411
 
533
- **Fallback**: Binding fails because host object is immutable (Machine published, Service published, etc.) must create a new host object. Binding fails with type constraint (e.g., `voting_guard` `GuardIdentifier` not numeric) → return to R2, fix the table entry type, CREATE a new Guard, re-test, rebind.
412
+ #### Practical Tips (not strict constraints, but strongly recommended)
534
413
 
535
- **Checkpoint**: Persist `{ round: R9, bound_to: <host_object_id>, binding_field, export_path }`.
414
+ - **Testing with production durations**: Set time-lock durations to small values (e.g., 1000 milliseconds) during testing. Increase to production values only after verifying the logic works correctly. A Guard with a 30-day lock tested with real durations cannot produce results for a month.
415
+ - **Forgetting to export before recreating**: Guards are immutable. If you need to change one, export it first with `guard2file` so you have the exact on-chain definition as a reference. Then create a new Guard with a versioned name and update all references.
416
+ - **Not checking Arbitration pause state**: Even with a valid usage_guard Passport, the dispute fails if the Arbitration is paused (`bPaused: true`). The pause check happens before the guard check — advise customers to verify the Arbitration is active before generating Passports.
536
417
 
537
- ### R10: Post-Bind Verification & Iteration Plan
418
+ #### Runtime-Phase Constraints (enforced by native `verify_guard`)
538
419
 
539
- **AI Goal**: Verify the Guard is live and effective. Document the iteration workflow for future changes (Guards are immutable iteration = export edit → CREATE new → rebind).
420
+ These constraints are checked at Guard verification time (gen_passport or actual usage), not at creation. They are often overlooked because creation succeeds but runtime fails:
540
421
 
541
- **Key Questions**:
542
- - Want me to query the host object and show the Guard in context?
543
- - Do you anticipate needing to change this Guard's logic later? (If yes, document the export → edit → CREATE new → rebind workflow now while context is fresh.)
544
- - For Arbitration `voting_guard`: is the Arbitration still paused? (Unpause only after all Guards are bound and tested.)
545
-
546
- **Tool Calls**:
547
- 1. `query_toolkit` `onchain_objects` for the host object confirm the Guard reference is present and `_guard_node_comments` (human-readable annotations) match the intended logic.
548
- 2. `onchain_events` confirm any Guard-related events fired (e.g., Guard bound event).
549
- 3. `guard2file` export the final bound Guard as the canonical reference for future iteration.
550
- 4. `local_info_operation` → persist the iteration workflow: "To change this Guard: (1) `guard2file` export, (2) edit JSON, (3) CREATE new Guard with versioned name, (4) re-test via `gen_passport`, (5) rebind to host object, (6) update all references."
551
-
552
- **Success Criteria**: Guard is live, verified, and the iteration workflow is documented. Handoff packet produced for the host object's Skill ([wowok-provider](../wowok-provider/SKILL.md), [wowok-machine](../wowok-machine/SKILL.md), [wowok-arbitrator](../wowok-arbitrator/SKILL.md), etc.).
553
-
554
- **Fallback**: Post-bind verification shows the Guard isn't where expected → check the binding field name (common mistake: binding to `buy_guard` when the user meant `order_allocators[].guard`). Re-call the MODIFY with the correct field. If the host object is now immutable → create a new host object.
555
-
556
- **Checkpoint**: Persist `{ round: R10, verified: true, iteration_workflow_documented: true, handoff_emitted: true }`. Mark Guard design COMPLETE.
422
+ - **RUN_IMMUTABLE_01**: Guard must have `immutable=true` to be verified. A Guard that hasn't been finalized via `guard::create` cannot be used.
423
+ - **RUN_SUB_01**: The submission's `value[0]` (type byte) must match the table declaration. A submission with the wrong type byte is rejected.
424
+ - **RUN_SUB_02**: Every table entry with `b_submission=true` must have a corresponding submission value. Missing submissions cause failure.
425
+ - **RUN_SUB_03**: Total submission bytes must be `MAX_SUBMISSION_SIZE` (256).
426
+ - **RUN_WITNESS_01/02**: When witness conversion runs, the source object must have the associated field, and the derived target object must exist. Multi-hop witnesses (106-108) require the intermediate Order object to exist.
427
+ - **RUN_QUERY_01**: The query target object must exist and its type must match.
428
+ - **RUN_IMPACK_01/02**: At least one impack guard is required; an impack guard failure fails the entire passport. **Note**: `impack_list` is always empty during verify (see Repository section above), so quote_guard queries will fail unless `quote_guard = None`.
429
+ - **RUN_TX_01**: The Passport's `tx_hash` must match the current transaction.
430
+ - **RUN_RELY_01**: Rely guards must have been added to the passport.
557
431
 
558
432
  ---
559
433
 
560
- ## Decision Trees
561
-
562
- ### D1: Guard Pattern Selection
563
-
564
- ```
565
- What are you validating?
566
- ├── Identity (single address or allowlist)? ──→ context(Signer) + logic_equal / vec_contains_address
567
- ├── Time constraint? ──→ context(Clock) + calc_number_* comparisons
568
- ├── External on-chain data? ──→ query + table entry declaring target object address
569
- ├── Progress state / forward history? ──→ query_progress_history_* + convert_witness (TypeOrderProgress=100)
570
- ├── One-time claim (no prior record)? ──→ query_reward_record_count + logic_equal(0)
571
- ├── Dynamic vote weight? ──→ GuardIdentifier + numeric table entry (b_submission: true)
572
- ├── External Repository data? ──→ query + table entry declaring Repository address
573
- ├── Entity reputation / tier? ──→ query + table entry for ENTITY_REGISTRAR_ADDRESS (0xaab) or ENTITY_LINKER_ADDRESS (0xaaa)
574
- └── Multi-condition (combine above)? ──→ multiple query/logic nodes joined with logic_and / logic_or
575
- ```
576
-
577
- ### D2: Submission vs Constant Table Entry
578
-
579
- ```
580
- For each piece of data the Guard touches:
581
- ├── Value known at Guard creation time and never changes? ──→ CONSTANT (b_submission: false, value: <baked_in>)
582
- │ ├── System address (EntityRegistrar, EntityLinker)? ──→ Address-type constant with the system address
583
- │ ├── Query target object address? ──→ Address-type constant OR name reference (circular pattern)
584
- │ └── Threshold / cap / duration? ──→ Numeric constant (use small values for testing per trap 5)
585
- ├── Value provided by the caller at runtime? ──→ SUBMISSION (b_submission: true, value: <placeholder>)
586
- │ ├── Will the host object read this value? ──→ ensure type matches host's extraction field (e.g., Repository data_from_submission must match value_type)
587
- │ └── Will this value be retained in Progress? ──→ ensure Machine Forward's retained_submission references the right index
588
- └── Value derived from another submitted object? ──→ SUBMISSION of the source ID + convert_witness in the query node
589
- ```
590
-
591
- ### D3: `convert_witness` Selection
592
-
593
- ```
594
- Guard needs to query object B, but caller submits object A's ID:
595
- ├── A = Order, B = Progress? ──→ convert_witness: TypeOrderProgress (100)
596
- ├── A = Arb (case), B = Arbitration (parent service)? ──→ convert_witness: TypeArbArbitration (105)
597
- ├── A = Order, B = Service? ──→ convert_witness: TypeOrderService
598
- ├── A = Progress, B = Machine? ──→ convert_witness: TypeProgressMachine
599
- ├── A = Reward, B = Service? ──→ convert_witness: TypeRewardService
600
- ├── Other source→target pairs? ──→ query wowok_buildin_info (info: "guard instructions") for the complete witness type catalog
601
- └── No conversion needed (caller submits the exact object the Guard queries)? ──→ omit convert_witness
602
- ```
603
-
604
- ### D4: Binding Target & Circular Reference
605
-
606
- ```
607
- Where will this Guard attach?
608
- ├── Service buy_guard? ──→ CREATE Service (no guard) → CREATE Guard (reference Service by name in table) → MODIFY Service (set buy_guard)
609
- ├── Service order_allocators[].guard? ──→ CREATE Service (no allocators) → CREATE Guard (may reference Service) → MODIFY Service (set order_allocators with guard)
610
- ├── Machine Forward guard? ──→ CREATE Machine (unpublished, no guard) → CREATE Guard (reference Machine if needed) → MODIFY Machine (set Forward.guard)
611
- ├── Arbitration voting_guard / usage_guard? ──→ CREATE Arbitration (paused, no guards) → CREATE Guard → MODIFY Arbitration (add voting_guard / set usage_guard)
612
- ├── Reward guard? ──→ CREATE Reward (no guard) → CREATE Guard (reference Reward by name) → MODIFY Reward (guard_add)
613
- ├── Repository write_guard? ──→ CREATE Repository (no guard) → CREATE Guard → MODIFY Repository (set write_guard)
614
- └── Demand ServiceGuard? ──→ CREATE Demand (no guard) → CREATE Guard → MODIFY Demand (set ServiceGuard)
615
- ```
616
-
617
- ### D5: Iteration Workflow (When Guard Logic Must Change)
434
+ ## Tool Reference
618
435
 
619
- ```
620
- Guard logic needs to change:
621
- ├── Guard already created (immutable, cannot edit)? ──→ YES, always
622
- │ ├── Export current Guard? ──→ guard2file JSON/Markdown
623
- │ ├── Edit file (table, root tree, rely)? ──→ offline edit
624
- │ ├── Review edited JSON with user? ──→ confirm
625
- │ ├── CREATE new Guard from file? ──→ onchain_operations(guard) with root.type="file"
626
- │ ├── Test new Guard? ──→ gen_passport with mock submissions
627
- │ ├── Rebind to host object? ──→ MODIFY host (if host is mutable)
628
- │ │ └── Host is immutable (published Machine/Service)? ──→ must create new host object too
629
- │ └── Update all references? ──→ update Machine Forwards, Service allocators, Arbitration voting_guard, etc.
630
- └── Guard not yet created? ──→ just edit the design and CREATE
631
- ```
436
+ | Tool | Purpose |
437
+ |------|---------|
438
+ | `wowok_buildin_info` (`info: "guard instructions"`) | Discover all available query instructions — their IDs, parameter types, return types, and target object types |
439
+ | `wowok_buildin_info` (`info: "value types"`) | Discover the numeric codes for all supported value types used in table entries |
440
+ | `wowok_buildin_info` (`info: "built-in permissions"`) | Discover all built-in permission index codes for use with `permission.entity.perm has` queries |
441
+ | `onchain_operations` (`operation_type: "gen_passport"`) | Test Guard validation with runtime submissions and generate a verified on-chain credential on success |
442
+ | `guard2file` | Export an existing Guard's complete definition (description, table, root tree, dependencies) to a local JSON or Markdown file |
443
+ | `query_toolkit` (`query_type: "onchain_objects"`) | Query any Guard object on-chain by name or address to inspect its full definition |
444
+ | `schema_query` (`name: "onchain_operations_guard"`) | Retrieve the complete Guard operation schema with all parameter definitions |
632
445
 
633
446
  ---
634
447
 
635
- ## Failure Playbooks
636
-
637
- ### F1: Guard CREATE Fails with Type Mismatch
638
-
639
- **Trigger**: `onchain_operations` → `operation_type: "guard"` CREATE reverts with a type-validation error naming a specific node and the expected vs actual types.
640
-
641
- **Diagnosis**: The computation tree has a type incompatibility. Common variants: (a) `logic_equal` comparing String to U64; (b) `query` node's parameter count off-by-one; (c) missing `convert_witness` when querying Progress from an Order; (d) `rely` referencing a Guard with `rep: false`.
642
-
643
- **Recovery**:
644
- 1. Read the error message — it identifies the offending node and the type mismatch.
645
- 2. Cross-reference `wowok_buildin_info` → `info: "value types"` to confirm numeric codes if any are used.
646
- 3. Cross-reference `wowok_buildin_info` → `info: "guard instructions"` to confirm the `query` node's instruction ID and parameter count.
647
- 4. Insert an explicit `convert_*` node where types differ, or use `logic_as_u256_*` variants for cross-width numeric comparisons.
648
- 5. Re-attempt CREATE. Guards are CREATE-only — there is no MODIFY, so a failed CREATE simply retries with the fixed tree.
649
-
650
- **Prevention**: R6's pre-create review walks the tree and checks every comparison node's operand types. The §10 Common Pitfalls traps 1–4 catch 90% of these issues before CREATE.
651
-
652
- ### F2: `gen_passport` Returns FAIL
653
-
654
- **Trigger**: The static test returns FAIL — the Guard rejected the mock submission when it was expected to pass.
655
-
656
- **Diagnosis**: Either the Guard's logic is wrong, or the mock submission doesn't match what the Guard expects. The error usually indicates which `logic_*` or `query` node returned false.
657
-
658
- **Recovery**:
659
- 1. `guard2file` → export the failing Guard to a JSON/Markdown file.
660
- 2. Walk the computation tree manually, evaluating each node with the mock submission values.
661
- 3. Identify the first node that returns an unexpected value.
662
- 4. Common causes: (a) `query` node returns empty because the target object doesn't exist or the wrong ID was submitted; (b) `convert_witness` produces the wrong target type; (c) time-lock duration is in milliseconds but the test used seconds; (d) `logic_equal` compares Address to String representation.
663
- 5. If the logic is genuinely wrong: CREATE a new Guard with corrected logic (immutable — cannot edit the original), re-test.
664
- 6. If the submission was wrong: re-run `gen_passport` with corrected mock data.
665
-
666
- **Prevention**: R6's pre-create review includes a mental walkthrough with edge cases. R8's test should include both an expected-pass scenario and an expected-fail scenario — if the expected-fail scenario passes, the logic is inverted.
667
-
668
- ### F3: Guard Bound to Wrong Host Field
669
-
670
- **Trigger**: The Guard was bound to `buy_guard` when the user meant `order_allocators[].guard`, or vice versa. The Guard is live but in the wrong place.
671
-
672
- **Diagnosis**: Querying the host object shows the Guard in the wrong field. The intended field is empty or has a different Guard.
673
-
674
- **Recovery** (host object still mutable):
675
- 1. `onchain_operations` → MODIFY the host object: clear the wrong field (set to null/empty), set the correct field to the Guard.
676
- 2. Re-query to confirm the Guard is now in the intended field.
677
-
678
- **Recovery** (host object immutable — published Machine/Service):
679
- 1. Cannot modify the host. The Guard is permanently in the wrong field.
680
- 2. If the wrong field is harmless (e.g., `buy_guard` set when no buy was intended) → the Service may reject all purchases. Must create a new Service.
681
- 3. If the wrong field leaves the intended field empty → the intended gate has no validation. Must create a new host object with correct binding.
682
-
683
- **Prevention**: R5's binding plan explicitly documents `host_object` and `binding_field` before R9's MODIFY call. R9 lists the exact field name for each binding target. Always re-query the host object after binding to confirm the Guard is in the expected field.
684
-
685
- ### F4: Circular Reference Fails to Resolve
686
-
687
- **Trigger**: Guard CREATE fails because a table entry references an object by NAME, but the SDK cannot resolve the name to an address.
688
-
689
- **Diagnosis**: The object either (a) doesn't exist yet (circular reference pattern not followed — object should be CREATEd first), (b) was created but under a different name (typo), or (c) was created on a different account/network.
690
-
691
- **Recovery**:
692
- 1. Confirm the object exists via `query_toolkit` → `onchain_objects` with the intended name.
693
- 2. If it doesn't exist: CREATE the object first (without the Guard), then CREATE the Guard referencing the object's name, then MODIFY the object to bind the Guard.
694
- 3. If it exists under a different name: fix the table entry's `value` to match the actual name.
695
- 4. If it's on a different account/network: switch `env.account` / `env.network` to match, or re-create the object on the current account.
696
-
697
- **Prevention**: R5's binding plan explicitly documents the circular reference steps. The §Object-Guard Circular Reference Pattern in [wowok-tools](../wowok-tools/SKILL.md) is the universal three-step pattern: CREATE object → CREATE Guard (reference by name) → MODIFY object (bind Guard). Never CREATE the Guard before the object it references.
698
-
699
- ### F5: `voting_guard` Weight Type Error
700
-
701
- **Trigger**: Adding a `voting_guard` with `GuardIdentifier` to an Arbitration reverts with `E_GUARD_IDENTIFIER_NOT_NUMBER`.
702
-
703
- **Diagnosis**: The table entry at the `GuardIdentifier` index is either (a) not `b_submission: true`, or (b) not a numeric type (U8–U256). The Arbitration's `voting_guard` validation requires a numeric submission to cast as u32 vote weight.
704
-
705
- **Recovery**:
706
- 1. `guard2file` → export the Guard, inspect the table entry at the `GuardIdentifier` index.
707
- 2. If `b_submission` is false → CREATE a new Guard with `b_submission: true` at that index.
708
- 3. If `value_type` is non-numeric (e.g., Address, String) → CREATE a new Guard with a numeric `value_type` (U8/U16/U32/U64/U128/U256).
709
- 4. Re-test via `gen_passport` with a numeric mock submission.
710
- 5. Re-add the new Guard to the Arbitration's `voting_guard[]`.
711
-
712
- **Prevention**: R5's binding plan explicitly checks the `GuardIdentifier` type constraint for Arbitration `voting_guard`. The §Type Requirements by Object table lists this constraint. Always validate before CREATE.
713
-
714
- ### F6: Guard Logic Correct but Host Object Rejects Operation
715
-
716
- **Trigger**: The Guard passes `gen_passport` in isolation, but when bound to a live Machine Forward, the operation still fails.
717
-
718
- **Diagnosis**: The Guard's logic is correct in isolation but the host object's context provides different data. Common causes: (a) the Machine Forward's `retained_submission` index doesn't match the Guard's table; (b) the Service's `order_allocators` evaluation order means a different Allocator's Guard wins first (first-Guard-wins); (c) the Arbitration is paused (`bPaused: true`), which blocks before the Guard is even evaluated.
719
-
720
- **Recovery**:
721
- 1. Query the host object via `query_toolkit` → `onchain_objects` — check `bPaused`, `order_allocators` order, Forward `retained_submission` indices.
722
- 2. If Arbitration is paused → unpause first (after confirming all config is ready).
723
- 3. If `order_allocators` order is wrong → MODIFY the Service to reorder (pre-publish only; post-publish, `order_allocators` is immutable).
724
- 4. If `retained_submission` index mismatches → CREATE a new Guard with the correct index, rebind.
725
- 5. Re-test the live operation.
726
-
727
- **Prevention**: R9's binding verifies the host object's state. For Arbitration, confirm `pause: false` before expecting Guard evaluation. For Service `order_allocators`, confirm the evaluation order matches the intended priority. For Machine Forwards, confirm `retained_submission` indices align with the Guard's table.
728
-
729
448
  ---
730
449
 
731
- ## Tier Layering
732
-
733
- ### Novice Tier Single-Purpose Guard
734
-
735
- - One Guard, one purpose: e.g., a `buy_guard` that checks a single condition (signer equals authorized address, or amount ≤ cap).
736
- - Table has 1–3 entries, all clearly typed. Computation tree is a single `logic_equal` or `logic_and` of 2–3 nodes.
737
- - No `rely` dependencies, no `convert_witness`, no cross-object queries.
738
- - R1-R6 reduce to "fill in this template". R7-R8 are the only interactive rounds.
739
- - The §Quick Decision pattern table is the primary reference.
740
- - Trigger: user is new, or the validation rule is genuinely simple.
741
-
742
- ### Advanced Tier — Multi-Condition & Cross-Object
743
-
744
- - Guards combine multiple conditions via `logic_and` / `logic_or`. Tables have 4–10 entries including submissions and constants.
745
- - Cross-object queries via `convert_witness` (e.g., query Progress from an Order ID, query Machine from a Progress).
746
- - `rely` composition with up to 4 standalone (`rep: true`) Guards for modular logic.
747
- - Time-lock Guards with `context(Clock)` and `calc_number_*` arithmetic.
748
- - R1-R6 are full design sessions. R8 tests multiple scenarios (pass, fail, edge).
749
- - The §Phase 1-5 design phases and §Quick Decision pattern table are the primary references.
750
- - Trigger: user says "I want a complex Guard" or has completed prior single-purpose Guards.
751
-
752
- ### Expert Tier — Dynamic Data & Composition
753
-
754
- - Guards provide dynamic data to host objects: Arbitration `voting_guard` with `GuardIdentifier` for weighted voting, Repository `write_guard` with `id_from_submission` and `data_from_submission` for data extraction.
755
- - `rely` composition with OR logic (any dependency passing is sufficient) for flexible eligibility.
756
- - Cross-Machine Guards querying sub-Progress and sub-Orders via `convert_witness` (per [wowok-machine](../wowok-machine/SKILL.md) §Cross-Machine Composition).
757
- - `retained_submission` on Machine Forwards for audit trails and subsequent validation.
758
- - Multi-Guard `gen_passport` calls (up to 20 Guards AND-ed) for complex credential issuance.
759
- - Off-chain Passport use cases: Guards as credential issuers for off-chain permission verification, not just on-chain gates.
760
- - R1-R6 are expert design sessions; the AI's role is to validate types and constraints, not to suggest patterns.
761
- - The §Guard Data Flow and §Type Requirements by Object tables are the primary references.
762
- - Trigger: user explicitly asks for "expert mode", references `convert_witness` types by number, or designs Guards for Arbitration voting / Repository data extraction.
450
+ ## Appendices (Progressive Disclosure)
451
+
452
+ > The following sections have been extracted to [APPENDIX.md](./APPENDIX.md) for on-demand loading:
453
+ > - Dialogue Scripts (R1-R10) — guided conversation scripts
454
+ > - Decision Trees branching logic reference
455
+ > - Failure Playbooks recovery scenarios
456
+ > - Tier Layering expertise-tier based guidance
457
+ >
458
+ > Load APPENDIX.md when the user needs guided dialogue, recovery help, or tier-specific guidance.