Skip to content

QVAC-23995: migrate vla-ggml to shared @qvac/fabric runtime - #3998

Open
jpgaribotti wants to merge 3 commits into
mainfrom
feature/QVAC-23995
Open

QVAC-23995: migrate vla-ggml to shared @qvac/fabric runtime#3998
jpgaribotti wants to merge 3 commits into
mainfrom
feature/QVAC-23995

Conversation

@jpgaribotti

@jpgaribotti jpgaribotti commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

🎯 What problem does this PR solve?

  • @qvac/vla-ggml still compiled and bundled the static qvac-fabric vcpkg port, duplicating the ggml runtime and compute backends that @qvac/fabric already ships once per process.
  • The package was absent from .github/fabric-consumers.json npm_runtime, so fabric-stack PRs could not validate VLA against PR-built @qvac/fabric prebuilds.
  • on-pr-vla still ran verify-qvac-fabric-lockstep and built ROCm/HIP via qvac-fabric[hip-backend] in vcpkg/prebuilds — patterns superseded by the shared npm runtime model used by @qvac/classification-ggml.

📝 How does it solve it?

  • Package (packages/vla-ggml, 0.22.00.23.0):
    • Add @qvac/fabric (^0.6.0); remove qvac-fabric (and hip-backend) from vcpkg.json.
    • Refactor CMakeLists.txt to qvac-addon fabric helpers (qvac_addon_use_fabric, dynamic DT_NEEDED: qvac__fabric@0.bare); drop the static ggml backend install loop.
    • Preload @qvac/fabric in binding.js; resolve ggml backends from node_modules/@qvac/fabric/prebuilds/ on desktop via resolveBackendsDir() (mobile fallback to local prebuilds/).
    • Stage @qvac/fabric for C++ unit tests (qvac_addon_stage_fabric_for_test, relaxed ASAN options).
  • CI:
    • Register vla-ggml in .github/fabric-consumers.json npm_runtime.
    • Replace verify-fabric-lockstep with detect-fabric-stack / resolve-fabric-prebuilds on on-pr-vla.yml (mirrors classification-ggml).
    • Thread fabric-overlay-artifact through cpp-tests-vla, prebuilds-vla, and integration-test-vla; remove vla-side ROCm prebuild/lint wiring (HIP comes from fabric prebuilds).

🧪 How was it tested?

Local (linux-x64):

  • npm install@qvac/fabric prebuilds present under node_modules/.
  • bare-make generate && bare-make build && bare-make installprebuilds/linux-x64/qvac__vla-ggml.bare only (no bundled ggml backend .so files); readelf shows NEEDED: qvac__fabric@0.bare.
  • npm run test:unit — 6/6 JS tests passed.
  • npm run test:cpp — 63 passed, 30 skipped (GR00T/Pi05 oracle fixtures not staged locally); fabric backends staged next to addon-test.
  • bare -e "require('@qvac/fabric'); require('./binding')" — binding loads successfully.

CI:

  • verify + cpp labels on on-pr-vla (sanity, cpp-lint, cpp-tests matrix).
  • prebuilds label — fresh native prebuilds without bundled ggml backends.
  • desktop label — integration tests with @qvac/fabric available.
  • fabric-stack exercise: PR touching packages/fabric + prebuilds label to confirm overlay path via resolve-fabric-prebuilds.

Updated How was it tested section for PR #3998:


🧪 How was it tested?

Local (linux-x64)

  • npm install@qvac/fabric prebuilds present under node_modules/.
  • bare-make generate && bare-make build && bare-make installprebuilds/linux-x64/qvac__vla-ggml.bare only (no bundled ggml backend .so files); readelf shows NEEDED: qvac__fabric@0.bare.
  • npm run test:unit — 6/6 JS tests passed.
  • npm run test:scripts — 12/12 run-cpp-tests.js runner regression tests passed.
  • npm run test:cpp — 63 passed, 30 skipped (GR00T/Pi05 oracle fixtures not staged locally); fabric backends staged next to addon-test via qvac_addon_stage_fabric_for_test. Run with ASAN_OPTIONS=alloc_dealloc_mismatch=0:detect_leaks=0:abort_on_error=1 (now applied automatically by scripts/run-cpp-tests.js).
  • bare -e "require('@qvac/fabric'); require('./binding')" — binding loads successfully.

CI (verify + cpp + prebuilds + desktop labels on on-pr-vla)

Migration commit (8471146) — run 32499686737:

  • Sanity, cpp-lint, ts-checks, detect-fabric-stack, verify-fabric-lockstep
  • cpp-tests: darwin-arm64, darwin-x64, windows-x64
  • linux-x64-cpp-tests failed — all 93 tests passed, then ASAN alloc-dealloc-mismatch at @qvac/fabric teardown (instrumented addon-test vs non-ASan fabric prebuild)
  • Prebuild matrix (all 9 targets) — vla prebuild only, no bundled ggml backends
  • Integration tests (desktop + mobile matrix entries that ran)
  • merge-guard / validate-pr

