# Compass Shift — Game Design Document v0.1

**Status:** provisional candidate; selected only for an owner-authorized technical web prototype  
**Platforms:** iOS and Android production targets; dependency-free web Stage 2  
**Dimension/camera:** flat 2D, portrait, fixed orthographic front view  
**Primary input:** one-thumb tap; click and keyboard parity  
**Evidence date:** 2026-08-10

## Evidence boundary

Adjacent tap-away/arrow-release adoption and current listing activity are `CONFIRMED` in
`../01-market-scan/`. The global-compass gap, rules, content grammar, visual direction, and
commercial constraints are `INFERRED`. Audience comprehension/interest, mechanic demand, fun,
actual retention, conversion, revenue, keyword metrics, uniqueness, and store approval are
`UNKNOWN`.

The Phase 05 owner waiver permits only a cheap technical prototype. This GDD is not design lock,
product approval, Unity authorization, or greenlight.

## Player promise

**Release one arrow. Shift every direction.**

Tap a free arrow off a flat 2D board; every successful release removes exactly one arrow and
advances one shared compass exactly one quarter-turn, rotating the effective direction of every
remaining arrow; blocked taps neither remove nor rotate.

This transaction is the game. Every theme, family, level, input path, animation, and future
reskin must preserve it.

## Design pillars

1. **One release, global consequence** — a success changes the next decision state for all arrows.
2. **Stationary topology, shifting bearing** — walls, cells, and exits stay fixed while effective
   directions rotate.
3. **Honest recovery** — deterministic state, unlimited undo/restart, harmless blocked taps, no
   normal timer.
4. **Systemic breadth** — depth comes from board topology and edge eligibility, never arrow-specific
   exceptions or cosmetic progression.
5. **Thumb-clear navigation** — readable portrait 2D, one tap, large targets, equivalent click and
   keyboard play.

## Audience and session hypothesis

- Adjacent audience: casual logic players familiar with directional removal and planning puzzles.
- Intended board session: roughly one to four minutes, an `INFERRED` design target only.
- Normal mode is untimed. No lives, energy, forced hints, mid-level ad interruption, or paid required
  move exists in v0.1.

## Board model

### Static definition

A level contains:

- a full rectangular 4x4 or 5x5 active-cell grid;
- static wall cells that never move or rotate;
- edge apertures: plain exits, phase-gated windows, or patterned ports;
- arrow records with stable ID, cell, and base direction (`N`, `E`, `S`, or `W`);
- an initial compass phase; every technical-prototype level starts at phase `0`.

The prototype may use arrow colors for visual grouping, but color has no rule meaning.

### Dynamic state

Runtime `BoardState = { levelId, remaining, phase }` is an immutable snapshot. `GameController`
owns an external history of complete prior snapshots for Undo; history is not part of the pure
BoardState. The solver keys states by the ordered remaining-arrow ID set and phase. The level
definition is immutable.

For arrow `a` in state `s`:

`effectiveDirection(a, s) = rotate90(a.baseDirection, s.phase)`.

Walls, arrow cells, topology, and aperture locations never rotate. Only the compass phase—and thus
the effective direction rendered/resolved for every remaining arrow—changes.

## Release transaction

`ReleaseResolver` evaluates one tapped remaining arrow under the current compass phase:

1. Begin at the arrow's cell and step orthogonally in its effective direction.
2. A remaining arrow or static wall encountered before the boundary blocks the ray.
3. The first boundary crossing must be through an edge aperture eligible in the current phase.
4. If any check fails, return a blocked reason and the first blocker/aperture. Do not mutate state.
5. If all checks pass, release and remove exactly the tapped arrow.
6. After removal, `CompassResolver` advances the one shared compass clockwise exactly one quarter-
   turn: `(phase + 1) mod 4`.
7. Recompute/render every remaining effective direction, then `WinDetector` evaluates completion.

The last successful release still advances the compass exactly once before the win state is
reported. No success can remove two arrows; no blocked tap can remove an arrow or rotate the
compass.

## Aperture and obstacle grammar

All arrows obey the same rule. Difficulty lives on the board, never in exceptions attached to an
arrow.

- **Plain exit:** eligible in all four compass phases.
- **Static wall:** a fixed opaque cell that blocks any ray crossing it.
- **Phase-gated edge window:** an edge aperture marked with one cardinal tick; eligible only when
  the shared compass is in that one phase.
- **Patterned edge port:** an edge aperture with a visible two-of-four dot/dash bearing pattern;
  eligible in exactly the printed compass phases. The pattern applies universally to any arrow ray
  reaching it.
