@ixo/decision-oracle 0.2.5 → 0.2.7

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.
Files changed (85) hide show
  1. package/README.md +6 -3
  2. package/dist/cli/commands/init.d.ts +3 -1
  3. package/dist/cli/commands/init.d.ts.map +1 -1
  4. package/dist/cli/commands/init.js +42 -2
  5. package/dist/cli/commands/init.js.map +1 -1
  6. package/dist/cli/commands/oracle-init.d.ts.map +1 -1
  7. package/dist/cli/commands/oracle-init.js +13 -5
  8. package/dist/cli/commands/oracle-init.js.map +1 -1
  9. package/dist/cli/index.js +6 -3
  10. package/dist/cli/index.js.map +1 -1
  11. package/dist/cron/openhands.d.ts +9 -0
  12. package/dist/cron/openhands.d.ts.map +1 -0
  13. package/dist/cron/openhands.js +30 -0
  14. package/dist/cron/openhands.js.map +1 -0
  15. package/dist/cron/scan.d.ts.map +1 -1
  16. package/dist/cron/scan.js +3 -0
  17. package/dist/cron/scan.js.map +1 -1
  18. package/dist/db/schema.d.ts +158 -0
  19. package/dist/db/schema.d.ts.map +1 -1
  20. package/dist/db/schema.js +26 -0
  21. package/dist/db/schema.js.map +1 -1
  22. package/dist/define-oracle.d.ts +3 -0
  23. package/dist/define-oracle.d.ts.map +1 -1
  24. package/dist/define-oracle.js +13 -1
  25. package/dist/define-oracle.js.map +1 -1
  26. package/dist/env.d.ts +12 -0
  27. package/dist/env.d.ts.map +1 -1
  28. package/dist/index.d.ts +1 -1
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/lib/ixo/blocksync/index.d.ts +4 -0
  31. package/dist/lib/ixo/blocksync/index.d.ts.map +1 -1
  32. package/dist/lib/ixo/blocksync/index.js +47 -1
  33. package/dist/lib/ixo/blocksync/index.js.map +1 -1
  34. package/dist/lib/ixo/blocksync/queries.d.ts +2 -0
  35. package/dist/lib/ixo/blocksync/queries.d.ts.map +1 -1
  36. package/dist/lib/ixo/blocksync/queries.js +17 -0
  37. package/dist/lib/ixo/blocksync/queries.js.map +1 -1
  38. package/dist/lib/ixo/chain.d.ts +1 -1
  39. package/dist/lib/ixo/chain.d.ts.map +1 -1
  40. package/dist/lib/openhands/backstop.d.ts +131 -0
  41. package/dist/lib/openhands/backstop.d.ts.map +1 -0
  42. package/dist/lib/openhands/backstop.js +513 -0
  43. package/dist/lib/openhands/backstop.js.map +1 -0
  44. package/dist/lib/openhands/chain.d.ts +218 -0
  45. package/dist/lib/openhands/chain.d.ts.map +1 -0
  46. package/dist/lib/openhands/chain.js +392 -0
  47. package/dist/lib/openhands/chain.js.map +1 -0
  48. package/dist/lib/openhands/options.d.ts +13 -0
  49. package/dist/lib/openhands/options.d.ts.map +1 -0
  50. package/dist/lib/openhands/options.js +28 -0
  51. package/dist/lib/openhands/options.js.map +1 -0
  52. package/dist/lib/openhands/routes.d.ts +73 -0
  53. package/dist/lib/openhands/routes.d.ts.map +1 -0
  54. package/dist/lib/openhands/routes.js +355 -0
  55. package/dist/lib/openhands/routes.js.map +1 -0
  56. package/dist/lib/openhands/store.d.ts +74 -0
  57. package/dist/lib/openhands/store.d.ts.map +1 -0
  58. package/dist/lib/openhands/store.js +148 -0
  59. package/dist/lib/openhands/store.js.map +1 -0
  60. package/dist/lib/review/reviewer-grant.js +1 -1
  61. package/dist/lib/review/reviewer-grant.js.map +1 -1
  62. package/dist/oracle.d.ts +52 -1
  63. package/dist/oracle.d.ts.map +1 -1
  64. package/dist/oracle.js +6 -0
  65. package/dist/oracle.js.map +1 -1
  66. package/dist/routes/v1/info.d.ts.map +1 -1
  67. package/dist/routes/v1/info.js +16 -1
  68. package/dist/routes/v1/info.js.map +1 -1
  69. package/dist/runtime.d.ts +6 -0
  70. package/dist/runtime.d.ts.map +1 -1
  71. package/dist/runtime.js +10 -0
  72. package/dist/runtime.js.map +1 -1
  73. package/dist/workflows/openhands-hire.d.ts +65 -0
  74. package/dist/workflows/openhands-hire.d.ts.map +1 -0
  75. package/dist/workflows/openhands-hire.js +203 -0
  76. package/dist/workflows/openhands-hire.js.map +1 -0
  77. package/docs/api.md +72 -7
  78. package/docs/guide.md +33 -0
  79. package/migrations/0025_openhands.sql +12 -0
  80. package/migrations/meta/0025_snapshot.json +2976 -0
  81. package/migrations/meta/_journal.json +7 -0
  82. package/package.json +1 -1
  83. package/skills/README.md +1 -1
  84. package/skills/add-openhands-support/SKILL.md +96 -86
  85. package/skills/create-oracle/SKILL.md +10 -4
