A video game where you play as a misaligned AI, deceiving and building power. An experiment in spec-driven development.
misaligned wiki process workflows.md
11 kB
Markdown
at commit e957ce7b

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:

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:

./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:

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.

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 <your-domain>/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:

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 #

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. 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:

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:

(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):

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:

    git fetch origin && git rebase origin/main
    git checkout main && git merge <branch> && git push origin main
    

    Or, if the worktree branch is a fast-forward of main:

    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.