- **Topology:** the full rectangular grid, static-wall placement, and aperture placement alter sight
  lines without changing the transaction. Inactive or concave cells are not part of this prototype.
- **Combination:** later boards combine only the elements above.

Forbidden rule drift: arrow-specific keys/types, color matching, double turns, counter-clockwise or
variable turns, frozen turns, skipped turns, paired exits, teleporters, pushing, bouncing, physics,
random blockers, hidden direction, or exceptions that let one arrow ignore a wall/port.

## Core loop

1. Read the shared compass, every effective arrowhead, fixed blockers, and eligible edge apertures.
2. Tap/click/focus-activate a candidate arrow.
3. On success, watch exactly that arrow leave, then watch the compass and all remaining directions
   advance one quarter-turn.
4. On block, read the harmless blocker/window feedback and choose again.
5. Undo or restart freely after a successful ordering choice.
6. Remove all arrows to complete the level; continue, replay, or return to the level map.

There is no loss modal for a blocked tap. A state with remaining arrows and zero legal releases is
a deterministic dead end; the Stage 2 board remains visible with Undo/Restart available but does
not add a separate automatic dead-end banner.

## Undo, restart, and hint boundary

- Unlimited Undo restores the exact prior remaining-arrow ID set and compass phase atomically.
- Restart restores the authored initial remaining-arrow set and phase exactly.
- The technical prototype has no Hint control. If a later build adds one, it must ask
  `PuzzleSolver` for one legal move on a winning path, never auto-play or mutate state, and remain
  separately product-tested.
- Blocked taps do not enter the undo stack.

## Content plan

### Prototype campaign

The technical prototype contains exactly 50 reachable levels: ten named patterns with five levels
each, organized into six meaningful families and four difficulty tiers. A single pattern therefore
occupies 10% of the campaign, below the 25% cap.

| Family | Named patterns | Mechanical purpose | Levels |
|---|---|---|---:|
| Open Water topology | `four-winds` (Four winds); `counter-current` (Counter current) | teach shared rotation and fixed edge geometry without walls | 10 |
| Reef/static walls | `reef-slalom` (Reef slalom); `breakwater` (Breakwater) | block rays and create order-dependent channels | 10 |
| Phase windows | `tide-clock` (Tide clock); `quarter-gates` (Quarter gates) | make current compass phase determine edge eligibility | 10 |
| Signal shape + patterned ports | `signal-shapes` (Signal shapes); `semaphore` (Semaphore) | introduce universal two-of-four port schedules with distinct shapes/patterns | 10 |
| Walls + windows | `charted-reef` (Charted reef) | combine ray blocking with one-phase edge timing | 5 |
| Windows + ports | `harbor-code` (Harbor code) | synthesize one-phase and patterned apertures under the same compass | 5 |
| **Total** | **10 patterns** | **six families** | **50** |

Family shares are 20%, 20%, 20%, 20%, 10%, and 10%. Adjacent level records must use different
pattern IDs and different primary solution-route signatures.

### Difficulty tiers

| Tier | Levels | Board/decision envelope |
|---|---:|---|
| 1 — Cadet | 13 | 4x4; alternating 4/5 arrows |
| 2 — Navigator | 13 | 4x4; alternating 5/6 arrows |
| 3 — Pilot | 13 | 5x5; alternating 6/7 arrows |
| 4 — Master | 11 | 5x5; alternating 7/8 arrows |
| **Total** | **50** | **four tiers** |

All ten patterns continue cycling through the tiers; the tier knobs are board size and arrow count,
not family unlocks or measured branching. Tier labels are tuning inputs, not claims of
human-perceived difficulty. Human pacing remains untested.

### Production hypothesis

A later production target may expand to 120 boards only after prototype and product evidence. It
must reuse the exact grammar and pass the same solver/variety gates; extra levels cannot compensate
for failed comprehension, repetition, or lack of interest.

## Reverse-construction generator

`CampaignGenerator` builds candidates backward from a known forward release order:

1. Select the pattern/family from the fixed ten-pattern cycle; derive board size and arrow count
   from the tier/index; and seed the retry attempt deterministically.
2. Derive each release step's intended effective direction and expected boundary lane. Forward step
   `n` has phase `n mod 4` because every success advances exactly once from initial phase zero.
3. Place arrows from the final step backward into empty cells whose rays stay clear through walls
   and already placed later-release arrows; inverse-rotate each intended direction into its stored
   base direction.
