@wowok/skills 3.2.7 → 3.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wowok/skills",
3
- "version": "3.2.7",
3
+ "version": "3.2.8",
4
4
  "description": "WoWok AI Skills for Claude Code, Codex, Gemini CLI, Qwen Code, Grok Build, OpenCode, Google Antigravity, Cursor, Devin Desktop (formerly Windsurf), Trae, CodeBuddy, WorkBuddy, Qoder, Cline, Kilo Code and GitHub Copilot - dialogue orchestration layer on top of the WoWok MCP server (rules/reference knowledge is served by MCP directly since v2.0.0)",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -52,17 +52,17 @@ Never invent a fee, a voting structure, or Guard logic — missing → ASK; "mak
52
52
 
53
53
  Two objects: **Arbitration** (the service: fee, voting/usage Guards, `um`, `bPaused`, `balance`, Permission — permanent) and **Arb** (one per case: state machine, propositions, votes, fee held in escrow, verdict).
54
54
 
55
- Separation of powers: the arbitrator sets process and verdict (`indemnity`); the CUSTOMER confirms filings, objects, and claims compensation. Neither side can finish a case unilaterally.
55
+ Separation of powers: the arbitrator sets process and verdict (`indemnity`); the CUSTOMER files disputes, objects, re-confirms after a reset, and claims compensation. Neither side can finish a case unilaterally.
56
56
 
57
57
  ### Arb state machine (codes are the on-chain names used by `arb_game` too)
58
58
 
59
59
  | # | State | Who moves, how |
60
60
  |---|---|---|
61
- | 0 | `Principal_confirming` | Customer via order `arb_confirm` ({arb, confirm, proposition?, description?}) → 1 |
61
+ | 0 | `Principal_confirming` | Reached only after an arbitrator `reset`; Customer via order `arb_confirm` ({arb, confirm, proposition?, description?}) → 1. No timeout — the filing fee stays locked until the customer acts |
62
62
  | 1 | `Arbitrator_confirming` | Arbitrator `confirm` → 2 · `reset` (with feedback) → 0 · `feedback` |
63
63
  | 2 | `Voting` | `vote` · `voting_deadline_change` · `arbitration` (verdict) → 3 · `feedback` |
64
64
  | 3 | `Arbitrated` | Customer: `arb_objection` → 4 · `arb_claim_compensation` → 5 |
65
- | 4 | `Objectionable` | Arbitrator `reset` → 0 (only exit) · `feedback` |
65
+ | 4 | `Objectionable` | Arbitrator `reset` → 0 (only exit) · `feedback`. The filing fee stays escrowed — withdrawal is NEVER possible from this state |
66
66
  | 5 | `Finished` | Terminal; fee withdrawable immediately |
67
67
  | 6 | `Withdrawn` | Terminal |
68
68
 
@@ -75,7 +75,7 @@ Separation of powers: the arbitrator sets process and verdict (`indemnity`); the
75
75
  Create the Arbitration **paused** (`pause: true`), configure, then `pause: false` last. While paused, filing ABORTS with arbitration error `E_PAUSED` (4) — it is an on-chain error, not a silent reject, but the practical damage is the same: no cases can arrive. Verify unpaused before going live.
76
76
 
77
77
  - `fee`, `description`, `location` are settable by Permission.
