Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d75cfe9
fix(tui): unify dialog behavior across tabs and overlays
jussielo-amd Sep 8, 2026
b6abbaa
fix(tui): address review findings on dialog enhancements
jussielo-amd Sep 8, 2026
955b713
fix(tui): dim the backdrop behind the theme picker and instance detail
jussielo-amd Sep 8, 2026
d6e8c36
fix(tui): make Help scrollable and surface mock tool approvals
jussielo-amd Sep 8, 2026
a58a20d
test(e2e): cover approval-defaults-to-deny and backdrop dimming
jussielo-amd Sep 8, 2026
30c1907
fix(dash-tui): clamp help-overlay scroll to the last page
jussielo-amd Sep 8, 2026
1d1a343
test(e2e): restore sequential scenario order in dash.feature
jussielo-amd Sep 8, 2026
98aa5e8
fix(dash-tui): clamp help-overlay scroll to the wrapped row count
jussielo-amd Sep 9, 2026
b0b08e1
fix(dash-tui): stop MockAgentClient re-firing approval on follow-up
jussielo-amd Sep 9, 2026
ae09df7
fix(dash-tui): reset help scroll when /help or /? opens Help
jussielo-amd Sep 9, 2026
d54e7a7
test(e2e): add dash-14/dash-15 scenarios, fix flaky detail-popup step
jussielo-amd Sep 9, 2026
251d5ae
fix(tui): clamp help scroll and correct back-out narrative
jussielo-amd Sep 10, 2026
b370b3e
fix(tui): apply cargo fmt, fix footer chip fallback, reword dash-11
jussielo-amd Sep 10, 2026
e8246c8
fix(e2e): wait for populated instance table before opening detail
jussielo-amd Sep 11, 2026
a7bc4dd
fix(tui): unify Esc-closes-console predicate, add scrollbar affordance
jussielo-amd Sep 14, 2026
1762748
fix(e2e): isolate timing-sensitive dash scenarios from concurrent con…
jussielo-amd Sep 14, 2026
320822a
merge: bring in origin/main, resolve dash.feature/dash_steps.rs confl…
jussielo-amd Sep 14, 2026
cfce2e2
fix(dash-tui): include install_config in onboarding's overlay-at-root…
jussielo-amd Sep 14, 2026
6307730
docs(agents): note review-dismissal and gh rerun-job gotchas
jussielo-amd Sep 14, 2026
cd25801
fix(dash-tui,e2e): route wheel scroll to help modals, fix dash-15 timing
jussielo-amd Sep 14, 2026
2612f47
fix(dash-tui,e2e): address pr-review-watcher non-blocking findings
jussielo-amd Sep 14, 2026
3750cd0
fix(dash-tui,e2e): dim periphery in draw_focused, add regression tests
jussielo-amd Sep 15, 2026
9deb12d
Merge remote-tracking branch 'origin/main' into worktree-tui-dialog-e…
jussielo-amd Sep 15, 2026
41aa05d
fix(dash-tui,e2e): confirm menu close before quit; test draw_focused …
jussielo-amd Sep 15, 2026
e40da41
fix(dash-tui): resolve remaining review findings from PR #358
jussielo-amd Sep 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ Before each stateful decision or public status update:
Do not rely on stale memory, partial CI views, or prior snapshots.
Subagent reports are hypotheses until directly re-verified. When re-verifying, match the verification scope to the claim: if subagent claimed "tests pass", re-run the same test suite; if it claimed "no conflicts", do the rebase locally; if it claimed "leak-free", re-run the scan.

A dismissed `CHANGES_REQUESTED` review (`review_dismissed` event) is not an approval — the reviewer withdrew their objection, but `reviewDecision` can still read `REVIEW_REQUIRED` afterward. Re-check `reviewDecision` directly rather than treating a dismissal as clearing the merge gate.
Comment thread
jussielo-amd marked this conversation as resolved.

After rebase/cherry-pick/merge, grep for conflict markers:

