Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,15 @@ Prefer the smallest test command covering the change. Host-dependent backend sui

## Schema and policy rules

- Production parsing dispatches through exact closed contracts. Rolling wire parsing is only a differential-development oracle.
- Production parsing dispatches through exact closed contracts and their
version-specific adapters into private normalization input.
- Preserve optional-field presence through parsing and binding. Apply defaults and semantic validation in the backend.
- New features use their intended permanent JSON location in the exact
development contract. JSON placement, publication eligibility, and runtime
experimental authorization are separate; while the rolling oracle remains,
update both it and the exact development contract.
experimental authorization are separate.
- Never edit `schemas/stable/`; released schemas are immutable.
- Never hand-edit generated development schemas or generated TypeScript wire types.
- Never hand-edit generated exact development schemas or generated TypeScript
contract types.
- `schemas/schema-version.json` is the canonical source for compatibility constants.

See [`docs/schema-codegen.md`](../docs/schema-codegen.md) for regeneration commands.
Expand Down
8 changes: 1 addition & 7 deletions .github/workflows/Versioning.Checks.Job.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,9 @@ jobs:
- name: Check Linux probe-timeout parity (SDK backstop > native worst case)
run: node scripts/versioning/check-linux-probe-timeouts.js

- name: Check schema is in sync with the Rust wire model (codegen)
run: node scripts/versioning/check-schema-codegen.js

- name: Check PSEC generated contract (provenance + drift)
run: node scripts/versioning/check-psec-codegen.js

- name: Check SDK wire types are in sync with the Rust wire model (codegen)
run: node scripts/versioning/check-sdk-types-codegen.js

- name: Check exact contract generated artifacts and fixtures
run: node scripts/versioning/check-contract-codegen.js

Expand All @@ -68,5 +62,5 @@ jobs:
- name: Check C# bindings codegen (regenerates and asserts entry points)
run: node scripts/check-dotnet-bindings-codegen.js

