Skip to content

Commit 10381b0

Browse files
committed
release: v0.7.0
1 parent 9869427 commit 10381b0

1 file changed

Lines changed: 64 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,70 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.7.0] - 2026-05-03
9+
10+
### Changed
11+
12+
- **Bridged to OpenCode upstream v1.4.0 across a history rewrite.** Upstream rewrote git history between v1.3.17 and v1.4.0 (2026-04-04), leaving zero common ancestor with our fork. A new `script/upstream/bridge-merge.ts` tool overlays v1.4.0's tree file-by-file: take v1.4.0's content for unmarked upstream-shared files, keep main's version entirely for files carrying `altimate_change` markers (61 files), keep `keepOurs` files unchanged (65 files), and drop excluded `skipFiles` (3676 files). PR #18186 (Anthropic provider exclusion handling) is reapplied programmatically. Net diff vs v0.6.1: 361 files, +88,823 / -34,416 LoC. The merge passed nine adversarial audit cycles and ships a 234-test bridge-merge regression suite plus 76-test E2E suite that fails CI loudly on every regression class we hit. (#757)
13+
- **Pinned the dependency floor for the bridge merge.** Added overrides for `effect@4.0.0-beta.43`, `@effect/platform-node@4.0.0-beta.43`, and `@effect/platform-node-shared@4.0.0-beta.43` (beta.58 removed `ServiceMap` in favor of `Context`). Held back `@ai-sdk/*`, `@openrouter/ai-sdk-provider`, and `@opentui/*` from upstream's bumps. Restored upstream's `solid-js@1.9.10` patchedDependencies declaration (Solid Transition correctness, issue #2046).
14+
15+
### Added
16+
17+
- **`--dangerously-skip-permissions` flag on `altimate run`** (upstream PR #21266 backport). Aliased to our existing `--yolo` / `ALTIMATE_CLI_YOLO` branch. Strictly safer than upstream's version: `--yolo` honors explicit `deny` rules in session config, upstream's auto-approves anything not denied with no notion of deny rules. Documented in `docs/docs/usage/cli.md`.
18+
- **`variant_list` TUI keybind** (upstream PR #21185 backport). Opens the "Switch model variant" dialog (`/variants`); hidden when no variants are configured. Schema entry in `config.ts`; documented in `docs/docs/configure/keybinds.md`.
19+
- **Plain-text rate-limit retry detection** (upstream PR #21355 backport). `session/retry.ts` now retries Alibaba/DashScope and other providers that return non-JSON 429 responses.
20+
- **Telemetry diagnostic fields on `agent_outcome`.** `final_tool`, `error_class`, and `reason` are now populated for non-completed outcomes (was empty in ~30% of `abandoned`/`aborted`/`error` runs). `reason` is PII-masked at extraction (capped 500 chars for `error`, 200 for `aborted`); `final_tool` includes MCP-namespaced names (e.g. `mcp__atlassian__getJiraIssue`); `error_class` derives from `classifyError` patterns. Documented in `docs/docs/reference/telemetry.md`.
21+
- **`bridge-guard` skill** (`.claude/commands/bridge-guard.md`). Codifies the v1.4.0 audit playbook into a reusable runbook covering split-brain module pairs, brand-leak patterns, behavior-patch loss, logo/color regressions, internal-script binary names, and the three-layer safety net. Invoke as `/bridge-guard [PR#]`.
22+
23+
### Fixed
24+
25+
- **Permission split-brain — infinite ask loop.** v1.4.0 introduced an Effect-TS `Permission` service in `src/permission/index.ts`, but every runtime ask site still called `PermissionNext.ask` from the older module in `src/permission/next.ts`. The two modules each owned their own pending map: asks landed in `PermissionNext`'s map, the HTTP reply route looked them up in the Effect service's empty map, returned 200 without resolving the deferred. User-visible: clicking "Allow once" / "Allow always" / "Reject" did nothing, the prompt kept re-rendering. Routed both reply routes plus `GET /permission` to `PermissionNext`. Pinned with 4 static-text invariants, 1 tree-wide import scan, and 3 runtime end-to-end deadlock tests.
26+
- **`mcp add` lost its 7-flag non-interactive mode.** Bridge merge overwrote `McpAddCommand` with upstream's interactive-only version. Scripts/CI calling `mcp add --name foo --type remote --url …` either hung (no TTY) or silently dropped into prompts ignoring args. Restored full `--name --type --url --command --header --oauth --global` flag block with markers.
27+
- **`mcp remove` command (and `rm` alias) restored** — entirely lost during v1.4.0 merge. `mcp remove <not-found>` now exits non-zero (was exiting 0 because `process.exit(1)` inside the async Effect chain was swallowed).
28+
- **`SessionStatus.set` / `cancel` async drift.** v1.4.0 made these async but six callers in `prompt.ts` and `processor.ts` were unawaited, racing the idle-state flush on shutdown. All call sites now await; `defer(cancel)` switched to `await using`.
29+
- **`tool/plan.ts` PlanExitTool reject semantics.** v1.4.0 changed reject from `answer !== "Yes"` to `answer === "No"`, so dialog cancel / dismiss / network drop silently confirmed the agent transition (unsafe). Reverted to "reject on anything but explicit Yes".
30+
- **SQLite `IMMEDIATE` transaction was silently `DEFERRED`.** `Database.transaction()` wrapper didn't accept the `behavior` option, so `SyncEvent.run`'s read-then-write sequence fell back to deferred locking — concurrent runs could interleave and produce duplicate sequence numbers / corrupt event log. Pass-through added; runtime test exercises 10 parallel writers to prove serialization.
31+
- **Plugin hook isolation.** `Plugin.trigger()` invoked each hook's callback with no try/catch — a single buggy plugin (third-party or local: codex/copilot/gitlab/etc.) would crash the entire LLM call with a confusing unrelated stack. Wrapped in try/catch with logged failure; iteration continues across remaining hooks.
32+
- **HTML escaping in OAuth/codex callback templates.** `${error}` was interpolated raw in `mcp/oauth-callback.ts` (real XSS) and `plugin/codex.ts`. Added `escapeHtml()` helper, applied at every interpolation.
33+
- **Symlink escape in `containsPath` boundary checks.** `project/instance.ts` and `plugin/shared.ts` reverted to `Filesystem.contains()` (lexical) during the bridge merge; restored to `Filesystem.containsReal()` (resolves symlinks before checking project boundary).
34+
- **Effect Service identifier collision (`@opencode/Account`).** `account/index.ts` and `account/service.ts` both registered the same id with two parallel ManagedRuntimes (undefined merge behaviour). Deleted dead `effect/runtime.ts` and `account/service.ts`; renamed `auth/index.ts` to `@opencode/Auth.cli` to disambiguate from the live `auth/service.ts`.
35+
- **`chat.params` `maxOutputTokens` hook silently ignored.** `session/llm.ts` computed `maxOutputTokens` *after* the hook fired and never read back from `params.maxOutputTokens` — codex/copilot's own `output.maxOutputTokens = undefined` was a no-op, and any third-party plugin altering this field did nothing. Now matches upstream PRs #21220 + #21225.
36+
- **`File.search()` race with initial scan.** Cache was empty when tests called search before the initial scan completed. `files()` now tracks the in-flight scan with a `pending` promise and awaits it on call.
37+
- **`MessageV2.fromError` regressions.** "OAuth token refresh failed" now returns `MessageV2.AuthError` instead of `UnknownError`. `errorMessage()` surfaces stack location for empty-message Error instances. Context-overflow detection added for OpenAI-style `context_length_exceeded` codes.
38+
- **`workspace-router-middleware.ts` typeerror under `OPENCODE_EXPERIMENTAL_WORKSPACES=1`.** Adaptor API was renamed `fetch → target` in v1.4.0; rewrote to `adaptor.target()` + `ServerProxy.http()` and skip routing for local targets.
39+
- **`Truncate.init()` lost from `project/bootstrap.ts`.** Hourly scheduler that prunes `Global.Path.data/tool-output/tool_*` never re-registered, so the directory grew unboundedly. Restored.
40+
- **`provider/models.ts` `setTimeout(…, 0)` deferral on initial refresh.** Removed during merge, re-introducing the circular-dep risk fixed by altimate `980efaab64`. Restored.
41+
- **TUI mid-render display corruption.** `clipboard.ts`, `dialog-workspace-list.tsx`, `dialog-mcp.tsx` had `console.log` writing directly to the terminal mid-render. Restored structured `Log.Default.debug` calls and removed a stray workspace-result `JSON.stringify` debug-print.
42+
- **Workspace SSE reconnect loop killed by transient network blips.** `control-plane/workspace.ts` lost its defensive `.catch(() => undefined)` and a `return` from the local-workspace branch was permanent rather than per-iteration. Restored both.
43+
- **Branding restoration after v1.4.0 leaks.** Fixed in three batches: cycle-7 audit (196 leaks across 66 files: `$schema` URLs, system prompts, repo references, generated SDK strings, route descriptions); ASCII logo (`ALTIMATE | CODE` block letters were swapped for `OPEN | CODE`); brand colors on the startup logo (`theme.primary` warm orange + `theme.accent` purple were replaced with monochrome grey/white); `attach.ts` Basic-auth username (was `opencode:`, broke authentication against altimate-code servers); `cli/cmd/github.ts` AGENT_USERNAME / WORKFLOW_FILE / GitHub App slug / OIDC audience / branch prefix; CLI describe text in 8+ subcommands; `mcp` resolveConfigPath order (`altimate-code.json` precedence with `opencode.json` fallback for existing installs); plugin install path (`.altimate-code/` for new installs, keep `.opencode/` if it exists).
44+
- **API-key leakage in masked strings.** `maskString` only redacted quoted spans. Added unquoted-API-key (`sk-`, `sk-ant-`, `sk-proj-`) and `Bearer …` patterns with a 20-char length floor (avoids false positives on short identifiers like `sk-foo`). All 9 existing `maskString` consumers pick this up.
45+
- **`ERROR_PATTERNS` coverage for HTTP 5xx + rate-limit prose.** Real provider errors like `APIError: Service unavailable (503)` and `Rate limit exceeded. Retry after 60s` were classifying as `unknown` because patterns only matched the prefixed forms. Added phrases: `service unavailable`, `rate limit`, `rate_limit`, `retry after`, `too many requests`, `503`, `502`, `504` to the `http_error` class.
46+
- **`marker-guard` strict mode on bridge-merge pushes to main.** PR-side guard already runs non-strict for `upstream/merge-*` head_refs, but the squash-merge push event has no head_ref — was failing on the hundreds of upstream files the bridge brings in. Now detects bridge/upstream-merge commits in the pushed range by subject (`grep -qiE '(bridge|merge) upstream'`) and downgrades strict→non-strict. (#782, closes #781)
47+
48+
### Security
49+
50+
- **API-key redaction at the diagnostic surface.** `Telemetry.deriveAgentOutcomeReason()` applies `maskString` to both `error` and `aborted` reasons before they enter the `agent_outcome.reason` field (which surfaces in our backend telemetry). `prompt.ts` extracts only `err.data.message` instead of `JSON.stringify(error.data)` (which leaked `responseBody` / `responseHeaders` / metadata).
51+
- **Plugin hook crash containment.** A single plugin throwing in `chat.params` / `chat.headers` / any registered hook no longer takes down the entire LLM call (see Fixed).
52+
53+
### Internal
54+
55+
- **Three-layer regression backstop for bridge merges.** (1) `script/upstream/analyze.ts --branding` now catches bare `opencode` strings in user-visible contexts (yargs `describe`, console output, MCP `clientInfo.name`, User-Agent, OIDC audiences, GitHub workflow YAML, `spawn` binary names); skips lines inside `altimate_change` blocks. (2) New `MergeConfig.requireMarkers` allowlist of 38 files known to hold altimate behavioral patches; `bridge-merge.ts` treats them as `keepOurs` and hard-aborts the merge if any is missing markers. (3) Retroactive marker sweep added markers to 14 previously-unmarked files. CI runs `--branding` and `--require-markers --strict` on every PR.
56+
- **9 audit cycles documented and pinned.** 310 tests across 8 files in `test/upstream/` (`bridge-merge`, `bridge-merge-invariants`, `bridge-merge-runtime`, `bridge-merge-v3`, `bridge-merge-e2e`, `v140-merge-adversarial`, `v140-merge-fuzz`, `v140-merge-chaos`, `v140-permission-deadlock`).
57+
- **`tracing.ts` `flushSync` vs async `snapshot` race.** Crashed-trace file could be clobbered by an in-flight async snapshot completing its `fs.rename` after `flushSync`'s sync write. Added a `crashed` flag with two checkpoint reads on the async path. Plus `Recap.flush()` helper to replace `setTimeout(50)` waits in tests on slow CI runners.
58+
- **GitGuardian whitelisting.** `.gitguardian.yaml` paths-ignore for the `protected.ts` deny-list (filenames like `.pgpass` / `id_rsa` / `credentials.json` are filenames, not credentials); split filename literals via `DOT + "name"` concatenation so the GG dashboard doesn't keep flagging them; replaced JWT-shaped synthetic tokens in the v140 adversarial suite with generic 36-char alphanumeric tokens.
59+
- **`.github/meta/{commit,diff,pr-body-*}` untracked + gitignored.** Per CLAUDE.md these are transient scratch files; tracked instances were leaking false-positive branding hits and stale commit messages. Pattern broadened to `**/.github/meta/...` so nested paths are covered.
60+
- **`globalThis.fetch` leak in `session-proxy-middleware.test.ts`.** Test stubbed `fetch` but never restored it, cascading into ~15 unrelated test failures (OAuth, ECONNRESET, HttpExporter, Discovery, live-trace-viewer). Now snapshots and restores in `afterEach`.
61+
- **Restored `.github/TEAM_MEMBERS`.** Bridge merge replaced our 30-name list with upstream's 15-name list, removing 28 altimate maintainers including `anandgupta42``pr-standards.yml` was flagging every team member's PR with `needs:title` / `needs:compliance` and auto-closing after 2 hours.
62+
63+
### Testing
64+
65+
- **200+ new tests pinning every audit-cycle fix:** static-text invariants for service identifiers, async signatures, marker integrity, branding; runtime tests for `Database.transaction` IMMEDIATE serialization, `BusEvent.define` idempotency, `SyncEvent``BusEvent` registry bridge, `PlanExitTool` reject semantics, plugin trigger isolation; property-based fuzz of `maskString` (5×500 random iterations on unicode/control-chars/emoji), `deriveAgentOutcomeReason` field bounds; chaos: 100 parallel `deriveAgentOutcomeReason` calls, regex DoS resistance with relative-budget thresholds; E2E: spawns the CLI as a real user (`bun run src/index.ts <args>` with isolated `XDG_*` env vars) and visually inspects `--version`, `--help`, `mcp --help`, theme schemas, system-prompt files, etc.
66+
- **Hardened flaky tests against parallel-suite contention.** Extracted pure helpers from `tui/thread.ts` to remove `mock.module()` calls that leaked across files. Replaced FIFO request-matching queue in `session/llm.test.ts` with a path-keyed Map (out-of-order requests no longer resolve another test's deferred). Added explicit `30_000ms` timeouts to slow-SDK tests. Local full suite: 7965 pass / 0 fail.
67+
68+
### Documentation
69+
70+
- **README refreshed for v0.5.12 through v0.6.1** — adds three Key Features entries (cross-dialect data parity, automated dbt unit tests, GitLab MR review), four providers (Altimate LLM Gateway, Databricks AI Gateway, Snowflake Cortex, LM Studio), Microsoft Fabric warehouse footnote, `/data-parity` and `/dbt-unit-tests` quick-demo examples, inline list of the 19 built-in skills. Source of truth is CHANGELOG.md; bullets are condensed restatements. (#784)
71+
872
## [0.6.1] - 2026-04-24
973

1074
### Fixed

0 commit comments

Comments
 (0)