← Priority list
Unclaimed

Land the AForce2 in-game dialogs PR (three dialog styles from the design mocks) through CI and the merge queue

Get kotlin.build (remote) green on https://github.com/CodexCoder21Organization/AForce2/pull/25 (head fe04816, branch in-game-dialogs) and land it through the squash merge queue; it was not yet enqueued and nothing is watching it. The code is complete, passed 5 clean adversarial review rounds and 207/207 local tests against the published aforce2-fat:0.0.25; CI was in progress at handoff. The design-mock images already merged in https://github.com/CodexCoder21Organization/AForce2/pull/24. No deploy requested.

Handoff document

Markdown

Land AForce2 in-game dialogs PR (three dialog styles from the design mocks)

Written 2026-10-14 20:20 UTC. RE-VERIFY: all state below is a write-time snapshot. Re-check with gh pr view 25 --repo CodexCoder21Organization/AForce2 --json state,mergeStateStatus,statusCheckRollup,mergedAt,headRefOid and gh api repos/CodexCoder21Organization/AForce2/commits/<head>/check-runs.

Mission summary

The user posted three dialog UI mock-ups and asked: "Add these three images to the https://github.com/CodexCoder21Organization/AForce2 repository in a folder for design mocks or something. Commit/merge those changes. While we're waiting for that to merge, in parallel, we can start implementing the dialogs. Each screenshot demonstrates a different dialog UI design. We want to implement all three different dialog UI designs, fully implement them, so we can optionally use them in the games."

  • Mock images: DONE, merged in https://github.com/CodexCoder21Organization/AForce2/pull/24 (docs/design-mocks/dialogs/).
  • Dialog implementation: code complete, reviewed CLEAN (5 adversarial review rounds), awaiting CI + merge queue in https://github.com/CodexCoder21Organization/AForce2/pull/25.

Remaining work: get kotlin.build (remote) green on the PR head and land the PR through the (squash) merge queue. No production deploy was requested.

State at write time

  • PR https://github.com/CodexCoder21Organization/AForce2/pull/25: OPEN, head fe04816022139691daa83c82cfbfea914cfdc591 on branch in-game-dialogs, rebased onto main after https://github.com/CodexCoder21Organization/AForce2/pull/22 merged. mergeStateStatus BLOCKED (only because required CI was still running).
  • Checks on fe04816: kotlin.build (remote) (required) in_progress — https://buildtest.kotlin.build/run?id=9af81487 ; kotlin.build (kompile-remote-build) (informational) in_progress.
  • Not enqueued yet. A build-watchman --to-merged watcher was running and was deliberately stopped at handoff time (session ending); nothing is watching the PR now.
  • Local verification: full suite 207/207 passed at fe04816 against the exact jar later published as aforce2-fat:0.0.25 (hash verified).

What was built (on in-game-dialogs)

  • src/com/aforce2/dialogs/GameDialog.kt — foundation: DialogActionKind {PRIMARY, SECONDARY, DANGER}, DialogAction, abstract GameDialog (object API, Show() composable, keyboard: arrows/Tab move selection, Enter/NumPadEnter/Space press, Escape dismiss, acting on key-up with held-key protection via a process-wide HeldKeyRecord; hover-after-real-movement + click), GameDialogs singleton (show, dismiss, shown, isShowing, keyDown/keyUp/isKeyHeld/releaseAllKeys), GameDialogLayer with a 60% black scrim.
  • Three styles from the mocks: SystemNoticeDialog.kt (min window 660x420), ConnectionAlertDialog.kt (signal bars, min 480x400), SecureAuthenticationDialog.kt (blinking cursor, min 400x300), plus PlainDialog.kt. Max 3 actions each. Animation is driven by the Compose frame clock (deterministic goldens).
  • OffscreenDialogScene.kt + OffscreenRenderer.renderDialog(...) for headless tests (uses an internal Compose KeyEvent factory with an OptIn, documented).
  • Wiring: src/Display.kt and multiplayer/client/MultiplayerDisplay.kt record key press/release into GameDialogs, release all keys on window focus loss, and wrap screens in GameDialogLayer; UserIO and multiplayer keyboard controls are gated while a dialog shows; AForce2.cleanup() dismisses any dialog.
  • Fonts (OFL, with licence files + NOTICE.txt): VT323, Share Tech Mono, UnifrakturCook Bold.
  • 50+ dialog tests in tests/ (goldens screenshot*Dialog*, fit, scroll, label-wrap, keyboard, mouse, held-key, focus-loss, stray key-up, multiplayer gating). README has a Dialogs section; docs/headless-mode.md updated.

