§1: reroute bare rocm/chat → dash chat + parity gate (tui.rs RETAINED) - #37
Conversation
rominf
left a comment
There was a problem hiding this comment.
Approve with minor comments. Reroute + tui.rs retention is well-documented (single dead-code anchor, retirement checklist).
Notes:
- Compat change: interactive
rocm chat --provider/--modelno longer presets the session (dash auto-detects +/providerswitches). Recoverable, but worth a changelog/user-doc line rather than only a code comment. Same for--chat-mockbeing interactive-only (silently ignored on the render path). - The parity-gate tests assert on
main.rssource text (brace-slicing +.contains) — genuine (fail on revert) but brittle: arustfmtreformat or rename breaks them with no behavioral regression. Acceptable stopgap given the paths need a TTY; flagging as test debt.assert_ne!(target as usize, 0)is a tautology — the compile-time signature coercion above it is the real guard.
de9b2e8 to
c217073
Compare
488ca6a to
11f5683
Compare
rominf
left a comment
There was a problem hiding this comment.
Requesting changes on signing grounds — this is separate from the code review above, which still stands.
Every commit on this PR is unsigned: GitHub reports verification.verified = false (reason unsigned) for all of them. Signed commits are required before this can merge.
To fix, configure commit signing and re-sign the branch history, e.g. with SSH signing:
git config gpg.format ssh
git config user.signingkey <your-signing-key.pub>
git config commit.gpgsign true
git rebase --exec 'git commit --amend --no-edit -S' <base-branch>
git push --force-with-lease
Since this is a stacked PR, re-signing is easiest from the bottom of the stack upward — re-signing a base branch rewrites its SHAs and the dependent branches will need rebasing/re-pushing on top.
Once the commits show as Verified I'll clear this.
c217073 to
ba10a67
Compare
11f5683 to
05085b1
Compare
rominf
left a comment
There was a problem hiding this comment.
Signing gate cleared — all commits on this PR now show Verified (verification.verified = true, reason valid). Re-reviewed the current diff against this PR's own base after the re-sign; it's substantively unchanged from my prior review.
Approving on both grounds: code is sound and commits are signed.
ba10a67 to
0cf26f3
Compare
05085b1 to
4c515e0
Compare
There was a problem hiding this comment.
Pull request overview
Routes the default interactive rocm entrypoint and interactive rocm chat (no --prompt) to the unified dash chat (dash::run_chat focusing ActiveTab::Chat), while intentionally retaining the legacy tui.rs behind a single retention anchor and documenting the human deletion gate once parity is accepted.
Changes:
- Reroutes bare
rocmand interactiverocm chattodash::run_chat, adds--chat-mockpassthrough, and pinstui.rsreachability via a retention anchor. - Adds
dash::run_chatand threadsinitial_tabinto the dash async launcher to support chat-first launches. - Adds/updates parity + retirement documentation (parity map, parity checklist, and a human-only deletion checklist).
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/tui-retirement-checklist.md | Adds the human-only go/no-go procedure and explains the retention anchor. |
| docs/dash-parity-map.md | Updates parity map with Phase 9 routing note and links to the retirement checklist. |
| docs/dash-parity-checklist.md | Adds the accept/retire gate checklist summarizing parity evidence. |
| apps/rocm/src/main.rs | Reroutes interactive entrypoints to dash chat, adds --chat-mock, adds retention anchor + routing verification tests. |
| apps/rocm/src/dash.rs | Adds run_chat entrypoint and plumbs initial_tab into run_async/resolved_args. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
rominf
left a comment
There was a problem hiding this comment.
Re-approving the current head after the cascade rebase onto the updated base — refreshing my prior approval onto this exact commit.
Re-reviewed: reroute bare rocm + interactive rocm chat → dash::run_chat; legacy tui.rs retained behind a single anchor with a human-only deletion gate.
Copilot re-reviewed this same commit (COMMENTED, no blocking findings). No clear issues; LGTM.
|
Reviewed the Copilot suggestions here (simplicity-first / ponytail pass) — dismissing all three; nothing to change on this PR.
|
volen-silo
left a comment
There was a problem hiding this comment.
Reviewed from the diff — clean, well-documented reroute. One real UX regression to address, plus a test-robustness suggestion. Not blocking.
🟡 --provider is silently ignored on the interactive path
Previously the interactive launch honored it: tui::run(provider.map(provider_name).map(str::to_owned)). Now the branch calls dash::run_chat(chat_mock), whose signature is run_chat(chat_mock: bool) — provider is dropped. So rocm chat --provider anthropic (interactive) starts on auto-detect, not anthropic. clap still accepts the flag, so it's silently ignored — no error, no effect. The code comment documents this intentionally, but a user can't see a comment.
Pick one:
- Thread it through:
run_chat(provider, chat_mock)to set the starting backend (the dash already supports/providerto switch afterward), or - If intentionally deferred, emit a one-line notice when
--provideris passed interactively ("ignoring --provider; use /provider in the dash").
Same question for --tools on the interactive branch — confirm it isn't silently dropped too.
🟡 Source-introspection tests are brittle
launch_default_routes_to_dash_run_chat_not_tui et al. read main.rs at test time and hand-roll brace balancing to extract handler bodies, then string-match. Clever given the TTY constraint, but it breaks on any harmless refactor (e.g. extracting the arm into a fn) even when behavior is unchanged, and the brace counter doesn't account for braces inside string/char literals (fine today, latent).
More robust: extract the routing decision into a pure function returning an enum (e.g. chat_route(interactive, prompt, chat_mock) -> ChatRoute), call it from both entrypoints, and unit-test that — assertions key on real logic, not source text. Worth doing before the eventual tui.rs deletion churns these strings.
🟢 Good
- Retention anchor (
_RETAINED_TUI_ENTRY) is a clean way to keep the frozen module reachable under-D warningswithout a dead_code cascade, andtui_run_is_referenced_only_by_the_retention_anchorlocks it to exactly one reference. run_chatreuses the samerun_asyncpath (replay=None ⇒ live executor + embedded daemon), so chat parity inherits the Phase 2/3 seam correctly.- The retirement checklist is excellent — compiler-driven pruning, "don't run automatically," rollback section. Right way to stage a risky deletion.
Notes
- CI hasn't reported on this branch yet. With the license-header hawkeye hook now on main (#51), rebase this stack so hawkeye/fmt run clean here too.
- Reviewed from the diff only; I didn't check out the phase-8 stack, so I haven't run its tests or verified the parity-checklist's cross-phase evidence pointers.
1dac2c7 to
ae78484
Compare
Bare `rocm` and interactive `rocm chat` now open the unified dash with the Chat tab focused via dash::run_chat, instead of the legacy tui::run assistant. run_async takes an initial_tab; run_chat is a thin wrapper. Adds --chat-mock to the Chat command. Prompt/non-interactive passthrough (render_chat_*) unchanged. tui.rs is RETAINED and compiling via a single dead_code-allowed retention anchor (_RETAINED_TUI_ENTRY) that keeps its call graph reachable under -D warnings without deleting the module. Signed-off-by: Michael Roy <michael.roy@amd.com>
… checklist - dash-parity-map.md: header note that all 30 commands are covered as of Phase 9 and bare rocm/chat route to the dash (30 covered, 0 pending-status). - dash-parity-checklist.md: accept/retire gate (ROADMAP §1 step 1) — 6 capability buckets, all ACCEPTED with concrete test/artifact pointers, zero unaccepted. - tui-retirement-checklist.md: exact human go/no-go deletion steps (not executed) with a compiler-driven dead-code discovery procedure and verify command. Signed-off-by: Michael Roy <michael.roy@amd.com>
Source-level dispatch tests (interactive branches need a TTY, untestable in CI): - launch_default and the Command::Chat interactive arm call dash::run_chat and no longer call tui::run; - --chat-mock is forwarded to run_chat(chat_mock); --prompt still routes to render_chat_prompt_text / render_chat_text (scriptable passthrough); - dash::run_chat exists with fn(bool) -> Result<()>; - tui::run is referenced exactly once in production code (the retention anchor). Signed-off-by: Michael Roy <michael.roy@amd.com>
cargo fmt wrapped the multi-arg run_async call; the dash::run_chat existence test now asserts on the fn pointer address so the binding has an effect under clippy::no_effect_underscore_binding (-D warnings). Signed-off-by: Michael Roy <michael.roy@amd.com>
4c515e0 to
2c8d3c8
Compare
… against nested tokio runtimes The #37 reroute sends bare `rocm` / `rocm chat` to `dash::run_chat`, which builds a tokio runtime and `block_on`s `run_async`. `run_async` called `resolved_args`, which resolved the Anthropic key via the native secret store; on Linux that store uses `zbus::blocking` (its own `block_on`). Running it with a tokio runtime context already entered panics "Cannot start a runtime from within a runtime" — so every Linux user launching `rocm`/`rocm chat` without ANTHROPIC_API_KEY in env crashed at startup. The acceptance PTY harness caught it; unit tests did not. Two layers, fixing the instance and the class: 1. Resolve the Anthropic key off-runtime. `dash::run` and `dash::run_chat` now call `anthropic_api_key_for_dash()` before building the runtime and thread the resolved `Option<String>` through `run_async` -> `resolved_args` (new param). This keeps secret I/O off the async hot path and self-documents the intent. 2. Make `provider_keys::with_native_entry` runtime-safe. It is the single chokepoint for every store op (get/set/clear) and thus for `resolve_provider_api_key` / `provider_key_status`. When a tokio runtime is active (`Handle::try_current().is_ok()`), it now runs `native_entry` + the action on a fresh `std::thread::scope` thread that has no runtime entered, and `join()`s it (mapping a worker panic to an `Err` so `thread::scope` cannot re-propagate it into a process abort). `block_in_place` is deliberately not used: it keeps the runtime context entered, so the nested `block_on` would still panic. This also hardens the latent provider-assisted `/plan` path (run_internal_mcp_call -> provider_chat -> resolve_provider_api_key), which only avoids the panic today because it runs under spawn_blocking. Adds `native_store_access_inside_tokio_runtime_does_not_panic`, which reproduces the exact panic without the guard (verified RED) and passes with it. It asserts the no-panic / graceful-Err contract (CI has no Secret Service), which is the behavior that regressed. Signed-off-by: Michael Roy <michael.roy@amd.com>
After the #37 reroute, `rocm chat` runs the dash event loop. Two paths could turn a clean quit into a non-zero exit once the terminal/PTY closed: - `event_loop` mapped a crossterm `EventStream` error to `return Err(..)`. When the controlling terminal goes away (the PTY/stdin closes), that read error is not a failure — the session is over. Now it breaks cleanly, mirroring the existing `None => break` EOF arm and the legacy blocking reader's behavior. - `app::run` tore down the terminal with `?` on every step. If the terminal is already gone, those writes can fail with a broken pipe and flip the exit code. Teardown is now best-effort so it never overrides the session result. This surfaced as the acceptance PTY smoke (`rocm chat --provider openai` driven by a finite input pipe) exiting non-zero on Linux but not Windows: only Linux takes the `maybe_spawn_embedded_daemon` path, whose startup delay let the input pipe close before the first key was read, so the event stream errored. With a live daemon (or on Windows, where embedded-daemon spawn is a no-op) startup is instant and the bug is masked. Also dump the captured TUI log on smoke failure so a non-zero exit is debuggable in CI instead of failing opaquely. Signed-off-by: Michael Roy <michael.roy@amd.com>
…GPIPE The TUI smoke drives `rocm chat` by piping `q`/`y` keystrokes into `script`. After the #37 reroute the dash quits immediately on `q`, so the feeder's trailing `printf 'y'` races with the child exiting and takes a broken pipe (non-zero). Under `set -o pipefail` that poisoned the pipeline status and failed the smoke even though `script -e` reported the dash exited 0 — masked previously by the startup panic. The verified-clean-exit signal is `script`'s child code, so drop `pipefail` for just this pipeline. Real TUI failures (non-zero child) are still caught. Signed-off-by: Michael Roy <michael.roy@amd.com>
…headers) The phase-10 app.rs split predates #36/#37 and the repo's MIT relicense, so the extracted modules carried stale logic and license headers that the rebase's "keep the split structure" resolution preserved. Restore main's behavior: - build_chat_agent's OpenAI arm requires a non-empty key and returns None otherwise (#36); the older split passed the raw Option through, building a dead sk-no-key backend that 401s at request time. - /update --apply is position-independent (scan all tokens), matching /uninstall, not only the second token. - /uninstall rejects conflicting --apply + --dry-run with a guided error. - app/{chat,slash,summary}.rs SPDX headers switched Apache-2.0 → MIT to match the relicensed tree (licenserc.toml / hawkeye gate). All dash-tui tests pass; hawkeye clean. Signed-off-by: Michael Roy <michael.roy@amd.com>
Stack 9/10 · base:
supergoal/phase-8-provider-anthropicrocmand interactiverocm chatnow route to the dash chat (dash::run_chat);--chat-mock+ prompt passthrough preserved.tui.rsRETAINED (parity then gate) via a single#[allow(dead_code)]retention anchor — deletion is a human step indocs/tui-retirement-checklist.md(NOT performed here).docs/dash-parity-map.md(30 covered) + addsdocs/dash-parity-checklist.md.Reviewed: rust + maintainability. All cargo gates green.