Merge jobdori/parity-followup: bash validation module + output truncation

This commit is contained in:
Jobdori
2026-04-03 19:35:11 +09:00
4 changed files with 1061 additions and 6 deletions

View File

@@ -39,7 +39,7 @@ Canonical scenario map: `rust/mock_parity_scenarios.json`
| Lane | Status | Feature commit | Merge commit | Evidence |
|---|---|---|---|---|
| 1. Bash validation | branch-only | `36dac6c` | | `jobdori/bash-validation-submodules`, `rust/crates/runtime/src/bash_validation.rs` (`+1005` on branch) |
| 1. Bash validation | merged | `36dac6c` | `1cfd78a` | `jobdori/bash-validation-submodules`, `rust/crates/runtime/src/bash_validation.rs` (`+1004` on `main`) |
| 2. CI fix | merged | `89104eb` | `f1969ce` | `rust/crates/runtime/src/sandbox.rs` (`+22/-1`) |
| 3. File-tool | merged | `284163b` | `a98f2b6` | `rust/crates/runtime/src/file_ops.rs` (`+195/-1`) |
| 4. TaskRegistry | merged | `5ea138e` | `21a1e1d` | `rust/crates/runtime/src/task_registry.rs` (`+336`) |
@@ -171,17 +171,17 @@ Canonical scenario map: `rust/mock_parity_scenarios.json`
## Still open
- [ ] End-to-end MCP runtime lifecycle beyond the registry bridge now on `main`
- [ ] Output truncation (large stdout/file content)
- [x] Output truncation (large stdout/file content)
- [ ] Session compaction behavior matching
- [ ] Token counting / cost tracking accuracy
- [ ] Bash validation lane merged onto `main`
- [x] Bash validation lane merged onto `main`
- [ ] CI green on every commit
## Migration Readiness
- [x] `PARITY.md` maintained and honest
- [x] 9 requested lanes documented with commit hashes and current status
- [ ] All 9 requested lanes landed on `main` (`bash-validation` is still branch-only)
- [x] All 9 requested lanes landed on `main` (`bash-validation` is still branch-only)
- [x] No `#[ignore]` tests hiding failures
- [ ] CI green on every commit
- [x] Codebase shape clean enough for handoff documentation

View File

@@ -134,8 +134,8 @@ async fn execute_bash_async(
};
let (output, interrupted) = output_result;
let stdout = String::from_utf8_lossy(&output.stdout).into_owned();
let stderr = String::from_utf8_lossy(&output.stderr).into_owned();
let stdout = truncate_output(&String::from_utf8_lossy(&output.stdout));
let stderr = truncate_output(&String::from_utf8_lossy(&output.stderr));
let no_output_expected = Some(stdout.trim().is_empty() && stderr.trim().is_empty());
let return_code_interpretation = output.status.code().and_then(|code| {
if code == 0 {
@@ -281,3 +281,53 @@ mod tests {
assert!(!output.sandbox_status.expect("sandbox status").enabled);
}
}
/// Maximum output bytes before truncation (16 KiB, matching upstream).
const MAX_OUTPUT_BYTES: usize = 16_384;
/// Truncate output to `MAX_OUTPUT_BYTES`, appending a marker when trimmed.
fn truncate_output(s: &str) -> String {
if s.len() <= MAX_OUTPUT_BYTES {
return s.to_string();
}
// Find the last valid UTF-8 boundary at or before MAX_OUTPUT_BYTES
let mut end = MAX_OUTPUT_BYTES;
while end > 0 && !s.is_char_boundary(end) {
end -= 1;
}
let mut truncated = s[..end].to_string();
truncated.push_str("\n\n[output truncated — exceeded 16384 bytes]");
truncated
}
#[cfg(test)]
mod truncation_tests {
use super::*;
#[test]
fn short_output_unchanged() {
let s = "hello world";
assert_eq!(truncate_output(s), s);
}
#[test]
fn long_output_truncated() {
let s = "x".repeat(20_000);
let result = truncate_output(&s);
assert!(result.len() < 20_000);
assert!(result.ends_with("[output truncated — exceeded 16384 bytes]"));
}
#[test]
fn exact_boundary_unchanged() {
let s = "a".repeat(MAX_OUTPUT_BYTES);
assert_eq!(truncate_output(&s), s);
}
#[test]
fn one_over_boundary_truncated() {
let s = "a".repeat(MAX_OUTPUT_BYTES + 1);
let result = truncate_output(&s);
assert!(result.contains("[output truncated"));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
mod bash;
pub mod bash_validation;
mod bootstrap;
mod compact;
mod config;