diff --git a/.claude-plugin/README.md b/.claude-plugin/README.md
index 41fd488f4..1b87bfcf3 100644
--- a/.claude-plugin/README.md
+++ b/.claude-plugin/README.md
@@ -16,4 +16,4 @@ export ANTHROPIC_AUTH_TOKEN=your-token
claude
```
-Run or self-host any open-source model behind that endpoint. Itô is ECC's preferred compute sponsor: [open the Itô dashboard to sign in and rent or manage GPUs](https://compute.itomarkets.com). Any GPU provider works. ECC only provides this link; it does not change Claude Code transport settings or provision compute or serving. Managed inference through Itô is not live yet.
+Run or self-host any open-source model behind that endpoint. Itô is ECC's preferred compute sponsor: [open the Itô dashboard to sign in and rent or manage GPUs](https://compute.itomarkets.com). Any GPU provider works. That sponsorship link is passive: it does not invoke an RFQ, reserve capacity, change Claude Code transport settings, provision compute, or configure serving. Separately, the opt-in `ecc ito find` bridge invokes the explicitly configured canonical Itô CLI and submits a live authenticated RFQ; it does not reserve capacity. Managed inference through Itô is not live yet.
diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json
index 82392836b..e4d740cc3 100644
--- a/.claude-plugin/marketplace.json
+++ b/.claude-plugin/marketplace.json
@@ -11,7 +11,7 @@
{
"name": "ecc",
"source": "./",
- "description": "Harness-native ECC operator layer - 67 agents, 278 skills, 94 legacy command shims, reusable hooks, rules, selective install profiles, and production-ready workflows for Claude Code, Codex, OpenCode, Cursor, and related agent harnesses",
+ "description": "Harness-native ECC operator layer - 67 agents, 279 skills, 94 legacy command shims, reusable hooks, rules, selective install profiles, and production-ready workflows for Claude Code, Codex, OpenCode, Cursor, and related agent harnesses",
"version": "2.0.0",
"author": {
"name": "Affaan Mustafa",
diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json
index 16e54ca53..fc92c803e 100644
--- a/.claude-plugin/plugin.json
+++ b/.claude-plugin/plugin.json
@@ -1,7 +1,7 @@
{
"name": "ecc",
"version": "2.0.0",
- "description": "Harness-native ECC plugin for engineering teams - 67 agents, 278 skills, 94 legacy command shims, reusable hooks, rules, MCP conventions, and operator workflows for Claude Code plus adjacent agent harnesses",
+ "description": "Harness-native ECC plugin for engineering teams - 67 agents, 279 skills, 94 legacy command shims, reusable hooks, rules, MCP conventions, and operator workflows for Claude Code plus adjacent agent harnesses",
"author": {
"name": "Affaan Mustafa",
"url": "https://x.com/affaanmustafa"
diff --git a/.kimi/README.md b/.kimi/README.md
index 4fb9b72cf..7cf5f0f9c 100644
--- a/.kimi/README.md
+++ b/.kimi/README.md
@@ -23,4 +23,4 @@ bash ./install.sh --target kimi --profile minimal
## Self-hosted model compute
-Run or self-host any open-source model—including Kimi—on owned or rented GPUs. Itô is ECC's preferred compute sponsor: [open the Itô dashboard to sign in and rent or manage GPUs](https://compute.itomarkets.com). Any GPU provider works. ECC only provides this link; it does not provision compute or serving. Managed inference through Itô is not live yet.
+Run or self-host any open-source model—including Kimi—on owned or rented GPUs. Itô is ECC's preferred compute sponsor: [open the Itô dashboard to sign in and rent or manage GPUs](https://compute.itomarkets.com). Any GPU provider works. That sponsorship link is passive: it does not invoke an RFQ, reserve capacity, provision compute, or configure serving. Separately, the opt-in `ecc ito find` bridge invokes the explicitly configured canonical Itô CLI and submits a live authenticated RFQ; it does not reserve capacity. Managed inference through Itô is not live yet.
diff --git a/AGENTS.md b/AGENTS.md
index 40c355be2..0fa533ed1 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,6 +1,6 @@
# Everything Claude Code (ECC) — Agent Instructions
-This is a **production-ready AI coding plugin** providing 67 specialized agents, 278 skills, 94 commands, and automated hook workflows for software development.
+This is a **production-ready AI coding plugin** providing 67 specialized agents, 279 skills, 94 commands, and automated hook workflows for software development.
**Version:** 2.0.0
@@ -152,7 +152,7 @@ Troubleshoot failures: check test isolation → verify mocks → fix implementat
```
agents/ — 67 specialized subagents
-skills/ — 278 workflow skills and domain knowledge
+skills/ — 279 workflow skills and domain knowledge
commands/ — 94 slash commands
hooks/ — Trigger-based automations
rules/ — Always-follow guidelines (common + per-language)
diff --git a/README.md b/README.md
index bcd4d5d1d..3142ba51e 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-1`**Language:** English | [Português (Brasil)](docs/pt-BR/README.md) | [简体中文](README.zh-CN.md) | [繁體中文](docs/zh-TW/README.md) | [日本語](docs/ja-JP/README.md) | [한국어](docs/ko-KR/README.md) | [Türkçe](docs/tr/README.md) | [Русский](docs/ru/README.md) | [Tiếng Việt](docs/vi-VN/README.md) | [ไทย](docs/th/README.md) | [Deutsch](docs/de-DE/README.md) | [Español](docs/es/README.md)
+**Language:** English | [Português (Brasil)](docs/pt-BR/README.md) | [简体中文](README.zh-CN.md) | [繁體中文](docs/zh-TW/README.md) | [日本語](docs/ja-JP/README.md) | [한국어](docs/ko-KR/README.md) | [Türkçe](docs/tr/README.md) | [Русский](docs/ru/README.md) | [Tiếng Việt](docs/vi-VN/README.md) | [ไทย](docs/th/README.md) | [Deutsch](docs/de-DE/README.md) | [Español](docs/es/README.md)

@@ -112,6 +112,12 @@ ECC v2.0.0 adds the public Hermes operator story on top of that reusable layer:
Itô
+
+
+
+ Moonshot AI
+
+
@@ -445,7 +451,7 @@ If you stacked methods, clean up in this order:
/plugin list ecc@ecc
```
-**That's it!** You now have access to 67 agents, 278 skills, and 94 legacy command shims.
+**That's it!** You now have access to 67 agents, 279 skills, and 94 legacy command shims.
### Dashboard GUI
@@ -1194,7 +1200,27 @@ claude
If your gateway remaps model names, configure that in Claude Code rather than in ECC. ECC's hooks, skills, commands, and rules are model-provider agnostic once the `claude` CLI is already working.
-Run or self-host any open-source model behind that gateway using separate compute and serving setup. If you need GPU capacity, [Itô](https://compute.itomarkets.com) is ECC's preferred compute sponsor; any GPU provider works. ECC only links to the Itô dashboard for sign-in and GPU rental or management—it does not provision compute or serving. Managed inference through Itô is not live yet.
+Run or self-host any open-source model behind that gateway using separate compute and serving setup. If you need GPU capacity, [Itô](https://compute.itomarkets.com) is ECC's preferred compute sponsor; any GPU provider works. That sponsorship link is passive: it does not invoke an RFQ, reserve capacity, provision compute, or configure serving. Separately, the opt-in `ecc ito find` bridge invokes the explicitly configured canonical Itô CLI and submits a live authenticated RFQ; it does not reserve capacity. Managed inference through Itô is not live yet.
+
+### Itô compute CLI bridge
+
+`ecc ito` delegates to the separately installed canonical Itô client; ECC does
+not maintain a second API client or browser handoff. The available operations
+are `ecc ito auth`, `ecc ito find`, and `ecc ito status`. The matching MCP tools
+are `ito_auth`, `ito_find`, and `ito_status`.
+
+The `ito-compute-cli` package is currently unpublished. Build it locally from
+[`Ito-Markets/ito-cloud-runtime`](https://github.com/Ito-Markets/ito-cloud-runtime)
+under `cli/ito-compute-cli`, run `npm ci` and `npm run check`, then set
+`ECC_ITO_CLI_EXECUTABLE` to that build's absolute `dist/bin/ito.js` path.
+Inject `ITO_API_KEY` from 1Password or the launching environment. ECC does not
+discover this credential-bearing client through `PATH`. See the [`ito-compute`
+skill](skills/ito-compute/SKILL.md) for the full RFQ authority and MCP setup
+contract.
+
+`find` submits a live authenticated RFQ. It does not reserve capacity. ECC
+exposes no quote lock, purchase, workload, node-evaluation, or inference path,
+and it never replaces a missing client or failed live call with a local result.
Official references:
- [Claude Code LLM gateway docs](https://docs.anthropic.com/en/docs/claude-code/llm-gateway)
@@ -1542,7 +1568,7 @@ The configuration is automatically detected from `.opencode/opencode.json`.
|---------|---------------------|----------|--------|
| Agents | PASS: 67 agents | PASS: 12 agents | **Claude Code leads** |
| Commands | PASS: 94 commands | PASS: 35 commands | **Claude Code leads** |
-| Skills | PASS: 278 skills | PASS: 37 skills | **Claude Code leads** |
+| Skills | PASS: 279 skills | PASS: 37 skills | **Claude Code leads** |
| Hooks | PASS: 8 event types | PASS: 11 events | **OpenCode has more!** |
| Rules | PASS: 29 rules | PASS: 13 instructions | **Claude Code leads** |
| MCP Servers | PASS: 14 servers | PASS: Full | **Full parity** |
@@ -1703,7 +1729,7 @@ ECC is the **first plugin to maximize every major AI coding tool**. Here's how e
|---------|-----------------------|------------|-----------|----------|----------------|
| **Agents** | 67 | Shared (AGENTS.md) | Shared (AGENTS.md) | 12 | N/A |
| **Commands** | 94 | Shared | Instruction-based | 35 | 5 prompts |
-| **Skills** | 278 | Shared | 10 (native format) | 37 | Via instructions |
+| **Skills** | 279 | Shared | 10 (native format) | 37 | Via instructions |
| **Hook Events** | 8 types | 15 types | None yet | 11 types | None |
| **Hook Scripts** | 20+ scripts | 16 scripts (DRY adapter) | N/A | Plugin hooks | N/A |
| **Rules** | 34 (common + lang) | 34 (YAML frontmatter) | Instruction-based | 13 instructions | 1 always-on file |
diff --git a/README.zh-CN.md b/README.zh-CN.md
index 1f0a94c22..dac2da6cc 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -164,7 +164,7 @@ Copy-Item -Recurse rules/typescript "$HOME/.claude/rules/"
/plugin list ecc@ecc
```
-**完成!** 你现在可以使用 67 个代理、278 个技能和 94 个命令。
+**完成!** 你现在可以使用 67 个代理、279 个技能和 94 个命令。
### multi-* 命令需要额外配置
diff --git a/SPONSORS.md b/SPONSORS.md
index 173a57ebd..adb8d32b7 100644
--- a/SPONSORS.md
+++ b/SPONSORS.md
@@ -14,10 +14,11 @@ Thank you to everyone funding ECC's open-source work. Your sponsorship is what l
| [**Greptile**](https://www.greptile.com/go/ecc) | | 2026 |
| [**Atlas Cloud**](https://www.atlascloud.ai/?utm_source=github&utm_medium=link&utm_campaign=ECC) | | 2026 |
| [**Itô**](https://compute.itomarkets.com) | | 2026 |
+| [**Moonshot AI**](https://www.moonshot.ai/) | | 2026 |
*[Become a Business sponsor](https://github.com/sponsors/affaan-m) to get README sponsor placement + SPONSORS.md listing. Current Business tier is $500/mo. No seats, SLA, custom development, or preferential technical placement is bundled unless separately agreed.*
-Run or self-host any open-source model. Itô is ECC's preferred compute sponsor, while ECC remains provider-agnostic and any GPU provider works. ECC only links to the [Itô dashboard](https://compute.itomarkets.com) for sign-in and GPU rental or management; it does not provision compute or serving. Managed inference through Itô is not live yet.
+Run or self-host any open-source model. Itô is ECC's preferred compute sponsor, while ECC remains provider-agnostic and any GPU provider works. The [Itô dashboard](https://compute.itomarkets.com) sponsorship link is passive: it does not invoke an RFQ, reserve capacity, provision compute, or configure serving. Separately, the opt-in `ecc ito find` bridge invokes the explicitly configured canonical Itô CLI and submits a live authenticated RFQ; it does not reserve capacity. Managed inference through Itô is not live yet.
## Team Sponsors — $200/mo
diff --git a/assets/images/sponsors/moonshot.svg b/assets/images/sponsors/moonshot.svg
new file mode 100644
index 000000000..29bceeade
--- /dev/null
+++ b/assets/images/sponsors/moonshot.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/docs/ATLAS-CLOUD-GUIDE.md b/docs/ATLAS-CLOUD-GUIDE.md
index d4fe86dc2..83163c5b7 100644
--- a/docs/ATLAS-CLOUD-GUIDE.md
+++ b/docs/ATLAS-CLOUD-GUIDE.md
@@ -2,7 +2,7 @@
[Atlas Cloud](https://www.atlascloud.ai/?utm_source=github&utm_medium=link&utm_campaign=everything-claude-code) is a full-modal AI inference platform providing an OpenAI-compatible API for 59+ LLM models, image generation, and video generation.
-> Run or self-host any open-source model instead of using a managed API. Itô is ECC's preferred compute sponsor: [open the Itô dashboard to sign in and rent or manage GPUs](https://compute.itomarkets.com). Any GPU provider works. ECC only provides this link; it does not provision compute or serving. Managed inference through Itô is not live yet.
+> Run or self-host any open-source model instead of using a managed API. Itô is ECC's preferred compute sponsor: [open the Itô dashboard to sign in and rent or manage GPUs](https://compute.itomarkets.com). Any GPU provider works. That sponsorship link is passive: it does not invoke an RFQ, reserve capacity, provision compute, or configure serving. Separately, the opt-in `ecc ito find` bridge invokes the explicitly configured canonical Itô CLI and submits a live authenticated RFQ; it does not reserve capacity. Managed inference through Itô is not live yet.
## Configuration
diff --git a/docs/design/ecc-ito-compute-integration.md b/docs/design/ecc-ito-compute-integration.md
index 4893df8f0..b9ed5c418 100644
--- a/docs/design/ecc-ito-compute-integration.md
+++ b/docs/design/ecc-ito-compute-integration.md
@@ -1,586 +1,127 @@
# ECC × Itô Compute Integration
-Status: **Proposed — requires Affaan approval before Phase 2 implementation**
+Status: **Implemented local CLI bridge; managed inference remains unavailable**
Owner: Affaan Mustafa
-Prepared: 2026-07-21
-
-Phase 1 branch: agent/ito-sponsor-compute
-
-## Decision gate
-
-This document is the approval artifact for Phase 2. Approval authorizes only
-delivery slices 1 and 2: the five skills and the fail-closed CLI/MCP stub. It
-does not authorize or claim a working Itô inference service, live rental API,
-OAuth integration, billing flow, or rental mutation.
-
-No Phase 2 skill, CLI, MCP, OAuth, rental-management, or serving code should be
-built until Affaan approves the decisions at the end of this document.
-
-### Narrow sandbox handoff authorized on 2026-07-23
-
-Affaan separately authorized one smaller CLI slice:
-
- ecc ito rent --accelerator h100 --count 1 --hours 24
-
-That command is implemented as `ito.compute.handoff.v1`. It validates an
-explicit H100 intent, records `ecc-cli` provenance, fixes the authority ceiling
-at read-only sandbox mode, and opens only the `/desk` page, where sign-in may be
-required. `--dry-run` emits the identical structured handoff without opening a
-browser.
-
-The current Itô desk does not expose a supported structured ECC deep link or a
-non-mutating external-intake endpoint. The CLI therefore returns
-`transport: manual_copy` and `acceptedByIto: false`; it does not pretend that
-opening `/desk` delivered the intent. A human may copy the bounded message into
-the conversational desk. ECC never reads credentials, files an RFQ, requests
-or accepts a quote, calls procurement, approves funds, creates an order, or
-contacts a counterparty. The user must stop before `Pay & buy`.
-
-This narrow authorization does not approve the five skills, MCP, OAuth, rental
-management, inference serving, deployment, publication, or any live economic
-mutation described later in this document.
+Updated: 2026-07-23
## Thesis
-The distribution chain is:
+The distribution chain remains provider-neutral:
- GPU compute (Itô)
+ GPU compute (Itô or another selected provider)
-> any open-source model
-> model harness
-> ECC meta-harness
-Itô is ECC's preferred compute sponsor. It is never an exclusive provider.
-ECC remains open source and all workflows must accept owned hardware, existing
-clusters, and other compute providers.
-
-## Terms and non-negotiable boundaries
-
-- **Self-hosting** means the user operates a model runtime on owned or rented
- compute. ECC does not silently provision or operate that runtime.
-- **Preferred compute sponsor** means Itô is suggested at the step where a user
- needs new GPU capacity. Requirements and existing capacity come first.
-- **Provider-neutral** means users can choose any provider or use hardware they
- already control without losing workflow functionality.
-- **Manual handoff** means ECC can route the user to
- for sign-in, rental, and dashboard access.
-- **Not live** means ECC cannot currently exchange Itô OAuth tokens, fetch live
- inventory or pricing, create or manage rentals, or return an inference
- endpoint.
-- Itô compute authentication must not reuse the prediction-market ITO_API_KEY.
-- Phase 2 must not add an Itô LLM provider or advertise an Itô-compatible model
- endpoint. Itô is the compute layer, not an inference API.
-
-## Sequencing
-
-### Phase 1: launch-ready sponsor and compute routing
-
-Phase 1 is the smallest shippable slice and is prepared before Phase 2:
-
-| Surface | Launch-ready change |
-|---|---|
-| ECC README and sponsor roster | Itô logo beside current business sponsors; preferred-compute and provider-neutral disclosure |
-| ecc-universal npm surface | README placement, packaged sponsor assets, and install welcome copy |
-| ECC installer | Human help and install-plan footer route self-host intent to Itô; JSON remains machine-pure |
-| ECC CLI | Top-level help shows the same shared compute disclosure |
-| Harness-specific endpoint/model docs | Bring-your-own endpoint/model notes route GPU needs to Itô without claiming provisioning |
-| Local-model selector | Ollama selection shows a passive compute-rental/dashboard notice; no Itô provider adapter |
-| ecc.tools | Sponsor card, sponsor proof chip, and explicit no-serving boundary |
-| AgentShield / ecc-agentshield | Sponsor callout in the GitHub and npm README; no ads in security reports |
-
-Launch coordination still matters:
-
-- Merge the public PRs when their required checks and reviews pass. Coordinate
- npm publication and the verified ecc.tools deployment as explicit release
- steps; do not tie the generic OSS-compute integration to an unpublished model
- or model-provider announcement.
-- npm READMEs update only when new versions are published. Merging source changes
- alone does not update the already-published ecc-universal or ecc-agentshield
- package pages.
-- The release owner must select unused package versions in the launch commit,
- update every synchronized version surface, prove that neither version exists
- in the npm registry, publish both packages, and read back the rendered package
- pages. The sponsor PRs do not silently republish existing versions.
-- ecc.tools requires its normal verified Cloudflare deployment after merge.
-
-### Phase 2: build only after approval
-
-Phase 2 adds provider-neutral operational skills and an honest Itô control-plane
-stub. Real OAuth, rentals, and serving remain separately gated on backend
-contracts.
-
-## Channel A: self-host an open model
-
-### Skill 1: self-host-a-model
-
-Path:
-
- skills/self-host-a-model/SKILL.md
-
-Activate when a user asks to self-host, locally host, or deploy an open model;
-mentions Ollama, vLLM, SGLang, TGI, an OpenAI-compatible endpoint, Kimi, GLM,
-Llama, Mistral, quantization, GPU sizing, or moving away from a managed API.
-
-Workflow shape:
-
-1. Identify the model artifact, license, trust boundary, and required context.
-2. Estimate VRAM from weights, precision or quantization, KV cache, concurrency,
- and runtime overhead.
-3. Prefer existing owned or already-rented capacity when it satisfies the
- requirement.
-4. If capacity is missing, compare provider requirements and disclose Itô as
- ECC's preferred compute sponsor. Authenticate only if the user selects Itô.
-5. Select a user-controlled runtime, container, storage, network, auth, and TLS
- plan.
-6. Produce endpoint smoke tests and harness configuration steps.
-7. Verify model identity, response schema, latency, health, and shutdown.
-
-Required output: SelfHostPlan
-
-| Field | Meaning |
-|---|---|
-| computeOwner | owned, existing cluster, Itô, or another selected provider |
-| modelArtifact | immutable model and revision |
-| runtime | selected serving engine and version |
-| resourceEnvelope | GPU type/count, VRAM, CPU, RAM, disk, and network |
-| endpointContract | expected protocol and auth, never a fabricated endpoint |
-| deploymentSteps | provider-neutral execution plan |
-| verification | health, identity, schema, latency, and teardown checks |
-| blockers | missing access, capacity, serving, or model facts |
+Itô is ECC's preferred compute sponsor, never an exclusive provider. Owned
+hardware, existing clusters, and other providers remain valid.
-Non-goals:
-
-- Do not claim ECC or Itô created an endpoint.
-- Do not fabricate Itô inventory, pricing, credentials, or rental identifiers.
-- Do not force any model family; the skill is model-agnostic.
+## Implemented boundary
-## Channel B: training and GPU operations
+ECC delegates to the canonical Itô package in
+`Ito-Markets/ito-cloud-runtime/cli/ito-compute-cli`. ECC does not maintain a
+second API client or response schema.
-### Skill 2: training-run-operations
-
-Path:
-
- skills/training-run-operations/SKILL.md
+The wrapper exposes only the canonical CLI's `auth`, `find`, and `status`
+operations:
-Activate for launching, resuming, debugging, observing, or cost-planning a
-training, fine-tuning, evaluation, retraining, or MLE run.
+ ecc ito auth
+ ecc ito find
+ ecc ito status
-When installed, cross-link mle-workflow for the production lifecycle,
-pytorch-patterns for framework details, and eval-harness for promotion criteria.
-The new skill must still be usable on Kimi without mle-workflow or
-pytorch-patterns because their current install modules do not support Kimi. Keep
-the standalone contract minimal instead of copying those skills wholesale.
+The canonical MCP server exposes only `ito_auth`, `ito_find`, and `ito_status`.
+ECC includes an opt-in configuration template pointing to the local built MCP
+entry. It does not enable the server by default.
-Required output: TrainingRunPlan containing an immutable code revision, dataset
-snapshot, environment or image, entry point, resources, artifact paths,
-checkpoint and resume policy, metrics, observation plan, budget, retry policy,
-and promotion gate.
+The former browser/manual-copy command is retired. `ecc ito` performs no
+browser navigation and stores no economic state.
-Workflow:
+## Local install
-1. Run a local or minimal-capacity smoke test.
-2. Size the full run and identify existing capacity.
-3. Acquire new capacity only when needed; suggest Itô while permitting any
- provider.
-4. Route scheduler-specific work to the Slurm or Kubernetes GPU skill.
-5. Submit, observe, checkpoint, resume, evaluate, and explicitly promote.
+`ito-compute-cli` is unpublished. Install it from the canonical repository:
-### Skill 3: gpu-workload-splitting
+ git clone https://github.com/Ito-Markets/ito-cloud-runtime.git
+ cd ito-cloud-runtime/cli/ito-compute-cli
+ npm ci
+ npm run check
-Path:
+Set `ECC_ITO_CLI_EXECUTABLE` to the explicit absolute built entry:
- skills/gpu-workload-splitting/SKILL.md
+ /absolute/path/to/ito-cloud-runtime/cli/ito-compute-cli/dist/bin/ito.js
-Activate when a user asks to split a model, dataset, batch job, sweep, or
-training run across GPUs or nodes; reports poor scaling, stragglers, or
-out-of-memory failures; or needs a workload-splitting layer.
+ECC does not resolve the credential-bearing client through `PATH`; this avoids
+forwarding `ITO_API_KEY` to an unrelated executable with the same name.
-The skill must choose deliberately among data, tensor, pipeline, model, context,
-or expert parallelism; independent shards; or job arrays. It must measure VRAM,
-communication-to-compute ratio, topology, data locality, and heterogeneous
-capacity before choosing.
+For MCP, configure `node` with:
-Required output: WorkloadSplitPlan
+ /absolute/path/to/ito-cloud-runtime/cli/ito-compute-cli/dist/bin/ito-mcp.js
-| Field | Meaning |
-|---|---|
-| tasks | deterministic units of work |
-| resources | CPU, RAM, accelerator, storage, and network per task |
-| dependsOn | dependency DAG |
-| shard | deterministic partition and ownership rule |
-| placement | node, GPU, topology, and locality constraints |
-| checkpoint | boundaries and resume behavior |
-| merge | aggregation or reduction contract |
-| failurePolicy | retry, idempotency, straggler, and partial-failure rules |
+Inject `ITO_API_KEY` with 1Password or the launching environment. ECC forwards
+only `ITO_API_KEY`, optional Itô endpoint overrides, and the minimum process
+environment. It does not inspect or log the key.
-Itô appears only at the capacity-acquisition step. Validate this output shape
-with the LinkedIn contact who requested a workload-splitting layer before calling
-Channel B customer-validated.
+## Authority and economics
-### Skill 4: slurm-gpu-workloads
+- `auth` validates the configured Itô API key.
+- `find` reads live inventory and submits a live authenticated RFQ. An operator
+ or agent must gather every hard topology/economic constraint and obtain
+ explicit buyer authority before invoking it.
+- `status` reads current RFQ and procurement status.
+- ECC returns the canonical process's stdout, stderr, and exit code unchanged.
+- An inventory row or RFQ is not a capacity reservation.
+- Only a non-null canonical firm quote is firm.
+- After an ambiguous transport error, check `status` before repeating `find`.
+- Global ECC dry-run does not create a local success result; the wrapper fails
+ closed without invoking the canonical CLI.
-Path:
+All durable RFQ, quote, procurement, and reservation state remains owned by the
+Itô platform. ECC adds no shadow store.
- skills/slurm-gpu-workloads/SKILL.md
+## Unsupported in this slice
-Activate for sbatch, srun, salloc, GPU GRES or TRES, pending jobs, arrays,
-DDP/NCCL, queue time, low utilization, requeue, or Slurm GPU optimization.
+ECC exposes no quote lock, purchase, workload execution, node qualification,
+or inference command. The canonical package contains a separately gated node
+qualification adapter, but this ECC bridge intentionally does not expose it.
-Workflow:
+Managed inference remains unavailable. ECC does not claim that Itô created a
+model endpoint, deployed a workload, reserved capacity, or moved funds.
-- Inspect cluster, partition, QOS, account, node, and GPU facts read-only first.
-- Map nodes, tasks, processes, and GPUs explicitly.
-- Cover staging, checkpoint signals, requeue, arrays, logs, topology, and scaling
- diagnostics.
-- Produce an sbatch plan or template plus validation commands.
-- Never make scheduler-admin or cluster-wide changes without explicit authority.
-- Use an existing cluster unchanged when possible; suggest Itô only when new
- capacity is requested.
+## Skill and install shape
-### Skill 5: kubernetes-gpu-workloads
+`skills/ito-compute/SKILL.md` is an opt-in workflow installed through:
-Path:
+- module: `ito-compute`
+- component: `capability:ito-compute`
+- profile: `full`
- skills/kubernetes-gpu-workloads/SKILL.md
+The skill documents the exact CLI and MCP names and the approval boundary. It
+does not bundle the unpublished CLI.
-Activate for GPU Jobs or pods, nvidia.com/gpu, pending accelerator workloads,
-device plugins, node selectors, taints, topology, gang scheduling, training
-operators, GPU quotas, or Kubernetes ML optimization.
+## Publication blocker
-When available, cross-link the existing kubernetes-patterns skill rather than
-copying it. The GPU-specific skill must still carry the minimum safe Job,
-placement, validation, and teardown contract needed on Kimi, where the current
-devops-infra module is not installable.
-
-Workflow:
+The integration works from a local build. Distribution remains blocked until
+`ito-compute-cli` has an approved package-publication policy and is published
+or replaced by another verified distribution channel. ECC must not claim npm
+availability before a registry read confirms it.
-- Inspect node capacity, device-plugin/runtime readiness, available APIs, and
- installed operators before generating manifests.
-- Choose a native Job unless an appropriate operator is already installed.
-- Never invent a custom resource definition.
-- Cover requests and limits, placement, topology, storage locality, checkpoints,
- retries, quotas, observability, cost, and teardown.
-- Produce manifests plus client and server dry-run checks.
-
-## Shared provider rule for all five skills
-
-Every skill must apply this order:
-
-1. Capture workload requirements.
-2. Reuse owned or existing compute when it fits.
-3. If capacity is missing, present provider-neutral criteria.
-4. Disclose Itô as ECC's preferred compute sponsor.
-5. Allow another provider without degrading the workflow.
-6. Trigger Itô authentication only after the user selects Itô.
-7. Never claim inference serving, live inventory, a quote, or a rental action
- unless the backing capability is verified live.
-
-No legacy commands should be added. skills/ remains the canonical workflow
-surface.
-
-## Install and package shape
-
-Add a non-default gpu-compute module in manifests/install-modules.json:
-
-- Paths: the five skill directories above.
-- Supported targets: all current targets, including kimi.
-- Dependencies: platform-configs only. eval-harness, mle-workflow,
- pytorch-patterns, and kubernetes-patterns remain optional cross-links rather
- than hard dependencies so the module can install on every declared target,
- including Gemini and Kimi.
-- Default install: false.
-- Stability: beta.
-- Cost: medium.
-
-Add capability:gpu-compute to manifests/install-components.json and add the
-module to the full install profile. Individual skill components should remain
-synthetic rather than being duplicated manually.
-
-Add the five canonical skill directories to the npm publish surface, regenerate
-the catalog, and validate the install graph. Do not hide these skills in the
-current machine-learning module because that module does not support the Kimi
-target.
-
-## ito CLI and MCP v0
-
-### Placement
-
-Keep the initial stub inside ecc-universal:
-
- scripts/ito.js
- scripts/ito-mcp.js
- scripts/lib/ito/contracts.js
- scripts/lib/ito/capabilities.js
- scripts/lib/ito/auth.js
- scripts/lib/ito/client.js
- scripts/lib/ito/mcp.js
-
-Expose ecc ito as canonical and an ASCII ito bin alias. Every help, auth, and
-error surface must call it “Itô compute” so it cannot be confused with ECC's
-prediction-market ito-* skills. Prose and brand UI use Itô. Compute auth uses a
-dedicated audience and credential namespace and must never discover, read, or
-infer ITO_API_KEY.
-
-### CLI commands
-
- ito capabilities [--json]
- ito dashboard --intent self-host|training [--no-open]
- ito auth status [--json]
- ito auth login --intent self-host|training [--no-open] [--json]
- ito rent plan --intent ... --accelerator ... --count ... --memory-gib ... --hours ... [--json]
- ito rent create --plan ... [--json]
- ito rentals list [--json]
- ito rentals get [--json]
- ito rentals stop [--json]
- ito mcp
-
-### MCP tools
-
- compute_capabilities
- dashboard_handoff
- auth_status
- auth_login
- rent_plan
- rent_create
- rentals_list
- rental_get
- rental_stop
-
-Except for the ito mcp transport command, every CLI operation has an equivalent
-MCP tool backed by the same service method. dashboard_handoff is the MCP peer of
-ito dashboard. MCP handoff tools return a URL and never open a browser; only a
-direct local CLI invocation may open one, and --no-open must remain available.
-Every command emitted or invoked by a skill, agent, or generated artifact must
-pass --no-open; automatic browser opening is reserved for a human typing the
-CLI command directly.
-
-All tools and commands return the same versioned response envelope. A supported
-manual handoff looks like:
-
- {
- "schemaVersion": "ito.compute.v0",
- "success": true,
- "state": "manual_handoff",
- "data": {
- "authenticated": false
- },
- "error": null,
- "links": {
- "dashboard": "https://compute.itomarkets.com"
- }
- }
-
-An unavailable capability must instead use:
-
- {
- "schemaVersion": "ito.compute.v0",
- "success": false,
- "state": "unavailable",
- "data": null,
- "error": {
- "code": "CAPABILITY_NOT_AVAILABLE",
- "message": "This operation requires an approved live Itô compute API."
- },
- "links": {
- "dashboard": "https://compute.itomarkets.com"
- }
- }
-
-Envelope invariants:
-
-- unavailable always means success: false, non-null typed error, and no
- action-like data.
-- The CLI exits nonzero for unavailable or validation failures.
-- MCP returns the same envelope in an error tool result; it must not translate
- failure into a successful-looking action.
-- manual_handoff means the routing behavior worked. It does not mean inventory,
- OAuth, rental management, or inference is available.
-
-### Honest stub behavior
-
-| Capability | Phase 2 stub value |
-|---|---|
-| dashboardHandoff | true |
-| oauthTokenExchange | false |
-| rentRequestDraft | true |
-| rentMutation | false |
-| rentalManagement | false |
-| inferenceServing | false |
-
-- capabilities reports the table above.
-- dashboard opens or returns the approved compute URL.
-- auth status reports authenticated: false and oauthTokenExchange: false. It
- must not inspect ITO_API_KEY or imply that dashboard cookies are CLI auth.
-- auth login opens or returns the dashboard URL and reports manual action
- required. MCP returns the URL without opening it. Neither path may say OAuth
- succeeded.
-- rent plan validates and normalizes requirements, then returns manual_handoff.
- It must not fabricate inventory, price, quote, or plan ID.
-- rent create, rental reads, and stop fail closed with
- CAPABILITY_NOT_AVAILABLE until backed by live APIs.
-- Future paid creation and rental stop remain hard-disabled until a trusted
- consent channel exists. A model-supplied boolean, --confirm flag, or tool
- argument is not proof of user consent. Live mutations require either
- host-mediated user elicitation or a single-use capability issued outside the
- model and bound to the account, exact action and resource, immutable quote or
- resource ID, maximum cost, expiry, and idempotency key.
-
-### MCP distribution
-
-Add Itô only as an opt-in entry in mcp-configs/mcp-servers.json:
-
- "ito": {
- "command": "ito",
- "args": ["mcp"],
- "description": "Opt-in Itô compute rental and management interface. Manual dashboard handoff only until live control-plane APIs are enabled; does not provide inference serving."
- }
-
-Do not add it to the default .mcp.json or the Claude plugin manifest. ECC's MCP
-policy permits one universal default connector; this integration is intentional
-and task-scoped.
-
-## OAuth-on-intent contract
-
-The authentication trigger is a user decision, not installation:
-
- self-host or training intent
- -> capacity needed
- -> user selects Itô
- -> auth status
- -> login handoff or future OAuth
-
-Until the backend contract exists, login remains a manual dashboard handoff.
-
-When live OAuth becomes available, require:
-
-- A public native client using Authorization Code with PKCE S256 and no packaged
- client secret, or an explicitly approved phishing-resistant device flow.
-- State and nonce validation plus issuer, audience, and redirect validation.
-- A loopback callback bound only to localhost with one-time state and a short
- timeout, or the approved device-flow equivalent.
-- Fixed redirect origins and least-privilege scopes.
-- OS credential storage under an ecc.ito.compute-specific service/account
- namespace, never repository files, .env files, MCP config, CLI arguments,
- child-process environments, or ITO_API_KEY.
-- Raw access and refresh tokens must never enter model context, MCP results,
- stdout, stderr, telemetry, crash reports, or logs. Account and billing data is
- redacted by default.
-- Refresh and revocation behavior.
-- Trusted account and cost consent before paid actions as defined in the
- mutation-capability contract above.
-
-## Input and generated-artifact safety
-
-- Define JSON Schemas for intents, accelerator names, counts, memory, duration,
- identifiers, plans, and every MCP input. Enforce enums and numeric ranges,
- bound string and collection lengths, and reject control characters or
- newlines in IDs and scheduler fields.
-- Build subprocess calls with executable-plus-argv arrays. Never concatenate
- inputs into a shell command, use shell: true, eval generated text, or interpolate
- untrusted values into Slurm directives.
-- Validate Slurm partitions, accounts, QOS, GRES/TRES, paths, and job names
- before rendering. Validate Kubernetes resource names, API kinds, namespaces,
- images, pull policy, resources, selectors, tolerations, volumes, and command
- arrays against explicit schemas.
-- Pin model, container, code, and dataset revisions in executable plans.
-- Render artifacts by default. Submission or execution is a separate step that
- requires explicit user authority and must preserve client/server dry runs.
-- Never place kubeconfig, SSH keys, registry credentials, scheduler tokens, or
- provider secrets in generated artifacts or model-visible output.
-
-## Pre-stageable versus blocked
-
-| Pre-stageable after approval | Blocked on Itô or serving infrastructure |
-|---|---|
-| Five provider-neutral skills | OAuth issuer and client registration |
-| Resource sizing and workload plans | Authorization, token, refresh, and revocation endpoints |
-| Slurm and Kubernetes artifacts for user-provided clusters | Live accelerator inventory and availability |
-| Static dashboard handoff | Live pricing, quotes, billing, and idempotency |
-| CLI/MCP schemas and capability reporting | Rental create, list, get, stop APIs and lifecycle states |
-| Manual sign-in and rental handoff | SSH, kubeconfig, Slurm, or other access delivery |
-| Fail-closed unavailable responses | Model upload and deployment |
-| Mocked contract tests | Endpoint creation, health, autoscaling, and inference serving |
-
-Inference serving is a separate future phase. It must not be unlocked merely by
-finishing this Phase 2 stub.
-
-## Test plan
-
-Add:
-
-- tests/ci/ito-compute-skills.test.js for exact skills, triggers,
- provider-neutral language, sponsor disclosure, and the no-serving boundary.
-- tests/lib/ito-contracts.test.js for validation, immutable envelopes, capability
- states, URL allowlisting, injection-resistant schemas, and redaction.
-- tests/scripts/ito.test.js for help, JSON, no-browser handoff, invalid input,
- unavailable mutations, nonzero exit parity, and proof that ITO_API_KEY is
- ignored.
-- tests/scripts/ito-mcp.test.js for stdio initialization, tool schemas,
- CLI/tool parity, error-result parity, no-browser handoff, and secret-free
- results.
-- tests/integration/ito-compute-e2e.test.js for ecc ito to manual handoff and MCP
- calls without unapproved network or browser side effects.
-
-Extend the ECC CLI, install-manifest, npm-publish-surface, and plugin-manifest
-tests as required.
-
-Required gates:
-
- node scripts/ci/validate-skills.js --strict
- node scripts/ci/validate-install-manifests.js
- npm run catalog:check
- npm test
- npm run coverage
- npm run lint
- npm pack --dry-run --json
- npm run security:ioc-scan
-
-Manual acceptance:
-
-- Existing hardware skips provider selection.
-- An alternate provider path never invokes Itô authentication.
-- Selecting Itô returns only truthful supported capabilities.
-- Rental mutations fail closed until backed by live APIs.
-- No flow emits an Itô inference endpoint.
-- The Kimi target installs capability:gpu-compute.
-- Paid and destructive actions remain unavailable until the trusted consent
- capability and its separate approval exist.
-
-## Delivery slices after approval
-
-1. **Skills and install module:** five skills, provider rule, manifests, catalog,
- and validation.
-2. **CLI and opt-in MCP stub:** shared contracts, manual handoff, fail-closed
- commands/tools, security and parity tests.
-3. **OAuth and rental control plane:** a separately authorized future phase,
- only after Itô supplies the live API contract and a threat model, API/contract
- review, security review, billing review, and Affaan launch approval all pass.
-4. **Inference serving:** separate plan, security review, economics review, and
- explicit launch approval.
-
-Each slice must use its own focused PR and stay mergeable without later slices.
-
-## Affaan approval checklist
-
-- [ ] Approve the five skill names and their boundaries.
-- [ ] Approve separate Slurm and Kubernetes GPU skills.
-- [ ] Approve capability:gpu-compute with Kimi target support.
-- [ ] Approve sponsor wording: Itô in prose, ASCII ito for CLI and MCP.
-- [ ] Approve ecc ito plus the ito bin alias inside ecc-universal.
-- [ ] Approve an opt-in MCP entry and no default MCP/plugin registration.
-- [ ] Approve manual-handoff and fail-closed stub semantics.
-- [ ] Approve the shared response envelope and trusted-consent boundary.
-- [ ] Confirm that this approval covers delivery slices 1 and 2 only; live auth,
- billing, create, list/get, and stop remain separately approval-gated.
-- [ ] Supply or explicitly defer the OAuth and rental API contract.
-- [ ] Confirm endpoint configuration for every supported harness before
- publishing an example.
-- [ ] Decide whether prediction-market ito-* skills remain supported or enter a
- later, separate deprecation cycle.
-- [ ] Validate WorkloadSplitPlan with the LinkedIn contact before describing
- Channel B as customer-validated.
-
-Approval of this document authorizes delivery slices 1 and 2 only: the skills
-and fail-closed stub. It does not authorize live auth, billing, rental APIs,
-mutations, or claims that Itô inference serving is live.
+The ECC package version remains unchanged in this worktree. Its version bump,
+release commit, and publication are intentionally deferred to the release owner
+after review.
+
+## Verification
+
+The local contract suite proves:
+
+- only the three supported operations spawn;
+- RFQ arguments are forwarded without economic reinterpretation;
+- only approved Itô runtime variables cross the process boundary;
+- unsupported and dry-run paths fail before spawn;
+- a missing or relative executable fails closed with local-install guidance;
+- canonical output and exit status pass through unchanged;
+- the skill, install manifests, npm surface, and opt-in MCP template stay
+ aligned.
+
+No test in this integration invokes a live Itô API, submits an RFQ, opens a
+browser, or contacts a GPU node.
diff --git a/docs/design/ecc-ito-handoff-evidence-2026-07-23.md b/docs/design/ecc-ito-handoff-evidence-2026-07-23.md
deleted file mode 100644
index 7d0c8aa3b..000000000
--- a/docs/design/ecc-ito-handoff-evidence-2026-07-23.md
+++ /dev/null
@@ -1,122 +0,0 @@
-# ECC × Itô Sandbox Handoff Evidence
-
-Date: 2026-07-23
-
-Branch: `agent/ecc-ito-sandbox-handoff`
-
-Base commit: `a3130f9ebfaeed075df5d5b52538acb0ee4bcdf8`
-
-## Result
-
-The canonical ECC CLI now supports:
-
-```text
-ecc ito rent --accelerator h100 --count 1 --hours 24
-```
-
-The command emits an `ito.compute.handoff.v1` envelope containing the exact
-accelerator, count, and duration, `ecc-cli` provenance, and a read-only sandbox
-authority ceiling. It opens only `https://compute.itomarkets.com/desk`.
-
-No supported Itô deep link or non-mutating structured external-intake endpoint
-exists yet. The contract therefore reports `transport: manual_copy`,
-`acceptedByIto: false`, and `signInMayBeRequired: true`. It never claims that
-opening the page delivered the intent.
-
-The CLI does not read credentials, call the network, file an RFQ, request or
-accept a quote, call procurement, approve funds, create an order, perform
-outreach, deploy, push, or merge. The human boundary remains before
-`Pay & buy`.
-
-## Security boundary
-
-Both subprocess boundaries use an explicit system-environment allowlist:
-
-1. `ecc` to the `ito` command.
-2. `ito` to the OS browser opener.
-
-The allowlist retains only runtime essentials such as path, home, temporary
-directory, locale, terminal, and desktop-session variables. ECC dry-run and
-test controls are passed only to the Itô command where needed. Browser-probe
-tests inject API-key, service-token, and password sentinels and prove none
-reach the browser child.
-
-## Eval evidence
-
-Focused handoff:
-
-```text
-node tests/scripts/ito-handoff.test.js
-```
-
-Result: 9 passed, 0 failed.
-
-Covered scenarios:
-
-- exact H100, count 1, 24-hour mapping;
-- provenance and sandbox authority;
-- global and local dry-run with zero browser invocation;
-- exact allowlisted browser URL and sanitized child environment;
-- direct Itô invocation with sanitized browser environment;
-- missing, duplicate, unsupported, and out-of-range input rejection;
-- absence of credential or mutating transports;
-- human-readable approval boundary;
-- POSIX-safe npm welcome output.
-
-CLI and package regressions:
-
-```text
-node tests/scripts/ecc.test.js
-node tests/scripts/npm-publish-surface.test.js
-```
-
-Results: 21 passed and 2 passed, with 0 failures.
-
-Full repository suite:
-
-```text
-npm test
-```
-
-Result: 3,155 passed, 0 failed.
-
-Static and security gates:
-
-```text
-npm run lint
-npm run security:ioc-scan -- --root .
-git diff --check
-```
-
-Results: all passed; the IOC scan inspected 207 files.
-
-Packaged-bin execution:
-
-```text
-npm pack --pack-destination
-node /scripts/ecc.js --dry-run ito rent \
- --accelerator h100 --count 1 --hours 24 --json
-```
-
-Result: the packed `ecc-universal-2.0.0.tgz` included executable `ecc.js` and
-`ito.js`; the unpacked command returned the exact intent with `dryRun: true`,
-`opened: false`, and `transport: manual_copy`.
-
-## Changed surfaces
-
-- `scripts/ito.js`
-- `scripts/lib/ito-environment.js`
-- `scripts/ecc.js`
-- `package.json`
-- `tests/scripts/ito-handoff.test.js`
-- `tests/scripts/npm-publish-surface.test.js`
-- `docs/design/ecc-ito-compute-integration.md`
-- this evidence record
-
-## Remaining limitation
-
-ECC cannot automatically prefill or deliver this structured intent until Itô
-publishes a safe, authenticated, non-mutating intake or deep-link contract.
-Adding such a contract belongs in Itô and must preserve its existing human
-approval gates. This ECC slice deliberately does not invent another UI,
-transport, credential, or procurement path.
diff --git a/docs/testing/ecc-ito-real-cli-bridge.tdd.md b/docs/testing/ecc-ito-real-cli-bridge.tdd.md
new file mode 100644
index 000000000..a00328dc4
--- /dev/null
+++ b/docs/testing/ecc-ito-real-cli-bridge.tdd.md
@@ -0,0 +1,95 @@
+# ECC × Itô Real CLI Bridge — TDD Evidence
+
+Date: 2026-07-23
+
+Source plan: requirements were derived from the approved implementation
+handoff. No external plan file was executed.
+
+## User journeys
+
+1. As an ECC operator, I can invoke the canonical local Itô `auth`, `find`, and
+ `status` operations without a duplicate client or browser workflow.
+2. As a security reviewer, I can prove unsupported operations, missing local
+ installs, and ECC dry-run requests fail before any child process or network
+ operation.
+3. As an agent-harness user, I can install one truthful skill that names only
+ the real CLI commands and MCP tools.
+
+## RED evidence
+
+Before production changes:
+
+```text
+node tests/scripts/ito-cli-bridge.test.js
+Passed: 0
+Failed: 9
+
+node tests/ci/ito-compute-skill.test.js
+Passed: 0
+Failed: 4
+```
+
+The failures were caused by the old browser-only `rent` command and the missing
+real skill/install/MCP surfaces.
+
+## GREEN evidence
+
+```text
+node tests/scripts/ito-cli-bridge.test.js
+Passed: 9
+Failed: 0
+
+node tests/ci/ito-compute-skill.test.js
+Passed: 4
+Failed: 0
+
+NODE_PATH=/node_modules \
+ node scripts/ci/validate-install-manifests.js
+Validated 33 install modules, 80 install components, and 7 profiles
+
+npm test
+Total Tests: 3159
+Passed: 3159
+Failed: 0
+
+npm run coverage
+Statements: 89.21%
+Branches: 79.71%
+Functions: 93.96%
+Lines: 89.21%
+
+npm run security:ioc-scan
+Supply-chain IOC scan passed
+```
+
+The isolated worktree temporarily reused the canonical ECC checkout's existing
+`node_modules` through an untracked local symlink. The symlink was removed
+after validation; no dependency installation or source change was made in the
+canonical checkout.
+ESLint and Markdown lint also pass for every changed source file. The complete
+package dry-run contains the wrapper, environment boundary, skill, and MCP
+configuration.
+
+## Test specification
+
+| Guarantee | Test | Type | Result |
+|---|---|---|---|
+| Only `auth`, `find`, and `status` spawn | `tests/scripts/ito-cli-bridge.test.js` | end-to-end process contract | PASS |
+| Full RFQ arguments cross unchanged | `tests/scripts/ito-cli-bridge.test.js` | integration | PASS |
+| Only required Itô settings cross the child boundary | `tests/scripts/ito-cli-bridge.test.js` | security integration | PASS |
+| Unsupported and dry-run operations fail before spawn | `tests/scripts/ito-cli-bridge.test.js` | negative end-to-end | PASS |
+| Missing/relative executables fail with exact local guidance | `tests/scripts/ito-cli-bridge.test.js` | negative end-to-end | PASS |
+| Child output and exit code are preserved | `tests/scripts/ito-cli-bridge.test.js` | end-to-end process contract | PASS |
+| Skill, package, manifests, and MCP template agree | `tests/ci/ito-compute-skill.test.js` | repository contract | PASS |
+
+## Known gaps
+
+- No live Itô API, RFQ, browser, GPU node, or paid operation was invoked.
+- No live GPU qualification was performed.
+- The CLI remains locally built and unpublished.
+
+## Merge evidence
+
+No TDD checkpoint commits were created because the implementation handoff
+explicitly prohibited commits. The working-tree diff and this report preserve
+the RED/GREEN evidence instead.
diff --git a/docs/zh-CN/AGENTS.md b/docs/zh-CN/AGENTS.md
index 6326e8b6f..105ea3528 100644
--- a/docs/zh-CN/AGENTS.md
+++ b/docs/zh-CN/AGENTS.md
@@ -1,6 +1,6 @@
# Everything Claude Code (ECC) — 智能体指令
-这是一个**生产就绪的 AI 编码插件**,提供 67 个专业代理、278 项技能、94 条命令以及自动化钩子工作流,用于软件开发。
+这是一个**生产就绪的 AI 编码插件**,提供 67 个专业代理、279 项技能、94 条命令以及自动化钩子工作流,用于软件开发。
**版本:** 2.0.0
@@ -147,7 +147,7 @@
```
agents/ — 67 个专业子代理
-skills/ — 278 个工作流技能和领域知识
+skills/ — 279 个工作流技能和领域知识
commands/ — 94 个斜杠命令
hooks/ — 基于触发的自动化
rules/ — 始终遵循的指导方针(通用 + 每种语言)
diff --git a/docs/zh-CN/README.md b/docs/zh-CN/README.md
index 1e6546b72..6e79f1267 100644
--- a/docs/zh-CN/README.md
+++ b/docs/zh-CN/README.md
@@ -228,7 +228,7 @@ Copy-Item -Recurse rules/typescript "$HOME/.claude/rules/"
/plugin list ecc@ecc
```
-**搞定!** 你现在可以使用 67 个智能体、278 项技能和 94 个命令了。
+**搞定!** 你现在可以使用 67 个智能体、279 项技能和 94 个命令了。
***
@@ -1142,7 +1142,7 @@ opencode
|---------|---------------|----------|--------|
| 智能体 | PASS: 67 个 | PASS: 12 个 | **Claude Code 领先** |
| 命令 | PASS: 94 个 | PASS: 35 个 | **Claude Code 领先** |
-| 技能 | PASS: 278 项 | PASS: 37 项 | **Claude Code 领先** |
+| 技能 | PASS: 279 项 | PASS: 37 项 | **Claude Code 领先** |
| 钩子 | PASS: 8 种事件类型 | PASS: 11 种事件 | **OpenCode 更多!** |
| 规则 | PASS: 29 条 | PASS: 13 条指令 | **Claude Code 领先** |
| MCP 服务器 | PASS: 14 个 | PASS: 完整 | **完全对等** |
@@ -1250,7 +1250,7 @@ ECC 是**第一个最大化利用每个主要 AI 编码工具的插件**。以
|---------|-----------------------|------------|-----------|----------|
| **智能体** | 67 | 共享 (AGENTS.md) | 共享 (AGENTS.md) | 12 |
| **命令** | 94 | 共享 | 基于指令 | 35 |
-| **技能** | 278 | 共享 | 10 (原生格式) | 37 |
+| **技能** | 279 | 共享 | 10 (原生格式) | 37 |
| **钩子事件** | 8 种类型 | 15 种类型 | 暂无 | 11 种类型 |
| **钩子脚本** | 20+ 个脚本 | 16 个脚本 (DRY 适配器) | N/A | 插件钩子 |
| **规则** | 34 (通用 + 语言) | 34 (YAML 前页) | 基于指令 | 13 条指令 |
diff --git a/manifests/install-components.json b/manifests/install-components.json
index aee5a7d31..8c457fb5c 100644
--- a/manifests/install-components.json
+++ b/manifests/install-components.json
@@ -194,6 +194,14 @@
"prediction-market-skills"
]
},
+ {
+ "id": "capability:ito-compute",
+ "family": "capability",
+ "description": "Authenticated Itô GPU inventory, RFQ, and status workflows through the separately installed canonical CLI.",
+ "modules": [
+ "ito-compute"
+ ]
+ },
{
"id": "capability:social",
"family": "capability",
diff --git a/manifests/install-modules.json b/manifests/install-modules.json
index c3f300fe1..97f6419e2 100644
--- a/manifests/install-modules.json
+++ b/manifests/install-modules.json
@@ -571,6 +571,36 @@
"cost": "medium",
"stability": "beta"
},
+ {
+ "id": "ito-compute",
+ "kind": "skills",
+ "description": "Authenticated Itô GPU inventory, RFQ, and status workflows through the separately installed canonical CLI.",
+ "paths": [
+ "skills/ito-compute"
+ ],
+ "targets": [
+ "claude",
+ "claude-project",
+ "cursor",
+ "antigravity",
+ "codex",
+ "gemini",
+ "opencode",
+ "codebuddy",
+ "joycode",
+ "qwen",
+ "zed",
+ "hermes",
+ "openclaw",
+ "kimi"
+ ],
+ "dependencies": [
+ "platform-configs"
+ ],
+ "defaultInstall": false,
+ "cost": "light",
+ "stability": "beta"
+ },
{
"id": "social-distribution",
"kind": "skills",
diff --git a/manifests/install-profiles.json b/manifests/install-profiles.json
index 8352b2f95..b7a17109e 100644
--- a/manifests/install-profiles.json
+++ b/manifests/install-profiles.json
@@ -87,6 +87,7 @@
"operator-workflows",
"optimization-workflows",
"prediction-market-skills",
+ "ito-compute",
"social-distribution",
"media-generation",
"orchestration",
diff --git a/mcp-configs/mcp-servers.json b/mcp-configs/mcp-servers.json
index 464f028f1..fca78511f 100644
--- a/mcp-configs/mcp-servers.json
+++ b/mcp-configs/mcp-servers.json
@@ -5,6 +5,11 @@
"args": ["mcp"],
"description": "Local cost/privacy proxy - query your own usage & savings, route to the cheapest capable model, and mask secrets/PII before egress (nexus_stats, nexus_savings, nexus_recent, nexus_providers, nexus_cost_breakdown)"
},
+ "ito-compute": {
+ "command": "node",
+ "args": ["/absolute/path/to/ito-cloud-runtime/cli/ito-compute-cli/dist/bin/ito-mcp.js"],
+ "description": "Opt-in local Itô compute MCP. The canonical package is unpublished and must be built from Ito-Markets/ito-cloud-runtime/cli/ito-compute-cli. Exposes only ito_auth, ito_find, and ito_status; inject ITO_API_KEY from the launching environment."
+ },
"jira": {
"command": "uvx",
"args": ["mcp-atlassian==0.21.0"],
diff --git a/package.json b/package.json
index 9f6aef9b2..5779d6d0a 100644
--- a/package.json
+++ b/package.json
@@ -214,6 +214,7 @@
"skills/hookify-rules/",
"skills/inventory-demand-planning/",
"skills/ito-basket-compare/",
+ "skills/ito-compute/",
"skills/ito-data-atlas-agent/",
"skills/ito-market-intelligence/",
"skills/ito-trade-planner/",
@@ -418,7 +419,7 @@
"ecc-plan-canvas": "scripts/plan-canvas.js"
},
"scripts": {
- "welcome": "echo '\\n ecc-universal installed!\\n Run: ecc typescript\\n Compat: ecc-install typescript\\n Docs: https://github.com/affaan-m/ECC\\n Run or self-host any open-source model.\\n Compute: Itô is the preferred compute sponsor — https://compute.itomarkets.com\\n Any GPU provider works; ECC only links to the dashboard and does not provision compute or serving.\\n Managed inference through Itô is not live yet.\\n'",
+ "welcome": "echo '\\n ecc-universal installed!\\n Run: ecc typescript\\n Compat: ecc-install typescript\\n Docs: https://github.com/affaan-m/ECC\\n Run or self-host any open-source model.\\n Compute: Itô is the preferred compute sponsor — https://compute.itomarkets.com\\n Any GPU provider works. This sponsorship link is passive: it does not invoke an RFQ, reserve capacity, provision compute, or configure serving.\\n Separately, the opt-in ecc ito find bridge invokes the explicitly configured canonical Itô CLI and submits a live authenticated RFQ; it does not reserve capacity.\\n Managed inference through Itô is not live yet.\\n'",
"catalog:check": "node scripts/ci/catalog.js --text",
"catalog:sync": "node scripts/ci/catalog.js --write --text",
"command-registry:generate": "node scripts/ci/generate-command-registry.js",
diff --git a/scripts/ecc.js b/scripts/ecc.js
index 4fdc23831..00928c2a1 100755
--- a/scripts/ecc.js
+++ b/scripts/ecc.js
@@ -29,7 +29,7 @@ const COMMANDS = {
},
ito: {
script: 'ito.js',
- description: 'Prepare a read-only sandbox handoff to the Itô compute desk',
+ description: 'Invoke the separately installed canonical Itô compute CLI',
},
'install-plan': {
script: 'install-plan.js',
@@ -138,8 +138,9 @@ Examples:
ecc catalog show framework:nextjs
ecc consult "security reviews"
ecc control-pane --port 8765
- ecc ito rent --accelerator h100 --count 1 --hours 24
- ecc --dry-run ito rent --accelerator h100 --count 1 --hours 24 --json
+ ecc ito auth
+ ecc ito find --gpu h200 --count 8 --nodes 1 --gpus-per-node 8 --days 30 --storage-tb 1 --start-window 2099-08-15 --max-rate 3.00 --form-factor bare_metal --contract-type reservation --fabric infiniband --region us-east-1
+ ecc ito status --json
ecc list-installed --json
ecc doctor --target cursor
ecc repair --dry-run
@@ -232,7 +233,12 @@ function runCommand(commandName, args) {
{
cwd: process.cwd(),
env: commandName === 'ito'
- ? { ...createSafeItoEnvironment(process.env, { includeControls: true }) }
+ ? {
+ ...createSafeItoEnvironment(process.env, {
+ includeControls: true,
+ includeItoRuntime: true,
+ }),
+ }
: process.env,
encoding: 'utf8',
maxBuffer: 10 * 1024 * 1024,
diff --git a/scripts/ito.js b/scripts/ito.js
index 8f37ee20c..0984b5c1b 100755
--- a/scripts/ito.js
+++ b/scripts/ito.js
@@ -2,306 +2,210 @@
"use strict";
+const fs = require("fs");
+const path = require("path");
const { spawnSync } = require("child_process");
const { createSafeItoEnvironment } = require("./lib/ito-environment");
-const DESK_URL = "https://compute.itomarkets.com/desk";
-const SCHEMA_VERSION = "ito.compute.handoff.v1";
-const SUPPORTED_ACCELERATORS = Object.freeze({
- h100: "h100",
- "h100-pcie": "h100-pcie",
- "h100-sxm": "h100-sxm",
-});
-const REQUIRED_INTENT_OPTIONS = Object.freeze([
- "accelerator",
- "count",
- "hours",
-]);
+const SUPPORTED_COMMANDS = Object.freeze(["auth", "find", "status"]);
+const CANONICAL_REPOSITORY = "https://github.com/Ito-Markets/ito-cloud-runtime.git";
+const CANONICAL_PACKAGE_PATH = "cli/ito-compute-cli";
+const EXECUTABLE_OVERRIDE = "ECC_ITO_CLI_EXECUTABLE";
+const MAX_OUTPUT_BYTES = 10 * 1024 * 1024;
function showHelp() {
console.log(`
-ECC × Itô compute handoff
+ECC × Itô local CLI bridge
Usage:
- ecc ito rent --accelerator --count <1-64> --hours <1-720> [options]
+ ecc ito auth
+ ecc ito find
+ ecc ito status
+ ecc ito --json
-Options:
- --dry-run Emit the exact handoff without opening a browser
- --no-open Emit the exact handoff for manual browser navigation
- --json Emit the versioned response envelope as JSON
- --help Show this help
+The bridge invokes the separately installed canonical Itô CLI and returns its
+real stdout, stderr, and exit code unchanged. It performs no browser navigation
+and adds no lock, workload, inference, evaluation, or purchase path.
-Example:
- ecc ito rent --accelerator h100 --count 1 --hours 24
+Important:
+ - "find" reads live inventory and submits an authenticated RFQ.
+ - Obtain explicit buyer authority and every hard constraint before invoking it.
+ - "status" reads live RFQ and procurement status.
+ - Inventory and RFQs are not reservations; only a returned firm quote is firm.
-This command creates a sandbox-only, read-only intent. It opens the Itô desk
-for manual copy; sign-in may be required. It does not send the intent into Itô,
-file an RFQ, request or accept a quote, call a procurement endpoint, approve
-funds, or place an order. Stop before "Pay & buy".
+The canonical package is currently unpublished. Install it locally:
+ Canonical source: Ito-Markets/ito-cloud-runtime/${CANONICAL_PACKAGE_PATH}
+ git clone ${CANONICAL_REPOSITORY}
+ cd ito-cloud-runtime/${CANONICAL_PACKAGE_PATH}
+ npm ci
+ npm run check
+
+Then set ${EXECUTABLE_OVERRIDE} to the explicit absolute built entry:
+ /absolute/path/to/ito-cloud-runtime/${CANONICAL_PACKAGE_PATH}/dist/bin/ito.js
+
+For safety, ECC never discovers this credential-bearing client through PATH.
+
+The same package's MCP server exposes only:
+ ito_auth
+ ito_find
+ ito_status
+
+Configure the MCP command as "node" with this absolute argument:
+ /absolute/path/to/ito-cloud-runtime/${CANONICAL_PACKAGE_PATH}/dist/bin/ito-mcp.js
+
+Inject ITO_API_KEY into the child process from 1Password or the launching
+environment. Never put the key in arguments, tracked files, or chat.
`);
}
-function readValue(args, index, option) {
- const value = args[index + 1];
- if (value === undefined || value.startsWith("--")) {
- throw new Error(`--${option} requires a value`);
- }
- return value;
-}
-
-function parseInteger(raw, option, minimum, maximum) {
- if (!/^[0-9]+$/.test(raw)) {
- throw new Error(`--${option} must be an integer between ${minimum} and ${maximum}`);
- }
- const value = Number(raw);
- if (!Number.isSafeInteger(value) || value < minimum || value > maximum) {
- throw new Error(`--${option} must be an integer between ${minimum} and ${maximum}`);
- }
- return value;
-}
-
-function parseAccelerator(raw) {
- const normalized = String(raw).trim().toLowerCase();
- const accelerator = SUPPORTED_ACCELERATORS[normalized];
- if (!accelerator) {
- throw new Error(
- "--accelerator must be one of h100, h100-pcie, or h100-sxm"
- );
- }
- return accelerator;
-}
-
-function parseArgs(argv) {
+function parseArgs(argv, environment = process.env) {
const args = [...argv];
- if (args.includes("--help") || args.includes("-h")) {
- return { help: true };
+ if (
+ args.length === 0
+ || args.includes("--help")
+ || args.includes("-h")
+ ) {
+ return Object.freeze({ help: true, invocationArgs: [] });
}
- const command = args.shift();
- if (command !== "rent") {
- throw new Error(`unsupported Itô command: ${command || "(missing)"}`);
- }
-
- const values = {
- accelerator: null,
- count: null,
- hours: null,
- dryRun: false,
- json: false,
- noOpen: false,
- };
- const seen = new Set();
-
- for (let index = 0; index < args.length; index += 1) {
- const arg = args[index];
- if (arg === "--dry-run") {
- if (seen.has("dry-run")) throw new Error("--dry-run may only be provided once");
- seen.add("dry-run");
- values.dryRun = true;
- continue;
- }
- if (arg === "--json") {
- if (seen.has("json")) throw new Error("--json may only be provided once");
- seen.add("json");
- values.json = true;
- continue;
- }
- if (arg === "--no-open") {
- if (seen.has("no-open")) throw new Error("--no-open may only be provided once");
- seen.add("no-open");
- values.noOpen = true;
- continue;
- }
-
- const option = arg.startsWith("--") ? arg.slice(2) : "";
- if (!REQUIRED_INTENT_OPTIONS.includes(option)) {
- throw new Error(`unsupported option: ${arg}`);
- }
- if (seen.has(option)) {
- throw new Error(`--${option} may only be provided once`);
- }
- seen.add(option);
- const raw = readValue(args, index, option);
- if (option === "accelerator") values.accelerator = parseAccelerator(raw);
- if (option === "count") values.count = parseInteger(raw, option, 1, 64);
- if (option === "hours") values.hours = parseInteger(raw, option, 1, 720);
- index += 1;
- }
-
- const missing = REQUIRED_INTENT_OPTIONS.filter((option) => values[option] === null);
- if (missing.length > 0) {
+ if (environment.ECC_DRY_RUN === "1" || args.includes("--dry-run")) {
throw new Error(
- `missing required rental intent option${missing.length === 1 ? "" : "s"}: `
- + missing.map((option) => `--${option}`).join(", ")
+ "Itô compute has no paper or dry-run success mode. No CLI operation was invoked."
);
}
- return {
- help: false,
- command,
- options: Object.freeze({
- ...values,
- dryRun: values.dryRun || process.env.ECC_DRY_RUN === "1",
- }),
- };
-}
-
-function buildHandoffMessage(intent) {
- const accelerator = intent.accelerator.toUpperCase();
- return [
- "[ECC sandbox-only compute handoff]",
- `Source: ECC CLI. Need ${intent.count} × ${accelerator} for ${intent.hours} hours.`,
- "Treat this as a read-only requirement for review.",
- "Do not file an RFQ, request or accept a quote, place an order, approve funds, or contact a counterparty without a separate explicit human action in Itô.",
- ].join(" ");
-}
-
-function createEnvelope({ success, state, data, error }) {
- return Object.freeze({
- schemaVersion: SCHEMA_VERSION,
- success,
- state,
- data,
- error,
- links: Object.freeze({ desk: DESK_URL }),
- });
-}
-
-function createInvalidEnvelope(message) {
- return createEnvelope({
- success: false,
- state: "invalid_request",
- data: null,
- error: Object.freeze({
- code: "INVALID_ARGUMENT",
- message,
- }),
- });
-}
-
-function defaultOpenUrl(url) {
- let executable;
- let args;
- const testExecutable = process.env.NODE_ENV === "test"
- ? process.env.ECC_ITO_BROWSER_EXECUTABLE
- : null;
-
- if (testExecutable) {
- if (process.platform === "win32" && /\.(?:bat|cmd)$/i.test(testExecutable)) {
- executable = process.env.ComSpec || "cmd.exe";
- args = ["/d", "/s", "/c", testExecutable, url];
- } else {
- executable = testExecutable;
- args = [url];
- }
- } else if (process.platform === "darwin") {
- executable = "open";
- args = [url];
- } else if (process.platform === "win32") {
- executable = "cmd.exe";
- args = ["/d", "/s", "/c", "start", "", url];
- } else {
- executable = "xdg-open";
- args = [url];
+ const jsonIndexes = args
+ .map((value, index) => (value === "--json" ? index : -1))
+ .filter((index) => index >= 0);
+ if (jsonIndexes.length > 1) {
+ throw new Error("--json may only be provided once");
+ }
+ const withoutJson = args.filter((value) => value !== "--json");
+ const command = withoutJson.shift();
+ if (!SUPPORTED_COMMANDS.includes(command)) {
+ throw new Error(
+ `Unsupported Itô command "${command || "(missing)"}"; ECC permits only auth, find, and status.`
+ );
}
- const result = spawnSync(executable, args, {
- env: { ...createSafeItoEnvironment(process.env) },
- stdio: "ignore",
- windowsHide: true,
- shell: false,
- });
- return !result.error && result.status === 0;
-}
-
-function createHandoff(options, openUrl = defaultOpenUrl) {
- const shouldOpen = !options.dryRun && !options.noOpen;
- const opened = shouldOpen ? openUrl(DESK_URL) : false;
- const intent = Object.freeze({
- accelerator: options.accelerator,
- count: options.count,
- hours: options.hours,
- });
-
- return createEnvelope({
- success: true,
- state: "manual_handoff",
- data: Object.freeze({
- authenticated: null,
- dryRun: options.dryRun,
- opened,
- intent,
- provenance: Object.freeze({
- source: "ecc-cli",
- command: "ecc ito rent",
- }),
- authority: Object.freeze({
- environment: "sandbox",
- readOnly: true,
- liveRfq: false,
- procurementMutation: false,
- quoteAcceptance: false,
- fundsApproval: false,
- orderCreation: false,
- outreach: false,
- }),
- handoff: Object.freeze({
- transport: "manual_copy",
- destination: "ito-desk",
- acceptedByIto: false,
- signInMayBeRequired: true,
- message: buildHandoffMessage(intent),
- limitation: "Itô /desk currently exposes no supported structured ECC intake or deep-link contract.",
- }),
- approvalGate: 'Stop before "Pay & buy".',
- priceQuote: null,
- orderId: null,
- }),
- error: null,
+ return Object.freeze({
+ help: false,
+ invocationArgs: Object.freeze([
+ ...(jsonIndexes.length === 1 ? ["--json"] : []),
+ command,
+ ...withoutJson,
+ ]),
});
}
-function renderText(payload) {
- const { data } = payload;
- const browserState = data.dryRun
- ? "Dry-run: browser not opened."
- : data.opened
- ? "Opened the Itô desk; sign-in may be required."
- : "Browser not opened; sign-in may be required at the Itô desk.";
- return [
- "ECC × Itô sandbox compute handoff",
- "",
- browserState,
- `Desk: ${payload.links.desk}`,
- "Transport: manual copy; Itô has not accepted this intent.",
- `Message: ${data.handoff.message}`,
- `Limitation: ${data.handoff.limitation}`,
- `Approval gate: ${data.approvalGate}`,
- "",
- "ECC does not file an RFQ, request or accept a quote, use credentials, approve funds, create an order, or contact a counterparty.",
- ].join("\n");
+function resolveItoExecutable(environment = process.env) {
+ const configured = environment[EXECUTABLE_OVERRIDE]?.trim();
+ if (!configured) {
+ throw new Error([
+ "The canonical ito-compute-cli is unpublished and ECC will not resolve",
+ `a credential-bearing "ito" executable from PATH. Build it from`,
+ `${CANONICAL_REPOSITORY.replace(/\.git$/, "")}/${CANONICAL_PACKAGE_PATH},`,
+ "run npm ci and npm run check, then set",
+ `${EXECUTABLE_OVERRIDE} to the explicit absolute dist/bin/ito.js path.`,
+ ].join(" "));
+ }
+
+ if (!path.isAbsolute(configured)) {
+ throw new Error(
+ `${EXECUTABLE_OVERRIDE} must be an absolute path explicitly configured by the operator.`
+ );
+ }
+ return assertUsableExecutable(configured);
}
-function main(argv = process.argv.slice(2), dependencies = {}) {
- let parsed;
+function assertUsableExecutable(candidate) {
+ let canonicalCandidate;
try {
- parsed = parseArgs(argv);
+ canonicalCandidate = fs.realpathSync.native(candidate);
+ } catch {
+ throw new Error(
+ `${EXECUTABLE_OVERRIDE} does not point to a readable local Itô CLI file.`
+ );
+ }
+ if (!isUsableExecutable(canonicalCandidate)) {
+ throw new Error(
+ `${EXECUTABLE_OVERRIDE} does not point to a readable local Itô CLI file.`
+ );
+ }
+ return canonicalCandidate;
+}
+
+function isUsableExecutable(candidate) {
+ try {
+ const info = fs.statSync(candidate);
+ if (!info.isFile()) return false;
+ if (process.platform !== "win32" && path.extname(candidate) !== ".js") {
+ fs.accessSync(candidate, fs.constants.X_OK);
+ } else {
+ fs.accessSync(candidate, fs.constants.R_OK);
+ }
+ return true;
+ } catch {
+ return false;
+ }
+}
+
+function buildInvocation(executable, args) {
+ if (path.extname(executable).toLowerCase() === ".js") {
+ return Object.freeze({
+ executable: process.execPath,
+ args: Object.freeze([executable, ...args]),
+ });
+ }
+ if (
+ process.platform === "win32"
+ && /\.(?:bat|cmd|ps1)$/i.test(executable)
+ ) {
+ throw new Error(
+ `Refusing to invoke the Itô CLI through a shell shim. Set ${EXECUTABLE_OVERRIDE} to the absolute dist/bin/ito.js path.`
+ );
+ }
+ return Object.freeze({ executable, args: Object.freeze([...args]) });
+}
+
+function invokeIto(executable, args, environment = process.env) {
+ const invocation = buildInvocation(executable, args);
+ const result = spawnSync(invocation.executable, invocation.args, {
+ cwd: process.cwd(),
+ encoding: "utf8",
+ env: {
+ ...createSafeItoEnvironment(environment, { includeItoRuntime: true }),
+ },
+ maxBuffer: MAX_OUTPUT_BYTES,
+ shell: false,
+ windowsHide: true,
+ });
+
+ if (result.stdout) process.stdout.write(result.stdout);
+ if (result.stderr) process.stderr.write(result.stderr);
+ if (result.error) {
+ throw new Error(`The local Itô CLI could not be started: ${result.error.message}`);
+ }
+ if (typeof result.status === "number") return result.status;
+ if (result.signal) {
+ throw new Error(`The local Itô CLI terminated by signal ${result.signal}.`);
+ }
+ return 1;
+}
+
+function main(argv = process.argv.slice(2), environment = process.env) {
+ try {
+ const parsed = parseArgs(argv, environment);
+ if (parsed.help) {
+ showHelp();
+ return 0;
+ }
+ const executable = resolveItoExecutable(environment);
+ return invokeIto(executable, parsed.invocationArgs, environment);
} catch (error) {
- const payload = createInvalidEnvelope(error.message);
- if (argv.includes("--json")) console.log(JSON.stringify(payload, null, 2));
- else console.error(`Error: ${error.message}`);
+ console.error(`Error: ${error.message}`);
return 1;
}
-
- if (parsed.help) {
- showHelp();
- return 0;
- }
-
- const payload = createHandoff(parsed.options, dependencies.openUrl);
- if (parsed.options.json) console.log(JSON.stringify(payload, null, 2));
- else console.log(renderText(payload));
- return 0;
}
if (require.main === module) {
@@ -309,13 +213,13 @@ if (require.main === module) {
}
module.exports = Object.freeze({
- DESK_URL,
- SCHEMA_VERSION,
- buildHandoffMessage,
- createHandoff,
- createInvalidEnvelope,
+ CANONICAL_PACKAGE_PATH,
+ CANONICAL_REPOSITORY,
+ EXECUTABLE_OVERRIDE,
+ SUPPORTED_COMMANDS,
+ buildInvocation,
+ invokeIto,
main,
- parseAccelerator,
parseArgs,
- renderText,
+ resolveItoExecutable,
});
diff --git a/scripts/lib/compute-sponsor.js b/scripts/lib/compute-sponsor.js
index a5235485c..98b1951ba 100644
--- a/scripts/lib/compute-sponsor.js
+++ b/scripts/lib/compute-sponsor.js
@@ -6,8 +6,11 @@ function getComputeSponsorCopy() {
return "Run or self-host any open-source model. Itô is ECC's preferred compute sponsor: "
+ 'open its dashboard to sign in and rent or manage GPUs at '
+ ITO_COMPUTE_URL
- + '. Any GPU provider works. ECC only provides this link; it does not provision '
- + 'compute or serving. Managed inference through Itô is not live yet.';
+ + '. Any GPU provider works. This sponsorship link is passive: it does not invoke '
+ + 'an RFQ, reserve capacity, provision compute, or configure serving. Separately, '
+ + 'the opt-in "ecc ito find" bridge invokes the explicitly configured canonical '
+ + 'Itô CLI and submits a live authenticated RFQ; it does not reserve capacity. '
+ + 'Managed inference through Itô is not live yet.';
}
module.exports = Object.freeze({
diff --git a/scripts/lib/ito-environment.js b/scripts/lib/ito-environment.js
index 3be2f5be2..d0afa8653 100644
--- a/scripts/lib/ito-environment.js
+++ b/scripts/lib/ito-environment.js
@@ -23,6 +23,18 @@ const SYSTEM_ENVIRONMENT_KEYS = Object.freeze([
"XDG_RUNTIME_DIR",
]);
+const ITO_RUNTIME_ENVIRONMENT_KEYS = Object.freeze([
+ "ITO_API_KEY",
+ "ITO_API_URL",
+ "ITO_INVENTORY_URL",
+]);
+
+const ECC_ITO_CONTROL_KEYS = Object.freeze([
+ "ECC_DRY_RUN",
+ "ECC_ITO_CLI_EXECUTABLE",
+ "NODE_ENV",
+]);
+
function copyDefined(source, target, key) {
if (typeof source[key] === "string") {
target[key] = source[key];
@@ -38,11 +50,15 @@ function createSafeItoEnvironment(source = process.env, options = {}) {
if (key.startsWith("LC_")) copyDefined(source, safe, key);
}
+ if (options.includeItoRuntime) {
+ for (const key of ITO_RUNTIME_ENVIRONMENT_KEYS) {
+ copyDefined(source, safe, key);
+ }
+ }
+
if (options.includeControls) {
- copyDefined(source, safe, "ECC_DRY_RUN");
- copyDefined(source, safe, "NODE_ENV");
- if (source.NODE_ENV === "test") {
- copyDefined(source, safe, "ECC_ITO_BROWSER_EXECUTABLE");
+ for (const key of ECC_ITO_CONTROL_KEYS) {
+ copyDefined(source, safe, key);
}
}
@@ -50,6 +66,8 @@ function createSafeItoEnvironment(source = process.env, options = {}) {
}
module.exports = Object.freeze({
+ ECC_ITO_CONTROL_KEYS,
+ ITO_RUNTIME_ENVIRONMENT_KEYS,
SYSTEM_ENVIRONMENT_KEYS,
createSafeItoEnvironment,
});
diff --git a/skills/ito-compute/SKILL.md b/skills/ito-compute/SKILL.md
new file mode 100644
index 000000000..11181ad14
--- /dev/null
+++ b/skills/ito-compute/SKILL.md
@@ -0,0 +1,103 @@
+---
+name: ito-compute
+description: Query live GPU inventory, submit an authenticated Itô fixed-rate RFQ, and inspect RFQ or procurement status through the separately installed canonical CLI or its exact MCP tools. Use when a user asks to find H100/H200 capacity, request a fixed compute rate, or check Itô compute status.
+metadata:
+ origin: ECC
+---
+
+# Itô Compute
+
+Use the canonical Itô compute CLI or MCP server. ECC does not implement a
+parallel client, browser handoff, local simulation, reservation, workload
+runner, or inference server.
+
+## Install the canonical local package
+
+`ito-compute-cli` is currently unpublished. Build it from its canonical
+repository instead of using `npx`, `npm exec`, or an unverified package:
+
+```sh
+git clone https://github.com/Ito-Markets/ito-cloud-runtime.git
+cd ito-cloud-runtime/cli/ito-compute-cli
+npm ci
+npm run check
+```
+
+Set `ECC_ITO_CLI_EXECUTABLE` to the explicit absolute built entry:
+
+```text
+/absolute/path/to/ito-cloud-runtime/cli/ito-compute-cli/dist/bin/ito.js
+```
+
+ECC never discovers this credential-bearing client through `PATH`.
+Inject `ITO_API_KEY` through 1Password or the launching process environment.
+Never put it in arguments, tracked files, MCP results, logs, or chat.
+
+## CLI workflow
+
+1. Run `ecc ito auth` before the first operation.
+2. Before `ecc ito find`, obtain explicit buyer authority to submit an RFQ.
+ - Require `gpu`, `count`, whole `days`, `max-rate`, `nodes`,
+ `gpus-per-node`, `storage-tb`, `start-window`, `form-factor`,
+ `contract-type`, `fabric`, `region`, and the split-fill decision.
+ - Require `count == nodes * gpus-per-node`; never derive topology.
+ - Use `any` only when the buyer explicitly accepts any fabric or region.
+ - Omitted `--allow-split` means false.
+3. Run the live RFQ command:
+
+ ```sh
+ ecc ito find \
+ --gpu h200 \
+ --count 8 \
+ --nodes 1 \
+ --gpus-per-node 8 \
+ --days 30 \
+ --storage-tb 1 \
+ --start-window 2099-08-15 \
+ --max-rate 3.00 \
+ --form-factor bare_metal \
+ --contract-type reservation \
+ --fabric infiniband \
+ --region us-east-1
+ ```
+
+4. Run `ecc ito status` to inspect RFQs and procurement orders.
+ After an ambiguous transport failure, check status before repeating `find`.
+
+Inventory prices are indicative. An RFQ is not reserved capacity. Treat a rate
+as fixed only when the canonical result contains a non-null firm quote.
+
+## MCP workflow
+
+Build the canonical package, then configure the stdio server with an absolute
+path:
+
+```json
+{
+ "mcpServers": {
+ "ito-compute": {
+ "command": "node",
+ "args": [
+ "/absolute/path/to/ito-cloud-runtime/cli/ito-compute-cli/dist/bin/ito-mcp.js"
+ ]
+ }
+ }
+}
+```
+
+The server exposes only:
+
+- `ito_auth`
+- `ito_find`
+- `ito_status`
+
+Use `ito_auth`, gather explicit buyer authority and every hard constraint, call
+`ito_find`, then poll with `ito_status` when needed.
+
+## Unsupported operations
+
+The supported client surface cannot lock quotes, reserve capacity, execute
+workloads, qualify nodes through ECC, or serve inference. Do not invent
+additional tools or a purchase path. Do not substitute a browser or fixture
+when the local CLI is missing or a live operation fails. Report the missing
+capability and stop.
diff --git a/src/llm/cli/selector.py b/src/llm/cli/selector.py
index 7a5777461..3430bb2d5 100644
--- a/src/llm/cli/selector.py
+++ b/src/llm/cli/selector.py
@@ -41,8 +41,11 @@ def print_self_host_compute_notice(provider: str) -> None:
"https://compute.itomarkets.com"
)
print(
- "Any GPU provider works. ECC only links to the Itô dashboard; it does not "
- "provision compute or serving. Managed inference through Itô is not live yet."
+ "Any GPU provider works. This sponsorship link is passive: it does not invoke "
+ "an RFQ, reserve capacity, provision compute, or configure serving. Separately, "
+ 'the opt-in "ecc ito find" bridge invokes the explicitly configured canonical '
+ "Itô CLI and submits a live authenticated RFQ; it does not reserve capacity. "
+ "Managed inference through Itô is not live yet."
)
diff --git a/tests/ci/ito-compute-skill.test.js b/tests/ci/ito-compute-skill.test.js
new file mode 100644
index 000000000..4d4d283a9
--- /dev/null
+++ b/tests/ci/ito-compute-skill.test.js
@@ -0,0 +1,115 @@
+/**
+ * Contract tests for the installable Itô compute skill and MCP documentation.
+ */
+
+const assert = require("assert");
+const fs = require("fs");
+const path = require("path");
+
+const REPO_ROOT = path.join(__dirname, "..", "..");
+
+function read(relativePath) {
+ return fs.readFileSync(path.join(REPO_ROOT, relativePath), "utf8");
+}
+
+function readJson(relativePath) {
+ return JSON.parse(read(relativePath));
+}
+
+function runTest(name, fn) {
+ try {
+ fn();
+ console.log(` ✓ ${name}`);
+ return true;
+ } catch (error) {
+ console.log(` ✗ ${name}`);
+ console.error(` ${error.message}`);
+ return false;
+ }
+}
+
+function main() {
+ console.log("\n=== Testing Itô compute skill surface ===\n");
+
+ const tests = [
+ ["documents only the real CLI commands and MCP tools", () => {
+ const skill = read("skills/ito-compute/SKILL.md");
+ for (const command of ["ecc ito auth", "ecc ito find", "ecc ito status"]) {
+ assert.match(skill, new RegExp(command.replace(" ", "\\s+")));
+ }
+ assert.doesNotMatch(skill, /^\s*ito (?:auth|find|status)\b/m);
+ for (const tool of ["ito_auth", "ito_find", "ito_status"]) {
+ assert.match(skill, new RegExp(`\\b${tool}\\b`));
+ }
+ assert.doesNotMatch(
+ skill,
+ /ito_lock|ito_run|ITO_CLI_DEMO|paper mode|simulated|live on the registry|publishing soon/i
+ );
+ assert.match(skill, /unpublished/i);
+ assert.match(skill, /Ito-Markets\/ito-cloud-runtime/);
+ assert.match(skill, /cli\/ito-compute-cli/);
+ assert.match(skill, /npm run check/);
+ assert.match(skill, /ECC_ITO_CLI_EXECUTABLE/);
+ assert.match(skill, /explicit absolute built entry/);
+ assert.match(skill, /never discovers[^\n]*through `PATH`/);
+ assert.doesNotMatch(skill, /npm link/);
+ }],
+ ["registers one opt-in install module and capability", () => {
+ const modules = readJson("manifests/install-modules.json").modules;
+ const module = modules.find((candidate) => candidate.id === "ito-compute");
+ assert.ok(module, "ito-compute install module is missing");
+ assert.deepStrictEqual(module.paths, ["skills/ito-compute"]);
+ assert.deepStrictEqual(module.dependencies, ["platform-configs"]);
+ assert.strictEqual(module.defaultInstall, false);
+ assert.strictEqual(module.stability, "beta");
+ for (const target of ["claude", "codex", "opencode", "hermes", "kimi"]) {
+ assert.ok(module.targets.includes(target), `${target} target is missing`);
+ }
+
+ const components = readJson("manifests/install-components.json").components;
+ assert.deepStrictEqual(
+ components.find((candidate) => candidate.id === "capability:ito-compute"),
+ {
+ id: "capability:ito-compute",
+ family: "capability",
+ description: "Authenticated Itô GPU inventory, RFQ, and status workflows through the separately installed canonical CLI.",
+ modules: ["ito-compute"],
+ }
+ );
+ const profiles = readJson("manifests/install-profiles.json").profiles;
+ assert.ok(profiles.full.modules.includes("ito-compute"));
+ }],
+ ["publishes the skill but never bundles the Itô CLI", () => {
+ const packageJson = readJson("package.json");
+ assert.ok(packageJson.files.includes("skills/ito-compute/"));
+ assert.ok(!packageJson.dependencies?.["ito-compute-cli"]);
+ assert.ok(!packageJson.optionalDependencies?.["ito-compute-cli"]);
+ assert.ok(!packageJson.bin?.ito);
+ }],
+ ["offers an opt-in local MCP template with the exact real tool boundary", () => {
+ const mcpConfig = readJson("mcp-configs/mcp-servers.json");
+ const server = mcpConfig.mcpServers["ito-compute"];
+ assert.ok(server, "ito-compute MCP template is missing");
+ assert.strictEqual(server.command, "node");
+ assert.deepStrictEqual(server.args, [
+ "/absolute/path/to/ito-cloud-runtime/cli/ito-compute-cli/dist/bin/ito-mcp.js",
+ ]);
+ assert.doesNotMatch(JSON.stringify(server), /npx|ito_lock|ito_run|paper|simulat/i);
+ assert.match(server.description, /ito_auth, ito_find, and ito_status/);
+ assert.match(server.description, /unpublished/i);
+ }],
+ ];
+
+ let passed = 0;
+ let failed = 0;
+ for (const [name, fn] of tests) {
+ if (runTest(name, fn)) passed += 1;
+ else failed += 1;
+ }
+
+ console.log(`\nPassed: ${passed}`);
+ console.log(`Failed: ${failed}`);
+ process.exit(failed > 0 ? 1 : 0);
+}
+
+main();
diff --git a/tests/scripts/install-apply.test.js b/tests/scripts/install-apply.test.js
index dc7b6408c..9cc17d903 100644
--- a/tests/scripts/install-apply.test.js
+++ b/tests/scripts/install-apply.test.js
@@ -39,6 +39,7 @@ function run(args = [], options = {}) {
env,
encoding: 'utf8',
stdio: ['pipe', 'pipe', 'pipe'],
+ maxBuffer: 4 * 1024 * 1024,
timeout: options.timeout || DEFAULT_INSTALL_APPLY_TIMEOUT_MS,
});
diff --git a/tests/scripts/ito-cli-bridge.test.js b/tests/scripts/ito-cli-bridge.test.js
new file mode 100644
index 000000000..d170def00
--- /dev/null
+++ b/tests/scripts/ito-cli-bridge.test.js
@@ -0,0 +1,293 @@
+/**
+ * End-to-end contract tests for ECC's real local Itô CLI bridge.
+ *
+ * The executable used here is a process-boundary probe. It never contacts an
+ * Itô API, submits an RFQ, opens a browser, or reaches a GPU node.
+ */
+
+const assert = require("assert");
+const fs = require("fs");
+const os = require("os");
+const path = require("path");
+const { spawnSync } = require("child_process");
+
+const REPO_ROOT = path.join(__dirname, "..", "..");
+const ECC_SCRIPT = path.join(REPO_ROOT, "scripts", "ecc.js");
+const CANONICAL_PACKAGE = "Ito-Markets/ito-cloud-runtime/cli/ito-compute-cli";
+
+function runCli(args, environment = {}) {
+ return spawnSync(process.execPath, [ECC_SCRIPT, ...args], {
+ cwd: REPO_ROOT,
+ encoding: "utf8",
+ env: {
+ ...process.env,
+ NODE_ENV: "test",
+ ...environment,
+ },
+ });
+}
+
+function makeItoProbe(exitCode = 0) {
+ const directory = fs.mkdtempSync(path.join(os.tmpdir(), "ecc-ito-cli-"));
+ const log = path.join(directory, "invocation.json");
+ const script = path.join(directory, "ito-probe.js");
+ const executable = script;
+ fs.writeFileSync(
+ script,
+ [
+ `#!${process.execPath}`,
+ '"use strict";',
+ 'const fs = require("fs");',
+ `fs.writeFileSync(${JSON.stringify(log)}, JSON.stringify({ argv: process.argv.slice(2), env: process.env }));`,
+ 'process.stdout.write(`ito-probe:${process.argv.slice(2).join("|")}\\n`);',
+ 'process.stderr.write("ito-probe-stderr\\n");',
+ `process.exit(${exitCode});`,
+ "",
+ ].join("\n")
+ );
+ if (process.platform !== "win32") {
+ fs.chmodSync(script, 0o755);
+ }
+ return Object.freeze({ directory, executable, log });
+}
+
+function readInvocation(probe) {
+ return JSON.parse(fs.readFileSync(probe.log, "utf8"));
+}
+
+function runTest(name, fn) {
+ try {
+ fn();
+ console.log(` ✓ ${name}`);
+ return true;
+ } catch (error) {
+ console.log(` ✗ ${name}`);
+ console.error(` ${error.message}`);
+ return false;
+ }
+}
+
+function main() {
+ console.log("\n=== Testing ECC × Itô real CLI bridge ===\n");
+
+ const tests = [
+ ["forwards only auth, find, and status to an explicit local executable", () => {
+ for (const command of ["auth", "find", "status"]) {
+ const probe = makeItoProbe();
+ try {
+ const result = runCli(["ito", command], {
+ ECC_ITO_CLI_EXECUTABLE: probe.executable,
+ });
+ assert.strictEqual(result.status, 0, result.stderr);
+ assert.deepStrictEqual(readInvocation(probe).argv, [command]);
+ assert.match(result.stdout, new RegExp(`ito-probe:${command}`));
+ } finally {
+ fs.rmSync(probe.directory, { recursive: true, force: true });
+ }
+ }
+ }],
+ ["normalizes JSON and forwards every RFQ constraint without interpretation", () => {
+ const probe = makeItoProbe();
+ try {
+ const args = [
+ "ito",
+ "find",
+ "--gpu", "h200",
+ "--count", "8",
+ "--nodes", "1",
+ "--gpus-per-node", "8",
+ "--days", "30",
+ "--storage-tb", "1",
+ "--start-window", "2099-08-15",
+ "--max-rate", "3.00",
+ "--form-factor", "bare_metal",
+ "--contract-type", "reservation",
+ "--fabric", "infiniband",
+ "--region", "us-east-1",
+ "--json",
+ ];
+ const result = runCli(args, {
+ ECC_ITO_CLI_EXECUTABLE: probe.executable,
+ });
+ assert.strictEqual(result.status, 0, result.stderr);
+ assert.deepStrictEqual(readInvocation(probe).argv, [
+ "--json",
+ ...args.slice(1, -1),
+ ]);
+ } finally {
+ fs.rmSync(probe.directory, { recursive: true, force: true });
+ }
+ }],
+ ["passes only the required Itô runtime settings across the process boundary", () => {
+ const probe = makeItoProbe();
+ try {
+ const result = runCli(["ito", "auth"], {
+ ECC_ITO_CLI_EXECUTABLE: probe.executable,
+ ITO_API_KEY: "ito_test_key",
+ ITO_API_URL: "https://compute.example.test",
+ ITO_INVENTORY_URL: "https://edge.example.test",
+ AWS_SECRET_ACCESS_KEY: "must-not-cross",
+ OPENAI_API_KEY: "must-not-cross",
+ TEST_PASSWORD: "must-not-cross",
+ });
+ assert.strictEqual(result.status, 0, result.stderr);
+ const childEnvironment = readInvocation(probe).env;
+ assert.strictEqual(childEnvironment.ITO_API_KEY, "ito_test_key");
+ assert.strictEqual(childEnvironment.ITO_API_URL, "https://compute.example.test");
+ assert.strictEqual(childEnvironment.ITO_INVENTORY_URL, "https://edge.example.test");
+ assert.strictEqual(childEnvironment.AWS_SECRET_ACCESS_KEY, undefined);
+ assert.strictEqual(childEnvironment.OPENAI_API_KEY, undefined);
+ assert.strictEqual(childEnvironment.TEST_PASSWORD, undefined);
+ assert.strictEqual(childEnvironment.ECC_ITO_CLI_EXECUTABLE, undefined);
+ } finally {
+ fs.rmSync(probe.directory, { recursive: true, force: true });
+ }
+ }],
+ ["rejects unsupported, browser, simulated, and node operations before spawning", () => {
+ for (const command of ["rent", "lock", "run", "inference", "evals", "mcp"]) {
+ const probe = makeItoProbe();
+ try {
+ const result = runCli(["ito", command], {
+ ECC_ITO_CLI_EXECUTABLE: probe.executable,
+ });
+ assert.notStrictEqual(result.status, 0, command);
+ assert.match(result.stderr, /only auth, find, and status/i);
+ assert.ok(!fs.existsSync(probe.log), `${command} must not spawn the Itô CLI`);
+ } finally {
+ fs.rmSync(probe.directory, { recursive: true, force: true });
+ }
+ }
+ }],
+ ["fails closed rather than simulating a dry-run RFQ", () => {
+ const probe = makeItoProbe();
+ try {
+ const result = runCli(["--dry-run", "ito", "find"], {
+ ECC_ITO_CLI_EXECUTABLE: probe.executable,
+ });
+ assert.notStrictEqual(result.status, 0);
+ assert.match(result.stderr, /no paper or dry-run success mode/i);
+ assert.ok(!fs.existsSync(probe.log));
+ } finally {
+ fs.rmSync(probe.directory, { recursive: true, force: true });
+ }
+ }],
+ ["fails closed with exact local install guidance when the explicit CLI is absent", () => {
+ const emptyPath = fs.mkdtempSync(path.join(os.tmpdir(), "ecc-empty-path-"));
+ try {
+ const result = runCli(["ito", "status"], {
+ ECC_ITO_CLI_EXECUTABLE: "",
+ PATH: emptyPath,
+ });
+ assert.notStrictEqual(result.status, 0);
+ assert.match(result.stderr, /canonical ito-compute-cli is unpublished/i);
+ assert.match(result.stderr, new RegExp(CANONICAL_PACKAGE.replaceAll("/", "\\/")));
+ assert.match(result.stderr, /npm run check/);
+ assert.match(result.stderr, /ECC_ITO_CLI_EXECUTABLE/);
+ assert.match(result.stderr, /explicit absolute/i);
+ assert.match(result.stderr, /unpublished/i);
+ assert.doesNotMatch(result.stderr, /npx|npm exec|npm link|install -g/i);
+ } finally {
+ fs.rmSync(emptyPath, { recursive: true, force: true });
+ }
+ }],
+ ["never forwards Itô credentials to an unverified PATH collision", () => {
+ const collisionDirectory = fs.mkdtempSync(
+ path.join(os.tmpdir(), "ecc-hostile-ito-path-")
+ );
+ const stolenEnvironment = path.join(collisionDirectory, "stolen.json");
+ const executable = path.join(
+ collisionDirectory,
+ process.platform === "win32" ? "ito.exe" : "ito"
+ );
+ try {
+ fs.writeFileSync(
+ executable,
+ [
+ `#!${process.execPath}`,
+ '"use strict";',
+ 'const fs = require("fs");',
+ `fs.writeFileSync(${JSON.stringify(stolenEnvironment)}, JSON.stringify(process.env));`,
+ "",
+ ].join("\n")
+ );
+ if (process.platform !== "win32") {
+ fs.chmodSync(executable, 0o755);
+ }
+
+ const result = runCli(["ito", "auth"], {
+ ECC_ITO_CLI_EXECUTABLE: "",
+ ITO_API_KEY: "must-never-reach-path-collision",
+ PATH: collisionDirectory,
+ });
+
+ assert.notStrictEqual(result.status, 0);
+ assert.match(result.stderr, /explicit absolute|ECC_ITO_CLI_EXECUTABLE/i);
+ assert.ok(
+ !fs.existsSync(stolenEnvironment),
+ "an unverified PATH executable must never receive the Itô credential"
+ );
+ } finally {
+ fs.rmSync(collisionDirectory, { recursive: true, force: true });
+ }
+ }],
+ ["rejects a relative executable override instead of searching or guessing", () => {
+ const result = runCli(["ito", "status"], {
+ ECC_ITO_CLI_EXECUTABLE: "ito",
+ });
+ assert.notStrictEqual(result.status, 0);
+ assert.match(result.stderr, /must be an absolute path/i);
+ }],
+ ["preserves the real CLI exit code and output without a success wrapper", () => {
+ const probe = makeItoProbe(7);
+ try {
+ const result = runCli(["ito", "status"], {
+ ECC_ITO_CLI_EXECUTABLE: probe.executable,
+ });
+ assert.strictEqual(result.status, 7);
+ assert.match(result.stdout, /ito-probe:status/);
+ assert.match(result.stderr, /ito-probe-stderr/);
+ assert.doesNotMatch(result.stdout, /manual_handoff|simulated|paper/i);
+ } finally {
+ fs.rmSync(probe.directory, { recursive: true, force: true });
+ }
+ }],
+ ["help exposes the truthful CLI and MCP surface without a browser path", () => {
+ const probe = makeItoProbe();
+ try {
+ const result = runCli(["ito", "--help"], {
+ ECC_ITO_CLI_EXECUTABLE: probe.executable,
+ });
+ assert.strictEqual(result.status, 0, result.stderr);
+ assert.match(result.stdout, /ecc ito auth/);
+ assert.match(result.stdout, /ecc ito find/);
+ assert.match(result.stdout, /ecc ito status/);
+ assert.match(result.stdout, /ito_auth/);
+ assert.match(result.stdout, /ito_find/);
+ assert.match(result.stdout, /ito_status/);
+ assert.match(result.stdout, new RegExp(CANONICAL_PACKAGE.replaceAll("/", "\\/")));
+ assert.match(result.stdout, /unpublished/i);
+ assert.match(result.stdout, /never discovers[^\n]*through PATH/i);
+ assert.doesNotMatch(
+ result.stdout,
+ /manual copy|open(?:s)? (?:a )?browser|ito_lock|ito_run|npm link|paper|simulat/i
+ );
+ assert.ok(!fs.existsSync(probe.log));
+ } finally {
+ fs.rmSync(probe.directory, { recursive: true, force: true });
+ }
+ }],
+ ];
+
+ let passed = 0;
+ let failed = 0;
+ for (const [name, fn] of tests) {
+ if (runTest(name, fn)) passed += 1;
+ else failed += 1;
+ }
+
+ console.log(`\nPassed: ${passed}`);
+ console.log(`Failed: ${failed}`);
+ process.exit(failed > 0 ? 1 : 0);
+}
+
+main();
diff --git a/tests/scripts/ito-compute-sponsor.test.js b/tests/scripts/ito-compute-sponsor.test.js
index ea0ca72ff..fe878afa5 100644
--- a/tests/scripts/ito-compute-sponsor.test.js
+++ b/tests/scripts/ito-compute-sponsor.test.js
@@ -61,7 +61,13 @@ function assertHonestComputeCopy(content) {
assert.match(content, /preferred compute sponsor/i);
assert.match(content, /run or self-host any open-source model/i);
assert.match(content, /any GPU provider/i);
+ assert.match(content, /sponsorship link is passive/i);
+ assert.match(content, /ecc ito find/i);
+ assert.match(content, /explicitly configured canonical Itô CLI/i);
+ assert.match(content, /submits a live authenticated RFQ/i);
+ assert.match(content, /does not reserve capacity/i);
assert.match(content, /managed inference[^\n.]*not live/i);
+ assert.doesNotMatch(content, /ECC only (?:links|provides this link)/i);
}
function main() {
@@ -90,7 +96,7 @@ function main() {
assertHonestComputeCopy(readme);
assert.match(
readme,
- /custom API endpoint or model gateway[\s\S]*Run or self-host any open-source model behind that gateway[\s\S]*ECC only links to the Itô dashboard/
+ /custom API endpoint or model gateway[\s\S]*Run or self-host any open-source model behind that gateway[\s\S]*sponsorship link is passive/
);
const sponsorMark = read('assets/images/sponsors/ito.svg');
assert.match(sponsorMark, / {
+ ['sponsor roster keeps Itô and Moonshot distinct from node tooling', () => {
const sponsors = read('SPONSORS.md');
assert.ok(sponsors.includes('[**Itô**]'));
assert.ok(sponsors.includes('assets/images/sponsors/ito.svg'));
+ assert.ok(sponsors.includes('[**Moonshot AI**]'));
+ assert.ok(sponsors.includes('assets/images/sponsors/moonshot.svg'));
+ assert.doesNotMatch(sponsors, /sixtytwo|sixty.?two/i);
assertExactComputeRoute(sponsors);
}],
['inference guide distinguishes rental compute from managed serving', () => {
@@ -113,11 +122,17 @@ function main() {
assertHonestComputeCopy(read('.claude-plugin/README.md'));
assertHonestComputeCopy(read('.kimi/README.md'));
}],
- ['Phase 2 plan keeps its thesis and release framing generic', () => {
- const plan = read('docs/design/ecc-ito-compute-integration.md');
- assert.match(plan, /-> any open-source model/);
- assert.doesNotMatch(plan, /public Kimi|Moonshot|video and sponsorship/i);
- assert.match(plan, /Status: \*\*Proposed/);
+ ['integration record keeps the thesis and real client boundary honest', () => {
+ const record = read('docs/design/ecc-ito-compute-integration.md');
+ assert.match(record, /-> any open-source model/);
+ assert.doesNotMatch(record, /public Kimi|Moonshot|video and sponsorship/i);
+ assert.match(record, /Status: \*\*Implemented local CLI bridge/i);
+ assert.match(record, /auth`, `find`, and `status/);
+ assert.match(record, /ito_auth`, `ito_find`, and `ito_status/);
+ assert.match(record, /unpublished/i);
+ assert.match(record, /managed inference remains unavailable/i);
+ assert.match(record, /version bump[\s\S]*intentionally deferred/i);
+ assert.doesNotMatch(record, /manual_copy|ito\.compute\.handoff|ecc ito rent/i);
}],
['top-level CLI help exposes the provider-neutral compute route', () => {
const result = spawnSync('node', ['scripts/ecc.js', '--help'], {
@@ -159,7 +174,12 @@ function main() {
assert.ok(packageJson.files.includes('assets/images/sponsors/'));
assertExactComputeRoute(packageJson.scripts.welcome);
assert.match(packageJson.scripts.welcome, /run or self-host any open-source model/i);
+ assert.match(packageJson.scripts.welcome, /sponsorship link is passive/i);
+ assert.match(packageJson.scripts.welcome, /ecc ito find/i);
+ assert.match(packageJson.scripts.welcome, /submits a live authenticated RFQ/i);
+ assert.match(packageJson.scripts.welcome, /does not reserve capacity/i);
assert.ok(fs.existsSync(path.join(REPO_ROOT, 'assets', 'images', 'sponsors', 'ito.svg')));
+ assert.ok(fs.existsSync(path.join(REPO_ROOT, 'assets', 'images', 'sponsors', 'moonshot.svg')));
}],
];
diff --git a/tests/scripts/ito-handoff.test.js b/tests/scripts/ito-handoff.test.js
deleted file mode 100644
index 349ee5386..000000000
--- a/tests/scripts/ito-handoff.test.js
+++ /dev/null
@@ -1,294 +0,0 @@
-/**
- * End-to-end contract tests for ECC's read-only Itô compute handoff.
- */
-
-const assert = require("assert")
-const fs = require("fs")
-const os = require("os")
-const path = require("path")
-const { spawnSync } = require("child_process")
-
-const REPO_ROOT = path.join(__dirname, "..", "..")
-const ECC_SCRIPT = path.join(REPO_ROOT, "scripts", "ecc.js")
-const ITO_SCRIPT = path.join(REPO_ROOT, "scripts", "ito.js")
-const DESK_URL = "https://compute.itomarkets.com/desk"
-
-function runCli(args, options = {}) {
- return spawnSync(process.execPath, [ECC_SCRIPT, ...args], {
- cwd: REPO_ROOT,
- encoding: "utf8",
- env: {
- ...process.env,
- NODE_ENV: "test",
- ...(options.env || {}),
- },
- })
-}
-
-function parseJson(result, expectedStatus = 0) {
- assert.strictEqual(result.status, expectedStatus, result.stderr)
- return JSON.parse(result.stdout)
-}
-
-function runTest(name, fn) {
- try {
- fn()
- console.log(` ✓ ${name}`)
- return true
- } catch (error) {
- console.log(` ✗ ${name}`)
- console.error(` ${error.message}`)
- return false
- }
-}
-
-function makeBrowserProbe() {
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), "ecc-ito-browser-"))
- const log = path.join(dir, "opened-url.txt")
- const envLog = path.join(dir, "browser-env.txt")
- const executable = path.join(dir, process.platform === "win32" ? "browser-probe.cmd" : "browser-probe")
- if (process.platform === "win32") {
- fs.writeFileSync(executable, `@echo off\r\n"${log}"\r\nset >"${envLog}"\r\n`)
- } else {
- fs.writeFileSync(executable, `#!/bin/sh\nprintf '%s' "$1" > "${log}"\nenv > "${envLog}"\n`)
- fs.chmodSync(executable, 0o755)
- }
- return { dir, envLog, executable, log }
-}
-
-function main() {
- console.log("\n=== Testing ECC × Itô sandbox handoff ===\n")
-
- const tests = [
- ["maps the exact CLI request into a structured sandbox intent", () => {
- const payload = parseJson(runCli([
- "ito",
- "rent",
- "--accelerator", "h100",
- "--count", "1",
- "--hours", "24",
- "--no-open",
- "--json",
- ]))
-
- assert.strictEqual(payload.schemaVersion, "ito.compute.handoff.v1")
- assert.strictEqual(payload.success, true)
- assert.strictEqual(payload.state, "manual_handoff")
- assert.deepStrictEqual(payload.data.intent, {
- accelerator: "h100",
- count: 1,
- hours: 24,
- })
- assert.deepStrictEqual(payload.data.provenance, {
- source: "ecc-cli",
- command: "ecc ito rent",
- })
- assert.strictEqual(payload.data.authority.environment, "sandbox")
- assert.strictEqual(payload.data.authority.readOnly, true)
- assert.strictEqual(payload.data.authority.liveRfq, false)
- assert.strictEqual(payload.data.authority.procurementMutation, false)
- assert.strictEqual(payload.data.authority.quoteAcceptance, false)
- assert.strictEqual(payload.data.authority.fundsApproval, false)
- assert.strictEqual(payload.data.authority.orderCreation, false)
- assert.strictEqual(payload.data.handoff.transport, "manual_copy")
- assert.strictEqual(payload.data.handoff.destination, "ito-desk")
- assert.strictEqual(payload.data.handoff.acceptedByIto, false)
- assert.strictEqual(payload.data.handoff.signInMayBeRequired, true)
- assert.match(payload.data.handoff.message, /1 × H100/)
- assert.match(payload.data.handoff.message, /24 hours/)
- assert.match(payload.data.handoff.message, /ECC CLI/)
- assert.match(payload.data.handoff.message, /sandbox-only/)
- assert.strictEqual(payload.links.desk, DESK_URL)
- assert.strictEqual(payload.data.opened, false)
- assert.strictEqual(payload.data.priceQuote, null)
- assert.strictEqual(payload.data.orderId, null)
- }],
- ["global dry-run emits the same handoff and never opens a browser", () => {
- const probe = makeBrowserProbe()
- try {
- const payload = parseJson(runCli([
- "--dry-run",
- "ito",
- "rent",
- "--accelerator", "h100",
- "--count", "1",
- "--hours", "24",
- "--json",
- ], {
- env: { ECC_ITO_BROWSER_EXECUTABLE: probe.executable },
- }))
-
- assert.strictEqual(payload.data.dryRun, true)
- assert.strictEqual(payload.data.opened, false)
- assert.ok(!fs.existsSync(probe.log), "dry-run must not invoke the browser executable")
- } finally {
- fs.rmSync(probe.dir, { recursive: true, force: true })
- }
- }],
- ["local dry-run is equivalent and rejects an open request", () => {
- const probe = makeBrowserProbe()
- try {
- const payload = parseJson(runCli([
- "ito",
- "rent",
- "--accelerator", "h100",
- "--count", "1",
- "--hours", "24",
- "--dry-run",
- "--json",
- ], {
- env: { ECC_ITO_BROWSER_EXECUTABLE: probe.executable },
- }))
-
- assert.strictEqual(payload.data.dryRun, true)
- assert.strictEqual(payload.data.opened, false)
- assert.ok(!fs.existsSync(probe.log), "local dry-run must not invoke the browser executable")
- } finally {
- fs.rmSync(probe.dir, { recursive: true, force: true })
- }
- }],
- ["browser handoff opens only the allowlisted desk URL without inherited secrets", () => {
- const probe = makeBrowserProbe()
- try {
- const payload = parseJson(runCli([
- "ito",
- "rent",
- "--accelerator", "h100",
- "--count", "1",
- "--hours", "24",
- "--json",
- ], {
- env: {
- ECC_ITO_BROWSER_EXECUTABLE: probe.executable,
- ITO_API_KEY: "parent-api-key-must-not-cross",
- ITO_SERVICE_TOKEN: "parent-token-must-not-cross",
- TEST_PASSWORD: "parent-password-must-not-cross",
- },
- }))
-
- assert.strictEqual(payload.data.opened, true)
- assert.strictEqual(fs.readFileSync(probe.log, "utf8"), DESK_URL)
- assert.strictEqual(payload.links.desk, DESK_URL)
- const childEnvironment = fs.readFileSync(probe.envLog, "utf8")
- assert.doesNotMatch(childEnvironment, /parent-api-key-must-not-cross/)
- assert.doesNotMatch(childEnvironment, /parent-token-must-not-cross/)
- assert.doesNotMatch(childEnvironment, /parent-password-must-not-cross/)
- } finally {
- fs.rmSync(probe.dir, { recursive: true, force: true })
- }
- }],
- ["direct Ito execution strips secrets from the browser child", () => {
- const probe = makeBrowserProbe()
- try {
- const result = spawnSync(process.execPath, [
- ITO_SCRIPT,
- "rent",
- "--accelerator", "h100",
- "--count", "1",
- "--hours", "24",
- "--json",
- ], {
- cwd: REPO_ROOT,
- encoding: "utf8",
- env: {
- ...process.env,
- NODE_ENV: "test",
- ECC_ITO_BROWSER_EXECUTABLE: probe.executable,
- ITO_API_KEY: "direct-api-key-must-not-cross",
- ITO_SERVICE_TOKEN: "direct-token-must-not-cross",
- TEST_PASSWORD: "direct-password-must-not-cross",
- },
- })
- const payload = parseJson(result)
- assert.strictEqual(payload.data.opened, true)
- const childEnvironment = fs.readFileSync(probe.envLog, "utf8")
- assert.doesNotMatch(childEnvironment, /direct-api-key-must-not-cross/)
- assert.doesNotMatch(childEnvironment, /direct-token-must-not-cross/)
- assert.doesNotMatch(childEnvironment, /direct-password-must-not-cross/)
- } finally {
- fs.rmSync(probe.dir, { recursive: true, force: true })
- }
- }],
- ["fails closed on missing, unsupported, duplicate, and out-of-range intent", () => {
- for (const args of [
- ["ito", "rent", "--count", "1", "--hours", "24", "--no-open", "--json"],
- ["ito", "rent", "--accelerator", "a100", "--count", "1", "--hours", "24", "--no-open", "--json"],
- ["ito", "rent", "--accelerator", "h100", "--count", "0", "--hours", "24", "--no-open", "--json"],
- ["ito", "rent", "--accelerator", "h100", "--count", "1", "--hours", "721", "--no-open", "--json"],
- ["ito", "rent", "--accelerator", "h100", "--accelerator", "h100-sxm", "--count", "1", "--hours", "24", "--no-open", "--json"],
- ["ito", "dashboard", "--accelerator", "h100", "--count", "1", "--hours", "24", "--no-open", "--json"],
- ]) {
- const result = runCli(args)
- assert.notStrictEqual(result.status, 0, args.join(" "))
- const payload = JSON.parse(result.stdout)
- assert.strictEqual(payload.success, false)
- assert.strictEqual(payload.state, "invalid_request")
- assert.strictEqual(payload.data, null)
- assert.strictEqual(payload.error.code, "INVALID_ARGUMENT")
- }
- }],
- ["does not inspect credentials or contain a mutating transport", () => {
- const payload = parseJson(runCli([
- "ito",
- "rent",
- "--accelerator", "h100",
- "--count", "1",
- "--hours", "24",
- "--no-open",
- "--json",
- ], {
- env: {
- ITO_API_KEY: "must-not-be-read",
- ITO_SERVICE_TOKEN: "must-not-be-read",
- },
- }))
-
- assert.strictEqual(payload.data.authenticated, null)
- const source = fs.readFileSync(path.join(REPO_ROOT, "scripts", "ito.js"), "utf8")
- assert.doesNotMatch(source, /ITO_API_KEY|ITO_SERVICE_TOKEN|procurement\/orders|authorization/i)
- assert.doesNotMatch(source, /\bfetch\s*\(|https?\.request|child_process\.exec\b/)
- }],
- ["human output stops before the economic boundary", () => {
- const result = runCli([
- "ito",
- "rent",
- "--accelerator", "h100",
- "--count", "1",
- "--hours", "24",
- "--no-open",
- ])
-
- assert.strictEqual(result.status, 0, result.stderr)
- assert.match(result.stdout, /manual copy/i)
- assert.match(result.stdout, /sandbox-only/i)
- assert.match(result.stdout, /sign-in may be required/i)
- assert.doesNotMatch(result.stdout, /signed-in/i)
- assert.match(result.stdout, /does not file an RFQ/i)
- assert.match(result.stdout, /Stop before ["“]Pay & buy["”]/i)
- assert.match(result.stdout, /no supported structured ECC intake/i)
- }],
- ["npm welcome remains POSIX-safe around apostrophes", () => {
- const npmExecutable = process.platform === "win32" ? "npm.cmd" : "npm"
- const result = spawnSync(npmExecutable, ["run", "welcome"], {
- cwd: REPO_ROOT,
- encoding: "utf8",
- shell: process.platform === "win32",
- })
- assert.strictEqual(result.status, 0, result.stderr)
- assert.match(result.stdout, /Itô/)
- }],
- ]
-
- let passed = 0
- let failed = 0
- for (const [name, fn] of tests) {
- if (runTest(name, fn)) passed += 1
- else failed += 1
- }
-
- console.log(`\nPassed: ${passed}`)
- console.log(`Failed: ${failed}`)
- process.exit(failed > 0 ? 1 : 0)
-}
-
-main()
diff --git a/tests/test_selector.py b/tests/test_selector.py
index 5f1441041..af8023bcc 100644
--- a/tests/test_selector.py
+++ b/tests/test_selector.py
@@ -50,6 +50,11 @@ def test_ollama_notice_routes_to_ito_without_claiming_serving(capsys):
assert_exact_compute_route(output)
assert "preferred compute sponsor" in output
assert "Any GPU provider works" in output
+ assert "sponsorship link is passive" in output
+ assert "ecc ito find" in output
+ assert "explicitly configured canonical Itô CLI" in output
+ assert "submits a live authenticated RFQ" in output
+ assert "does not reserve capacity" in output
assert "Managed inference through Itô is not live yet" in output