Files
kst4contest/docs/superpowers/plans/2026-11-04-live-beacon-control.md
T
Praktimarc d925c83412 Apply live beacon settings and improve station map (#164)
Apply beacon checkbox changes at runtime and keep the aggregate status chip synchronized.

Improve explicit station-map navigation, spatial filter overlays, overlay legend, selected-path contrast, and the documented map screenshot.
2026-11-05 00:52:17 +01:00

6.8 KiB

Live Beacon Control Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Make both beacon enable switches effective immediately at runtime and make the aggregate beacon status chip an accurate shared toggle.

Architecture: Keep ChatPreferences as the profile-scoped source of truth, but expose the two activation flags as thread-safe observable values. Route settings and chip actions through ChatController, publish one aggregate MyBeacon status, and give only that thread-status chip an optional click action.

Tech Stack: Java 21, Kotlin 2.2, Compose Multiplatform, JUnit 5, Mockito, Gradle wrapper

Spec: docs/superpowers/specs/2026-11-04-live-beacon-control-design.md

Global Constraints

  • Work directly on main, as explicitly authorized.
  • Do not stage, commit, push, merge, tag, release or deploy.
  • Keep beacon templates, interval handling, TX framing and second-chat eligibility unchanged.
  • Write source-code and configuration comments in English.
  • Use focused tests first and finish with ./gradlew.bat build --console=plain.

Review Focus

  • A disabled second chat must leave its dormant second-beacon flag unchanged when the chip is clicked.
  • An external chip toggle must update an already open Beacon settings tab without reopening it.
  • A runtime toggle must not restart the timer or enqueue an immediate message.
  • An invalid beacon template must still be reported as a critical status rather than hidden by the aggregate state.
  • Profile reload must replace the observable values without carrying the previous profile's runtime flags across.

Task 1: Observable profile-scoped beacon activation

Files:

  • Modify: core/src/main/java/kst4contest/model/ChatPreferences.java
  • Test: core/src/test/java/kst4contest/model/ChatPreferencesBeaconStateTest.java

Interfaces:

  • Produces: existing boolean getters/setters plus observable main/second beacon value accessors

  • Consumes: existing MutableValue / SimpleValue infrastructure

  • Write tests that changes are observable, values remain independent, XML reload restores both values, and an unsaved in-memory change does not survive a fresh load.

  • Run ./gradlew.bat :core:test --tests kst4contest.model.ChatPreferencesBeaconStateTest --console=plain and verify the new observable-accessor tests fail because the API is absent.

  • Back the two flags with SimpleValue<Boolean> while preserving the existing getters, setters and XML element names.

  • Re-run the focused test and the existing ChatPreferences tests.

Task 2: Immediate settings effect and aggregate controller semantics

Files:

  • Modify: core/src/main/java/kst4contest/controller/ChatController.java
  • Modify: core/src/main/java/kst4contest/controller/BeaconTask.java
  • Create: core/src/main/java/kst4contest/controller/BeaconStatus.java
  • Test: core/src/test/java/kst4contest/controller/BeaconControlTest.java
  • Test: core/src/test/java/kst4contest/controller/BeaconTaskTest.java
  • Modify: app-desktop/src/main/kotlin/kst4contest/view/compose/tabs/BeaconTabState.kt
  • Modify: app-desktop/src/main/kotlin/kst4contest/view/compose/tabs/BeaconTab.kt
  • Modify: app-desktop/src/main/kotlin/kst4contest/view/compose/ObservedValue.kt
  • Modify: app-desktop/src/main/kotlin/kst4contest/view/compose/SettingsTabs.kt
  • Modify: app-desktop/src/test/kotlin/kst4contest/view/compose/tabs/BeaconTabStateTest.kt
  • Modify: app-desktop/src/test/kotlin/kst4contest/view/compose/tabs/SettingsApplyScreenTest.kt
  • Modify: app-desktop/src/test/kotlin/kst4contest/view/compose/tabs/DraftedSettingsTableTest.kt

Interfaces:

  • Consumes: observable preference values from Task 1

  • Produces: controller setters, usable-beacon toggle, aggregate status publication, Compose observation bridge

  • Write failing controller tests for off, 1/2, on, main-only toggling when second chat is disabled, and both-category toggling when it is enabled.

  • Write failing BeaconTask tests proving a flag changed between two runs changes queued output without restarting a timer, and that the final status is aggregate.

  • Change Beacon settings tests so activation is immediate while templates and interval still wait for Apply; verify RED against the current draft-backed flags.

  • Implement the aggregate status helper and controller actions without changing the outbound-message path.

  • Make only the enable flags bypass SettingsDraft, observe their preference values in Compose, and wire their setters through the controller.

  • Run the core and app-desktop focused tests and verify GREEN.

Task 3: Clickable beacon status chip

Files:

  • Modify: app-desktop/src/main/kotlin/kst4contest/view/compose/StatusIndicatorState.kt
  • Modify: app-desktop/src/main/kotlin/kst4contest/view/compose/StatusBar.kt
  • Modify: app-desktop/src/main/java/kst4contest/view/Kst4ContestApplication.java
  • Modify: app-desktop/src/test/kotlin/kst4contest/view/compose/StatusIndicatorStateTest.kt
  • Create or modify: focused Compose status-bar rendering test under app-desktop/src/test/kotlin/kst4contest/view/compose/

Interfaces:

  • Consumes: controller usable-beacon toggle from Task 2

  • Produces: optional per-source chip action registered only for MyBeacon

  • Write failing state tests for actions registered before and after the first status report and for non-action thread chips.

  • Write a failing Compose test proving the beacon chip invokes its action while an ordinary status chip remains non-clickable.

  • Add optional actions to thread-status buttons and apply button semantics only when an action exists.

  • Register the controller toggle for MyBeacon during main-window state construction.

  • Run the focused status tests and the affected main-window tests.

Task 4: Documentation and verification

Files:

  • Modify: relevant beacon sections in github_docs/de-Konfiguration.md
  • Modify: corresponding sections in github_docs/en-Configuration.md
  • Modify: docs/PROJECT_CONTEXT.md
  • Review: relevant screenshots and changelog impact only

Interfaces:

  • Consumes: completed runtime and UI behavior from Tasks 1-3

  • Produces: aligned user documentation and durable state/persistence invariant

  • Update both manuals with immediate runtime effect, explicit-save persistence, aggregate chip behavior and second-chat handling.

  • Record the observable canonical state, timer-read rule and persistence boundary in docs/PROJECT_CONTEXT.md.

  • Run all focused tests, then ./gradlew.bat build --console=plain and read test-result XML summaries.

  • Run git diff --check, inspect PMD/SpotBugs XML for findings in changed production files, and review the final diff for unrelated changes.

  • Leave all changes unstaged and uncommitted and report remaining manual UI checks.