The Studio has an answer pane. It reads an answer in the view layer as it streams from the assistant, draws each statement when it arrives, runs the engine call each one is bound to, and seals the answer with a receipt that is checked again by re-running. A stored answer carries its receipt and is verified when it is read back. The correctness record is off by default. When it is turned on, it keeps one record per answer in the browser: the codes, the verdict level, the repairs, whether the answer was accepted, and the receipt id. Nothing is sent anywhere, and the records leave only when exported. The failures export as an eval corpus in the conformance format. A test shows that nothing is recorded while it is off. The engine adds a noise argument to @Sample and @Check, keeps root-listed names that have not arrived in the snapshot order, and gives a model the layer's rules with a worked example. The desktop app answers the same calls. macOS can read a running process's energy, for the model harness. Co-Authored-By: Claude Opus 5.5 <[email protected]>
162 lines
7.2 KiB
YAML
162 lines
7.2 KiB
YAML
name: wai-quantum views in agent hosts
|
|
|
|
# The engine's answers drawn as interactive views inside an agent host, through
|
|
# the Model Context Protocol's extension for them (wai/wai-quantum/src/engine/views.rs,
|
|
# the page in wai/wai-quantum/views/, the engine inside it in wai/wai-quantum-views/,
|
|
# the views themselves in wai/quantum-studio/src/views/):
|
|
# - the committed page is built from its sources as they are (build-views.mjs
|
|
# --check), and rebuilt here: its script and styles to the same bytes. The
|
|
# engine inside it is compiled from wai-quantum, and LLVM lays the same code
|
|
# out differently once anything else in that crate changes, so its bytes are
|
|
# compared and a difference is a warning to rebuild, not a failure: the
|
|
# scripted host below holds the committed page's engine to the receipts the
|
|
# current servers seal;
|
|
# - the engine inside the views checks a receipt as the engine does, and
|
|
# engine::views gives the resources, the tool map, each view's data and its
|
|
# answer in plain words, every view within the size limit;
|
|
# - a scripted host draws every view from both MCP servers in a headless
|
|
# browser (test/views.test.mjs): under the extension's default
|
|
# content-security policy, which refuses WebAssembly, the receipt is checked
|
|
# in the view by the engine translated to JavaScript, and with WebAssembly
|
|
# allowed, by the WebAssembly; a changed result fails the check; the view's
|
|
# own tool for a running job is kept from the model; no view makes a request.
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- 'wai/wai-quantum-views/**'
|
|
- 'wai/wai-quantum/**'
|
|
- 'wai/wai-quantum-cli/**'
|
|
- 'wai/wai-quantum-service/**'
|
|
- 'wai/wai-quantum-qpu/**'
|
|
- 'wai/quantum-studio/**'
|
|
- 'rust-toolchain.toml'
|
|
- '.github/workflows/wai-quantum-views.yml'
|
|
pull_request:
|
|
paths:
|
|
- 'wai/wai-quantum-views/**'
|
|
- 'wai/wai-quantum/**'
|
|
- 'wai/wai-quantum-cli/**'
|
|
- 'wai/wai-quantum-service/**'
|
|
- 'wai/wai-quantum-qpu/**'
|
|
- 'wai/quantum-studio/**'
|
|
- 'rust-toolchain.toml'
|
|
- '.github/workflows/wai-quantum-views.yml'
|
|
|
|
jobs:
|
|
relevant:
|
|
name: does this change touch it
|
|
runs-on: linux-arm64
|
|
outputs:
|
|
run: ${{ steps.gate.outputs.run }}
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
with:
|
|
fetch-depth: 0
|
|
- id: gate
|
|
run: |
|
|
set -euo pipefail
|
|
r=$(python3 scripts/pr-touches-paths.py .github/workflows/wai-quantum-views.yml \
|
|
"${{ github.event.pull_request.base.sha }}" \
|
|
"${{ github.event.pull_request.head.sha }}")
|
|
echo "this change touches the views: $r"
|
|
echo "run=$r" >> "$GITHUB_OUTPUT"
|
|
|
|
page:
|
|
name: views · the page and its engine
|
|
needs: relevant
|
|
if: needs.relevant.outputs.run == 'true'
|
|
runs-on: linux
|
|
timeout-minutes: 60
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
- name: Install Rust 1.98.0 with the wasm32 target
|
|
shell: bash
|
|
run: |
|
|
export PATH="$HOME/.cargo/bin:$PATH"
|
|
command -v rustup >/dev/null 2>&1 || \
|
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0
|
|
rustup toolchain install 1.98.0 --profile minimal
|
|
rustup default 1.98.0
|
|
rustup target add wasm32-unknown-unknown
|
|
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
- name: The committed page is built from these sources
|
|
shell: bash
|
|
working-directory: wai/quantum-studio
|
|
run: |
|
|
set -euo pipefail
|
|
npm ci --no-audit --no-fund
|
|
node build-views.mjs --check
|
|
- name: The engine inside the views, and engine::views
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
(cd wai/wai-quantum-views && cargo test --locked --release 2>&1 | tee "$RUNNER_TEMP/views.log")
|
|
grep -qE '^test result: ok\. 3 passed; 0 failed' "$RUNNER_TEMP/views.log" || { echo "::error::the views' engine tests did not all run and pass"; exit 1; }
|
|
(cd wai/wai-quantum && cargo test --locked --release --features full --lib engine::views:: 2>&1 | tee "$RUNNER_TEMP/engine.log")
|
|
grep -qE '^test result: ok\. 4 passed; 0 failed' "$RUNNER_TEMP/engine.log" || { echo "::error::engine::views' tests did not all run and pass"; exit 1; }
|
|
- name: Rebuilt here, its script and styles to the same bytes
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
bash wai/wai-quantum-views/build.sh "$RUNNER_TEMP/views"
|
|
python3 - "$RUNNER_TEMP/views/manifest.json" wai/wai-quantum/views/manifest.json <<'EOF'
|
|
import json, sys
|
|
new, old = (json.load(open(p)) for p in sys.argv[1:])
|
|
bad = [k for k in ("script", "styles") if new["sha256"][k] != old["sha256"][k]]
|
|
if bad:
|
|
print(f"::error::the committed views page's {', '.join(bad)} are not what their sources build: run bash wai/wai-quantum-views/build.sh and commit what it writes")
|
|
sys.exit(1)
|
|
for k in ("engine_wasm", "engine_js"):
|
|
if new["sha256"][k] != old["sha256"][k]:
|
|
print(f"::warning::the engine inside the views ({k}) compiles to other bytes than the committed page holds: wai-quantum changed since it was built; rebuild it with bash wai/wai-quantum-views/build.sh")
|
|
print("the page's script and styles are what their sources build")
|
|
EOF
|
|
|
|
hosts:
|
|
name: views · a scripted host
|
|
needs: relevant
|
|
if: needs.relevant.outputs.run == 'true'
|
|
runs-on: linux
|
|
timeout-minutes: 75
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
- name: Install Rust 1.98.0
|
|
shell: bash
|
|
run: |
|
|
export PATH="$HOME/.cargo/bin:$PATH"
|
|
command -v rustup >/dev/null 2>&1 || \
|
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0
|
|
rustup toolchain install 1.98.0 --profile minimal
|
|
rustup default 1.98.0
|
|
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
- name: Both servers
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
(cd wai/wai-quantum-cli && cargo build --locked --release)
|
|
(cd wai/wai-quantum-service && cargo build --locked --release)
|
|
- name: Every view drawn by a scripted host in a browser
|
|
shell: bash
|
|
working-directory: wai/quantum-studio
|
|
env:
|
|
WAI_E2E_CHANNEL: ''
|
|
run: |
|
|
set -euo pipefail
|
|
npm ci --no-audit --no-fund
|
|
npx playwright install --with-deps chromium
|
|
WQ_CLI="$GITHUB_WORKSPACE/wai/wai-quantum-cli/target/release/wai-quantum" \
|
|
WQ_SERVICE="$GITHUB_WORKSPACE/wai/wai-quantum-service/target/release/wai-quantum-service" \
|
|
node test/views.test.mjs 2>&1 | tee "$RUNNER_TEMP/views.log"
|
|
grep -q '^every check passed$' "$RUNNER_TEMP/views.log" || { echo "::error::the scripted host's checks did not all pass"; exit 1; }
|