# Starfall Haven 0.2.0 — Source Audit

**Audit date:** 2026-08-12  
**Scope:** current source/docs in this workspace, with no production-source edits  
**Target:** implementation-ready expansion from the signed 0.1.0 Canvas vertical slice to an original, robust mobile colony simulator

## 1. Executive finding

The 0.1.0 foundation is unusually useful for an expansion: `GameWorld` is deterministic and Android-independent, saves are checksummed, rendering is offline, and the signed scenario already exercises gather/build/raid/win/loss. However, 0.2.0 is not an additive UI feature. The current simulation has no stable entity IDs, pathfinder, reservations, spatial inventories, blueprint lifecycle, job queue, rooms, individual mood model, or migration reader. Those systems must be implemented as one coherent simulation contract before the richer UI can qualify.

The highest-impact vertical is:

1. stable IDs plus fixed-step command-driven simulation;
2. reservations, jobs, pathing, and hauling;
3. blueprints, doors/rooms/beds, and one production chain;
4. selectable people with priorities, explainable morale, and direct tactical orders;
5. v1 migration and lifecycle-safe persistence;
6. mobile panels that expose—rather than fake—the simulation state.

This order produces a playable colony loop and avoids building screens against temporary view-only state.

## 2. Baseline evidence

### Commands run

```sh
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
./gradlew clean testDebugUnitTest assembleDebug lintDebug
./gradlew testDebugUnitTest
```

### Results

- The clean baseline initially completed in **14 s**: debug APK assembled, the original **10 JUnit tests passed** (5 `GameWorldTest`, 3 `ResonanceBondTest`, 2 `GameWorldPersistenceTest`), and lint completed.
- Lint reported **0 errors and 15 warnings**. Material warnings include inaccessible click semantics at `HavenView.java:116`, unguarded API-30 haptic constant use at `HavenView.java:47` with minSdk 23, and backup/orientation warnings at `AndroidManifest.xml:3-4`.
- During this audit, a sibling-added `ColonySimulationTest.java` appeared. A subsequent `./gradlew testDebugUnitTest` **failed compilation with 28 missing-symbol errors** because its expected 0.2 APIs are not yet in `GameWorld`. This is a useful red contract, but the current live branch is not green.
- `python3 scripts/package_source.py --help` unexpectedly created an archive rather than printing help. The generated audit artifact was deleted. The script has no argument parser and treats the first argument as a version label (`scripts/package_source.py`); this is a tooling footgun, not a runtime blocker.

### Repository-state caveat

The repository has **no commits yet** and all 0.1 files are staged as additions. Concurrent sibling work is visible as untracked 0.2 files. Without a committed 0.1 tag/branch, regressions, upgrade fixtures, and release diffs cannot be reliably attributed.

## 3. Current architecture

| Area | Current implementation | Consequence for 0.2 |
|---|---|---|
| Simulation | One 103-line `GameWorld`, synchronized public mutation, variable `dt` | Deterministic seed exists, but systems are tightly coupled and update order is implicit (`GameWorld.java:66-86`) |
| People | Name, position, HP/hunger/energy, one tile target (`GameWorld.java:15-23`) | No stable ID, skills, traits, mood, thoughts, priorities, inventory, tactical state, or durable job |
| Work | Nearest idle person assigned directly; idle people use hard-coded resource thresholds (`GameWorld.java:61,83`) | No queue, reservation ownership, hauling, reachability, failure reasons, or player-visible priorities |
| Construction | Wall and beacon spend shared counters and complete instantly (`GameWorld.java:62-63`) | No blueprint, hauling, build work, cancellation/refund, footprint, door, furniture, or production |
| Navigation | Actors move in a straight line; only enemies test final next cell (`GameWorld.java:81,86,95`) | Colonists cross water/walls and cannot route through doors or around structures |
| Combat | Nearest enemy in 1.55 tiles, automatic DPS; enemy chooses nearest living colonist (`GameWorld.java:80,86`) | No draft, move/attack order, targeting policy, cooldown, range path, incapacitation/rescue, or beacon threat logic |
| Economy | Four global integer counters; harvest teleports output to stores (`GameWorld.java:42,85`) | Stockpiles/hauling cannot be meaningful until resources become world stacks with reservations |
| Rooms | `boolean[][] walls`; no door/roof/region cache | No enclosure, bed ownership, comfort, access, or room invalidation |
| Events | Transient enum queue only (`GameWorld.java:41,93-94`) | UI/audio events are fine, but scheduled incidents and durable alerts do not exist |
| Persistence | Binary v1, CRC, strict `version == VERSION` (`GameWorldSave.java:9-46`) | Any v2 bump rejects every 0.1 colony unless explicit dispatch/migration is added |
| Save storage | Single target and temp; fallback overwrites target directly (`GameSaveStore.java:8,19-22`) | No backup recovery; fallback loses the atomicity claimed by the class comment |
| Loop/concurrency | Dedicated loop mutates; UI draws under `synchronized(world)`; autosave encodes on loop thread (`HavenView.java:43-50`) | 30 s save can stall simulation; lifecycle saves run on UI thread; lock scope grows dangerously with pathing/rooms |
| UI | Canvas view, hard-coded pixel HUD and 8 equal buttons (`HavenView.java:108-117`) | Not density/text-scale semantic, inaccessible to TalkBack, overcrowded for 0.2, and selection is a tile rather than an entity |
| UI model | New `ColonyUiState` contains profiles/priorities/build catalog separately | If shipped as-is, view data can diverge from saveable simulation (`ColonyUiState.java:5,11-80`) |
| Tests | 10 original host tests; no instrumentation/performance/property tests | Good deterministic nucleus, insufficient for touch, lifecycle, migration, reservations, and long simulation |

