Skip to content

docs: fix accuracy drift found in documentation audit #56

docs: fix accuracy drift found in documentation audit

docs: fix accuracy drift found in documentation audit #56

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
merge_group:
workflow_dispatch:
jobs:
# F-22 package isolation (fork-safe, no Unity license): prove every shipped package.json is a
# self-consistent UPM graph - all five packages versioned in lockstep and every internal
# com.neoxider.* dependency pin matches the pinned package's actual version. Catches a half-done
# version bump (one of A-01/A-02's failure classes) before it reaches a consumer.
package-graph:
name: Package graph (lockstep + deps)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Verify package versions are in lockstep and internal deps resolve
shell: bash
run: |
python3 - <<'PY'
import json, glob, sys
pkgs = {}
for path in glob.glob('Assets/*/package.json'):
with open(path, encoding='utf-8') as f:
data = json.load(f)
pkgs[data['name']] = (data.get('version', ''), data.get('dependencies', {}))
versions = {v[0] for v in pkgs.values()}
ok = True
if len(versions) != 1:
print(f"::error::package versions are not in lockstep: {versions}")
ok = False
for name, (ver, deps) in pkgs.items():
for dep, dver in deps.items():
if dep.startswith('com.neoxider.') and dep in pkgs and dver != pkgs[dep][0]:
print(f"::error::{name} pins {dep}@{dver} but that package is {pkgs[dep][0]}")
ok = False
print("packages:", {n: v[0] for n, v in pkgs.items()})
sys.exit(0 if ok else 1)
PY
# F-12 trusted merge-queue gate: on the merge queue the repository secrets ARE available, so a
# missing UNITY_LICENSE is a misconfiguration, not a forked PR - FAIL loudly instead of skipping,
# so an unlicensed runner can never merge an uncompiled/untested wave (the A-01/A-02 class).
merge-queue-gate:
name: Merge-queue license gate
runs-on: ubuntu-latest
if: github.event_name == 'merge_group'
steps:
- name: Require UNITY_LICENSE on the merge queue
shell: bash
run: |
if [ -z "${{ secrets.UNITY_LICENSE }}" ]; then
echo "::error::UNITY_LICENSE is unavailable on the merge queue; the EditMode/PlayMode Unity"
echo "::error::jobs would skip and let an uncompiled change merge. Configure the secret."
exit 1
fi
echo "UNITY_LICENSE present - Unity jobs will run and gate this merge."
# Secret-free analyzer guard. Uses plain dotnet (no Unity license), so it also runs
# on forked PRs where the Unity jobs are skipped. Building + testing the Roslyn
# analyzer project guards the committed CoreAI.UnityAsyncAnalyzers.dll against drift
# and proves rule CAIU001 (ban ConfigureAwait(false) in CoreAiUnity code) still fires.
analyzer:
name: Roslyn analyzer (dotnet)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Build analyzer + tests
run: dotnet build tools/CoreAI.Tools.sln -c Release --nologo
- name: Run analyzer tests (verifies CAIU001 fires)
run: dotnet test tools/CoreAI.Tools.sln -c Release --no-build --nologo
editmode-tests:
name: EditMode (${{ matrix.name }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Explicit include list (no cross-product). Three configurations must stay green:
# lua - default project with the bundled Lua-CSharp runtime.
# no-lua - COREAI_NO_LUA build so every Lua feature compiles out.
# no-llm - COREAI_NO_LLM build so the layer under #if !COREAI_NO_LLM compiles out.
include:
- name: lua
lua: lua
no_llm: false
- name: no-lua
lua: no-lua
no_llm: false
- name: no-llm
lua: lua
no_llm: true
steps:
- uses: actions/checkout@v4
- name: Check UNITY_LICENSE availability for this run
id: unity-license-check
shell: bash
run: |
if [ -z "${{ secrets.UNITY_LICENSE }}" ]; then
echo "::notice::Skipping EditMode tests because UNITY_LICENSE is unavailable (forked PRs do not receive repository secrets)."
echo "run_tests=false" >> "$GITHUB_OUTPUT"
else
echo "run_tests=true" >> "$GITHUB_OUTPUT"
fi
- name: Define COREAI_NO_LUA
if: matrix.lua == 'no-lua'
run: |
# The Lua-CSharp runtime ships bundled inside the CoreAI Mods package (Lua.dll), so there
# is no package to remove — this job proves the project compiles with every Lua feature
# compiled out via the COREAI_NO_LUA define (documented opt-out in
# Assets/CoreAI/Docs/LUA_SANDBOX_SECURITY.md).
# Append the define to every per-platform scriptingDefineSymbols entry.
sed -i 's/: DOTWEEN$/: DOTWEEN;COREAI_NO_LUA/' ProjectSettings/ProjectSettings.asset
grep -q 'COREAI_NO_LUA' ProjectSettings/ProjectSettings.asset || { echo 'COREAI_NO_LUA injection failed'; exit 1; }
- name: Define COREAI_NO_LLM
if: matrix.no_llm
run: |
# Compile out the LLM layer (real code lives under #if !COREAI_NO_LLM) so the
# no-LLM build can't silently break. Mirrors the COREAI_NO_LUA injection above.
sed -i 's/: DOTWEEN$/: DOTWEEN;COREAI_NO_LLM/' ProjectSettings/ProjectSettings.asset
grep -q 'COREAI_NO_LLM' ProjectSettings/ProjectSettings.asset || { echo 'COREAI_NO_LLM injection failed'; exit 1; }
- uses: actions/cache@v4
with:
path: Library
key: library-${{ matrix.name }}-${{ hashFiles('Packages/packages-lock.json', 'ProjectSettings/ProjectVersion.txt') }}
restore-keys: |
library-${{ matrix.name }}-
- name: Run EditMode tests
if: steps.unity-license-check.outputs.run_tests == 'true'
uses: game-ci/unity-test-runner@v4
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
with:
testMode: editmode
artifactsPath: artifacts-${{ matrix.name }}
checkName: EditMode results (${{ matrix.name }})
githubToken: ${{ secrets.GITHUB_TOKEN }}
- name: Enforce Lua sandbox escape-test coverage
if: matrix.lua == 'lua' && matrix.no_llm == false && steps.unity-license-check.outputs.run_tests == 'true'
run: |
# The sandbox isolation suite must actually have run — a green build with
# 0 executed escape tests (filter typo, asmdef regression, define drift)
# must fail, not pass silently.
count=$(grep -o 'LuaCsSecureSandboxEditModeTests' artifacts-${{ matrix.name }}/editmode-results.xml | wc -l)
echo "LuaCsSecureSandboxEditModeTests occurrences in results: $count"
if [ "$count" -lt 3 ]; then
echo "::error::Lua sandbox escape tests did not run (expected the LuaCsSecureSandboxEditModeTests fixture in EditMode results)."
exit 1
fi
- uses: actions/upload-artifact@v4
if: always() && steps.unity-license-check.outputs.run_tests == 'true'
with:
name: test-results-${{ matrix.name }}
path: artifacts-${{ matrix.name }}
# Deterministic, no-LLM PlayMode suite (main-thread marshaling, streaming/non-streaming
# parity, stop/cancel). Filtered to the FastNoLlm test assembly so the live LLM
# benchmark / LlmVerification fixtures (which need a model server) never run here.
playmode-fastnollm:
name: PlayMode (FastNoLlm)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check UNITY_LICENSE availability for this run
id: unity-license-check
shell: bash
run: |
if [ -z "${{ secrets.UNITY_LICENSE }}" ]; then
echo "::notice::Skipping PlayMode tests because UNITY_LICENSE is unavailable (forked PRs do not receive repository secrets)."
echo "run_tests=false" >> "$GITHUB_OUTPUT"
else
echo "run_tests=true" >> "$GITHUB_OUTPUT"
fi
- uses: actions/cache@v4
with:
path: Library
key: library-playmode-${{ hashFiles('Packages/packages-lock.json', 'ProjectSettings/ProjectVersion.txt') }}
restore-keys: |
library-playmode-
- name: Run PlayMode tests (FastNoLlm assembly only)
if: steps.unity-license-check.outputs.run_tests == 'true'
uses: game-ci/unity-test-runner@v4
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
with:
testMode: playmode
# The deterministic suite has no NUnit [Category]; isolate it by assembly name.
# The LlmVerification / benchmark fixtures live in separate assemblies and are
# excluded by not naming them here.
customParameters: -assemblyNames "CoreAI.Tests.PlayMode.FastNoLlm"
artifactsPath: artifacts-playmode
checkName: PlayMode results (FastNoLlm)
githubToken: ${{ secrets.GITHUB_TOKEN }}
- name: Enforce FastNoLlm PlayMode suite actually ran
if: steps.unity-license-check.outputs.run_tests == 'true'
run: |
# A green build with 0 executed FastNoLlm tests (filter typo, asmdef rename,
# define drift) must fail, not pass silently.
count=$(grep -o 'PlayModeTests' artifacts-playmode/playmode-results.xml | wc -l)
echo "PlayMode FastNoLlm test-case occurrences in results: $count"
if [ "$count" -lt 10 ]; then
echo "::error::FastNoLlm PlayMode suite did not run (expected the CoreAI.Tests.PlayMode.FastNoLlm fixtures in PlayMode results)."
exit 1
fi
- uses: actions/upload-artifact@v4
if: always() && steps.unity-license-check.outputs.run_tests == 'true'
with:
name: test-results-playmode
path: artifacts-playmode