@ixo/decision-oracle 0.2.10 → 0.2.12

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 (37) hide show
  1. package/README.md +13 -13
  2. package/dist/cli/commands/derive.d.ts +6 -2
  3. package/dist/cli/commands/derive.d.ts.map +1 -1
  4. package/dist/cli/commands/derive.js +33 -3
  5. package/dist/cli/commands/derive.js.map +1 -1
  6. package/dist/cli/commands/engine.d.ts.map +1 -1
  7. package/dist/cli/commands/engine.js +9 -2
  8. package/dist/cli/commands/engine.js.map +1 -1
  9. package/dist/cli/commands/init.js +2 -2
  10. package/dist/cli/commands/oracle-init.d.ts.map +1 -1
  11. package/dist/cli/commands/oracle-init.js +2 -2
  12. package/dist/cli/commands/oracle-init.js.map +1 -1
  13. package/dist/cli/index.js +24 -85
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/cli/lib/usage.d.ts +11 -0
  16. package/dist/cli/lib/usage.d.ts.map +1 -0
  17. package/dist/cli/lib/usage.js +112 -0
  18. package/dist/cli/lib/usage.js.map +1 -0
  19. package/dist/config.d.ts +9 -0
  20. package/dist/config.d.ts.map +1 -1
  21. package/dist/config.js +15 -1
  22. package/dist/config.js.map +1 -1
  23. package/dist/middleware/error-handler.d.ts.map +1 -1
  24. package/dist/middleware/error-handler.js +11 -0
  25. package/dist/middleware/error-handler.js.map +1 -1
  26. package/docs/api.md +7 -2
  27. package/docs/guide.md +13 -10
  28. package/package.json +1 -1
  29. package/skills/add-openhands-support/SKILL.md +3 -1
  30. package/skills/create-oracle/SKILL.md +20 -14
  31. package/skills/create-rubric/reference/format-cheatsheet.md +20 -0
  32. package/skills/decision-api-oracle/SKILL.md +2 -2
  33. package/templates/project/README.md +4 -3
  34. package/templates/project/package.json +1 -0
  35. package/templates/project/src/facts/index.ts +6 -2
  36. package/templates/project/src/index.ts +3 -1
  37. package/templates/project/wrangler.jsonc +116 -11
