Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
c90b9d4
Require authenticated LAN control and separate OSC exposure
iamfatness Sep 6, 2026
5cd73e8
Generate versioned lifecycle contracts and shared wire fixtures
iamfatness Sep 6, 2026
79b8d98
Track recording finalization and keep controls responsive during Zoom…
iamfatness Sep 6, 2026
1cf3cbc
Gate releases on required suites and exact-package hardware evidence
iamfatness Sep 6, 2026
efa34b4
Keep output intent separate and recover saved production settings vis…
iamfatness Sep 6, 2026
346c99d
Render observed recording lifecycle in development clients and evidence
iamfatness Sep 6, 2026
d7a1470
Guard macOS bridge generations and display observed recording state
iamfatness Sep 6, 2026
d2a9155
Reject incompatible and stale core responses in Windows transport
iamfatness Sep 6, 2026
8c5b095
Document migration boundaries and add reproducible media validation
iamfatness Sep 6, 2026
1bc357e
Repair npm 10 clean-install lockfile for existing optional dependencies
iamfatness Sep 6, 2026
d011b81
Synchronize stub encoder snapshots across audio and video workers
iamfatness Sep 6, 2026
7dc7eb3
Bound WinUI test hangs and retain diagnostic evidence
iamfatness Sep 6, 2026
8d60b34
Provision the pinned Windows App Runtime for hosted WinUI tests
iamfatness Sep 6, 2026
cd83c3b
Keep child test working directories independent of fixture cleanup
iamfatness Sep 6, 2026
834798e
Allow explicit handshake before gating application commands
iamfatness Sep 6, 2026
9fde96b
Reconcile output polling and retry explicit Stop targets
iamfatness Sep 6, 2026
059e453
Bound recording media across retries and validate harness exits
iamfatness Sep 6, 2026
663f1ad
Make solicited handshake rejection terminal and generation safe
iamfatness Sep 6, 2026
1029fbe
Reconcile macOS recording Stop retries and stale completions
iamfatness Sep 6, 2026
a17790a
Record review validation and retain behavioral test coverage
iamfatness Sep 6, 2026
5e14c1d
Keep recording Stop intent through delayed live snapshots
iamfatness Sep 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: CI

on:
workflow_call:
push:
branches: [main]
pull_request:
Expand All @@ -19,6 +20,10 @@ jobs:
node-version: 22
- name: Version sources agree with package.json
run: node scripts/stamp-version.mjs --check
- name: Generated contracts are current
run: node contracts/generate.mjs --check
- name: Release evidence validator tests
run: node --test scripts/tests/release-evidence.test.mjs

