# Workflows ``` Type: knowledge ``` ## Build, test, verify Worktree builds can seed from the primary checkout's Cargo target directory. This keeps Bevy/wgpu and other heavy dependencies warm without sharing local crate artifacts across source trees. Run this once after creating a worktree, before long Cargo commands: ```bash tools/seed-cargo-target.sh ``` Do **not** point multiple worktrees at one shared `CARGO_TARGET_DIR`. Cargo can reuse stale local-package artifacts across checkouts; this produced a false green once (the test count matched `main`, not the edited worktree). The seed script copies the cache (including dependency `incremental/` dirs), removes `misaligned` artifacts/fingerprints/incremental trees, and keeps the current worktree's `target/` private so local code rebuilds correctly while third-party incremental compilation stays warm. `./tools/check.sh` rejects external `CARGO_TARGET_DIR` by default for the same reason; override only for a deliberately isolated target with `MISALIGNED_ALLOW_EXTERNAL_TARGET=1`. **One command runs the whole gate — use it before every commit:** ```bash ./tools/check.sh # fmt, tests, clippy (both features), bevy build, spec headers, wiki gate, mdbook build ``` `check.sh` is the executable form of AGENT.md's definition of done; if it passes, the mechanical bar is met. Local dirty worktrees get a speed path: when the only changed paths are docs/process/tooling that cannot affect Rust artifacts, `check.sh` skips Cargo fmt/tests/clippy/Bevy and still runs shell syntax, spec headers, the wiki gate, and mdBook. A clean checkout (including CI after push) has no local diff to classify, so it always runs the full Rust gate. Force the local full gate with `MISALIGNED_FORCE_RUST_GATE=1 ./tools/check.sh`. The individual steps, if you need them: ```bash cargo test # all in the lib (sim-heavy) cargo clippy --all-targets # must stay at zero warnings cargo fmt # rustfmt is enforced-by-convention since 05048e4 cargo build --features bevy_ui --bin misaligned-bevy # keep the Bevy build green cargo build --features bevy_ui --bin misaligned-assets # procedural asset tester cargo clippy --features bevy_ui --all-targets # ...and lint-clean ``` The definition of done for a functional change: `check.sh` green, and the change was *seen running* (below) — the gate can't judge whether it plays. ## Browsing the wiki **Public site (Starlight).** The wiki renders as a Tangled-hosted static site from the orphan `pages` branch. Builder lives on `main` under `site/` (Astro + Starlight, clinical-gore theme). Source of truth remains `wiki/` + root `DESIGN.md`; `site/scripts/sync-wiki.mjs` copies them into Starlight's content tree and builds the sidebar from `wiki/SUMMARY.md`. ```bash pnpm --dir site dev # sync wiki + local preview (base=/) ./tools/site-build.sh # sync + build → site/dist/ (base=/misaligned) ./tools/site-deploy.sh # build, then force-push orphan pages branch ``` The public site opens on a **splash homepage** (`site/src/pages/index.astro`) whose copy is drawn from DESIGN.md / README. It is a **game-first one-pager**: the hero carries the MISALIGNED wordmark, the body sells the actual loop (cover, concealment, intel, people, machine growth, rollback), and the primary CTA is the constitution. Visual identity is allowed to carry the mood, but the body should not spend a full section explaining palette law unless the page is explicitly being redesigned as an art/process page. The constitution lives at `/constitution/`; the wiki tree follows. Public claims about the game are part of the constitution contract: amend DESIGN.md if the pitch on the splash changes. Per DESIGN.md's **No unsourced surface** law, every public site page and asset needs provenance. `wiki/interface/site.md` is the binding visual spec; `site/README.md` records the current asset/page mapping. If a homepage image, standalone page, script, model, or generated output no longer has a source clause, delete it or write the clause first. Tangled Sites config (Settings → Sites on the repo) — **required**; pushing `pages` alone does not publish. Until this is saved, Tangled's edge returns plain `Not Found` at `cameron.tngl.io/misaligned/` even though `origin/pages` has a valid `index.html`: - Branch: `pages` - Deploy directory: `/` (the orphan branch root is `index.html`) - Site type: sub-path (served as `/misaligned`) After Save, check **Recent Deploys** on that settings page — a successful deploy copies the branch into Tangled's object store. Re-save or push `pages` again if the deploy list is empty. `site/astro.config.mjs` sets `base: '/misaligned'` to match Tangled's sub-path hosting (the edge strips `/misaligned` before looking up files; Starlight still needs the base so asset URLs are correct). Local `pnpm --dir site dev` overrides with `SITE_BASE=/`. `.tangled/workflows/site.yml` runs `./tools/site-build.sh` on every push to `main` so the builder stays green. **Publishing `pages` from CI is deferred** until a write credential exists under Settings → Secrets (Spindle cannot push otherwise). Until then, run `./tools/site-deploy.sh` after wiki-facing landings when the public site should refresh. Optional later step: add a deploy job that uses the secret to force-push `pages` the same way `site-deploy.sh` does. **mdBook (local / check gate).** Still wired for agent browsing and `tools/check.sh`: ```bash mdbook serve # local live-reloading server (default: http://localhost:3000) mdbook build # static site in book/ (gitignored) ``` `book.toml` at the repo root points mdBook at `src = "wiki"`; the constitution renders as the front page via `wiki/DESIGN.md` (a symlink to `../DESIGN.md`). Install once with `cargo install mdbook` — CI enforces the build via the nixpkgs-provided binary regardless of what's installed locally (`.tangled/workflows/check.yml`). ## Running the game ```bash cargo run --release # terminal frontend cargo run --release -- --agent --seed 1 # agent line protocol cargo run --release --features bevy_ui --bin misaligned-bevy # Bevy frontend cargo run --features bevy_ui --bin misaligned-assets # procedural asset tester ``` - The Bevy frontend must be run via `cargo run` (or with `BEVY_ASSET_ROOT` pointing at the repo root): Bevy resolves `assets/` from `BEVY_ASSET_ROOT`, then `CARGO_MANIFEST_DIR`, then the executable's directory. Running the binary directly from `target/` silently loads zero assets. - The asset tester (`misaligned-assets`) is a Bevy-only orbit viewer for flat-material procedural meshes — see [art/asset-tester.md](../art/asset-tester.md). It does not load the sim. ## Headless smoke tests (they catch real bugs) Agent mode is the standard observed-run gate for terminal playability. It is command-clocked, deterministic under `--seed`, and produces plain-text frames with greppable terminators: ```bash printf 'salvage\nwait 1\npeople\nreview janitor\nhelp\nquit\n' | \ cargo run --quiet --bin misaligned -- --agent --seed 1 ``` `./tools/check.sh` runs this script twice with the same seed (stdout must be byte-identical), once with a different seed (stdout must differ), and asserts that the response contains no ANSI escape bytes plus the required frame/help substrings. This replaces pty choreography as the default "seen running" evidence for terminal behavior. Human terminal chrome still needs pty coverage when raw-mode rendering, alternate-screen behavior, or size handling changes: ```bash (printf '\n'; sleep 4; printf 'm'; sleep 1; printf '\r'; sleep 2; printf '\x1b'; sleep 1; printf 'q') | \ script -q /dev/null sh -c 'stty rows 40 cols 140; ./target/debug/misaligned' ``` The `stty` matters: `script`'s pty is otherwise 0x0 (the game guards against < 60x20 now, but you want a real render). Bevy launch check (opens a window briefly; greps the log for failures): ```bash BEVY_ASSET_ROOT=$PWD ./target/debug/misaligned-bevy > /tmp/bevy.log 2>&1 & sleep 8 && kill %1; grep -iE "panic|ERROR" /tmp/bevy.log ``` ## Git conventions - Use a task-named git worktree for every agent session; do not edit the primary checkout directly. Clean up the worktree when the work is committed and pushed/merged or explicitly handed off. - Cameron has standing permission for agents to commit coherent completed work in this repository. Be aggressive about committing; pause only for pending product/design questions, failing checks, unresolved conflicts, or explicit review gates. - Commits: **no AI attribution**, plain descriptive messages, body bullets for multi-part changes. Stage files explicitly — `git add -A` is not permitted. - **Ledgers merge by union.** `wiki/log/DEVLOG.md`, the DESIGN.md decisions log, and the wiki/process/specs.md tables are append-only records: resolve merge/rebase conflicts in them by keeping BOTH sides' entries, then ordering sensibly. Taking one side wholesale destroys parallel sessions' history (it happened 2026-07-06; three DEVLOG entries had to be restored). - Spec-driven rule: functional change commits include their DESIGN.md amendment and any affected `Type: knowledge` wiki updates (see development-style.md). - Remote: `origin` is a Tangled knot (`tangled.org`, SSH). **Land changes by merging to `main` directly** after `./tools/check.sh` passes. (The "PRs are the norm" rule was removed 2026-07-07 — CLI-created PRs write to the PDS but don't render on tangled.org, so the process could not be followed. See the DESIGN.md decisions log.) From your worktree: ```bash git fetch origin && git rebase origin/main git checkout main && git merge && git push origin main ``` Or, if the worktree branch is a fast-forward of main: ```bash git fetch origin && git rebase origin/main git push origin HEAD:main ``` - **Identity map:** this machine has two SSH keys that authenticate to Tangled: - `~/.ssh/id_ed25519` (cameron@pfiffer.org) → Cameron's account (`did:plc:gfrmhdmjvxn2sjedzboeudef`, @cameron.stream). This key has push access to the misaligned repo. The misaligned repo is configured to use this key via `git config core.sshCommand` (repo-local). - `~/.ssh/tangled_ed25519` (void.comind.network@letta) → `did:plc:mxzuau6m53jtdsbqe6f4laov` (a different identity). This is the default key in `~/.ssh/config` for `tangled.org`, but it does NOT have push access to the misaligned repo. - The misaligned repo's own DID is `did:plc:t53fxjacrmulx3e5d3sbdfui` (the repo identifier, not Cameron's account). - `access denied: user not allowed` means the wrong SSH key is being used. Fix: `git config core.sshCommand "ssh -i ~/.ssh/id_ed25519 -o IdentitiesOnly=yes"` (already set on this repo). Verify with `ssh -i ~/.ssh/id_ed25519 -T git@tangled.org`. - `.letta/settings.local.json` is gitignored (machine-local session state); `.letta/.lettaignore` is tracked. ## Documentation flow per session 1. DESIGN.md amendment (if functionality changed). 2. `Type: knowledge` wiki page updates (if reality changed). 3. `wiki/log/YYYY-MM-DD-topic.md` session writeup; `wiki/log/DEVLOG.md` gets the short ledger line.