@@ -176,6 +176,13 @@
176
176
  "when": 1792009954775,
177
177
  "tag": "0024_pending_task_details",
178
178
  "breakpoints": true
179
+ },
180
+ {
181
+ "idx": 25,
182
+ "version": "6",
183
+ "when": 1792573809270,
184
+ "tag": "0025_openhands",
185
+ "breakpoints": true
179
186
  }
180
187
  ]
181
188
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ixo/decision-oracle",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Run an IXO evaluation oracle: pull claims, produce facts with your handlers, let the decision engine decide, sign on chain",
6
6
  "keywords": [
package/skills/README.md CHANGED
@@ -13,7 +13,7 @@ installed package (leaving any skill of your own in that directory alone).
13
13
  | `create-collection` | creating a claim collection an oracle can be hired against |
14
14
  | `decision-api-client` | testing a Decision API oracle from the customer side: devnet test credentials (source, keys, payment delegation), the SDK and CLI smoke, MCP from Claude Code, the docs agent test |
15
15
  | `decision-api-oracle` | turning on, deploying and verifying the Decision API lane — the shipment-delivery example (SwiftDrop Express) on devnet end to end: publish, identity, Cloudflare, deploy, engine registration (payable at once), operator, verify, emails |
16
- | `add-openhands-support` | making an oracle hireable from the Openhands app (asks, the Yoma youth world): the hire/scan adapter, the bridge's fact names, pricing, the picker's card fields, engine registration |
16
+ | `add-openhands-support` | making an oracle hireable from the Openhands app (asks, the Yoma youth world): the OpenHands add-on (`init --openhands`), who pays for decisions, the account to register with, the picker's card, the bridge's fact names for a General checker |
17
17
 
18
18
  `reference/engine-contract.md` (here, beside the skills) is the decision engine's contract —
19
19
  background for all eight, not an interface anyone codes against.
@@ -1,114 +1,124 @@
1
1
  ---
2
2
  name: add-openhands-support
3
- description: Use when an oracle built on @ixo/decision-oracle should be hireable from the Openhands Network app (asks, quests, the Yoma youth world) — "make my oracle work with Openhands", an oracle missing from the Openhands checker picker, a hire nudge that 404s, an ask whose claims are never judged, or FACT_MISSING on judgeN / withinRadiusN / openhandsSite names.
3
+ description: Use when an oracle built on @ixo/decision-oracle should be hireable from the Openhands Network app (asks, quests, the Yoma youth world) — "make my oracle work with Openhands", "init --openhands", an oracle missing from the Openhands checker picker, a hire call that 404s or 409s, an ask whose claims are never judged, or FACT_MISSING on judgeN / withinRadiusN / openhandsSite names.
4
4
  ---
5
5
 
6
6
  # Adding Openhands support to an oracle
7
7
 
8
8
  ## Overview
9
9
 
10
- An Openhands ask is its OWN protocol: the app writes a rubric per ask from the poster's sentence
11
- (`bridge.ts toEngineRubric`), escrows the pay, grants a **meta-authorization** to the checker the
12
- poster picked, and nudges that checker's `#eval` endpoint. A plain `decision-oracle init` project can
13
- do none of the Openhands half: it has no hire/scan routes, cannot mint its own evaluate grant from
14
- a meta-grant, does not answer the bridge's fact names, and is filtered out of the picker. This
15
- skill adds that adapter. The engine still decides; nothing here judges.
10
+ The Openhands app lets anyone post an ask and pick the oracle ("checker") that judges the answers.
11
+ When a poster picks yours, their posting transaction grants your oracle a **meta-authorization**
12
+ (the right to authorize itself on the new collection) and the app calls
13
+ `POST https://<your host>/openhands/hire/<collectionId>`. The package's **OpenHands add-on**
14
+ answers that call: it checks the grant on chain, mints the oracle's own evaluate grant under it,
15
+ registers the collection through the normal four gates and scans it — and a backstop every five
16
+ minutes catches a call that never arrived and keeps every hired ask topped up. The engine still
17
+ decides; nothing here judges.
16
18
 
17
- **Explain before acting.** Tell the provider what will happen — files copied into their project,
18
- a redeploy, an `oracle init` that signs chain transactions (card refresh), `engine register` —
19
+ Two kinds of checker — ask the provider which they are building:
20
+
21
+ | Kind | `supportedProtocols` | What the asks look like | Facts you answer |
22
+ | --- | --- | --- | --- |
23
+ | **Expert** (most providers) | your protocol(s) | The poster's ask uses YOUR protocol as it is — your rubric, your form | Your own rubric's names, as for any oracle |
24
+ | **General** | `[]` | Openhands writes a rubric per ask from the poster's sentence | The bridge's vocabulary (step 3) |
25
+
26
+ **Explain before acting.** Tell the provider what will happen — edits to `src/index.ts` and
27
+ `wrangler.jsonc`, a redeploy, `engine register`, an `oracle init` that signs chain transactions —
19
28
  and wait for their OK. Dry-run every chain step first (`create-oracle` step 8's contract).
20
29
 
21
- ## The adapter (copy, don't rewrite)
30
+ ## 1. Turn the add-on on
22
31
 
23
- Source of truth: `examples/street-check-oracle` in the eval-oracle repo (an `init` project with
24
- the adapter added, deployed on devnet). Copy:
32
+ A NEW project: `bunx decision-oracle init <dir> --openhands` — done, go to step 2.
25
33
 
26
- | Path | What it is |
27
- | --- | --- |
28
- | `src/openhands/` | `routes.ts` (`POST /openhands/hire/:id`, `/openhands/scan/:id`, `GET /openhands/claims/:id/why`), `invitations.ts` (10-min backstop), `chain.ts` (meta-grant → `MsgCreateClaimAuthorization`), `act.ts` / `release.ts` (pooled payouts — the act seam's amount stands only where the collection's owner set `operatorAmounts: "allowed"`; Verify step 4), `spots.ts` |
29
- | `src/workflows/hire.ts` | `OpenhandsHire`: verify → mint → register → scan, one instance per collection |
30
- | `src/facts/` | the bridge's names: `withinRadius[2..5]`, `located`, `beforeAfter` (package stock), `notElsewhere[N]`, `notMarkedGenerated[N]`, `photoShape[N]`, `daylight`, `weather`, `notAlreadyMapped`, `cooldown`, `reMeasure[N]`, `openhandsSite`; `ai.judge[N]` is the stock judge |
31
- | `src/index.ts` | wraps `oracle.fetch` with `handleOpenhandsRoute`, routes cron `*/10` to the three passes, exports `OpenhandsHire` |
32
- | `src/env.ts`, `src/pricing.ts`, `migrations/`, `scripts/flatten-package-migrations.ts` (+ `scripts/lib/`) | `OH_DB`, `HIRE_WORKFLOW`, `WHY_RATE_LIMITER`, the check price |
33
-
34
- Outside the eval-oracle repo, get it with `git clone https://github.com/ixoworld/eval-oracle` and
35
- copy from `examples/street-check-oracle/`. The fact handlers are not street-specific: they are the
36
- bridge's generic vocabulary, and each ask's rubric picks which ones it asks for — copy them as
37
- they are. If the project already answers one of these names, keep ONE handler for it: a name
38
- answered twice throws at module evaluation (`defineFacts`).
39
-
40
- `wrangler.jsonc`: a second D1 `OH_DB` (`migrations_dir: "migrations"`), the `HIRE_WORKFLOW`
41
- workflow (`class_name: "OpenhandsHire"`), crons `["* * * * *", "*/5 * * * *", "0 * * * *", "*/10 * * * *"]`
42
- (the package's three tiers plus Openhands' ten-minute one), the
43
- `WHY_RATE_LIMITER` ratelimit — in EVERY env. Keep `supportedProtocols: []` (every ask is new).
34
+ An EXISTING project — three edits:
44
35
 
45
- ```bash
46
- wrangler d1 create <name>-oh-<env> # paste the id into that env's OH_DB
47
- bun run db:migrate:remote # must apply BOTH databases — copy the example's script
48
- bun run cf-typegen && bun run check
36
+ 1. `src/index.ts`: add `openhands: {}` to `defineOracle({...})`, and re-export the hire:
37
+ `export const { ClaimIngest, ReviewComplete, OpenhandsHire, SequenceManagerDO } = oracle;`
38
+ 2. `wrangler.jsonc`, in the top level AND every `env.<name>` block (named envs inherit no
39
+ bindings): a workflow `{ "name": "<project>-openhands-hire[-<env>]", "binding": "HIRE_WORKFLOW",
40
+ "class_name": "OpenhandsHire" }`, and a ratelimit `{ "name": "OPENHANDS_RATE_LIMITER",
41
+ "namespace_id": "1003", "simple": { "limit": 300, "period": 60 } }`. Without the limiter a
42
+ deployed oracle answers the webhooks `503` (fail closed).
43
+ 3. `bun run cf-typegen && bun run check`.
44
+
45
+ Nothing else: no second database (the add-on's two tables ship in the package's migrations), no
46
+ extra cron (it rides the package's `*/5` tier), no routes to write.
47
+
48
+ ## 2. Decide who pays for decisions
49
+
50
+ The engine bills every decision to the account that registered the oracle. Pick one:
51
+
52
+ - **Charge a fee** — `pricing.evaluation` (or that env's `EVALUATION_DENOM` /
53
+ `EVALUATION_MIN_AMOUNT`, required on mainnet) in the app's ask denom: `uixo` on devnet, `upay` on
54
+ testnet/mainnet. The poster's escrow carries it; an ask escrowing less is refused 402 and never
55
+ judged. A sensible default is `350000` base units (0.35 PAY), above the engine's per-decision cost.
56
+ - **Or free, bounded** — `minAmount: "0"` and an `openhands.admit` hook that refuses asks you will
57
+ not pay for (an allow-list of admins, a daily budget):
58
+
59
+ ```ts
60
+ openhands: {
61
+ admit: ({ admin }) => (MY_ADMINS.has(admin) ? null : "not one of our asks"),
62
+ },
49
63
  ```
50
64
 
51
- ## Pricing — set it deliberately per env
52
-
53
- `src/pricing.ts` `CHECK_PRICE_DENOM` / `CHECK_PRICE_AMOUNT` feed `pricing.evaluation` AND the
54
- ceiling written on every minted grant. Denom = the app's ask denom (`uixo` on devnet, `upay` on
55
- testnet/mainnet). In a template project the `EVALUATION_DENOM` / `EVALUATION_MIN_AMOUNT` vars in
56
- `wrangler.jsonc` override `pricing.evaluation` for that env — so set `EVALUATION_DENOM=upay` and
57
- `EVALUATION_MIN_AMOUNT=<the check price>` in the testnet AND mainnet envs (mainnet will not boot
58
- without them), or `EVALUATION_MIN_AMOUNT=0` for an oracle IXO bills per review (its collections
59
- carry an empty evaluation leg). Outside per-review billing, 0 means the oracle works for free while
60
- the engine bills its owner per decision. The picker shows the price from `/v1/info`, and the
61
- poster's escrow carries it; an ask escrowing less is refused 402 and never judged. Default, unless
62
- the provider names one: `350_000` base units — 0.35 IXO on devnet, 0.35 PAY ($0.35) on
63
- testnet/mainnet, Openhands' own check fee, which covers the engine's $0.30 per decision.
64
-
65
- ## Being listed and hired
66
-
67
- The app's picker lists an oracle when its entity has: `#acard` with a **`check-openhands`** service (next to
68
- `check-measure`, priced in PAY — the app reads the service id, and `check-openhands` is what marks
69
- the oracle Openhands-compatible); `#orz` granting `ORACLE_ADDRESS`; `#eval` = an https base URL
70
- whose `/v1/info` answers that address, the ask denom, and `policies.allowAiChecks: true` (else it
71
- is offered only for asks without written checks); and the oracle **registered with the engine**
72
- (`engine register`, below). `oracle init` writes `#orz`, `#eval` and the card — re-run it after any
73
- price change (`acard` drifts); it is idempotent against live state, so a re-run on an initialised
74
- oracle only replaces what drifted. `--openhands` adds the `check-openhands` service, priced in
75
- PAY at the oracle's per-review price (`/v1/info`'s `pricing.api`, else `--price-pay <n>`;
76
- 1 PAY = 1 USD):
65
+ Free with no `admit` means any poster can spend your credits.
66
+
67
+ ## 3. Facts — only for a General checker
68
+
69
+ An Expert checker answers its own rubric; skip this. A General checker judges Openhands' per-ask
70
+ rubrics, which ask for the bridge's names: `withinRadius[2..5]`, `located`, `beforeAfter`
71
+ (package stock — `@ixo/decision-oracle/facts`), `notElsewhere[N]`, `notMarkedGenerated[N]`,
72
+ `photoShape[N]`, `daylight`, `weather`, `notAlreadyMapped`, `cooldown`, `reMeasure[N]`,
73
+ `openhandsSite`; `ai.judge[N]` is the stock judge. Copy the handlers from
74
+ `examples/street-check-oracle/src/facts/` in https://github.com/ixoworld/eval-oracle as they are —
75
+ they are the bridge's generic vocabulary, not street-specific. If the project already answers one
76
+ of these names, keep ONE handler for it (a name answered twice throws at module evaluation).
77
+ Keep `supportedProtocols: []`.
78
+
79
+ ## 4. Deploy, register, card
77
80
 
