41 rules classified executable / checkable / decorative, each tagged with
the failure class it catches. Counts: 11 executable, 22 checkable, 4
decorative (one of them dead policy).
Audit: history/260731-inner-loop-rule-audit.md
New tools/loop-lint.py makes 7 rules executable (tier declared, chaos
roll recorded, tier-L review trail, unmeasured-in-evidence, whole-file
loadability, reporting tools expose --self-test). It found three real
violations on its first run, none previously visible:
- specs/ArchitectureBlueprint.md was 543 lines against a ~400 limit
the loop has stated since v0.2 and never measured. Split at its own
section boundaries into Blueprint (1-8) + Runtime (9-15).
- tools/dep-weight.py and tools/rule-coverage.py had positive-control
logic and no --self-test, so nothing verified the control worked.
Adding rule-coverage's self-test exposed a latent instance of the exact
class this workplan is about: if the spec regex stopped matching, rules
was empty, missing was empty, and the tool exited 0 reporting "0/0" --
a silent pass, in the tool that reports our headline AM-1 number. Both
tools now assert they found something before reporting.
Two demotions applied in the spec rather than left implicit: "structured
over prose" is marked guidance (nothing can check it), and the 8k/10k
token budget is struck through and marked DEAD POLICY pointing at T05.
The audit's uncomfortable finding: rule 13 (re-derive inherited numbers)
has no mechanical form, is deliberately left decorative, and caught the
LARGEST error in CB-WP-0002. That is a counter-example to this
workplan's own hypothesis. "A rule that cannot be executed is not a
rule" is wrong as stated; the defensible version is that such a rule
cannot be relied on to fire, so it must not be the only defence for a
class that matters.
Class coverage: harness-does-nothing has five executable rules;
trusted-arithmetic has ZERO and produced the largest single error.
make loop-lint and make self-tests wired into `make all` and CI.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
344 lines
11 KiB
Markdown
344 lines
11 KiB
Markdown
# Clay-Borg Architecture Blueprint
|
|
|
|
Reference architecture for the Clay-Borg framework. This document describes
|
|
the stable structural decisions: layers, component planes, capability ports,
|
|
data flows, and repository layout. For motivation and product intent see
|
|
[`../INTENT.md`](../INTENT.md); for the full originating exploration see
|
|
[`../history/260730-InitialExploration.md`](../history/260730-InitialExploration.md).
|
|
|
|
Status: **draft** — this blueprint is normative for new work but still
|
|
malleable (Clay). Changes go through a decision record in `decisions/`.
|
|
|
|
---
|
|
|
|
## 1. Layered architecture
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
TR["TargetRevenue Control Plane
|
|
phases • workload • revenue • licensing • trust"]
|
|
|
|
AF["Agentic Development Forge
|
|
specifications • work packets • generators
|
|
tests • scenarios • benchmarks • evidence"]
|
|
|
|
GP["Game Packages
|
|
GROUND • fixture games • future products"]
|
|
|
|
TT["Tabletop Framework
|
|
cards • decks • tokens • zones • hands
|
|
seats • hidden information • manipulation"]
|
|
|
|
GR["Game Runtime
|
|
commands • validation • rules • events
|
|
phases • simultaneous actions • replay"]
|
|
|
|
WS["World and Simulation
|
|
entities • components • transforms • time
|
|
scheduling • spatial queries • snapshots"]
|
|
|
|
PORTS["Canonical Capability Ports
|
|
render • physics • network • assets
|
|
UI • audio • persistence • scripting"]
|
|
|
|
LIBS["Assimilated Libraries
|
|
wgpu • Rapier • Bevy ECS • Wasmtime
|
|
Quinn • egui • Serde • tracing"]
|
|
|
|
PLATFORM["Platform Substrate
|
|
native • browser/WASM • server • CI"]
|
|
|
|
TR --> AF
|
|
AF --> GP
|
|
GP --> TT
|
|
TT --> GR
|
|
GR --> WS
|
|
WS --> PORTS
|
|
PORTS --> LIBS
|
|
LIBS --> PLATFORM
|
|
|
|
AF -.tests and measures.-> GR
|
|
AF -.tests and measures.-> WS
|
|
AF -.tests and measures.-> PORTS
|
|
TR -.governs releases.-> GP
|
|
TR -.governs releases.-> PORTS
|
|
```
|
|
|
|
### The four state kinds
|
|
|
|
Every subsystem must respect the separation between:
|
|
|
|
| State kind | Definition | Owner |
|
|
|---|---|---|
|
|
| **Authoritative semantic state** | What is legally happening in the game | Game runtime |
|
|
| **World state** | Where representations currently are | World layer |
|
|
| **Physical state** | How objects are moving | Physics port |
|
|
| **Presentation state** | What a particular player is allowed to see | Projection layer |
|
|
|
|
A game must remain playable in a headless process with no rendering and no
|
|
rigid-body simulation. The 3D tabletop is a projection and interaction
|
|
surface, never the definition of the game.
|
|
|
|
---
|
|
|
|
## 2. Clay Canon
|
|
|
|
The stable conceptual foundation shared by engines, games, tools, and agents.
|
|
|
|
| Component | Responsibility |
|
|
|---|---|
|
|
| Capability model | Names and describes each engine capability and its implementations |
|
|
| Canonical identifiers | Stable IDs for entities, players, assets, games, commands, events, sessions, packages |
|
|
| Schema system | Machine-readable definitions for game packages, assets, scenarios, engine configuration |
|
|
| Contract system | Interfaces and invariants every implementation must satisfy |
|
|
| Versioning model | Compatibility rules for APIs, schemas, save games, event logs |
|
|
| Capability registry | What exists, where it lives, maturity, dependencies, evidence, release phase |
|
|
| Assimilation manifests | Why a library was adopted, what boundary contains it, how it can be replaced |
|
|
|
|
### Assimilation manifest (required per external dependency)
|
|
|
|
```toml
|
|
capability = "physics.rigid-body.3d"
|
|
implementation = "rapier3d"
|
|
boundary_crate = "cb-physics-rapier"
|
|
canonical_interface = "cb-physics-api"
|
|
|
|
determinism = "authoritative-server"
|
|
replaceability = "high"
|
|
exposed_upstream_types = false
|
|
|
|
required_tests = [
|
|
"physics-conformance",
|
|
"snapshot-restore",
|
|
"card-stack-stability",
|
|
"drag-release-behavior",
|
|
]
|
|
|
|
required_benchmarks = [
|
|
"1000-resting-cards",
|
|
"deck-shuffle-and-deal",
|
|
"multi-object-picking",
|
|
]
|
|
```
|
|
|
|
**Hard rule: no external library type leaks across a canonical interface.**
|
|
A card must not contain a `RapierRigidBodyHandle`, a `wgpu::Texture`, or an
|
|
engine-specific entity id.
|
|
|
|
---
|
|
|
|
## 3. Runtime substrate
|
|
|
|
The lowest layer Clay-Borg owns itself:
|
|
|
|
- Platform abstraction, application lifecycle
|
|
- Time and fixed simulation ticks
|
|
- Task scheduling and job execution
|
|
- Memory and resource ownership conventions
|
|
- Deterministic random-number streams
|
|
- Configuration and feature flags
|
|
- Diagnostics and structured tracing (`tracing`)
|
|
- Capability discovery
|
|
- Error taxonomy
|
|
- Shutdown, recovery, headless execution
|
|
|
|
### Port/implementation pattern
|
|
|
|
Every important capability ships a **null**, a **reference**, and (when
|
|
financed) an **optimized** implementation:
|
|
|
|
```text
|
|
cb-time-api
|
|
├── cb-time-realtime
|
|
└── cb-time-controlled
|
|
|
|
cb-render-api
|
|
├── cb-render-null
|
|
└── cb-render-wgpu
|
|
|
|
cb-network-api
|
|
├── cb-network-loopback
|
|
└── cb-network-quic
|
|
|
|
cb-physics-api
|
|
├── cb-physics-null
|
|
├── cb-physics-reference
|
|
└── cb-physics-rapier
|
|
```
|
|
|
|
Null and reference implementations keep tests fast, expose semantic
|
|
assumptions, and let agents work without a GPU or a multiplayer environment.
|
|
|
|
---
|
|
|
|
## 4. Simulation kernel
|
|
|
|
Small and largely independent of game-specific concepts.
|
|
|
|
### Entity and component model
|
|
|
|
- **ECS** (`bevy_ecs`, assimilated standalone — not full Bevy) for world
|
|
composition, spatial representation, runtime scheduling.
|
|
- **Explicit typed aggregates** for game rules and authoritative state.
|
|
Canonical game state is never reduced to arbitrary ECS components.
|
|
|
|
### Mutation pipeline
|
|
|
|
Every meaningful state change follows:
|
|
|
|
```text
|
|
Intent
|
|
→ Command
|
|
→ Validation
|
|
→ Domain Events
|
|
→ State Reducer
|
|
→ New Authoritative State
|
|
→ World/Presentation Projection
|
|
```
|
|
|
|
This yields replay, undo/branching, multiplayer sync, bot/agent access,
|
|
auditing, save-game migration, rule debugging, and scenario testing.
|
|
|
|
### Snapshots and event logs
|
|
|
|
- Periodic full snapshots; append-only event streams
|
|
- Stable event serialization (Serde behind versioned Clay-Borg schemas)
|
|
- State hashes, replay seeds, branching from earlier state
|
|
- Snapshot migration; expected-vs-actual state comparison
|
|
- **Every failed test produces a replay bundle an agent can execute locally.**
|
|
|
|
---
|
|
|
|
## 5. Physics subsystem
|
|
|
|
Physics is a **service of the world, not a source of game truth**.
|
|
Rapier is the optimized implementation; the server owns authoritative
|
|
physical outcomes while clients interpolate and predict interaction
|
|
feedback. Do not depend on independently simulated client physics remaining
|
|
identical across platforms.
|
|
|
|
Tabletop physics scope (initial, deliberately narrow): pick up / move /
|
|
flip / place a card, stack and unstack, move relation markers, snap tokens
|
|
to tracks, animate reveal and resolution, prevent accidental scattering.
|
|
Dice, complex joints, bags, arbitrary models, and unrestricted throwing come
|
|
later.
|
|
|
|
---
|
|
|
|
## 6. World-building layer
|
|
|
|
Binds semantic objects to spatial representations.
|
|
|
|
| Concept | Meaning |
|
|
|---|---|
|
|
| World | An independently simulated environment |
|
|
| Scene | A loadable arrangement of objects |
|
|
| Object | A spatially represented entity |
|
|
| Prototype | Reusable object definition |
|
|
| Instance | Runtime occurrence of a prototype |
|
|
| Transform | Position, orientation, scale |
|
|
| Zone | A spatial area with semantic meaning |
|
|
| Surface | Table, board, tray, or similar placement area |
|
|
| Seat | A participant position and viewpoint |
|
|
| View | Player-specific projection of world state |
|
|
| Binding | Connection between domain state and world objects |
|
|
|
|
The world system supports multiple simultaneous projections: authoritative
|
|
server world, player-visible worlds, spectator, debug, replay, and
|
|
agent-observation worlds. This is what makes hidden hands and simultaneous
|
|
decisions tractable.
|
|
|
|
---
|
|
|
|
## 7. Tabletop domain framework
|
|
|
|
Canonical tabletop object set (no game reinvents these):
|
|
|
|
```text
|
|
Table Board Card Deck Stack Token Counter Marker Die Bag
|
|
Zone Hand Seat PlayerPointer Note Rulebook ScoreTrack
|
|
SequenceTrack Timer
|
|
```
|
|
|
|
Each object carries: physical representation, semantic identity, ownership,
|
|
visibility policy, interaction permissions, allowed operations, snap
|
|
behavior, serialization, behavior hooks, presentation variants.
|
|
|
|
### Game-operation modes
|
|
|
|
| Mode | Rule |
|
|
|---|---|
|
|
| **Sandbox** | Players manipulate objects freely; physics is primary, rules are social |
|
|
| **Governed** | Only legal commands alter authoritative state; objects merely visualize |
|
|
| **Hybrid** | Physical gestures *propose* commands; zones, ownership, and rules decide acceptance |
|
|
|
|
GROUND uses **hybrid mode**: dragging a card toward another player only
|
|
becomes an attack or support action when the rules engine validates target,
|
|
relationship capacity, timing, and card availability.
|
|
|
|
---
|
|
|
|
## 8. Game runtime and packages
|
|
|
|
A game package describes five things separately:
|
|
|
|
1. **Content** — cards, tokens, text, symbols, assets
|
|
2. **Setup** — session initialization
|
|
3. **Rules** — legal commands and their effects
|
|
4. **Flow** — phases, simultaneous windows, end conditions
|
|
5. **Presentation bindings** — how semantic state appears on the table
|
|
|
|
```text
|
|
games/ground/
|
|
├── GAME.toml
|
|
├── INTENT.md
|
|
├── rules/ # ground.wit, phases.yaml, actions.yaml, resolution.yaml
|
|
├── content/ # cards.yaml, tokens.yaml, symbols.yaml
|
|
├── scenes/ # table.scene.yaml, tutorial.scene.yaml
|
|
├── assets/
|
|
├── scenarios/
|
|
├── bots/
|
|
├── tests/
|
|
└── migrations/
|
|
```
|
|
|
|
### Extension boundary
|
|
|
|
Early GROUND rules live in native Rust crates. The stable extension boundary
|
|
is later expressed through **WebAssembly Interface Types** loaded via
|
|
**Wasmtime**. A game component receives explicit capabilities from the host
|
|
(read public state, propose commands, spawn canonical objects) — never
|
|
direct filesystem, network, clock, or GPU access.
|
|
|
|
### Simultaneous action primitive
|
|
|
|
```text
|
|
Open decision window
|
|
→ privately choose action and target
|
|
→ commit
|
|
→ wait for all players or timeout
|
|
→ reveal
|
|
→ order or group interactions
|
|
→ resolve
|
|
→ emit consequences
|
|
```
|
|
|
|
Networked play uses commit/reveal semantics so early submissions cannot be
|
|
inspected and exploited. The interaction-group resolver (mutual attacks,
|
|
support opposing an attack, capacity conflicts, simultaneous end conditions)
|
|
is expected to become one of the first genuinely reusable Clay-Borg
|
|
capabilities.
|
|
|
|
---
|
|
|
|
---
|
|
|
|
**Continued in [ArchitectureRuntime.md](ArchitectureRuntime.md)** — §9
|
|
rendering/input/creation tools, §10 networking and sessions, §11 the
|
|
agentic inner loop, §12 TargetRevenue integration, §13 repository
|
|
structure, §14 milestones, §15 governing design decisions.
|
|
|
|
*(Split 2026-07-31: this file was 543 lines against the loop's ~400-line
|
|
whole-file loadability rule. The rule had been stated since v0.2 and
|
|
nothing measured it until `tools/loop-lint.py` — see
|
|
`history/260731-inner-loop-rule-audit.md`.)*
|