Skip to content
Merged
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
51 changes: 51 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ jobs:
-p warp-geom \
-p warp-wasm \
-p echo-wasm-abi \
-p echo-edict-canonical \
-p echo-edict-provider-lowerer \
-p echo-runtime-schema \
-p echo-dry-tests \
-p echo-graph \
Expand Down Expand Up @@ -175,6 +177,55 @@ jobs:
.
- name: cargo test (workspace sans warp-core)
run: cargo test --workspace --exclude warp-core
- name: package publishable Edict canonical leaf
run: cargo package -p echo-edict-canonical --locked

build-edict-provider-lowerer:
name: Build and check Edict provider lowerer
runs-on: ubuntu-24.04
container:
image: docker.io/library/rust@sha256:3914072ca0c3b8aad871db9169a651ccfce30cf58303e5d6f2db16d1d8a7e58f
options: --platform linux/amd64
steps:
- uses: actions/checkout@v4
with:
submodules: false
- uses: dtolnay/rust-toolchain@1.90.0
with:
components: clippy
targets: wasm32-unknown-unknown
- name: build, audit, and check exact component bytes
env:
GIT_CONFIG_COUNT: 1
GIT_CONFIG_KEY_0: safe.directory
GIT_CONFIG_VALUE_0: ${{ github.workspace }}
run: |
cargo xtask provider-lowerer-component check \
--target-dir target/provider-lowerer-component \
--output schemas/edict-provider/components/v1/lowerer.echo-dpo.component.wasm
- name: clippy (wasm32 Edict provider adapter)
run: cargo +1.90.0 clippy -p echo-edict-provider-lowerer --target wasm32-unknown-unknown --lib -- -D warnings -D missing_docs

edict-provider-host-v1:
name: Edict provider host contract (Rust 1.94)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
submodules: false
- uses: dtolnay/rust-toolchain@1.90.0
with:
targets: wasm32-unknown-unknown
- uses: dtolnay/rust-toolchain@1.94.0
with:
components: clippy
- uses: Swatinem/rust-cache@v2
with:
workspaces: |
.
tests/edict-provider-host-v1 -> target/edict-provider-host-v1
- name: invoke and replay through the exact Edict host
run: scripts/verify-edict-provider-host-v1.sh

build-echo-cas-wasm:
name: Build echo-cas (wasm32)
Expand Down
117 changes: 92 additions & 25 deletions .github/workflows/det-gates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -220,57 +220,120 @@ jobs:
perf.log
perf-report.json

build-repro:
name: G4 build reproducibility (wasm)
build-repro-candidate:
name: G4 build candidate ${{ matrix.candidate }}
needs: classify-changes
if: needs.classify-changes.outputs.run_g4 == 'true'
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
container:
image: docker.io/library/rust@sha256:3914072ca0c3b8aad871db9169a651ccfce30cf58303e5d6f2db16d1d8a7e58f
options: --platform linux/amd64
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
candidate: [1, 2]
steps:
- name: Setup Rust (Global)
uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown
- name: Checkout Build 1
- name: Checkout exact candidate source
uses: actions/checkout@v4
with:
path: build1
- name: Build 1
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Install wasm target
run: rustup target add wasm32-unknown-unknown
- name: Build isolated candidate
env:
CANDIDATE: ${{ matrix.candidate }}
GIT_CONFIG_COUNT: 1
GIT_CONFIG_KEY_0: safe.directory
GIT_CONFIG_VALUE_0: ${{ github.workspace }}
run: |
cd build1
rustup target add wasm32-unknown-unknown
repo_root="$(pwd -P)"
export RUSTFLAGS="--remap-path-prefix=${repo_root}=/workspace"
cargo build --release --target wasm32-unknown-unknown -p warp-wasm --features engine
sha256sum target/wasm32-unknown-unknown/release/warp_wasm.wasm > ../hash1.txt
cp target/wasm32-unknown-unknown/release/warp_wasm.wasm ../build1.wasm
- name: Checkout Build 2
sha256sum target/wasm32-unknown-unknown/release/warp_wasm.wasm > "hash${CANDIDATE}.txt"
cp target/wasm32-unknown-unknown/release/warp_wasm.wasm "build${CANDIDATE}.wasm"
cargo xtask provider-lowerer-component designated-build \
--target-dir target/provider-lowerer-repro \
--output target/lowerer.echo-dpo.component.wasm
sha256sum target/lowerer.echo-dpo.component.wasm > "lowerer-hash${CANDIDATE}.txt"
cp target/lowerer.echo-dpo.component.wasm "build${CANDIDATE}.lowerer.component.wasm"
- name: Upload isolated candidate
uses: actions/upload-artifact@v4
with:
name: build-repro-candidate-${{ matrix.candidate }}
overwrite: true
path: |
hash${{ matrix.candidate }}.txt
build${{ matrix.candidate }}.wasm
lowerer-hash${{ matrix.candidate }}.txt
build${{ matrix.candidate }}.lowerer.component.wasm

