278 lines
13 KiB
JSON
278 lines
13 KiB
JSON
{
|
|
"schema_version": 1,
|
|
"entries": [
|
|
{
|
|
"id": "api-shape-policy",
|
|
"rule": "api-shape",
|
|
"scope": "src/**",
|
|
"owner": "engine-maintainers",
|
|
"issue": "EVENGINE-QUALITY-API-SHAPES",
|
|
"reason": "Changed-line lint rejects new ambiguous operation bools and lastError channels; predicates remain valid bool APIs.",
|
|
"expiry": "2027-12-31",
|
|
"evidence": [
|
|
"docs/dev/Result检查与不得丢弃返回值规范.md",
|
|
"scripts/check_nodiscard.py"
|
|
],
|
|
"tests": [
|
|
"scripts/tests/test_architecture_contracts.py",
|
|
"scripts/tests/fixtures_architecture_contracts/valid_api.h"
|
|
],
|
|
"result_policy": "Operation outcomes use Result<T> or a named status enum; predicates may return bool.",
|
|
"nodiscard_policy": "Critical handles, subscriptions, scopes and operation Results are [[nodiscard]].",
|
|
"pointer_policy": "A public pointer requires Doxygen ownership/lifetime wording or an explicit reviewed adapter contract."
|
|
},
|
|
{
|
|
"id": "physics-link-contract",
|
|
"rule": "link",
|
|
"scope": "src/modules/physics/PhysicsLink.h",
|
|
"owner": "physics::World3D and physics::World",
|
|
"issue": "EVENGINE-ARCH-LINK-CONTRACTS",
|
|
"reason": "Physics links are process-local projections and must be stale-safe across either destruction order and restore.",
|
|
"expiry": "2027-12-31",
|
|
"evidence": [
|
|
"src/modules/physics/PhysicsLink.h",
|
|
"docs/dev/物理系统分层与后端契约.md"
|
|
],
|
|
"tests": [
|
|
"test/physics_artifact_provider.cpp",
|
|
"scripts/tests/test_architecture_contracts.py"
|
|
],
|
|
"symbols": ["PhysicsLink", "PhysicsShapeLink", "PhysicsJointLink"],
|
|
"create": "attach/fromBody/fromShape/fromJoint validate owner-qualified runtime handles",
|
|
"ownership": "World owns bodies, shapes and joints; gameplay stores only the typed link projection.",
|
|
"destroy_order": "Shape/Joint before Body/World and World before dependants both invalidate to StaleHandle.",
|
|
"restore": "Rebuild process-local links from persistent identity after transactional world restore or hot reload.",
|
|
"stale": "Generation and owner identity are checked by resolve; encoded validity alone is insufficient."
|
|
},
|
|
{
|
|
"id": "rts-link-contract",
|
|
"rule": "link",
|
|
"scope": "src/modules/rts/RTSTypes.h",
|
|
"owner": "RTS ECS world and registered RTS services",
|
|
"issue": "EVENGINE-ARCH-LINK-CONTRACTS",
|
|
"reason": "RTS cross-domain links distinguish ECS generation handles from service keys and rebuild after restore.",
|
|
"expiry": "2027-12-31",
|
|
"evidence": [
|
|
"src/modules/rts/RTSTypes.h",
|
|
"docs/dev/领域短根继承与跨域组合架构.md"
|
|
],
|
|
"tests": [
|
|
"test/rts_composition.cpp",
|
|
"scripts/tests/test_architecture_contracts.py"
|
|
],
|
|
"symbols": ["EntityLink", "ServiceLink", "FactionLink", "WeaponLink"],
|
|
"create": "EntityLink::bind and ServiceLink::bind return checked links.",
|
|
"ownership": "The ECS world or capability registry owns the target; a link never claims target ownership.",
|
|
"destroy_order": "Target destruction invalidates generation links; service unregister invalidates key links.",
|
|
"restore": "Entity links rebuild from entity identity and service links rebind by stable logical key.",
|
|
"stale": "Entity generation and service presence are checked before use."
|
|
},
|
|
{
|
|
"id": "scene-link-contract",
|
|
"rule": "link",
|
|
"scope": "src/modules/scene/SceneLink.h",
|
|
"owner": "scene node owner plus target-module provider",
|
|
"issue": "EVENGINE-ARCH-LINK-CONTRACTS",
|
|
"reason": "Scene link dispatch stays module-neutral and drops dead targets through provider-owned liveness checks.",
|
|
"expiry": "2027-12-31",
|
|
"evidence": [
|
|
"src/modules/scene/SceneLink.h",
|
|
"docs/dev/模块编排与裁剪架构.md"
|
|
],
|
|
"tests": [
|
|
"test/scene.cpp",
|
|
"scripts/tests/test_architecture_contracts.py"
|
|
],
|
|
"symbols": ["LinkOps", "SceneLink"],
|
|
"create": "The target module registers LinkOps and the scene stores a typed-kind projection.",
|
|
"ownership": "Scene owns link records; the provider owns the target object and callback table.",
|
|
"destroy_order": "Target teardown unregisters or reports dead before scene link dispatch; scene teardown drops records.",
|
|
"restore": "Provider re-registers operations and scene rebuilds link records from persistent node identity.",
|
|
"stale": "alive callback is consulted before push/pull; an absent operation id is not dereferenced."
|
|
},
|
|
{
|
|
"id": "state-owner-policy",
|
|
"rule": "state-owner",
|
|
"scope": "src/**",
|
|
"owner": "engine-maintainers",
|
|
"issue": "EVENGINE-ARCH-STATE-OWNERSHIP",
|
|
"reason": "Every mutable fact has one owner; adapters, snapshots and links are explicitly non-authoritative projections.",
|
|
"expiry": "2027-12-31",
|
|
"evidence": [
|
|
"docs/dev/重构代码质量与系统完整性规范.md",
|
|
"src/engine/common/StateAccess.h"
|
|
],
|
|
"tests": [
|
|
"test/snapshot_envelope.cpp",
|
|
"scripts/tests/test_architecture_contracts.py"
|
|
],
|
|
"state": "Mutable runtime state, persistent snapshot state and cached projections are named separately.",
|
|
"authoritative_owner": "The domain registry/container/world named by the contract is the sole writer of the fact.",
|
|
"projections": "Links, handles, ECS views and UI/script values are invalidatable projections and cannot become a second store."
|
|
},
|
|
{
|
|
"id": "rts-ecs-system-contracts",
|
|
"rule": "ecs-system",
|
|
"scope": "src/modules/rts/RTSSystems.h",
|
|
"owner": "rts::RTSSystems",
|
|
"issue": "EVENGINE-ARCH-ECS-SYSTEM-METADATA",
|
|
"reason": "RTS systems publish machine-readable access contracts before view iteration and deferred structural changes.",
|
|
"expiry": "2027-12-31",
|
|
"evidence": [
|
|
"src/modules/rts/RTSSystems.h",
|
|
"src/modules/rts/RTSSystems.cpp"
|
|
],
|
|
"tests": [
|
|
"test/rts_composition.cpp",
|
|
"scripts/tests/test_architecture_contracts.py"
|
|
],
|
|
"systems": [
|
|
"CommandFanOutSystem",
|
|
"MotionSystem",
|
|
"OrderActionSystem",
|
|
"BuildingProductionSystem",
|
|
"EffectSystem"
|
|
],
|
|
"entity_scope": "live Unit and Building ECS entities in the current world",
|
|
"view": "typed generation-checked Unit/Building views with no mutation while the view is iterated",
|
|
"read_set": "Transform, Motion, OrderComponent, Production and Effect components as applicable",
|
|
"write_set": "Transform, Motion, OrderComponent and lifecycle component outputs",
|
|
"structural_changes": "enqueue deferred add/remove/despawn operations after view traversal",
|
|
"events": "order accepted/completed, production advanced and effect lifecycle events",
|
|
"services": "injected SimulationStep, action executor and capability services",
|
|
"phase": "deterministic simulation phase before presentation and after command ingestion"
|
|
},
|
|
{
|
|
"id": "time-rng-policy",
|
|
"rule": "time-rng",
|
|
"scope": "src/**",
|
|
"owner": "simulation-maintainers",
|
|
"issue": "EVENGINE-ARCH-TIME-RNG-INJECTION",
|
|
"reason": "Simulation code receives typed time and named random streams; wall clock access is kept at adapters.",
|
|
"expiry": "2027-12-31",
|
|
"evidence": [
|
|
"src/engine/common/Time.h",
|
|
"docs/dev/重构代码质量与系统完整性规范.md"
|
|
],
|
|
"tests": [
|
|
"test/time_contract.cpp",
|
|
"scripts/tests/test_architecture_contracts.py"
|
|
],
|
|
"time_source": "SimulationStep/SimulationTick supplied by the scheduler; wall clock is not read by deterministic systems.",
|
|
"rng_stream": "named seed/stream is supplied by the owning simulation context and is not global mutable state.",
|
|
"determinism": "same inputs, tick and named streams produce replay/lockstep-identical results where declared deterministic.",
|
|
"tolerance": "backend or floating-point paths declare an explicit tolerance rather than silently claiming bit identity."
|
|
},
|
|
{
|
|
"id": "public-api-lifetime-policy",
|
|
"rule": "api-lifetime",
|
|
"scope": "src/**",
|
|
"owner": "engine-maintainers",
|
|
"issue": "EVENGINE-QUALITY-API-LIFETIME",
|
|
"reason": "Public pointer and callback APIs must state ownership, lifetime, affinity and reentrancy in Doxygen.",
|
|
"expiry": "2027-12-31",
|
|
"evidence": [
|
|
"AGENTS.md",
|
|
"docs/dev/重构代码质量与系统完整性规范.md"
|
|
],
|
|
"tests": [
|
|
"scripts/tests/test_architecture_contracts.py",
|
|
"scripts/check_nodiscard.py"
|
|
],
|
|
"thread_affinity": "each public API names caller/owner thread or explicitly states thread-safe access.",
|
|
"reentrancy": "callbacks and script calls state whether reentrant and are not invoked while a mutex is held.",
|
|
"ownership_contract": "owned, borrowed, observer and transferred values are explicit.",
|
|
"lifetime": "borrowed values are bounded by the documented call/frame/task lifetime; handles are stale-safe.",
|
|
"lock_callback_policy": "release internal locks before invoking unknown callbacks or scripts."
|
|
},
|
|
{
|
|
"id": "persistence-contract-policy",
|
|
"rule": "persistence",
|
|
"scope": "src/**",
|
|
"owner": "serialization-maintainers",
|
|
"issue": "EVENGINE-ARCH-PERSISTENCE-CONTRACTS",
|
|
"reason": "Persistent formats are versioned and restore is candidate-first so failures do not publish partial state.",
|
|
"expiry": "2027-12-31",
|
|
"evidence": [
|
|
"src/engine/common/Snapshot.h",
|
|
"src/modules/schema/Schema.h",
|
|
"docs/dev/Eve-Schema子集与绑定契约.md"
|
|
],
|
|
"tests": [
|
|
"test/snapshot_envelope.cpp",
|
|
"test/schema_contract.cpp",
|
|
"scripts/tests/test_architecture_contracts.py"
|
|
],
|
|
"schema": "stable logical schema id and content hash identify the payload.",
|
|
"version": "SchemaVersion and snapshot revision/tick are distinct typed fields.",
|
|
"migration": "known older versions migrate into a local candidate before validation and commit.",
|
|
"unknown_fields": "unknown fields follow the schema's explicit reject, preserve or ignore policy.",
|
|
"restore_atomicity": "parse, validate and migrate locally; publish once; failure leaves the observable owner unchanged."
|
|
},
|
|
{
|
|
"id": "optional-capability-policy",
|
|
"rule": "optional-capability",
|
|
"scope": "src/**",
|
|
"owner": "platform-maintainers",
|
|
"issue": "EVENGINE-ARCH-OPTIONAL-CAPABILITIES",
|
|
"reason": "Capability absence is a tested state, not an implicit soft skip; fallback behavior is observable and classified.",
|
|
"expiry": "2027-12-31",
|
|
"evidence": [
|
|
"cmake/profile_checks.cmake",
|
|
"docs/dev/2026-08-26-profile-quality-gates.md"
|
|
],
|
|
"tests": [
|
|
"test/profile/capability_present.cpp",
|
|
"test/profile/capability_absent.cpp",
|
|
"scripts/tests/test_architecture_contracts.py"
|
|
],
|
|
"present_test": "provider-present profile builds and runs the capability probe.",
|
|
"absent_test": "provider-absent profile builds and runs the explicit absence probe.",
|
|
"fallback_observable": "fallback status/diagnostic is exposed to the caller and is not a silent success.",
|
|
"fallback_policy": "fallbacks are named, classified and tracked by the bounded quality-debt metadata gate."
|
|
},
|
|
{
|
|
"id": "backend-contract-policy",
|
|
"rule": "backend-contract",
|
|
"scope": "src/**",
|
|
"owner": "runtime-platform-maintainers",
|
|
"issue": "EVENGINE-ARCH-BACKEND-CONTRACTS",
|
|
"reason": "CPU/GPU and provider implementations share observable contracts and inject failures at lifecycle boundaries.",
|
|
"expiry": "2027-12-31",
|
|
"evidence": [
|
|
"docs/dev/物理系统分层与后端契约.md",
|
|
"src/modules/physics/SimulationBackend.h"
|
|
],
|
|
"tests": [
|
|
"test/physics_artifact_provider.cpp",
|
|
"test/procgen_artifact_publish.cpp",
|
|
"scripts/tests/test_architecture_contracts.py"
|
|
],
|
|
"contract": "provider implementations expose the same Result/status, ownership, determinism and failure semantics.",
|
|
"providers": "CPU reference plus production GPU/Vulkan/WebGPU providers where the profile supplies them.",
|
|
"shared_contract_tests": "the same lifecycle and parity assertions run against each available provider.",
|
|
"failure_injection": "prepare, commit, rollback, restore and capability-loss failures are injected and assert no partial publication."
|
|
},
|
|
{
|
|
"id": "quality-debt-policy",
|
|
"rule": "debt-metadata",
|
|
"scope": "scripts/**",
|
|
"owner": "engine-maintainers",
|
|
"issue": "EVENGINE-QUALITY-DEBT",
|
|
"reason": "All explicit debt has owner, issue, reason, expiry and zero net-growth budget; the existing gate remains authoritative.",
|
|
"expiry": "2027-12-31",
|
|
"evidence": [
|
|
"scripts/check_quality_metadata.py",
|
|
"scripts/quality_debt_allowlist.json",
|
|
"scripts/quality_debt_baseline.json"
|
|
],
|
|
"tests": [
|
|
"scripts/tests/test_quality_metadata.py",
|
|
"scripts/tests/test_architecture_contracts.py"
|
|
],
|
|
"removal_condition": "remove the debt entry when the corresponding migration or documentation is complete; expiry forces review before renewal.",
|
|
"max_net_growth": 0
|
|
}
|
|
]
|
|
}
|