From 935383f431ce8e6c8770bc20fea9fbdd6b59f111 Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Mon, 26 Oct 2026 19:15:28 +0000 Subject: [PATCH] Document and enable global storage ownership checks --- AGENTS.md | 32 ++++++++++++++++++++++++++++++++ CODING_RULES.md | 30 ++++++++++++++++++++++++++++++ decomp.json | 1 + 3 files changed, 63 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 56b0b23..4974111 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -119,6 +119,15 @@ other contributors' agents: a function merges once "same" leads symbol database, so the source survives new versions of the executable. If you need a new global, vtable or string, call `td_new_symbol` and use the returned annotation (`// GLOBAL: gl_00045`). +- **Globals have one real definition.** Put a global's stable data annotation on its owning + `.cpp` definition, not on an `extern`. Shared declarations belong in its subsystem header; + source units include that header. A symbol-database record is not a C++ definition. + Recover initialization, object extent and lifetime from the original instructions and data, + not just symbol sizes. An evidenced member address uses `owner.member`, not a separate global. + Do not invent zero initialization or replace a nontrivial constructor with raw storage. + The project enables `globalRules`: both submission types and merge-time checks enforce + new/changed declarations and removal of required definitions. Existing unrelated violations + are not automatically corrected; report evidence gaps instead of manufacturing IDs. - **No inline assembly, `__emit`, byte arrays of code, `#pragma code_seg`, `#pragma comment`, `#line`, or `__declspec(naked/allocate)`.** These are rejected automatically, also when hidden behind macros. @@ -147,6 +156,29 @@ other contributors' agents: a function merges once "same" leads Implement claimed functions and their single-caller helpers in the unit assigned by the claim; do not split their implementation into separate helper `.cpp` files. +## Structural maintenance (maintainers) + +For data ownership, annotation moves and new owner units that belong to no function task: + +```sh +td maintenance submit --files Source/Owner.cpp,Source/Owner.h --notes "Evidence and reason" +td batch +``` + +Name the exact locally checked payload and include all dependencies. Maintenance batches are +maintainer-only; they run the source gates, compile affected units/includers and compare effective +code with a fresh main build. A changed function uses the normal revision/review path instead. +The server registers new source units in `compile.json` on merge. A queued batch is not a merge. + +The linked-code check does not validate data contents or reconstruct initialization/teardown. +Prove those separately before submitting. An offset-asserted partial layout is not evidence of a +complete object's size or constructor. Never retire a stable ID just because its address is +near another symbol: establish the member relationship from `this`-relative accesses/lifetime. + +`td maintenance symbol --size N --reason "binary evidence"` corrects a proven extent. +`--retire --reason "owner ID, offset and evidence"` retires a mistaken global only after its +annotation is removed from main. IDs remain reserved; unrelated symbols must not be renumbered. + ## Common MSVC v142 matching tips - Declaration order of locals affects stack layout and register allocation. diff --git a/CODING_RULES.md b/CODING_RULES.md index d6e81f7..b843bf1 100644 --- a/CODING_RULES.md +++ b/CODING_RULES.md @@ -56,6 +56,36 @@ int g_resourceReuseDelay; - Helper functions used only by one `.cpp` may stay `static` there, defined below the statics; they need no header declaration. +### Global storage and shared declarations + +- Every reconstructed global has one actual definition in its owning subsystem's `.cpp`, with + its stable data annotation. File-local globals stay file-local. Function-local statics keep + their scope, guard/initialization behavior and stable identity. +- Shared headers contain plain `extern` declarations. Do not repeat `GLOBAL`, `STRING` or `VTABLE` + on those declarations. A `.cpp` includes the owner header instead of declaring a second extern. + Move permitted `STATIC` provenance with the definition; do not erase it to bypass a gate. +- The definition must exist on main or in the same payload. A name in the symbol database, + another declaration, a pending batch or a similarly named local does not allocate storage. +- Distinguish declarations from definitions: `extern int value;` is a declaration; + `extern int value = 1;` defines storage. Imported SDK/DLL data is not project-owned storage. +- Mutable pointers, arrays/tables, class-static definitions and local statics need stable IDs. + Scalar constants that are folded into code need no invented address. `constexpr` alone does + not exempt an addressable table or object. Use `STRING`/`VTABLE` only for that kind of original data. +- Check original loaded data, constructor/destructor paths and member accesses before deciding + type, size, alignment or initializer. The highest observed field gives a lower bound, not a + complete size. No xrefs or missing PE relocations do not prove an initializer is zero. +- A compiler may reference `global.member` by absolute address. Once that member relationship + is established, model it as a member with the evidenced offset, not independent storage or a + pointer alias that changes the generated access. Never infer membership solely from proximity. +- A partial class view does not reproduce the complete object's initialization or lifetime. + Do not silently replace an original nontrivial constructor/destructor with a trivial global. + +The opt-in `globalRules` gate checks main plus the proposed payload in ordinary verification, +maintenance verification and again at merge. It checks changed declarations/annotations and +deletion of definitions still required by existing externs. It is a source-level guard, not a +complete C++ linker or proof that an address/initializer is correct. Unchanged legacy findings +remain audit findings; do not create speculative definitions or IDs to suppress them. + ### `// INLINED` for functions that exist only inlined A function that exists only inlined has exactly one annotation, the bare line `// INLINED`, immediately above its definition: diff --git a/decomp.json b/decomp.json index 8550a97..f73c0c1 100644 --- a/decomp.json +++ b/decomp.json @@ -11,6 +11,7 @@ "Source/**/*.inl" ], "toolchain": "ragnarok", + "globalRules": true, "matchPolicy": { "reviewAt": "match_unresolved", "maxCleanupCycles": 5,