@@ -3,7 +3,8 @@ import { defineFacts } from "@ixo/decision-oracle/facts";
3
3
  /**
4
4
  * How this oracle produces the facts a rubric asks for. List only the names you answer yourself;
5
5
  * every other declared source runs the stock lane (a UCAN-signed POST to the declared endpoint)
6
- * and every other AI check runs OpenRouter with the rubric's own instructions.
6
+ * and every other AI check runs the stock judge with the rubric's own instructions (the Cloudflare
7
+ * AI Gateway by default; OpenRouter with AI_PROVIDER=openrouter).
7
8
  *
8
9
  * bunx decision-oracle protocol review <protocol did> — what the rubric declares, and which names need a handler
9
10
  * bunx decision-oracle facts scaffold <protocol did> — stubs + tests for those names
@@ -12,7 +13,10 @@ export const facts = defineFacts({
12
13
  ext: {
13
14
  // deliveryConfirmed: async ({ send }, tools) => {
14
15
  // const res = await tools.http.json(`https://courier.example/deliveries/${send.reference}`);
15
- // return res.ok && res.body?.status === "delivered";
16
+ // // An outage is not a "no": a throw becomes an error fact with the rubric's onError
17
+ // // (`throw fact.retryLater(…)` instead retries the whole step later).
18
+ // if (!res.ok) throw new Error(`courier answered ${res.status ?? "nothing"}`);
19
+ // return res.body?.status === "delivered";
16
20
  // },
17
21
  },
18
22
  ai: {},
@@ -10,7 +10,9 @@ const oracle = defineOracle({
10
10
  description: "Evaluates claims against the collection's rubric via the IXO decision engine.",
11
11
  // The protocol entity DIDs this oracle serves (GET /v1/info; enforced at register). [] ⇒ any.
12
12
  supportedProtocols: [],
13
- // The minimum on-chain evaluation payment a collection must carry (integer base units).
13
+ // The minimum on-chain evaluation payment a collection must carry (integer base units) — the one
14
+ // place to change it, except on mainnet, where wrangler.jsonc's EVALUATION_DENOM /
15
+ // EVALUATION_MIN_AMOUNT (required there, real USDC) replace it. Never PAY: only IXO-run oracles.
14
16
  pricing: { evaluation: { denom: "uixo", minAmount: "1000000" } },
15
17
  policies: {
16
18
  autoSign: true,
@@ -39,11 +39,11 @@
39
39
 
40
40
  // KV: caches only (UCAN principals, peer did:web documents, the engine-registered marker, chain
41
41
  // grants, the C2PA trust list). Nothing here is a source of truth — it can be emptied any time.
42
- // wrangler kv namespace create CACHE_KV
42
+ // wrangler kv namespace create {{name}}-cache
43
43
  "kv_namespaces": [
44
44
  {
45
45
  "binding": "CACHE_KV",
46
- "id": "<create with: wrangler kv namespace create CACHE_KV>"
46
+ "id": "<create with: wrangler kv namespace create {{name}}-cache>"
47
47
  }
48
48
  ],
49
49
 
@@ -133,6 +133,8 @@
133
133
  // Non-secret runtime config. Secrets go in .dev.vars locally (see .dev.vars.example) and via
134
134
  // `wrangler secret put <NAME>` once deployed — never here.
135
135
  "vars": {
136
+ // ENVIRONMENT is one of development | staging | production — anything else and the worker
137
+ // refuses its config (every request 500s, and the log names the var).
136
138
  "ENVIRONMENT": "development",
137
139
  "LOG_LEVEL": "debug",
138
140
  "SERVICE_NAME": "{{name}}",
@@ -148,12 +150,9 @@
148
150
  // store, VFS, IPFS gateway, RPC, portal) defaults from it — set one of those vars only to
149
151
  // override.
150
152
  "IXO_NETWORK": "devnet",
151
- // The coin (and minimum, integer base units) a collection's on-chain evaluation payment must
152
- // pay this oracle in — register refuses any other denom (402). It replaces `pricing.evaluation`
153
- // from `defineOracle`. devnet/testnet: a stand-in coin is fine (`uixo`). mainnet: REQUIRED,
154
- // and real USDC (see the production env) — the oracle refuses to start without it.
155
- "EVALUATION_DENOM": "uixo",
156
- "EVALUATION_MIN_AMOUNT": "1000000",
153
+ // The evaluation fee is `pricing.evaluation` in src/index.ts — the ONE place to change it off
154
+ // mainnet. EVALUATION_DENOM / EVALUATION_MIN_AMOUNT, when set in an env, REPLACE it there (the
155
+ // production env sets them: mainnet requires them, in real USDC).
157
156
 
158
157
  // THIS oracle's did:web host — the audience every inbound UCAN invocation must name, and the
159
158
  // issuer of every invocation this oracle mints. It must equal the Custom Domain in `routes`
@@ -226,6 +225,114 @@
226
225
  },
227
226
 
228
227
  "env": {
228
+ "devnet": {
229
+ // Without this the worker deploys as "<top-level name>-devnet" anyway — naming it here
230
+ // keeps the deployed name explicit and independent of the top-level one.
231
+ "name": "{{name}}-devnet",
232
+ // The Custom Domain IS the identity: it must equal ORACLE_HOSTNAME below. Declared here so
233
+ // the deploy attaches it (and its DNS record) instead of it being a dashboard step.
234
+ "routes": [{ "pattern": "<REPLACE: your devnet host>", "custom_domain": true }],
235
+ "vars": {
236
+ "ENVIRONMENT": "staging",
237
+ "LOG_LEVEL": "info",
238
+ "SERVICE_NAME": "{{name}}",
239
+ "SERVICE_VERSION": "0.1.0",
240
+ "CORS_ORIGINS": "*",
241
+ "CRON_COLLECTIONS_PER_TICK": "25",
242
+ "IXO_CLIENT_SEQUENCE_MIN_DELAY_MS": "1000",
243
+ "IXO_NETWORK": "devnet",
244
+ // No EVALUATION_DENOM / EVALUATION_MIN_AMOUNT: the fee is `pricing.evaluation` (src/index.ts).
245
+ "ORACLE_HOSTNAME": "<REPLACE: your devnet host>",
246
+ "ORACLE_DID": "did:ixo:<REPLACE_WITH_YOUR_ORACLE_ADDRESS>",
247
+ "ORACLE_ADDRESS": "<REPLACE_WITH_YOUR_ORACLE_ADDRESS>",
248
+ "ORACLE_MATRIX_USER_ID": "@did-ixo-<REPLACE_WITH_YOUR_ORACLE_ADDRESS>:devmx.ixo.earth",
249
+ "ORACLE_ENTITY_DID": "",
250
+ "AI_CHECK_MODEL": "openai/gpt-6-luna",
251
+ // AI provider (README "Configuration"): the AI Gateway by default — the `ai` binding plus the
252
+ // gateway's name; OpenRouter instead with AI_PROVIDER=openrouter + the OPENROUTER_API_KEY secret.
253
+ "AI_PROVIDER": "cloudflare",
254
+ // "AI_AUDIO_VIDEO": "false", // audio/video inputs — OpenRouter only
255
+ // "AI_GATEWAY_ID": "<your gateway>",
256
+ "C2PA_IMAGE_CHECK": "true",
257
+ "AUTO_SIGN": "true",
258
+ "API_LANE": "false",
259
+ "API_PAYMENTS": "false"
260
+ // "API_PRICE_USD_CENTS": "120",
261
+ // "X402_FACILITATOR_URL": "https://<facilitator host>",
262
+ // "X402_NETWORK": "cosmos:devnet-1",
263
+ // Where your earnings land (your own accounts; each offer's payTo). Unset ⇒ that way to pay is not offered.
264
+ // "EARNINGS_ADDRESS": "ixo1<your account>",
265
+ // "EARNINGS_BASE_WALLET": "0x<your Base wallet>",
266
+ // "BILLING_ENGINE_URL": "https://<billing-engine host>",
267
+ // "CONSOLE_URL": "https://<console host>",
268
+ // The OAuth server of /v1/mcp (MCP over OAuth); defaults per IXO_NETWORK — set for a local AuthHub.
269
+ // "AUTH_HUB_URL": "https://<authhub host>",
270
+ // "ORACLE_ADMIN_DIDS": "did:ixo:<admin>",
271
+ // "STATUS_READER_DIDS": "did:web:<monitor host>",
272
+
273
+ // "EMAIL_FROM_ADDRESS": "oracle@your-domain",
274
+ // "EMAIL_FROM_NAME": "Your Oracle",
275
+
276
+ // "SENTRY_TRACES_SAMPLE_RATE": "0.2",
277
+ // "SENTRY_ENVIRONMENT": "devnet"
278
+ },
279
+
280
+ // Optional Workers Traces for this env (billed per span from 2026-10-01): `observability` is
281
+ // inherited whole, so uncommenting this replaces the top-level block — traces 20%.
282
+ // "observability": {
283
+ // "enabled": true,
284
+ // "head_sampling_rate": 1,
285
+ // "traces": { "enabled": true, "head_sampling_rate": 0.2 },
286
+ // "logs": { "enabled": true }
287
+ // },
288
+
289
+ // Every binding and the `vars` block are redeclared per env — those inherit nothing from the
290
+ // top level (unlike `main`, `compatibility_date`, `triggers`, `migrations`, `observability`).
291
+ // wrangler d1 create {{name}}-devnet
292
+ "ai": { "binding": "AI" },
293
+ "d1_databases": [
294
+ {
295
+ "binding": "DB",
296
+ "database_name": "{{name}}-devnet",
297
+ "database_id": "<DEVNET_D1_ID>",
298
+ "migrations_dir": "node_modules/@ixo/decision-oracle/migrations"
299
+ }
300
+ ],
301
+ "kv_namespaces": [{ "binding": "CACHE_KV", "id": "<DEVNET_CACHE_KV_ID>" }],
302
+ "ratelimits": [
303
+ {
304
+ "name": "API_RATE_LIMITER",
305
+ "namespace_id": "1001",
306
+ "simple": { "limit": 100, "period": 60 }
307
+ },
308
+ {
309
+ "name": "API_KEY_RATE_LIMITER",
310
+ "namespace_id": "1002",
311
+ "simple": { "limit": 600, "period": 60 }
312
+ }
313
+ ],
314
+ // wrangler r2 bucket create {{name}}-uploads-devnet
315
+ // "r2_buckets": [{ "binding": "API_UPLOADS", "bucket_name": "{{name}}-uploads-devnet" }],
316
+ // wrangler r2 bucket create {{name}}-answers-devnet
317
+ // "r2_buckets": [{ "binding": "ANSWERS_ARCHIVE", "bucket_name": "{{name}}-answers-devnet" }],
318
+ // "analytics_engine_datasets": [{ "binding": "METRICS", "dataset": "eval_oracle_metrics_devnet" }],
319
+ "send_email": [{ "name": "EMAIL", "remote": true }],
320
+ "workflows": [
321
+ {
322
+ "name": "{{name}}-claim-ingest-devnet",
323
+ "binding": "CLAIM_WORKFLOW",
324
+ "class_name": "ClaimIngest"
325
+ },
326
+ {
327
+ "name": "{{name}}-review-complete-devnet",
328
+ "binding": "REVIEW_WORKFLOW",
329
+ "class_name": "ReviewComplete"
330
+ }
331
+ ],
332
+ "durable_objects": {
333
+ "bindings": [{ "name": "SEQUENCE_MANAGER", "class_name": "SequenceManagerDO" }]
334
+ }
335
+ },
229
336
  "testnet": {
230
337
  // Without this the worker deploys as "<top-level name>-testnet" anyway — naming it here
231
338
  // keeps the deployed name explicit and independent of the top-level one.
@@ -242,9 +349,7 @@
242
349
  "CRON_COLLECTIONS_PER_TICK": "25",
243
350
  "IXO_CLIENT_SEQUENCE_MIN_DELAY_MS": "1000",
244
351
  "IXO_NETWORK": "testnet",
245
- // Stand-in coin on testnet (owner ruling: any coin is fine off mainnet).
246
- "EVALUATION_DENOM": "uixo",
247
- "EVALUATION_MIN_AMOUNT": "1000000",
352
+ // No EVALUATION_DENOM / EVALUATION_MIN_AMOUNT: the fee is `pricing.evaluation` (src/index.ts).
248
353
  "ORACLE_HOSTNAME": "<REPLACE: your testnet host>",
249
354
  "ORACLE_DID": "did:ixo:<REPLACE_WITH_YOUR_ORACLE_ADDRESS>",
250
355
  "ORACLE_ADDRESS": "<REPLACE_WITH_YOUR_ORACLE_ADDRESS>",