ASAN fix commit (f503c97) — run 32731496250 (auto pull_request_target on push):

  • Same label-gated stages above; darwin/windows cpp-tests, prebuilds, integration tests green
  • linux-x64-cpp-tests still redpull_request_target ran the base-branch cpp-tests-vla.yml (direct ./addon-test, not npm run test:cpp:run), so the ASAN fix was not exercised on that auto-triggered run

Full pipeline validation (f503c97) — run 32739988913 (manual workflow_dispatch on branch workflow):

  • Full on-pr-vla pipeline success (19m 22s)
  • linux-x64-cpp-tests — 93 tests via npm run test:cpp:run / run-cpp-tests.js; no ASAN fabric-boundary abort; cpp-test-results-linux-x64 artifact uploaded
  • cpp-tests matrix (linux-x64, darwin-arm64, darwin-x64, windows-x64), prebuild matrix, integration matrix, merge-guard

Fabric-stack overlay

  • PR touching packages/fabric + prebuilds label to confirm resolve-fabric-prebuilds overlay path: Test/fabric stack #4033
    Actions validated wiring and smoke tests pass.

Note for reviewers

Linux cpp ASAN is handled the same way as @qvac/classification-ggml: scripts/run-cpp-tests.js sets relaxed ASAN_OPTIONS at the fabric boundary. Auto PR checks use pull_request_target and load reusable workflow YAML from main until this PR merges; the manual dispatch above validates the branch workflow end-to-end on f503c97.

Move ggml off the static qvac-fabric vcpkg port onto @qvac/fabric (^0.6.0):
use qvac-addon fabric helpers, preload fabric in binding.js, resolve backends
from node_modules on desktop, and stage fabric for C++ unit tests. Remove
qvac-fabric[hip-backend] from vcpkg (ROCm/HIP now comes from fabric prebuilds).
Register vla-ggml in fabric-consumers npm_runtime and wire on-pr-vla
fabric-stack overlay through cpp-tests, prebuilds, and integration jobs.
Bump @qvac/vla-ggml to 0.23.0.
@jpgaribotti jpgaribotti self-assigned this Aug 21, 2026
@jpgaribotti
jpgaribotti requested review from a team as code owners August 21, 2026 15:13
@jpgaribotti jpgaribotti added verify prebuilds CI: run only prebuild/cache stage (requires verified) run-cpp-addon-tests CI: run C++ addon tests (requires verified) run-desktop-addon-tests CI: run desktop integration tests (requires verified) run-mobile-addon-tests CI: run mobile integration tests (requires verified) labels Aug 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Review Status

Current Status: ❌ PENDING
Approvals so far: none

Pending reviews: Needs 1 Management or Team Lead, and 1 more from Management, Team Lead, or Member.

@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

License compliance — findings detected (warn-only)

Critical: 0 · High: 3 · Medium: 0

Dependency License Scope Severity Outcome
actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f (none detected) runtime High blocks
tetherto/qvac/.github/actions/detect-fabric-stack@6620d695d3a07cafe3931182e7844dde376a23f8 (none detected) runtime High blocks
tetherto/qvac/.github/actions/wait-and-download-fabric-prebuilds@6620d695d3a07cafe3931182e7844dde376a23f8 (none detected) runtime High blocks

How to resolve a blocking finding:

  • Remove or replace the disallowed dependency, or
  • If the license is genuinely acceptable, run the compliance SKILL and record the decision in .github/license-allowlist.yml (CODEOWNERS-reviewed), or
  • For a one-off, a maintainer can apply the license-override label (High findings only; Critical cannot be overridden).

Warn-only (shadow) mode — this check does not block merges yet.

Updated automatically by the canonical license compliance workflow.

NOTICE presence (advisory)

Missing NOTICE (advisory, does not block):

  • ./.github/actions/release-merge-guard
  • ./docs/website
  • ./packages/ggml-coload-smoke
  • ./packages/fabric/test/integration
  • ./packages/inference-addon-cpp/mobile
  • ./packages/sdk/e2e
  • ./packages/llm-llamacpp/benchmarks/performance
  • ./packages/llm-llamacpp/benchmarks/server
  • ./packages/vla-ggml/sim/server
  • ./packages/embed-llamacpp/benchmarks/performance
  • ./packages/embed-llamacpp/benchmarks/server
  • ./packages/asr-ggml/benchmarks/server

@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Workflow security (shadow mode)

