Novolis Docs
novolis-governance / completed-plans/bridge_commander_ux_03759127.plan.md

Bridge Commander: parser, context, and UI cleanup

dotnetgovernancenovolis

name: Bridge Commander UX overview: Fix Bridge Commander by teaching the command engine multi-word verbs and explicit context prefixes (with station aliases), then simplifying the Hex1b UI so help and history are readable and basic orders like helm heading 270 and tactical lock target parse correctly. todos:

  • id: engine-phrases

content: Add multi-word verb phrase matching to CommandParser + Engine tests status: completed

  • id: engine-context

content: Add GetContextAliases, require explicit prefix, built-in help; stop active-context filtering status: completed

  • id: bridge-registry

content: Rewrite BridgeCommandRegistry + context aliases; fix processor for help and nav args status: completed

  • id: bridge-ui

content: "Simplify Hex1b layout: remove station UI, help panel, await transmit, compact log" status: completed

  • id: verify

content: dotnet test both repos; manual Bridge Commander checklist status: completed isProject: false


Problems (from screenshot + code review)

flowchart LR
  subgraph broken [Why basic input fails]
    A["User: helm full stop"]
    B["Parser uses ONE verb token: full"]
    C["Registry expects phrase full stop"]
    D["Unknown command"]
    A --> B --> C --> D
  end
IssueCause
helm full stop, tactical lock target, engineering divert shields fail`CommandParser` matches one verb token; registry lists ["full","stop"] as alternatives, not a phrase
help works in log but status shows Unknown commandLikely stale status + Hex1b not re-rendering after fire-and-forget SubmitPromptAsync (`BridgeHexApp.Transmit`)
Chaotic logFull help text (40+ lines) dumped into command log; static Help panel duplicates it
Station buttonsUser wants explicit prefix only (helm, tactical, aliases weaps/pilot) — not a separate “selected station” UI

Target behavior

Every order must start with a context prefix (station name or alias). No implicit active station.

InputResult
helm heading 270Parse → helm.set-heading, heading 270
pilot heading 180pilot alias → helm context, same command
tactical lock targetParse → tactical.lock-target
weaps fireweaps alias → tactical, fire weapons
help / help tacticalBuilt-in or system help (not unknown)
heading 270 (no prefix)UnknownContext with hint: “Prefix with station (helm, tactical, weaps…)”

Part 1 — Engine: multi-word verbs (novolis-commands)

Change `CommandDefinition`: treat each entry in Verbs as a phrase (space-separated), not a single-token alternative.

Change `CommandParser`:

  • After context resolution, longest-prefix match verb phrases against remaining tokens (e.g. full stop, lock target, set heading, fire weapons, divert shields).
  • Argument tokens = everything after the matched phrase.
  • Keep single-token verbs (fire, hail, repair) working.

Tests in `Novolis.Commands.Engine.Tests`: add cases for multi-word phrases and regression for existing single-token verbs.


Part 2 — Engine: explicit context prefixes + aliases

Change `ICommandContextResolver<TContext>`:

IReadOnlyDictionary<string, string> GetContextAliases(TContext context);
// existing GetAliases → rename/clarify as verb aliases only

Change `CommandEngine`:

  1. First token → resolve via GetContextAliases, then check registry context words.
  2. If missing/unknown → ParseFailureCode.UnknownContext with message listing valid contexts/aliases.
  3. Stop using GetActiveContextWord for parse filtering (pass null as activeContextWord to parser, or remove that branch in v0.1 parser).

Built-in `BuiltInCommandMatcher` + `BuiltInCommands`:

  • Add system.help for exact help and help <topic> (topic in Arguments["topic"]).
  • Remove app-only help bypass in Bridge once processor handles it.

Part 3 — Bridge: expanded command tree

Rewrite `BridgeCommandRegistry` with phrase verbs:

CommandPrefixPhrase(s)Args
helm.set-headinghelmset heading, headingint heading
helm.full-stophelmfull stop, all stop—
helm.set-speedhelmset warp, warpint warp
tactical.lock-targettacticallock target, target lock—
tactical.fire-weaponstacticalfire, fire weapons—
engineering.divert-shieldsengineeringdivert shields, shields max—
engineering.divert-weaponsengineeringdivert weapons—
engineering.repairengineeringrepair, damage control—
nav.set-coursenavset course, coursestring destination (multi-token)
comms.hailcommshail, open channel—
crew.dismiss-personneladminfire— (ambiguity demo with tactical fire)

Context aliases in `BridgeContextResolver`:

AliasContext
pilot, connhelm
weaps, guns, tactactical
eng, damageengineering
navnav
commscomms

Remove verb aliases that tried to patch broken single-token parsing (stop → full stop, etc.).

Processor `BridgeCommandProcessor`: handle system.help — set BridgeState.HelpPanelLines (new property), do not enqueue.

State `BridgeState`:

  • Remove ActiveStation (or stop exposing in UI).
  • Add HelpPanelLines for dedicated help view.
  • Log: one-line summary for help (HELP help — opened reference panel), not 40 log lines.

Delete `BridgeHelp.TryGetHelpLines` bypass from `BridgeCommandService` once built-in help exists; keep BridgeHelp as content provider called from processor.

Nav multi-word destination: engine follow-up in same PR — if phrase matching leaves multiple arg tokens, join as destination string (alpha centauri).


Part 4 — Hex1b UI: less chaos

Redesign `BridgeHexApp`:

┌─ Status (ship + last status line only) ─────────────┐
├─ Command log (compact: PARSE/DONE/FAIL one-liners) ┤  ← no help walls
├─ Help panel (state.HelpPanelLines, scrollable)     ┤  ← replaces static Help box
├─ Order: [TextBox] [Transmit]                       ┤
└─ InfoBar: prefix required | help | belay | Ctrl+C  ┘
  • Remove station button row and Active station: label.
  • Remove static Help border (content moves to Help panel).
  • Transmit: await commands.SubmitPromptAsync(...) so status/log/help panel refresh reliably.
  • Log formatting `BridgeState.FormatHistory`: only expand details for ParseFailure (candidates), not Help.

Update `BridgeHelp` copy to say prefix required (no “active station” / buttons).


Part 5 — Verification

cd d:\novolis\novolis-commands && dotnet test
cd d:\novolis\novolis-dogfooding && dotnet run --project apps/BridgeCommander

Manual checklist:

  • helm heading 270, pilot warp 6, tactical lock target, weaps fire, engineering divert shields
  • heading 270 → clear UnknownContext hint
  • help, help tactical → help panel updates, log stays short
  • belay that during long engineering repair cancels
  • fire without prefix → ambiguity (admin vs tactical)

Scope boundaries

  • In scope: engine phrase matching, context aliases, built-in help, Bridge registry/UI, tests.
  • Out of scope: NLP, fuzzy match, confirmation flows, publishing new NuGet until engine changes are merged in novolis-commands.