From b5b380107ac995b3a2bae8bd03037e0f8e1188bd Mon Sep 17 00:00:00 2001 From: Bob Date: Tue, 9 Jun 2026 14:09:49 +0800 Subject: [PATCH 1/2] feat: infer repo for bare issue numbers --- README.md | 5 ++ src/cli.rs | 34 ++++++++- src/domain/resource.rs | 37 +++++++++- src/runner.rs | 157 ++++++++++++++++++++++++----------------- src/session.rs | 81 +++++++++++++++++++-- 5 files changed, 241 insertions(+), 73 deletions(-) diff --git a/README.md b/README.md index abb50105..829226a8 100644 --- a/README.md +++ b/README.md @@ -48,8 +48,13 @@ Open a pull request or issue: gzg openclaw/openclaw#81834 gzg https://github.com/openclaw/openclaw/pull/81834 gzg https://github.com/openclaw/openclaw/issues/88499 +gzg 81834 ``` +When you run `gzg` from inside a git checkout with a GitHub remote, a bare +number uses that repository. For example, `gzg 81834` inside a checkout of +`openclaw/openclaw` opens `openclaw/openclaw#81834`. + Run `gzg` again from the same terminal context to restore the last ghzinga dashboard for that pane, tmux pane, Herdr pane, working tree, or named session. Use `--new` to start a separate saved session, `--no-restore` to ignore saved diff --git a/src/cli.rs b/src/cli.rs index 4e4abf18..58796758 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -17,7 +17,7 @@ pub const DEFAULT_REFRESH_SECONDS: u64 = 300; about = "Monitor a GitHub PR or issue in a terminal UI" )] pub struct Cli { - /// GitHub resource as URL, owner/repo#number, or owner/repo number. + /// GitHub resource as URL, owner/repo#number, owner/repo number, or bare number in a GitHub repo. #[arg(value_name = "RESOURCE")] pub resource: Vec, @@ -102,18 +102,33 @@ impl Cli { } pub fn parse_resource_id(&self) -> Result { + self.parse_resource_id_with_repo_context(None) + } + + pub fn parse_resource_id_with_repo_context( + &self, + repo_name_with_owner: Option<&str>, + ) -> Result { match self.resource.as_slice() { - [single] => ResourceId::parse(single), + [single] => ResourceId::parse_with_repo_context(single, repo_name_with_owner), [owner_repo, number] => ResourceId::from_owner_repo_number(owner_repo, number), _ => Err(ResourceIdError::Invalid), } } pub fn parse_optional_resource_id(&self) -> Result, ResourceIdError> { + self.parse_optional_resource_id_with_repo_context(None) + } + + pub fn parse_optional_resource_id_with_repo_context( + &self, + repo_name_with_owner: Option<&str>, + ) -> Result, ResourceIdError> { if self.resource.is_empty() { Ok(None) } else { - self.parse_resource_id().map(Some) + self.parse_resource_id_with_repo_context(repo_name_with_owner) + .map(Some) } } } @@ -173,6 +188,19 @@ mod tests { ); } + #[test] + fn parses_relative_resource_from_repo_context() { + let cli = Cli::parse_from(["ghzinga", "81834"]); + + assert_eq!( + cli.parse_resource_id_with_repo_context(Some("openclaw/openclaw")) + .unwrap() + .canonical_name(), + "openclaw/openclaw#81834" + ); + assert!(cli.parse_resource_id().is_err()); + } + #[test] fn parses_offline_fixture_flag() { let cli = Cli::parse_from([ diff --git a/src/domain/resource.rs b/src/domain/resource.rs index b73e39d2..7efd79c0 100644 --- a/src/domain/resource.rs +++ b/src/domain/resource.rs @@ -16,7 +16,7 @@ static OWNER_REPO_HASH_RE: LazyLock = LazyLock::new(|| { #[derive(Debug, Error, PartialEq, Eq)] pub enum ResourceIdError { - #[error("expected a GitHub PR/issue URL, owner/repo#number, or owner/repo number")] + #[error("expected a GitHub PR/issue URL, owner/repo#number, owner/repo number, or a number from inside a GitHub repo")] Invalid, #[error("resource number must be positive")] InvalidNumber, @@ -48,6 +48,13 @@ pub struct ResourceId { impl ResourceId { pub fn parse(input: &str) -> Result { + Self::parse_with_repo_context(input, None) + } + + pub fn parse_with_repo_context( + input: &str, + repo_name_with_owner: Option<&str>, + ) -> Result { let trimmed = input.trim(); if trimmed.is_empty() { return Err(ResourceIdError::Invalid); @@ -61,6 +68,13 @@ impl ResourceId { return Ok(parsed); } + if let Some(repo_name_with_owner) = repo_name_with_owner { + let number = trimmed.strip_prefix('#').unwrap_or(trimmed); + if !number.is_empty() && number.chars().all(|ch| ch.is_ascii_digit()) { + return Self::from_owner_repo_number(repo_name_with_owner, number); + } + } + Err(ResourceIdError::Invalid) } @@ -743,6 +757,27 @@ mod tests { assert_eq!(id.canonical_name(), "openclaw/openclaw#81834"); } + #[test] + fn parses_relative_numbers_with_repo_context() { + let id = ResourceId::parse_with_repo_context("81834", Some("openclaw/openclaw")).unwrap(); + + assert_eq!(id.canonical_name(), "openclaw/openclaw#81834"); + assert_eq!(id.kind_hint, None); + + let hash_id = + ResourceId::parse_with_repo_context("#88499", Some("openclaw/openclaw")).unwrap(); + + assert_eq!(hash_id.canonical_name(), "openclaw/openclaw#88499"); + } + + #[test] + fn rejects_relative_numbers_without_repo_context() { + assert_eq!( + ResourceId::parse_with_repo_context("81834", None).unwrap_err(), + ResourceIdError::Invalid + ); + } + #[test] fn rejects_zero_number() { assert_eq!( diff --git a/src/runner.rs b/src/runner.rs index 16926f22..0bc8f1e3 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -64,8 +64,9 @@ async fn run_open_command(raw_args: &[String], args: &[String]) -> anyhow::Resul print_open_usage_to_stderr(); return Ok(2); } - let resources = parse_resource_args(&resource_args)?; let cwd = std::env::current_dir().unwrap_or_else(|_| ".".into()); + let repo_context = session::github_repo_name_from_cwd(&cwd); + let resources = parse_resource_args(&resource_args, repo_context.as_deref())?; let plan = match session::resolve_control_plan(session_ref, raw_args.to_vec(), cwd.clone()) { Ok(plan) => plan, Err(session::ControlResolveError::Ambiguous(matches)) => { @@ -224,19 +225,31 @@ fn parse_control_session_option(args: &[String]) -> anyhow::Result<(Option anyhow::Result> { +fn parse_resource_args( + args: &[String], + repo_name_with_owner: Option<&str>, +) -> anyhow::Result> { match args { [] => anyhow::bail!("expected at least one GitHub PR/issue resource"), - [single] => Ok(vec![ResourceId::parse(single).map_err(anyhow::Error::new)?]), + [single] => Ok(vec![ResourceId::parse_with_repo_context( + single, + repo_name_with_owner, + ) + .map_err(anyhow::Error::new)?]), [owner_repo, number] - if ResourceId::parse(owner_repo).is_err() && number.parse::().is_ok() => + if owner_repo.contains('/') + && ResourceId::parse(owner_repo).is_err() + && number.parse::().is_ok() => { Ok(vec![ResourceId::from_owner_repo_number(owner_repo, number) .map_err(anyhow::Error::new)?]) } many => many .iter() - .map(|value| ResourceId::parse(value).map_err(anyhow::Error::new)) + .map(|value| { + ResourceId::parse_with_repo_context(value, repo_name_with_owner) + .map_err(anyhow::Error::new) + }) .collect(), } } @@ -262,7 +275,7 @@ fn print_sessions_usage_to_stderr() { fn print_open_usage() { println!("usage: gzg open [--session ] [resource...]"); println!(); - println!("Resources may be GitHub URLs or owner/repo#number values."); + println!("Resources may be GitHub URLs, owner/repo#number values, or bare numbers from inside a GitHub repo."); println!("The owner/repo number form is supported for one resource at a time."); } @@ -460,8 +473,9 @@ pub async fn run_from_cli() -> anyhow::Result<()> { } let cli = Cli::parse(); let loaded_config = config::load(); - let resource_id = cli.parse_optional_resource_id()?; let cwd = std::env::current_dir().unwrap_or_else(|_| ".".into()); + let repo_context = session::github_repo_name_from_cwd(&cwd); + let resource_id = cli.parse_optional_resource_id_with_repo_context(repo_context.as_deref())?; let restore_plan = if cli.once { RestorePlan { handle: None, @@ -480,64 +494,65 @@ pub async fn run_from_cli() -> anyhow::Result<()> { let api_depth = cli .api_depth .unwrap_or_else(crate::github::api::ApiDepth::from_env); - let (mut state, fetch_source, initial_fetch, restored_ui) = - if let Some(path) = &cli.offline_fixture { - let resource = load_fixture(path)?; - let fixture_source = OfflineFixtureSource::from_primary_and_paths( - resource.clone(), - &cli.offline_resource_fixture, - )?; + let (mut state, fetch_source, initial_fetch, restored_ui) = if let Some(path) = + &cli.offline_fixture + { + let resource = load_fixture(path)?; + let fixture_source = OfflineFixtureSource::from_primary_and_paths( + resource.clone(), + &cli.offline_resource_fixture, + )?; + ( + AppState::new(resource), + FetchSource::OfflineFixtures(fixture_source), + None, + false, + ) + } else { + let gateway = GithubApiGateway::new(api_depth); + let fetch_source = FetchSource::Github(gateway); + if cli.once { + let Some(resource_id) = resource_id.clone() else { + anyhow::bail!( + "expected a GitHub PR/issue URL, owner/repo#number, owner/repo number, or a number from inside a GitHub repo" + ); + }; ( - AppState::new(resource), - FetchSource::OfflineFixtures(fixture_source), + AppState::new(fetch_source.fetch_resource(&resource_id).await?), + fetch_source, None, false, ) + } else if let Some(snapshot) = &restore_plan.snapshot { + let mut state = session::restore_state_from_snapshot( + snapshot, + &restore_plan + .handle + .as_ref() + .map(|handle| handle.cache_dir.clone()) + .unwrap_or_else(session::cache_dir), + ) + .unwrap_or_else(empty_launch_state); + let initial_fetch = + prepare_restored_initial_fetch(&mut state, snapshot, resource_id.clone()); + (state, fetch_source, initial_fetch, true) } else { - let gateway = GithubApiGateway::new(api_depth); - let fetch_source = FetchSource::Github(gateway); - if cli.once { - let Some(resource_id) = resource_id.clone() else { - anyhow::bail!( - "expected a GitHub PR/issue URL, owner/repo#number, or owner/repo number" - ); - }; - ( - AppState::new(fetch_source.fetch_resource(&resource_id).await?), - fetch_source, - None, - false, - ) - } else if let Some(snapshot) = &restore_plan.snapshot { - let mut state = session::restore_state_from_snapshot( - snapshot, - &restore_plan - .handle - .as_ref() - .map(|handle| handle.cache_dir.clone()) - .unwrap_or_else(session::cache_dir), - ) - .unwrap_or_else(empty_launch_state); - let initial_fetch = - prepare_restored_initial_fetch(&mut state, snapshot, resource_id.clone()); - (state, fetch_source, initial_fetch, true) - } else { - let initial_resource = resource_id - .clone() - .map(loading_resource_placeholder) - .unwrap_or_else(empty_launch_resource); - let mut state = AppState::new(initial_resource); - if resource_id.is_none() { - state.open_add_resource_prompt(); - } - ( - state, - fetch_source, - resource_id.map(|id| FetchAction::Initial { id }), - false, - ) + let initial_resource = resource_id + .clone() + .map(loading_resource_placeholder) + .unwrap_or_else(empty_launch_resource); + let mut state = AppState::new(initial_resource); + if resource_id.is_none() { + state.open_add_resource_prompt(); } - }; + ( + state, + fetch_source, + resource_id.map(|id| FetchAction::Initial { id }), + false, + ) + } + }; state.config_path = loaded_config.path.clone(); if !restored_ui { @@ -1958,10 +1973,13 @@ mod tests { #[test] fn open_parser_accepts_multiple_single_token_resources() { - let resources = parse_resource_args(&[ - "owner/repo#2".to_string(), - "https://github.com/owner/repo/issues/3".to_string(), - ]) + let resources = parse_resource_args( + &[ + "owner/repo#2".to_string(), + "https://github.com/owner/repo/issues/3".to_string(), + ], + None, + ) .unwrap(); assert_eq!(resources.len(), 2); @@ -1971,12 +1989,23 @@ mod tests { #[test] fn open_parser_keeps_owner_repo_number_single_resource_form() { - let resources = parse_resource_args(&["owner/repo".to_string(), "4".to_string()]).unwrap(); + let resources = + parse_resource_args(&["owner/repo".to_string(), "4".to_string()], None).unwrap(); assert_eq!(resources.len(), 1); assert_eq!(resources[0].canonical_name(), "owner/repo#4"); } + #[test] + fn open_parser_accepts_relative_numbers_with_repo_context() { + let resources = + parse_resource_args(&["2".to_string(), "#3".to_string()], Some("owner/repo")).unwrap(); + + assert_eq!(resources.len(), 2); + assert_eq!(resources[0].canonical_name(), "owner/repo#2"); + assert_eq!(resources[1].canonical_name(), "owner/repo#3"); + } + #[test] fn control_help_parser_does_not_consume_session_name() { assert!(has_command_help_arg(&["--help".to_string()])); diff --git a/src/session.rs b/src/session.rs index 8dbe4655..18b69815 100644 --- a/src/session.rs +++ b/src/session.rs @@ -468,20 +468,58 @@ pub fn collect_launch_contexts(explicit_session: Option<&str>, cwd: &Path) -> Ve } fn git_remote_context(cwd: &Path) -> Option { + let remote = github_remote_url_from_cwd(cwd)?; + let key = github_repo_key_from_remote(&remote)?; + Some(LaunchContext::new("git", key, ContextConfidence::Weak).with_metadata("remote", remote)) +} + +pub fn github_repo_name_from_cwd(cwd: &Path) -> Option { + github_repo_name_from_remote(&github_remote_url_from_cwd(cwd)?) +} + +fn github_remote_url_from_cwd(cwd: &Path) -> Option { + if let Some(remote) = git_remote_url(cwd, "origin") + .filter(|remote| github_repo_name_from_remote(remote).is_some()) + { + return Some(remote); + } + let output = Command::new("git") - .args(["remote", "get-url", "origin"]) + .arg("remote") .current_dir(cwd) .output() .ok()?; if !output.status.success() { return None; } - let remote = String::from_utf8_lossy(&output.stdout).trim().to_string(); - let key = github_repo_key_from_remote(&remote)?; - Some(LaunchContext::new("git", key, ContextConfidence::Weak).with_metadata("remote", remote)) + String::from_utf8_lossy(&output.stdout) + .lines() + .map(str::trim) + .filter(|name| !name.is_empty() && *name != "origin") + .find_map(|name| { + git_remote_url(cwd, name) + .filter(|remote| github_repo_name_from_remote(remote).is_some()) + }) +} + +fn git_remote_url(cwd: &Path, name: &str) -> Option { + let output = Command::new("git") + .args(["remote", "get-url", name]) + .current_dir(cwd) + .output() + .ok()?; + output + .status + .success() + .then(|| String::from_utf8_lossy(&output.stdout).trim().to_string()) + .filter(|remote| !remote.is_empty()) } fn github_repo_key_from_remote(remote: &str) -> Option { + github_repo_name_from_remote(remote).map(|repo| format!("github.com/{repo}")) +} + +fn github_repo_name_from_remote(remote: &str) -> Option { let mut value = remote.trim().trim_end_matches(".git").to_string(); if let Some(rest) = value.strip_prefix("git@github.com:") { value = rest.to_string(); @@ -494,7 +532,7 @@ fn github_repo_key_from_remote(remote: &str) -> Option { } let parts = value.split('/').collect::>(); (parts.len() >= 2 && !parts[0].is_empty() && !parts[1].is_empty()) - .then(|| format!("github.com/{}/{}", parts[0], parts[1])) + .then(|| format!("{}/{}", parts[0], parts[1])) } fn current_tty() -> Option { @@ -1302,6 +1340,39 @@ mod tests { github_repo_key_from_remote("git@github.com:dutifuldev/ghzinga.git"), Some("github.com/dutifuldev/ghzinga".into()) ); + assert_eq!( + github_repo_name_from_remote("ssh://git@github.com/dutifuldev/ghzinga.git"), + Some("dutifuldev/ghzinga".into()) + ); + } + + #[test] + fn github_repo_name_from_cwd_uses_available_github_remote() { + let dir = tempdir().unwrap(); + assert!(Command::new("git") + .arg("init") + .current_dir(dir.path()) + .output() + .unwrap() + .status + .success()); + assert!(Command::new("git") + .args([ + "remote", + "add", + "upstream", + "git@github.com:dutifuldev/ghzinga.git", + ]) + .current_dir(dir.path()) + .output() + .unwrap() + .status + .success()); + + assert_eq!( + github_repo_name_from_cwd(dir.path()), + Some("dutifuldev/ghzinga".into()) + ); } #[test] From bf3bd98844d97bb8addb4bb7e0a81b0ccd7dd041 Mon Sep 17 00:00:00 2001 From: Bob Date: Tue, 9 Jun 2026 14:10:12 +0800 Subject: [PATCH 2/2] test: refresh capture manifests for repo inference --- captures/ghzinga-issue-88499/large/manifest.json | 4 ++-- captures/ghzinga-issue-88499/manifest.json | 4 ++-- captures/ghzinga-issue-88499/medium/manifest.json | 4 ++-- captures/ghzinga-issue-88499/mouse-smoke/manifest.json | 4 ++-- captures/ghzinga-issue-88499/narrow/manifest.json | 4 ++-- captures/ghzinga-pr-81834/large/manifest.json | 4 ++-- captures/ghzinga-pr-81834/manifest.json | 4 ++-- captures/ghzinga-pr-81834/medium/manifest.json | 4 ++-- captures/ghzinga-pr-81834/mouse-smoke/manifest.json | 4 ++-- captures/ghzinga-pr-81834/narrow/manifest.json | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/captures/ghzinga-issue-88499/large/manifest.json b/captures/ghzinga-issue-88499/large/manifest.json index 25474b3f..5439e791 100644 --- a/captures/ghzinga-issue-88499/large/manifest.json +++ b/captures/ghzinga-issue-88499/large/manifest.json @@ -4,7 +4,7 @@ "title": "openai-responses provider: 404 on previous_response_id when store=false (default)", "mode": "issue", "binary": "target/debug/gzg", - "git_commit": "d1c4c23a3cc65a3dd83871080ad6fcf19be99d14", + "git_commit": "b5b380107ac995b3a2bae8bd03037e0f8e1188bd", "config_path": "captures/ghzinga-issue-88499/capture-empty-config.toml", "requested_columns": 160, "requested_rows": 50, @@ -113,5 +113,5 @@ } ], "actual_tmux_size": "160x50", - "app_tree_hash": "6ae1209dc8e8616c4c3261c38aa550b693d11b9c6052ad724339380e053c3813" + "app_tree_hash": "da9cc487fc389c235f2a0e7757d9db29532c8c3fca520e60c8da4b5f45d18cc7" } diff --git a/captures/ghzinga-issue-88499/manifest.json b/captures/ghzinga-issue-88499/manifest.json index 7db531b6..5fb7448b 100644 --- a/captures/ghzinga-issue-88499/manifest.json +++ b/captures/ghzinga-issue-88499/manifest.json @@ -3,7 +3,7 @@ "title": "openai-responses provider: 404 on previous_response_id when store=false (default)", "mode": "issue", "binary": "target/debug/gzg", - "git_commit": "d1c4c23a3cc65a3dd83871080ad6fcf19be99d14", + "git_commit": "b5b380107ac995b3a2bae8bd03037e0f8e1188bd", "config_path": "captures/ghzinga-issue-88499/capture-empty-config.toml", "offline_fixture": "fixtures/issue-88499.json", "offline_resource_fixtures": [], @@ -24,5 +24,5 @@ "rows": 50 } ], - "app_tree_hash": "6ae1209dc8e8616c4c3261c38aa550b693d11b9c6052ad724339380e053c3813" + "app_tree_hash": "da9cc487fc389c235f2a0e7757d9db29532c8c3fca520e60c8da4b5f45d18cc7" } diff --git a/captures/ghzinga-issue-88499/medium/manifest.json b/captures/ghzinga-issue-88499/medium/manifest.json index 2ceafbd5..adc506b1 100644 --- a/captures/ghzinga-issue-88499/medium/manifest.json +++ b/captures/ghzinga-issue-88499/medium/manifest.json @@ -4,7 +4,7 @@ "title": "openai-responses provider: 404 on previous_response_id when store=false (default)", "mode": "issue", "binary": "target/debug/gzg", - "git_commit": "d1c4c23a3cc65a3dd83871080ad6fcf19be99d14", + "git_commit": "b5b380107ac995b3a2bae8bd03037e0f8e1188bd", "config_path": "captures/ghzinga-issue-88499/capture-empty-config.toml", "requested_columns": 120, "requested_rows": 36, @@ -113,5 +113,5 @@ } ], "actual_tmux_size": "120x36", - "app_tree_hash": "6ae1209dc8e8616c4c3261c38aa550b693d11b9c6052ad724339380e053c3813" + "app_tree_hash": "da9cc487fc389c235f2a0e7757d9db29532c8c3fca520e60c8da4b5f45d18cc7" } diff --git a/captures/ghzinga-issue-88499/mouse-smoke/manifest.json b/captures/ghzinga-issue-88499/mouse-smoke/manifest.json index 8e5ec2e6..b5270c5d 100644 --- a/captures/ghzinga-issue-88499/mouse-smoke/manifest.json +++ b/captures/ghzinga-issue-88499/mouse-smoke/manifest.json @@ -5,7 +5,7 @@ "fixtures/issue-66943.json" ], "binary": "target/debug/gzg", - "git_commit": "d1c4c23a3cc65a3dd83871080ad6fcf19be99d14", + "git_commit": "b5b380107ac995b3a2bae8bd03037e0f8e1188bd", "config_path": "captures/ghzinga-issue-88499/mouse-smoke/capture-empty-config.toml", "command": "cd . && TERM=xterm-256color GZG_CONFIG_PATH=./captures/ghzinga-issue-88499/mouse-smoke/capture-empty-config.toml GZG_STATE_HOME=./captures/ghzinga-issue-88499/mouse-smoke/.capture-state GZG_CACHE_HOME=./captures/ghzinga-issue-88499/mouse-smoke/.capture-cache BROWSER=./captures/ghzinga-issue-88499/mouse-smoke/capture-open-url.sh GZG_COPY_COMMAND=./captures/ghzinga-issue-88499/mouse-smoke/capture-copy-url.sh ./target/debug/gzg https://github.com/openclaw/openclaw/issues/88499 --offline-fixture ./captures/ghzinga-issue-88499/mouse-smoke/navigation-fixture.json --offline-resource-fixture ./fixtures/issue-66943.json --no-restore --refresh-seconds 0", "actual_tmux_size": "120x36", @@ -120,5 +120,5 @@ "ansi": "70_mouse_quit_confirm.ansi" } ], - "app_tree_hash": "6ae1209dc8e8616c4c3261c38aa550b693d11b9c6052ad724339380e053c3813" + "app_tree_hash": "da9cc487fc389c235f2a0e7757d9db29532c8c3fca520e60c8da4b5f45d18cc7" } diff --git a/captures/ghzinga-issue-88499/narrow/manifest.json b/captures/ghzinga-issue-88499/narrow/manifest.json index 48179564..82901c52 100644 --- a/captures/ghzinga-issue-88499/narrow/manifest.json +++ b/captures/ghzinga-issue-88499/narrow/manifest.json @@ -4,7 +4,7 @@ "title": "openai-responses provider: 404 on previous_response_id when store=false (default)", "mode": "issue", "binary": "target/debug/gzg", - "git_commit": "d1c4c23a3cc65a3dd83871080ad6fcf19be99d14", + "git_commit": "b5b380107ac995b3a2bae8bd03037e0f8e1188bd", "config_path": "captures/ghzinga-issue-88499/capture-empty-config.toml", "requested_columns": 80, "requested_rows": 24, @@ -113,5 +113,5 @@ } ], "actual_tmux_size": "80x24", - "app_tree_hash": "6ae1209dc8e8616c4c3261c38aa550b693d11b9c6052ad724339380e053c3813" + "app_tree_hash": "da9cc487fc389c235f2a0e7757d9db29532c8c3fca520e60c8da4b5f45d18cc7" } diff --git a/captures/ghzinga-pr-81834/large/manifest.json b/captures/ghzinga-pr-81834/large/manifest.json index 527b9ab4..5624fef6 100644 --- a/captures/ghzinga-pr-81834/large/manifest.json +++ b/captures/ghzinga-pr-81834/large/manifest.json @@ -4,7 +4,7 @@ "title": "feat(senseaudio): add SenseAudio TTS provider", "mode": "pr", "binary": "target/debug/gzg", - "git_commit": "d1c4c23a3cc65a3dd83871080ad6fcf19be99d14", + "git_commit": "b5b380107ac995b3a2bae8bd03037e0f8e1188bd", "config_path": "captures/ghzinga-pr-81834/capture-empty-config.toml", "requested_columns": 160, "requested_rows": 50, @@ -183,5 +183,5 @@ } ], "actual_tmux_size": "160x50", - "app_tree_hash": "6ae1209dc8e8616c4c3261c38aa550b693d11b9c6052ad724339380e053c3813" + "app_tree_hash": "da9cc487fc389c235f2a0e7757d9db29532c8c3fca520e60c8da4b5f45d18cc7" } diff --git a/captures/ghzinga-pr-81834/manifest.json b/captures/ghzinga-pr-81834/manifest.json index 8ea3271d..e8388b40 100644 --- a/captures/ghzinga-pr-81834/manifest.json +++ b/captures/ghzinga-pr-81834/manifest.json @@ -3,7 +3,7 @@ "title": "feat(senseaudio): add SenseAudio TTS provider", "mode": "pr", "binary": "target/debug/gzg", - "git_commit": "d1c4c23a3cc65a3dd83871080ad6fcf19be99d14", + "git_commit": "b5b380107ac995b3a2bae8bd03037e0f8e1188bd", "config_path": "captures/ghzinga-pr-81834/capture-empty-config.toml", "offline_fixture": null, "offline_resource_fixtures": [], @@ -24,5 +24,5 @@ "rows": 50 } ], - "app_tree_hash": "6ae1209dc8e8616c4c3261c38aa550b693d11b9c6052ad724339380e053c3813" + "app_tree_hash": "da9cc487fc389c235f2a0e7757d9db29532c8c3fca520e60c8da4b5f45d18cc7" } diff --git a/captures/ghzinga-pr-81834/medium/manifest.json b/captures/ghzinga-pr-81834/medium/manifest.json index 5ced4d4b..eb4890b3 100644 --- a/captures/ghzinga-pr-81834/medium/manifest.json +++ b/captures/ghzinga-pr-81834/medium/manifest.json @@ -4,7 +4,7 @@ "title": "feat(senseaudio): add SenseAudio TTS provider", "mode": "pr", "binary": "target/debug/gzg", - "git_commit": "d1c4c23a3cc65a3dd83871080ad6fcf19be99d14", + "git_commit": "b5b380107ac995b3a2bae8bd03037e0f8e1188bd", "config_path": "captures/ghzinga-pr-81834/capture-empty-config.toml", "requested_columns": 120, "requested_rows": 36, @@ -183,5 +183,5 @@ } ], "actual_tmux_size": "120x36", - "app_tree_hash": "6ae1209dc8e8616c4c3261c38aa550b693d11b9c6052ad724339380e053c3813" + "app_tree_hash": "da9cc487fc389c235f2a0e7757d9db29532c8c3fca520e60c8da4b5f45d18cc7" } diff --git a/captures/ghzinga-pr-81834/mouse-smoke/manifest.json b/captures/ghzinga-pr-81834/mouse-smoke/manifest.json index fe210ad8..e75ebd8c 100644 --- a/captures/ghzinga-pr-81834/mouse-smoke/manifest.json +++ b/captures/ghzinga-pr-81834/mouse-smoke/manifest.json @@ -5,7 +5,7 @@ "fixtures/issue-66943.json" ], "binary": "target/debug/gzg", - "git_commit": "d1c4c23a3cc65a3dd83871080ad6fcf19be99d14", + "git_commit": "b5b380107ac995b3a2bae8bd03037e0f8e1188bd", "config_path": "captures/ghzinga-pr-81834/mouse-smoke/capture-empty-config.toml", "command": "cd . && TERM=xterm-256color GZG_CONFIG_PATH=./captures/ghzinga-pr-81834/mouse-smoke/capture-empty-config.toml GZG_STATE_HOME=./captures/ghzinga-pr-81834/mouse-smoke/.capture-state GZG_CACHE_HOME=./captures/ghzinga-pr-81834/mouse-smoke/.capture-cache BROWSER=./captures/ghzinga-pr-81834/mouse-smoke/capture-open-url.sh GZG_COPY_COMMAND=./captures/ghzinga-pr-81834/mouse-smoke/capture-copy-url.sh ./target/debug/gzg 'openclaw/openclaw#81834' --offline-fixture ./captures/ghzinga-pr-81834/mouse-smoke/navigation-fixture.json --offline-resource-fixture ./fixtures/issue-66943.json --no-restore --refresh-seconds 0", "actual_tmux_size": "120x36", @@ -240,5 +240,5 @@ ], "load_full_fixture": "captures/ghzinga-pr-81834/mouse-smoke/load-full-fixture.json", "load_full_command": "cd . && TERM=xterm-256color GZG_CONFIG_PATH=./captures/ghzinga-pr-81834/mouse-smoke/capture-empty-config.toml GZG_STATE_HOME=./captures/ghzinga-pr-81834/mouse-smoke/.capture-state GZG_CACHE_HOME=./captures/ghzinga-pr-81834/mouse-smoke/.capture-cache ./target/debug/gzg 'openclaw/openclaw#81834' --offline-fixture ./captures/ghzinga-pr-81834/mouse-smoke/load-full-fixture.json --no-restore --refresh-seconds 0", - "app_tree_hash": "6ae1209dc8e8616c4c3261c38aa550b693d11b9c6052ad724339380e053c3813" + "app_tree_hash": "da9cc487fc389c235f2a0e7757d9db29532c8c3fca520e60c8da4b5f45d18cc7" } diff --git a/captures/ghzinga-pr-81834/narrow/manifest.json b/captures/ghzinga-pr-81834/narrow/manifest.json index 68610539..79c91a5f 100644 --- a/captures/ghzinga-pr-81834/narrow/manifest.json +++ b/captures/ghzinga-pr-81834/narrow/manifest.json @@ -4,7 +4,7 @@ "title": "feat(senseaudio): add SenseAudio TTS provider", "mode": "pr", "binary": "target/debug/gzg", - "git_commit": "d1c4c23a3cc65a3dd83871080ad6fcf19be99d14", + "git_commit": "b5b380107ac995b3a2bae8bd03037e0f8e1188bd", "config_path": "captures/ghzinga-pr-81834/capture-empty-config.toml", "requested_columns": 80, "requested_rows": 24, @@ -183,5 +183,5 @@ } ], "actual_tmux_size": "80x24", - "app_tree_hash": "6ae1209dc8e8616c4c3261c38aa550b693d11b9c6052ad724339380e053c3813" + "app_tree_hash": "da9cc487fc389c235f2a0e7757d9db29532c8c3fca520e60c8da4b5f45d18cc7" }