zizmor found 1095 finding(s) in .github/ (highest severity: high). This check is warn-only and does not block the merge.

Findings are annotated inline on the changed files and listed in the job summary.

Reproduce locally:

pipx run zizmor==1.27.0 --offline .github/

… ASAN

Port classification-ggml's addon-test runner so ASAN_OPTIONS relaxes
alloc-dealloc-mismatch and leak detection at the @qvac/fabric boundary.
Wire test:cpp:run and cpp-tests-vla through the script instead of invoking
addon-test directly with a workflow env var that did not reach Linux CI.
qvac_addon_use_fabric()

add_bare_module(qvac-lib-infer-vla EXPORTS ${BACKEND_DL_LIBS})
add_bare_module(qvac-lib-infer-vla EXPORTS)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The mobile branch of resolveBackendsDir() returns <pkg>/prebuilds, and this PR removes the only code that ever populated it with ggml backend modules.

The base branch staged them explicitly, with Android as the named target:

set(BACKEND_DL_LIBS "")
if((ANDROID OR UNIX) AND NOT APPLE)
  foreach(_backend ${GGML_AVAILABLE_BACKENDS})
    list(APPEND BACKEND_DL_LIBS INSTALL TARGET ggml::${_backend})
  endforeach()
endif()
add_bare_module(qvac-lib-infer-vla EXPORTS ${BACKEND_DL_LIBS})

Nothing replaces it: there is no INSTALL TARGET left anywhere in cmake/qvac-addon/qvac-addon.cmake. qvac_addon_use_fabric() only resolves the package and computes BACKENDS_SUBDIR_VALUE, qvac_addon_link_fabric() only links, and the sole thing that copies backends is the test-only qvac_addon_stage_fabric_for_test(). qvac_addon_finalize() still defines GGML_BACKEND_DL for Android, so Android must dlopen real .so files, and mobile:copy-prebuilds only fans android-arm64 out to the other arch names.

Impact: on Android, native appends android-arm64/qvac__fabric to the returned root, ggml_backend_load_all_from_path() registers nothing, and the first load throws "no CPU backend available". packages/fabric/INTEGRATION.md lists that companion install as mandatory checklist item 5. Mobile integration is workflow_dispatch-only, so no PR check catches it.

Suggested fix: re-add an install of the fabric companion and its backend modules into prebuilds/<host>/qvac__fabric/, so the path the mobile fallback resolves to is populated at pack time. Worth a dispatch of integration-mobile-test-vla.yml first — if mobile staging happens outside this repo, this is a false alarm and the comment at index.js:20-22 should say where.

"bugs": "https://github.com/tetherto/qvac/issues",
"homepage": "https://qvac.tether.io",
"dependencies": {
"@qvac/fabric": "^0.6.0",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

please bump to 0.8.0

Comment on lines +16 to +17
- The `qvac-fabric[hip-backend]` vcpkg feature is removed from this package; ROCm/HIP
backends are provided by `@qvac/fabric` when present in its prebuilds.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The CHANGELOG states ROCm/HIP backends "are provided by @qvac/fabric when present in its prebuilds"; no build path in the monorepo puts them there, so HIP execution is silently dropped.

Two verified facts against the premise:

  • packages/fabric/vcpkg.json declares only a vk-profiling feature. It never requests hip-backend.
  • .github/workflows/prebuilds-fabric.yml passes only artifact-name-prefix: fabric- and include-vulkan-sdk: true. It never sets include-rocm, whose default is false in reusable-prebuilds.yml.

Repo-wide, hip-backend appears in no other consumer's manifest — vla-ggml was the only one requesting it — and include-rocm has no enabling caller anywhere under .github/.

Impact: libqvac-ggml-hip.so ships in no @qvac/fabric prebuild, so the HIP-preference branch in addon/src/utils/BackendSelection.cpp:121-148 becomes unreachable — hipDev is always null and pickBestGpuDevice() falls through to Vulkan. Nothing breaks, but the ~18% warm-path win #2781 was built for (479 → 384 ms on gfx1151) is given back on that target, and the ROCm build and lint steps were removed in the same change, so CI cannot detect it.

Suggested fix: either add hip-backend to packages/fabric/vcpkg.json and include-rocm: true to prebuilds-fabric.yml, so the shared runtime actually ships what this line promises; or drop the claim, state plainly that HIP is dropped, and remove the now-dead branch in BackendSelection.cpp. Either way this line needs changing — as written it asserts something untrue about where the backend comes from.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

prebuilds CI: run only prebuild/cache stage (requires verified) run-cpp-addon-tests CI: run C++ addon tests (requires verified) run-desktop-addon-tests CI: run desktop integration tests (requires verified) run-mobile-addon-tests CI: run mobile integration tests (requires verified) verify

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants