From 39ed402958cd7374c588c73abccf315f7c8e40b9 Mon Sep 17 00:00:00 2001 From: Bhada Yun Date: Mon, 18 May 2026 16:57:54 +0200 Subject: [PATCH] release v0.3.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the workspace to 0.3.0 — the 0.x minor (rather than 0.2.10 patch) is motivated by the breaking signature change to `pcr_core::config::pcr_dir()` from #86 (returns `Result` instead of `PathBuf`). The CLI surface (`pcr ` flags / exit codes / output format) is unchanged. Version touchpoints: * `Cargo.toml` workspace.package.version → 0.3.0 * `crates/pcr-napi/package.json` version + all 4 optionalDependencies * `crates/pcr-napi/npm/{darwin-arm64,darwin-x64,linux-x64-gnu, win32-x64-msvc}/package.json` versions * `README.md` TUI mock version stamp * `CHANGELOG.md` `[Unreleased]` promoted to `[0.3.0] — 2026-05-18` with full release notes catalogued by PR (#85, #86, #87, #88) and grouped Added / Changed / Fixed / Tests. Workspace verification: * `cargo fmt --all --check` clean * `cargo clippy --workspace --all-targets -- -D warnings` clean * `cargo test --workspace` — 153 passing, 0 failing (was 128 on the v0.2.9 baseline; +25 across the 4 merged PRs) * `cargo build -p pcr-cli --release` → `pcr 0.3.0 (rust)` After this lands on `main`, the release commit is tagged `v0.3.0` locally and pushed; that triggers the release workflow which publishes npm + builds binaries + dispatches the homebrew formula update. Co-authored-by: Cursor --- CHANGELOG.md | 165 +++++++++++++----- Cargo.toml | 2 +- README.md | 2 +- crates/pcr-napi/npm/darwin-arm64/package.json | 2 +- crates/pcr-napi/npm/darwin-x64/package.json | 2 +- .../pcr-napi/npm/linux-x64-gnu/package.json | 2 +- .../pcr-napi/npm/win32-x64-msvc/package.json | 2 +- crates/pcr-napi/package.json | 10 +- 8 files changed, 130 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cd64ce..32480a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,59 +10,132 @@ the `pcr-dev@X.Y.Z` npm dist-tag. ## [Unreleased] +## [0.3.0] — 2026-05-18 + +This release rolls up the in-flight watcher / dedup / packaging work +from PRs #85, #86, #87, and #88. The 0.3.0 minor bump (rather than +0.2.10) is motivated by the **public API change in pcr-core**: +`config::pcr_dir()` now returns `Result` instead of `PathBuf` +(see #86). The CLI surface (`pcr ` shapes, flags, exit codes, +output format) is unchanged. + ### Added -- **Update-available notice on `pcr` runs.** Every interactive command - now does a best-effort background check against the npm registry's - `pcr-dev@latest` and prints a soft "X is available" notice at the end - of the command if a newer version exists. The check is throttled - (registry hit at most once per 24h, notice shown at most once per 1h), - cached in `~/.pcr-dev/update-check.json`, and never blocks the - command. Suggested upgrade command is install-method-aware: +- **Update-available notice on `pcr` runs** ([#87]). Every interactive + command now does a best-effort background check against the npm + registry's `pcr-dev@latest` and prints a soft "X is available" + notice at the end of the command if a newer version exists. The + check is throttled (registry hit at most once per 24 h, notice + shown at most once per 1 h), cached in + `~/.pcr-dev/update-check.json`, and never blocks the command. + Suggested upgrade command is install-method-aware: `brew upgrade pcr` for Homebrew installs, `npm i -g pcr-dev@latest` - for npm installs. Opt out with `PCR_NO_UPDATE_CHECK=1` (also skipped - automatically when `CI` is set, when `--json` is used, and for the - internal `hook` and `mcp` subcommands). + for npm installs. Opt out with `PCR_NO_UPDATE_CHECK=1` (also + skipped automatically when `CI` is set, when `--json` is used, and + for the internal `hook` and `mcp` subcommands). +- **`NOTICE` file** ([#88]) carrying the project's copyright + assertion (`Copyright 2026 PCR.dev`) per Apache 2.0 §4(d). +- **`CHANGELOG.md`** ([#87]) — this file. Previously the CLI repo + had no curated changelog; release notes lived only in commit + messages and PR bodies. -### Fixed +### Changed + +- **Public API:** `pcr_core::config::pcr_dir()` now returns + `Result` instead of `PathBuf` ([#86]). Callers that + previously took a `PathBuf` from this function need to use `?` / + `match` / `.ok()`. The runtime contract on a well-configured Unix + or Windows machine is unchanged (the `Err` branch only fires + inside sandboxes / containers where neither `$HOME` nor + `%USERPROFILE%` resolves). +- **Cursor watcher periodic scan** ([#86]): interval bumped from + 20 s to 60 s. The `notify`-driven path is unchanged and still + delivers ~600 ms end-to-end pickup latency; the periodic loop is + now strictly a safety net for notify-misses. -The following items are in-flight as separate PRs and will be folded -into the next release when those land: +### Fixed -- **#85 — VS Code Copilot Chat dual-watch dedup.** When both +- **VS Code Copilot Chat dual-watch dedup** ([#85]). When both `chatSessions/` and the legacy `transcripts/` directory exist on - disk (the upgrade window for VS Code 0.45+), the watcher now scopes - itself to `chatSessions/` only, so the same prompt is no longer - ingested twice. Also normalises `captured_at` formatting in the V2 - content hash so timestamp-only differences ("Z" vs "+00:00", millis - vs micros) collapse to the same `prompt_id_v2`. Ships with a - one-shot DB cleanup migration in the `functions` repo - (`20260518000000_dedupe_vscode_prompts.sql`). -- **#86 — Watcher correctness + perf.** Seven fixes from the recent - audit: - - `pcr start` Ctrl-C now triggers cooperative shutdown across every - long-running scan loop (cursor watcher, session-state watcher, - diff tracker) — was previously SIGINT-with-leaked-PID-file. - - `update_draft_response` is scoped to the single most recent row - matching `(session_id, prompt_text)`, fixing the silent overwrite - when the same prompt text re-appears in one session ("go", - "continue", "yes"). - - Cursor watcher walks are skipped entirely when neither the - top-level dir mtime nor the notify-pending flag indicate new - activity, with per-file mtime cache to skip already-parsed files - on the cold path. Periodic interval bumped 20 s → 60 s. - - `gc::orphaned` batches its existence checks into a single - `git cat-file --batch-check` per repo, replacing O(N) one-shot - subprocesses. - - `pcr_dir()` now returns `Result` and surfaces a clear - "set HOME and re-run" error instead of silently writing auth + - SQLite to `/tmp` when no home directory can be resolved. - - Claude Code state cursor advances only after a successful parse, - so a transient JSONL truncation no longer drops unprocessed - lines. - - Byte-slicing on user-supplied IDs replaced with `chars().take(N)` - in `commands/log.rs::short_sha` and the session-state-watcher - short-id log line — matches the `truncate_diff` fix from #85. + disk (the upgrade window for VS Code 0.45+), the watcher now + scopes itself to `chatSessions/` only, so the same prompt is no + longer ingested twice. Also normalises `captured_at` formatting in + the V2 content hash so timestamp-only differences ("Z" vs + "+00:00", millis vs micros) collapse to the same `prompt_id_v2`. + Ships with a one-shot DB cleanup migration in the `functions` repo + (`20260518000000_dedupe_vscode_prompts.sql`) for rows already + double-written before this release. +- **`pcr start` graceful shutdown** ([#86]). The Ctrl-C handler was + installed inside `wait_for_shutdown` — i.e. after PID-file write + and after `spawn_all_sources`. SIGINT in that window killed the + process with `W_TERMSIG(SIGINT)` and leaked the PID file. New + `crate::shutdown` module wires a cooperative flag through every + long-running scan loop (`cursor::watcher`, + `session_state_watcher`, `diff_tracker`); the handler is installed + at the very top of `commands::start::run` before any setup work. +- **`update_draft_response` overwrote multiple rows** ([#86]). The + unscoped `UPDATE drafts WHERE session_id=? AND prompt_text=?` was + overwriting every row with that `(session, prompt)` pair, so + identical re-sent prompts ("go", "continue", "yes") had their + earlier responses stomped by later turns. Now scoped to the single + most recent matching row via `SELECT id ... LIMIT 1` + `UPDATE + WHERE id = ?`. +- **`gc::orphaned` batched `git cat-file`** ([#86]). Was spawning one + `git cat-file -e ` per unpushed commit (O(N) processes per + GC pass). Now a single `git cat-file --batch-check` invocation per + repo: pipe every SHA on stdin, parse ` missing` / + ` ` on stdout. +- **`pcr_dir()` no longer silently falls back to `/tmp`** ([#86]). + Previously did `dirs::home_dir().unwrap_or_else(env::temp_dir)`, + silently writing auth + SQLite + watcher state under `/tmp` + whenever `$HOME` / `%USERPROFILE%` couldn't be resolved. Drafts + and login evaporated on reboot. Now returns `anyhow::Result` + with a clear "set HOME and re-run" error. +- **Claude Code state cursor ordering** ([#86]). `state.set(file_path, + lines)` ran before the parse — a transient parse failure (corrupt + JSONL, mid-write truncation) advanced the cursor without saving + anything, so unprocessed lines were lost until a full re-scan + (which never happens in steady state). Moved `state.set` to after + the `prompts.is_empty()` check. +- **Byte-slicing on IDs** ([#86]). Two spots (`commands/log.rs::short_sha` + and `cursor::session_state_watcher` short-id log line) still + byte-sliced on text we didn't allocate — composer IDs are UUIDs + in practice but any future non-ASCII tag would have panicked. + Switched to `chars().take(N).collect::()`, matching the + `truncate_diff` fix from #85. +- **Cursor watcher full-walk on every tick** ([#86]). The 20 s + periodic `WalkDir` was CPU/disk-heavy at scale and re-processed + every transcript on every pass. Now tracks top-level dir mtime + plus a `notify_event_pending` flag; on the periodic tick, the walk + is skipped entirely when neither signal indicates new activity. + When a walk does run, per-file mtime cache skips `process_session` + for paths whose mtime hasn't moved. +- **`LICENSE` no longer detects as "Other"** ([#88]). The previous + file had dozens of substantive wording deviations from canonical + Apache 2.0 (likely an old reformatter pass). Replaced with the + verbatim `apache.org/licenses/LICENSE-2.0.txt` (11,358 bytes, + byte-identical to upstream). GitHub now correctly reports the + repo as Apache-2.0 in the sidebar and in the API. Existing + `Cargo.toml` and `package.json` SPDX identifiers were already + correct — no functional change to the license. + +### Tests + +- Workspace test count: 128 (v0.2.9 baseline) → **153** passing, + 0 failures. Net additions: + - 11 new tests across #86's seven fixes (`start_graceful_shutdown`, + `drafts_update_response_scoped`, `claudecode_state_ordering`, + `gc::orphaned --batch-check` parsing, mtime-cache, `pcr_dir` + error-branch, byte-slicing fallback). + - 1 new test in #85 (`v2_hash_normalizes_captured_at_format`). + - 6 new tests in #87 (`update_check::tests::*`: semver compare + happy / prerelease / malformed, cache roundtrip, forward-compat + cache deserialisation, quiet-subcommand skip). + +[#85]: https://github.com/pcr-developers/cli/pull/85 +[#86]: https://github.com/pcr-developers/cli/pull/86 +[#87]: https://github.com/pcr-developers/cli/pull/87 +[#88]: https://github.com/pcr-developers/cli/pull/88 ## [0.2.9] — 2026-05-17 diff --git a/Cargo.toml b/Cargo.toml index 888323f..11e1086 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ members = [ ] [workspace.package] -version = "0.2.9" +version = "0.3.0" edition = "2021" license = "Apache-2.0" repository = "https://github.com/pcr-developers/cli" diff --git a/README.md b/README.md index 2e250ef..64e0a7c 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ Run `pcr --help` for examples. Full reference at [pcr.dev/docs](https://pc registered projects, the live event log, and the draft → bundled → pushed pipeline: ```text -PCR.dev · start · v0.2.9 ✓ bhada@pcr.dev 14:08:42 +PCR.dev · start · v0.3.0 ✓ bhada@pcr.dev 14:08:42 Capturing — 7 exchanges this session, 3 unbundled across 2 projects ▁▃▆█▇▅▂ diff --git a/crates/pcr-napi/npm/darwin-arm64/package.json b/crates/pcr-napi/npm/darwin-arm64/package.json index dd72356..a908bbd 100644 --- a/crates/pcr-napi/npm/darwin-arm64/package.json +++ b/crates/pcr-napi/npm/darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "pcr-dev-darwin-arm64", - "version": "0.2.9", + "version": "0.3.0", "description": "PCR.dev CLI prebuilt binary for macOS arm64", "license": "Apache-2.0", "os": [ diff --git a/crates/pcr-napi/npm/darwin-x64/package.json b/crates/pcr-napi/npm/darwin-x64/package.json index a762065..f254c27 100644 --- a/crates/pcr-napi/npm/darwin-x64/package.json +++ b/crates/pcr-napi/npm/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "pcr-dev-darwin-x64", - "version": "0.2.9", + "version": "0.3.0", "description": "PCR.dev CLI prebuilt binary for macOS x64", "license": "Apache-2.0", "os": [ diff --git a/crates/pcr-napi/npm/linux-x64-gnu/package.json b/crates/pcr-napi/npm/linux-x64-gnu/package.json index ff1605b..091dcc7 100644 --- a/crates/pcr-napi/npm/linux-x64-gnu/package.json +++ b/crates/pcr-napi/npm/linux-x64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "pcr-dev-linux-x64-gnu", - "version": "0.2.9", + "version": "0.3.0", "description": "PCR.dev CLI prebuilt binary for Linux x64 (glibc)", "license": "Apache-2.0", "os": [ diff --git a/crates/pcr-napi/npm/win32-x64-msvc/package.json b/crates/pcr-napi/npm/win32-x64-msvc/package.json index 997c920..b693e93 100644 --- a/crates/pcr-napi/npm/win32-x64-msvc/package.json +++ b/crates/pcr-napi/npm/win32-x64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "pcr-dev-windows-x64", - "version": "0.2.9", + "version": "0.3.0", "description": "PCR.dev CLI prebuilt binary for Windows x64", "license": "Apache-2.0", "os": [ diff --git a/crates/pcr-napi/package.json b/crates/pcr-napi/package.json index 7feb76e..ca99011 100644 --- a/crates/pcr-napi/package.json +++ b/crates/pcr-napi/package.json @@ -1,6 +1,6 @@ { "name": "pcr-dev", - "version": "0.2.9", + "version": "0.3.0", "description": "PCR.dev CLI \u2014 capture AI coding prompts for peer review", "license": "Apache-2.0", "author": "PCR.dev", @@ -49,10 +49,10 @@ } }, "optionalDependencies": { - "pcr-dev-darwin-x64": "0.2.9", - "pcr-dev-darwin-arm64": "0.2.9", - "pcr-dev-linux-x64-gnu": "0.2.9", - "pcr-dev-windows-x64": "0.2.9" + "pcr-dev-darwin-x64": "0.3.0", + "pcr-dev-darwin-arm64": "0.3.0", + "pcr-dev-linux-x64-gnu": "0.3.0", + "pcr-dev-windows-x64": "0.3.0" }, "devDependencies": { "@napi-rs/cli": "^2.18.4"