diff --git a/.claude-plugin/README.md b/.claude-plugin/README.md
index 72c85f7e5..41fd488f4 100644
--- a/.claude-plugin/README.md
+++ b/.claude-plugin/README.md
@@ -15,3 +15,5 @@ export ANTHROPIC_BASE_URL=https://your-gateway.example.com
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.
diff --git a/.kimi/README.md b/.kimi/README.md
index f496f724d..4fb9b72cf 100644
--- a/.kimi/README.md
+++ b/.kimi/README.md
@@ -20,3 +20,7 @@ bash ./install.sh --target kimi --profile minimal
- The `kimi` target installs into the project-level `./.kimi/` directory.
- Kimi Code CLI's own config (`~/.kimi-code/config.toml`, plugins) is **not** touched by ECC install.
- Use `npx ecc doctor --target kimi` to check install health.
+
+## 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.
diff --git a/README.md b/README.md
index 125692102..10b01a457 100644
--- a/README.md
+++ b/README.md
@@ -106,9 +106,17 @@ ECC v2.0.0 adds the public Hermes operator story on top of that reusable layer:
Atlas Cloud
+
+Run or self-host any open-source model. Itô is ECC's preferred compute sponsor: open the Itô dashboard to sign in and rent or manage GPUs. Any GPU provider works. ECC only provides this link; it does not provision compute or serving. Managed inference through Itô is not live yet.
+
Community sponsors:Mike Morgan · @jasonwu513 · @1anter · @massimotodaro · @meadmccabeBecome a Sponsor · Sponsor Tiers · Sponsorship Program
@@ -1188,6 +1196,8 @@ 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.
+
Official references:
- [Claude Code LLM gateway docs](https://docs.anthropic.com/en/docs/claude-code/llm-gateway)
- [Claude Code model configuration docs](https://docs.anthropic.com/en/docs/claude-code/model-config)
diff --git a/SPONSORS.md b/SPONSORS.md
index 9846d8656..173a57ebd 100644
--- a/SPONSORS.md
+++ b/SPONSORS.md
@@ -13,9 +13,12 @@ Thank you to everyone funding ECC's open-source work. Your sponsorship is what l
| [**CodeRabbit**](https://www.coderabbit.ai) | | 2026 |
| [**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 |
*[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.
+
## Team Sponsors — $200/mo
| Sponsor | Since |
diff --git a/assets/images/sponsors/ito.svg b/assets/images/sponsors/ito.svg
new file mode 100644
index 000000000..89ae6fcb3
--- /dev/null
+++ b/assets/images/sponsors/ito.svg
@@ -0,0 +1,148 @@
+
+
+
+
diff --git a/docs/ATLAS-CLOUD-GUIDE.md b/docs/ATLAS-CLOUD-GUIDE.md
index 9a919d184..d4fe86dc2 100644
--- a/docs/ATLAS-CLOUD-GUIDE.md
+++ b/docs/ATLAS-CLOUD-GUIDE.md
@@ -2,6 +2,8 @@
[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.
+
## Configuration
Set the following environment variables to use Atlas Cloud as your LLM backend:
diff --git a/docs/design/ecc-ito-compute-integration.md b/docs/design/ecc-ito-compute-integration.md
new file mode 100644
index 000000000..9e1d4133b
--- /dev/null
+++ b/docs/design/ecc-ito-compute-integration.md
@@ -0,0 +1,562 @@
+# ECC × Itô Compute Integration
+
+Status: **Proposed — requires Affaan approval before Phase 2 implementation**
+
+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.
+
+## Thesis
+
+The distribution chain is:
+
+ GPU compute (Itô)
+ -> 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 |
+
+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.
+
+## Channel B: training and GPU operations
+
+### Skill 2: training-run-operations
+
+Path:
+
+ skills/training-run-operations/SKILL.md
+
+Activate for launching, resuming, debugging, observing, or cost-planning a
+training, fine-tuning, evaluation, retraining, or MLE run.
+
+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.
+
+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.
+
+Workflow:
+
+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.
+
+### Skill 3: gpu-workload-splitting
+
+Path:
+
+ skills/gpu-workload-splitting/SKILL.md
+
+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.
+
+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.
+
+Required output: WorkloadSplitPlan
+
+| 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 |
+
+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.
+
+### Skill 4: slurm-gpu-workloads
+
+Path:
+
+ skills/slurm-gpu-workloads/SKILL.md
+
+Activate for sbatch, srun, salloc, GPU GRES or TRES, pending jobs, arrays,
+DDP/NCCL, queue time, low utilization, requeue, or Slurm GPU optimization.
+
+Workflow:
+
+- 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 5: kubernetes-gpu-workloads
+
+Path:
+
+ skills/kubernetes-gpu-workloads/SKILL.md
+
+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.
+
+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:
+
+- 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.
diff --git a/package-lock.json b/package-lock.json
index b80cf2b7c..4fa6d5881 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1122,9 +1122,9 @@
"license": "MIT"
},
"node_modules/fast-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz",
- "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==",
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz",
+ "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==",
"funding": [
{
"type": "github",
@@ -1472,9 +1472,9 @@
}
},
"node_modules/js-yaml": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz",
- "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz",
+ "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==",
"dev": true,
"funding": [
{
@@ -1590,9 +1590,9 @@
}
},
"node_modules/linkify-it": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz",
- "integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==",
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.2.tgz",
+ "integrity": "sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==",
"dev": true,
"funding": [
{
@@ -1652,9 +1652,9 @@
}
},
"node_modules/markdown-it": {
- "version": "14.2.0",
- "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz",
- "integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==",
+ "version": "14.3.0",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.0.tgz",
+ "integrity": "sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==",
"dev": true,
"funding": [
{
@@ -1669,8 +1669,8 @@
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1",
- "entities": "^4.4.0",
- "linkify-it": "^5.0.1",
+ "entities": "^4.5.0",
+ "linkify-it": "^5.0.2",
"mdurl": "^2.0.0",
"punycode.js": "^2.3.1",
"uc.micro": "^2.1.0"
diff --git a/package.json b/package.json
index fa24f7521..ae74ebee2 100644
--- a/package.json
+++ b/package.json
@@ -58,6 +58,7 @@
"agent.yaml",
"assets/ecc-icon.svg",
"assets/hero.png",
+ "assets/images/sponsors/",
"agents/",
"commands/",
"docs/de-DE/",
@@ -410,7 +411,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'",
+ "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'",
"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",
@@ -459,12 +460,14 @@
"node": ">=18"
},
"overrides": {
- "markdown-it": ">=14.2.0",
- "js-yaml": ">=4.2.0"
+ "fast-uri": "3.1.4",
+ "markdown-it": "14.3.0",
+ "js-yaml": "4.3.0"
},
"resolutions": {
- "markdown-it": ">=14.2.0",
- "js-yaml": ">=4.2.0"
+ "fast-uri": "3.1.4",
+ "markdown-it": "14.3.0",
+ "js-yaml": "4.3.0"
},
"packageManager": "yarn@4.9.2+sha512.1fc009bc09d13cfd0e19efa44cbfc2b9cf6ca61482725eb35bbc5e257e093ebf4130db6dfe15d604ff4b79efd8e1e8e99b25fa7d0a6197c9f9826358d4d65c3c"
}
diff --git a/scripts/ecc.js b/scripts/ecc.js
index 7e38b3d38..7f1e7bfb8 100755
--- a/scripts/ecc.js
+++ b/scripts/ecc.js
@@ -3,6 +3,7 @@
const { spawnSync } = require('child_process');
const path = require('path');
const { listAvailableLanguages } = require('./lib/install-executor');
+const { getComputeSponsorCopy } = require('./lib/compute-sponsor');
const COMMANDS = {
install: {
@@ -119,6 +120,9 @@ Compatibility:
Global Flags:
--dry-run Preview actions without executing (sets ECC_DRY_RUN=1)
+Compute:
+ ${getComputeSponsorCopy()}
+
Examples:
ecc typescript
ecc install --profile developer --target claude
diff --git a/scripts/install-apply.js b/scripts/install-apply.js
index c0702ff27..9c427cd7b 100755
--- a/scripts/install-apply.js
+++ b/scripts/install-apply.js
@@ -17,6 +17,7 @@ const {
normalizeInstallRequest,
parseInstallArgs,
} = require('./lib/install/request');
+const { getComputeSponsorCopy } = require('./lib/compute-sponsor');
function getHelpText() {
const languages = listLegacyCompatibilityLanguages();
@@ -60,6 +61,9 @@ Options:
--json Emit machine-readable plan/result JSON
--help Show this help text
+Compute:
+ ${getComputeSponsorCopy()}
+
Available languages:
${languages.map(language => ` - ${language}`).join('\n')}
@@ -115,6 +119,8 @@ function printHumanPlan(plan, dryRun) {
if (!dryRun) {
console.log(`\nDone. Install-state written to ${plan.installStatePath}`);
}
+
+ console.log('\nCompute: ' + getComputeSponsorCopy());
}
function main() {
diff --git a/scripts/lib/compute-sponsor.js b/scripts/lib/compute-sponsor.js
new file mode 100644
index 000000000..a5235485c
--- /dev/null
+++ b/scripts/lib/compute-sponsor.js
@@ -0,0 +1,16 @@
+'use strict';
+
+const ITO_COMPUTE_URL = 'https://compute.itomarkets.com';
+
+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.';
+}
+
+module.exports = Object.freeze({
+ ITO_COMPUTE_URL,
+ getComputeSponsorCopy,
+});
diff --git a/src/llm/cli/selector.py b/src/llm/cli/selector.py
index 87b513e21..7a5777461 100644
--- a/src/llm/cli/selector.py
+++ b/src/llm/cli/selector.py
@@ -31,6 +31,21 @@ def print_providers(providers: list[tuple[str, str]]) -> None:
print(f" {Color.GREEN}{i}{Color.RESET}. {Color.BOLD}{name}{Color.RESET} - {desc}")
+def print_self_host_compute_notice(provider: str) -> None:
+ if provider != "ollama":
+ return
+
+ print(
+ "\nRun or self-host any open-source model. "
+ "Itô is ECC's preferred compute sponsor: "
+ "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."
+ )
+
+
def select_provider(providers: list[tuple[str, str]]) -> str | None:
if not providers:
print("No providers available.")
@@ -126,6 +141,8 @@ def interactive_select(
if not provider:
return None
+ print_self_host_compute_notice(provider)
+
models = models_per_provider.get(provider, [])
model = select_model(models)
if not model:
diff --git a/tests/scripts/ito-compute-sponsor.test.js b/tests/scripts/ito-compute-sponsor.test.js
new file mode 100644
index 000000000..ea0ca72ff
--- /dev/null
+++ b/tests/scripts/ito-compute-sponsor.test.js
@@ -0,0 +1,178 @@
+/**
+ * Tests for the Phase 1 Ito compute-sponsor surface.
+ */
+
+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 URL_TOKEN_PATTERN = /https?:\/\/[^\s<>"'`(){}\\]+/g;
+const EXPECTED_COMPUTE_ROUTE = Object.freeze({
+ protocol: 'https:',
+ hostname: 'compute.itomarkets.com',
+ port: '',
+ username: '',
+ password: '',
+ pathname: '/',
+ search: '',
+ hash: '',
+});
+
+function read(relativePath) {
+ return fs.readFileSync(path.join(REPO_ROOT, relativePath), 'utf8');
+}
+
+function runTest(name, fn) {
+ try {
+ fn();
+ console.log(` ✓ ${name}`);
+ return true;
+ } catch (error) {
+ console.log(` ✗ ${name}`);
+ console.error(` ${error.message}`);
+ return false;
+ }
+}
+
+function isExactComputeRoute(candidate) {
+ try {
+ const parsed = new URL(candidate.replace(/[.,;:!?]+$/, ''));
+ return Object.entries(EXPECTED_COMPUTE_ROUTE).every(
+ ([property, expected]) => parsed[property] === expected
+ );
+ } catch {
+ return false;
+ }
+}
+
+function assertExactComputeRoute(content) {
+ const candidates = content.match(URL_TOKEN_PATTERN) || [];
+ assert.ok(
+ candidates.some(isExactComputeRoute),
+ 'Should include the exact Itô compute route'
+ );
+}
+
+function assertHonestComputeCopy(content) {
+ assertExactComputeRoute(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, /managed inference[^\n.]*not live/i);
+}
+
+function main() {
+ console.log('\n=== Testing Ito compute-sponsor surface ===\n');
+
+ let passed = 0;
+ let failed = 0;
+
+ const tests = [
+ ['compute route validation rejects deceptive lookalike hosts', () => {
+ const deceptiveCopy = [
+ 'Itô is the preferred compute sponsor:',
+ 'https://compute.itomarkets.com.attacker.example',
+ 'Any GPU provider works.',
+ 'Managed inference through Itô is not live.',
+ ].join(' ');
+
+ assert.throws(
+ () => assertHonestComputeCopy(deceptiveCopy),
+ /exact Itô compute route/
+ );
+ }],
+ ['README exposes the sponsor logo and honest self-hosting route', () => {
+ const readme = read('README.md');
+ assert.ok(readme.includes('assets/images/sponsors/ito.svg'));
+ 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/
+ );
+ const sponsorMark = read('assets/images/sponsors/ito.svg');
+ assert.match(sponsorMark, / {
+ const sponsors = read('SPONSORS.md');
+ assert.ok(sponsors.includes('[**Itô**]'));
+ assert.ok(sponsors.includes('assets/images/sponsors/ito.svg'));
+ assertExactComputeRoute(sponsors);
+ }],
+ ['inference guide distinguishes rental compute from managed serving', () => {
+ assertHonestComputeCopy(read('docs/ATLAS-CLOUD-GUIDE.md'));
+ }],
+ ['harness docs route generic open-source model intent without lock-in', () => {
+ 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/);
+ }],
+ ['top-level CLI help exposes the provider-neutral compute route', () => {
+ const result = spawnSync('node', ['scripts/ecc.js', '--help'], {
+ cwd: REPO_ROOT,
+ encoding: 'utf8',
+ });
+ assert.strictEqual(result.status, 0, result.stderr);
+ assertHonestComputeCopy(result.stdout);
+ }],
+ ['installer help and human dry-run expose the compute route', () => {
+ const help = spawnSync('node', ['scripts/install-apply.js', '--help'], {
+ cwd: REPO_ROOT,
+ encoding: 'utf8',
+ });
+ assert.strictEqual(help.status, 0, help.stderr);
+ assertHonestComputeCopy(help.stdout);
+
+ const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-ito-home-'));
+ const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-ito-project-'));
+ try {
+ const dryRun = spawnSync(
+ 'node',
+ [path.join(REPO_ROOT, 'scripts', 'install-apply.js'), '--profile', 'minimal', '--dry-run'],
+ {
+ cwd: projectDir,
+ env: { ...process.env, HOME: homeDir },
+ encoding: 'utf8',
+ }
+ );
+ assert.strictEqual(dryRun.status, 0, dryRun.stderr);
+ assertHonestComputeCopy(dryRun.stdout);
+ } finally {
+ fs.rmSync(homeDir, { recursive: true, force: true });
+ fs.rmSync(projectDir, { recursive: true, force: true });
+ }
+ }],
+ ['npm package publishes the Ito mark and welcome route', () => {
+ const packageJson = JSON.parse(read('package.json'));
+ 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.ok(fs.existsSync(path.join(REPO_ROOT, 'assets', 'images', 'sponsors', 'ito.svg')));
+ }],
+ ];
+
+ for (const [name, fn] of tests) {
+ if (runTest(name, fn)) {
+ passed += 1;
+ } else {
+ failed += 1;
+ }
+ }
+
+ console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
+ process.exit(failed > 0 ? 1 : 0);
+}
+
+main();
diff --git a/tests/scripts/npm-publish-surface.test.js b/tests/scripts/npm-publish-surface.test.js
index 47dc5c08a..7aa17ae62 100644
--- a/tests/scripts/npm-publish-surface.test.js
+++ b/tests/scripts/npm-publish-surface.test.js
@@ -83,6 +83,7 @@ function buildExpectedPublishPaths(repoRoot) {
"VERSION",
"assets/ecc-icon.svg",
"assets/hero.png",
+ "assets/images/sponsors",
]
const exclusionPaths = [
"!**/__pycache__/**",
diff --git a/tests/test_selector.py b/tests/test_selector.py
new file mode 100644
index 000000000..5f1441041
--- /dev/null
+++ b/tests/test_selector.py
@@ -0,0 +1,59 @@
+"""Tests for provider-selection compute guidance."""
+
+import importlib.util
+import re
+from pathlib import Path
+from urllib.parse import urlsplit
+
+import pytest
+
+
+SELECTOR_PATH = Path(__file__).parents[1] / "src" / "llm" / "cli" / "selector.py"
+SPEC = importlib.util.spec_from_file_location("ecc_selector", SELECTOR_PATH)
+assert SPEC is not None and SPEC.loader is not None
+SELECTOR = importlib.util.module_from_spec(SPEC)
+SPEC.loader.exec_module(SELECTOR)
+print_self_host_compute_notice = SELECTOR.print_self_host_compute_notice
+
+URL_TOKEN_PATTERN = re.compile(r"https?://[^\s<>\"'`()\[\]{}\\]+")
+EXPECTED_COMPUTE_ROUTE = (
+ "https",
+ "compute.itomarkets.com",
+ "",
+ "",
+ "",
+)
+
+
+def assert_exact_compute_route(content: str) -> None:
+ candidates = URL_TOKEN_PATTERN.findall(content)
+ routes = (
+ urlsplit(candidate.rstrip(".,;:!?"))
+ for candidate in candidates
+ )
+ assert any(route == EXPECTED_COMPUTE_ROUTE for route in routes), (
+ "Should include the exact Itô compute route"
+ )
+
+
+def test_compute_route_validation_rejects_deceptive_lookalike_host():
+ deceptive_output = "https://compute.itomarkets.com.attacker.example"
+
+ with pytest.raises(AssertionError, match="exact Itô compute route"):
+ assert_exact_compute_route(deceptive_output)
+
+
+def test_ollama_notice_routes_to_ito_without_claiming_serving(capsys):
+ print_self_host_compute_notice("ollama")
+
+ output = capsys.readouterr().out
+ assert_exact_compute_route(output)
+ assert "preferred compute sponsor" in output
+ assert "Any GPU provider works" in output
+ assert "Managed inference through Itô is not live yet" in output
+
+
+def test_managed_provider_does_not_show_self_host_compute_notice(capsys):
+ print_self_host_compute_notice("openai")
+
+ assert capsys.readouterr().out == ""
diff --git a/yarn.lock b/yarn.lock
index 4eaebc311..5dfedb05d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -622,7 +622,7 @@ __metadata:
languageName: node
linkType: hard
-"entities@npm:^4.4.0":
+"entities@npm:^4.5.0":
version: 4.5.0
resolution: "entities@npm:4.5.0"
checksum: 10c0/5b039739f7621f5d1ad996715e53d964035f75ad3b9a4d38c6b3804bb226e282ffeae2443624d8fdd9c47d8e926ae9ac009c54671243f0c3294c26af7cc85250
@@ -801,10 +801,10 @@ __metadata:
languageName: node
linkType: hard
-"fast-uri@npm:^3.0.1":
- version: 3.1.2
- resolution: "fast-uri@npm:3.1.2"
- checksum: 10c0/5b35641895959f3f7ab7a7b1b5542bded159346f25ec9f256817b206d50b64eda5828e90d605a2e2fc645c90519a7259c2bab2c942ee728c88b88e5be21b090d
+"fast-uri@npm:3.1.4":
+ version: 3.1.4
+ resolution: "fast-uri@npm:3.1.4"
+ checksum: 10c0/f90948821ceb49980f64f89b8216ba498f5957f26035be813526a55b6145d26cbd63ef5618d5205a3292b31edc9c08589749350cd72bd86c7095eb434dceb757
languageName: node
linkType: hard
@@ -1066,14 +1066,14 @@ __metadata:
languageName: node
linkType: hard
-"js-yaml@npm:>=4.2.0":
- version: 4.2.0
- resolution: "js-yaml@npm:4.2.0"
+"js-yaml@npm:4.3.0":
+ version: 4.3.0
+ resolution: "js-yaml@npm:4.3.0"
dependencies:
argparse: "npm:^2.0.1"
bin:
js-yaml: bin/js-yaml.js
- checksum: 10c0/1916456c118746603b067d74bbcbb0445d9a1d5e474ad4ae775e7b20525bed902e01d9d97dd0c81fcd8d4f596162309d0eb057f4aa38f3e9647f14075e9dea45
+ checksum: 10c0/058b30473d6915ca5b4feb11e2f7d4d97242f98d00a798ed48dd90b46b7c640398afe9128c5db22c5300f8c6528fe2a174b9a93f351a70ebc28c6203938d8bff
languageName: node
linkType: hard
@@ -1156,12 +1156,12 @@ __metadata:
languageName: node
linkType: hard
-"linkify-it@npm:^5.0.1":
- version: 5.0.1
- resolution: "linkify-it@npm:5.0.1"
+"linkify-it@npm:^5.0.2":
+ version: 5.0.2
+ resolution: "linkify-it@npm:5.0.2"
dependencies:
uc.micro: "npm:^2.0.0"
- checksum: 10c0/d06d04f1ed03be131740fc900a5e74ea1f49886b052213599e306d469d5ffe2303db76dd8f771de9f28e2b0b38852de22ec46ae597d245f8b66439b0ceb19b10
+ checksum: 10c0/dd70b1735a13d41a2cff0a058ac3771166038f23f6aff004dd53873cf985c64b107902fe0b544a5b3d1ff6e63249cf9c648fb3ae9f285481db48f56887adb0d6
languageName: node
linkType: hard
@@ -1190,19 +1190,19 @@ __metadata:
languageName: node
linkType: hard
-"markdown-it@npm:>=14.2.0":
- version: 14.2.0
- resolution: "markdown-it@npm:14.2.0"
+"markdown-it@npm:14.3.0":
+ version: 14.3.0
+ resolution: "markdown-it@npm:14.3.0"
dependencies:
argparse: "npm:^2.0.1"
- entities: "npm:^4.4.0"
- linkify-it: "npm:^5.0.1"
+ entities: "npm:^4.5.0"
+ linkify-it: "npm:^5.0.2"
mdurl: "npm:^2.0.0"
punycode.js: "npm:^2.3.1"
uc.micro: "npm:^2.1.0"
bin:
markdown-it: bin/markdown-it.mjs
- checksum: 10c0/1d3a50061d2fe4efbcf317aac853dbee6892ed6f5a217570eead723f2ef2dd1c9baaeef5a687cd283480c45c2d20724a73e84a9ed72843cf7b3b719067af40ef
+ checksum: 10c0/b2dea908968109d6e9088ac972254bca842157d85d2e6838d0eb263cd8106e7e6a72663b138366cc98f57441d9f3f2ebfb842bf7b2f9e1c13187ebe70e0af8f9
languageName: node
linkType: hard