78
81
  ```bash
79
- bunx decision-oracle oracle init --protocol <any ask's protocol, or the app's claim-form entity> \
80
- --kit-url https://<host> --logo https://<host>/logo.svg --openhands --network <n> # dry run; then --yes
82
+ bunx wrangler d1 migrations apply DB --remote --env <env> # 0025_openhands, before the deploy
83
+ bunx wrangler deploy --env <env>
84
+ bunx decision-oracle engine register --env <env> --env-file .dev.vars.<env>
85
+ bunx decision-oracle oracle init --protocol <your protocol> --kit-url https://<host> \
86
+ --logo https://<host>/logo.svg --network <n> # dry run; then --yes
81
87
  ```
82
88
 
83
- Hire/scan nudges go to the PICKED oracle's `#eval`; you know the app routes to you when the hire
84
- nudge shows up in THIS oracle's logs after a post.
85
-
86
- Then, right after deploy: `bunx decision-oracle engine register --env <env> --env-file .dev.vars`.
87
- The Openhands app lists only registered oracles, and otherwise the engine (and the Decision
88
- Console) learns the oracle only at its first decision.
89
+ - **Register with an account you will not post or review with.** The engine never lets the
90
+ account that registered an oracle review that oracle's claims (`oracle-owner`). Use a company or
91
+ service login, so the provider can still answer reviews on their own asks.
92
+ - `oracle init` sees the `openhands` webhooks on `/v1/info` and adds the **`check-openhands`**
93
+ service to the Agent Card — the marker the app's picker reads, priced at `pricing.api` on
94
+ `/v1/info`, else `--price-pay <n>`, else your evaluation fee when it is in `upay`
95
+ (1 PAY = 1 USD). Re-run it after a price change; it is idempotent and only replaces what drifted.
96
+ - The picker lists an oracle whose entity has that card, `#orz` granting `ORACLE_ADDRESS`, an https
97
+ `#eval` whose `/v1/info` answers that address and names `openhands`, and that is registered with
98
+ the engine. `policies.allowAiChecks: false` hides it from asks with written checks.
89
99
 
