dashboard: surface peer questions + operator override
questions pane now shows both operator-targeted threads (target IS NULL) and agent-to-agent threads (target = some agent). filter chips above the list: all / @operator / @peer / per-participant. peer rows get a mauve left rule + a 0V3RR1D3 button that POSTs the same /answer-question endpoint (OperatorQuestions::answer already permits the operator as answerer on any target). wire changes: OperatorQuestions gains pending_all + recent_answered_all; QuestionAdded + QuestionResolved events carry target: Option<String>; emit sites drop their target.is_none() guard. answered-history rows show the answerer prefix so override answers are auditable at a glance.
This commit is contained in:
parent
e7ce35c503
commit
a15fafb5de
9 changed files with 187 additions and 71 deletions
|
|
@ -243,11 +243,10 @@ impl Coordinator {
|
|||
});
|
||||
}
|
||||
|
||||
/// Emit `QuestionAdded` after an operator-targeted question is
|
||||
/// inserted. Peer-to-peer questions (those with a non-null
|
||||
/// `target` agent) never fire this — they don't surface on the
|
||||
/// dashboard at all. Caller is responsible for the
|
||||
/// `target.is_none()` guard.
|
||||
/// Emit `QuestionAdded` after a question is inserted. Fires for
|
||||
/// both operator-targeted (`target = None`) and peer-to-peer
|
||||
/// (`target = Some(agent)`) threads — the dashboard surfaces
|
||||
/// both, distinguishing visually + offering operator override.
|
||||
pub fn emit_question_added(
|
||||
&self,
|
||||
id: i64,
|
||||
|
|
@ -256,6 +255,7 @@ impl Coordinator {
|
|||
options: &[String],
|
||||
multi: bool,
|
||||
deadline_at: Option<i64>,
|
||||
target: Option<&str>,
|
||||
) {
|
||||
let asked_at = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
|
|
@ -271,20 +271,22 @@ impl Coordinator {
|
|||
multi,
|
||||
asked_at,
|
||||
deadline_at,
|
||||
target: target.map(str::to_owned),
|
||||
});
|
||||
}
|
||||
|
||||
/// Emit `QuestionResolved` when an operator-targeted question
|
||||
/// transitions to answered (operator answer, peer override,
|
||||
/// cancel, or ttl watchdog). Caller filters on the original
|
||||
/// question's `target.is_none()` — peer questions are dashboard-
|
||||
/// invisible.
|
||||
/// Emit `QuestionResolved` when a question transitions to
|
||||
/// answered (operator answer, peer answer, operator override on
|
||||
/// a peer thread, operator cancel, or ttl watchdog). Both
|
||||
/// operator-targeted and peer threads fire so the dashboard's
|
||||
/// derived store can move the row from pending to history.
|
||||
pub fn emit_question_resolved(
|
||||
&self,
|
||||
id: i64,
|
||||
answer: &str,
|
||||
answerer: &str,
|
||||
cancelled: bool,
|
||||
target: Option<&str>,
|
||||
) {
|
||||
let answered_at = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
|
|
@ -298,6 +300,7 @@ impl Coordinator {
|
|||
answerer: answerer.to_owned(),
|
||||
answered_at,
|
||||
cancelled,
|
||||
target: target.map(str::to_owned),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue