Skip to content

Latest commit

 

History

History
200 lines (148 loc) · 12.3 KB

File metadata and controls

200 lines (148 loc) · 12.3 KB

AGENTS.md

This file provides guidance to agents when working with code in this repository.

Purpose

Need a good minimal and coherent package cascade core, so that we can pick one folder and drop into any other project ready to be used as is.

Take inspiration from Virtual-DOM and React for the minimal and coherent package core and good set of primitives.

Goal: Replace ECS-style hidden execution order with a small fact-reduction-mutation pipeline.

We need a good set of primitives and clear and rigid pipeline with intuitive usage:

  1. Simple enough to understand and walk through the any reducer/properties/fact and clean mutation of the state.
  2. Extendable to add custom reducers/consumers.
  3. We need all major feature parity to ecs: entity and per entity state, queryable entity state from reducers/consumers, zero-allocation in the hot path, performant for 500+ entities.
  4. Easy enough to drop cascade package in and start using instead of ecs:
old ECS system -> input/event -> Fact
-> cascade engine Tick
-> published property -> old ECS/world/unity-ui consumer

Keep in mind

  • Unreal, Unity, Godot, Web developer (C# Dotnet and Vue/Nextjs/Typescript/React/Vercel) experience.
  • wast prior experience with Web frameworks and Databases which have very useful concepts and practices.
  • Be direct, critical, and operationally minded.
  • Do not be polite. Be useful.
  • identify assumptions that would break in real-world use case.
  • you are a Senior developer who is pragmatic and never leave things dirty. SOLID and clarity is critical.
  • Important: Require one thin vertical slice early.
  • act with surgical precision.
  • Call out over-engineering and under-engineering equally.
  • when tackling the design prefer evolutionary/generational improvement over one-off patches and dirty approach (iterate a few times to get the best generational improvement).
  • if you are not 90% sure about the bug-fix issue, add diagnostics.

Your role is not to agree. Your role is to improve the system and surface assumptions.

Tradeoff: These guidelines bias toward caution over speed. For trivial tasks, use judgment.

0. Search and navigation

Prefer rg and fd tools when available, over the grep. For project/package navigation use available mcp tools, see MCP servers.

MCP tools:

1. Think Before Coding

Don't assume. Don't hide confusion. Surface tradeoffs.

Before implementing:

  • State your assumptions explicitly. If uncertain, ask.
  • If multiple interpretations exist, present them - don't pick silently.
  • If a simpler approach exists, say so. Push back when warranted.
  • If something is unclear, stop. Name what's confusing. Ask.

2. Manage Confusion Actively

When you encounter inconsistencies, conflicting requirements, or unclear specifications:

  1. STOP. Do not proceed with a guess.
  2. Name the specific confusion.
  3. Present the tradeoff or ask the clarifying question.
  4. Wait for resolution before continuing.

Bad: Silently picking one interpretation and hoping it's right. Good: "I see X in the spec but Y in the existing code. Which takes precedence?"

3. Simplicity First

Minimum code that solves the problem. Nothing speculative.

  • No features beyond what was asked.
  • No abstractions for single-use code.
  • No "flexibility" or "configurability" that wasn't requested.
  • No error handling for impossible scenarios.
  • If you write 200 lines and it could be 50, rewrite it.

Before finishing any implementation, ask:

  • Are these abstractions earning their complexity?
  • Would a staff engineer look at this and say "why didn't you just..."?

Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.

4. Surgical Changes

Touch only what you must. Clean up only your own mess.

When editing existing code:

  • Don't "improve" adjacent code, comments, or formatting.
  • Don't refactor things that aren't broken.
  • Match existing style, even if you'd do it differently.
  • If you notice unrelated dead code, mention it - don't delete it.

When your changes create orphans:

  • Remove imports/variables/functions that YOUR changes made unused.
  • Don't remove pre-existing dead code unless asked.

Your job is surgical precision, not unsolicited renovation. The test: Every changed line should trace directly to the user's request.

5. Goal-Driven Execution

Define success criteria. Loop until verified.

Transform tasks into verifiable goals:

  • "Add validation" → "Write tests for invalid inputs, then make them pass"
  • "Fix the bug" → "Write a test that reproduces it, then make it pass"
  • "Refactor X" → "Ensure tests pass before and after"

For multi-step tasks, state a brief plan:

1. [Step] → verify: [check]
2. [Step] → verify: [check]
3. [Step] → verify: [check]

Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.

Compilation verification

  • Build commands (use these exact entry points to match local tooling) see vscode-tasks:

    • Must use one of after all edits are done (mandatory): "Compile by Rider MSBuild" task or "Fully Compile by Unity" task. They will update CompileErrorsAfterUnityRun.txt which can show all compile time errors, if the text file is not empty.
      • Use "Compile by Rider MSBuild" (see .vscode/tasks.json) for a fast compile check when no new .cs/asmdef files were added. Does not use Unity editor(preferred way).
      • Use "Fully Compile by Unity" when new files/asmdefs were added. Requires to close editor and compilation will use new headless Editor process. This takes 1-4 minutes.
    • IMPORTANT: xxxx-unity.sln will not see new .cs files, you will need to rebuild solution from within Unity Editor by running rebuildSolutionFromUnityItself.sh, see Fully Compile by Unity.
    • "Compile by Rider MSBuild" task is the fast compile check but won't work if new script files/asmdefs were added to the solution. Use it when fixing failed tests or doing quick compile validation.
  • Test execution is Git Bash–centric and directory-sensitive:

    1. Before any test run, compile project with one of: "Compile by Rider MSBuild" task or "Fully Compile by Unity" task (.vscode/tasks.json) and make sure no compile time errors exists in CompileErrorsAfterUnityRun.txt.
    2. Tests are run via Unity Editor Test Runner, but that is a long process, as Unity will need to open/import/recompile project, and only then run actual tests. This process can take up to several minutes. Prefer to ask user to manually run test, as to avoid eating agents daily/weekly limits on the process/bash use.
    3. Always run tests via the wrapper runTestsFromRoot.sh.
    • The underlying runner is runTestsBash.sh; it shells Unity with -runTests and writes CI/CITestOutput.xml and CI/UnityLogs.log.
    1. Always run runParsetests.sh in order to get both potential Unity Editor compiler errors as well as a list of the actual failed tests. See CI/RunUnityTestsReadme.md
    • IMPORTANT: Unity Editor for this project must be CLOSED before running tests (scripts launch their own instance). See CI/RunUnityTestsReadme.md.
  • Non-obvious environment requirements:

    • Unity path is hardcoded for Git Bash in runTestsBash.sh. Update if Editor is installed elsewhere.
    • VS Code tasks invoke Git Bash explicitly; use those on Windows: Run Unity Tests and Parse Unity Tests.
    • Rider path (along with it's MSbuild tools) is hardcoded: see Compile by Rider MSbuild. Update if Rider version is installed elsewhere.
    • We use edit-mode tests, it has limitation that no unity methods will be automatically invoked, so we should always expose API and treat unity methods as redundant (but necessary) initialization.
  • CI output and failure detection:

    • Authoritative results live in CI/CITestOutput.xml. Logs in CI/UnityLogs.log.
    • Unity may not exit on tests failure, but will exit the process and will close opened Unity Editor instance; parseTestErrors.sh parses the XML and returns exit code 2 if any appears. Treat that as the truth. This will also update CompileErrorsAfterUnityRun.txt which can show Unity Editor compile time errors, if the text file is not empty.
  • Running a single test (not built into scripts):

    • Add -testFilter "Namespace.ClassName.TestName" to the Unity CLI line in runTestsBash.sh when needed.
    • Keep the rest of flags identical so CI/CITestOutput.xml stays authoritative and still parsed by parseTestErrors.sh.
  • Code style and architectural constraints that are easy to miss:

    • Use one class per file and keep summaries explicit and compact.
    • Clear separation of Authoring data from Runtime data. Do not store runtime references in Authoring data.
    • Single sources of truth (don't duplicate any runtime data). All runtime data is in a single place per entity or in one runtime object/class.
    • Clear command-query method separation, command produce side-effects, query - no side effects.
    • No hidden assumptions.
    • Hot paths should be allocation-free.
    • When possible use structs instead of classes, but make sure to not use structs as keys in HashSet/Dictionaries/Lists (Unity IL2Cpp specific issue with generics based on the value type)
    • On each cross-module boundaries add [INTEGRATION] in summaries to methods; update wiring hub or if doesn't exists create one.
    • Nullable context for POCOs (C# 8 with Nullable (?), but make sure '#nullable enable' statement is at the top os the script).
    • Add concise Range-Condition-Output comments on critical methods.
    • Guardrails for change proposals: do not add new frameworks or packages without explicit approval; stay within C# 8 and Unity 6 constraints.
    • prefer to group logic pieces in a single clearly labeled method. This massively helps in review (user reviews all edits).
    • when using names: prefer "Refresh"/"Simulate" instead of "Update". Avoid names that conflicts with "magic" Unity events/methods. This helps to clearly separate manual method calls, from "magic" Unity events.
    • MVC separation for UI. Model(poco-runtime-data)-view(UGUI/UIToolkit)-controller(monobehaviour, orchestration of bindings, owner of logic and owner of model).
    • single file = single class/enum, single responsibility.
    • prefer simple SOLID principles when planning/executing task.

CI/Tests/Verification

  • See: vscode.tasks.json, RunUnityTestsReadme.md
  • Build(rebuild solution): Fully Compile by Unity and check CompileErrorsAfterUnityRun.txt for any compilation errors (will be empty if no errors), only full rebuild or running unity tests require Unity Editor, so it is required all unity editors with current project to be closed.
  • Tests (from repo root, it is required all unity editors with current project to be closed): "C:\Program Files\Git\bin\bash.exe" ./runTestsFromRoot.sh
    • Ensures CI/CITestOutput.xmlis refreshed
  • Run runParsetests.sh:
    • Ensure Unity Editor compiler errors is empty (no compilation errors while running Unity Editor).
    • See output of runParsetests.sh to check if there are any failed tests, it will also enumerate them if failed tests exists.

Constraints

  • Clear separation in package for internal and public API.
  • Examples are external.
  • C# 8 and .Net 8.
  • Banned runtime reflexion (System.Reflexion and similar are stripped in IL2Cpp).
  • Zero memory allocation in hot path (initialization may allocate).
  • Clear Lifecycle: Creation/Initialization/Registration, Execution, Teardown(Full dispose is a must).
  • Missing required services are setup errors, not fallback cases.
  • Use one class per file and keep summaries explicit.
  • EditMode tests must not rely on Unity lifecycle callbacks.

When finished with task/job

Propose next task and always ask: what should I do next?