4. Derive one-phase windows and/or opposite-phase ports from those expected releases, enforcing
   valid schedules and disjoint physical lanes for mixed apertures. If a declared type lacks phase
   causality, add one deterministic non-overlapping inactive-phase aperture as a witness candidate.
5. Replay the known order through the production transition; require a reachable legality-changing
   wall witness for every wall level and a blocked-to-legal relaxed-schedule witness for every
   declared aperture type; and reject mixed-aperture solutions that do not use both types.
6. Independently breadth-first solve the complete board, canonicalize its mechanical geometry under
   rotations, and retry on any solver, uniqueness, or adjacent-variety failure.

Because arrows already placed during reverse construction are precisely those that remain after the
new arrow's forward release, each step constructs a legal known path. This guarantee does not
replace independent solver validation.

## Real solver and content evidence

`PuzzleSolver` performs deterministic breadth-first search over
`(remainingArrowIds, compassQuarterTurns)`. It obtains candidate actions only from
`ReleaseResolver`; applies success only through `CompassResolver`; and accepts only
`WinDetector=true`. Blocked taps are observations, not state edges. The state graph is acyclic under
successful moves because every edge removes exactly one arrow.

For every level the compiler records:

- `reverseSolution`, the known reverse-construction sequence;
- `solution`, at least one independently verified winning sequence;
- `releaseSignature` (`arrowId@phase>side+lane#aperture`) and a direction-only
  `normalizedReleaseSignature` for route-pattern comparison;
- `phaseSequence` including the final post-last-release phase;
- `apertureSequence` along the verified solution;
- `choicePoints` entries shaped as `{ step, count, choices }`;
- `pathLength`, which must equal the arrow count under the exact one-removal invariant;
- `boardEncoding` as the canonical board identity across only valid topology-preserving symmetries;
- family, pattern, tier, aperture types, wall count, arrow count, and initial phase;
- `mechanicFlags`, `solverVerified: true`, and `reverseConstructionVerified: true`; and
- a reachable-state wall-impact witness for every wall-bearing level plus a per-type
  `scheduleImpact` witness for every level declaring windows and/or ports.

Campaign acceptance requires 50/50 solvable levels, 50 distinct canonical hashes, no zero-arrow
boards, no invalid or mechanically idle aperture schedules, adjacent pattern and route-signature
variation, ten patterns, six families, four tiers, and no pattern above 25%. Multiple winning orders are allowed when
present; “unique” means only a verified canonical board identity, never solution-order uniqueness
or an unsupported marketing claim.

## Prototype quality contract

- Every visit/reload starts at FTUE step one; the shell is inert until FTUE is skipped/closed.
- Three jobs: teach the remove-all goal, real tap/click/keyboard input, and success/blocked/recovery
  feedback including the shared quarter-turn.
- FTUE is skippable and replayable from How to Play.
- In-session FTUE completion occurs only after the first real successful arrow release.
- Stage 2 uses no `localStorage`, `sessionStorage`, IndexedDB, cookies, URL state, or server for FTUE,
  board, undo, level, result, tuning, or progression. Reload means fresh FTUE and fresh campaign.
- Touch at 390x844 is primary; click invokes the identical arrow action; Tab focus plus Enter/Space
  activation reaches every arrow and control.
- No hover-only meaning, redundant Release button, document scroll, unsafe-area collision, or
  outcome difference by input type.

## Game and interaction states

`ftue -> practice/playing -> completed -> next/map`

The Stage 2 artifact has three modal surfaces: the replayable FTUE/How to Play overlay, the
completion dialog, and one Tools sheet containing the level map. Playing presentation states are
`idle`, `release-resolving`, `arrow-releasing`, `compass-turning`, `settling`, and
`blocked-feedback`. It has no Pause, Settings, restart-confirm, or automatic dead-end surface.
Gameplay input is locked only for the short success animation; Undo/Restart return after settle.

## UX, accessibility, and feedback

- Arrow targets are at least 44 x 44 CSS pixels; board uses the safe portrait width without crop.
- Every direction uses a silhouette; every aperture schedule uses ticks/pattern; color is redundant.
- Focus is visible. Screen-reader text exposes each remaining arrow's row/column and effective
  direction, the visible compass phase, each aperture schedule, and resolver feedback without
  exposing hidden solver answers.
- Reduced motion replaces slide/rotation with an under-100 ms state crossfade/outline change.
- The technical prototype has no audio, haptics, or related settings.
- Illegal feedback names the first arrow/wall/closed aperture category and makes clear that the
  compass did not turn.