- name: Validate config corpus against dev schema
- name: Validate config corpus against exact registered schemas
run: node scripts/versioning/validate-configs.js
80 changes: 35 additions & 45 deletions docs/authoring-a-new-feature.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@
> into a *new* stable schema file at promotion time (per
> [Promoting to Stable](#promoting-to-stable) below).
>
> **Stable schemas document only the non-experimental surface.**
> Experimental backends, the `experimental.*` block, and any in-progress
> shapes live solely in `schemas/dev/` — they must not be mirrored into
> a stable file. Configs that need editor validation for experimental
> fields should point `$schema` at the dev file. The `--experimental`
> runtime gate is unchanged: it still controls execution regardless of
> which schema validated the config.
> **Development features use permanent field locations.**
> Add an in-progress backend or feature at its intended top-level location in
> the mutable development contract. Do not place it under an
> `experimental` JSON wrapper. The `--experimental` runtime gate controls
> execution until graduation regardless of which schema validated the config.

## Prerequisites

Expand Down Expand Up @@ -113,36 +111,35 @@ Adding a feature may touch these files:
| File | What to change |
|------|----------------|
| `src/core/mxc_config_contract/src/dev/` | Add the field to the authoritative closed mutable development contract |
| `src/core/wxc_common/src/wire.rs` | Mirror the field in the rolling differential model while that characterization oracle remains |
| `src/core/wxc_common/src/config_contract_adapters/dev/` | Adapt the exact field into private `ConfigInput` |
| `src/core/wxc_common/src/wire.rs` | Add only reusable nested normalization DTOs needed by the adapter; never add a whole-request root |
| `src/core/mxc_engine/src/policy/exact/v0_10.rs` | If the Rust SDK exposes the field, update the production exact development builder |
| `schemas/dev/mxc-config.schema.0.10.0-dev.json` | **Generated rolling artifact** — do not hand-edit |
| `schemas/dev/mxc-config.schema.0.10.0-alpha.json` | **Generated exact artifact** — do not hand-edit |
| `sdk/node/src/generated/v0_10_0_alpha/wire.ts` | **Generated exact artifact** — do not hand-edit |
| `src/core/wxc_common/src/models.rs` | Add `GpuIsolationConfig` struct, add field to `ExperimentalConfig` |
| `src/core/wxc_common/src/config_parser.rs` | Map the new wire field to the domain struct in `convert_wire_config` |
| `src/core/wxc_common/src/config_parser.rs` | Map the new config-input field to the domain struct in `convert_config_input` |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

domain struct

What is the domain struct? not mentioned in this file anywhere.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in #1188. Good catch. I replaced the undefined "domain struct" terminology with the concrete flow: the exact contract field is adapted through CommonRequestIR and normalized into models::GpuIsolationConfig on ExecutionRequest.

| Runner (`appcontainer.rs` or `lxc_runner.rs`) | Feature logic, guarded behind `experimental_enabled` |
| `tests/configs/` | Test config exercising your feature |

## Step 1: Add the field to the exact contract and rolling oracle
## Step 1: Add the field to the exact contract and config input

Add the feature to the authoritative closed request types under
`src/core/mxc_config_contract/src/dev/`, then mirror it in the rolling Rust wire
model (`src/core/wxc_common/src/wire.rs`) while differential characterization
remains. The rolling experimental struct remains permissive; the exact
development contract and every nested experimental object are recursively
closed.
`src/core/mxc_config_contract/src/dev/`, then adapt it into the shared internal
config input used by semantic normalization.
The exact development request and every nested object are recursively closed.

```rust
// in wire.rs
pub struct Experimental {
pub compartments: Option<Compartments>,
pub gpu_isolation: Option<GpuIsolation>, // ← add this
// ...
// in mxc_config_contract/src/dev/one_shot.rs
pub struct Request {
// Existing permanent fields...
#[serde(default)]
pub gpu_isolation: OptionalField<GpuIsolation>,
}

/// GPU device isolation (experimental).
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, serde::Deserialize)]
#[cfg_attr(feature = "schema-gen", derive(schemars::JsonSchema))]
#[serde(rename_all = "camelCase")]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct GpuIsolation {
/// GPU device index to assign to the container.
pub device_index: Option<u32>,
Expand All @@ -157,14 +154,12 @@ The `///` doc comments become schema `description`s and `#[schemars(...)]`
attributes become constraints. Then regenerate the committed schema:

```
cargo run --manifest-path src/Cargo.toml -p mxc_schema_gen -- schema --legacy-wire --out schemas/dev/mxc-config.schema.0.10.0-dev.json
cargo run --manifest-path src/Cargo.toml -p mxc_schema_gen -- types --legacy-wire --out sdk/node/src/generated/wire.ts
cargo run --manifest-path src/Cargo.toml -p mxc_schema_gen -- schema --version 0.10.0-alpha --out schemas/dev/mxc-config.schema.0.10.0-alpha.json
cargo run --manifest-path src/Cargo.toml -p mxc_schema_gen -- types --version 0.10.0-alpha --out sdk/node/src/generated/v0_10_0_alpha/wire.ts
```

The rolling and exact codegen gates fail if any committed artifact drifts, so
all applicable regeneration steps are mandatory.
The exact codegen gate fails if either committed artifact drifts, so both
regeneration steps are mandatory.

## Step 2: Add the model struct

Expand Down Expand Up @@ -194,9 +189,9 @@ pub struct ExperimentalConfig {

Production parsing first deserializes JSON into the exact registered request
contract. The version-specific adapter then converts that closed type into the
shared `wire::MxcConfig` representation used by semantic normalization. Add the
shared private `config_input::ConfigInput` used by semantic normalization. Add the
adapter mapping for your exact contract field, then map the corresponding wire
field to the domain struct inside `convert_wire_config`:
field to the domain struct inside `convert_config_input`:

```rust
let experimental = if let Some(raw_exp) = cfg.experimental {
Expand All @@ -223,9 +218,8 @@ Add tests to verify:
- `gpuIsolation` is accepted by the exact request root and maps through its
adapter to `ExecutionRequest.experimental`
- Missing optional fields use defaults
- Unknown fields under exact `experimental` objects are rejected
- The rolling parser's permissive behavior remains characterized separately
while that differential oracle exists
- Unknown fields in the exact feature object are rejected
- Version-boundary tests reject the field from contracts that predate it

## Step 4: Implement the feature in the runner

Expand Down Expand Up @@ -332,25 +326,21 @@ The SDK passes `--experimental` to the underlying binary when this is set.

When your experimental feature is ready to ship:

1. Move the field from `experimental` to the top-level stable-candidate surface
in both transitional Rust models, then regenerate all rolling and exact
artifacts with `mxc_schema_gen`
1. Carry the field from the mutable development contract into the next exact
stable contract at the same permanent location, then regenerate its exact
schema and TypeScript artifacts with `mxc_schema_gen`
2. Move the struct from `ExperimentalConfig` to `ExecutionRequest`
3. Map the now-top-level wire field in `convert_wire_config` (and add
`deny_unknown_fields` to the wire struct so the promoted, stable surface is
closed)
3. Add the stable contract adapter mapping while retaining the existing
`convert_config_input` domain normalization
4. Remove the `if request.experimental_enabled` guard
5. Bump the minor version
6. Add a parser error for configs still referencing the feature under
`experimental`: `"gpuIsolation has moved to the stable section"`.
This error should persist for at least one release cycle so users have
time to migrate, then it can be relaxed to the standard "unknown field"
behavior.
6. Preserve every published contract unchanged; older contracts continue to
reject the field structurally.

## Checklist

- [ ] Rolling and exact development contract types updated
- [ ] Rolling and exact generated schemas and TypeScript oracles regenerated
- [ ] Exact development contract and adapter updated
- [ ] Exact generated schema and TypeScript oracle regenerated
Comment on lines +342 to +343

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: just an fyi, i think if rolling doesn't exist anymore then "exact" probably loses it's meaning right? and then we can call it "development contract" for example.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in #1188. Mostly agreed. I removed redundant phrases such as "exact development contract" where "development contract" or "next published contract" is sufficient. I retained "exact contract" where it distinguishes an exact registered version from range-based or rolling interpretation.

- [ ] Model struct added to `models.rs`
- [ ] Exact contract adapter and domain mapping added with unit tests
- [ ] `--experimental` flag wired through (if not already)
Expand Down
6 changes: 3 additions & 3 deletions docs/bwrap-support/bubblewrap-backend-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ A backend-specific config can be added later under `ExperimentalConfig` if neede

- Add a `Bubblewrap` variant to the wire `Containment` enum (or rely on the
abstract `process` intent resolving to `Bubblewrap` on Linux)
- Add any backend-specific fields to the wire model (under `experimental` while
experimental), then regenerate the applicable rolling and exact schemas with
`mxc_schema_gen schema`
- Add backend-specific fields at their permanent location in the exact
development contract, adapt them into `ConfigInput`, and regenerate the
exact schema with `mxc_schema_gen schema`
- Map the new `containment` value in `map_wire_containment`
- Optionally: make `"process"` resolve to `Bubblewrap` on Linux when LXC is unavailable
(or add a `"process"` → bwrap fallback chain)
Expand Down
2 changes: 1 addition & 1 deletion docs/nanvix-microvm/nanvix-integration-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ Setup scripts (PowerShell & Bash) will download matching pre-release binaries an

**What changed:**
- `models.rs` — Added `MicroVm` variant to `ContainmentBackend`, added `NanVixConfig` struct, added `nanvix_config` field to `ExecutionRequest`
- `config_parser.rs` — Added `"microvm"` containment parsing and NanVix config section parsing (originally via `Raw*` structs; the parser has since been rewired onto the `wire::MxcConfig` model — new work maps the wire types in `convert_wire_config`)
- `config_parser.rs` — Added `"microvm"` containment parsing and NanVix config section parsing (originally via `Raw*` structs; exact adapters now construct `config_input::ConfigInput`, and normalization maps its nested DTOs in `convert_config_input`)
- `error.rs` — Added `WxcError::NanVix(String)` variant
- `nanvix_runner.rs` — **NEW** — `NanVixScriptRunner` implementing `ScriptRunner` trait
- `lib.rs` — Added `pub mod nanvix_runner`
Expand Down
Loading
Loading