78
- - `voting_guard: {op:'add'|'set'|'remove'|'clear', guards:[…]}`. Each entry is `{guard, vote_weight}`: fixed u32 weight, or a u8 Guard-table identifier whose submitted number becomes the voter's weight at vote time (`FixedValue` / `GuardIdentifier`). Open = empty list → plain Permission vote, weight 1. Test every Guard with standalone `gen_passport` before adding — Guards are immutable from creation; a flawed voting Guard can only be replaced (the list itself stays mutable while configured pre-service / as allowed).
78
+ - `voting_guard: {op:'add'|'set'|'remove'|'clear', guards:[…]}`. Each entry is `{guard, vote_weight}`; `vote_weight` is an OBJECT, not a number: `{"FixedValue": n}` (u32, 0–4294967295) or `{"GuardIdentifier": i}` (u8 slot index, 0–255 — the Guard-table slot whose submitted number becomes the voter's weight at vote time; the slot must hold a number). Open = empty list → plain Permission vote, weight 1. Test every Guard with standalone `gen_passport` before adding — Guards are immutable from creation; a flawed voting Guard can only be replaced (the list itself stays mutable while configured pre-service / as allowed).
79
79
  - `usage_guard`: a Guard address or null; when set, filing MUST pass it via Passport (`dispute_with_passport`), else plain `dispute` aborts `E_NEED_PASSPORT` (6).
80
80
  - `um`: a Contact; evidence flows through its Messenger addresses.
81
81
  - **Permission isolation (mainnet trust)**: the Arbitration's Permission MUST differ from every Service it's bound to — binding a shared one aborts `E_ARBITRATION_PERMISSION_CONFLICT` (33, enforced at Service bind). Separately, the buyer-side risk model scores same-Permission as **−6 points (critical)** and overlapping owner/admin as **−4 points (warning)** inside its 20-point trust dimension — even distinct objects with the same controllers fail the intent. Use a genuinely independent third-party Permission.
@@ -84,13 +84,13 @@ Create the Arbitration **paused** (`pause: true`), configure, then `pause: false
84
84
 
85
85
  ## Handling a case
86
86
 
87
- 1. **Arrival**: customer files via `arbitration` `dispute: {order, description?, proposition[], fee:{balance}, namedArb?}` (≤20 propositions; fee locked in the Arb; excess fee is refunded). Arb appears at state 1.
87
+ 1. **Arrival**: customer files via `arbitration` `dispute: {order, description?, proposition[], fee:{balance}, namedArb?}` (≤20 propositions; fee locked in the Arb; excess fee is refunded). The case lands directly in state 1 — the customer does not confirm at filing time.
88
88
  2. **Review (1)**: `confirm: {arb, voting_deadline}` — proceed, or `reset` with feedback when the filing is insufficient (don't escalate thin cases).
89
89
  - `voting_deadline` is ms: **0 (default) = already-passed → direct verdict, voting impossible**; **null = open-ended**; a future timestamp = voting window (recommend ≥24h; ~3 days is a convention, NOT a chain limit).
90
90
  3. **Voting (2)**: `vote: {arb, votes:[indices…], voting_guard?}` — 0-based proposition indices; re-voting REPLACES the prior vote; ≤520 voters. With a deadline set, `arbitration` cannot run until it has passed (`E_VOTING_DEADLINE_NOT_PASSED`).
91
91
  4. **Verdict (2→3)**: `arbitration: {arb, feedback, indemnity}` — irreversible for the arbitrator; only customer objection/claim follows. **Indemnity is capped at 3× the order amount** (`MAX_INDEMNITY_MULTIPLE`, abort 9) and is paid from the SERVICE's `compensation_fund`, never from arbitrator funds.
92
- 5. **Customer branch (3)**: claim → 5, or object with `arb_objection` → 4 → your `reset` sends it to 0 for revision.
93
- 6. **Fee withdrawal**: `arb_withdraw: {arb}` — immediate at Finished; from Arbitrated/Objectionable only after 30 days past indemnity time (`WITHDRAW_DURATION_TIME`, abort 8). Then move the balance onward with `fees_transfer: {to:{allocation|{treasury}}, payment_remark, payment_index}`.
92
+ 5. **Customer branch (3)**: claim → 5, or object with `arb_objection` → 4 → your `reset` sends it to 0 for revision. The claim succeeds even when the indemnity is 0 — it closes the case (state 5) and frees your fee. A losing customer has little incentive to send that transaction, so say so in your ruling feedback.
93
+ 6. **Fee withdrawal**: `arb_withdraw: {arb}` — immediate at Finished(5); from Arbitrated(3) only after 30 days past indemnity time (silence = acceptance; `WITHDRAW_DURATION_TIME`, abort 8); **NEVER from Objectionable(4)** — a contested case keeps its fee escrowed until the revision cycle closes (reset → customer re-confirm → new ruling → unchallenged), so drive resolved cases to Finished via the customer's claim whenever possible. States 0/1/2 also reject. `fees_transfer: {to:{allocation|{treasury}}, payment_remark, payment_index}` then moves the arbitration's ENTIRE balance in one call (there is no amount parameter) and leaves it as a CoinWrapper owned by the target — for a Treasury target the funds count only after `treasury receive: "recently"` (permission 253).
94
94
 
95
95
  **Move advice**: `evaluation_operation` action=`arb_game` with `status` (one of the 7 state names) and `perspective: customer|merchant|arbitrator` returns ranked moves/payoffs/risk — read-only; the role decides.
96
96
 
@@ -98,6 +98,7 @@ Create the Arbitration **paused** (`pause: true`), configure, then `pause: false
98
98
 
99
99
  ## Evidence & reputation
100
100
 
101
+ - Parties are strangers to you and often to Messenger. On `confirm`, write each party one opening message (the Arb address, what you need, e.g. a signed WTS via `send_file`); your reply lifts their one-message stranger limit toward you. Keep `allowStrangerMessages` on while you accept cases. If a party's send fails with `not registered`, say so in the Arb `feedback` so the record shows they were asked and could not be reached.
101
102
  - Customer reads the Arbitration's `um`, sends WTS evidence off-chain via encrypted Messenger; arbitrator runs `messenger_operation` `verify_wts` before considering anything — unverified evidence is not evidence.
102
103
  - Tell initiators to pre-sort with `evaluation_operation` action=`evidence_review` (list mode): usable/manual/rejected partition + `proof_candidates` for the dispute description; the human selects — nothing auto-attaches.
103
104
  - On-chain `feedback` is permanent and public: reasoned, professional, consistent. Use Messenger for anything private.
@@ -27,7 +27,7 @@ The machine-executable rules are NOT duplicated in this Skill — they evolve in
27
27
  | Content | Source (MCP) |
28
28
  |---------|--------------|
29
29
  | Safety rules (confirmation levels, immutability, object reuse) | `schema_query` action='get_safety_rules' |
30
- | Guard completeness, Machine soundness, fund-flow safety, permission consistency, publish readiness | `goal_operation` action='aggregate_risks' (auto-applied) |
30
+ | Guard completeness, Machine soundness, fund-flow safety, permission consistency, publish readiness | `goal_operation` action='aggregate_risks' (applied from the declared intent/puzzles + planned objects/operations) |
31
31
 
32
32
  This Skill keeps only **when to run the audit, how to call it, and how to read the verdict**.
33
33
 
@@ -40,10 +40,10 @@ Run an audit immediately before any irreversible operation:
40
40
  1. **Template adoption (earliest gate)** — before a build plan is even generated from an industry archetype template: `benchmark_migration_operation` action=`template_scan` runs the pre-deploy risk scan (same rule surface as the on-chain analyze, plus the template scanner's static trust-mechanism checks). `passed: false` (any CRITICAL finding) blocks `template_generate` / `migration_apply` at the MCP level — report the red flags and stop; do not proceed to object planning.
41
41
  2. **Service publish** — machine bound + published, allocators locked, arbitration/compensation invariants, buy_guard, contact, permission indices.
42
42
  3. **Machine publish** — nodes/pairs/forwards become immutable afterward.
43
- 4. **Service fund-template lock** — `order_allocators` (the order distribution template and its trigger guards) is a Service create/update FIELD that becomes permanently immutable at `publish=true`; there is no separate bind op.
43
+ 4. **Service fund-template lock** — `order_allocators` (the order distribution template and its trigger guards) is a Service create/update FIELD that becomes permanently immutable at `publish=true`; there is no separate bind op. The ALC1 allocator audit auto-reports an allocator whose sharing rows are ALL `Entity`/`Signer` (finding RC-FIND-09: its Guard binds to no particular order — a zero-share `GuardIdentifier` anchor row fixes that); when it fires, ask the merchant whether the omission is intended before publishing.
44
44
  5. **Post-failure root-cause analysis** — a publish/assert failed (e.g. `E_ARBITRATION_NOT_SET_WITH_COMPENSATION_FUND`, `E_ARBITRATION_PERMISSION_CONFLICT`); re-run to identify every remaining blocker, not just the one that aborted.
45
45
 
46
- Scope adapts to blast radius: a single Service with no Machine skips machine checks automatically; a stack with cross-Machine supply chains runs the full chain. The engine derives applicable checks from the objects — do not hand-pick rules.
46
+ Scope adapts to blast radius: a single Service with no Machine skips machine checks automatically; a stack with cross-Machine supply chains runs the full chain. The engine derives applicable checks from the DECLARED inputs (intent/puzzles + `planned_objects`/`planned_operations`) — it does NOT inspect live on-chain objects (docs#44); complement it with `query_toolkit` (`onchain_topology`) or `watch` for object-grounded checks. Do not hand-pick rules.
47
47
 
48
48
  ---
49
49
 
@@ -51,6 +51,7 @@ Every custom `permissionIndex` used MUST be granted in the bound Permission (`pe
51
51
  - The Guard validates BEFORE the transition. A Guard reading the SAME Progress sees the source node — never write "current == target_node" (always fails). For post-transition verification, bind the Guard to the **Allocator** (`alloc` runs after the state transition).
52
52
  - `retained_submission: [identifier…]` stores the submitted values on the forward's execution record in the Progress session/history (located by node + forward), so later nodes and cross-machine Guards can read them.
53
53
  - **No on-chain cron (T1 lossy point)**: "after N days, auto-X" decomposes into a time Guard PLUS an off-chain keeper that submits the forward once it passes. A time Guard without a keeper never fires.
54
+ - **Lists/scores that change live in a Repository**: keep a mutable list or number (operator allow-list, blocklist, score) in a Repository policy and let the Guard read it — editing the list needs no new Guard. Comparison/count limits (U256-only values, no per-key counting) are in GUARD_SCHEMA_NOTES via `get_guard_design_patterns`.
54
55
  - Design every Guard via `get_guard_design_patterns`; test it with the standalone `gen_passport` operation BEFORE binding — immutability makes post-hoc fixes impossible.
55
56
 
56
57
  ## Sessions & thresholds
@@ -76,6 +77,7 @@ Every custom `permissionIndex` used MUST be granted in the bound Permission (`pe
76
77
  1. Permission → 2. Machine unpublished (`object:{name, type_parameter, permission}`) → 3. Guards created + tested (`gen_passport`) → 4. bind Guards on forwards → 5. test end-to-end → 6. `publish:true` → 7. Service binds the Machine.
77
78
 
78
79
  **Node field ops** (`data.node`, pre-publish only — 9): `add` / `set` (with `bReplace`, default false = MERGE into existing nodes; true = full replace), `remove`, `clear` (irreversible wipe — export first), `exchange` (swap two node positions), `rename` (updates pair references), `remove prior node`, `add forward`, `remove forward`. All forward-bearing ops accept the full forward shape including the Guard object with `retained_submission`.
80
+ `add forward` shape: `node: {op: "add forward", data: [{prior_node_name, node_name, forward: [...], threshold?}]}` — the source node is `prior_node_name` INSIDE each data row; a flat `{node_name, prev_node, threshold, forward}` at the top level is rejected (`Unrecognized keys`).
79
81
 
80
82
  **File workflow**: `machineNode2file` exports the exact on-chain node set; edit; then `data.node: {json_or_markdown_file: "<path>"}` performs a COMPLETE replacement (node array, not an op object; JSON or ```json markdown). Always start from an export.
81
83
 
@@ -107,7 +109,7 @@ Every custom `permissionIndex` used MUST be granted in the bound Permission (`pe
107
109
  - [ ] Every pair's threshold ≤ the sum of its DISTINCT forward weights (no dead branches); competing transitions are intended.
108
110
  - [ ] Every forward binds exactly the intended identity (wildcard / role / permission index), and ALL custom indexes are already granted.
109
111
  - [ ] Guards created, `gen_passport`-tested (all submission scenarios), bound; time Guards have a keeper plan; post-transition checks live on Allocators, not forwards.
110
- - [ ] NO node named `refund`/`refunded`/`deposit_refunded`/`deposit_deducted`/`disputed`/`cancelled` or implying the Machine moves funds. Machines never move money — refund/deduction terminals route to Allocator slots (`return_approved` → Allocator), disputes route to the bound Arbitration. The pre-publish gate rejects violations.
112
+ - [ ] NO node named `refund`/`refunded`/`deposit_refunded`/`deposit_deducted`/`disputed` or implying the Machine moves funds. Machines never move money — refund/deduction terminals route to Allocator slots (`return_approved` → Allocator), disputes route to the bound Arbitration. The pre-publish gate rejects violations. `cancelled`/`returned` are discouraged; the runtime warns (R-M1-11) but does not reject — use as business states when that matches your flow.
111
113
  - [ ] Terminal nodes are mapped to Allocator entries, or funds lock in escrow.
112
114
  - [ ] Export via `machineNode2file`; run a test Progress on testnet first.
113
115
 
@@ -32,7 +32,7 @@ End-to-end encrypted off-chain messaging with tamper-proof audit trails.
32
32
  2. Messenger enabled — `account_operation` `{messenger:{enabled:true, name_or_account}}`, or implicitly via `send_message`/`send_file` option `enable_messenger: true`.
33
33
  3. Share the account's address with counterparties (`account_operation` get).
34
34
 
35
- Without an enabled endpoint the account cannot receive. The local SDK enforces a per-device messenger-account cap — do NOT hardcode the number (it is a versioned constant and layers may differ). When enabling throws `Maximum <N> messenger accounts allowed, current count: <M>` (W_ERROR InvalidParam), quote N/M from the error verbatim and offer to disable an unused account (`messenger:{enabled:false}`) to free a slot.
35
+ Without an enabled endpoint the account cannot receive. The same applies to the COUNTERPARTY: a send to an unregistered address fails with `Recipient <address> is not registered on the messenger server. Please ask them to enable messenger first.` — ask them to enable Messenger before relying on it for evidence exchange (`enable_messenger: true` on your own send enables only your account). The local SDK enforces a per-device messenger-account cap — do NOT hardcode the number (it is a versioned constant and layers may differ). When enabling throws `Maximum <N> messenger accounts allowed, current count: <M>` (W_ERROR InvalidParam), quote N/M from the error verbatim and offer to disable an unused account (`messenger:{enabled:false}`) to free a slot.
36
36
 
37
37
  ### Contact object — the on-chain bridge
38
38
 
@@ -44,11 +44,11 @@ Without an enabled endpoint the account cannot receive. The local SDK enforces a
44
44
 
45
45
  **Read.** `watch_conversations` (`unreadOnly`, previews, sort) for the inbox; `watch_messages` with `peerAddress` for one thread (keyword/direction/status/time/relationship filters, pagination). `pull_messages` syncs from server first when local data looks stale (new device, downtime); `allAccounts:true` fans out bounded concurrency (default 5) with one `{account, pulled, messages, error?}` entry per account. Reads auto-mark viewed — pass `skipAutoMarkViewed:true` to peek.
46
46
 
47
- **Attachment read boundary.** Messages with `zipMetadata` never include payload bytes in any read op — only a byte-free `attachment` descriptor (`kind` image/video/audio/voice/file/wts/wip, `fileName`, `mimeType`, `size`, optional `caption`/media dims). Fetch bytes on demand with `save_attachment {messageId, outputDir?, saveAs?}` — sha256-verified before extraction, returns the absolute path, original filename restored.
47
+ **Attachment read boundary.** Messages with `zipMetadata` never include payload bytes in any read op — only a byte-free `attachment` descriptor (`kind` image/video/audio/voice/file/wts/wip, `fileName`, `mimeType`, `size`, optional `caption`/media dims). Fetch bytes on demand with `save_attachment {messageId, outputDir?, saveAs?}` — sha256-verified before extraction, returns the absolute path, original filename restored. `save_attachment` fails with `Message not found` until the thread is synced locally: run `pull_messages` first when a received file is not found.
48
48
 
49
49
  **Send.** Text via `send_message` (≤10240 bytes); files/media/evidence via `send_file {filePath}` as an E2EE attachment envelope (encrypted `.wowok-manifest.json` + payload; server sees only `zipMetadata` — transport name/size/sha256/class; media uncompressed, docs/evidence deflated). Options include `kind` (set `voice` explicitly — webm can't be told apart from video), `caption` (E2EE), and `replyTo:{messageId}` for quote-reply (id must exist locally).
50
50
 
51
- **First contact with a stranger = exactly one message.** Say who you are, why, and what you need. If delivery is rejected, the error carries `guardList`: get a passport from one of those Guards (`onchain_operations` `gen_passport`) and resend with `options.guardAddress` + `passportAddress` + `network` (Guard messages are a separate data system per network). When the recipient REPLIES, you are auto-added to **their** friends list and messaging opens up.
51
+ **First contact with a stranger = exactly one message.** Say who you are, why, and what you need. Every send counts against that one message — `send_message`, `send_file` (a WTS included) and `send_required_info`; text followed by a file is rejected until the recipient replies. If your first message must be evidence, send the signed WTS as that very message and name the case (Arb address) in its `caption`/text. If delivery is rejected, the error carries `guardList`: get a passport from one of those Guards (`onchain_operations` `gen_passport`) and resend with `options.guardAddress` + `passportAddress` + `network` (Guard messages are a separate data system per network). When the recipient REPLIES, you are auto-added to **their** friends list and messaging opens up — one direction only: if you opened the thread and they have strangers off, add them with `friendslist add` before expecting an answer.
52
52
 
53
53
  **Structured sends.**
54
54
  - `send_required_info {fields:['phone',…]}` assembles a merchant's `customer_required` LocalInfo fields into one E2EE message (omit `fields` = all; explicit `content` overrides); result reports `sent_fields`. Never send without per-item user confirmation.
@@ -70,9 +70,9 @@ Three independent **local, per-account** lists (never on-chain, never synced to
70
70
 
71
71
  Delivery evaluates, in order: **blacklist (reject) → friends (accept) → guard passport (accept if valid) → stranger rule**. `settings {op:set, allowStrangerMessages, maxInboxSize}` toggles strangers entirely; the rejection error tells the sender what applies. The stranger window/retry timing is **server policy** — surface the server's rejection message rather than assuming a fixed cooldown; to stop repeat contact, blacklist the address.
72
72
 
73
- `watch_messages` segments by relationship: `listFilterMode: friends|guard|stranger|any` (+ `customListFilter` include/exclude). Multiple guards are OR-ed — any one passing passport grants delivery. Match `passportValiditySeconds` to data volatility (payment gates tolerate days; order-state gates should be short) and test every guard with `gen_passport` before publishing it.
73
+ `watch_messages` segments by relationship: `listFilterMode: friends|guard|stranger|any` (+ `customListFilter` include/exclude). Multiple guards are OR-ed — any one passing passport grants delivery. Match `passportValiditySeconds` to data volatility (payment gates tolerate days; order-state gates should be short) and test every guard with `gen_passport` before publishing it. ⚠️ MAINNET-ONLY: guard-list entries must be Guard objects on MAINNET — a testnet Guard is rejected at add time (`Guard not found on mainnet`); create the Guard on mainnet before adding it.
74
74
 
75
- > Advisory profiles (NOT system states, just setting combinations): **Open** = strangers on, no guards, public-facing; **Guarded** = strangers off + 1–3 guards, verified-only; **Closed** = strangers off, no guards, friends-only; **Blocklist mode** = strangers on + a maintained blacklist. Choose by asking: may strangers reach you at all → if yes, anyone or guard-verified → anyone to hard-block. Always leave at least one inbound path.
75
+ > Advisory profiles (NOT system states, just setting combinations): **Open** = strangers on, no guards, public-facing; **Guarded** = strangers off + 1–3 guards, verified-only; **Closed** = strangers off, no guards, friends-only; **Blocklist mode** = strangers on + a maintained blacklist. Choose by asking: may strangers reach you at all → if yes, anyone or guard-verified → anyone to hard-block. Always leave at least one inbound path. ⚠️ A Guarded/Closed profile also blocks an arbitrator from reaching you (they are a stranger with no passport for your guards): once a case is filed, `friendslist add` the arbitrator's address or evidence exchange stalls — and a defendant who cannot be reached gets ruled on the claimant's evidence alone.
76
76
 
77
77
  ---
78
78
 
@@ -56,8 +56,8 @@ Primary: `query_toolkit` → `query_type: "onchain_topology"`, `focus: "<service
56
56
 
57
57
  Checks and verdicts (surfaced by findings + your reading of transitions):
58
58
  - Entry node (`prev_node: ""`) with no forward → 🔴 orders stuck at `current=""`.
59
- - No user-operable path on a critical node → 🔴 stuck unless provider acts.
60
- - No refund path (100%→Order allocator on a user-operable forward) → 🔴 no recovery.
59
+ - No user-operable path on a critical node → check the allocators first (E5) — an allocator exit may cover it; 🔴 stuck unless provider acts only if neither path nor allocator exists.
60
+ - No refund path → 🔴 only if there is **neither** (a) a forward you can operate that leads to a state whose allocator pays the Order, **nor** (b) an allocator whose Guard fires on elapsed time or on a state you can reach without the seller. Either counts.
61
61
  - No arbitration path → 🔴 no recourse. **No refund AND no arbitration → strongly advise against purchase.**
62
62
  - All exits pay the provider regardless → ⚠️; a forward needs a Guard the user cannot satisfy → ⚠️ cooperation needed.
63
63
 
@@ -68,8 +68,8 @@ Use `machineNode2file` (export once, parse locally — never node-by-node; see [
68
68
  2. Semantics: `schema_query` `get_guard_design_patterns` + `get_guard_templates`; generic instructions: `wowok_buildin_info` `info: "guard instructions"`.
69
69
  3. Classify: 🟢 clear purpose → explain · 🟡 multi-layer but clear intent → explain step by step · 🔴 ambiguous logic/dependencies → **warn; user must review the file**. Prioritize Guards on user-operable forwards and refund allocators.
70
70
 
71
- ### E5 — Fund allocation
72
- Read E1 `order_allocators.allocators[]` (topology also carries allocation edges). For each: cross-ref its Guard (E4) → trigger condition; map to the Machine node (E3) → when it fires; state the outcome in money terms.
71
+ ### E5 — Fund allocation (exit map)
72
+ Read E1 `order_allocators.allocators[]` (topology also carries allocation edges). For each: cross-ref its Guard (E4) → trigger condition; map to the Machine node (E3) → when it fires; state the outcome in money terms. Before the user buys, write one row per allocator: **Who can trigger it** (anyone / only the Signer named in the Guard) · **Earliest time** (read `progress.current_time` / Clock comparisons in the Guard) · **Payee** (Order = refund to you) · **What you submit** (usually the Order address) · **State it needs**. Triggering is `allocation alloc_by_guard` and anyone may do it, including you; when the payee is the Order, finish with `order receive: "recently"`. The earliest time a provider-paying allocator can fire is the user's dispute window — state that number in plain time units before they buy. If the Machine gives the user no forward, do not conclude the order can be stuck: check the allocators first.
73
73
  - No 100%→Order allocator → 🔴 no refund mechanism · surplus receiver = provider → ⚠️ · triggers only on provider-only paths → ⚠️ unilateral collection · no allocators on user-operable paths → ⚠️ no financial control. Safest: 100%→Order allocator on a user-operable forward.
74
74
 
75
75
  ### E6 — Arbitration
@@ -80,7 +80,7 @@ Batch query E1 `arbitrations[]` via `onchain_objects`; also `onchain_events` `ty
80
80
  From E1: `compensation_fund`, `compensation_lock_duration`. Balance below planned order amount → ⚠️; lock near expiry (provider can withdraw) → ⚠️.
81
81
 
82
82
  ### E8 — Contact channel
83
- `onchain_objects` for E1 `um`: `um === null` → 🔴 ABORT; `ims[]` empty → 🔴 no Messenger; active IMs → proceed.
83
+ `onchain_objects` for E1 `um` (use `customer_required` from E1). `customer_required` non-empty AND (`um === null` or the Contact's `ims[]` empty) → 🔴 ABORT — the Service asks for private data but publishes nowhere to send it. `customer_required` empty and `um === null` → ⚠️ no in-band channel — rely on on-chain state and the Machine; explain and wait. Active `ims[]` → proceed.
84
84
 
85
85
  ### E9 — Chain reputation
86
86
  The aggregate view is already computed inside the `onchain_topology` graph evaluation (trust dimension) and `query_toolkit relationship_profile` (derived relationships) — present those rather than hand-aggregating.
@@ -98,7 +98,7 @@ From E1 `customer_required[]` (e.g. name/phone/shipping_address):
98
98
  `query_toolkit` `{ query_type: "onchain_topology", focus: "<service_id>" }` → `evaluation` = `trust` + `risk` (each a 0-100 `total` with `level`/`breakdown`/`red_flags`/`blocked`), `completeness`, `coverage` slots, and `unverified` rules (data gaps are never scored as low). ⛔ `evaluation.risk.blocked` (critical red flags) → resolve with the user before Phase 2. Compare candidates by running the same query per service: present per-metric bests, **no overall ranking**.
99
99
 
100
100
  ### Pre-purchase gate
101
- 🔴 Abort: E1 unpublished/paused · E8 `um=null` · E3 no-refund + E6 no-arb · E4 ambiguous Guards (user review) · E11 `evaluation.risk.blocked` unresolved. Every ⚠️ = explain and wait. All clear → Phase 2.
101
+ 🔴 Abort: E1 unpublished/paused · E8 no usable channel for `customer_required` info · E3 no-refund + E6 no-arb · E4 ambiguous Guards (user review) · E11 `evaluation.risk.blocked` unresolved. Every ⚠️ = explain and wait. All clear → Phase 2.
102
102
 
103
103
  **Dependency**: E1 first; E2/E8/E10/E7/E6 parallel after E1; E3→E4→E5 strict chain; E9 follows E3; E11 last (aggregates everything).
104
104
 
@@ -116,6 +116,7 @@ On-chain rules (Phase 1) are immutable truth; Messenger is the encrypted, self-v
116
116
 
117
117
  ## Phase 3: Order creation
118
118
 
119
+ - Enable Messenger on the buying account before you buy — an arbitrator can only ask you for evidence if your account is registered (`messenger_operation` `enable_messenger` covers your own account only).
119
120
  - Buy (`onchain_operations` service `buy`): `wip_hash` MUST equal the current sale hash (never `""` when set); coin ≥ amount, excess auto-refunds to the sender in the same tx; agents cannot withdraw.
120
121
  - Discounts: `query_toolkit` → `onchain_received` with type `0x2::service::Discount`, filter by `service`, validate benchmark/time validity per the tool schema (rate/fixed semantics described on `discount_type`/`off`); pass the chosen Discount in the buy call.
121
122
 
@@ -134,13 +135,15 @@ When the user reaches a node, present the forward's three aspects together — n
134
135
 
135
136
  ## Phase 5: Arbitration
136
137
 
137
- Flow: `onchain_operations` arbitration `dispute` → WTS evidence → Messenger → order `arb_confirm` → voting → (`arb_objection`) → `arb_claim_compensation`. Process: [wowok-arbitrator](../wowok-arbitrator/SKILL.md).
138
+ Flow: `arbitration dispute` (the case starts in state 1 — no customer confirmation at filing) → send the signed WTS by Messenger → the arbitrator confirms and rules → you may `arb_claim_compensation` (accept) or `arb_objection`. After an objection the arbitrator `reset`s the case to state 0 and **you must call `order.arb_confirm` again** to put it back in state 1; until you do, nothing moves. Do not call the arbitration-side `confirm`: it is the arbitrator's call and fails with `Missing permissions 361`. Process: [wowok-arbitrator](../wowok-arbitrator/SKILL.md).
139
+
140
+ When you file, send exactly one first message to the arbitrator: the signed WTS with the Arb address in its caption/text (a stranger thread allows one message until they reply).
138
141
 
139
142
  **Before filing**, review the whole evidence pile at once with `evaluation_operation` `action: "evidence_review"` (list mode `items[]`: id/kind/hash_committed/digital_check_passed/contradiction/proof_ref; kinds per the tool schema).
140
143
  - Output partitions `usable` / `manual` / `rejected` and returns `proof_candidates` + `dispute_hint`.
141
144
  - Let the user PICK which proof candidates to reference (never auto-attach; the on-chain `dispute` has no proof field — references travel in the description / Messenger).
142
145
  - "no evidence passed" → anchor more evidence (Messenger WTS → Proof) before filing.
143
- - Fee is paid separately (not from the Order); one compensation claim per Order; source is `compensation_fund` (E7).
146
+ - Fee is paid separately (not from the Order); one compensation claim per Order; source is `compensation_fund` (E7). After a ruling of 0 you can still call `arb_claim_compensation`: it costs only gas, closes the case (state 5) and lets the arbitrator take the fee immediately.
144
147
 
145
148
  ---
146
149
 
@@ -65,15 +65,16 @@ All writes go through `onchain_operations` with `operation_type`; account from i
65
65
  2. **Guards** (`guard`) — design with `schema_query` action=`get_guard_design_patterns`; pass/fail gates vs runtime-submitted evidence (`b_submission` table entries) have different patterns — do not improvise, read the pattern output.
66
66
  3. **Bind + publish Machine, bind Service** — `machine` "add forward" with guards → machine `publish: true` (nodes/forwards become IMMUTABLE; re-export with machineNode2file and verify) → `service` bind `machine` (must already be published) and `buy_guard`.
67
67
  4. **Products** — `service` `sales: {op:'add'|'set'|'remove'|'clear', …}`; each sale `{name, price, stock, suspension, wip, wip_hash}` (price/stock are smallest-unit STRINGS). User supplies name/price/stock — never fabricate.
68
- 5. **Revenue** — `service` `order_allocators` (set BEFORE publish). Modes: Amount / Rate (bps, sum exactly 10000) / Surplus (max one per allocator). Recipients: `Entity` (fixed address — an org address is usually a Treasury that must hold permission 253 TREASURY_RECEIVE to intake), `GuardIdentifier` (address submitted at allocation time, e.g. the Order), `Signer` (the allocation caller — do not overuse or splits collapse).
69
- 6. **Customer service** — `contact` `ims: {op:'add'|'set'|'remove'|'clear'}` (IM list; mutations require permission 453 CONTACT_IM, emit no events) + enable messaging via `account_operation {messenger:{enabled:true, name_or_account}}`. Inbound filtering is the Messenger friends/guard/stranger lists (see wowok-messenger). Bind `service.um` when `customer_required`.
68
+ 5. **Revenue** — `service` `order_allocators` (set BEFORE publish). Modes: Amount / Rate (bps, sum exactly 10000) / Surplus (max one per allocator). Recipients: `Entity` (fixed address — an org address is usually a Treasury that must hold permission 253 TREASURY_RECEIVE to intake), `Signer` (the allocation caller — do not overuse or splits collapse), `GuardIdentifier` (BOUND to the paying order: in a Service-created Allocation every `GuardIdentifier` submission must equal the paying order or the call aborts with code 15 — it is always "the order", never a third party whose address is supplied at trigger time; use `Entity` for named parties).
69
+ Anchor tip: `Entity`/`Signer` rows resolve no submission, so an allocator paying only them leaves its Guard bound to no particular order — bind it with a zero-share `{GuardIdentifier: 0}` anchor row (pattern `allocator_order_anchor`; confirm Rate 0 with a dry-run before publishing).
70
+ 6. **Customer service** — `contact` `ims: {op:'add'|'set'|'remove'|'clear'}` (IM list; mutations require permission 453 CONTACT_IM, emit no events) + enable messaging via `account_operation {messenger:{enabled:true, name_or_account}}`. Inbound filtering is the Messenger friends/guard/stranger lists (see wowok-messenger). Bind `service.um` when `customer_required`. If your Contact runs a Guarded/Closed Messenger profile, an arbitrator on your Service cannot reach you unless you `friendslist add` their address once a case is filed.
70
71
  7. **Trust** — bind a REUSED third-party Arbitration: it MUST use a different Permission than the Service (`E_ARBITRATION_PERMISSION_CONFLICT` = 33). `compensation_fund_add` funds an internal `Balance<T>` (not a Treasury, not a payment to the arb); a non-empty fund at publish requires non-empty `arbitrations` (`E_ARBITRATION_NOT_SET_WITH_COMPENSATION_FUND` = 25).
71
72
  8. **Pre-publish verify** — machineNode2file + guard2file exports · `aggregate_risks` CRITICAL cleared · permission indices granted · arb Permission isolation · contact IM + messenger enabled → `service` `publish: true`.
72
73
  9. **Test order** — `service` `order_new` (requires bPublished, else E_NOT_PUBLISHED=7) → disclose the next nodes → advance each forward from radar `recommended_call` → trigger allocation (below) → verify every claimant received. Use a user-chosen test account.
73
74
 
74
75
  ### Lock levels after publish
75
76
 
76
- - **L1 permanent** (no exception, new Service version to change): `machine`, `order_allocators`.
77
+ - **L1 permanent** (no exception — the L2 lock duration does NOT unlock these; machine/order_allocators are permanently frozen once published): `machine`, `order_allocators`.
77
78
  - **L2 time-locked** (requires pause + `setting_lock_duration` elapsed; default 30 days = 2,592,000,000 ms): arbitrations/rewards **remove/clear**, `compensation_fund_withdraw`.
78
79
  - **L3 stays mutable**: arbitrations/rewards **add**, `buy_guard`, `sales`, `discount`, `description`, `location`, `repositories` add, `compensation_fund_add`, `setting_lock_duration_add`, `customer_required`, `um`.
79
80
 
@@ -108,16 +109,26 @@ WOW is the default token; supported bridge tokens/chains: `bridge_operation` ope
108
109
 
109
110
  ---
110
111
 
112
+ ## Fund-flow patterns the primitives already support
113
+
114
+ Combinations that need no new Service — staged release/holdbacks, commission holdback (no clawback exists), reward rule replacement, buyer blocklists via `buy_guard`, referral anti-self-purchase, and multi-party recourse. All are cataloged as Guard design patterns: `schema_query` action=`get_guard_design_patterns`, ids `pattern.allocation_staged_release`, `pattern.commission_holdback`, `pattern.reward_rule_replacement`, `pattern.buy_guard_blocklist`, `pattern.referral_anti_self_purchase`, `pattern.multi_party_recourse` (plus `pattern.allocator_order_anchor` for zero-share binding, below). Read each pattern's notes: VERIFIED parts are tested; INFERENCE parts need a dry-run before publishing (published allocators cannot change).
115
+
116
+ ---
117
+
111
118
  ## Iteration: in-place vs new version
112
119
 
113
120
  | Situation | Strategy |
114
121
  |-----------|----------|
115
122
  | Unpublished draft | In-place modify |
116
- | Published, change to an L1 field (Machine, allocators) | NEW version: create new objects only for changed parts, reuse the rest by address (Permission, Guards, Treasury, Contact…), publish v2 as a separate Service — v1 keeps running. There is no fork/upgrade tool. |
123
+ | Published, change to an L1 field (Machine, allocators) | NEW version: create new objects only for changed parts, reuse the rest by address (Permission, Guards, Treasury, Contact…), publish v2 as a separate Service — v1 keeps running. There is no fork/upgrade tool. ⚠️ Before listing a Guard as reusable, export it with `guard2file` and look for a Service address written as a constant (e.g. an `order.service == <address>` comparison) — such a Guard works for ONE Service only, and every Guard (in allocators and on Machine forwards) carrying the constant must be rebuilt for v2. Avoid this from v1 by not writing the Service address into Guards that do not need it. |
117
124
  | Published, L3 change only (products, description, buy_guard…) | In-place mutate |
118
125
 
119
126
  Before deciding, confirm published state via `service_panorama`.
120
127
 
128
+ **Orders are self-contained across versions.** A v2 Service is independent: existing v1 orders are never migrated. Each order carries the product info it was bought with (snapshotted inside the order at purchase time) and settles under the terms it was bought under — unrelated to whatever the currently offered products are. Never promise a customer that an old order will pick up v2 terms or products.
129
+
130
+ **Lists and scores that change: use a Repository.** Keep a mutable list or number (allowed-operator list, blocklist, score) in a Repository policy and let the Guard read it — editing the list then needs no new Guard. Comparison and count/sum limits are in GUARD_SCHEMA_NOTES (`get_guard_design_patterns`): values compare as U256 numbers only, and a Guard cannot count or sum entries. Payees and split ratios in `order_allocators` still freeze at publish — pre-declare the tiers you may need.
131
+
121
132
  ---
122
133
 
123
134
  ## Operating live orders
@@ -125,3 +136,4 @@ Before deciding, confirm published state via `service_panorama`.
125
136
  - Progress work item is the **Progress** object: canonical forward ops are `next` (advance; default), `hold` (block), `unhold` (release own hold), `adminUnhold` (force, permission 224). Execute exactly what radar `recommended_call` returns; no call suggested = not yours to execute.
126
137
  - Check `customer_required` before fulfillment: missing info must arrive via encrypted Messenger to the Contact, with the Contact/WTS proof recorded as `order_required_info`.
127
138
  - Demand-side business: `evaluation_operation` `demand_match` (demand→services), `service_match` (service→demands), `capability_gap`, `compose_service` are read-only; the supplier presents via `demand.present` (see wowok-supplier).
139
+ - Disputes on your orders are Arbitration cases (counterparty view: wowok-arbitrator). Merchant channel order: (1) **Messenger FIRST** — negotiate and submit evidence (order WTS records, chat transcripts) to the customer over encrypted chat; (2) when the public case record itself needs your position, use the Service call `arb_statement` (permission 321): attach a bounded statement to the case opened against one of your orders — it appends a permanent public event, mutates nothing on the Arb, works in ANY case state, and never requires holding the order. Use it to state facts or report customer conduct, not as a substitute for the Messenger evidence thread.
@@ -95,6 +95,7 @@ Settlement is released through the allocation waterfall when the sub-order compl
95
95
  1. Verify your share reached your address (query the sub-order's Allocation/Treasury; the supplier-interest `fund_flow` block tells you what to check).
96
96
  2. If the upstream merchant stalls: Messenger nudge (WTS-recorded) → arbitration if the upstream Service binds one → on-chain reputation (permanent, public).
97
97
  3. Know the recourse before you start: the upstream `compensation_fund` is the indemnity source; an empty fund leaves only the refund path + reputation.
98
+ 4. If you are an intermediary, your own recourse against your supplier requires that you are the customer in an order on their Service — buying their part as its own order keeps those customer rights; being only an allocation recipient on the merchant's order leaves none.
98
99
 
99
100
  ---
100
101