Skip to main content

Quality Gates And Continuous Integration

STAGE uses layered, claim-matched quality gates. The purpose is not to make the repository look mature or to maximize the number of green tools. It is to catch inexpensive failures early, preserve human decisions, and make every remaining claim explicit.

This guide answers four questions:

  1. Which failures should an agent catch before handing work to a human?
  2. Which checks belong on a workstation, in the engine, or in hosted CI?
  3. Which configuration may an agent change without hiding a defect?
  4. What still requires a human director even when every automated gate passes?

The short answer is:

Source -> Model -> Engine -> Consumer -> Distribution -> Director
cheap experiential
frequent human-owned

The layers are additive. A later layer does not make an earlier one unnecessary, and an earlier pass does not imply a later result.

Why A Layered Model

Game projects fail across boundaries that a single linter or test runner cannot see.

Failure classExampleEarliest useful detector
Mechanical driftmalformed YAML, unused import, formatting churnsource gate
Architecture driftruntime code instantiates a resource that a factory ownsmodel gate
Engine-data driftmissing serialized reference, unsupported shader, stale GUIDengine gate
Clean-machine driftlocal generated state masks a missing package or bankclean-checkout gate
Consumer failureinput, audio, loading, reset, or UI wiring fails in compositionconsumer gate
Product failurethe loop is confusing, ugly, tedious, unfair, or not worth continuingDirector's Call

SonarQube, Roslyn, Ruff, Unity Test Framework, a standalone build, and a human playtest answer different questions. Treating any one as a universal quality score creates false confidence.

The Six Gate Families

1. Source Gate

Question: Is the changed source mechanically coherent and reviewable?

Typical checks:

  • formatter check;
  • linter and compiler diagnostics;
  • strict JSON and YAML parsing;
  • duplicate-key and schema validation;
  • Markdown link validation;
  • prohibited path or generated-output checks;
  • git diff --check;
  • secret scanning where credentials are plausible; and
  • an intended-diff review.

Useful evidence:

  • exact command and exit status;
  • tool version;
  • changed path list;
  • revision or working-tree coordinates; and
  • diagnostic output.

Does not prove:

  • Unity serialization;
  • runtime composition;
  • gameplay behavior;
  • visual quality;
  • performance; or
  • fun.

The source gate should usually run on every bounded change because it is fast and deterministic.

2. Model Gate

Question: Do deterministic rules and declared architecture contracts still hold?

Typical checks:

  • unit and property tests;
  • deterministic scenario tests;
  • dependency-direction tests;
  • namespace or assembly-boundary rules;
  • ownership rules such as "runtime objects are created by this factory";
  • state-machine and transition invariants;
  • forecast-versus-resolution equality;
  • source generators or analyzers;
  • package, content, and manifest contracts; and
  • replay or state-hash checks.

This is where a focused Roslyn analyzer, architecture test, or custom repository validator can be more useful than a large generic platform. Add one when a rule is important, mechanically expressible, and has failed or is likely to fail repeatedly.

Does not prove:

  • the Unity scene contains the right serialized objects;
  • the real input and presentation route reaches the rule;
  • the game communicates the rule;
  • the choice is interesting; or
  • players value the outcome.

3. Engine Gate

Question: Does the real engine accept and compose the project state?

For Unity, typical checks are:

  • wait for import, compilation, and domain reload to settle;
  • inspect project-owned Console errors;
  • run EditMode tests through Unity Test Framework;
  • run relevant PlayMode tests through the composed project;
  • validate scenes, prefabs, materials, shaders, animation controllers, and serialized references;
  • verify Addressables, localization tables, Wwise SoundBanks, or other middleware output when they are material;
  • run project-specific authoring validators; and
  • save only intentionally changed authored assets.

The generated .csproj compiling outside Unity is supporting evidence. It is not a replacement for Unity compilation because Unity controls assembly definitions, serialization, importers, generated code, platform defines, and engine integration.

Does not prove:

  • the intended runtime path was exercised;
  • standalone behavior;
  • performance on target hardware;
  • visual or audio acceptance; or
  • player comprehension.

4. Consumer Gate

Question: Does the changed behavior work through its production consumer?

Examples:

