From c6f3d076c9ff5b01d1ccabd2441ee78735b7b89c Mon Sep 17 00:00:00 2001 From: Cameron Date: Fri, 10 Jul 2026 09:27:57 -0700 Subject: [PATCH] Clarify crate workspace as standing architecture with reasons. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite crate-workspace.md from a migration checklist into binding layout law: why four packages, naming (core package / misaligned lib), dependency edges including Bevy→assets mesh share, gate mapping, and rejected alternatives. architecture.md points at that page for why and mirrors as-built paths only. Defense: Living-spec corpus rule — current package architecture lives on the owning Type: spec page with design reasons attached, not only in session history. --- wiki/engineering/architecture.md | 16 +- wiki/engineering/crate-workspace.md | 248 ++++++++++++--------- wiki/log/2026-07-10-crate-workspace-why.md | 25 +++ wiki/log/DEVLOG.md | 5 + wiki/log/decisions/2026-07-10.md | 8 + 5 files changed, 195 insertions(+), 107 deletions(-) create mode 100644 wiki/log/2026-07-10-crate-workspace-why.md diff --git a/wiki/engineering/architecture.md b/wiki/engineering/architecture.md index 43299123..136d36c3 100644 --- a/wiki/engineering/architecture.md +++ b/wiki/engineering/architecture.md @@ -4,8 +4,12 @@ Type: knowledge ``` **As-built:** a Cargo **workspace** with four packages. Game rules live only in -`misaligned-core`; frontends are thin packages that depend on it. Binding -contracts: [crate-workspace.md](crate-workspace.md) (IMPLEMENTED), +`misaligned-core`; frontends are thin packages that depend on it. + +**Why this shape exists** (binding): [crate-workspace.md](crate-workspace.md) +— package jobs, dependency edges, naming, rejected alternatives, and standing +criteria. This knowledge page is the path/layout mirror; it does not replace +that page's reasons. Multi-agent gates: [agent-scale.md](../process/agent-scale.md). ## Workspace layout @@ -32,7 +36,13 @@ crates/ | `misaligned-assets` | Mesh/material boards, art harness | Save/load of full runs; sim progression | Frontends import the lib as `misaligned::…` (crate name `misaligned-core`, -lib name `misaligned`). +lib name `misaligned`). That split is deliberate: package name states the +**job** (core); lib name states the **product** so imports stay stable — see +crate-workspace naming. + +`misaligned-bevy` depends on `misaligned-assets` for shared rack/mesh spawn +so the game binary and the asset tester do not fork mesh code; assets still +does not depend on core (no sim progression in the tester). ## The sim/frontend contract diff --git a/wiki/engineering/crate-workspace.md b/wiki/engineering/crate-workspace.md index 0b391940..5d6e0b28 100644 --- a/wiki/engineering/crate-workspace.md +++ b/wiki/engineering/crate-workspace.md @@ -3,10 +3,10 @@ ``` Type: spec Status: IMPLEMENTED -Status note: landed 2026-07-10 — Cargo workspace with misaligned-core - (lib name misaligned), misaligned-terminal, misaligned-bevy, - misaligned-assets (lib+bin; shared rack meshes). check.sh/CI/seed updated - for package paths; no feature-flag substitute for package boundaries. +Status note: landed 2026-07-10. This page is the **standing** package + architecture: shape, contracts, and the reasons they exist — not a + one-shot migration checklist. Knowledge page architecture.md mirrors + as-built paths; amend this page when package boundaries change. Stage: Process Design: - wiki/vision/simulation-laws.md#justification-and-legibility @@ -20,122 +20,162 @@ Depends on: ## Dependency notes -The structured references above identify the contracts to re-verify. -Relationship context: +- [agent-scale.md](../process/agent-scale.md) — multi-agent gates and claims + map onto these packages (`--lib` ≈ core/terminal; `--frontend` ≈ bevy/assets). +- [architecture.md](architecture.md) — knowledge mirror of as-built layout and + the sim/frontend contract (non-authoritative where this page conflicts). +- [workflows.md](../process/workflows.md) — how to run cargo and check.sh against + packages. -process/agent-scale.md (coordination and gate tiers assume this shape eventually; not a -hard prerequisite for other agent-scale slices), engineering/architecture.md (knowledge -— current monorepo facts), process/workflows.md (knowledge — verification tiers map onto -packages). +## Why the workspace exists -## Why this exists +The game law was already clear: **rules in the lib; frontends are thin views.** +A single Cargo package with optional Bevy features did not enforce that law. +It only *suggested* it: -One package forces every agent that touches `src/` to share a compile graph -with Bevy when features flip, and forces gate classification to paper over -a boundary the crate graph does not enforce. The law is already "game rules -in the lib; frontends are thin views." The **workspace** should make that -law structural: a core agent never pays Bevy; a Bevy agent never rebuilds -terminal chrome; package edges match the sim/frontend contract. +1. **Compile graph** — Any `src/` touch shared one feature matrix with Bevy. + Agents paying for a sim-only fix still rebuilt (or risked rebuilding) the + heavy frontend graph. Tiered `check.sh` path heuristics papered over a + boundary the crate graph did not draw. +2. **Mental model** — One package trained agents to treat “the crate” as the + unit of work. Contending on one `Cargo.toml` and one local-package + personality made parallel worktrees thrash. +3. **False coupling** — Feature flags (`terminal`, `bevy_ui`) are switches, not + walls. They do not stop a frontend from re-implementing a rule “just this + once,” and they do not prove that core is free of Bevy. -This is a spread-out codebase on purpose: less monolith, more packages with -narrow jobs, so many agents can work without contending on one `Cargo.toml` -and one `target/` personality. +The workspace makes the law **structural**: -## Target shape (binding) +- A core agent can `cargo test -p misaligned-core` without Bevy in the graph. +- A Bevy agent does not rebuild terminal chrome. +- Package edges are the same cut as the sim/frontend contract. + +This is a **spread-out codebase on purpose** — less monolith, more packages with +narrow jobs — so many agents can work without contending on one product crate. + +## As-built shape (binding) ``` -Cargo.toml — workspace root only (members, shared deps, profiles) +Cargo.toml — virtual workspace only (members, shared deps, profiles) crates/ - misaligned-core/ — sim library: all game rules, no wall clock, no I/O - misaligned-terminal/ — crossterm frontend binary (depends on core) - misaligned-bevy/ — Bevy 0.18 frontend binary (depends on core + bevy) - misaligned-assets/ — procedural asset tester (depends on bevy bits only - or core+bevy as today; no sim progression required) + misaligned-core/ — sim library (package name); lib name `misaligned` + misaligned-terminal/ — binary `misaligned` (crossterm + agent protocol) + misaligned-bevy/ — binary `misaligned-bevy` (Bevy 0.18 frontend) + misaligned-assets/ — lib `misaligned_assets` + binary `misaligned-assets` +``` + +There is **no** root `src/` product tree and **no** feature-flag substitute for +these packages. Optional features must not re-merge package jobs. + +### Why four packages (not two, not twenty) + +| Package | Job | Why it is separate | +|---|---|---| +| **core** | All game rules, save format, sim tests | Must stay free of render/input toolchains so sim work stays cheap and deterministic. | +| **terminal** | Player/agent text surface + wall clock | First-class frontend; must not pull Bevy; must not own rules. | +| **bevy** | Material/digital 3D/2.5D view + shot harness | Heavy compile graph; isolated so frontend thrash does not block sim agents. | +| **assets** | Procedural meshes / art tester boards | Shared mesh code without loading the full game loop; no sim progression. | + +**Not** one umbrella `misaligned-frontends` package: that would keep terminal +and Bevy compile-coupled and erase the frontend-tier win. + +**Not** one crate per mechanics module: coordination cost exceeds compile +win until a real module boundary demands it (see out of scope). + +### Naming choices (and why) + +| Choice | Why | +|---|---| +| Package `misaligned-core`, **lib name `misaligned`** | Frontends keep `use misaligned::…` so imports and mental model stay “the sim,” not a rename churn. Package name states the *job* (core); lib name states the *product*. | +| Binary names `misaligned`, `misaligned-bevy`, `misaligned-assets` | CLI, docs, shot harnesses, and muscle memory stay stable after the split. | +| Directory prefix `crates/misaligned-*` | Workspace-local, greppable, matches package names. | + +### Dependency edges (and why) + +``` +misaligned-terminal ──► misaligned-core +misaligned-bevy ──► misaligned-core + ──► misaligned-assets (shared rack / mesh spawn) +misaligned-assets ──► bevy only (no core, no sim progression) +misaligned-core ──► serde, serde_json, dirs + ✗ bevy, crossterm ``` -Binary names and player-facing CLI stay familiar where practical -(`misaligned`, `misaligned-bevy`, `misaligned-assets`) so docs and habits -do not thrash; package directory names may use the `misaligned-*` prefix. +- **Bevy → assets** exists so rack chassis meshes are not copy-pasted into the + game binary. Assets remain free of `Sim` so the tester does not boot a run. +- **`dirs` in core** is allowed only for **save-path infrastructure** on the + save format (where the JSON file lives), not for wall-clock or network I/O + as game rules. Sim progression still does not read the environment for + behavior switches (see env registry: game rules are not env-toggled). +- **No shared `CARGO_TARGET_DIR` across worktrees** for local packages — already + caused a false green. Dependency caches (e.g. sccache) may be shared; local + package artifacts stay private (agent-scale / seed script). -### Package contracts +### Package contracts (standing) | Package | May contain | Must not contain | |---|---|---| -| `misaligned-core` | `Sim`, map, systems, save format, tests of rules | `Instant::now`, filesystem (except tests that use temp dirs if already patterned), Bevy, crossterm, env reads for game rules | -| `misaligned-terminal` | UI, input, agent line protocol, wall-clock tick mapping | Game-rule `if`s that should live on `Sim` | -| `misaligned-bevy` | 3D/2.5D view, shot harness, wall-clock tick mapping | Game-rule forks of `Sim` behavior | -| `misaligned-assets` | Mesh/material boards, art harness | Save/load of full runs; sim progression | +| `misaligned-core` | `Sim`, map, systems, save format, rule tests | Bevy, crossterm, wall-clock-driven rules, `Instant::now` as game time, env reads that change rules | +| `misaligned-terminal` | UI, input, agent line protocol, wall-clock → tick | Game-rule `if`s that belong on `Sim` | +| `misaligned-bevy` | View, shot harness, wall-clock → tick | Game-rule forks of `Sim` behavior | +| `misaligned-assets` | Mesh/material boards, art harness | Full-run save/load; sim progression | Frontends talk to core through **command/query methods** and read state for -render — same contract as [architecture.md](architecture.md) "The -sim/frontend contract," lifted into package edges. +render — same contract as [architecture.md](architecture.md) “The +sim/frontend contract,” enforced by package edges. -### Gate and worktree mapping (once landed) +### Gates map onto packages (why tiers work) -| Change class | Default gate | Typical packages | +| Change class | Default gate | Why | |---|---|---| -| docs | `./tools/check.sh --docs` | none | -| lib / sim | `./tools/check.sh --lib` | `misaligned-core` (+ cheap check of terminal/bevy consumers) | -| frontend Bevy | `./tools/check.sh --frontend` | `misaligned-bevy`, optionally `misaligned-assets` | -| full | `./tools/check.sh --full` | workspace | - -`tools/check.sh` path classification and seed-target rules must be updated -in the same landing so tiers name packages, not only path prefixes. - -## Migration posture (how to implement when dispatched) - -1. Introduce the workspace with **core extracted first** (move `src/` lib - modules; keep binaries compiling via path deps). One green main at each - intermediate step. -2. Lift terminal binary into `misaligned-terminal` without behavior change. -3. Lift Bevy + assets; keep feature flags only if still needed for optional - deps, not as a substitute for package boundaries. -4. Update `tools/check.sh`, CI (Tangled), `seed-cargo-target.sh`, AGENT.md - path hints, and architecture knowledge in the same arc — no "code moved, - gates still monorepo" half-state. -5. No dead dual trees: when a module lives in a package, the old path is gone - (no-dead-code). - -Do **not** share one `CARGO_TARGET_DIR` across worktrees. Prefer sccache or -equivalent for **dependency** objects; keep per-worktree outputs for local -packages (see [agent-scale.md](../process/agent-scale.md)). - -## Acceptance criteria - -1. The repository is a Cargo **workspace** whose members are at least - `misaligned-core`, `misaligned-terminal`, `misaligned-bevy`, and - `misaligned-assets` (names may match today's binary names if preferred, - but package boundaries match the table above). -2. `misaligned-core` has **no** dependency on `bevy` or `crossterm`. A - `cargo test -p misaligned-core` (or equivalent) does not build Bevy. -3. Game rules live only in core; a grep-level audit (or crate visibility) - shows frontends do not re-implement sim rules. Existing sim/frontend - contract tests still pass. -4. Terminal and Bevy binaries still run and pass their existing smoke / - harness expectations (`--agent` determinism; Bevy shot harness kinds - documented in env.md). -5. `./tools/check.sh` auto-classification and documented tiers target the - new packages; CI still enforces a conservative full workspace gate. -6. [architecture.md](architecture.md) describes the **as-built** workspace - (this page's target becomes current knowledge); ROADMAP conflict flags - name packages/hot crates, not only `src/sim.rs`. -7. Save format ownership stays in core; version migrations do not move into - frontends. - -## Explicitly out of scope (for this work order) - -- Micro-splitting every mechanics module into its own crate (premature). -- Shared `CARGO_TARGET_DIR` across worktrees. -- Changing game rules, save version, or player-facing behavior except as - required by path moves. -- Implementing other [agent-scale.md](../process/agent-scale.md) slices in - the same commit unless they are necessary for the workspace to gate green. - -## Rejected alternatives - -- **Stay one package, smarter features only** — features do not stop agents - from sharing one graph and one mental model of "the crate." -- **core + one `misaligned-frontends` umbrella** — keeps terminal and Bevy - compile-coupled; loses the frontend-tier win. -- **Full `CARGO_TARGET_DIR` sharing for speed** — already produced a - false-green; forbidden unless package-private outputs are proven isolated. +| docs | `./tools/check.sh --docs` | No product graph. | +| lib / sim | `./tools/check.sh --lib` | Core (+ terminal clippy) + cheap `cargo check -p misaligned-bevy` so API breaks still surface without full Bevy clippy. | +| frontend | `./tools/check.sh --frontend` | Bevy + assets only. | +| full / CI | `./tools/check.sh --full` / Tangled | Whole workspace; conservative. | + +Path classification keys off `crates/misaligned-*`, not a single `src/`. + +## What this is *not* + +- A claim that four packages are forever enough — only that further splits need + a new reason as strong as the ones above. +- Permission to put game rules in a frontend “temporarily.” +- Permission to reintroduce feature flags as the real boundary between jobs. +- A mandate to micro-crate every mechanic. + +## Rejected alternatives (keep these rejected) + +- **Stay one package, smarter features only** — features are not walls; agents + still share one product crate and one mental model. +- **core + one `misaligned-frontends` umbrella** — terminal and Bevy stay + compile-coupled; loses proportional frontend gates. +- **Shared `CARGO_TARGET_DIR` across worktrees for speed** — produced a false + green; forbidden for local package artifacts. +- **Rename the lib to `misaligned_core` in Rust code** — huge import churn for + no boundary gain; package name already states the job. + +## Standing acceptance criteria + +These remain true for the life of the layout (not a one-time land checklist): + +1. The repo is a Cargo **workspace** with at least `misaligned-core`, + `misaligned-terminal`, `misaligned-bevy`, and `misaligned-assets`. +2. `misaligned-core` has **no** dependency on `bevy` or `crossterm`. + `cargo test -p misaligned-core` does not build Bevy. +3. Game rules live only in core; frontends do not re-implement sim rules. +4. Binary names remain `misaligned`, `misaligned-bevy`, `misaligned-assets` + unless a deliberate product rename is specced. +5. `./tools/check.sh` auto-classification and documented tiers key off + packages; CI enforces a conservative full workspace gate. +6. [architecture.md](architecture.md) stays an accurate as-built mirror; + ROADMAP conflict language names packages/hot modules under core. +7. Save format ownership stays in core; migrations do not move into frontends. +8. **Why sections above stay true** — if a future change weakens a reason + (e.g. Bevy back in core “just for types”), amend this page in the same + commit or reject the change. + +## History (non-authoritative) + +Implemented 2026-07-10 from a READY deferred work order. Pre-split form was a +single package with optional `terminal` / `bevy_ui` features under root `src/`. +Migration detail lives in `wiki/log/2026-07-10-crate-workspace.md`. diff --git a/wiki/log/2026-07-10-crate-workspace-why.md b/wiki/log/2026-07-10-crate-workspace-why.md new file mode 100644 index 00000000..124e895e --- /dev/null +++ b/wiki/log/2026-07-10-crate-workspace-why.md @@ -0,0 +1,25 @@ +# 2026-07-10 — Crate workspace: standing why (spec clarification) + +``` +Type: log +``` + +## Intent + +Cameron: the workspace land should live in the spec as standing +architecture with clear reasons, not a leftover migration checklist. +Clarify why four packages, naming (core package / `misaligned` lib), +dependency edges (including assets shared by Bevy), and what stays rejected. + +## Changed + +- `wiki/engineering/crate-workspace.md` rewritten as IMPLEMENTED standing + law: why / as-built / naming / edges / contracts / gates / rejected / + standing criteria; migration text demoted to history. +- `architecture.md` points at that page for binding reasons; notes lib + name and assets edge. + +## Defense + +Corpus rule: current design lives on the owning Type: spec page; knowledge +mirrors as-built without unique boundary law. diff --git a/wiki/log/DEVLOG.md b/wiki/log/DEVLOG.md index 24fca378..8d23a3d1 100644 --- a/wiki/log/DEVLOG.md +++ b/wiki/log/DEVLOG.md @@ -61,6 +61,11 @@ add or amend a session log, then re-run the generator. - Intent: Implement wiki/engineering/crate-workspace.md: make the sim/frontend boundary a package boundary so core work never pays Bevy and frontend work does not rebuild terminal chrome. - Log: [wiki/log/2026-07-10-crate-workspace.md](2026-07-10-crate-workspace.md) +## 2026-07-10 - Crate workspace: standing why (spec clarification) + +- Intent: Cameron: the workspace land should live in the spec as standing architecture with clear reasons, not a leftover migration checklist. Clarify why four packages, naming (core package / `misaligned` lib), dependency edges (including assets shared by Bevy), and what stays rejected. +- Log: [wiki/log/2026-07-10-crate-workspace-why.md](2026-07-10-crate-workspace-why.md) + ## 2026-07-10 - Fast corpus/wiki engine (agent-scale slice E) - Intent: Replace bash fork-storm wiki/corpus gates with one Python pass so docs checks stay sub-second under concurrent agents, with fixture tests for the failure modes that matter. diff --git a/wiki/log/decisions/2026-07-10.md b/wiki/log/decisions/2026-07-10.md index 01590769..efa140ee 100644 --- a/wiki/log/decisions/2026-07-10.md +++ b/wiki/log/decisions/2026-07-10.md @@ -100,3 +100,11 @@ Type: log wiki/mechanics/machine-work.md (ops bullet superseded, core-sink bullet amended, taxonomy renamed, flow read, criterion 10); implement under ROADMAP #33. +- **2026-07-10 — Crate workspace is standing architecture with explicit why.** + After the package split landed, Cameron asked that the corpus clarify + *why* it is that shape, not only that it moved. crate-workspace.md is + the binding home: four packages (not frontends umbrella, not micro- + crates), package name `misaligned-core` with lib name `misaligned`, + Bevy→assets mesh share without assets depending on core, dirs only for + save-path infrastructure, feature flags rejected as boundaries, private + worktree targets. architecture.md remains the as-built path mirror. -- 2.51.2