Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
123 commits
Select commit Hold shift + click to select a range
eedc9a3
refactor(nn): make bmrt ownership explicit
Fernandez81 Jul 31, 2026
b6b5aa1
build(model-guard): admit the v2.3.3 runtime SDK
Fernandez81 Jul 31, 2026
4ef5570
feat(model-guard): load preset CEMC through CMG_2.0
Fernandez81 Jul 31, 2026
6a136fa
feat(models): publish protected BM1688 presets
Fernandez81 Jul 31, 2026
a95203a
feat(release): add signed atomic release transactions
Fernandez81 Jul 31, 2026
b66d7ea
feat(upgrade): accept signed release archives
Fernandez81 Jul 31, 2026
e5a3a49
build(sophon): produce verified protected packages
Fernandez81 Jul 31, 2026
aefb227
feat(source): install SOURCE runtime without backups
Fernandez81 Jul 31, 2026
964fa43
docs(security): document protected model release flows
Fernandez81 Jul 31, 2026
d0f9efe
docs(source): align Chinese installer behavior
Fernandez81 Jul 31, 2026
4e618bc
refactor(model-guard): remove redundant admission gates
Fernandez81 Jul 31, 2026
472dae4
docs(model-guard): update deployment operations
Fernandez81 Jul 31, 2026
f5f6cd9
feat(model-guard): support legacy upgrades and authorization
athenawxd Aug 4, 2026
8f6e0dc
style(model-guard): format authorization sources
athenawxd Aug 4, 2026
dd31eda
fix(package): default to legacy-compatible archive
athenawxd Aug 4, 2026
4d344d2
refactor(upgrade): unify permanent md5 package flow
athenawxd Aug 4, 2026
7208e33
fix(upgrade): support legacy sh installer invocation
athenawxd Aug 4, 2026
9415c63
build(guard): select staged production sdk
athenawxd Aug 5, 2026
1ef9557
fix(guard): stream device authorization request
athenawxd Aug 5, 2026
60c6b24
build: add RK3576 RKNN toolchain
samuel--hu Aug 5, 2026
0064b59
feat: integrate RK3576 RKNN backend
samuel--hu Aug 5, 2026
ae2e800
perf: harden RK3576 runtime admission
samuel--hu Aug 5, 2026
670d0ec
feat: add Rockchip native media pipeline
samuel--hu Aug 5, 2026
5a5169e
test: harden RK3576 long-run qualification
samuel--hu Aug 5, 2026
5856058
fix: harden websocket HTTP probe handling
samuel--hu Aug 5, 2026
9478cfc
test: add RK3576 customer journey fixture
samuel--hu Aug 5, 2026
bba6c3a
chore: curate RK3576 integration assets
samuel--hu Aug 5, 2026
8a7d77a
fix: harden runtime logs and startup contracts
samuel--hu Aug 5, 2026
81f3f24
fix: mark unreliable RK3576 NPU telemetry unavailable
samuel--hu Aug 5, 2026
ec4ac42
fix: clean up scenario bench on shutdown signals
samuel--hu Aug 5, 2026
d3b52fb
fix: report RK3576 NPU busy-time load
samuel--hu Aug 5, 2026
515a149
fix: model RK3576 accelerator memory as shared
samuel--hu Aug 5, 2026
dec90b4
Merge remote-tracking branch 'origin/main' into codex/rk3576-integration
samuel--hu Aug 5, 2026
933ca6a
perf: add RKNN preprocessing stage metrics
samuel--hu Aug 5, 2026
44575a5
perf: add RK3576 RGA detector preprocessing
samuel--hu Aug 5, 2026
29a155c
perf: feed RKNN detector with native int8 NHWC input
samuel--hu Aug 5, 2026
63107ee
fix: preserve RKNN classifier preprocessing compatibility
samuel--hu Aug 5, 2026
dbc5b21
test: qualify RK3576 detector fast path
samuel--hu Aug 5, 2026
14ed613
perf: add quantized RKNN output reconstruction
samuel--hu Aug 5, 2026
05583dc
perf: use native RKNN detector outputs
samuel--hu Aug 5, 2026
6025cd2
perf: optimize RKNN YOLOv8 output consumption
samuel--hu Aug 5, 2026
686d68b
fix: make algorithm orchestration paths portable
samuel--hu Aug 5, 2026
fd6e575
test: disable default OSD pixel heuristic
samuel--hu Aug 5, 2026
3615b50
perf: decode RKNN YOLOv8 candidates directly
samuel--hu Aug 6, 2026
1825b00
perf: register RKNN output tensor contracts
samuel--hu Aug 6, 2026
11ebdff
perf: bind RKNN detector input memory
samuel--hu Aug 6, 2026
7be57b2
perf: bind RKNN detector input to persistent RGA target
samuel--hu Aug 6, 2026
5f61160
fix(upgrade): restore legacy installer lifecycle
athenawxd Aug 6, 2026
68139c3
fix(package): allow plaintext VLLM presets
athenawxd Aug 6, 2026
f512d7e
perf: feed RKNN detector from MPP DMA-BUF
samuel--hu Aug 6, 2026
d696ad3
fix(package): require protected VLLM presets
athenawxd Aug 6, 2026
cbd74a1
perf: qualify RKNN detector core scheduling
samuel--hu Aug 6, 2026
25e2657
fix: measure shared detector throughput per channel
samuel--hu Aug 6, 2026
deb63eb
fix: exclude event reports from CV throughput
samuel--hu Aug 6, 2026
956417f
perf: expose RKNN fused input telemetry
samuel--hu Aug 6, 2026
e00ff7c
perf: gate RKNN uint8 binding by model contract
samuel--hu Aug 6, 2026
3b9d8a0
fix: preserve RKNN FP16 input contract
samuel--hu Aug 6, 2026
69e9c72
test: separate pool warmup from long-run growth
samuel--hu Aug 6, 2026
8f8b4b8
fix: reuse RK3576 decoder across stream loops
samuel--hu Aug 6, 2026
9124d1b
merge: integrate latest main into model guard v2.3
athenawxd Aug 7, 2026
fd434fc
Merge origin/main into rk3576-integration
samuel--hu Aug 7, 2026
34e315b
merge: integrate rk3576 support into model guard v2.3
athenawxd Aug 7, 2026
67e15f6
fix(build): link cpu allocator in cross-backend tests
athenawxd Aug 7, 2026
8d5bd15
docs(readme): draft next-release landing pages
samuel--hu Aug 7, 2026
bd4e103
docs(readme): address draft review feedback
samuel--hu Aug 7, 2026
2564d35
docs(readme): refresh RK3576 evidence and links
samuel--hu Aug 7, 2026
a8b283b
docs(changelog): document changes since v1.0.0
samuel--hu Aug 7, 2026
6f77799
fix(stream): reduce preview and OSD startup latency
samuel--hu Aug 9, 2026
dffd87b
feat(macos): add Docker Desktop preview workflow
samuel--hu Aug 9, 2026
dbc94dd
build: derive compatible version from git tags
athenawxd Aug 10, 2026
61be86c
fix(resources): publish unprotected open-source models
athenawxd Aug 10, 2026
f6b481f
docs: complete Sophon and macOS quick starts
athenawxd Aug 10, 2026
9fd1c28
docs: restore Sophon SSH installation flow
athenawxd Aug 10, 2026
93a0c9d
chore(build): ignore rknn build output
Fernandez81 Aug 11, 2026
f318c00
build(rk3576): add reproducible docker package entry
Fernandez81 Aug 11, 2026
aa9d2c1
ci(rk3576): add nightly cross-build workflow
Fernandez81 Aug 11, 2026
c690e78
docs(rk3576): document stable release workflow
Fernandez81 Aug 11, 2026
b7b65ea
fix(system): preserve model authorization on factory reset
Fernandez81 Aug 11, 2026
ea4414d
feat(web): restore network speaker menus
athenawxd Aug 12, 2026
b76ba84
fix(web): clear channel id when adding camera
athenawxd Aug 12, 2026
a2c0733
fix(audio): initialize device operations with valid values
athenawxd Aug 12, 2026
36afe4b
feat: enable Qwen3.5 RKLLM vision inference on RK3576
samuel--hu Aug 11, 2026
22d4a75
fix(rknn): restore model uploads and release version
samuel--hu Aug 12, 2026
43772c7
perf(rkllm): reduce visual prefill latency
samuel--hu Aug 12, 2026
46d8f87
fix(rk3576): expose only validated model types
samuel--hu Aug 12, 2026
791f035
fix(rkllm): keep baseline RK3576 builds compatible
samuel--hu Aug 12, 2026
e547c8b
fix(linkage): allow empty workflow drafts
athenawxd Aug 12, 2026
6cd8419
fix(web): rebuild empty linkage canvas
athenawxd Aug 12, 2026
1f10148
fix(web): restore linkage editor interactions
athenawxd Aug 12, 2026
e2d6170
Merge pull request #96 from cosmo-wander-ai/perf/rk3576-qwen35-validated
Fernandez81 Aug 12, 2026
0951a39
docs(benchmarks): add v1.1 multi-platform candidate
nquyencubas523-cloud Aug 13, 2026
a4124a7
fix(web): align linkage flow and upgrade cache handling
athenawxd Aug 13, 2026
c0e77f2
fix(web): persist linkage alarm selections
athenawxd Aug 13, 2026
209bc2b
style(cpp): format candidate sources with clang-format
Fernandez81 Aug 13, 2026
9206dbe
docs(release): finalize v1.1 multi-platform materials
nquyencubas523-cloud Aug 13, 2026
993840b
Merge remote-tracking branch 'origin/feat/model-guard-v2.3' into docs…
nquyencubas523-cloud Aug 13, 2026
acd4197
Merge remote-tracking branch 'origin/feat/model-guard-v2.3' into docs…
nquyencubas523-cloud Aug 13, 2026
6cf2801
docs(cv186x): bind open benchmark models
nquyencubas523-cloud Aug 13, 2026
647b9ad
refactor(resources): split BM1688 and CV186X sets
nquyencubas523-cloud Aug 13, 2026
8a0a7f7
docs(benchmarks): link rendered v1.1 reports
nquyencubas523-cloud Aug 13, 2026
c8de334
test(audio): add network speaker simulator
athenawxd Aug 13, 2026
efdcd1d
Merge branch 'feat/model-guard-v2.3' of https://github.com/cosmo-wand…
athenawxd Aug 13, 2026
7bec8d8
docs(benchmarks): complete v1.1 release audit
nquyencubas523-cloud Aug 13, 2026
ed4ce07
feat(build): select Sophon resources by chip
athenawxd Aug 13, 2026
4446db2
Merge branch 'docs/v1.1-multiplatform-benchmark-candidate' into feat/…
athenawxd Aug 13, 2026
a0f8b04
fix: harden multi-platform release validation
nquyencubas523-cloud Aug 14, 2026
22f41f9
fix: embed target chip in release archives
nquyencubas523-cloud Aug 14, 2026
87e6b58
fix: cache and further bound npm fetches
nquyencubas523-cloud Aug 14, 2026
3f7c7de
fix: serialize npm fetches on validated mirror
nquyencubas523-cloud Aug 14, 2026
72aab13
fix: install web dependencies from a serialized cache
nquyencubas523-cloud Aug 14, 2026
7ac23b1
docs: qualify CV186X and RK3576 model evidence
nquyencubas523-cloud Aug 14, 2026
b3c7ce9
build: pin published RK3576 RKLLM image
nquyencubas523-cloud Aug 14, 2026
a01c310
fix(package): isolate profile entrypoint regression test
athenawxd Aug 17, 2026
29b85cf
Merge pull request #98 from cosmo-wander-ai/fix/model-guard-v2.3-vali…
samuel--hu Aug 17, 2026
49258cb
fix(package): include chip in protected output assertion
athenawxd Aug 17, 2026
bf3f7c8
fix(installer): reduce appfs upgrade staging usage
athenawxd Aug 17, 2026
095a0cd
docs(sophon): consolidate build guidance
Fernandez81 Aug 17, 2026
c8b1775
Merge branch 'feat/model-guard-v2.3' of https://github.com/cosmo-wand…
athenawxd Aug 17, 2026
0adaa7a
feat(upgrade): reclaim event media when data space is low
athenawxd Aug 17, 2026
967f6ba
style(upgrade): format storage changes
athenawxd Aug 17, 2026
d997efa
docs(deployment): deduplicate ssh installation steps
Fernandez81 Aug 18, 2026
26bed1a
fix(media): prevent looping local video tasks from stopping at EOF (#…
nquyencubas523-cloud Aug 18, 2026
0a7350b
fix(face-lib): process staged person pictures
athenawxd Aug 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
/tags
/compile_commands.json
/build_output
/output
6 changes: 6 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
*.css text eol=lf
*.scss text eol=lf
*.html text eol=lf
*.txt text eol=lf
*.log text eol=lf
*.svg text eol=lf
CMakeLists.txt text eol=lf
Makefile text eol=lf

Expand All @@ -31,8 +34,11 @@ Makefile text eol=lf

# 二进制文件不做转换
*.bmodel binary
*.nn binary
*.onnx binary
*.rknn binary
*.so binary
*.so.* binary
*.a binary
*.png binary
*.jpg binary
Expand Down
76 changes: 76 additions & 0 deletions .github/workflows/ci-build-rk3576.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Nightly RK3576 Cross Build

on:
# Run daily at 02:12 Beijing Time (18:12 UTC on the previous day).
schedule:
- cron: '12 18 * * *'
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build-rk3576:
runs-on: ubuntu-latest
timeout-minutes: 90

steps:
- name: Checkout code
uses: actions/checkout@v7
with:
submodules: recursive

- name: Validate RK3576 Compose entry
run: docker compose -f docker-compose.rk3576.yml config --quiet

- name: Pull pinned RK3576 builder with RKLLM
run: docker compose -f docker-compose.rk3576.yml pull cosmo-rk3576-package

- name: Build RK3576 package and tests
run: docker compose -f docker-compose.rk3576.yml run --rm cosmo-rk3576-package

- name: Verify RK3576 artifacts
run: |
set -euo pipefail
shopt -s nullglob
packages=(build_output/rk3576/cosmo-*.tar.gz)
if (( ${#packages[@]} != 1 )) || [[ ! -f "${packages[0]:-}" || -L "${packages[0]:-}" ]]; then
echo "Expected exactly one regular RK3576 package artifact." >&2
exit 1
fi
package="${packages[0]}"
package_name="${package##*/}"
digest="$(sha256sum -- "$package")"
digest="${digest%% *}"
printf '%s %s\n' "$digest" "$package" | tee rk3576-package.sha256
package_listing="$(tar -tzf "$package")"
grep -Eq '/lib/librkllmrt[.]so$' <<< "$package_listing"
grep -Eq '/share/licenses/rkllm/LICENSE$' <<< "$package_listing"
for binary in build_rknn/cosmo-tests build_rknn/cosmo-rknn-backend-smoke build_rknn/cosmo-rknn-fastpath-qualify; do
binary_info="$(file "$binary")"
printf '%s\n' "$binary_info"
grep -Fq 'ARM aarch64' <<< "$binary_info"
done
docker compose -f docker-compose.rk3576.yml run --rm --entrypoint /usr/bin/python3 \
cosmo-rk3576-package -I -B scripts/verify_package_contents.py \
--archive "/build_output/rk3576/$package_name" --build-profile public-runtime
printf '## RK3576 candidate\n\n- Package: `%s`\n- SHA-256: `%s`\n' \
"$package_name" "$digest" >> "$GITHUB_STEP_SUMMARY"

- name: Upload RK3576 candidate
uses: actions/upload-artifact@v7
with:
name: rk3576-candidate-${{ github.sha }}
path: |
build_output/rk3576/*.tar.gz
rk3576-package.sha256
build_rknn/cosmo-tests
build_rknn/cosmo-rknn-backend-smoke
build_rknn/cosmo-rknn-fastpath-qualify
if-no-files-found: error
overwrite: true
retention-days: 7
200 changes: 183 additions & 17 deletions .github/workflows/nightly-build-test-sophon.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ jobs:
build-sophon:
runs-on: ubuntu-latest
timeout-minutes: 60
outputs:
candidate_guard_sha256: ${{ steps.candidate_guard_runtime.outputs.sha256 }}
candidate_tests_sha256: ${{ steps.candidate_test_binary.outputs.sha256 }}
env:
COSMO_MODEL_GUARD_BUILD_PROFILE: public-runtime

# Specify the public container image for the build environment
container:
Expand All @@ -26,13 +31,13 @@ jobs:
submodules: recursive # Recommended if the repository uses git submodules

# Enforce project standards: use the unified build script instead of cmake directly.
# A single configure builds the clean production package and cosmo-tests
# A single configure builds the clean public-runtime package and cosmo-tests
# together, sharing one set of compiled OBJECT libraries; coverage is off
# by default (COSMO_ENABLE_COVERAGE), so the package binary stays clean.
- name: Build package and tests
run: |
chmod +x scripts/build.sh
./scripts/build.sh -T
./scripts/build.sh -T -c bm1688

# Upload the build artifacts for deployment or download
- name: Upload Artifacts
Expand All @@ -41,13 +46,62 @@ jobs:
name: sophon-build-package
# Path where the built binaries/packages are generated by scripts/build.sh
path: build/install/
overwrite: true
retention-days: 3

- name: Record Candidate Test Binary
id: candidate_test_binary
run: |
set -euo pipefail
binary="build/cosmo-tests"
if [ ! -f "$binary" ] || [ -L "$binary" ]; then
echo "Candidate test binary is not a regular file: $binary" >&2
exit 1
fi
digest="$(sha256sum "$binary" | awk '{print $1}')"
if [ "${#digest}" -ne 64 ] || [[ "$digest" == *[!0-9a-f]* ]]; then
echo "Invalid Candidate test binary SHA-256: $digest" >&2
exit 1
fi
echo "sha256=$digest" >> "$GITHUB_OUTPUT"
echo "Candidate test binary SHA-256: $digest"

- name: Upload Test Binary
uses: actions/upload-artifact@v7
with:
name: sophon-tests-binary
path: build/cosmo-tests
if-no-files-found: error
overwrite: true
retention-days: 1

- name: Record Candidate Guard Runtime
id: candidate_guard_runtime
run: |
set -euo pipefail
runtime="build/install/lib/libcosmo_model_guard.so.2.0.0"
if [ ! -f "$runtime" ] || [ -L "$runtime" ]; then
echo "Candidate Guard runtime is not a regular file: $runtime" >&2
exit 1
fi
digest="$(sha256sum "$runtime" | awk '{print $1}')"
if [ "${#digest}" -ne 64 ] || [[ "$digest" == *[!0-9a-f]* ]]; then
echo "Invalid Candidate Guard SHA-256: $digest" >&2
exit 1
fi
echo "sha256=$digest" >> "$GITHUB_OUTPUT"
echo "Candidate Guard SHA-256: $digest"

# Keep the candidate Guard runtime independent from the large package and
# test-binary cache. overwrite=true makes a full job re-run replace the
# artifact, while a failed-job re-run still downloads the build's artifact.
- name: Upload Candidate Guard Runtime
uses: actions/upload-artifact@v7
with:
name: sophon-model-guard-runtime
path: build/install/lib/libcosmo_model_guard.so.2.0.0
if-no-files-found: error
overwrite: true
retention-days: 1

test-sophon:
Expand All @@ -61,34 +115,100 @@ jobs:
COSMO_CATCH2_RESULTS_DIR: test-results/catch2
COSMO_CATCH2_REPORTER: compact
COSMO_SOPHON_LD_LIBRARY_PATH: /appfs/cosmo_wander/cwai_data/lib:/data:/usr/lib
COSMO_CANDIDATE_RUNTIME_DIR: ${{ github.workspace }}/candidate-runtime
COSMO_CANDIDATE_GUARD_SHA256: ${{ needs.build-sophon.outputs.candidate_guard_sha256 }}
COSMO_CANDIDATE_TESTS_SHA256: ${{ needs.build-sophon.outputs.candidate_tests_sha256 }}

steps:
# The test binary may be restored from the persistent device cache, but
# the Guard library must always come from this build's current artifact.
- name: Prepare Candidate Guard Runtime Directory
run: |
set -euo pipefail
expected_dir="$GITHUB_WORKSPACE/candidate-runtime"
if [ "$COSMO_CANDIDATE_RUNTIME_DIR" != "$expected_dir" ]; then
echo "Refusing unexpected candidate runtime directory: $COSMO_CANDIDATE_RUNTIME_DIR" >&2
exit 1
fi
rm -rf -- "$COSMO_CANDIDATE_RUNTIME_DIR"
mkdir -p -- "$COSMO_CANDIDATE_RUNTIME_DIR"

- name: Download Candidate Guard Runtime
uses: actions/download-artifact@v8
with:
name: sophon-model-guard-runtime
path: candidate-runtime

- name: Verify Candidate Guard Runtime
run: |
set -euo pipefail
runtime="$COSMO_CANDIDATE_RUNTIME_DIR/libcosmo_model_guard.so.2.0.0"
if [ ! -f "$runtime" ] || [ -L "$runtime" ]; then
echo "Downloaded Candidate Guard runtime is not a regular file: $runtime" >&2
exit 1
fi
if [ "${#COSMO_CANDIDATE_GUARD_SHA256}" -ne 64 ] \
|| [[ "$COSMO_CANDIDATE_GUARD_SHA256" == *[!0-9a-f]* ]]; then
echo "Missing or invalid expected Candidate Guard SHA-256." >&2
exit 1
fi
actual_sha256="$(sha256sum "$runtime" | awk '{print $1}')"
if [ "$actual_sha256" != "$COSMO_CANDIDATE_GUARD_SHA256" ]; then
echo "Candidate Guard SHA-256 mismatch." >&2
echo "Expected: $COSMO_CANDIDATE_GUARD_SHA256" >&2
echo "Actual: $actual_sha256" >&2
exit 1
fi
ln -s -- "libcosmo_model_guard.so.2.0.0" \
"$COSMO_CANDIDATE_RUNTIME_DIR/libcosmo_model_guard.so.2"
ln -s -- "libcosmo_model_guard.so.2" \
"$COSMO_CANDIDATE_RUNTIME_DIR/libcosmo_model_guard.so"
test "$(readlink "$COSMO_CANDIDATE_RUNTIME_DIR/libcosmo_model_guard.so.2")" \
= "libcosmo_model_guard.so.2.0.0"
test "$(readlink "$COSMO_CANDIDATE_RUNTIME_DIR/libcosmo_model_guard.so")" \
= "libcosmo_model_guard.so.2"
echo "Candidate Guard runtime verified: $actual_sha256"

# The Download step below is the dominant wall-clock cost on this
# self-hosted device (fetching the artifact from GitHub over a slow link
# routinely takes 7-13 min, vs seconds-to-minutes for the tests). On
# "Re-run failed jobs" the whole job re-runs, so we cache the binary on
# the device's persistent filesystem keyed by GITHUB_RUN_ID (stable across
# re-run attempts) and skip re-downloading on a cache hit.
# CAVEAT: "Re-run all jobs" rebuilds the binary under the same artifact
# name; this cache would then serve a stale binary. Before a full re-run,
# clear the cache dir on the device (rm -rf $HOME/cosmo-ci-cache).
# the device's persistent filesystem keyed by both GITHUB_RUN_ID and the
# build-produced SHA-256. A full job re-run therefore cannot reuse a stale
# binary, while a failed-job re-run can still skip the large download.
- name: Restore Test Binary From Device Cache
id: binary-cache
run: |
set -euo pipefail
if [ "${#COSMO_CANDIDATE_TESTS_SHA256}" -ne 64 ] \
|| [[ "$COSMO_CANDIDATE_TESTS_SHA256" == *[!0-9a-f]* ]]; then
echo "Missing or invalid expected Candidate test binary SHA-256." >&2
exit 1
fi
# $HOME persists across runs and is outside the per-job workspace
# GitHub cleans, so a file saved here survives across attempts.
# Override the dir by setting COSMO_TEST_BINARY_CACHE_DIR in env.
cache_dir="${COSMO_TEST_BINARY_CACHE_DIR:-$HOME/cosmo-ci-cache}"
mkdir -p "$cache_dir"
cached="$cache_dir/cosmo-tests-${GITHUB_RUN_ID}"
if [ -f "$cached" ]; then
cp "$cached" ./cosmo-tests
echo "cache-hit=true" >> "$GITHUB_OUTPUT"
echo "Restored cosmo-tests from $cached (skipping artifact download)."
cached="$cache_dir/cosmo-tests-${GITHUB_RUN_ID}-${COSMO_CANDIDATE_TESTS_SHA256}"
if [ -f "$cached" ] && [ ! -L "$cached" ]; then
cached_sha256="$(sha256sum "$cached" | awk '{print $1}')"
if [ "$cached_sha256" = "$COSMO_CANDIDATE_TESTS_SHA256" ]; then
cp -- "$cached" ./cosmo-tests
restored_sha256="$(sha256sum ./cosmo-tests | awk '{print $1}')"
if [ "$restored_sha256" != "$COSMO_CANDIDATE_TESTS_SHA256" ]; then
echo "Restored Candidate test binary SHA-256 mismatch." >&2
exit 1
fi
echo "cache-hit=true" >> "$GITHUB_OUTPUT"
echo "Restored verified cosmo-tests from $cached (skipping artifact download)."
else
echo "cache-hit=false" >> "$GITHUB_OUTPUT"
echo "Ignoring corrupt test-binary cache entry: $cached"
fi
else
echo "cache-hit=false" >> "$GITHUB_OUTPUT"
echo "No cached binary for run ${GITHUB_RUN_ID}; will download."
echo "No verified cache entry for run ${GITHUB_RUN_ID} and SHA ${COSMO_CANDIDATE_TESTS_SHA256}; will download."
fi

- name: Download Test Binary
Expand All @@ -98,32 +218,78 @@ jobs:
name: sophon-tests-binary
path: .

- name: Verify Candidate Test Binary
run: |
set -euo pipefail
if [ ! -f ./cosmo-tests ] || [ -L ./cosmo-tests ]; then
echo "Candidate test binary is not a regular file." >&2
exit 1
fi
actual_sha256="$(sha256sum ./cosmo-tests | awk '{print $1}')"
if [ "$actual_sha256" != "$COSMO_CANDIDATE_TESTS_SHA256" ]; then
echo "Candidate test binary SHA-256 mismatch." >&2
echo "Expected: $COSMO_CANDIDATE_TESTS_SHA256" >&2
echo "Actual: $actual_sha256" >&2
exit 1
fi
echo "Candidate test binary verified: $actual_sha256"

- name: Save Test Binary To Device Cache
if: steps.binary-cache.outputs.cache-hit != 'true' && success()
run: |
set -euo pipefail
cache_dir="${COSMO_TEST_BINARY_CACHE_DIR:-$HOME/cosmo-ci-cache}"
cached="$cache_dir/cosmo-tests-${GITHUB_RUN_ID}"
cp ./cosmo-tests "$cached"
cached="$cache_dir/cosmo-tests-${GITHUB_RUN_ID}-${COSMO_CANDIDATE_TESTS_SHA256}"
pending="${cached}.pending-${GITHUB_RUN_ATTEMPT}"
cp --remove-destination -- ./cosmo-tests "$pending"
pending_sha256="$(sha256sum "$pending" | awk '{print $1}')"
if [ "$pending_sha256" != "$COSMO_CANDIDATE_TESTS_SHA256" ]; then
echo "Refusing to cache test binary with mismatched SHA-256." >&2
exit 1
fi
mv -f -- "$pending" "$cached"
# Prune to the 5 most-recent entries; never touch the current run.
# `|| true`: grep exits 1 when only the current run's file exists
# (nothing left after filtering), which under `set -o pipefail` would
# otherwise fail this step. Pruning is best-effort cleanup.
ls -t "$cache_dir"/cosmo-tests-* 2>/dev/null \
| grep -v -F -- "cosmo-tests-${GITHUB_RUN_ID}" \
| grep -v -F -- "$cached" \
| tail -n +6 \
| xargs -r rm -f || true
echo "Saved cosmo-tests to $cached; cache pruned."

- name: Add Execution Permission
run: chmod +x ./cosmo-tests

- name: Verify Candidate Guard Resolution
run: |
set -euo pipefail
export LD_LIBRARY_PATH="$COSMO_CANDIDATE_RUNTIME_DIR:$COSMO_SOPHON_LD_LIBRARY_PATH:${LD_LIBRARY_PATH:-}"
if ! command -v ldd >/dev/null 2>&1; then
echo "Required command is missing: ldd" >&2
exit 1
fi
resolved="$(ldd ./cosmo-tests \
| awk '$1 == "libcosmo_model_guard.so.2" && $2 == "=>" {print $3; exit}')"
if [ -z "$resolved" ]; then
echo "cosmo-tests did not resolve libcosmo_model_guard.so.2." >&2
exit 1
fi
expected_real="$(readlink -f \
"$COSMO_CANDIDATE_RUNTIME_DIR/libcosmo_model_guard.so.2.0.0")"
resolved_real="$(readlink -f "$resolved")"
if [ "$resolved_real" != "$expected_real" ]; then
echo "cosmo-tests resolved a non-candidate Guard runtime: $resolved" >&2
exit 1
fi
echo "cosmo-tests resolves Candidate Guard runtime: $resolved_real"

- name: Run Catch2 Tests
run: |
set +e
set -uo pipefail

export LD_LIBRARY_PATH="$COSMO_SOPHON_LD_LIBRARY_PATH:${LD_LIBRARY_PATH:-}"
export LD_LIBRARY_PATH="$COSMO_CANDIDATE_RUNTIME_DIR:$COSMO_SOPHON_LD_LIBRARY_PATH:${LD_LIBRARY_PATH:-}"

shard_count="$COSMO_CATCH2_SHARDS"
shard_timeout_seconds="$COSMO_CATCH2_SHARD_TIMEOUT_SECONDS"
Expand Down
Loading
Loading