Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ versioning theo [SemVer](https://semver.org). **8sync rule:** mỗi PR cập nh

## [Unreleased]

## [0.110.67] — 2026-10-22
### Fixed
- **Sweep zombie của `shot` giết nhầm shot chạy song song** (v0.110.64/.65 khớp mọi chromium `8sync-shot-*` → 2 phòng shot cùng lúc giết nhau, card #184/#185 "8sync shot fails on all WebGL pages" thiếu bằng chứng QA): giờ chỉ kill chromium mồ côi THẬT — pid cha đã chết (8sync chết giữa render). Shot sống (bất kỳ tuổi, kể cả song song) không bao giờ bị đụng. HQ auto-tick dùng cùng luật mồ côi.
## [0.110.66] — 2026-10-22
### Fixed
- **Critic sweep đụng phòng của dự án KHÔNG chạy auto** (owner: "không gửi nhầm inbox các dự án không phải chế độ 8sync ccc auto"): `sweepStuckAsks` quét mọi phòng trên máy rồi nhắn tin + đóng dialog hỏi — giờ lọc đúng `inAutoScope` + bỏ dự án bị ghim nghỉ, cùng luật với auto-tick. Rust (`ccc msg`, ship-fast/loop, relay_stuck) đã root-scope sẵn, không đổi.
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ resolver = "2"
members = ["crates/cli", "crates/ccc-core"]

[workspace.package]
version = "0.110.66"
version = "0.110.67"
edition = "2021"
license = "PolyForm-Noncommercial-1.0.0"
authors = ["8sync-dev <[email protected]>"]
Expand Down
5 changes: 3 additions & 2 deletions apps/hq-ui/lib/server/auto-tick.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,11 @@ async function tickOnce(status: AutoStatus, now: number): Promise<TickResult> {
void run("8sync", ["ccc", "auto", "revive"], REVIVE_MS);
// Headless Chromium left by an `8sync shot` whose 8sync died mid-render (a guard pause
// kills the room's shell tree; Chromium's children survive and burn GPU for hours —
// 2026-10-22, 47% GPU). One sweep per revive minute; live shots are younger than that.
// 2026-10-22, 47% GPU). Orphan rule only: the parent pid is gone; a live shot (any age,
// also a concurrent one) keeps its parent chain and is never touched.
void run(
"powershell",
["-NoProfile", "-Command", `Get-CimInstance Win32_Process -Filter "Name='chrome.exe'" | Where-Object { $_.CommandLine -like '*8sync-shot-*' -and $_.CreationDate -lt (Get-Date).AddMinutes(-10) } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }`],
["-NoProfile", "-Command", `$p = Get-CimInstance Win32_Process; $alive = @({} + $p.ProcessId); $p | Where-Object { $_.Name -eq 'chrome.exe' -and $_.CommandLine -like '*8sync-shot-*' -and -not $alive.Contains($_.ParentProcessId) } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }`],
REVIVE_MS,
).catch(() => {});
}
Expand Down
2 changes: 1 addition & 1 deletion assets/claude/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "8sync-kit",
"displayName": "8sync kit",
"version": "0.110.66",
"version": "0.110.67",
"description": "8 Sync kit for Claude Code: role-routed subagents (explore, task, quick-task, reviewer, designer, researcher, verifier, pm, architect, qa, critic) and the /ship /rules /sec /harden skills. Hooks, rules and the full skill set come from `8sync ccc kit`.",
"author": { "name": "8 Sync", "url": "https://8syncdev.com" },
"homepage": "https://get.8syncdev.com",
Expand Down
17 changes: 11 additions & 6 deletions crates/cli/src/verbs/shot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,15 @@ const SHOT_MARK: &str = "8sync-shot-";
/// Kill Chromium processes left over from earlier shots whose `8sync` died mid-render (the auto
/// guard pausing a room kills the room's shell tree; Chromium's children survive it and a stuck one
/// burned ~20% GPU for hours, 2026-10-22). Ours (`keep`) is spared. Best effort, never fails a shot.
fn sweep_zombies(keep: &std::path::Path) {
let keep = keep.display().to_string();
fn sweep_zombies(_keep: &std::path::Path) {
// Only true orphans: a marker Chromium whose parent pid is gone (the `8sync shot` that spawned
// it died — e.g. the RAM guard paused the room mid-render). A LIVE shot's Chromium keeps its
// parent chain, so concurrent shots (two rooms shooting at once, 2026-10-22) never kill each
// other — the v0.110.64 sweep matched every marker and did exactly that.
#[cfg(windows)]
{
let script = format!(
"Get-CimInstance Win32_Process -Filter \"Name='chrome.exe'\" | Where-Object {{ $_.CommandLine -like '*{SHOT_MARK}*' -and -not ($_.CommandLine -like '*{keep}*') }} | ForEach-Object {{ Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }}"
"$p = Get-CimInstance Win32_Process; $alive = @({{ }} + $p.ProcessId); $p | Where-Object {{ $_.Name -eq 'chrome.exe' -and $_.CommandLine -like '*{SHOT_MARK}*' -and -not $alive.Contains($_.ParentProcessId) }} | ForEach-Object {{ Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }}"
);
let _ = Command::new("powershell")
.args(["-NoProfile", "-Command", &script])
Expand All @@ -232,12 +235,14 @@ fn sweep_zombies(keep: &std::path::Path) {
}
#[cfg(not(windows))]
{
let _ = Command::new("pkill")
.args(["-f", &format!("chrome.*{SHOT_MARK}")])
// Kill a marker Chromium only when its parent pid is gone (a live shot keeps its parent
// chain; concurrent shots never touch each other).
let _ = Command::new("sh")
.arg("-c")
.arg(format!("ps -eo pid=,ppid=,args= | grep '[c]hrome.*{SHOT_MARK}' | while read pid ppid rest; do kill -0 \"$ppid\" 2>/dev/null || kill \"$pid\" 2>/dev/null || true; done"))
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.status();
let _ = keep;
}
}

Expand Down
Loading