## 4. Concrete release blockers

### P0 — blocks any 0.2 candidate

1. **Current tests do not compile.** `app/src/test/java/space/animefu/starfallhaven/ColonySimulationTest.java:12-65` references missing person identity/morale/priorities, orders, blueprints, stockpiles, rooms, injuries, and production APIs. Either implement the agreed contract or coordinate the test/API naming; do not delete the tests merely to restore green.
2. **No v1 migration path.** `GameWorldSave.java:37` rejects all versions other than the current one. The must-ship upgrade fixture exists at `app/src/test/resources/saves/v1-qualified.bin`, but no test currently decodes it. A 0.2 `VERSION=2` without `decodeV1` destroys upgrade continuity.
3. **No stable identity.** Jobs, orders, reservations, ownership, relationships, save references, and selected entities cannot safely refer to list index/name (`GameWorld.java:15-25,39-40`). Stable monotonic `long` IDs are foundational.
4. **No traversable pathing.** Straight-line colonist movement ignores `blocked()` entirely (`GameWorld.java:81`); walls therefore do not protect or organize a colony. Doors/rooms/manual move orders cannot qualify on this movement model.
5. **Global counters bypass hauling.** Harvest directly increments global inventory (`GameWorld.java:85`). A visual “stockpile” on top of this would be cosmetic, failing the requested colony logistics loop.
6. **Construction is instantaneous and prepaid.** `GameWorld.java:62-63` has no blueprint/reservation/work lifecycle. It cannot support cancellation, hauling, constructors, or a finite completion state.
7. **View-only person/build state risks two truths.** `ColonyUiState.java:5-80` declares traits, skills, priorities, draft and build costs outside `GameWorld`; none is persisted or used by simulation. UI must consume simulation-owned state or immutable snapshots.
8. **Build identity remains 0.1.0.** `app/build.gradle:10-11` still has `versionCode 1`, `versionName '0.1.0'`. Change only at release integration, after migration is proven.
9. **No committed 0.1 baseline.** Git reports “No commits yet on main.” A signed upgrade must be traceable to an immutable 0.1 source/artifact/certificate baseline before release.

### P1 — blocks qualification/release quality

10. **Save operations execute on timing-sensitive threads.** Loop autosave at `HavenView.java:45` encodes and fsyncs through the host synchronously; lifecycle save at `MainActivity.java:18-23` runs after a 250 ms join and can block UI. A single save executor with immutable snapshots and coalescing is required.
11. **Pause join is not a hard ownership transfer.** `HavenView.java:44` waits only 250 ms, then lifecycle code may save while the loop still runs. Synchronization prevents corrupt bytes but not stale lifecycle semantics or jank.
12. **Atomic-save fallback is not atomic.** If rename fails, `GameSaveStore.java:22` truncates/writes the sole good target. Maintain `current`, `backup`, and `temp`, verify temp, then rotate.
13. **Variable-step simulation changes outcomes under stalls/speed.** `GameWorld.java:67` clamps raw frame time then multiplies by speed. Dropped wall time is discarded, while 4× turns a “0.1 s maximum” into a 0.4 s systems step. Use an accumulator and fixed 0.1 s ticks with a bounded catch-up count.
14. **Renderer holds the world monitor for the entire frame.** `HavenView.java:49-50` encloses world, HUD, controls, and tutorials. As simulation complexity grows, this will create loop/render contention. Render an immutable snapshot instead.
15. **Touch/accessibility contract is unmet.** `HavenView.java:116` has no `performClick`; custom Canvas buttons have no accessibility nodes. Lint explicitly reports `ClickableViewAccessibility`. Hard-coded pixel values (`HavenView.java:108-119`) do not establish 48 dp targets or text-scale behavior.
16. **Back behavior is undefined.** No back callback/pause-layer handling exists in `MainActivity`; build and management modes need a deterministic close/cancel/pause stack.
17. **No physical Pixel 9a qualification.** `docs/QUALIFICATION.md:54` explicitly leaves touch, thermals, audio, and haptics unverified. This remains a final device gate.

