Repository navigation
fix(dcs): one relay endpoint label, record only while relaying, waiting wording matches the mode - #156
Merged
Conversation
…ng wording matches the mode X9: relay-rules relayEndpoint is the one endpoint label, pushed as relay:facts.endpoint and read by the Relay pill, the Overview DCS Link tile and the event log: host:port for TCP, the multicast group for loopback, 0.0.0.0:listenPort for Unicast. X12: one canRecord rule for the Connection card and Settings > Connection: a recording starts only while relaying, one already on can always be stopped. Main refuses capture:toggle before the save dialog when the rule says no. N2: the Overview Link tile says "relay waiting" only while the relay waits for the board; Monitor and an undriven Replay read "stream running". N3: a Replay driving the Gateway waits for the board as Bridge does: the pill, the note under Start and the Overview show the waiting reason. Part of #134.
mottihoresh
added a commit
that referenced
this pull request
Oct 17, 2026
…saved on commit with validation, psu fields follow imports (#157) Part of chunk 5 (#134): items X10, N5 and N8. Base: `fix/chunk-5`. ## X10: one telemetry spec - **Today:** the idle placeholders are their own spec. IAS and Press Alt read `% FS` until the first telemetry tick, then switch to kt and ft. Press Alt's idle id was `D_ALT_NEEDLE`, not `ALT_FT`. - **After:** there is one spec, `TELEMETRY` in `main/dcs/sim-telemetry-decoder.ts`. `idleTelemetry()` returns the decoder's live readouts with nothing decoded yet, so the gauges show kt, ft and % from the start. The contract's `TELEMETRY_IDLE` (`shared/dcs/ipc.ts`) is the renderer's starting value. A test pins it to the decoder's output. - **Side effect:** the idle Press Alt ring now uses the secondary tone, the same as the live Press Alt ring. Before, the idle ring was primary and only switched to secondary on the first tick. This follows from having one spec. ## N5: host and port - **Today:** the host and port are saved on every keystroke, and a port that isn't a number silently saves as 7778. - **After:** typing saves nothing. The field is saved on commit (blur or Enter). Main checks the port in `settings-form.ts` `commandPortOf`, which accepts whole digits from 1 to 65535. A bad port saves nothing and pushes nothing. `config:edit` then answers `{ ok: false, error }` (new `ConfigEditResult`). Both the Settings › Connection form and the Connection tab's DCS Link form show main's error using the existing `input--bad` / `aria-invalid` outline and `set-err` text. No new CSS. A blur that follows an Enter with nothing new typed sends nothing. An import resets the typed text and the error. - **API guard:** `editConfig` now answers `ConfigEditResult` instead of `AppConfig`. The frozen copy is updated on purpose, with a header note. No channel was added, removed or renamed. ## N8: PSU limit fields - **Today:** Settings › Cockpit's custom-limit fields hold their own typed text, which is never refreshed after an import replaces the settings. - **After:** an import (and `config:get`) bumps the config store's `formsReset`. `PowerSupply` is keyed on it, so the fields restart from the pushed config. This works the same way as the other form fields, which restart from the config on an import. A form's own edit still leaves its typed text alone. ## Tests changed on purpose (they pinned the old behaviour) - `sim-telemetry-decoder.test.ts`: the "idle readouts are their own spec" test becomes "one spec": idle equals the live snapshot, with units `% RPM / kt / % DN / ft / % QTY`. A new test checks that the first frame keeps the idle ids, labels and units. - `t27`: the idle gauges read `—kt` / `—ft` instead of `—% FS`. - `settings-edit.test.ts`: removed the "junk port saves as 7778" assertions. Added tests for `commandPortOf`, for a junk port being refused with its error, and for `SettingsService.edit` saving and pushing nothing on a junk port. Updated the tests for the new `SavedEdit` / `ConfigEditResult` shapes. - `pushed-rules.seam.test.ts`: `config:edit { port: '77a' }` is refused with the error. `config.json` and `config:get` keep the last good port, and no `config:changed` is pushed. - `t28` / `t31`: "saved as typed" becomes "saved on commit". These tests check that typing saves nothing, that blur and Enter each save, and that a blur after Enter does not send again. New tests check that a junk port shows the error with `aria-invalid` and saves nothing, and that a good port then saves and clears the error. - `t29` (new): renders the Cockpit and Configuration sections together. A typed (refused) limit is followed by an import with other limits, and the fields show the imported limits. - `skyhawk-mock.ts`: `editConfig` answers `ConfigEditResult` the way main does. All new and changed tests fail on the old source. I checked this by stashing the non-test changes: 16 tests failed. ## How verified `npm run lint`, `npm run lint:deps`, `npm run typecheck` and `npm test` (1421 tests) all pass locally, after rebasing onto `fix/chunk-5` at 8c48345 (#156). I have not tested on the DCS computer yet; that belongs in the chunk 5 device session.
mottihoresh
added a commit
that referenced
this pull request
Oct 18, 2026
…etry in real units, port validated on commit (#158) Chunk 5 of the fix track (#135): relay, telemetry and the settings form. Closes #134. Item PRs squash-merged into `fix/chunk-5`: - #156 — one `relayEndpoint` label for the pill, the Overview and the event log, correct per transport (Unicast reads "this PC:<port>"); Record only while relaying (or to stop a recording in progress), in Settings and on the Connection card, enforced in main before the save dialog; no device-waiting wording in Monitor; a Replay that drives the device shows the same waiting reason as Bridge. - #157 — one telemetry spec: idle gauges read kt/ft/% from the start; host and port are saved on commit (blur/Enter), a bad port shows an error and nothing is saved; the PSU custom-limit fields refresh after an import. Tested with a recorded replay before merge (checklist in #134); a live DCS session goes on the v0.2.0 QA run. Rebased on main after chunk 4. BEGIN_COMMIT_OVERRIDE fix(dcs): one relay endpoint label, record only while relaying, waiting wording matches the mode fix(settings): telemetry in real units from the start, host and port saved on commit with validation, psu fields follow imports END_COMMIT_OVERRIDE
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #134 (chunk 5): X9, X12, N2 and N3. All four live in
dcs/relay-rules.tsand are pushed onrelay:facts. The renderer only reads them.X9: one endpoint label
Today: the Relay pill and the Overview DCS Link tile each build their own endpoint, and the two disagree. TCP showed
host:porton the pill andhost:port · remoteon the tile. Unicast showedunicast listenon the pill and239.255.50.10:5010 · local(the multicast group) on the tile. Both used the host and port as typed in the renderer's form.After: there is one
relayEndpoint()inrelay-rules.ts, built from the settings main holds and pushed asRelayFacts.endpoint(a string). The pill tooltip, the DCS Link tile and the event log's relay rows all show it. The label per transport:host:commandPort239.255.50.10:50100.0.0.0:listenPort(the transport bindslistenPorton every address)relay-events.tsused to build its own copy of this label; it now callsrelayEndpoint().EndpointLabel,pillEndpoint,overviewEndpointand the renderer'sendpointTextwere removed. The title bar no longer passes host and port to the pill.X12: Record only while relaying
RelaySurfaces.canRecordboolean, fromcanRecord(relaying, recording). A recording can start only while relaying. A recording that is already running can always be stopped, so stopping the relay mid-recording never leaves a recording you can't stop. Main also enforces the rule:DcsRelay.mayRecord()is checked first incapture:toggle, so a refused Start never opens the save dialog. The save dialog still opens when a recording starts.N2: no device-waiting wording in Monitor
runningvalue, worded "stream running".N3: a driven Replay shows the waiting reason
waitingForDeviceusesexportToDevice(Bridge, or Replay with Drive Gateway on). So a driven Replay that loses the board now shows the waiting reason: the pill tooltip says it waits for the Gateway and turns gold, the note under Start says the same, and the Overview says "relay waiting".startBlockeduses the sameexportToDevicerule.Tests changed on purpose
relay-rules.test.ts: the X9, X12, N2 and N3 blocks that pinned the old behaviour were rewritten: the per-surface endpoints, the per-surfacecanRecord, "waiting in every mode", and "a driven Replay is never waiting". The facts test now expects a driven Replay running with no board to showwaiting-device.pushed-rules.seam.test.ts: theconfig:editfacts test now expects the Unicast endpoint0.0.0.0:5010. New seam tests cover X9 (all three transports from the settings main holds), X12 (refused while stopped with no dialog, allowed while relaying, stoppable after Stop), N2 (Monitor with no Gateway isrunning) and N3 (a driven Replay that loses the board waits for it).link-view.test.ts: the relay inputs carryreplayDriveSerial, andrelayWaitinggains a driven-Replay case.t27: the DCS Link tile expectations are now the shared label, without the· remote/· localsuffix, and Unicast shows its listen port. The old "reconnecting while relaying" Link case is now Bridge, since Monitor no longer waits. New cases: Monitor with no board reads "stream running"; a driven Replay reads "relay waiting"; the pill and the DCS Link tile show the same endpoint in<App />for TCP, Multicast and Unicast.t31: Settings › Connection's Record is disabled while stopped and enabled once relaying. This was contract B62; the comment noting the old behaviour was removed.t15/t28: new tests. A driven Replay with no board shows the waiting reason on the pill and in the note under Start. An undriven Replay just plays. Monitor with no board has no waiting wording.With the production files reverted to the base branch, 25 of these tests fail. Both the main and renderer tests catch every item.
How verified
npm run lint,npm run lint:deps,npm run typecheckandnpm testall pass (1414 tests). The API guard header records the type change: no channel, intent or method was renamed. Still to do: the on-device checklist in #134.