ClaimConsumer-complete route
Pause blocks gameplay inputreal input adapter -> modal owner -> game-time consumer
Main-menu music hands offauthoring event -> generated media -> runtime backend -> loading -> gameplay state
Retry resets a rundeath -> Curtain Call -> retry -> reset owners -> first gameplay frames
Upgrade can be selectedreal mouse/controller navigation -> production UI -> applied runtime state
Generated terrain is traversableproduction generator -> colliders -> player/enemy movement in representative seeds
Moon forecast is truthfulproduction command -> forecast UI -> commit -> authoritative resolver -> dawn explanation

Useful routes include:

  • composed PlayMode smoke;
  • scripted production input;
  • deterministic reproduction;
  • a live engine scene with real assets;
  • diagnostics or a profiler capture;
  • production middleware integration; and
  • targeted manual inspection where automation cannot operate the consumer reliably.

This gate is often where regressions in game projects actually surface. It should be scoped to the changed claim rather than replaced with an unrelated full-project test.

Does not prove:

  • a first-time player understands the affordance;
  • a visual is attractive;
  • a sound mix feels right;
  • a challenge is fair;
  • a mechanic is engaging; or
  • the game should ship.

5. Distribution Gate

Question: Can a clean, declared environment reproduce and run the intended artifact?

Typical checks:

  • fresh checkout with no local caches treated as source;
  • pinned engine, package, compiler, middleware, and action versions;
  • project-owned build command;
  • declared scene/content list;
  • complete artifact-tree receipt or hash;
  • launch smoke of the exact built artifact;
  • target-platform logs;
  • bounded performance and memory checks on relevant hardware;
  • signing or packaging checks when release scope requires them; and
  • unchanged source state after a check-only operation.

Hosted CI is strongest here because it exposes assumptions hidden on the author's workstation. A CI pass means only that the declared workflow passed on that runner and revision.

Does not prove:

  • every target machine works;
  • platform certification;
  • player experience;
  • commercial readiness; or
  • release acceptance.

6. Director Gate

Question: Is the product result acceptable for the intended experience?

The accountable human judges:

  • comprehension;
  • control feel and usability;
  • visual hierarchy and polish;
  • animation, audio, and feedback;
  • pacing and balance;
  • accessibility and comfort;
  • emotional meaning;
  • engagement and desire to continue;
  • whether the game still expresses its identity; and
  • whether the tradeoff is worth the scope and maintenance cost.

For a new or materially changed gameplay premise, this is the Player Experience Gate. For ordinary visual, balance, or feel work, it can be a short direct inspection or play session.

Automated evidence can block a broken candidate before human time is spent. It cannot accept the product on the human's behalf.

Gate Selection

Do not run every possible gate for every change. Select the smallest stack that contains the claim's material boundaries.

ChangeSourceModelEngineConsumerDistributionDirector
Documentation typorequiredlink/map rulesnorendered doc if layout claimnoprose judgment
Pure economy formularequiredrequiredif Unity assembly owns itrepresentative scenarioif release-boundbalance
Serialized prefab referencerequiredownership rule if availablerequiredcomposed spawnclean build if release-boundappearance/fit
Input remappingrequiredadapter testsrequiredkeyboard/controller production pathtarget buildusability
Loading performancerequiredstage invariantsrequiredoverlay under real workloadtarget hardware if claimedcontinuity
New gameplay kernelrequireddeterministic rulesrequiredthin complete loopprototype build when neededmandatory
Release candidaterequiredfull declared suiterequiredcritical-path smokerequiredrelease decision

Change Gate And Release Gate

A practical repository usually exposes two aggregate commands:

  • change gate: fast checks appropriate while iterating;
  • release gate: the full deterministic repository baseline.

Engine and experiential checks may remain separate because they require a specific editor, GPU, middleware connection, target device, or human. The aggregate command must say what it omits.

Stage Director's Flow Integration

Quality gates support, but do not replace, the Stage Director's Flow.

Flow boundaryRequired quality action
Dialogue -> Readyname material claims, consumers, selected gates, and human questions
Active -> Rehearsalpass the selected source/model gates and prepare the real consumer
Rehearsal -> Director's Callrecord all attempted outcomes and limitations
Director's Call -> Checkpointedhuman disposition is explicit; accepted work passes required checkpoint gates
Rejected -> revise/revertpreserve the finding; do not weaken gates or conceal the rejection