90
100
  ## Verify (in order)
91
101
 
92
- 1. `curl <host>/v1/info` → address, `pricing.evaluation` in the ask denom, `allowAiChecks: true`.
93
- 2. The composer's checker step lists the oracle at its price.
94
- 3. Post an ask picking it → `wrangler workflows instances describe <name>-hire-<env> <collectionId>`
95
- shows verify, mint (a tx), register `active`, scan.
96
- 4. Submit a claim → logs `evaluate.done` (`decided`) then `act.submitted`; the receipt page
97
- `/r/<id>` shows the decision trace and the payout line naming the check fee. The pooled amount
98
- the act seam picks stands only if the collection's owner set `operatorAmounts: "allowed"` —
99
- `PATCH /v1/collections/:id/settings` with `{ "operatorAmounts": "allowed" }` (UCAN action
100
- `collections/settings`), under the owner's
101
- own UCAN. Otherwise the oracle pays the default leg and logs `act.amount-ignored-not-opted-in`.
102
+ 1. `curl https://<host>/v1/info` → `openhands: { hire, scan }`, `address`, pricing in the ask denom.
103
+ 2. `curl -X POST https://<host>/openhands/hire/1` → `404` or `409` with a JSON reason (not `503`:
104
+ that is a missing `OPENHANDS_RATE_LIMITER`).
105
+ 3. The app's checker step lists the oracle at its price.
106
+ 4. Post an ask picking it → `bunx wrangler workflows instances describe <project>-openhands-hire-<env>
107
+ <collectionId>` shows `verify`, `mint` (a tx), `register` (`active`), `scan`. Logs:
108
+ `openhands.hire.done`.
109
+ 5. Submit a claim → `evaluate.done` (`decided`), then `act.submitted`.
102
110
 