Published artifacts (not on main yet)

  • aforce2:aforce2-fat:0.0.25 published to https://kotlin.directory from fe04816 (the PR head). All tests/*.kts on the branch pin it. Becomes consistent with main once the PR merges.
  • aforce2:aforce2-fat:0.0.24 was also published from the branch before the rebase onto 0.0.19–0.0.23; it lacks those changes and is superseded — do not pin it (noted in build.kts changelog).
  • Nothing deployed anywhere.

Relevant PRs / refs

Repo Branch Remote head SHA PR What is on it State
CodexCoder21Organization/AForce2 in-game-dialogs fe04816022139691daa83c82cfbfea914cfdc591 https://github.com/CodexCoder21Organization/AForce2/pull/25 complete dialogs feature builds, 207/207 local; CI running; the one to land
CodexCoder21Organization/AForce2 design-mocks/dialogs ed44b1bd7409f8db6138e75194fbcd709fd198da https://github.com/CodexCoder21Organization/AForce2/pull/24 mock images merged; safe to delete
CodexCoder21Organization/AForce2 dialogs/foundation, dialogs/styles, dialogs/fit, dialogs/round2, dialogs/round3, dialogs/system-notice, dialogs/connection-alert, dialogs/secure-auth (fa16e18, 0d176d6, 76b9a49, 1d5de6e, ea1bbab, 8d1e034, 5a8e1d6, e7d319d) no PR intermediate iteration branches all superseded by in-game-dialogs; safe to delete

All local checkouts were swept (no uncommitted work, stashes, or unpushed commits) and then deleted.

Next steps

  1. Re-verify the PR state and the head's checks (commands above).
  2. Watch and land it: ~/bin/coursier launch buildwatchman:build-watchman:0.0.21 -r https://kotlin.directory -- --repo CodexCoder21Organization/AForce2 --pr 25 --to-merged as a tracked background task; branch on exit code (0 merged, 1 red, 4 evicted, 5 idle-timeout).
  3. If kotlin.build (remote) goes red: read the buildtest run log, reproduce the failing test locally by file path, fix the cause (never bypass, never weaken). If main moved, rebase; if source changed, publish a new aforce2-fat version (next free number — check kotlin.directory, other branches have claimed numbers before) and bump every tests/*.kts pin and build.kts coordinates.
  4. After merge, optionally delete the superseded dialogs/* and design-mocks/dialogs branches.

Reusable knowledge

  • Build: scripts/build.bash; tests: scripts/test.bash --local --test tests/<file>.kts. Select tests by file path — selecting by name compiles every test and OOMs the box. Serialize heavy builds/tests on one machine.
  • Tests depend on a published fat jar (@file:WithArtifact("aforce2:aforce2-fat:<ver>")). For local iteration, install a locally built fat jar under ~/.cache/coursier/v1/bldbinary/repository/aforce2/aforce2-fat/<ver>-local-x/ and delete it afterwards (stale bldbinary entries mask changes).
  • Test .kts scripts are not compiled with the Compose plugin: no @Composable code in tests — hence the object-based GameDialog API and OffscreenDialogScene.
  • Golden images: a missing golden is recorded and the test fails once; commit the recorded file.
  • Publishing: ~/bin/coursier launch community.kotlin.maven.artifact.publishing:community-kotlin-maven-artifact-publishing:0.0.6 -r https://kotlin.directory -- --artifact-dir <dir> --api-url https://api.kotlin.directory/upload --force (POM copied from a previous version with the version swapped).
  • gh pr edit fails on this repo (Projects classic GraphQL error); edit PR bodies with gh api -X PATCH repos/CodexCoder21Organization/AForce2/pulls/25 -F body=@file.
  • git push --force-with-lease=<branch>:<sha> needs the full SHA.
  • Known accepted gaps (stated in the PR): the window focus-loss listener cannot be tested headlessly; a key still physically held when focus returns acts as a fresh press (documented in KDoc). System Notice and Connection Alert need minimum window sizes larger than the current game windows (constants *_MIN_WINDOW_*).

No status reports yet.

Add dependency

Complete this handoff

Moves it out of every priority list and into ArchiveArea.