build-repro:
name: G4 independent build comparison
needs:
- classify-changes
- build-repro-candidate
if: needs.classify-changes.outputs.run_g4 == 'true' && needs.build-repro-candidate.result == 'success'
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- name: Checkout exact candidate source
uses: actions/checkout@v4
with:
path: build2
- name: Build 2
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Setup Rust for portable promotion
uses: dtolnay/rust-toolchain@1.90.0
- name: Download candidate 1
uses: actions/download-artifact@v4
with:
name: build-repro-candidate-1
path: candidate1
- name: Download candidate 2
uses: actions/download-artifact@v4
with:
name: build-repro-candidate-2
path: candidate2
- name: Assemble exact evidence names
run: |
cd build2
rustup target add wasm32-unknown-unknown
repo_root="$(pwd -P)"
export RUSTFLAGS="--remap-path-prefix=${repo_root}=/workspace"
cargo build --release --target wasm32-unknown-unknown -p warp-wasm --features engine
sha256sum target/wasm32-unknown-unknown/release/warp_wasm.wasm > ../hash2.txt
cp target/wasm32-unknown-unknown/release/warp_wasm.wasm ../build2.wasm
- name: Compare hashes
cp candidate1/hash1.txt hash1.txt
cp candidate2/hash2.txt hash2.txt
cp candidate1/build1.wasm build1.wasm
cp candidate2/build2.wasm build2.wasm
cp candidate1/lowerer-hash1.txt lowerer-hash1.txt
cp candidate2/lowerer-hash2.txt lowerer-hash2.txt
cp candidate1/build1.lowerer.component.wasm build1.lowerer.component.wasm
cp candidate2/build2.lowerer.component.wasm build2.lowerer.component.wasm
- name: Compare, promote, and check exact bytes
run: |
diff hash1.txt hash2.txt || (echo "Reproducibility failure: Hashes differ!" && exit 1)
diff lowerer-hash1.txt lowerer-hash2.txt || (echo "Lowerer reproducibility failure: Hashes differ!" && exit 1)
cmp build1.wasm build2.wasm
cmp build1.lowerer.component.wasm build2.lowerer.component.wasm
cargo xtask provider-lowerer-component promote \
--candidate-a build1.lowerer.component.wasm \
--candidate-b build2.lowerer.component.wasm \
--output target/lowerer.echo-dpo.promoted.component.wasm \
--write
cmp build1.lowerer.component.wasm target/lowerer.echo-dpo.promoted.component.wasm
cmp build1.lowerer.component.wasm schemas/edict-provider/components/v1/lowerer.echo-dpo.component.wasm
cmp build2.lowerer.component.wasm schemas/edict-provider/components/v1/lowerer.echo-dpo.component.wasm
echo "Hashes match: $(cat hash1.txt)"
echo "Lowerer hashes match: $(cat lowerer-hash1.txt)"
- name: Upload build artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: build-repro-artifacts
overwrite: true
path: |
hash1.txt
hash2.txt
build1.wasm
build2.wasm
lowerer-hash1.txt
lowerer-hash2.txt
build1.lowerer.component.wasm
build2.lowerer.component.wasm

validate-evidence:
name: Evidence artifact presence
Expand Down Expand Up @@ -349,6 +412,10 @@ jobs:
gathered-artifacts/build-repro-artifacts/hash2.txt
gathered-artifacts/build-repro-artifacts/build1.wasm
gathered-artifacts/build-repro-artifacts/build2.wasm
gathered-artifacts/build-repro-artifacts/lowerer-hash1.txt
gathered-artifacts/build-repro-artifacts/lowerer-hash2.txt
gathered-artifacts/build-repro-artifacts/build1.lowerer.component.wasm
gathered-artifacts/build-repro-artifacts/build2.lowerer.component.wasm
)
fi

Expand Down
36 changes: 36 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,42 @@

### Added

- Echo now provides the exact `edict:target-provider/lowerer@1.0.0`
Component Model implementation for the first checked provider closure. The
pure lowerer accepts only explicit digest-bound Core, target-profile,
authority, lawpack, lowerability, and output-role inputs; produces canonical
`echo.span-ir/v1` Target IR with byte-for-byte parity to Edict's built-in Echo
wrapper; and returns typed refusals for unsupported ABI, profiles, semantics,
reads, rebound operations, unresolved authored optics, changed type bindings,
Core type definitions, evaluation budgets, out-of-scope locals, intrinsics,
and output roles. Local admission distinguishes pre-effect, obstruction-arm,
and post-effect scope from the exact input, effect-result, and obstruction
declarations before cloning any expression into Target IR. The first closure
also requires an empty input-constraint set and the exact zero-argument
`domain.WriteRejected` obstruction constructor. Effect inputs and intent
results admit no call-expression callee, refusing unreviewed calls until their
own lowering laws exist. A
deterministic build boundary pins the frozen
WIT bytes, rejects ambient or callable imports, checks the exact decoded world
type graph and contract attestation, and reproduces the checked component
byte-for-byte across independently provisioned `linux/amd64` containers from
the immutable Rust image used by CI. The builder resolves and authenticates the
exact Rust and Cargo executables, binds Cargo to that compiler, owns the inner
Cargo home, removes ambient Cargo profile/build/target overrides, remaps its
dependency source paths to `/cargo`, and atomically promotes only distinct
candidates matching a reviewed repository digest.
Other-host builds are structural and semantic witnesses
rather than cross-host compiler-identity claims. The publication-enabled,
archive-self-contained `echo-edict-provider-lowerer` source crate carries
package-local copies of its four exact admitted resources, with a workspace
witness binding them to the checked generated corpus. Its full package gate
follows publication of `echo-edict-canonical 0.1.0`. These artifacts describe
and translate provider semantics; they confer no Echo runtime authority.
- `echo-edict-canonical` now owns the shared pure implementation of Edict's
canonical CBOR and domain-framed digest contracts as a publishable `0.1.0`
leaf. `echo-wesley-gen` retains its existing compatibility surface through a
re-export, while executable provider components use the same codec without
depending on generator or Wesley APIs.
- `echo-wesley-gen` now checks in the first exact 22-file Edict provider
artifact corpus: five canonical-CBOR primaries, fourteen canonical-CBOR
resources, the self-contained CDDL, Wesley provenance JSON, and
Expand Down
Loading
Loading