feat: add image analysis API guide and test page #146
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: PR Checks | |
| on: | |
| pull_request: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} | |
| cancel-in-progress: true | |
| jobs: | |
| # ── Non-blocking workflow policy audit ───────────────────────────── | |
| # This remains informational until the team agrees to enforce it in | |
| # the repository ruleset. | |
| policy-audit: | |
| name: policy-audit | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Audit issue, scope, candidate, and risk evidence | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| PR_BODY: ${{ github.event.pull_request.body }} | |
| PR_DRAFT: ${{ github.event.pull_request.draft }} | |
| run: | | |
| set -uo pipefail | |
| warnings=() | |
| add_warning() { | |
| warnings+=("$1") | |
| echo "::warning::$1" | |
| } | |
| changed_paths=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA") | |
| changed_lines=$(git diff --numstat "$BASE_SHA" "$HEAD_SHA" | awk ' | |
| BEGIN { total = 0 } | |
| { | |
| if ($1 ~ /^[0-9]+$/) total += $1 | |
| if ($2 ~ /^[0-9]+$/) total += $2 | |
| } | |
| END { print total } | |
| ') | |
| shopt -s nocasematch | |
| if (( changed_lines > 50 )) && \ | |
| [[ ! "$PR_BODY" =~ (close[sd]?|fix(e[sd])?|resolve[sd]?)[[:space:]]+#[0-9]+ ]]; then | |
| add_warning "Changes over 50 lines must use a closing keyword to reference an agreed issue." | |
| fi | |
| shopt -u nocasematch | |
| if [[ "$PR_DRAFT" != "true" ]]; then | |
| for heading in \ | |
| "## Related issue" \ | |
| "## Root cause" \ | |
| "## Scope" \ | |
| "## Candidate identity" \ | |
| "## Verification" \ | |
| "## Acceptance and cleanup"; do | |
| if ! grep -Fqi "$heading" <<< "$PR_BODY"; then | |
| add_warning "PR body is missing required heading: $heading" | |
| fi | |
| done | |
| candidate=$(sed -nE \ | |
| 's/^[[:space:]-]*Candidate commit:[[:space:]]*`?([0-9a-fA-F]{7,40})`?.*/\1/p' \ | |
| <<< "$PR_BODY" | head -n 1) | |
| if [[ -z "$candidate" ]]; then | |
| add_warning "PR body does not record a candidate commit." | |
| elif [[ "$HEAD_SHA" != "$candidate"* ]]; then | |
| add_warning "Recorded candidate commit does not match the current PR HEAD." | |
| fi | |
| fi | |
| risk_notes=() | |
| if grep -Eq '^(src/api/|src/network/)' <<< "$changed_paths"; then | |
| risk_notes+=("API/network changes require authentication, invalid-input, error-response, and lifecycle evidence.") | |
| fi | |
| if grep -Eq '^(src/media/|src/service/media/|src/web/.*(whep|flv|bigScreen))' <<< "$changed_paths"; then | |
| risk_notes+=("Media changes require ownership, first-frame, switching, overlay, and sustained-playback evidence.") | |
| fi | |
| if grep -Eq '^(src/infer/|src/nn/|src/flow/)' <<< "$changed_paths"; then | |
| risk_notes+=("Inference, NN, or flow changes require Sophon package and focused device evidence.") | |
| fi | |
| if grep -Eq '^src/web/' <<< "$changed_paths"; then | |
| risk_notes+=("Frontend changes require the Docker production build and affected UI evidence.") | |
| fi | |
| if grep -Eq '(^|/)(CMakeLists[.]txt|docker-compose[.]sophon[.]yml)$|^(cmake/|data/resource/|scripts/build)' <<< "$changed_paths"; then | |
| risk_notes+=("Build, resource, or package changes require final package checksum and compatibility evidence.") | |
| fi | |
| { | |
| echo "## Workflow policy audit" | |
| echo | |
| echo "This job is informational and does not block merging." | |
| echo | |
| echo "- Changed lines: $changed_lines" | |
| echo "- Candidate HEAD: \`$HEAD_SHA\`" | |
| echo | |
| if (( ${#warnings[@]} == 0 )); then | |
| echo "No policy gaps detected." | |
| else | |
| echo "### Policy gaps" | |
| for warning in "${warnings[@]}"; do | |
| echo "- $warning" | |
| done | |
| fi | |
| if (( ${#risk_notes[@]} > 0 )); then | |
| echo | |
| echo "### Risk-based evidence reminders" | |
| for note in "${risk_notes[@]}"; do | |
| echo "- $note" | |
| done | |
| fi | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| exit 0 | |
| # ── Platform-neutral validation tools ───────────────────────────── | |
| validation-tools: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| cache-dependency-path: tools/scenario-bench/package-lock.json | |
| - uses: actions/setup-python@v7 | |
| with: | |
| python-version: '3.12' | |
| - name: Test scenario benchmark tooling | |
| working-directory: tools/scenario-bench | |
| run: | | |
| npm ci | |
| npm test | |
| - name: Test offline accuracy comparison | |
| run: python -m unittest discover -s test -p 'test_offline_accuracy_compare.py' | |
| - name: Test agent-assisted workflow safety boundaries | |
| run: python -m unittest discover -s test/agent -p 'test_agent_workflow.py' | |
| - name: Test measured model-conversion workflow | |
| run: python -m unittest discover -s test/agent -p 'test_model_conversion_workflow.py' | |
| - name: Test task-scoped interactive remote access | |
| run: python -m unittest discover -s test/agent -p 'test_remote_access.py' | |
| # ── Windows remains an orchestration, assessment, and SSH entry ─── | |
| agent-windows-routing: | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-python@v7 | |
| with: | |
| python-version: '3.12' | |
| - name: Test read-only assessment and Linux routing | |
| working-directory: test/agent | |
| run: >- | |
| python -m unittest | |
| test_agent_workflow.AgentWorkflowTest.test_memory_probe_tolerates_windows_missing_sysconf | |
| test_agent_workflow.AgentWorkflowTest.test_private_json_write_tolerates_windows_missing_fchmod | |
| test_agent_workflow.AgentWorkflowTest.test_unspecified_toolchain_selects_capability_probe_without_version_pin | |
| test_agent_workflow.AgentWorkflowTest.test_assessment_asks_only_for_missing_business_input | |
| test_agent_workflow.AgentWorkflowTest.test_windows_assessment_routes_to_linux_without_calling_windows_unsupported | |
| test_agent_workflow.AgentWorkflowTest.test_remote_linux_assessment_consolidates_missing_authority | |
| test_agent_workflow.AgentWorkflowTest.test_windows_doctor_returns_linux_environment_guidance_not_traceback | |
| test_agent_workflow.AgentWorkflowTest.test_remote_route_requires_explicit_grants_and_authorization_invalidates_assessment | |
| test_remote_access.RemoteAccessTest | |
| # ── Documentation structure, links, build, and rendered smoke ───── | |
| docs: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| cache-dependency-path: package-lock.json | |
| - name: Install documentation dependencies | |
| run: npm ci | |
| - name: Verify tutorial documentation | |
| run: npm run docs:verify | |
| # ── C++ format check via clang-format ────────────────────────────── | |
| # Only checks files changed in the PR (not the entire codebase) | |
| format-check: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 # fetch all history for diff against base | |
| - name: Install clang-format | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y clang-format-18 | |
| sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-18 100 | |
| - name: Check C++ formatting (changed files only) | |
| run: | | |
| clang-format --version | |
| BASE=$(git merge-base HEAD origin/main) | |
| echo "merge-base: $BASE" | |
| CHANGED=$(git diff --name-only --diff-filter=ACMR "$BASE" HEAD -- \ | |
| '*.cc' '*.h' | grep -vE '(^|/)(3rd|prebuild|node_modules)/' || true) | |
| if [ -z "$CHANGED" ]; then | |
| echo "No C++ files changed." | |
| exit 0 | |
| fi | |
| echo "Checking $(echo "$CHANGED" | wc -l) changed file(s)..." | |
| FAIL=0 | |
| for f in $CHANGED; do | |
| if ! diff <(clang-format "$f") "$f" > /dev/null 2>&1; then | |
| echo " ❌ $f" | |
| FAIL=1 | |
| fi | |
| done | |
| if [ $FAIL -eq 0 ]; then | |
| echo "✅ All changed files are properly formatted." | |
| else | |
| echo "" | |
| echo "Run 'scripts/format_check.sh --fix' locally to auto-fix." | |
| exit 1 | |
| fi | |
| # ── Vue 3 frontend build (includes i18n checks via prebuild hook) ── | |
| frontend-build: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: src/web | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| # Node 22 LTS ships npm 10, matching the build image used for | |
| # production frontend builds. Node 24 ships npm 11, whose stricter | |
| # lockfile validation rejects the npm 10-generated lockfile and | |
| # would test a different dependency resolution than what ships. | |
| node-version: 22 | |
| cache: npm | |
| cache-dependency-path: src/web/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Build frontend | |
| run: npm run build | |
| # ── cppcheck static analysis (changed files only) ─────────────────── | |
| cppcheck: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install cppcheck | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y cppcheck | |
| - name: Run cppcheck (changed files only) | |
| run: | | |
| BASE=$(git merge-base HEAD origin/main) | |
| CHANGED=$(git diff --name-only --diff-filter=ACMR "$BASE" HEAD -- \ | |
| 'src/**/*.cc' 'src/**/*.h' 'test/**/*.cc' 'test/**/*.h') | |
| if [ -z "$CHANGED" ]; then | |
| echo "No C++ files changed." | |
| exit 0 | |
| fi | |
| echo "Checking $(echo "$CHANGED" | wc -l) changed file(s)..." | |
| cppcheck \ | |
| --std=c++17 \ | |
| --language=c++ \ | |
| --enable=warning,style,performance,portability \ | |
| --inline-suppr \ | |
| --suppressions-list=.cppcheck-suppressions \ | |
| --quiet \ | |
| --template='{file}:{line}: [{severity}] {id}: {message}' \ | |
| -I src \ | |
| -j"$(nproc)" \ | |
| $CHANGED |