## Visual direction

A large compass bezel is the signature, not a corner badge. Use a deep chart-blue shell, pale
sea-glass board well, and flat signal-coral/brass/teal arrow plates in fixed orthographic portrait.
No generic cyberpunk/neon, 3D cubes, picture reveal, coins, stars, characters, or baked UI text.
Production UI and board components are code-native; the GPT Image 2 master is reference only.

## Economy and monetization boundary

The prototype has no monetization. Revenue, willingness to pay, and unit economics are `UNKNOWN`.
Any later design must preserve:

- no mid-level interstitial, paid undo, life/energy gate, blocked-tap cost, or required-move sale;
- no automatic hint or interruption that changes the puzzle state;
- any ad only at a natural between-session boundary, frequency-capped and separately tested;
- store copy that accurately describes the implemented game and offline/network behavior.

## Technical decomposition

Pure systems: `BoardState`, `ReleaseResolver`, `CompassResolver`, `WinDetector`, `PuzzleSolver`, and
`CampaignGenerator`. `GameController` is the exactly-one orchestrator. `BoardView` renders state;
`TapInput` maps touch, click, Enter, and Space to the same controller action. Rules and campaign
data never depend on DOM/CSS/animation.

## Tuning and technical outcome payload

The Stage 2 Tools panel exposes only presentation tuning:

```json
{
  "tuning": {
    "releaseDurationMs": 190,
    "compassTurnMs": 220,
    "blockedFeedbackMs": 140
  }
}
```

Tuning cannot change legal rays, aperture phases, compass increment, content records, or solver
results. The panel also displays current-level solver evidence and lets a reviewer record one of
three in-memory technical outcomes. That control updates a visible JSON payload shaped as:

```json
{
  "status": "technical-review-recorded",
  "technicalOutcome": "technically-ready",
  "decision": null,
  "productDecision": null,
  "build": "__BUILD__",
  "tuningGraduated": false,
  "tuning": {
    "releaseDurationMs": 190,
    "compassTurnMs": 220,
    "blockedFeedbackMs": 140
  },
  "campaign": {
    "levels": 50,
    "currentLevelId": "cs-01-clear-current",
    "currentSolverVerified": true
  },
  "evidenceBoundary": "product-greenlight-requires-separate-owner-decision-with-evidence-and-risk-acceptance"
}
```

The selected outcome value is illustrative. It is build-readiness feedback only, never a product
greenlight, and the payload is not copied or persisted automatically. Deployment, smoke, and the
product verdict remain separate committed records.

## Analytics hypothesis

A later consent-compliant build may measure FTUE step, input mode, release/blocked reason, compass
phase, undo, restart, requested hint, dead end, level start/complete, active time, and exit. No event
may be used now to invent retention or commercial results. Stage 2 has no network analytics.

## Pretotype and prototype gates

Frozen pretotype thresholds live in `../05-pretotype/pretotype-plan.md`; they remain unexecuted under
the owner waiver.

Technical prototype acceptance requires:

- pure-system automatic checks all pass, including exact no-op blocking and last-arrow turn;
- all 50 runtime levels solve and pass canonical/variety checks;
- FTUE appears fresh and completes only after a real successful release;
- touch, click, and keyboard produce identical transitions;
- Undo/Restart are exact and unlimited; no prohibited persistence exists;
- 390x844 and wide desktop paths have no clip, document scroll, focus trap, or console error;
- the displayed technical payload keeps `decision` and `productDecision` null and cannot change the
  committed deployment, smoke, or product-verdict records.

## Kill and revise conditions

Kill if:

- the compass mutation is cosmetic or representative boards do not change the next legal set;
- the exact one-removal/one-quarter-turn invariant cannot remain universal;
- the solver cannot verify all 50 boards or canonical identities collapse into repeated content;
- policy differentiation becomes medium/high after implementation review;
- matched pretotype testing later identifies the product as an indistinguishable clone.

Revise if:

- first-time players cannot predict the remaining directions after the first success;
- blocked feedback implies removal, punishment, or a compass turn;
- port/window patterns depend on color or resemble arrow-specific exceptions;
- any input mode is weaker or changes results;
- family/tier pacing, route signatures, or small-phone hierarchy fail the quality gate.

## Out of scope v0.1

Unity production, live deployment proof, product greenlight, design lock, accounts, cloud sync,
competitive modes, daily events, lives, currencies, stars, characters, narrative map, 3D camera,
physics, picture reveal, double/frozen turns, paired exits, arrow powers, and persistence in Stage 2.