# Design-token gate for the macOS shell (docs/design-handoff-macos.md).
# The 2026-08-04 audit found ~90% of mac-shell text rendering in SF Pro /
Expand Down Expand Up @@ -280,7 +285,19 @@ jobs:
- run: npm ci
- name: Native media-core stub gate
run: npm run test:native-media-core
- name: MediaCore bridge + unit tests
- name: Restore and provision WinUI test runtime
run: |
dotnet restore native-shell/CoreVideoPro.WinUI.Tests/CoreVideoPro.WinUI.Tests.csproj
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
./scripts/provision-winui-test-runtime.ps1
- name: MediaCore, Control, WinUI and bridge tests
run: npm run test:native-shell
- name: Upload Windows test results
if: always()
uses: actions/upload-artifact@v4
with:
name: windows-shell-test-results
path: artifacts/test-results/**
if-no-files-found: error
- name: Publish WinUI shell (build gate)
run: dotnet publish native-shell/CoreVideoPro.WinUI/CoreVideoPro.WinUI.csproj -c Release -r win-x64 --self-contained false
133 changes: 107 additions & 26 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,19 @@ concurrency:
cancel-in-progress: false

jobs:
required-tests:
uses: ./.github/workflows/ci.yml
permissions:
contents: read

# Job 0 -- validate: tag == package.json version, all version sources in sync
# (D1 stamp check), and a CHANGELOG section exists for the release notes.
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.sha }}
- uses: actions/setup-node@v4
with:
node-version: 22
Expand All @@ -77,14 +84,16 @@ jobs:
run: node scripts/release-notes.mjs "$GITHUB_REF_NAME"

release-windows:
needs: validate
needs: [validate, required-tests]
runs-on: windows-latest
timeout-minutes: 120
defaults:
run:
shell: pwsh
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.sha }}
- uses: actions/setup-node@v4
with:
node-version: 22
Expand Down Expand Up @@ -311,43 +320,26 @@ jobs:
Set-Content -Path "artifacts/latest.json" -Value $latest -Encoding utf8
Write-Host $latest

- name: Create GitHub Release
- name: Assemble immutable signed release candidate
if: github.event_name == 'push'
env:
GH_TOKEN: ${{ github.token }}
run: |
$version = "${{ steps.version.outputs.version }}"
$tag = $env:GITHUB_REF_NAME
$releaseDir = "artifacts/release"
New-Item -ItemType Directory -Path $releaseDir -Force | Out-Null
Copy-Item "artifacts/native/CoreVideoPro.msix" "$releaseDir/CoreVideoPro-v$version.msix"
Copy-Item "artifacts/native/CoreVideoPro.appinstaller" "$releaseDir/CoreVideoPro.appinstaller"
Copy-Item "artifacts/CoreVideoPro-symbols-v$version.zip" $releaseDir
Copy-Item "artifacts/latest.json" $releaseDir
$notes = Join-Path $env:RUNNER_TEMP "release-notes.md"
node scripts/release-notes.mjs $tag | Out-File -FilePath $notes -Encoding utf8
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
$assets = Get-ChildItem -Path $releaseDir -File | ForEach-Object { $_.FullName }
gh release create $tag --title "CoreVideo Pro v$version" --notes-file $notes --verify-tag @assets
node scripts/release-evidence.mjs candidate $env:GITHUB_SHA "$releaseDir/CoreVideoPro-v$version.msix" native/build-dev/CMakeCache.txt native-shell/CoreVideoPro.WinUI/msix-payload "$releaseDir/candidate.json"
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

- name: Publish to update host (TODO -- D0/D4 hosting decision)
- name: Upload signed candidate for controlled hardware validation
if: github.event_name == 'push'
env:
COREVIDEO_UPDATE_BASE_URL: ${{ vars.COREVIDEO_UPDATE_BASE_URL }}
run: |
# TODO(D0/D4): automate once the owner picks the update host + creds
# (spec D4 recommends an R2 bucket behind the existing Cloudflare
# account with a custom domain). Deliberately fail-soft: the signed
# release exists either way; auto-update just won't see it until the
# files below are published.
$version = "${{ steps.version.outputs.version }}"
$base = $env:COREVIDEO_UPDATE_BASE_URL.TrimEnd('/')
Write-Host "::warning::Update-host publish is NOT automated yet. To light up install/auto-update, upload these GitHub Release assets to the update host so these URLs resolve:"
Write-Host " CoreVideoPro-v$version.msix -> $base/CoreVideoPro-v$version.msix"
Write-Host " CoreVideoPro.appinstaller -> $base/CoreVideoPro.appinstaller"
Write-Host " latest.json -> $base/latest.json"
Write-Host "Example (R2): wrangler r2 object put <bucket>/CoreVideoPro.appinstaller --file CoreVideoPro.appinstaller (+ msix + latest.json), or the R2 dashboard."
uses: actions/upload-artifact@v4
with:
name: signed-release-candidate
path: artifacts/release/*
if-no-files-found: error

# ---- Dry-run (workflow_dispatch) artifacts: explicitly UNSIGNED. ----

Expand All @@ -366,3 +358,92 @@ jobs:
name: CoreVideoPro-symbols-dry-run
path: artifacts/CoreVideoPro-symbols-v*.zip
if-no-files-found: error

hardware-evidence:
if: github.event_name == 'push'
needs: release-windows
# Dedicated controlled rig, never a pull-request runner. Its harness must
# install and exercise the downloaded package, not build another binary.
runs-on: [self-hosted, Windows, X64, corevideo-release-rig]
environment: production-hardware-validation
permissions:
contents: read
timeout-minutes: 240
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.sha }}
- uses: actions/setup-node@v4
with:
node-version: 22
- uses: actions/download-artifact@v4
with:
name: signed-release-candidate
path: artifacts/candidate
- name: Run controlled rig harness on signed candidate
shell: pwsh
env:
COREVIDEO_HARDWARE_HARNESS: ${{ vars.COREVIDEO_HARDWARE_HARNESS }}
run: |
$ErrorActionPreference = 'Stop'
if (-not $env:COREVIDEO_HARDWARE_HARNESS -or -not (Test-Path -LiteralPath $env:COREVIDEO_HARDWARE_HARNESS -PathType Leaf)) {
throw 'Configure COREVIDEO_HARDWARE_HARNESS on the controlled rig; hardware evidence is mandatory for publication.'
}
$evidenceDir = Join-Path $env:RUNNER_TEMP ([guid]::NewGuid().ToString())
New-Item -ItemType Directory -Path $evidenceDir | Out-Null
Add-Content -LiteralPath $env:GITHUB_ENV -Value "COREVIDEO_EVIDENCE_DIR=$evidenceDir"
$manifest = (Resolve-Path artifacts/candidate/candidate.json).Path
$candidate = Get-Content -LiteralPath $manifest -Raw | ConvertFrom-Json
if ($candidate.sourceSha -ne $env:GITHUB_SHA) { throw 'Candidate source SHA differs from release workflow SHA.' }
$package = (Resolve-Path (Join-Path artifacts/candidate $candidate.artifact.name)).Path
# A successful PowerShell script need not set LASTEXITCODE. Clear any
# inherited native status, then check both PowerShell and native failure.
$global:LASTEXITCODE = 0
& $env:COREVIDEO_HARDWARE_HARNESS -CandidateManifest $manifest -PackagePath $package -EvidenceDirectory $evidenceDir
$harnessSucceeded = $?
if (-not $harnessSucceeded -or $LASTEXITCODE -ne 0) { throw "Hardware harness failed: $LASTEXITCODE" }
node scripts/release-evidence.mjs validate $manifest (Join-Path $evidenceDir evidence.json) $package (Join-Path $evidenceDir verdict.json)
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
- name: Archive sanitized hardware evidence
if: always() && env.COREVIDEO_EVIDENCE_DIR != ''
uses: actions/upload-artifact@v4
with:
name: hardware-release-evidence
path: ${{ env.COREVIDEO_EVIDENCE_DIR }}
if-no-files-found: error

publish:
if: github.event_name == 'push'
needs: [required-tests, release-windows, hardware-evidence]
runs-on: ubuntu-latest
environment: production-release
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.sha }}
- uses: actions/setup-node@v4
with:
node-version: 22
- uses: actions/download-artifact@v4
with:
name: signed-release-candidate
path: artifacts/release
- uses: actions/download-artifact@v4
with:
name: hardware-release-evidence
path: artifacts/evidence
- name: Revalidate candidate and evidence before publishing
run: |
PACKAGE=$(node -p "JSON.parse(require('fs').readFileSync('artifacts/release/candidate.json')).artifact.name")
node scripts/release-evidence.mjs validate artifacts/release/candidate.json artifacts/evidence/evidence.json "artifacts/release/$PACKAGE" artifacts/release/verification.json
node -e "const c=JSON.parse(require('fs').readFileSync('artifacts/release/candidate.json')); if(c.sourceSha!==process.env.GITHUB_SHA) process.exit(1)"
- name: Create GitHub Release from validated bytes
env:
GH_TOKEN: ${{ github.token }}
run: |
node scripts/release-notes.mjs "$GITHUB_REF_NAME" > "$RUNNER_TEMP/release-notes.md"
gh release create "$GITHUB_REF_NAME" --title "CoreVideo Pro $GITHUB_REF_NAME" --notes-file "$RUNNER_TEMP/release-notes.md" --verify-tag artifacts/release/*
- name: Update host publication reminder
run: echo "::warning::Update-host upload remains manual. Publish the validated release assets to COREVIDEO_UPDATE_BASE_URL; do not rebuild them."
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Three processes, not a web app:
- **Zoom engine subprocess** — `native/zoom-engine/` → `corevideo-zoom-engine.exe` —
speaks the Zoom Meeting SDK, writes raw **I420** frames to shared memory.

IPC: JSON-line commands/snapshots over named pipes; video as keyed-mutex **DXGI shared
IPC: JSON-line commands/snapshots over child stdin/stdout pipes; video as keyed-mutex **DXGI shared
textures** (cross-process) for program/preview, and shared-memory I420 for Zoom frames.

Process boundaries + where spine features (ISO/NDI/SRT/browser) plug in: `docs/architecture-seams.md`.
Expand Down
Loading
Loading