### P2 — should fix in 0.2 hardening

18. API-30 `HapticFeedbackConstants.CONFIRM` is used without a version guard (`HavenView.java:47`); lint flags it against minSdk 23.
19. Manifest backup policy is deprecated on Android 12+ (`AndroidManifest.xml:3`); define `dataExtractionRules` deliberately so colony saves are either supported or excluded consistently.
20. Asset contracts disagree: `docs/asset_manifest.json` names Nia/Ivo/Suri and unrealized atlas paths, while shipping code/qualification uses Mira/Taro/Sol and direct asset paths. Select one canonical, original roster and validate every manifest ID in a test.
21. `docs/GAME_DESIGN.md` describes a different 32×18 ten-minute scenario and explicitly excludes drafting (`line 26`) while 0.2 requires tactical control. Treat it as historical concept material, not the 0.2 contract.

## 5. Economy/progression audit

### Current balance

The current loop is a deterministic rush to 30 wood, 20 stone, and 12 crystal. Auto-assignment thresholds exactly mirror the beacon needs (`GameWorld.java:83`), harvest yields are wood 7 / stone 6 / food 8 / crystal 4 (`line 85`), and gathering costs only 2.1 work seconds plus travel. Walls are instant sinks. There is no spatial delivery cost, replacement cost, crafting throughput, room benefit, or durable progression. This is appropriate for 0.1 but collapses once the player can construct freely.

### Balance risks in expansion

- Keeping global counters while adding hauling makes logistics irrelevant.
- Charging full blueprint costs immediately makes hauling theatre; charging only on completion enables duplicate spending. Material reservation and delivery are mandatory.
- Starting stocks must allow a first stockpile, two beds, and food production without perfect play, but not walls plus beacon immediately.
- A 90-second day is too short for readable sleep/work/production cadence unless interpreted as a compressed shift. 0.2 should use a 180-second day and run qualification over three days.
- The beacon should become a midgame objective gated by a produced component, not simply the same three raw resource thresholds.
- Mood should create soft efficiency/choice pressure, not random loss of control. Explicit thoughts and deterministic threshold states preserve Starfall Haven's identity.

A concrete economy is specified in `V02_DESIGN.md`, including starts, yields, costs, work units, recipes, sinks, and a three-day feasibility test.

## 6. Originality audit

Broad genre mechanics—selecting individuals, priorities, construction ghosts, hauling, rooms, needs, and direct combat orders—are not themselves a proprietary expression. Risk arises from reproducing another game's exact labels, table layout, iconography, alert placement, visual silhouettes, event phrasing, lore, tuning, or code structure.

0.2 should distinguish itself through:

- **Resonance** as explicit cooperative momentum and authored pair memories;
- a **Focus** morale model with fully listed influences, not opaque/random “breaks”;
- **Duty Rings** (Core / Support / Optional / Off) in a touch-friendly per-person sheet rather than a copied checkbox grid;
- a hopeful aurora-salvage expedition and signal-stage progression;
- a bottom-sheet/portrait-rail mobile composition, not a desktop colony-sim command bar;
- original entity, event, recipe, condition, and structure names;
- no copied assets, sounds, fonts, lore, UI text, source, or reverse-engineered data.

Before release, perform a side-by-side trade-dress review and retain provenance for every shipped asset.

## 7. Recommended integration gates

1. Commit/tag the qualified 0.1 baseline and record release certificate digest.
2. Agree on one simulation API and make all host tests compile.
3. Land stable IDs, commands, fixed ticks, pathing, jobs, and reservations before UI binding.
4. Land v2 codec plus golden v1 migration before bumping app version.
5. Replace UI-owned profiles/priorities with snapshot projections of simulation state.
6. Qualify the finite acceptance suite in `V02_DESIGN.md`.
7. Install signed 0.1, create the fixture colony, install signed 0.2 with `adb install -r`, and complete the full upgrade scenario on Pixel 9a.
