feat(session): record csa_version + tool_version in session state (#714)#967
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces version tracking for both the CSA binary and the individual tools used within a session. It adds a csa_version field to the session state and a tool_version field to the tool state, with logic to automatically detect and persist these versions. The session list command has been updated with --csa-version and --show-version flags to filter and display this information. Additionally, tool state initialization was refactored into a separate module. Feedback suggests refactoring the tool state initialization to use the entry API for better clarity and replacing manual version string parsing with a regular expression for improved maintainability.
| dirty = true; | ||
| } | ||
|
|
||
| if let Some(tool_state) = session.tools.get_mut(&tool_name) { |
There was a problem hiding this comment.
| fn parse_first_numeric_version_token(text: &str) -> Option<String> { | ||
| let bytes = text.as_bytes(); | ||
| let mut idx = 0; | ||
|
|
||
| while idx < bytes.len() { | ||
| let ch = text[idx..].chars().next()?; | ||
| let ch_len = ch.len_utf8(); | ||
| let next_is_digit = text[idx + ch_len..] | ||
| .chars() | ||
| .next() | ||
| .is_some_and(|next| next.is_ascii_digit()); | ||
| if ch.is_ascii_digit() || ((ch == 'v' || ch == 'V') && next_is_digit) { | ||
| let start = if ch.is_ascii_digit() { idx } else { idx + ch_len }; | ||
| let mut end = start; | ||
| while end < bytes.len() { | ||
| let current = text[end..].chars().next()?; | ||
| if current.is_ascii_alphanumeric() || matches!(current, '.' | '-' | '_' | '+') { | ||
| end += current.len_utf8(); | ||
| } else { | ||
| break; | ||
| } | ||
| } | ||
| if end > start { | ||
| let candidate = &text[start..end]; | ||
| if candidate.chars().next().is_some_and(|c| c.is_ascii_digit()) { | ||
| return Some(candidate.to_string()); | ||
| } | ||
| } | ||
| } | ||
| idx += ch_len; | ||
| } | ||
|
|
||
| None | ||
| } |
There was a problem hiding this comment.
This manual parsing of the version string is complex and can be simplified using a regular expression. Since the regex crate is already a dependency of this crate, using it here would improve readability and maintainability without adding new dependencies.
fn parse_first_numeric_version_token(text: &str) -> Option<String> {
use once_cell::sync::Lazy;
use regex::Regex;
// This regex finds a version string, optionally prefixed with 'v' or 'V'.
// It captures the version number itself, which must start with a digit.
static VERSION_RE: Lazy<Regex> = Lazy::new(|| {
Regex::new(r"\b(?:v|V)?(?<version>\d[a-zA-Z0-9._+-]*)").unwrap()
});
VERSION_RE
.captures(text)
.and_then(|caps| caps.name("version").map(|m| m.as_str().to_string()))
}There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 85be157606
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| "Version probe timed out" | ||
| ); | ||
| return None; |
There was a problem hiding this comment.
Terminate timed-out version probes
If the --version probe times out, this branch logs and returns without terminating the spawned child process. In Tokio, timing out the wait future does not guarantee the subprocess exits, so a tool that blocks on --version (e.g., interactive wrapper or broken install) can leave orphaned processes on each execution path that initializes tool state, eventually consuming process/PID resources.
Useful? React with 👍 / 👎.
85be157 to
51bbf81
Compare
Sessions now persist the CSA binary version (`csa_version`, from
env!("CARGO_PKG_VERSION")) on creation and a best-effort tool version
(`tool_version` under each `[tools.<name>]`) captured at tool init
via a `--version` probe. Both fields are Option<String> and default
to None for backward compatibility — pre-feature session state files
deserialize silently.
`csa session list --csa-version <X>` filters sessions by recorded
binary version. More granular queries (range filters, tool-version
filter, sort-by) and the companion bisect-regression skill are
deferred to followups.
Closes #714.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
51bbf81 to
6a1904d
Compare
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces version tracking for the CSA binary and external tools. It adds a csa_version field to the session state and a tool_version field to the tool state, implementing logic to automatically detect tool versions via a --version probe. The session list command now supports filtering by CSA version and toggling a version column. Additionally, the PR refactors several test suites into separate files and increments the project version to 0.1.451. I have no feedback to provide.
Audit Trail — Merge Rationale (Severity-Tiered Protocol)Local pre-PR review (session `01KPP2SW129970ZNN9BS6MMM1Q`): verdict=fail/HAS_ISSUES but `findings=[]` and zero severity counts — classic parser FP. Cloud bot review (round 0):
Cloud bot review (round 1, after fix):
CI: All green. Test(macos-latest) FAILURE is pre-existing baseline per memory Dismissed MEDIUMs: gemini's if-let/regex suggestions are stylistic nits on an already-readable parser. Not blocking per severity-tiered protocol. Not filing followup — pure style, no correctness impact. Merging. |
Summary
csa_version(top-level) fromenv!("CARGO_PKG_VERSION")and a best-efforttool_versionper[tools.<name>]captured via a--versionprobe at tool init.Option<String>withskip_serializing_if— older session state files deserialize silently asNone.csa session list --csa-version <X>filters sessions by the recorded binary version. Range filters, tool-version filter, sort-by, and the companion bisect-regression skill are deferred to followups.Test plan
cargo test -p csa-session --releaseexit 0 (320 passed)cargo test -p cli-sub-agent --release -- --skip gate --skip lefthookexit 0 (1411 passed, 53 filtered out — pre-existing lefthook-test hygiene issue not introduced here)Closes #714.
🤖 Generated with Claude Code