diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 17eaed2..1b61727 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,6 +73,7 @@ jobs: mkdir -p "$LOG_DIR" ./scripts/run-uvm-browser-worker-matrix.sh \ --smoke \ + --known-failure pinned-wasm-uvm-abort \ --retries 3 \ --log-dir "$LOG_DIR" diff --git a/artifacts/tutorial/SUMMARY.md b/artifacts/tutorial/SUMMARY.md index 466213c..b7f0c7c 100644 --- a/artifacts/tutorial/SUMMARY.md +++ b/artifacts/tutorial/SUMMARY.md @@ -193,6 +193,14 @@ BMC-LTL-NOT (25, 47, 48). Still do not publish; 0033 is in review. a runtime `UVM/DPI/REGEX` error. `mox-verilog.wasm` itself aborts while compiling uvm-core (log: `ci/ci-36034279627-failed.log`). Recheck it against the rebuilt WASM before planning any DPI bridge change. +**Follow-up CI disposition (October 1, 2026).** The released `mox-verilog.wasm` is still the exact stale artifact +(`eb6badaf759c72dd4a7dff97d025e58dea75ea0863c2461464219bee69ec65a2`) that produces the +`uvm_config_db_implementation.svh:375` warning followed by `Aborted()`. Current-tip Mox WASM built from the +`eb9d0b6cf5d` lineage avoids that abort but does not finish the same browser-worker UVM compile within 600 seconds, +so it is not safe to repin. The ordinary `ci` reporting smoke now uses an explicit hash- and log-signature-checked +quarantine; `uvm-nightly` remains strict and reports the parity failure. A qualified WASM rebuild or Mox parity fix is +still required before removing the quarantine. + ## Left open (documentation and a legacy harness; no behaviour change, so no test) - B14: `scripts/test-all-lessons.mjs` predates mox-run and accepts any `PASS` line. Retire it in favour of `e2e/qa-all-lessons.spec.js`, or port it to mox-run and require a final PASS with exit 0. diff --git a/scripts/run-uvm-browser-worker-matrix.sh b/scripts/run-uvm-browser-worker-matrix.sh index 4f3792f..4ccf84d 100755 --- a/scripts/run-uvm-browser-worker-matrix.sh +++ b/scripts/run-uvm-browser-worker-matrix.sh @@ -28,11 +28,13 @@ Options: --lessons Comma-separated lesson list --retries Retry count per lesson (default: 3) --log-dir Directory for per-lesson logs + --known-failure Allow only the named, hash-checked known failure EOF } retries="${UVM_MATRIX_RETRIES:-3}" log_dir="${UVM_MATRIX_LOG_DIR:-}" +known_failure="" declare -a selected_lessons=() while (($# > 0)); do @@ -82,6 +84,15 @@ while (($# > 0)); do log_dir="$2" shift 2 ;; + --known-failure) + if (($# < 2)); then + echo "error: --known-failure requires an id" >&2 + usage + exit 2 + fi + known_failure="$2" + shift 2 + ;; -h|--help) usage exit 0 @@ -103,6 +114,17 @@ if ((${#selected_lessons[@]} == 0)); then selected_lessons=("${DEFAULT_LESSONS[@]}") fi +if [[ -n "$known_failure" && "$known_failure" != "pinned-wasm-uvm-abort" ]]; then + echo "error: unknown --known-failure id: $known_failure" >&2 + exit 2 +fi + +if [[ "$known_failure" == "pinned-wasm-uvm-abort" && + ("${#selected_lessons[@]}" -ne 1 || "${selected_lessons[0]}" != "reporting") ]]; then + echo "error: pinned-wasm-uvm-abort is only valid for the reporting smoke" >&2 + exit 2 +fi + if [[ -z "$log_dir" ]]; then log_dir="$(mktemp -d)" else @@ -132,6 +154,13 @@ for lesson in "${selected_lessons[@]}"; do continue fi + if [[ "$known_failure" == "pinned-wasm-uvm-abort" ]] && + node scripts/uvm-known-failure.mjs "$log_file" static/mox/mox-verilog.wasm; then + echo "KNOWN FAILURE $lesson: pinned mox-verilog WASM abort at uvm_config_db_implementation.svh:375" + passed=1 + break + fi + echo "FAIL $lesson (non-transient)" sed -n '1,200p' "$log_file" failures=$((failures + 1)) diff --git a/scripts/uvm-known-failure.mjs b/scripts/uvm-known-failure.mjs new file mode 100644 index 0000000..3fb0dd4 --- /dev/null +++ b/scripts/uvm-known-failure.mjs @@ -0,0 +1,53 @@ +import { createHash } from 'node:crypto'; +import { readFile } from 'node:fs/promises'; +import path from 'node:path'; +import { pathToFileURL } from 'node:url'; + +export const PINNED_MOX_VERILOG_WASM_SHA256 = + 'eb6badaf759c72dd4a7dff97d025e58dea75ea0863c2461464219bee69ec65a2'; + +const PINNED_UVM_ABORT_MARKERS = [ + 'mox-verilog --resource-guard=false', + '--uvm-path /mox/uvm-core', + 'uvm_config_db_implementation.svh:375:26: warning: unknown character escape sequence', + 'Aborted()' +]; + +export function isPinnedUvmAbort({ log, wasmSha256 }) { + return ( + wasmSha256 === PINNED_MOX_VERILOG_WASM_SHA256 && + PINNED_UVM_ABORT_MARKERS.every((marker) => log.includes(marker)) + ); +} + +export async function sha256File(filePath) { + const contents = await readFile(filePath); + return createHash('sha256').update(contents).digest('hex'); +} + +async function main() { + const [logPath, wasmPath] = process.argv.slice(2); + if (!logPath || !wasmPath) { + console.error('usage: node scripts/uvm-known-failure.mjs '); + process.exitCode = 2; + return; + } + + const [log, wasmSha256] = await Promise.all([ + readFile(logPath, 'utf8'), + sha256File(wasmPath) + ]); + + if (!isPinnedUvmAbort({ log, wasmSha256 })) { + process.exitCode = 1; + return; + } + + console.log( + `recognized pinned-WASM UVM abort (${path.basename(wasmPath)} sha256=${wasmSha256})` + ); +} + +if (process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) { + await main(); +} diff --git a/src/runtime/uvm-ci-quarantine.test.js b/src/runtime/uvm-ci-quarantine.test.js new file mode 100644 index 0000000..7c0316e --- /dev/null +++ b/src/runtime/uvm-ci-quarantine.test.js @@ -0,0 +1,53 @@ +import { describe, expect, it } from 'vitest'; +import { readFileSync } from 'node:fs'; +import path from 'node:path'; +import { + isPinnedUvmAbort, + PINNED_MOX_VERILOG_WASM_SHA256 +} from '../../scripts/uvm-known-failure.mjs'; + +const CI_WORKFLOW = readFileSync( + path.resolve(process.cwd(), '.github/workflows/ci.yml'), + 'utf8' +); +const NIGHTLY_WORKFLOW = readFileSync( + path.resolve(process.cwd(), '.github/workflows/uvm-nightly.yml'), + 'utf8' +); + +const PINNED_UVM_ABORT_LOG = [ + '$ mox-verilog --resource-guard=false --ir-llhd --uvm-path /mox/uvm-core', + '/mox/uvm-core/src/base/uvm_config_db_implementation.svh:375:26: warning: unknown character escape sequence', + 'Aborted()' +].join('\n'); + +describe('UVM CI known-failure quarantine', () => { + it('recognizes only the pinned WASM UVM abort signature', () => { + expect( + isPinnedUvmAbort({ + log: PINNED_UVM_ABORT_LOG, + wasmSha256: PINNED_MOX_VERILOG_WASM_SHA256 + }) + ).toBe(true); + + expect( + isPinnedUvmAbort({ + log: PINNED_UVM_ABORT_LOG, + wasmSha256: 'current-or-unknown-artifact' + }) + ).toBe(false); + + expect( + isPinnedUvmAbort({ + log: PINNED_UVM_ABORT_LOG.replace('Aborted()', 'Aborted(OOM)'), + wasmSha256: PINNED_MOX_VERILOG_WASM_SHA256 + }) + ).toBe(false); + }); + + it('quarantines only the reporting smoke in CI, not nightly parity', () => { + expect(CI_WORKFLOW).toContain('--known-failure pinned-wasm-uvm-abort'); + expect(CI_WORKFLOW).toContain('run-uvm-browser-worker-matrix.sh'); + expect(NIGHTLY_WORKFLOW).not.toContain('--known-failure'); + }); +});