A work item is not "done" merely because CI is green. State the boundary:

  • implemented;
  • mechanically checked;
  • engine-composed;
  • human accepted;
  • checkpointed; and
  • released.

Branch isolation, concurrent-agent limits, Unity path ownership, serial integration, build identity, and release proposal rules are defined in Change, Concurrency, And Release Workflow. Quality gates report whether a revision supports its claims; they do not decide which branches may overlap or whether an accepted checkpoint should become a release.

Agent-Safe Quality Policy

AI agents are nondeterministic contributors. The gate configuration is part of human project authority.

Agents May

  • run declared checks;
  • add a focused check for a newly introduced contract;
  • fix diagnostics caused by their own intended change;
  • propose a rule or suppression with evidence;
  • update a pinned tool deliberately and report the effect;
  • preserve command output and evidence coordinates; and
  • stop when a gate exposes an unrelated pre-existing failure.

Agents Must Not

  • disable, delete, or weaken a check merely to get green;
  • add broad suppressions without explicit human approval;
  • rewrite a baseline so new findings disappear;
  • mark warnings as accepted product decisions;
  • retry a flaky test until one pass is obtained and report only that pass;
  • run an auto-fixer over human-authored assets without a reviewed scope;
  • mutate a repository from CI unless that workflow is explicitly authorized;
  • infer that CI success grants release or product acceptance; or
  • claim unattempted engine or human checks.

Suppressions

A suppression should record:

  • exact diagnostic;
  • smallest affected scope;
  • reason the rule does not apply;
  • owner;
  • review trigger or expiry condition; and
  • evidence that a code fix is less appropriate.

Repository-wide suppressions are architecture decisions, not cleanup.

Flaky Checks

When a check is nondeterministic:

  1. preserve the failing seed, trace, environment, and revision;
  2. distinguish a product nondeterminism defect from a test harness defect;
  3. quarantine only when the project owner accepts the reduced protection;
  4. keep the quarantine visible; and
  5. repair or remove the unsupported claim.

Retries may gather evidence. They must not convert an intermittent failure into a reliable pass.

CI Design

Minimum Check-Only Workflow

For a small personal repository:

checkout exact revision
-> install pinned tools
-> run release gate
-> upload useful diagnostics on failure

Recommended properties:

  • read-only repository permissions by default;
  • actions pinned to immutable commit SHAs;
  • bounded timeout;
  • concurrency cancellation for superseded branch runs;
  • no automatic formatting or commits;
  • no hidden local generated state;
  • deterministic locale and relevant environment variables;
  • exact tool versions in logs; and
  • one clear completion signal.

Independent Source and Model jobs may run concurrently. Unity jobs for the same project should be serialized, and superseded branch runs may be canceled. After serial branch integration, rerun the production-consumer smoke on main; separate green branch runs do not establish the integrated state.

The workflow should be boring. Its job is to reproduce declared checks, not to become a second build system.

Unity CI

Unity needs more than a generic C# job. A future project workflow may include:

  1. license/entitlement setup through a trusted provider;
  2. exact Unity editor version;
  3. Library cache only as an optimization, never authority;
  4. batch-mode EditMode tests;
  5. batch-mode PlayMode tests compatible with the project's rendering needs;
  6. a project-owned player build;
  7. retained XML, editor logs, player logs, and build receipt; and
  8. target launch/performance jobs only where runners can support the claim.

Do not add hosted Unity execution until the project has stable local commands, secrets handling, and enough recurring value to justify maintenance. A clean local rehearsal copy can expose most clean-machine problems earlier.

Security

For hosted workflows:

  • grant the minimum permissions;
  • do not print secrets;
  • do not execute untrusted pull-request code with write credentials;
  • pin third-party actions;
  • separate release credentials from ordinary checks;
  • treat artifacts and cache contents as untrusted input;
  • review dependency-update changes; and
  • require explicit human authority for publishing.

Python Repositories

Use one tool for deterministic lint and format when it covers the need. Ruff is suitable for STAGE's Python support code because it is fast, check-only in CI, and locally auto-fixable under an intentional command.

Start with correctness, import, and bugbear-style rules. Earn broader style rules from recurring defects rather than enabling a maximal preset.

