From 55a8b970550bf847f306f32753b2f591f9ff7dec Mon Sep 17 00:00:00 2001 From: Haider Date: Mon, 10 Aug 2026 22:05:19 +0530 Subject: [PATCH 1/5] docs(changelog): v0.9.5 entry The v0.9.5 release PR (#1086) merged without a CHANGELOG entry because I mistakenly split it out. `CHANGELOG.md` is baked into the compiled binary at build time (`script/build.ts` embeds it as `OPENCODE_CHANGELOG`) and copied into every platform-specific npm package (`script/publish.ts`), so shipping v0.9.5 without this entry would give users an artifact whose embedded changelog stops at v0.9.4. Entry incorporates PM's release-notes feedback from the pre-release persona review: leads with the Windows grep fix (~16% of Windows users broken since v0.9.2, hard number from telemetry), collapses the welcome-panel two-round fix into a single bullet, includes the YOLO deny-rules-still-apply safety caveat, and files the three telemetry / instrumentation commits under Changed (observability) rather than Added (user-visible feature) so the release isn't overstated. --- CHANGELOG.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30f9ee83a4..fcbb0b963c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,26 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.9.5] - 2026-08-10 + +Windows `grep` back for the ~16% of Windows users it silently broke since v0.9.2, plus a mid-session YOLO toggle and a welcome panel that stops eating half of narrow terminals. + +### Added + +- **`Ctrl+Y` toggles YOLO mode mid-session.** Previously YOLO was launch-time only — you either started the CLI with `--yolo` / `ALTIMATE_CLI_YOLO=true` or opened a new one. Now you can flip it on or off from inside the TUI. Enabling requires a one-tap confirmation; disabling is instant. The toggle is **session and subagent scoped and lives in memory only** — restart the CLI and it defaults back to whatever `--yolo`, `ALTIMATE_CLI_YOLO`, or `OPENCODE_YOLO` was at launch. Explicit `deny` rules stay enforced (`DROP DATABASE`, `DROP SCHEMA`, `TRUNCATE` remain blocked even with the toggle on). Heads-up: `Ctrl+Y` is `readline`'s "yank" keystroke in some shells — the toggle defaults to "No" on the confirmation, so a stray keypress can't do anything dangerous. (#1078) + +### Fixed + +- **Windows `grep` for the ~16% of Windows users it was silently broken for.** Since v0.9.2, ripgrep extraction shelled out to `powershell.exe` for the download's zip, and 99 of 617 Windows machines in a 14-day telemetry window couldn't complete the extraction — the tool failed silently on `grep` / `glob` from that point on. Extraction is now in-process via `@zip.js/zip.js` (`checkSignature: true`, exact-pinned) with atomic staged-then-renamed installs, no PowerShell dependency at all. Landed with a real Windows CI job (`windows-ripgrep-e2e`) that runs with PowerShell stripped from `PATH`, so this class of regression can't come back silently. (#1074, closes #1072) +- **Welcome panel no longer eats 40% of narrow or short terminals.** On anything smaller than ~110 cols wide or ~44 rows tall the panel now scales through three responsive tiers instead of holding the full desktop-sized dimensions. Landed in two rounds — the first added the breakpoint function; the second corrected the width measurement so the `full` tier no longer fired at ~84 usable cols. (#1067, #1069, #1071) +- **Telemetry opt-out honors `=1` and case-insensitive `true`, and finally wires up `OPENCODE_DISABLE_TELEMETRY`.** `ALTIMATE_TELEMETRY_DISABLED=1` and `=TRUE` used to be silently ignored (only `=true` worked). The v0.9.4 CHANGELOG advertised `OPENCODE_DISABLE_TELEMETRY=1` as an opt-out env var but that name was wired into test fixtures only, never checked in product — users who set it based on the release notes were not opted out. Both env vars now route through a shared helper that accepts `"true"` / `"TRUE"` / `"1"`. If you set either one and expected it to work, this release makes it actually work. (#1086) + +### Changed + +- **`cli_context` on the sign-in URL for PostHog session correlation.** After successful sign-in, the frontend registers the CLI machine-id as the `cli_machine_id` PostHog super-property so CLI activity is attributed to the authenticated account in aggregate funnel analytics. The value travels in the URL *fragment* (`#cli_context=…`, not a query string) so the durable identifier stays out of server access logs, CDN/WAF, and the `Referer` header — the frontend reads it via `location.hash`. (#1068) +- **First-run onboarding and review feature usage now emit funnel telemetry.** New event types: `activation_menu_shown`, `activation_job_selected`, `first_prompt_sent`, `environment_scan_completed`, plus review-lane latency and outcome events. All existing opt-out mechanisms (`ALTIMATE_TELEMETRY_DISABLED`, `OPENCODE_DISABLE_TELEMETRY`, `telemetry.disabled` in config) gate every new event; full list in `docs/reference/telemetry.md`. (#1049, #1064) +- **UTM parameters on outbound `altimate.ai` marketing links.** Non-functional; helps attribute web traffic back to the CLI. (#1063) + ## [0.9.4] - 2026-07-31 Onboarding UX + first-run OAuth reliability. Ships the CLI's first-run scan + activation menu (Altimate LLM Gateway top of picker; bundled jaffle-shop DuckDB sample for users with no warehouse yet), then hardens the sign-in flow that path leads into. From 3fa26748b6890dc62e1c32d5c6218a2b9f0911f6 Mon Sep 17 00:00:00 2001 From: Haider Date: Mon, 10 Aug 2026 22:08:16 +0530 Subject: [PATCH 2/5] test(skill): adversarial coverage for v0.9.5 surfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per the release skill's Step 6, every release ships with an adversarial test file under `test/skill/release-v{X}-adversarial.test.ts` — one per release since v0.5.14. The v0.9.5 file was written but not committed; adding it here so the release PR carries the intended coverage. Categories per the skill (empty/null/undefined, boundary values, type confusion, injection attacks, error propagation), applied to the v0.9.5 code surface: - **Flag.truthyEnv:** 32KB env values, embedded null bytes, whitespace, unknown keys — all must not enable and must not throw. - **Telemetry.classifyProvider:** 10KB providerIDs, control characters, JSON-stringified inputs, prototype keys (`__proto__` / `prototype` / `hasOwnProperty` / `isPrototypeOf`), unusual modelID values — all must fall through to "other" without leaking a raw id or extending Object. - **OnboardingTelemetry.claimEnvironmentScan:** empty / 10KB / path-shaped / SQL-shaped sessionIDs — idempotent and session-scoped; the composed gate short-circuits correctly when the session was never marked. - **redactPaths / countSampleContents:** empty input, 100KB input in <1s, regex metacharacters in `extras`, user text already containing ``, fs symlink loops on `countSampleContents`. - **buildCliContext / buildAuthorizeUrl:** base64url shape, `v=1` payload, redirect / state encoding on hostile inputs (newlines, tabs, fragment chars), fragment-goes-last invariant, graceful degradation when the machine-id path is unreadable (payload valid, `machine_id` omitted). 22 tests, all pass locally. No `mock.module()`; real helpers, real fs where needed, real `process.env` mutation with `beforeEach` / `afterEach` snapshot-and-restore. --- .../skill/release-v0.9.5-adversarial.test.ts | Bin 0 -> 13936 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 packages/opencode/test/skill/release-v0.9.5-adversarial.test.ts diff --git a/packages/opencode/test/skill/release-v0.9.5-adversarial.test.ts b/packages/opencode/test/skill/release-v0.9.5-adversarial.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..8d2141e49d91472aeb227b365679c3b1b816c9a4 GIT binary patch literal 13936 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 Hs+Ru)`r&x_ literal 0 HcmV?d00001 From c79dae0b5328f6830028b027d825427f5d142f24 Mon Sep 17 00:00:00 2001 From: Haider Date: Mon, 10 Aug 2026 22:12:07 +0530 Subject: [PATCH 3/5] test(skill): escape null bytes as `\x00` so git treats the file as text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous commit landed the adversarial file with three raw null bytes embedded in string literals meant to test null-byte handling. Git classified the file as binary because of them, showing `Bin 0 -> 13936 bytes` and 0 insertions/deletions on the diff — reviewers on the PR couldn't see the file contents. Runtime behavior of the tests is unchanged; the JS string `"true\x00"` compiles to the same "true"+NUL sequence as a literal 0x00 byte in the source, without tripping git's binary detector. 22/22 tests still pass after the escape. --- .../skill/release-v0.9.5-adversarial.test.ts | Bin 13936 -> 13945 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/packages/opencode/test/skill/release-v0.9.5-adversarial.test.ts b/packages/opencode/test/skill/release-v0.9.5-adversarial.test.ts index 8d2141e49d91472aeb227b365679c3b1b816c9a4..ef32e1a75264fa5ed45c5476f151dcaf9730476c 100644 GIT binary patch delta 37 kcmey6^D}3I87E6jg@M6lbIz5l5Y|J!T5bp{UP@2~01OBWeEtc(nkZ}Aszj^gLy28v`z3CaKf!Se~) From c37889db8257051d975ab56bc9f3eef72b7c721d Mon Sep 17 00:00:00 2001 From: Haider Date: Mon, 10 Aug 2026 22:16:40 +0530 Subject: [PATCH 4/5] fix(pr-review): address coderabbit + cubic findings on PR #1088 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three inline findings, all valid, all small: - **CHANGELOG.md:25** (coderabbit + cubic, both P3) — repo-relative telemetry doc path was `docs/reference/telemetry.md`; the file actually lives at `docs/docs/reference/telemetry.md` (content root is `docs/` per `docs/mkdocs.yml`, published at `reference/telemetry/` on the docs site). Fixed the path so a maintainer following the link in the changelog finds the file. - **adversarial.test.ts:180** (coderabbit) — the 100KB stress test used `repeat(1000)` which is ~20KB, not 100KB as advertised, and asserted a wall-clock `performance.now()` budget which is flaky under host load / parallel test runners. Built exactly 100_000 characters via `Math.ceil(100_000 / segment.length)` slicing, and dropped the timing assertion — the test now proves only what it claims (redaction shape survives large input). - **adversarial.test.ts:225** (coderabbit) — the symlink-loop test had a bare `catch { return }` that would swallow every setup failure into a passing test, and `toBeGreaterThanOrEqual(0)` accepted incorrect positive counts. Narrowed the catch to the one known unsupported- symlink error class (`EPERM` on Windows without dev-mode), re-throw everything else, and tightened the assertion to exact `.toBe(0)` — a nonzero count would mean the helper is following the loop. 22/22 adversarial tests still pass after the changes. --- CHANGELOG.md | 2 +- .../skill/release-v0.9.5-adversarial.test.ts | 28 +++++++++++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fcbb0b963c..1fb6c7aeb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ Windows `grep` back for the ~16% of Windows users it silently broke since v0.9.2 ### Changed - **`cli_context` on the sign-in URL for PostHog session correlation.** After successful sign-in, the frontend registers the CLI machine-id as the `cli_machine_id` PostHog super-property so CLI activity is attributed to the authenticated account in aggregate funnel analytics. The value travels in the URL *fragment* (`#cli_context=…`, not a query string) so the durable identifier stays out of server access logs, CDN/WAF, and the `Referer` header — the frontend reads it via `location.hash`. (#1068) -- **First-run onboarding and review feature usage now emit funnel telemetry.** New event types: `activation_menu_shown`, `activation_job_selected`, `first_prompt_sent`, `environment_scan_completed`, plus review-lane latency and outcome events. All existing opt-out mechanisms (`ALTIMATE_TELEMETRY_DISABLED`, `OPENCODE_DISABLE_TELEMETRY`, `telemetry.disabled` in config) gate every new event; full list in `docs/reference/telemetry.md`. (#1049, #1064) +- **First-run onboarding and review feature usage now emit funnel telemetry.** New event types: `activation_menu_shown`, `activation_job_selected`, `first_prompt_sent`, `environment_scan_completed`, plus review-lane latency and outcome events. All existing opt-out mechanisms (`ALTIMATE_TELEMETRY_DISABLED`, `OPENCODE_DISABLE_TELEMETRY`, `telemetry.disabled` in config) gate every new event; full list in `docs/docs/reference/telemetry.md`. (#1049, #1064) - **UTM parameters on outbound `altimate.ai` marketing links.** Non-functional; helps attribute web traffic back to the CLI. (#1063) ## [0.9.4] - 2026-07-31 diff --git a/packages/opencode/test/skill/release-v0.9.5-adversarial.test.ts b/packages/opencode/test/skill/release-v0.9.5-adversarial.test.ts index ef32e1a752..d2d7993e00 100644 --- a/packages/opencode/test/skill/release-v0.9.5-adversarial.test.ts +++ b/packages/opencode/test/skill/release-v0.9.5-adversarial.test.ts @@ -172,12 +172,14 @@ describe("v0.9.5 — sample-setup helpers adversarial", () => { expect(redactPaths("")).toBe("") }) - test("redactPaths handles a 100KB message in reasonable time (< 1s)", () => { - const msg = ("normal text here " + "/Users/alice/x/y/z ".repeat(1000)).slice(0, 100_000) - const start = performance.now() + test("redactPaths handles a 100KB message without leaking paths or degenerating markers", () => { + // Coderabbit review on PR #1088: previous version used `repeat(1000)` which is + // ~20 KB not 100 KB, and a `performance.now()` wall-clock assertion which is + // flaky under host load / parallel test runners. Build exactly 100,000 chars + // deterministically and assert only the redaction shape. + const segment = "normal text here /Users/alice/x/y/z " + const msg = segment.repeat(Math.ceil(100_000 / segment.length)).slice(0, 100_000) const out = redactPaths(msg) - const elapsed = performance.now() - start - expect(elapsed).toBeLessThan(1000) expect(out).not.toContain("/Users/alice") // Should not have degenerated to `...` expect(out).not.toMatch(//) @@ -214,14 +216,22 @@ describe("v0.9.5 — sample-setup helpers adversarial", () => { try { fs.mkdirSync(path.join(root, "models")) // Create a symlink pointing back to models — a real loop. + // Coderabbit review on PR #1088: bare `catch` used to swallow every symlink + // setup failure into a passing test, and `toBeGreaterThanOrEqual(0)` was + // trivially true for any non-negative count. Narrow the skip to the one + // known-unsupported-symlink error class (EPERM on Windows without + // dev-mode); re-throw anything else so a real filesystem regression + // doesn't hide behind the skip. Assert exact `models === 0` — the loop + // link resolves to a directory but has no `.sql` inside; anything nonzero + // would mean the helper is following the loop. try { fs.symlinkSync(path.join(root, "models"), path.join(root, "models", "loop")) - } catch { - // Some CI runners disallow symlinks (Windows without dev-mode). Skip. - return + } catch (error) { + if ((error as NodeJS.ErrnoException).code === "EPERM") return + throw error } const counts = countSampleContents(root) - expect(counts.models).toBeGreaterThanOrEqual(0) + expect(counts.models).toBe(0) expect(counts.tables).toBe(0) } finally { fs.rmSync(root, { recursive: true, force: true }) From 3c0665d5b5230e3494b87e6a406100e891520c72 Mon Sep 17 00:00:00 2001 From: Haider Date: Mon, 10 Aug 2026 22:27:52 +0530 Subject: [PATCH 5/5] test(skill): scope `ALTIMATE_TELEMETRY_DISABLED` snapshot hooks to their describe block Kilo review on PR #1088: `beforeEach` / `afterEach` for the `ALTIMATE_TELEMETRY_DISABLED` env-var snapshot were declared at file scope, so they ran for all 22 tests even though only the four tests in `Flag.truthyEnv adversarial` ever set that variable. Moved the `const`, the `let`, and both hooks inside that describe block so scope matches usage. Behavior unchanged (still 22/22 pass); noise removed from unrelated tests' setup/teardown timeline. --- .../skill/release-v0.9.5-adversarial.test.ts | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/packages/opencode/test/skill/release-v0.9.5-adversarial.test.ts b/packages/opencode/test/skill/release-v0.9.5-adversarial.test.ts index d2d7993e00..07dc849d7f 100644 --- a/packages/opencode/test/skill/release-v0.9.5-adversarial.test.ts +++ b/packages/opencode/test/skill/release-v0.9.5-adversarial.test.ts @@ -29,18 +29,21 @@ import { buildCliContext, buildAuthorizeUrl } from "../../src/altimate/plugin/al // 1. Telemetry opt-out — `Flag.truthyEnv` on hostile / oversized env values // ----------------------------------------------------------------------------- -const OPT_OUT_VAR = "ALTIMATE_TELEMETRY_DISABLED" -let optOutSnapshot: string | undefined - -beforeEach(() => { - optOutSnapshot = process.env[OPT_OUT_VAR] -}) -afterEach(() => { - if (optOutSnapshot === undefined) delete process.env[OPT_OUT_VAR] - else process.env[OPT_OUT_VAR] = optOutSnapshot -}) - describe("v0.9.5 — Flag.truthyEnv adversarial", () => { + // Kilo review on PR #1088: env-var snapshot/restore hooks were previously + // file-scoped, so they ran for every test in this file even though only the + // tests in this describe block ever touch `ALTIMATE_TELEMETRY_DISABLED`. + // Scoping them here matches usage. + const OPT_OUT_VAR = "ALTIMATE_TELEMETRY_DISABLED" + let optOutSnapshot: string | undefined + beforeEach(() => { + optOutSnapshot = process.env[OPT_OUT_VAR] + }) + afterEach(() => { + if (optOutSnapshot === undefined) delete process.env[OPT_OUT_VAR] + else process.env[OPT_OUT_VAR] = optOutSnapshot + }) + test("very long value (32KB) — must not enable, must not throw", () => { // A 32KB env value should be rejected as a non-truthy string, not crash the // parser. Real users don't hit this, but a shell injection into the env