feat: add workspace resource human keys

This commit is contained in:
2026-08-20 02:17:00 +09:00
parent bb8eda379f
commit 1ca36d6b66
12 changed files with 899 additions and 60 deletions
+4
View File
@@ -317,6 +317,9 @@ fn state_style(state: &str) -> Style {
}
fn short_worker_id(worker: &BackendWorkerSummary) -> String {
if let Some(human_key) = worker.human_key.as_ref() {
return human_key.clone();
}
format!(
"{}:{}",
short_text(&worker.runtime_id),
@@ -358,6 +361,7 @@ mod tests {
BackendWorkerSummary {
runtime_id: runtime_id.to_string(),
worker_id: worker_id.to_string(),
human_key: None,
host_id: "host".to_string(),
label: "label".to_string(),
display_name: "label".to_string(),
+6 -1
View File
@@ -535,7 +535,12 @@ pub(super) fn ticket_detail_style(row: &PanelRow) -> Style {
pub(super) fn panel_ticket_reference(row: &PanelRow) -> String {
row.ticket
.as_ref()
.map(|ticket| ticket.id.clone())
.map(|ticket| {
ticket
.human_key
.clone()
.unwrap_or_else(|| ticket.id.clone())
})
.unwrap_or_else(|| match &row.key {
PanelRowKey::Ticket(id) | PanelRowKey::InvalidTicket(id) => id.clone(),
PanelRowKey::TicketIntakeWorker { ticket_id, .. } => ticket_id.clone(),
+5 -3
View File
@@ -1737,6 +1737,7 @@ fn panel_ticket_rows_render_state_title_then_detail_line() {
let state_start = 2;
let title_start = state_start + TICKET_STATE_COLUMN_WIDTH + 1;
let row_id = row.ticket.as_ref().unwrap().id.as_str();
let human_key = row.ticket.as_ref().unwrap().human_key.as_deref().unwrap();
assert!(title_line.starts_with(""));
assert!(detail_line.starts_with("│ meta "));
@@ -1746,7 +1747,7 @@ fn panel_ticket_rows_render_state_title_then_detail_line() {
display_column(&title_line, "Workspace Dashboard composer targets"),
title_start
);
assert!(detail_line.contains(row_id));
assert!(detail_line.contains(human_key));
assert!(detail_line.contains("Gate: clear"));
assert!(detail_line.contains("Action: Wait"));
}
@@ -1769,7 +1770,7 @@ fn panel_ticket_non_selected_rows_align_with_selected_marker_space() {
let title_start = state_start + TICKET_STATE_COLUMN_WIDTH + 1;
assert!(title_line.starts_with(" ready"));
assert!(detail_line.starts_with(" meta 00001KTTB479X"));
assert!(detail_line.starts_with(" meta T-1"));
assert_eq!(display_column(&title_line, "ready"), state_start);
assert_eq!(
display_column(&title_line, "Long Ticket title"),
@@ -1797,7 +1798,7 @@ fn panel_ticket_title_truncates_after_state_column() {
assert_eq!(display_column(&title_line, "Very long Ticket"), title_start);
assert!(title_line.ends_with('…'));
assert_eq!(detail_line.width(), 42);
assert!(detail_line.starts_with(" meta 00001KTTB479X · Gate: clear"));
assert!(detail_line.starts_with(" meta T-1 · Gate: clear"));
assert!(detail_line.ends_with('…'));
}
@@ -3259,6 +3260,7 @@ fn panel_test_ticket_row(
) -> PanelRow {
let ticket = crate::workspace_panel::TicketPanelEntry {
id: id.to_string(),
human_key: Some("T-1".to_string()),
title: title.to_string(),
priority: "P2".to_string(),
workflow_state: TicketWorkflowState::parse(state).unwrap_or(TicketWorkflowState::Planning),
+3
View File
@@ -253,6 +253,7 @@ impl NextUserAction {
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct TicketPanelEntry {
pub(crate) id: String,
pub(crate) human_key: Option<String>,
pub(crate) title: String,
pub(crate) priority: String,
pub(crate) workflow_state: TicketWorkflowState,
@@ -1063,6 +1064,7 @@ pub(crate) fn build_current_ticket_row(
fn ticket_summary_from_meta(meta: &TicketMeta) -> TicketSummary {
TicketSummary {
id: meta.id.clone(),
human_key: meta.human_key.clone(),
slug: meta.slug.clone(),
title: meta.title.clone(),
status: meta.status.clone(),
@@ -1238,6 +1240,7 @@ fn ticket_row(
let next_action = projection.next_action.map(next_user_action_from_workspace);
let entry = TicketPanelEntry {
id: summary.id.clone(),
human_key: summary.human_key.clone(),
title: summary.title.clone(),
priority: summary.priority.clone(),
workflow_state: summary.workflow_state,