aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-07-13 03:26:03 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-07-13 03:30:13 +0300
commit5cfe5e5e730246948b0c9428ad876b6938590aad (patch)
tree53d4bbe1aff6887f63f279eed1b5e4e11e7331b7 /tests
parent7f3364a468f7dcfd8c9c84e5737fe5699f0e3a93 (diff)
feat: add configurable sidebar metadata tokens
Diffstat (limited to 'tests')
-rw-r--r--tests/api_ping.rs54
-rw-r--r--tests/cli_wrapper.rs75
-rw-r--r--tests/cross_area.rs22
3 files changed, 116 insertions, 35 deletions
diff --git a/tests/api_ping.rs b/tests/api_ping.rs
index aea8188a..651a3aa5 100644
--- a/tests/api_ping.rs
+++ b/tests/api_ping.rs
@@ -425,6 +425,26 @@ fn workspace_list_and_create_round_trip() {
);
assert_eq!(fetched["result"]["workspace"]["workspace_id"], workspace_id);
+ let metadata = send_request(
+ &socket_path,
+ &format!(
+ r#"{{"id":"req_workspace_metadata","method":"workspace.report_metadata","params":{{"workspace_id":"{}","source":"user:test","tokens":{{"jj_status":"2 changes"}}}}}}"#,
+ workspace_id
+ ),
+ );
+ assert_eq!(metadata["result"]["type"], "ok");
+ let fetched = send_request(
+ &socket_path,
+ &format!(
+ r#"{{"id":"req_workspace_metadata_get","method":"workspace.get","params":{{"workspace_id":"{}"}}}}"#,
+ workspace_id
+ ),
+ );
+ assert_eq!(
+ fetched["result"]["workspace"]["tokens"]["jj_status"],
+ "2 changes"
+ );
+
let panes = send_request(
&socket_path,
r#"{"id":"req_6","method":"pane.list","params":{}}"#,
@@ -1545,7 +1565,7 @@ fn pane_report_agent_updates_effective_state() {
let metadata = send_request(
&socket_path,
&format!(
- r#"{{"id":"req_hook_metadata","method":"pane.report_metadata","params":{{"pane_id":"{}","source":"user:pi-display","agent":"pi","applies_to_source":"herdr:pi","title":"Refactor auth","display_agent":"Pi auth","custom_status":"middleware","state_labels":{{"working":"deep in the mines"}}}}}}"#,
+ r#"{{"id":"req_hook_metadata","method":"pane.report_metadata","params":{{"pane_id":"{}","source":"user:pi-display","agent":"pi","applies_to_source":"herdr:pi","title":"Refactor auth","display_agent":"Pi auth","state_labels":{{"working":"deep in the mines"}},"tokens":{{"summary":"reviewing auth","model":"opus"}}}}}}"#,
pane_id
),
);
@@ -1562,11 +1582,15 @@ fn pane_report_agent_updates_effective_state() {
assert_eq!(pane["result"]["pane"]["agent_status"], "working");
assert_eq!(pane["result"]["pane"]["title"], "Refactor auth");
assert_eq!(pane["result"]["pane"]["display_agent"], "Pi auth");
- assert_eq!(pane["result"]["pane"]["custom_status"], "middleware");
assert_eq!(
pane["result"]["pane"]["state_labels"]["working"],
"deep in the mines"
);
+ assert_eq!(
+ pane["result"]["pane"]["tokens"]["summary"],
+ "reviewing auth"
+ );
+ assert_eq!(pane["result"]["pane"]["tokens"]["model"], "opus");
let agent = send_request(
&socket_path,
@@ -1585,28 +1609,20 @@ fn pane_report_agent_updates_effective_state() {
);
assert_eq!(agent["result"]["agent"]["title"], "Refactor auth");
assert_eq!(agent["result"]["agent"]["display_agent"], "Pi auth");
- assert_eq!(agent["result"]["agent"]["custom_status"], "middleware");
assert_eq!(
agent["result"]["agent"]["state_labels"]["working"],
"deep in the mines"
);
-
- let invalid_metadata = send_request(
- &socket_path,
- &format!(
- r#"{{"id":"req_hook_metadata_invalid","method":"pane.report_metadata","params":{{"pane_id":"{}","source":"user:pi-display","custom_status":"x","clear_custom_status":true}}}}"#,
- pane_id
- ),
- );
assert_eq!(
- invalid_metadata["error"]["code"],
- "invalid_metadata_request"
+ agent["result"]["agent"]["tokens"]["summary"],
+ "reviewing auth"
);
+ assert_eq!(agent["result"]["agent"]["tokens"]["model"], "opus");
let blank_source_metadata = send_request(
&socket_path,
&format!(
- r#"{{"id":"req_hook_metadata_blank_source","method":"pane.report_metadata","params":{{"pane_id":"{}","source":" ","custom_status":"x"}}}}"#,
+ r#"{{"id":"req_hook_metadata_blank_source","method":"pane.report_metadata","params":{{"pane_id":"{}","source":" ","title":"x"}}}}"#,
pane_id
),
);
@@ -1630,7 +1646,7 @@ fn pane_report_agent_updates_effective_state() {
let blank_authority_source_metadata = send_request(
&socket_path,
&format!(
- r#"{{"id":"req_hook_metadata_blank_authority_source","method":"pane.report_metadata","params":{{"pane_id":"{}","source":"user:pi-display","applies_to_source":" ","custom_status":"x"}}}}"#,
+ r#"{{"id":"req_hook_metadata_blank_authority_source","method":"pane.report_metadata","params":{{"pane_id":"{}","source":"user:pi-display","applies_to_source":" ","title":"x"}}}}"#,
pane_id
),
);
@@ -2277,7 +2293,7 @@ fn metadata_status_subscription_filter_and_ttl_expiry_are_observable() {
let metadata = send_request(
&socket_path,
&format!(
- r#"{{"id":"req_meta_sub_3","method":"pane.report_metadata","params":{{"pane_id":"{}","source":"user:pi-display","agent":"pi","applies_to_source":"herdr:pi","custom_status":"filtered out"}}}}"#,
+ r#"{{"id":"req_meta_sub_3","method":"pane.report_metadata","params":{{"pane_id":"{}","source":"user:pi-display","agent":"pi","applies_to_source":"herdr:pi","title":"filtered out"}}}}"#,
pane_id
),
);
@@ -2303,7 +2319,7 @@ fn metadata_status_subscription_filter_and_ttl_expiry_are_observable() {
let metadata = send_request(
&socket_path,
&format!(
- r#"{{"id":"req_meta_sub_4","method":"pane.report_metadata","params":{{"pane_id":"{}","source":"user:pi-display","agent":"pi","applies_to_source":"herdr:pi","custom_status":"short lived","ttl_ms":100}}}}"#,
+ r#"{{"id":"req_meta_sub_4","method":"pane.report_metadata","params":{{"pane_id":"{}","source":"user:pi-display","agent":"pi","applies_to_source":"herdr:pi","title":"short lived","ttl_ms":100}}}}"#,
pane_id
),
);
@@ -2314,14 +2330,14 @@ fn metadata_status_subscription_filter_and_ttl_expiry_are_observable() {
assert_eq!(set_event["data"]["pane_id"], pane_id);
assert_eq!(set_event["data"]["agent_status"], "working");
assert_eq!(set_event["data"]["agent"], "pi");
- assert_eq!(set_event["data"]["custom_status"], "short lived");
+ assert_eq!(set_event["data"]["title"], "short lived");
let expiry_event = reader.read_json_line(Duration::from_secs(3));
assert_eq!(expiry_event["event"], "pane.agent_status_changed");
assert_eq!(expiry_event["data"]["pane_id"], pane_id);
assert_eq!(expiry_event["data"]["agent_status"], "working");
assert_eq!(expiry_event["data"]["agent"], "pi");
- assert!(expiry_event["data"]["custom_status"].is_null());
+ assert!(expiry_event["data"]["title"].is_null());
cleanup_spawned_herdr(child, base);
}
diff --git a/tests/cli_wrapper.rs b/tests/cli_wrapper.rs
index 10a00c41..78d4c123 100644
--- a/tests/cli_wrapper.rs
+++ b/tests/cli_wrapper.rs
@@ -898,6 +898,61 @@ fn pane_run_sends_one_send_input_request_with_enter_key() {
}
#[test]
+fn workspace_report_metadata_sends_token_patch() {
+ let base = unique_test_dir();
+ fs::create_dir_all(&base).unwrap();
+ let socket_path = base.join("herdr.sock");
+ let listener = UnixListener::bind(&socket_path).unwrap();
+
+ let server = thread::spawn(move || {
+ let (mut stream, _) = listener.accept().unwrap();
+ let mut line = String::new();
+ let mut reader = BufReader::new(stream.try_clone().unwrap());
+ reader.read_line(&mut line).unwrap();
+ stream
+ .write_all(br#"{"id":"cli:request","result":{"type":"ok"}}"#)
+ .unwrap();
+ stream.write_all(b"\n").unwrap();
+ stream.flush().unwrap();
+ line
+ });
+
+ let run = run_cli(
+ &socket_path,
+ &[
+ "workspace",
+ "report-metadata",
+ "2",
+ "--source",
+ "user:jj",
+ "--token",
+ "jj_status=2 changes",
+ "--token",
+ "summary=clean",
+ "--clear-token",
+ "old",
+ "--ttl-ms",
+ "5000",
+ ],
+ );
+ assert!(
+ run.status.success(),
+ "stderr: {}",
+ String::from_utf8_lossy(&run.stderr)
+ );
+
+ let request: serde_json::Value = serde_json::from_str(&server.join().unwrap()).unwrap();
+ assert_eq!(request["method"], "workspace.report_metadata");
+ assert_eq!(request["params"]["workspace_id"], "2");
+ assert_eq!(request["params"]["tokens"]["jj_status"], "2 changes");
+ assert_eq!(request["params"]["tokens"]["summary"], "clean");
+ assert!(request["params"]["tokens"]["old"].is_null());
+ assert_eq!(request["params"]["ttl_ms"], 5000);
+
+ cleanup_test_base(&base);
+}
+
+#[test]
fn pane_report_metadata_sends_presentation_request() {
let base = unique_test_dir();
fs::create_dir_all(&base).unwrap();
@@ -931,10 +986,14 @@ fn pane_report_metadata_sends_presentation_request() {
"Refactor auth",
"--display-agent",
"Claude auth",
- "--custom-status",
- "middleware",
"--state-label",
"working=deep in the mines",
+ "--token",
+ "summary=reviewing auth",
+ "--token",
+ "model=opus",
+ "--clear-token",
+ "old",
"--ttl-ms",
"3600000",
],
@@ -954,11 +1013,13 @@ fn pane_report_metadata_sends_presentation_request() {
assert!(request["params"]["applies_to_source"].is_null());
assert_eq!(request["params"]["title"], "Refactor auth");
assert_eq!(request["params"]["display_agent"], "Claude auth");
- assert_eq!(request["params"]["custom_status"], "middleware");
assert_eq!(
request["params"]["state_labels"]["working"],
"deep in the mines"
);
+ assert_eq!(request["params"]["tokens"]["summary"], "reviewing auth");
+ assert_eq!(request["params"]["tokens"]["model"], "opus");
+ assert!(request["params"]["tokens"]["old"].is_null());
assert_eq!(request["params"]["ttl_ms"], 3_600_000);
cleanup_test_base(&base);
@@ -978,8 +1039,8 @@ fn pane_report_metadata_rejects_blank_source_before_socket_request() {
"1-1",
"--source",
" ",
- "--custom-status",
- "middleware",
+ "--token",
+ "summary=middleware",
],
);
@@ -1009,8 +1070,8 @@ fn pane_report_metadata_rejects_blank_applies_to_source_before_socket_request()
"user:claude-title",
"--applies-to-source",
" ",
- "--custom-status",
- "middleware",
+ "--token",
+ "summary=middleware",
],
);
diff --git a/tests/cross_area.rs b/tests/cross_area.rs
index 9fe71790..0ee9aa2b 100644
--- a/tests/cross_area.rs
+++ b/tests/cross_area.rs
@@ -836,7 +836,9 @@ fn cross_area_agent_process_survives_detach_and_reattach() {
client_handshake(&mut client_b, CURRENT_PROTOCOL, 80, 24);
let saw_working_on_client =
wait_for_frame_matching(&mut client_b, Duration::from_secs(5), |frame| {
- frame_contains_text(frame, "working")
+ ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]
+ .iter()
+ .any(|symbol| frame_contains_text(frame, symbol))
})
.expect("frame decoding should succeed");
assert!(
@@ -844,21 +846,23 @@ fn cross_area_agent_process_survives_detach_and_reattach() {
"reattached client frame should expose persisted agent working status"
);
- // Transition to idle and verify API + client surfaces both observe it.
- pane_report_agent(&api_socket, &pane_id, "pi", "idle", "cross-area-test");
+ // Transition to blocked and verify API + client surfaces both observe it.
+ // The fake process remains visibly working, so blocked is the deterministic
+ // higher-priority semantic transition for this cross-area projection test.
+ pane_report_agent(&api_socket, &pane_id, "pi", "blocked", "cross-area-test");
assert!(
- wait_for_agent_status(&api_socket, &pane_id, "idle", Duration::from_secs(3)),
- "pane agent status should transition to idle"
+ wait_for_agent_status(&api_socket, &pane_id, "blocked", Duration::from_secs(3)),
+ "pane agent status should transition to blocked"
);
- let saw_idle_on_client =
+ let saw_blocked_on_client =
wait_for_frame_matching(&mut client_b, Duration::from_secs(5), |frame| {
- frame_contains_text(frame, "idle")
+ frame_contains_text(frame, "◉")
})
.expect("frame decoding should succeed");
assert!(
- saw_idle_on_client,
- "reattached client frame should show idle status after transition"
+ saw_blocked_on_client,
+ "reattached client frame should show blocked status after transition"
);
cleanup_spawned_herdr(server, base);