This repo ships versioned git hooks in hooks/. Enable them once after cloning:
git config core.hooksPath hooksThe pre-commit hook rejects commits that stage junk files in the repository root:
- Known offenders:
debug.log,memory.db,msp_server.log,replay_pid*.log,TestRun_*.log,UnityTest_*.log,Remove-Item,_coreai_placeholder_lines.txt - Any root-level
*.logor*.db - Orphan root-level
*.metafiles (a.metawithout its corresponding file or folder)
If the hook blocks your commit, unstage the listed files with git restore --staged <file> and delete them if they are build/test artifacts.
.github/workflows/ci.yml runs on every push/PR to main:
- EditMode tests, two Lua configurations —
lua(the default project, with the bundled Lua-CSharp runtime) andno-lua(COREAI_NO_LUAappended to all platform Scripting Define Symbols, compiling all Lua features out). Both must stay green. - Sandbox coverage gate — the
luajob fails if theSecureLuaSandboxEditModeTestsescape-test fixture did not actually execute, so Lua isolation coverage cannot silently drop out. - Standalone core tests — a package-local
CoreAI.Core.TestsEditMode assembly proves thecom.neoxider.coreaipackage compiles and tests on its own, without the Unity layer. package-graphjob — fork-safe (no Unity licence needed): checks that all five packages carry the same lockstep version and that their internal dependency pins agree.merge-queue-gatejob — on themerge_grouptrigger the workflow fails (does not skip) whenUNITY_LICENSEis absent, so a PR can never be merged through the queue without the licensed test run having actually executed.
The workflow requires the standard GameCI repository
secrets: UNITY_LICENSE, UNITY_EMAIL, UNITY_PASSWORD.
New Lua-dependent test files must be wrapped in #if !COREAI_NO_LUA so the
no-lua job compiles.
Formatting is shared through the repo .editorconfig (Rider/ReSharper read it directly). Run
Rider → Code → Reformat & Cleanup Code before committing so a diff never mixes logic with style.
Notably: every attribute goes on its own line — never [SerializeField] private int x; and never
[Tooltip("...")] [SerializeField] packed together.
Keep only comments that carry information the code cannot. Label the intentional kinds with an explicit prefix and delete everything else:
/// <summary>— XML docs on public/protected API.// WHY:— rationale, non-obvious invariants, ordering constraints, workarounds, external-format notes.// TODO:— deferred work.// HACK:— deliberate shortcuts worth flagging.
Remove obvious "what" comments that merely restate the next line, step-number narration (// 1. Create…),
and section-divider banners.
Both casings are intentional and must not be "unified":
CoreAI— the root namespace and every type/asset in it (CoreAIAgent,CoreAISettingsAsset, …).CoreAi— the public Unity entry-point facade (CoreAi.AskAsync(...)). A type cannot share the exact name of its enclosing namespace, so the facade uses the lowercase-ispelling deliberately. It is the established public API; do not rename it.
New public symbols follow CoreAI…; only the top-level facade keeps CoreAi.
- Reformat — Rider Reformat & Cleanup Code (applies
.editorconfig, incl. attribute-per-line). - Tests — run the EditMode gate green (CI runs
lua+no-lua; run locally in batchmode for a fast pre-push check). - Changelog — add an entry under
[Unreleased](or the release section) in the affected packageCHANGELOG.md. - Version — for a release, bump all five
package.jsonfiles in lockstep to the same version.