callx402 0.0.0-stage → 1.0.1

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 (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +229 -2
  3. package/SPEC.md +264 -0
  4. package/bin/callx402.js +257 -0
  5. package/core/config.js +104 -0
  6. package/core/envelope.js +80 -0
  7. package/core/index.js +364 -0
  8. package/core/pipeline.js +371 -0
  9. package/core/remote.js +242 -0
  10. package/core/subsystems.js +136 -0
  11. package/dist/callx402-1.0.0.tgz +0 -0
  12. package/docs/ACTION_LANGUAGE.md +23 -0
  13. package/docs/MCP_IDENTITY.md +27 -0
  14. package/docs/README.md +315 -0
  15. package/docs/action-reference.md +247 -0
  16. package/docs/cli-help-verified-2026-10-06.txt +39 -0
  17. package/docs/logo.png +0 -0
  18. package/docs/problem-map.md +65 -0
  19. package/docs/troubleshooting/cx402-402afterfail-001-402-after-failed-settle.md +143 -0
  20. package/docs/troubleshooting/cx402-agentcap-001-agent-spending.md +114 -0
  21. package/docs/troubleshooting/cx402-eip3009-001-authorization-checklist.md +124 -0
  22. package/docs/troubleshooting/cx402-paidnores-001-paid-no-result.md +97 -0
  23. package/docs/troubleshooting/cx402-safretry-001-retry-after-payment.md +106 -0
  24. package/docs/troubleshooting/cx402-settlepend-001-settlement-pending.md +92 -0
  25. package/docs/troubleshooting/cx402-solanafail-001-solana-settlement.md +119 -0
  26. package/docs/troubleshooting/cx402-verset-001-verify-ok-settle-fails.md +101 -0
  27. package/docs/visuals/01-action-map.png +0 -0
  28. package/docs/visuals/02-diagnose.png +0 -0
  29. package/docs/visuals/03-resolve.png +0 -0
  30. package/docs/visuals/04-route.png +0 -0
  31. package/docs/visuals/05-preflight.png +0 -0
  32. package/docs/visuals/06-inspect.png +0 -0
  33. package/docs/visuals/07-status.png +0 -0
  34. package/docs/visuals/08-architecture.svg +49 -0
  35. package/docs/visuals/MANIFEST.md +40 -0
  36. package/docs/visuals/raw/01-help.out +39 -0
  37. package/docs/visuals/raw/02-diagnose.out +2 -0
  38. package/docs/visuals/raw/03-resolve.out +4 -0
  39. package/docs/visuals/raw/04-route.out +2 -0
  40. package/docs/visuals/raw/05-preflight.out +2 -0
  41. package/docs/visuals/raw/06-inspect.out +23 -0
  42. package/docs/visuals/raw/07-status.out +16 -0
  43. package/docs/visuals/render_terminal.py +149 -0
  44. package/docs/what-is-callx402.md +251 -0
  45. package/integrations/README.md +62 -0
  46. package/integrations/core.py +329 -0
  47. package/integrations/crewai/callx402_crewai.py +109 -0
  48. package/integrations/facilitator/settle-guard.js +99 -0
  49. package/integrations/langchain/callx402_tools.py +180 -0
  50. package/integrations/mcp-clients/README.md +121 -0
  51. package/integrations/n8n/callx402-incident-guard.json +1 -0
  52. package/mcp/README.md +63 -0
  53. package/mcp/index.js +239 -0
  54. package/mcp-publisher +0 -0
  55. package/package.json +28 -3
  56. package/scripts/drift-check.js +202 -0
  57. package/sdk/js/index.js +207 -0
  58. package/sdk/python/README.md +67 -0
  59. package/sdk/python/callx402/__init__.py +317 -0
  60. package/sdk/python/callx402/cli.py +193 -0
  61. package/sdk/python/pyproject.toml +30 -0
  62. package/sdk/python/setup.py +56 -0
  63. package/server/index.js +520 -0
  64. package/server/openapi.yaml +537 -0
  65. package/server.json +23 -0
  66. package/test/cli-dispatch.test.js +248 -0
  67. package/test/helpers.js +103 -0
  68. package/test/integrity.test.js +43 -0
  69. package/test/intent-pipeline.test.js +205 -0
  70. package/test/remote.test.js +166 -0
  71. package/test/safety.test.js +234 -0
  72. package/test/sdk.test.js +198 -0
  73. package/test/server.test.js +190 -0
  74. package/test/subsystems.test.js +118 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Payload
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,230 @@
1
- # Temporary Holding Version
1
+ > **Payload** — Developer infrastructure for x402, agent payments, and programmable revenue.
2
+ > PAYLOAD → VEYLINE (flagship) → CALLX402 (action layer) → REVRULE (separate) → developer products → free utilities.
3
+ > This repo: **callx402 by Payload — the universal action layer into Veyline's x402 infrastructure.**
2
4
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
5
+ <p align="center"><img src="docs/logo.png" alt="callx402 logo" width="200"></p>
6
+ # callx402 by Payload
7
+
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
9
+ [![Node >= 18](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)](package.json)
10
+ [![MCP stdio](https://img.shields.io/badge/MCP-stdio-blue.svg)](mcp/README.md)
11
+
12
+ **Powered by Veyline. When x402 breaks, callx402.**
13
+
14
+ callx402 is the universal action layer into Veyline's x402 infrastructure. Say what you need done in plain language (or hit an HTTP endpoint) and callx402 routes it to the production system that does the real work: diagnose a broken x402 payment, rescue a failed transaction, route an agent job to the cheapest viable path, resolve settlement state from on-chain evidence, or execute under an explicit budget with fail-closed safety rules.
15
+
16
+ **Why it exists:** x402 failures are expensive and opaque. A settlement attempt ends in `settlement_pending` and nobody knows whether the money moved. A 402 response your wallet misreads. A retry that signs a second authorization for the same intent and pays twice. callx402 exists for exactly those moments: `diagnose` pins the failure to a stage, `rescue` triages the incident, `resolve` settles the question from evidence, `route` finds the cheapest viable path, `execute` runs under a hard budget.
17
+
18
+ **Try it (one minute):**
19
+ ```sh
20
+ git clone https://github.com/Payloadhq/callx402
21
+ cd callx402 && npm install && npm link
22
+ callx402 diagnose --target "https://api.example.com/x402/pay"
23
+ ```
24
+
25
+ If it saves you one debugging session, star the repo and read on.
26
+
27
+ ## MCP server: connect in 60 seconds
28
+
29
+ This repo ships a zero-dependency, read-only MCP server (`mcp/index.js`, node
30
+ stdlib only, stdio transport) exposing six `x402_*` diagnostic tools. Nothing
31
+ here charges, executes, retries, or repays.
32
+
33
+ ```sh
34
+ git clone https://github.com/Payloadhq/callx402
35
+ # no npm install needed for the MCP server
36
+ ```
37
+
38
+ Add this block to your MCP client config (replace the path), then restart the
39
+ client:
40
+
41
+ | Client | Config file |
42
+ |---|---|
43
+ | Claude Desktop | `claude_desktop_config.json` (`~/Library/Application Support/Claude/` on macOS, `%APPDATA%\Claude\` on Windows) |
44
+ | Cursor | `~/.cursor/mcp.json` (user scope) or `.cursor/mcp.json` (project scope) |
45
+ | Windsurf | `~/.codeium/windsurf/mcp_config.json` |
46
+
47
+ ```json
48
+ {
49
+ "mcpServers": {
50
+ "callx402": {
51
+ "command": "node",
52
+ "args": ["/absolute/path/to/callx402/mcp/index.js"]
53
+ }
54
+ }
55
+ }
56
+ ```
57
+
58
+ Ask the client to list its MCP tools: the six `x402_*` tools should appear.
59
+ Per-client notes and the raw stdio test handshake:
60
+ [`integrations/mcp-clients/`](integrations/mcp-clients/).
61
+
62
+ ## The relationship
63
+
64
+ - **PAYLOAD** = the parent company.
65
+ - **VEYLINE** = production infrastructure for x402 + MCP. The flagship brand.
66
+ - **CALLX402 BY PAYLOAD** = the x402 response/action layer, powered by Veyline.
67
+ The entry action into Veyline's production infrastructure, not the flagship
68
+ name. Nothing here renames Veyline.
69
+
70
+ Discovery path: a developer searching for x402 finds callx402, uses it, and
71
+ learns Veyline. Payload is not affiliated with the x402 Foundation.
72
+
73
+ ## What it does
74
+
75
+ - **Diagnose** an x402 or MCP failure
76
+ - **Rescue** a failed transaction (auth-gated)
77
+ - **Route** a paid agent job to the cheapest viable path
78
+ - **Resolve** settlement state from on-chain evidence
79
+ - **Execute** under an explicit budget, with fail-closed safety rules
80
+
81
+ Behavioral usage language (not trademark claims):
82
+
83
+ - "Need to diagnose x402? callx402."
84
+ - "Need to rescue a transaction? callx402."
85
+ - "Need to route a paid agent job? callx402."
86
+ - "Need settlement certainty? callx402."
87
+ - "Need to execute under a budget? callx402."
88
+
89
+ ## Quickstart
90
+
91
+ ```sh
92
+ npm install callx402
93
+ ```
94
+
95
+ Alternative — install direct from GitHub (keeps working as a fallback):
96
+
97
+ ```sh
98
+ npm install Payloadhq/callx402
99
+ ```
100
+
101
+ Alternative — clone and link for local development:
102
+
103
+ ```sh
104
+ git clone https://github.com/Payloadhq/callx402
105
+ cd callx402
106
+ npm install
107
+ npm link # exposes the `callx402` command
108
+ ```
109
+
110
+ ```sh
111
+ callx402 status
112
+ callx402 "complete this job for under $1"
113
+ callx402 diagnose --target "https://api.example.com/x402/pay"
114
+ callx402 rescue --incident inc_123
115
+ callx402 route --goal "fetch 100 product prices for under $0.50"
116
+ callx402 resolve --evidence '{"txHash":"0xabc..."}'
117
+ ```
118
+
119
+ ### JavaScript SDK
120
+
121
+ ```js
122
+ const { callx402 } = require('callx402');
123
+
124
+ const result = await callx402({
125
+ intent: 'complete this job for under $1',
126
+ maxBudget: 1.00,
127
+ networks: ['base'],
128
+ assets: ['USDC'],
129
+ approvalThreshold: 5.00,
130
+ idempotencyKey: 'job-42',
131
+ });
132
+ ```
133
+
134
+ ### Python SDK
135
+
136
+ ```python
137
+ import callx402
138
+
139
+ result = callx402.callx402(
140
+ intent="complete this job for under $1",
141
+ max_budget=1.00,
142
+ networks=["base"],
143
+ assets=["USDC"],
144
+ approval_threshold=5.00,
145
+ idempotency_key="job-42",
146
+ )
147
+ ```
148
+
149
+ ### HTTP server
150
+
151
+ ```sh
152
+ CALLX402_PORT=8787 node server/index.js
153
+ curl -X POST http://127.0.0.1:8787/call \
154
+ -H 'Content-Type: application/json' \
155
+ -d '{"intent":"complete this job for under $1","maxBudget":1.00,"dryRun":true}'
156
+ ```
157
+
158
+ Full HTTP surface: `server/openapi.yaml` (served live at `GET /openapi.json`).
159
+
160
+ ## Commands
161
+
162
+ | Command | What it does |
163
+ |---|---|
164
+ | `callx402 "natural language intent"` | Intent mode: parse, plan, budget-check, route, execute |
165
+ | `callx402 status [--json]` | Subsystem reachability and flag state |
166
+ | `callx402 diagnose [--target ...]` | Diagnose an x402 / MCP failure |
167
+ | `callx402 rescue --incident <id>` | Rescue a transaction (auth-gated) |
168
+ | `callx402 route --goal <text>` | Route a paid job to the cheapest viable path |
169
+ | `callx402 resolve --evidence <json\|@file>` | Resolve settlement state from evidence |
170
+ | `callx402 doctor` | Run the MCP doctor checks |
171
+ | `callx402 execute --intent <text> [--max-budget N] [--dry-run]` | Execute under an explicit budget |
172
+ | `callx402 monitor [--once\|--watch]` | Watch subsystem/incident state |
173
+ | `callx402 preflight` | Preflight checks before a paid run |
174
+ | `callx402 inspect [--query <text>]` | Inspect capability graph / state |
175
+ | `callx402 config list \| get <k> \| set <k> <v>` | Manage local config |
176
+
177
+ ## Integrations
178
+
179
+ Working entry points for agent frameworks, automation, MCP clients, and x402
180
+ facilitators — all in [`integrations/`](integrations/) and tested against the
181
+ live rail:
182
+
183
+ - **LangChain** — 9 tools (`integrations/langchain/`): diagnose, recover,
184
+ resolve, evidence, explain, safe-retry, duplicate-payment risk, preflight,
185
+ plus the free live fee schedule
186
+ - **CrewAI** — the same actions as CrewAI Tools (`integrations/crewai/`)
187
+ - **n8n** — importable incident-guard workflow (`integrations/n8n/`): maps an
188
+ incident to a callx402 action, fetches the free live quote, invokes when
189
+ credentialed, otherwise emits payment instructions — never auto-pays
190
+ - **MCP clients** — Claude Desktop / Cursor / Windsurf setup for the free
191
+ read-only MCP server (`integrations/mcp-clients/`)
192
+ - **x402 facilitators** — `settle-guard.js` (`integrations/facilitator/`):
193
+ resolve settlement state from evidence *before* re-broadcasting a payment
194
+
195
+ Problem → action map: [`docs/problem-map.md`](docs/problem-map.md).
196
+ Machine front door for agents: https://payloadhq.github.io/agents.json.
197
+
198
+ ## Money-safety rules
199
+
200
+ - **Settlement UNKNOWN is never auto-retried and never repaid.**
201
+ - **Over-budget intents are refused with zero side effects.**
202
+ - **Approval thresholds fail closed.**
203
+ - **Idempotency keys dedupe** — repeats return the original, never re-execute.
204
+ - **Disabled or unreachable subsystems fail closed** — success is never faked.
205
+ - **Non-custodial** — callx402 dispatches work; it never holds funds or private keys.
206
+
207
+ ## What callx402 is not
208
+
209
+ - Not the flagship product name. The product is **Veyline**.
210
+ - Not a broker, negotiator, or custodian. It dispatches; it never holds funds.
211
+ - The phrases above are usage language, not exclusivity claims.
212
+
213
+ ## Links
214
+
215
+ - Canonical docs: https://payloadhq.github.io/
216
+ - Payload org profile: https://github.com/Payloadhq/Payloadhq
217
+ - RevRule by Payload (separate product): https://github.com/Payloadhq/revrule-console
218
+
219
+ Full subsystem reference: `docs/README.md`. Behavioral language: `docs/ACTION_LANGUAGE.md`.
220
+ Design spec: `SPEC.md`.
221
+
222
+ ## License
223
+
224
+ MIT. See `LICENSE`.
225
+
226
+ ---
227
+
228
+ **More from Payload** · [payloadhq.github.io](https://payloadhq.github.io/) · [all Payload repos](https://github.com/Payloadhq)
229
+
230
+ Related: [x402-manifest-check](https://github.com/Payloadhq/x402-manifest-check) · [x402-observatory](https://github.com/Payloadhq/x402-observatory) · [flow-agentic-demo](https://github.com/Payloadhq/flow-agentic-demo)
package/SPEC.md ADDED
@@ -0,0 +1,264 @@
1
+ # callx402 — Universal Action Layer — Build Spec
2
+
3
+ **FUNDAMENTAL RULE: callx402 is the ACTION, not the product name.**
4
+ The flagship keeps a separate unique brand (forthcoming). Do NOT rename Sentinel,
5
+ Rescue, Doctor, Router, Valuator, SpendGuard, Settlement Resolver, MCP fabric,
6
+ RevRule, the Payload brand, or any marketplace listing. callx402 is an
7
+ access/dispatch layer that CALLS existing subsystems. Architecture:
8
+
9
+ ```
10
+ UNIQUE PRODUCT BRAND → accessed through → callx402
11
+ ```
12
+
13
+ ## 1. Non-negotiables
14
+
15
+ - **NEVER modify** `~/workspace/products/x402-paid-api-starter-kit/v2.0.0/`. Import from it
16
+ via relative require. Verify at the end with `git` status or a checksum spot-check
17
+ that the tree is untouched (it is not a git repo necessarily; at minimum do not
18
+ write any file under it).
19
+ - **Real working code only.** No placeholders, no stubs presented as functional.
20
+ If a subsystem is feature-flag disabled or needs live infra that isn't reachable,
21
+ the command must say so clearly and exit non-zero. Never fake success.
22
+ - **No logic duplication.** Every command dispatches into the existing subsystem.
23
+ - **Do NOT publish** to npm, PyPI, or Docker Hub. Packages must be publish-*ready*
24
+ only. (npm `payloadtools` account suspended until 2026-10-07 12:14 CDT;
25
+ PyPI blocked on owner's account + 2FA.)
26
+ - **Do NOT** create an MCP tool named exactly `call_x402` (collides with an existing
27
+ live tool on the fiatdock marketplace). MCP identity stays a DEFERRED decision doc.
28
+ - Behavioral language only ("Need to diagnose x402? callx402."). Never claim
29
+ exclusive trademark ownership of the phrase.
30
+ - Stdlib only for the core/CLI/HTTP server. No new external dependencies.
31
+ (Python SDK: stdlib only — `subprocess`, `json`, `argparse`, `shutil`.)
32
+ - Node >= 18 (runtime here is v24.20.0). Python >= 3.9 (runtime 3.12.3).
33
+
34
+ ## 2. Directory layout (all under ~/workspace/products/callx402/)
35
+
36
+ ```
37
+ SPEC.md
38
+ package.json # name: callx402, version 0.1.0, MIT, bin {callx402: ./bin/callx402.js},
39
+ # main ./sdk/js/index.js, homepage + repository
40
+ # https://github.com/Payloadhq/callx402
41
+ bin/callx402.js # CLI entry (shebang, stdlib only, requires ../core)
42
+ core/
43
+ index.js # runAction(name, args, opts), runIntent(text, opts), getStatus()
44
+ subsystems.js # lazy require map of v2.0.0 modules + enabled() checks
45
+ config.js # config file (~/.config/callx402/config.json, $CALLX402_CONFIG),
46
+ # env overrides (CALLX402_*), safe defaults
47
+ envelope.js # result envelope builders + exit codes
48
+ pipeline.js # intent pipeline stage orchestration
49
+ sdk/js/
50
+ index.js # callx402({...}) -> Promise<result envelope>
51
+ sdk/python/
52
+ pyproject.toml # name callx402, version 0.1.0, console_scripts callx402,
53
+ # bundles ../bin + ../core as package data, invokes via node
54
+ callx402/__init__.py # callx402(...) -> dict (subprocess to bundled CLI --json)
55
+ callx402/cli.py # argparse main() -> same path
56
+ server/
57
+ index.js # node:http server: GET /health, GET /openapi.json,
58
+ # POST /call /rescue /route /resolve /diagnose
59
+ openapi.yaml
60
+ docs/
61
+ README.md # callx402 is the action; flagship brand separate/forthcoming
62
+ ACTION_LANGUAGE.md # behavioral phrases
63
+ MCP_IDENTITY.md # DEFERRED decision doc
64
+ test/ # (test agent) node --test suite
65
+ ```
66
+
67
+ ## 3. Subsystem module map (v2.0.0 root = ../../x402-paid-api-starter-kit/v2.0.0)
68
+
69
+ Default v2Root: `path.resolve(__dirname, '../../x402-paid-api-starter-kit/v2.0.0')`.
70
+ Overridable via `CALLX402_V2_ROOT` env or config `v2Root`. All requires lazy (inside
71
+ functions) so `status` can report per-module reachability.
72
+
73
+ | Subsystem | Require path (from v2Root) | Key exports |
74
+ |--------------------|----------------------------------|-------------|
75
+ | Sentinel | `lib/sentinel/index.js` | `createSentinel(opts)`, `createInertSentinel()`, `INCIDENT_TYPES`, `FLAG` (`PAYLOAD_SENTINEL`?), `enabled()` |
76
+ | Rescue | `lib/rescue/index.js` | `createRescue({...})`, `incidents`, `detector`, `actions`, `autorescue`, `receipts`, `pricing`, `RESCUE_VERSION`, `FLAG='PAYLOAD_RESCUE'`, `enabled()` |
77
+ | Doctor | `lib/mcp/doctor.js` | `runMcpDoctor(evidence)`, `classifyMcpFailure`, `STAGES`, `FLAG='PAYLOAD_MCP_DOCTOR'`, `enabled()` |
78
+ | Router | `lib/mcp/smart-router.js` | `selectTool`, `rankTools`, `normalizeCandidate`, `totalCost`, `POLICIES`, `DEFAULTS`, `enabled()` |
79
+ | Router (paths) | `lib/mcp/route-decider.js` | `choosePath`, `selectPath`, `expectedCost`, `enabled()` |
80
+ | Valuator | `valuator/quote.js` | inspect before use |
81
+ | SpendGuard | `lib/mcp/spendguard.js` | `createTaskSpendGuard({...})`, `DEFAULT_PHASES`, `enabled()` |
82
+ | Settlement Resolver| `lib/settlement-resolver.js` | `resolve(evidence)`, `STATES`, `POLICY_MATRIX`, `createMockChain`, `createMockFacilitator`, `FLAG='PAYLOAD_SETTLEMENT_RESOLVER'`, `enabled()` |
83
+ | Intent Engine | `lib/mcp/intent-engine.js` | `parse(text)` / `parseIntent`, `createEngine`, `GOALS`, `enabled()` |
84
+ | Capability Graph | `lib/mcp/capability-graph.js` | `createGraph()` → `{upsertTool, getToolProfile, findTools, recordObservation, stats, save, load}`, `enabled()` |
85
+ | Economic Planner | `lib/mcp/economic-planner.js` | `planGoal(opts)`, `scorePlan`, `OBJECTIVES`, `DEFAULTS`, `enabled()` |
86
+ | MCP fabric | `lib/mcp/index.js` | `transactional, saga, spendguard, resultRecovery, effectProof, executionKernel, ...` |
87
+ | RevRule | `lib/revrule-events.js` | `createEmitter({sink, idempotencyRegistry})`, `buildEvent`, `createMemorySink`, `enabled()` |
88
+ | Preflight | `lib/mcp/preflight.js` | `runMcpPreflight`, `buildChecks`, `enabled()` |
89
+ | Effect Proof | `lib/mcp/effect-proof.js` | `issueEffectProof`, `verifyEffectProof`, `enabled()` |
90
+ | Execution Kernel | `lib/mcp/execution-kernel.js` | `createKernel`, `STATES`, `TERMINAL`, `enabled()` |
91
+ | Result Recovery | `lib/mcp/result-recovery.js` | `createRecoveryStore`, `createResultRecoveryCache`, `buildOperationIdentity`, `enabled()` |
92
+
93
+ **Flag rule:** every module exposes `enabled()` (checks `process.env[FLAG]==='1'`)
94
+ and `FLAG`. Before dispatch, call `enabled()`. If false, return
95
+ `subsystemStatus: 'disabled'` naming the flag — do NOT fake success.
96
+ (You may document that the user can export the flag; do not silently force-enable
97
+ anything that guards real money movement. Read-only/diagnostic modules may note
98
+ the flag to enable.)
99
+
100
+ **Status honesty:** `getStatus()` must report per subsystem: `reachable` (require
101
+ succeeded), `enabled` (flag on), `version` where available, and `note` for
102
+ prototype/stub status (e.g. rescue-service `_rescue-stub.js` exists — inspect and
103
+ report honestly; never present a stub as production).
104
+
105
+ ## 4. Result envelope (JSON everywhere: CLI --json, SDKs, HTTP)
106
+
107
+ ```json
108
+ {
109
+ "ok": true,
110
+ "action": "diagnose",
111
+ "disposition": "human-readable outcome",
112
+ "subsystem": "doctor",
113
+ "subsystemStatus": "ok | disabled | unreachable | prototype",
114
+ "data": {},
115
+ "settlement": "DEFINITELY_PAID | DEFINITELY_NOT_PAID | AUTHORIZED_NOT_SETTLED | PENDING | CONFLICT | UNKNOWN | null",
116
+ "txHash": "0x... | null",
117
+ "receipt": {},
118
+ "idempotencyKey": "string | null",
119
+ "deduped": false,
120
+ "error": { "code": "string", "message": "string" }
121
+ }
122
+ ```
123
+
124
+ `error` is null on success. `ok:false` whenever `error` is set.
125
+
126
+ **Exit codes (CLI):** 0 ok · 1 generic failure · 2 usage/validation error ·
127
+ 3 subsystem disabled or unreachable · 4 budget refused (SpendGuard) ·
128
+ 5 settlement UNKNOWN (must never auto-retry/repay — surface and stop).
129
+
130
+ **Money-safety invariants (hard):**
131
+ - Settlement `UNKNOWN` → never auto-retry, never repay. Return exit 5 with
132
+ instructions for manual resolution.
133
+ - An explicit `--force-retry`/`retry` flag on execute MUST be rejected when the
134
+ prior settlement state is UNKNOWN (unsafe retry refusal).
135
+ - Over-budget intent → SpendGuard refusal, exit 4, zero execution side effects.
136
+ - Duplicate `idempotencyKey` → return the ORIGINAL stored result with
137
+ `deduped:true`; do not re-execute. Use result-recovery store.
138
+
139
+ ## 5. Config (`core/config.js`)
140
+
141
+ - File: `~/.config/callx402/config.json`, overridable by `$CALLX402_CONFIG`.
142
+ - Env overrides: `CALLX402_V2_ROOT`, `CALLX402_MODE` (local|remote),
143
+ `CALLX402_REMOTE_URL`, `CALLX402_AUTH_TOKEN`, `CALLX402_DEFAULT_NETWORK`,
144
+ `CALLX402_DEFAULT_ASSET`, `CALLX402_DEFAULT_BUDGET_USD`, `CALLX402_APPROVAL_THRESHOLD_USD`.
145
+ - `config get|set|list` via CLI (`callx402 config list`, `callx402 config set key value`).
146
+ - Safe defaults: mode local, no auto-spend, budget default 1.00 USD, approval
147
+ threshold default 5.00 USD (above → require explicit `--approve` or fail closed).
148
+ - Remote mode: CLI/SDK dispatch via HTTP to a callx402 server (auth header when
149
+ `CALLX402_AUTH_TOKEN` set). Unreachable remote → clear error, non-zero exit.
150
+
151
+ ## 6. Intent pipeline (`core/pipeline.js`)
152
+
153
+ `runIntent(text, opts)` stages (each honest about availability):
154
+ 1. **Intent Engine** `parse(text)` → structured intent (extract budget like
155
+ "under $1" → maxBudget).
156
+ 2. **Capability Graph** `findTools` → candidate tools.
157
+ 3. **Economic Planner** `planGoal` → costed plan.
158
+ 4. **SpendGuard** `createTaskSpendGuard` → budget check vs `maxBudget`
159
+ (opts override; default from config). Over → refuse (exit 4).
160
+ 5. **Router** `selectTool`/`choosePath` → route.
161
+ 6. **x402/MCP execution** via execution kernel — ONLY if a live executable route
162
+ exists; otherwise return `disposition: 'no executable route available'`
163
+ with `subsystemStatus` honest, no fake execution.
164
+ 7. **Effect Proof** `issueEffectProof`/`verifyEffectProof`.
165
+ 8. **Settlement** `resolve` → settlement state recorded; UNKNOWN → exit 5 path.
166
+ 9. **Delivery + Reconciliation** → receipt.
167
+ 10. **RevRule** `createEmitter` → emit economic event (idempotent).
168
+
169
+ Options: `maxBudget, deadline, speed ('fast'|'balanced'|'cheap'), risk
170
+ ('low'|'medium'|'high'), networks[], assets[], providers[], approvalThreshold,
171
+ idempotencyKey, timeoutMs, dryRun`.
172
+
173
+ `runAction(name, args, {deps}={})` — `deps` is an internal/test seam allowing
174
+ subsystem handle overrides. Document as internal.
175
+
176
+ ## 7. CLI contract (`bin/callx402.js`)
177
+
178
+ ```
179
+ callx402 <command> [args] [options]
180
+ callx402 "natural language intent" # intent mode
181
+ callx402 --help | -h
182
+ callx402 --version | -v
183
+ callx402 status [--json]
184
+ callx402 diagnose [--target ...] [--json]
185
+ callx402 rescue --incident <id> [--json] # auth-gated; without auth -> clear error
186
+ callx402 route --goal <text> [--json]
187
+ callx402 resolve --evidence <json|@file> [--json]
188
+ callx402 doctor [--json]
189
+ callx402 execute --intent <text> [--max-budget 1.00] [--dry-run] [--idempotency-key K]
190
+ callx402 monitor [--once|--watch] [--json]
191
+ callx402 preflight [--json]
192
+ callx402 inspect [--query <text>] [--json]
193
+ callx402 config list | get <k> | set <k> <v>
194
+ ```
195
+ - Global: `--json` (envelope on stdout), `--timeout <ms>`.
196
+ - Unknown command → usage error, exit 2, list valid commands.
197
+ - Malformed input (bad JSON, bad flags) → exit 2 with clear message.
198
+ - Default (no --json): concise human-readable summary + key fields.
199
+
200
+ ## 8. JS SDK (`sdk/js/index.js`)
201
+
202
+ ```js
203
+ const { callx402 } = require('callx402'); // or require('./sdk/js')
204
+ const result = await callx402({
205
+ intent: 'complete this job for under $1',
206
+ maxBudget: 1.00, deadline: '2026-10-07T00:00:00Z',
207
+ speed: 'balanced', risk: 'low',
208
+ networks: ['base'], assets: ['USDC'], providers: [],
209
+ approvalThreshold: 5.00, idempotencyKey: '...', timeoutMs: 30000, dryRun: false,
210
+ });
211
+ // result: envelope (see §4). Also export: callx402.version, callx402.status(), sub-actions
212
+ // callx402.diagnose(), .rescue(), .route(), .resolve(), .doctor(), .execute(), .monitor(), .preflight(), .inspect()
213
+ ```
214
+ Requires `../..` core directly (same process). No duplication.
215
+
216
+ ## 9. Python SDK (`sdk/python/`)
217
+
218
+ - `pyproject.toml`: name `callx402`, version `0.1.0`, `console_scripts: callx402 =
219
+ callx402.cli:main`. Bundles `../../bin` + `../../core` as package data;
220
+ at runtime finds `node` via `shutil.which('node')` and invokes the bundled
221
+ `bin/callx402.js --json`. If node missing → clear RuntimeError.
222
+ - `callx402/__init__.py`: `def callx402(intent=None, max_budget=None, deadline=None,
223
+ speed=None, risk=None, networks=None, assets=None, providers=None,
224
+ approval_threshold=None, idempotency_key=None, timeout_ms=None, dry_run=False,
225
+ action=None, **kwargs) -> dict`. Maps kwargs → CLI argv, parses stdout JSON.
226
+ Internal helper module may be named `call_x402.py` ONLY if needed for
227
+ snake_case conventions; the PUBLIC import stays `callx402`.
228
+ - `callx402/cli.py`: `main()` with argparse mirroring the node CLI surface
229
+ (subset: command + common options + --json passthrough).
230
+
231
+ ## 10. HTTP server (`server/index.js`, node:http only)
232
+
233
+ - `GET /health` → `{ok, version, subsystems: {...}}` (reuse getStatus).
234
+ - `GET /openapi.json` → serves openapi.yaml as JSON (convert or embed).
235
+ - `POST /call` → `{intent, maxBudget, deadline, speed, risk, networks, assets, providers, approvalThreshold, idempotencyKey, dryRun}` → runIntent.
236
+ - `POST /rescue` → `{incidentId, ...}` → rescue dispatch.
237
+ - `POST /route` → `{goal, ...}` → router dispatch.
238
+ - `POST /resolve` → `{evidence}` → settlement resolve.
239
+ - `POST /diagnose` → `{target/evidence}` → doctor dispatch.
240
+ - Auth: if `CALLX402_AUTH_TOKEN` set, require `Authorization: Bearer` — else 401.
241
+ - `openapi.yaml`: document all routes + envelope schema.
242
+
243
+ ## 11. Docs
244
+
245
+ - `docs/README.md`: what callx402 is (the action), what it is not (not the product
246
+ name), architecture diagram (brand → callx402 → subsystems), quickstart
247
+ (install from GitHub, `callx402 status`, `callx402 "…"`, SDK snippets),
248
+ money-safety rules, link to v2.0.0 subsystem docs.
249
+ - `docs/ACTION_LANGUAGE.md`: the five behavioral phrases, framed as usage
250
+ language, explicitly NOT trademark claims.
251
+ - `docs/MCP_IDENTITY.md`: DEFERRED. Proposed pattern: server name tied to future
252
+ flagship brand; tool `[future_brand]_call`; description "Call x402
253
+ infrastructure for routing, rescue, diagnosis, settlement resolution and
254
+ execution." Rationale for avoiding bare `call_x402` (live collision on
255
+ fiatdock). Mark clearly: DO NOT FINALIZE until flagship brand chosen.
256
+
257
+ ## 12. Definition of done (per builder)
258
+
259
+ - `node bin/callx402.js --help`, `--version`, `status` all work for real.
260
+ - Every command dispatches to the real subsystem or reports honestly why not.
261
+ - `npm install` works offline (zero deps). `npm link` exposes `callx402`.
262
+ - Python: `pip install -e ./sdk/python` works; `python -c "import callx402"`.
263
+ - No file written under v2.0.0. No publish attempted.
264
+ - Smoke-test every command you build and report the literal outputs.