```bash
Expand Down Expand Up @@ -252,6 +254,7 @@ Watch checks to completion and drive to all-green.
- fix real regressions from your change
- handle infrastructure flakes by rerun or maintainer escalation with evidence
- ensure flakes are not hiding real code failures in other checks
- `gh run rerun --job <id>` is rejected until the *entire* parent run reaches `completed`, even if the target job already failed; if sibling jobs are still `queued`/`in_progress`, wait for the whole run to finish (or use `gh run rerun --failed <run-id>` once it has) instead of retrying the per-job command

A red check means "not ready" until resolved.

Expand Down
100 changes: 100 additions & 0 deletions crates/rocm-dash-tui/src/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1569,12 +1569,25 @@ impl AgentClient for AnthropicAgentClient {
}
}

/// When the last user turn contains `phrase` (case-insensitive), the mock
/// surfaces `intent` for approval over `tx` — mirroring what a real
/// `rocm_mutating_tool!`'s `call()` does from inside the rig tool loop — instead
/// of returning the normal canned reply. Lets `--chat-mock` drive e2e coverage
/// of the deny-by-default approval modal without a live model or a real
/// [`crate::tool_exec::RocmToolExecutor`].
struct MockApprovalTrigger {
phrase: String,
intent: crate::tool_exec::ApprovalIntent,
tx: UnboundedSender<ClientMsg>,
}

/// Deterministic in-memory client for tests and the offline demo. Never touches
/// the network. Can emit a canned tool-calling-style answer (cites a Skill).
pub struct MockAgentClient {
reply: String,
fail: bool,
cited: Vec<String>,
approval: Option<MockApprovalTrigger>,
}

impl MockAgentClient {
Expand All @@ -1584,6 +1597,7 @@ impl MockAgentClient {
reply: reply.into(),
fail: false,
cited: Vec::new(),
approval: None,
}
}

Expand All @@ -1594,6 +1608,30 @@ impl MockAgentClient {
reply: reply.into(),
fail: false,
cited: vec![tool_name.into()],
approval: None,
}
}

/// Like [`Self::with_tool_call`], but when the last user message contains
/// `phrase` (case-insensitive) the mock instead sends `intent` over
/// `approval_tx` as a `ClientMsg::ChatApprovalRequired` and replies with a
/// "surfaced for approval" note — no tool actually executes.
pub fn with_tool_call_and_approval_trigger(
reply: impl Into<String>,
tool_name: impl Into<String>,
phrase: impl Into<String>,
intent: crate::tool_exec::ApprovalIntent,
approval_tx: UnboundedSender<ClientMsg>,
) -> Self {
Self {
reply: reply.into(),
fail: false,
cited: vec![tool_name.into()],
approval: Some(MockApprovalTrigger {
phrase: phrase.into().to_lowercase(),
intent,
tx: approval_tx,
}),
}
}

Expand All @@ -1603,6 +1641,7 @@ impl MockAgentClient {
reply: String::new(),
fail: true,
cited: Vec::new(),
approval: None,
}
}
}
Expand All @@ -1620,6 +1659,25 @@ impl AgentClient for MockAgentClient {
if history.is_empty() {
return Err(AgentError::Empty);
}
if let Some(trigger) = &self.approval {
let fires = matches!(
history.last(),
Some(t) if t.role == ChatRole::User
&& t.content.to_lowercase().contains(&trigger.phrase)
);
if fires {
if let Err(e) = trigger.tx.send(ClientMsg::ChatApprovalRequired {
intent: trigger.intent.clone(),
}) {
warn!(error = %e, "mock approval trigger dropped: receiver gone");
}
return Ok(
"This action needs operator approval; it has been surfaced to \
the operator."
.to_string(),
);
}
}
Ok(annotate_reply(self.reply.clone(), &self.cited))
}
}
Expand Down Expand Up @@ -2138,6 +2196,48 @@ mod tests {
assert!(matches!(err, AgentError::Empty));
}

#[tokio::test]
async fn approval_trigger_does_not_refire_on_follow_up() {
// `on_approval_result` appends the approved-action result as an Agent
// turn (not a new User turn) before raising the one-shot automatic
// follow-up. The trigger must key off the *last* turn only, so that
// follow-up call sees `[User(trigger), Agent(result)]` and does not
// re-surface approval a second time.
let (tx, _rx) = tokio::sync::mpsc::unbounded_channel::<ClientMsg>();
let agent = MockAgentClient::with_tool_call_and_approval_trigger(
"all good",
"gpu_status",
"install the sdk",
crate::tool_exec::ApprovalIntent {
title: "Install TheRock ROCm SDK?".to_string(),
body: vec!["install_sdk".to_string()],
name: "install_sdk".to_string(),
arguments: json!({}),
},
tx,
);

let first = vec![ChatTurn::user("please install the sdk")];
let reply = agent
.complete(&first, fixture_snapshot())
.await
.expect("mock reply");
assert!(reply.contains("surfaced to"));

let follow_up = vec![
ChatTurn::user("please install the sdk"),
ChatTurn::agent("Installed successfully."),
];
let reply = agent
.complete(&follow_up, fixture_snapshot())
.await
.expect("mock reply");
assert!(
!reply.contains("surfaced to"),
"approval trigger re-fired on the automatic follow-up: {reply}"
);
}

#[test]
#[allow(clippy::float_cmp)]
fn rig_client_stores_inference_params() {
Expand Down
Loading
Loading