Skip to content

Add AI agent guidance, architecture docs, and project skills#7550

Open
The-E wants to merge 14 commits into
scp-fs2open:masterfrom
The-E:feature/agent-guidance
Open

Add AI agent guidance, architecture docs, and project skills#7550
The-E wants to merge 14 commits into
scp-fs2open:masterfrom
The-E:feature/agent-guidance

Conversation

@The-E

@The-E The-E commented Jun 26, 2026

Copy link
Copy Markdown
Member

Summary

This branch adds onboarding/guidance material for AI coding agents (and
humans) working in the FSO tree, plus two small CI fixes turned up while
writing that guidance.

Top-level & per-module agent guidance

  • AGENTS.md — vendor-agnostic entry-point guide for agents: project
    overview, core philosophies (backwards compatibility, optional/gated
    gameplay changes, graceful hardware fallbacks), repo layout, build/test/style
    conventions, CI pipeline requirements (what actually has to pass — fatal
    warnings, the full compiler/platform matrix, valgrind on Linux Debug,
    clang-tidy's real scope), and runtime logging guidance (mprintf vs
    nprintf, per-frame logging pitfalls).
  • CLAUDE.md — thin Claude Code entry point that imports AGENTS.md via
    @AGENTS.md and indexes the Claude-specific skill stubs.
  • Per-module AGENTS.md stubs across code/* (ai, cfile, cmdline,
    globalincs, graphics, hud, io, lab, localization, menuui, mission,
    mod_table, model, network, object, options, parse, physics, scripting,
    ship, sound, ui, weapon) plus fred2/ and qtfred/.

Architecture & module documentation

  • documentation/ARCHITECTURE.md — high-level map of the engine's
    subsystems and where concepts live.
  • documentation/modules/*.md — per-module entry-point guides (~25 modules)
    so agents can navigate without blind grepping.

Vendor-agnostic project skills

  • .agents/skills/ is the canonical, tool-agnostic source of truth for FSO
    workflow skills: fso-add-table-field, fso-add-sexp, fso-add-lua-api,
    fso-add-object-type, fso-add-hud-gauge, fso-build-and-test, and
    thermo-nuclear-code-quality-review (an opt-in, strict
    maintainability/abstraction review, explicit invocation only), each
    encoding the exact files to touch and how to verify.
  • .claude/skills/ and .cursor/skills/ contain thin pointer stubs to the
    canonical .agents/skills/<name>/SKILL.md playbooks, so the guidance is
    authored once and shared across agent tools.
  • .agents/skills/README.md indexes the available skills and authoring
    conventions.

CI fixes found while documenting the pipeline

  • ci/linux/run_tests.sh: fixed a missing space ([ "$CONFIGURATION" = "Debug"]) that made the valgrind-vs-plain-test check always evaluate
    false — valgrind's leak checking was silently never running on the Linux
    Debug leg.
  • .github/workflows/test-pull_request.yaml: removed the macOS job's
    "Run Clang Tidy" / "Process clang-tidy warnings" steps. They were dead
    code (the if: startsWith(matrix.compiler, 'clang-') condition can never
    match macOS's bare clang compiler name) and, separately, clang_tidy.sh
    hardcodes a Linux-container-only binary path, so they couldn't have worked
    as written. clang-tidy remains Linux-only, as documented in AGENTS.md.

Why

FSO is a large, legacy-heavy, cross-platform C++ codebase. These docs give
agents (and new contributors) a navigable map of subsystems, the project's
build/style/CI conventions, and repeatable, FSO-correct workflows for common
engine extensions — reducing blind exploration and convention mistakes.

@The-E The-E force-pushed the feature/agent-guidance branch from f6bbf9f to bc3a6ca Compare July 5, 2026 09:37
@The-E The-E requested review from asarium and z64555 as code owners July 5, 2026 09:37
The-E and others added 2 commits July 5, 2026 12:40
The recent CI script typo fix (missing space in a bash test) means
valgrind now actually runs on Debug Linux builds, surfacing a
pre-existing one-time internal SDL2 allocation on SDL_Init that is
attributed to whichever test fixture's SetUp happens to run first
under --gtest_shuffle. This mirrors the existing gr_init suppression
below it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Valgrind 3.18.1 (used by CI) cannot parse the DWARF5 debug info that
clang-16 emits by default, causing the "unhandled dwarf2 abbrev form
code" errors and a hard valgrind abort before memcheck can even run.
Force -gdwarf-4 for Linux clang Debug builds (toolchain-clang.cmake is
Linux-only; macOS uses toolchain-apple-clang.cmake and never runs
valgrind) to keep the binary symbolizable.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment on lines +35 to +38
- Existing build dirs in-tree: `cmake-build-debug/`, `cmake-build-release/`,
`cmake-build-relwithdebinfo/` — reuse one instead of reconfiguring if present.
- The CI configure script is `ci/linux/configure_cmake.sh` (adds ccache, SIMD,
AppImage flags); match its options when reproducing a CI build.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I strongly disagree with reusing existing build dirs, as this will conflict with build caches from IDEs.
Any agent should be encouraged to only ever build in its own, seperate directory like cmake-build-agent and explicitly told to not touch other build dirs.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can make that change, but I am hesitant to make it an actual rule - my personal workflow, which consists of running claude inside CLion and letting it remote-control CLion for build tasks, kinda relies on using the build directories that already exist.


```bash
# Format only files you changed:
clang-format -i path/to/changed_file.cpp

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also not be prompted. In fact, I have expressly disabled the auto clang-format on my agent as this will introduces leagues of format-only changes in existing files. The agents should be told to adhere to clang-format, but NOT to run it as to avoid changing the format of existing code.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me.

Comment thread .agents/skills/README.md Outdated
| `fso-add-table-field` | Add/modify a parsed option in a `.tbl`/`.tbm` (ships, weapons, ai_profiles, game_settings, hud_gauges) and wire it into an `*_info` struct | `code/parse/parselo.*` + the owning module's parser | `documentation/modules/parse.md` |
| `fso-add-sexp` | Add a new SEXP operator (mission-scripting function): `OP_*`, `Operators` table, arg typing, `eval_sexp`, help text | `code/parse/sexp.{h,cpp}` | `documentation/modules/parse.md` |
| `fso-add-lua-api` | Expose engine data/functions to Lua via ADE bindings, or add a `scripting::Hook` mods can subscribe to | `code/scripting/` (`api/`, `global_hooks.*`) | `documentation/modules/scripting.md` |
| `fso-add-object-type` | Introduce a new in-world `OBJ_*` entity with create/move/delete + collision + render | `code/object/object.{h,cpp}` | `documentation/modules/object.md` |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably mention that adding an object type is a choice of last resort only if the existing object types cannot handle it at all

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment thread .agents/skills/README.md
- Builds use `FSO_FATAL_WARNINGS=ON` (CI default) — keep changes warning-clean.
- Code must compile on GCC, Clang, and MSVC; isolate platform code under
`code/osapi/`, `code/windows_stub/`, or platform guards.
- New parsed options use `optional_string` (never `required_string`) to preserve

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"unless gated as suboptions only passed if a new optional_string is hit"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

if: startsWith(matrix.compiler, 'clang-')
uses: asarium/clang-tidy-action@v1
with:
fixesFile: clang-fixes.yaml

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that remove was accidental?

@The-E The-E Jul 6, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, no - clang-tidy doesn't work like that on macOS runners. Replaced it with a step that actually works there.

Comment thread AGENTS.md
mkdir -p build && cd build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DFSO_BUILD_TESTS=ON \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
ninja -k 20 all

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe also -j 8 / 16?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added guidance to that effect

Comment thread AGENTS.md
- `FSO_BUILD_WITH_OPENGL` / `FSO_BUILD_WITH_VULKAN` — renderer backends.
- `FSO_FATAL_WARNINGS` — warnings become errors (used in CI; keep code clean).
- `FSO_BUILD_INCLUDED_LIBS` — build bundled libs instead of system libs
(default ON for Win/macOS, OFF for Linux).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FSO_BUILD_WITH_OPENGL_DEBUG is super useful
as is the options needed to build the interesting targets for unittests, fred and qtfred

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added.

Comment thread AGENTS.md Outdated
- **Includes:** sorted and regrouped; `globalincs/*.h` always come first.
Let clang-format handle include ordering.

Run formatting on changed files before submitting:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, let's not and in fact warn against blindly running clang-format

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

Comment thread AGENTS.md
transitions/edges (state changed, event fired) over logging steady-state
conditions every tick, and avoid building the message string when the
category is unlikely to be enabled.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also notes on Warning / WarningEx / ReleaseWarning and our stance on Assert vs Error vs error_display?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

Comment thread AGENTS.md Outdated
assume macOS gets clang-tidy coverage. Don't introduce new clang-tidy
findings in touched code.
- **clang-format is not enforced by CI** — there's no automated formatting
job — but reviewers expect it. Always run `clang-format -i` on changed files;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I am against clang-format

The-E added 4 commits July 6, 2026 17:58
Homebrew's Python on the macOS runners is externally managed, so a
plain `pip3 install` is rejected with "externally-managed-environment".
Pass --break-system-packages since the runner is ephemeral.
clang-tidy-diff.py only registers -export-fixes when it can import the
yaml module, so without pyyaml installed the argument is rejected as
unrecognized on macOS runners.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants