@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.
@@ -0,0 +1,388 @@
1
+ # Appendix — wowok-tools
2
+
3
+ > This file is loaded on-demand (Progressive Disclosure).
4
+ > Main skill: [SKILL.md](./SKILL.md)
5
+
6
+ ---
7
+
8
+ ## Dialogue Scripts (R1-R10)
9
+
10
+ A 10-round dialogue for the tool-selection journey: a user (or another Skill) arrives with a vague intent and the AI walks them from "which tool do I even need?" through "called the right tool with the right shape" to "verified the result and persisted state". Each round maps to one decision in the tool-selection tree from §Decision Tree above.
11
+
12
+ ### R1: Intent Capture & Operation Class
13
+
14
+ **AI Goal**: Classify the user's intent into one of six operation classes (Write / Read / Communicate / Local-only / Export / Discover) so the rest of the rounds narrow to one tool family.
15
+
16
+ **Key Questions**:
17
+ - What are you trying to accomplish in one sentence? (e.g., "I want to create a service", "I want to read on-chain events", "I want to send an encrypted message")
18
+ - Is this a one-time action or part of a multi-step build?
19
+ - Are you operating on-chain or only locally?
20
+
21
+ **Tool Calls**:
22
+ 1. `query_toolkit` → `local_names` — list accounts and local marks so the AI can phrase follow-ups in terms the user already knows.
23
+ 2. (No write call yet — R1 is classification only.)
24
+
25
+ **Success Criteria**: AI articulates the classified intent back to the user in plain language ("You want to write on-chain state, so we'll use `onchain_operations`. Next we pick the operation_type.") and the user confirms.
26
+
27
+ **Fallback**: User intent is genuinely ambiguous (e.g., "I want to set up a shop" could mean account creation OR service creation) → ask one disambiguating question, do not guess. If user invokes by raw tool name ("use `messenger_operation`"), skip R2-R3 and jump to the parameter-shape rounds.
28
+
29
+ **Checkpoint**: Persist `{ round: R1, intent: <one_line>, op_class: write|read|communicate|local|export|discover }` via `local_info_operation`.
30
+
31
+ ### R2: Tool Family Selection
32
+
33
+ **AI Goal**: Map the operation class to exactly one of the 13 tools. For `onchain_operations`, also pre-select the `operation_type` shortlist.
34
+
35
+ **Key Questions**:
36
+ - (Write) Are you creating, modifying, or advancing an object? Which object type?
37
+ - (Read) Do you need a single object, a table row, an event stream, or your local address book?
38
+ - (Communicate) Plain message, file, or WTS evidence?
39
+
40
+ **Tool Calls**:
41
+ 1. `schema_query` → `list` — confirm available schemas are generated (catches the "empty list → run `npm run generate:schemas`" trap from §13).
42
+ 2. (For `onchain_operations`) `schema_query` → `get` for the candidate operation_type schema (e.g., `onchain_operations_service`) to surface required fields early.
43
+
44
+ **Success Criteria**: One tool name and (for `onchain_operations`) one `operation_type` are committed. AI shows the user the high-level parameter shape and gets a "yes, that looks right".
45
+
46
+ **Fallback**: User wants an action the SDK doesn't expose directly (e.g., "refund a payment") → surface the protocol constraint (Payment is irreversible per §Immutability) and offer the closest valid path (e.g., Allocation-based refund). Never invent a tool.
47
+
48
+ **Checkpoint**: Persist `{ round: R2, tool: <name>, operation_type?: <name> }`.
49
+
50
+ ### R3: Structural Wrapper Selection
51
+
52
+ **AI Goal**: Decide the exact envelope shape: `{ operation_type, data, env?, submission? }` vs the three exceptions (`gen_passport`, `payment`, `personal`).
53
+
54
+ **Key Questions**:
55
+ - (Only if user is unsure) Are you generating a passport, making a payment, or updating personal info? These are the three exception branches.
56
+ - For everything else: do you have the `data` payload ready, or do you need to collect it across R4-R6?
57
+
58
+ **Tool Calls**:
59
+ 1. `schema_query` → `get` for the specific branch (e.g., `onchain_operations_gen_passport`) to lock the exact field set.
60
+ 2. Cross-reference §Structural Wrapper Rules table to confirm `data` presence and `submission` presence.
61
+
62
+ **Success Criteria**: The AI presents the exact JSON skeleton with field names (not values yet) and the user confirms the shape.
63
+
64
+ **Fallback**: User passes `data` to `gen_passport` or `submission` to `payment` → block, cite the §Structural Wrapper Rules table, re-route.
65
+
66
+ **Checkpoint**: Persist `{ round: R3, wrapper: standard|gen_passport|payment|personal, fields_expected: [...] }`.
67
+
68
+ ### R4: Account, Network & env Block
69
+
70
+ **AI Goal**: Resolve the `env` block — `account`, `network`, `no_cache`, `gas_budget`.
71
+
72
+ **Key Questions**:
73
+ - Which account? (Default `""` is fine if the user does not specify.)
74
+ - Testnet or mainnet? (Default `testnet`.)
75
+ - (If building multiple interdependent objects) OK to set `no_cache: true` to avoid stale-read failures?
76
+
77
+ **Tool Calls**:
78
+ 1. `query_toolkit` → `account_balance` for the chosen account — verify balance > 0 before any write.
79
+ 2. If balance = 0: `account_operation` → `faucet` (testnet) OR `account_operation` → `transfer` from a funded account (mainnet).
80
+ 3. (Optional) `query_toolkit` → `token_list` to confirm token decimals if amounts are involved.
81
+
82
+ **Success Criteria**: An account with non-zero balance is committed; `network` and `no_cache` are decided. AI shows the final `env` block.
83
+
84
+ **Fallback**: Faucet rate-limited → wait 60s and retry, or `transfer` 1 WOW from another funded account (sufficient for dozens of txns per §Mainnet operations). Mainnet user with no funded account → halt and instruct acquisition; do not reduce example amounts silently.
85
+
86
+ **Checkpoint**: Persist `{ round: R4, account: <name>, network: <testnet|mainnet>, balance: <n>, no_cache: <bool> }`.
87
+
88
+ ### R5: CREATE vs MODIFY Disambiguation
89
+
90
+ **AI Goal**: For every object-typed parameter, decide whether the user means REUSE (string) or CREATE (object shape). This is the most common silent failure per §safety 1.1.
91
+
92
+ **Key Questions**:
93
+ - For each object field (Permission, Machine, Guard, Contact, etc.): "Reuse an existing one (give me name/ID) or create a new one?"
94
+ - (If reuse) What is the name or `0x...` address?
95
+ - (If create) What are the new object's required fields?
96
+
97
+ **Tool Calls**:
98
+ 1. `query_toolkit` → `onchain_objects` — verify any "reuse" string actually resolves (catches typos before the SDK's `GetObjectExisted()` hard-errors).
99
+ 2. `local_mark_operation` → optional: tag a reused object with a friendly name for future reference.
100
+
101
+ **Success Criteria**: Every object-typed field is annotated as REUSE (with verified name/address) or CREATE (with field draft). The full `data` payload skeleton is now populated with placeholders.
102
+
103
+ **Fallback**: User passes a string that doesn't resolve → either offer to CREATE (with explicit confirmation) or query candidates via `onchain_objects` and let the user pick. Never silently swap string→object.
104
+
105
+ **Checkpoint**: Persist `{ round: R5, fields: [{name, mode: reuse|create, resolved?: <addr>}] }`.
106
+
107
+ ### R6: Permission Index Resolution
108
+
109
+ **AI Goal**: Resolve every `permissionIndex` and `namedOperator` reference against a real Permission object.
110
+
111
+ **Key Questions**:
112
+ - Which Permission object governs this operation? (Strongly recommended: reuse one Permission across all services.)
113
+ - For Machine Forwards: is this role shared across all Progress instances (`permissionIndex`) or per-order (`namedOperator`)?
114
+ - Custom indices must be ≥ 1000 (0–999 reserved). What indices does your Permission define?
115
+
116
+ **Tool Calls**:
117
+ 1. `query_toolkit` → `onchain_objects` (filter type=Permission) — list candidates for reuse.
118
+ 2. `wowok_buildin_info` → `info: "built-in permissions"` — confirm which 0–999 indices are protocol-reserved so the user doesn't try to claim one.
119
+
120
+ **Success Criteria**: Every `permissionIndex` value exists in the chosen Permission; every `namedOperator` is either `""` (order owner/agents) or a role name the user explicitly defined.
121
+
122
+ **Fallback**: User picks an index < 1000 → block, cite §Permission Index Model, suggest 1000–65535 range. User doesn't have a Permission yet → create one first (R5 CREATE path), then return.
123
+
124
+ **Checkpoint**: Persist `{ round: R6, permission_id, indices_used: [...] }`.
125
+
126
+ ### R7: Submission Loop Preparation
127
+
128
+ **AI Goal**: Pre-stage the two-phase submission pattern so R8's actual call doesn't surprise the user.
129
+
130
+ **Key Questions**:
131
+ - Will this operation require Guard validation? (If `submission` is in the schema, yes.)
132
+ - What data will the Guard prompt for? (Inspect Guard table via `guard2file`.)
133
+ - Do you have that data ready, or do we collect it in R8?
134
+
135
+ **Tool Calls**:
136
+ 1. `guard2file` → export every Guard the operation will hit — inspect `table` entries with `b_submission: true` to know what the prompt will ask.
137
+ 2. `wowok_buildin_info` → `info: "guard instructions"` — confirm any `query` node's instruction ID and parameter count.
138
+
139
+ **Success Criteria**: AI can enumerate the exact submission fields the user will be prompted for, and the user has confirmed they can provide each.
140
+
141
+ **Fallback**: User cannot provide a submission value (e.g., KYC address they don't have) → halt, surface the Guard logic via `guard2file`, discuss whether to relax the Guard or pause the operation. Never submit placeholder data to a Guard.
142
+
143
+ **Checkpoint**: Persist `{ round: R7, expected_submissions: [{identifier, name, value_type}] }`.
144
+
145
+ ### R8: Execute (Phase 1 — Probe)
146
+
147
+ **AI Goal**: Fire the operation WITHOUT `submission` to trigger the SDK's submission prompt. This is the safe first shot.
148
+
149
+ **Key Questions**:
150
+ - Confirm: I'm calling `<tool>` with `<operation_type>` and the data we prepared, but no submission yet. The SDK may return a prompt. Proceed?
151
+ - (If the call has no Guard) Confirm the full execution, since this is the only shot.
152
+
153
+ **Tool Calls**:
154
+ 1. `onchain_operations` (or other write tool) with the full `data` and `env`, omitting `submission`.
155
+ 2. Capture the response: either success (no Guard) or a structured submission prompt.
156
+
157
+ **Success Criteria**: Either the operation succeeds (no Guard involved) OR a structured submission prompt is returned and parsed.
158
+
159
+ **Fallback**: Call reverts with a gas error → re-faucet (R4 fallback), retry. Call reverts with "object not found" despite just creating it → set `env.no_cache: true` and retry (stale-cache trap from §Error Patterns). Schema validation error → re-read the schema via `schema_query`, fix the field, retry.
160
+
161
+ **Checkpoint**: Persist `{ round: R8, phase: probe, response: success|prompt, prompt_fields?: [...] }`.
162
+
163
+ ### R9: Execute (Phase 2 — Submit) or Verify
164
+
165
+ **AI Goal**: If R8 returned a submission prompt, collect the user's answers and re-call with `submission` populated. If R8 succeeded, verify the on-chain state matches expectations.
166
+
167
+ **Key Questions**:
168
+ - (Phase 2) For each prompted field, what value should I submit?
169
+ - (Verify) Want me to query the resulting object and show you the diff?
170
+
171
+ **Tool Calls**:
172
+ 1. (Phase 2) `onchain_operations` with the same `data` + `env` + `submission` populated.
173
+ 2. (Verify) `query_toolkit` → `onchain_objects` for the resulting object ID; `onchain_events` for the emitted event.
174
+ 3. (Optional) `local_mark_operation` → tag the new object with a friendly name.
175
+
176
+ **Success Criteria**: Operation finalizes successfully; on-chain query confirms the expected state; local mark persisted for future reference.
177
+
178
+ **Fallback**: Guard rejects the submission → consult the Guard's logic via `guard2file`, identify which `logic_*` or `query` node returned false, re-collect correct data, retry. Never bypass a Guard.
179
+
180
+ **Checkpoint**: Persist `{ round: R9, phase: submit|verify, object_id, tx_digest, verified: true }`.
181
+
182
+ ### R10: Handoff & Next-Action Routing
183
+
184
+ **AI Goal**: Determine the next tool call from the current state, using the §Handoff triggers (from strategy doc §4) — make tool-to-tool transitions deterministic, not semantic guesses.
185
+
186
+ **Key Questions**:
187
+ - What do you want to do next? (If unsure, I can suggest based on what we just did.)
188
+ - (Internal) Does the just-completed operation have a deterministic next action per the Handoff table?
189
+
190
+ **Tool Calls**:
191
+ 1. (Internal) Consult the Handoff trigger table: e.g., `service create` → next is `machine create`; `service publish` → next is `query_toolkit.verify`; `messenger WTS` → next is `arbitration.dispute`.
192
+ 2. (Optional) `local_info_operation` → write a handoff packet with `current_state`, `completed_objects`, `next_actions`, `carry_context`.
193
+
194
+ **Success Criteria**: AI presents 1–3 candidate next actions with rationale; user picks one or declares done. Handoff packet persisted for resume.
195
+
196
+ **Fallback**: User wants an action that doesn't fit the Handoff table → treat as a new R1 intent and re-classify. User wants to stop → persist checkpoint with `journey: paused` and a resume hint.
197
+
198
+ **Checkpoint**: Persist `{ round: R10, handoff: { next_tool, next_op_type, carry: [...] }, journey: complete|paused }`.
199
+
200
+ ---
201
+
202
+ ## Decision Trees
203
+
204
+ ### D1: Tool Family by Operation Class
205
+
206
+ ```
207
+ User intent
208
+ ├── Write on-chain state? ──→ onchain_operations
209
+ │ ├── Generating a credential? ──→ operation_type: gen_passport (no data wrapper)
210
+ │ ├── Transferring tokens? ──→ operation_type: payment (no submission)
211
+ │ ├── Updating personal profile? ──→ operation_type: personal (no submission)
212
+ │ └── Anything else? ──→ operation_type: service|machine|progress|guard|order|allocation|arbitration|treasury|reward|demand|contact|repository|permission (full wrapper)
213
+ ├── Read on-chain state? ──→ query_toolkit OR onchain_table_data
214
+ │ ├── Single object or simple list? ──→ query_toolkit
215
+ │ ├── Dynamic table row? ──→ onchain_table_data (needs parent except entity_registrar / entity_linker)
216
+ │ └── Historical events? ──→ onchain_events
217
+ ├── Communicate? ──→ messenger_operation
218
+ ├── Local-only? ──→ account_operation | local_mark_operation | local_info_operation
219
+ ├── Export for review? ──→ guard2file | machineNode2file | wip_file (verify/wts2html)
220
+ └── Discover schemas/instructions? ──→ schema_query | wowok_buildin_info
221
+ ```
222
+
223
+ ### D2: CREATE vs MODIFY (per object-typed field)
224
+
225
+ ```
226
+ For each field whose value could be a string OR an object:
227
+ ├── User said "reuse <name>" or gave 0x address? ──→ REUSE
228
+ │ ├── query_toolkit.onchain_objects verifies it resolves? ──→ use string value
229
+ │ └── Does not resolve? ──→ ask: typo, or did you mean CREATE?
230
+ ├── User said "create new" with details? ──→ CREATE (object shape)
231
+ ├── User unsure? ──→ query on-chain candidates, present list, let user pick or create
232
+ └── SDK auto-create shortcut ──→ pass object shape to a parent field (e.g., service.permission) and SDK creates the Permission implicitly — only for Permission, only when user accepts the auto-defaults
233
+ ```
234
+
235
+ ### D3: Submission Loop Branch
236
+
237
+ ```
238
+ About to call onchain_operations:
239
+ ├── Branch is gen_passport, payment, or personal? ──→ ONE-SHOT (no submission field)
240
+ ├── Branch has submission in schema?
241
+ │ ├── Call WITHOUT submission first ──→ SDK returns prompt? ──→ collect answers, re-call WITH submission
242
+ │ └── SDK returns success (no Guard gated this op)? ──→ done, no phase 2 needed
243
+ └── gen_passport special case ──→ each Guard's submission passed via top-level info, not data.submission
244
+ ```
245
+
246
+ ### D4: Error Recovery Routing
247
+
248
+ ```
249
+ Tool call returned error:
250
+ ├── Gas / insufficient balance? ──→ query_toolkit.account_balance → faucet or transfer → retry
251
+ ├── "Object not found" right after create? ──→ env.no_cache: true → retry (stale cache)
252
+ ├── Guard validation failure? ──→ guard2file export → inspect logic tree → fix submission → retry
253
+ ├── Schema validation error? ──→ schema_query.get for the branch → diff against payload → fix → retry
254
+ ├── Permission denied? ──→ query Permission object → verify caller's index → add index or switch account
255
+ ├── "machine not published" on service.publish? ──→ publish Machine first, then retry Service publish
256
+ └── Network timeout? ──→ retry once; if persists, switch network or escalate
257
+ ```
258
+
259
+ ### D5: Handoff Next-Action
260
+
261
+ ```
262
+ Just-completed operation:
263
+ ├── service CREATE ──→ next: machine CREATE (Service needs a Machine before publish)
264
+ ├── machine CREATE ──→ next: guard CREATE × N (Guards must exist before binding)
265
+ ├── guard CREATE ──→ next: gen_passport test (verify logic before binding)
266
+ ├── service publish ──→ next: query_toolkit.onchain_objects verify bPublished=true
267
+ ├── query Service ──→ next (if user wants contact): messenger_operation
268
+ ├── messenger WTS send ──→ next: arbitration.dispute (evidence closed)
269
+ ├── order.advance ──→ next: query allocation balance (verify fund flow)
270
+ └── None of the above ──→ re-invoke R1 intent classification
271
+ ```
272
+
273
+ ---
274
+
275
+ ## Failure Playbooks
276
+
277
+ ### F1: Schema List Returns Empty
278
+
279
+ **Trigger**: `schema_query` → `list` returns `[]` or throws "schemas not generated".
280
+
281
+ **Diagnosis**: The MCP server's schema files were not generated at deploy time. This is a deployment gap, not a usage error.
282
+
283
+ **Recovery**:
284
+ 1. Surface the issue to the user plainly: "The schema files are missing on the server side."
285
+ 2. Instruct running `npm run generate:schemas` on the MCP server host (per tool #13 in §The 13 Tools).
286
+ 3. While waiting, fall back to the field shapes documented in this Skill and in [wowok-safety](../wowok-safety/SKILL.md) — they are authoritative even without the generated schema.
287
+ 4. After regeneration, re-run `schema_query.list` to confirm.
288
+
289
+ **Prevention**: Add a `schema_query.list` health check at the start of every fresh session. If empty, fail fast and surface the deploy issue before any write attempt.
290
+
291
+ ### F2: Stale Cache After Sequential Creates
292
+
293
+ **Trigger**: Operation B fails with "object not found" immediately after operation A created that object.
294
+
295
+ **Diagnosis**: The SDK's read cache hasn't invalidated between dependent calls. This is the #1 cache trap per §Error Patterns.
296
+
297
+ **Recovery**:
298
+ 1. Retry operation B with `env.no_cache: true`.
299
+ 2. If still failing, query the object directly via `query_toolkit` → `onchain_objects` with `no_cache: true` to confirm it actually exists on-chain.
300
+ 3. If on-chain confirms existence, retry B once more with `no_cache: true`.
301
+
302
+ **Prevention**: When building multiple interdependent objects in one session (the common case in onboarding), set `env.no_cache: true` on EVERY operation from the start. The minor latency cost is far cheaper than debugging stale-cache failures mid-flow.
303
+
304
+ ### F3: Submission Loop Misuse
305
+
306
+ **Trigger**: User (or AI) calls `onchain_operations` with `submission` populated on the first try, and the call either reverts or silently accepts wrong data.
307
+
308
+ **Diagnosis**: The two-phase pattern was skipped. Either the AI guessed the submission fields, or the user pasted a submission from a previous unrelated call.
309
+
310
+ **Recovery**:
311
+ 1. Re-call the operation WITHOUT `submission` to get the authoritative prompt.
312
+ 2. Diff the prompt's requested fields against what was previously submitted.
313
+ 3. Re-collect any mismatched fields from the user.
314
+ 4. Re-call WITH the corrected `submission`.
315
+
316
+ **Prevention**: Treat the submission prompt as the single source of truth for what the Guard needs. Never pre-fill `submission` from memory or past calls. The `gen_passport` exception (submissions via top-level `info`) is the only branch where submission data is passed differently — and even there, each Guard's submission is independent.
317
+
318
+ ### F4: Guard creation fails with type mismatch
319
+
320
+ **Trigger**: `onchain_operations` → `operation_type: "guard"` CREATE reverts with a type-validation error (e.g., `logic_equal` received String vs U64).
321
+
322
+ **Diagnosis**: The computational tree has a type incompatibility that the schema-layer validation caught. Common variants: comparing across numeric widths without `logic_as_u256_*`, missing `convert_witness` when querying Progress from an Order, or a `query` node with the wrong parameter count.
323
+
324
+ **Recovery**:
325
+ 1. Inspect the error message — it usually names the offending node and the expected vs actual types.
326
+ 2. Cross-reference `wowok_buildin_info` → `info: "value types"` to confirm numeric codes.
327
+ 3. Cross-reference `wowok_buildin_info` → `info: "guard instructions"` to confirm the `query` node's instruction ID and parameter count.
328
+ 4. Fix the tree, re-attempt CREATE. Guards are CREATE-only — there is no MODIFY, so a failed CREATE simply retries.
329
+
330
+ **Prevention**: Before any Guard CREATE, mentally (or via a scratch file) walk the tree: every `identifier` index exists in the table; every comparison node receives compatible operand types; every `query` node's parameter count matches the instruction. The §Guard Best Practices traps 1–4 catch 90% of pre-flight issues.
331
+
332
+ ### F5: Tool Returns "Permission Denied"
333
+
334
+ **Trigger**: Operation reverts with a permission error despite the user believing they have access.
335
+
336
+ **Diagnosis**: The operating account lacks the required `permissionIndex` in the governing Permission object, OR the Forward's `namedOperator` doesn't match the caller's role.
337
+
338
+ **Recovery**:
339
+ 1. `query_toolkit` → `onchain_objects` for the governing Permission — list its indices.
340
+ 2. Cross-reference the operation's required index (from the schema or the Machine Forward definition).
341
+ 3. Either: switch to an account that holds the index, OR have the Permission owner add the index for the current account, OR (if Forward uses `namedOperator`) assign the role via `progress` MODIFY.
342
+
343
+ **Prevention**: During onboarding R6 (Permission resolution), record the full index→role map in the checkpoint. Before any operation, verify the caller's account holds the required index — this is a 1-query pre-flight that prevents 100% of permission-denied failures.
344
+
345
+ ### F6: Faucet Exhausted on Testnet
346
+
347
+ **Trigger**: `account_operation` → `faucet` returns rate-limit or timeout.
348
+
349
+ **Diagnosis**: Testnet faucet has per-account and per-IP rate limits. Common during onboarding loops with many test orders.
350
+
351
+ **Recovery**:
352
+ 1. Wait 60 seconds and retry once.
353
+ 2. If still failing, `account_operation` → `transfer` 1 WOW (10^9 base units) from another funded account the user owns.
354
+ 3. If no other account exists, surface the issue and pause — do not silently reduce example amounts (per §Mainnet operations, this rule applies to mainnet too).
355
+
356
+ **Prevention**: Pre-fund each new account with 5+ WOW at creation time via a single `transfer` from a treasury account, rather than relying on faucet per-operation. Track each account's balance in `local_info_operation` and proactively top up below 1 WOW threshold.
357
+
358
+ ---
359
+
360
+ ## Tier Layering
361
+
362
+ ### Novice Tier — Tool Discovery Path
363
+
364
+ - Always start with `query_toolkit` → `local_names` to ground the conversation in objects the user already knows.
365
+ - Use the §Decision Tree D1 (Tool Family by Operation Class) as a rigid router — do not let the user invoke tools by raw name until they've classified their intent.
366
+ - For every `onchain_operations` call, follow the full R1-R10 sequence: classify → select → wrap → env → CREATE/MODIFY → permission → submission prep → probe → submit → handoff.
367
+ - The two-phase submission loop is non-negotiable: never pre-fill `submission`.
368
+ - Always set `env.no_cache: true` when building multiple objects in one session.
369
+ - After every write, verify via `query_toolkit` → `onchain_objects` before declaring success.
370
+ - Trigger: user is new, or any time the AI is unsure which tool fits.
371
+
372
+ ### Advanced Tier — Direct Tool Invocation
373
+
374
+ - User invokes tools by name (e.g., "call `onchain_operations` with `operation_type: machine`"); AI provides the parameter shape and verifies, but does not re-classify intent from scratch.
375
+ - The R1-R3 rounds can be collapsed into a single confirmation: "You want `<tool>` + `<operation_type>`. Confirm?"
376
+ - `env.no_cache` is set selectively — only on operations known to depend on just-created objects.
377
+ - Submission loop is still two-phase, but the AI pre-fetches the Guard's expected submissions via `guard2file` in parallel with R8's probe call, so R9 is faster.
378
+ - Handoff next-actions are surfaced as suggestions, not enforced.
379
+ - Trigger: user says "I know what I'm doing" or has completed prior sessions.
380
+
381
+ ### Expert Tier — Raw Schema & Edge Cases
382
+
383
+ - User reads schemas directly via `schema_query` and constructs payloads by hand; AI's role is to catch schema-inexpressible traps (the three wrapper exceptions, first-Guard-wins ordering, convert_witness type rules) rather than to route.
384
+ - R1-R7 are skipped; AI engages at R8 (execute) and R10 (handoff).
385
+ - The §Common Pitfalls table and §Structural Wrapper Rules become the primary reference, not the decision trees.
386
+ - Expert users may compose multiple tool calls in a single transaction batch (where the SDK supports it) — AI verifies dependency ordering but does not serialize.
387
+ - Expert users may use `gen_passport` as a standalone credential issuer (off-chain verification use case), not just as a Guard test — AI supports this path directly.
388
+ - Trigger: user explicitly asks for "expert mode", references tools by raw name with parameters, or invokes `schema_query` themselves.