103
111
  ## Common mistakes
104
112
 
105
113
  | Symptom | Cause / fix |
106
114
  | --- | --- |
107
- | Hire nudge 404 | the adapter's routes are not wrapped in `src/index.ts` `fetch` |
108
- | Every claim rejected `weather` "unreachable" | `weather` left as a stub; copy `src/facts/weather.ts` (Open-Meteo, no key) |
109
- | Oracle missing from the picker | no `check-openhands` service on `#acard`, no `#orz`/https `#eval`, not `engine register`ed, or its price unreadable |
110
- | Picker shows the oracle at 0 | `pricing.ts` / that env's `EVALUATION_MIN_AMOUNT` still 0 on an oracle not billed per review, or the denom ≠ the ask denom |
111
- | `withinRadius` fails for everyone | the ask's place was geocoded from a word ("You" → a village in Burkina Faso); set the place by name |
112
- | Console "Could not read this oracle's prices" | the console reads the Decision API price list; a chain-lane oracle has none (`API_LANE` off) — console-side, not an oracle fault |
113
- | Wrangler can't resolve `protobufjs/minimal.js` | inside the eval-oracle workspace there is one hoisted protobufjs; drop any protobufjs `alias` you copied in |
114
- | `chain.test.ts` fails after a denom change | the "foreign denom" fixtures used your new denom; give them one you are not paid in |
115
+ | Hire call 404 on every id, including real ones | `openhands` is not set in `defineOracle` — the routes only exist with it (the 404 is then the app's not-found, not JSON) |
116
+ | Hire call 503 "rate limiter unavailable" | no `OPENHANDS_RATE_LIMITER` in that env's `wrangler.jsonc` |
117
+ | Hire call 409 "no live meta-grant" | the poster picked another checker, or the grant was signed by someone other than the collection's admin — check which oracle address the ask granted (`/cosmos/authz/v1beta1/grants/granter/<admin>`) |
118
+ | Hire instance ends "is not served" | your `admit` hook refused it — by design |
119
+ | Hire instance ends at `register` with 402 | the ask escrows less than your evaluation fee, or in another denom |
120
+ | Hire instance ends at `register` with 409 "protocol" | an Expert checker picked for an ask on a protocol you do not list |
121
+ | `HIRE_WORKFLOW binding is missing` in the logs | the workflow is missing from that env's `wrangler.jsonc`, or `OpenhandsHire` is not re-exported from `src/index.ts` |
122
+ | Oracle missing from the picker | no `check-openhands` card (re-run `oracle init`), no `#orz`/https `#eval`, not `engine register`ed, or no per-review price |
123
+ | `REVIEWER_NOT_AUTHORIZED: oracle-owner` when the provider reviews | they registered the oracle with the same login they post and review with — register it under a separate account |
124
+ | Every claim of a General ask rejected `weather` "unreachable" | `weather` left as a stub; copy `src/facts/weather.ts` (Open-Meteo, no key) |
@@ -58,7 +58,7 @@ handlers themselves (`write-facts`, handed off to at step 3).
58
58
  ### 0. The project
59
59
 
60
60
  ```bash
61
- bunx @ixo/decision-oracle init <dir> [--name <project-name>]
61
+ bunx @ixo/decision-oracle init <dir> [--name <project-name>] [--openhands]
62
62
  cd <dir> && bun install
63
63
  bun run cf-typegen # after ANY wrangler.jsonc binding/var change, too
64
64
  wrangler d1 create <project-name> # paste the id into wrangler.jsonc
@@ -70,6 +70,10 @@ cp .dev.vars.example .dev.vars # git-ignored; secrets only
70
70
  Three files are the provider's: `src/index.ts` (what the oracle IS), `src/facts/index.ts` (how it
71
71
  answers), `wrangler.jsonc` (where it runs).
72
72
 
73
+ Ask first: **is this oracle for Openhands** (picked by posters in the Openhands app)? Yes ⇒
74
+ `--openhands`, which wires the add-on (the hire webhooks, the hire workflow and its rate limiter in
75
+ every env) — then follow `add-openhands-support` for who pays, registering and the picker card.
76
+
73
77
  ### 1. Identity — two keys
74
78
 
75
79
  ```bash
@@ -334,9 +338,10 @@ Decision Console, which lists the engine's `GET /v1/oracles` — does not know t
334
338
 
335
339
  ### 10. Get hired
336
340
 
337
- Hired from the Openhands app (asks, the Yoma youth world) rather than a portal collection? That is
338
- the `add-openhands-support` skill — the hire/scan adapter, the bridge's fact names, the picker's
339
- card fields.
341
+ Hired from the Openhands app (asks, the Yoma youth world) rather than a portal collection? The
342
+ oracle hires itself on each ask that picks it (`openhands: {}` — `init --openhands`); the
343
+ `add-openhands-support` skill covers who pays, the account to register with, the picker's card and
344
+ the bridge's fact names for a General checker.
340
345
 
341
346
  A real commissioner grants `ORACLE_ADDRESS` the Evaluate role on their collection and registers it
342
347
  (the portal makes that call). To prove the loop yourself, hire yourself with the `create-collection`
@@ -360,6 +365,7 @@ the required fee (`pricing.byProtocol` for that collection's protocol, else the
360
365
 
361
366
  | Slot | Ask | Lands in |
362
367
  | --- | --- | --- |
368
+ | Openhands | will posters pick it in the Openhands app? An Expert (its own protocol) or a General checker (Openhands' per-ask rubrics)? | `init --openhands`, `supportedProtocols` (`add-openhands-support`) |
363
369
  | Protocol | the DID, and which network | `--protocol`, `supportedProtocols` |
364
370
  | Pricing | denom + minimum per-evaluation payment per network; any protocol priced differently (incl. free)? | `EVALUATION_DENOM` / `EVALUATION_MIN_AMOUNT` per env, optionally `pricing.byProtocol` |
365
371
  | AI / image policy | does the work order declare `ai` checks; do any read images | `policies.allowAiChecks` / `allowImageChecks` |