Unity C#

Use:

  • Unity's compiler diagnostics;
  • Unity Test Framework;
  • assembly definitions for real ownership boundaries;
  • focused Roslyn analyzers for important mechanically expressible rules;
  • project validators for serialized assets and content; and
  • production-consumer PlayMode routes.

IDE inspections are useful local feedback. A rule relied upon for project acceptance needs a reproducible command or engine route, not only one person's IDE state.

SonarQube Or Qodana

Do not begin with a dashboard platform.

Adopt one only when all are true:

  • source/compiler/engine gates already run reliably;
  • recurring maintainability findings need cross-revision trend analysis;
  • the owner will review and act on the findings;
  • supported-language coverage matches the project;
  • false-positive and baseline policy is explicit; and
  • the service's administration cost is lower than the decision value.

Sonar quality gates are useful for declared code-health thresholds and new-code analysis. They still do not understand Unity scene wiring, serialized assets, gameplay feel, or fun.

Qodana's Unity support can make sense when JetBrains inspections are already the team's accepted vocabulary. It should remain advisory until its project-specific signal is measured.

For a solo STAGE project, a small Ruff/Roslyn/Unity/custom-validator stack is usually more transparent and maintainable.

Evidence Receipt Example

An optional work-item entry:

| Claim | Route | Evidence | Outcome | Limitation |
| --- | --- | --- | --- | --- |
| Forecast and night resolve identically | `MoonForecastParityTests` | Unity 6.3, commit `abc123`, EditMode XML | passed | Scenario set MS-01..03 only |
| Controller can schedule a Tether | Input System gamepad -> production UI -> command queue | composed PlayMode `MS-H1` | passed | One controller profile |
| Daytime pressure improves the game | uncoached Director play | session note `2026-08-02` | rejected | One owner, not target-player study |

The third result may reject a mechanically perfect implementation. That is the system working.

Repository Baseline Versus Project Baseline

STAGE's own repository can enforce:

  • Python lint and format;
  • schemas and structured data;
  • tests;
  • documentation maps and links;
  • a production build of the derived human documentation site;
  • plugin package integrity; and
  • diff hygiene.

The hosted workflow keeps Conventional Commit policy, the repository release gate, and the Docusaurus build in separate read-only jobs. The site job installs the pinned lockfile with Node.js 24, builds the static site with broken links and anchors treated as failures, screens generated output for high-confidence private data, and confirms that the shipped static output has no production Node dependency surface. Development-tool advisories remain visible maintainer input; they do not become green by rewriting unrelated packages or pretending build tools are runtime dependencies.

The separate publication workflow is downstream of that quality workflow. It publishes only after a successful main run, checks out the triggering run's exact revision, and replaces only the public documentation repository's gh-pages branch through a scoped deploy key. This preserves a simple rule: publication cannot race ahead of the quality evidence for the source it renders. Cloudflare Pages observes only that public mirror and deploys it as a static site; it has no access to canonical private source. Serving proves artifact publication, not method correctness or human acceptance.

The write-capable release-proposal workflow is also downstream of successful main quality and skips a stale trigger if a newer revision heads main, but it is not a quality gate or a release operation. It may write only a draft release branch and pull request. Its pinned Release Please action explicitly skips tags and GitHub Releases; the existing repository contracts intentionally require human completion before the proposal can pass as a release candidate.

A game adopting STAGE does not inherit those exact tools. It selects equivalent gates from its actual engine, languages, middleware, risks, and consumers. Copying STAGE's CI file without those conditions would be cargo culting.

Adoption Sequence

For an existing personal Unity project:

  1. document the current reliable local compile and test routes;
  2. add a source formatter/linter in check-only mode;
  3. add one aggregate change gate;
  4. encode only high-value architecture rules that repeatedly regress;
  5. add engine-side content and serialization validation;
  6. stabilize one composed smoke per critical lifecycle;
  7. prove the same commands from a clean rehearsal copy;
  8. move deterministic check-only work into CI;
  9. add standalone builds when distribution is a recurring need; and
  10. add dashboards only when someone uses their trends to make decisions.

Each step should reduce a known class of failure. Stop adding infrastructure when maintenance exceeds the human attention it saves.

References