release: v0.9.4 review-fix bundle (A1-A12 + phase-label flake removal) - #1053
Conversation
…lock CI `spyOn(os, "homedir").mockImplementation(...)` in the mcp lifecycle suite's `beforeEach` was never torn down, so the mock leaked forward into the next test file loaded by bun. `packages/opencode/test/permission/next.test.ts` has six tilde-expansion assertions that resolve `~` via `os.homedir()`; those saw the still-active mock (which returns a temp dir with no resemblance to the real HOME) and failed with paths that pointed nowhere the assertions expected. Root cause of the red CI on PR #1001. Capture the spy in a mutable ref during `beforeEach` and restore it in a matching `afterEach`. Verified with the two suites together: 111 pass / 0 fail across mcp/lifecycle + permission/next. Flagged by the Tech Lead review; #1052 (D-list) does not need this.
… HOME is unsafe `materializeSample` refuses to write inside a root-owned HOME (the "sudo altimate-code" trap on Linux) with a clear message — but the recovery hint referenced a `--target-parent` flag that never existed. Users following the message got an "unknown flag" error and no path forward. Replace both occurrences with the working recipe: point HOME at the user's own home while running the CLI (`sudo HOME=/Users/you altimate-code` on macOS, `sudo HOME=/home/you altimate-code` on Linux). Same actionable intent, but the command in the message actually runs. Flagged by the Data Engineer persona; error text only, no behavioral change.
…w, echo authorize URL Three UX fixes to the Altimate LLM Gateway loopback OAuth handshake, all surfaced by the CTO + Support Engineer reviews: **Port collision (a3).** `startCallbackServer()` bound `127.0.0.1:7317` unconditionally. Second `altimate-code` process on the same box, an already-listening dev tool, or a lingering socket from a killed run made every OAuth attempt fail with EADDRINUSE and no fallback. Walk the 7317-7325 range on collision, remember which port bound, and use it to build the redirect URI so the callback matches what the gateway sees. **Auth window (a4-1).** `registerPending` timed out after 5 minutes. Corporate SSO + MFA + password-manager unlock routinely blows past that on first-run — the user comes back to an already-cancelled flow. Bump to 15 minutes. The pending map still evicts on completion or explicit cancel, so this is a ceiling, not a leak. **Headless fallback (a4-2).** `open()` silently no-ops on SSH sessions, tmux without a browser, WSL without wslview, and bare Docker containers. Users saw the CLI stall on "Waiting for browser…" with no clue what to do. Print the authorize URL to stderr immediately after `open()` so anyone in a headless context can paste it into a browser on their desktop and complete the handshake. Docs at docs/docs/getting-started/quickstart-new.md now describe the port range (a9). No test changes — behavior is verified by the release-day UX smoke.
…ndfather comment
The Support Engineer flagged a suspected regression: the tightened
cost-gate ("model.cost.input != null && !== 0") could exclude
legitimate paid providers whose model entries omit the `cost` field
— custom `altimate-code.json` registrations, BYOK entries with no
per-token metadata, self-hosted deployments — and force-feed them
the welcome picker on upgrade to v0.9.4.
Trace of the existing code confirmed the concern is a false alarm
for anyone whose provider id isn't "opencode": the outer `provider.id
!== "opencode" || …` short-circuits before the cost check runs. Only
OpenCode's own free-tier models are affected, which is the intended
tightening.
Rewrite as an explicit if/else so the intent reads at a glance
(non-opencode → connected; opencode → require nonzero cost) instead
of relying on short-circuit precedence, and add a grandfather comment
explaining WHY the check looks stricter than necessary. Semantically
identical to the pre-refactor code — verified by the existing
provider-connected test cases.
Proper prior-state regression detector (compare against the user's
last-known-connected set, not just current) is deferred to #1052 (D9).
…ives in onboard-connect Two clarifications to the /onboard-connect activation-menu template, both flagged by the End User persona from a first-run walkthrough: **a7.** "Try Altimate on a sample dbt project" gave no hint about where the sample would land on disk. Users who accepted the option had to guess (or dig through logs) to find `~/altimate-sample-dbt/`. Menu row now says so up front. **a8.** The "install dbt-duckdb" fallback offered only `pip install dbt-duckdb`, which fails on modern Python (PEP 668 externally-managed-environment) with an unhelpful "externally-managed" error. Add `pipx install dbt-duckdb`, `uv tool install dbt-duckdb`, and the venv recipe as first-class alternatives. Each is a one-liner that works out of the box on macOS / Homebrew Python 3.12+ and on Debian/Ubuntu with the system Python. Template only — no code changes.
…ivation menu Rewrite Step 2 of the getting-started quickstart to describe what users actually see on a fresh install: welcome panel, curated 6-provider picker with Altimate LLM Gateway on the top row, and the env-var short-circuit for CI users. Add a new Step 2.5 covering the first-run "Scan your environment?" Yes/No dialog and its four branches (warehouse found / dbt-only / git-repo-no-dbt / nothing), and explicitly note that the "What would you like to do?" menu is chat text — the user types the number, not arrow-selects a row. Interactive picker is deferred (see #1052 / D1). Loopback OAuth port range 7317-7325 documented under the "Don't want to manage API keys?" tip so users encountering a port-collision error have context. Flagged by the PM persona (release-notes story) + End User persona (first-run mismatch between docs and product).
…users at the chat Reorder the sample project's README so the "What to try" section leads with the activation-menu path (typical first-run) instead of the bare-shell dbt recipe. Move the pip flow to an appendix labelled for the "I `cd`'d in from a different shell" case. Also mention the PEP 668 alternatives that made it into the template (pipx / uv / venv) and note that altimate-code walks the common Python env managers when locating an existing dbt binary, so users don't have to install into their system Python. Flagged by End User persona: the previous README wording implied the sample was primarily a bring-your-own-dbt playground, undersold the in-chat workflow.
…e can't collide with success rows
The two error paths in `sample_setup` returned metadata shaped like
a fresh-materialize success row: `{ targetPath: "", reused: false,
suffix: 0, note: "" }`. Downstream consumers that read metadata (the
template branches on `output`, but external callers of the tool can
subscribe to the whole envelope) had no reliable way to distinguish
"error" from "materialized into the preferred slot" without also
checking the `error` field.
Set `suffix: -1` on error metadata. Negative suffixes are impossible
on success (the resolver always returns >= 0 for numeric slots or a
string suffix for the randomized-fallback case), so the shape alone
tells success from failure.
Flagged by the Tech Lead persona; comment in-place explains the
collision so a future refactor doesn't drift back.
… a follow-up The `writeJsonAtomic` helper's docstring promised "migration of the existing JSON.stringify + writeFileSync call sites" as if it were done in the same change. It isn't — only new sites use the helper; the legacy sites are still direct. That's a deliberate defer (the sweep touches sync-critical config files and needs its own review), but the docstring made it look landed. Update the docstring to reflect reality: helper exists, sweep is a tracked follow-up. No behavior change. Flagged by the Tech Lead persona.
…already CI-skipped) The test was gated with `test.skip` when `CI=true` because the `bootstrap.resolve-tools` span duration (~30-100ms) races the 50ms PTY sampling interval on cold runners — the label can complete between polls and the assertion drops it. Local runs also hit the flake (4/5 pass observed by the author). Since the test never runs in CI it provides no regression signal there; locally it emits noise on every full-suite run. Static + unit tests for the phase-event pipeline (server publish, TUI subscribe, store update) are separately in place and unaffected. Removes 9 references to an internal-tracker id from a public-repo file (D8 tracker-ref leak class, see #1052). Requested by @haider during v0.9.4 release testing.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe PR updates provider onboarding, optional environment scanning, sample-project activation, loopback OAuth handling, provider readiness checks, test isolation, CLI retries, binary staleness detection, and filesystem documentation. ChangesOnboarding and sign-in flow
Test and maintenance reliability
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant AltimateCLI
participant AltimateCallbackServer
participant Browser
participant AltimateOAuth
AltimateCLI->>AltimateCallbackServer: Start listener on ports 7317-7325
AltimateCallbackServer->>AltimateCLI: Return active callback port
AltimateCLI->>Browser: Launch authorization URL
Browser->>AltimateOAuth: Complete sign-in
AltimateOAuth->>AltimateCallbackServer: Redirect to active loopback port
AltimateCallbackServer->>AltimateCLI: Deliver authorization callback
Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Hey! Your PR title Please update it to start with one of:
Where See CONTRIBUTING.md for details. |
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 2 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
…n permission tests Six tests in `test/acp/permission.test.ts` failed when the developer had `ALTIMATE_CLI_YOLO=true` in their shell env (a common setup — direnv- managed at the repo root for daily use). Root cause is the short-circuit in `src/acp/permission.ts:57`: when the flag is set, the permission handler auto-approves with `reply: "once"` and returns before ever calling the ACP client's `requestPermission`, so: - The four tests that assert the reply shape (once/reject/etc.) saw the wrong reply and failed `toMatchObject`. - The two tests that `pollUntil(harness.requests.length === 1)` timed out after 2s because requestPermission was never called. The tests are correct — the code they test is a runtime feature toggle that should not leak into the deterministic test surface. Snapshot + restore `ALTIMATE_CLI_YOLO` (and its `OPENCODE_YOLO` fallback) around the whole file so the suite passes regardless of the developer's ambient env. Verified: 6/6 pass with and without `ALTIMATE_CLI_YOLO=true` in the parent env.
… older than build.ts The smoke tests picked up any `dist/*-<os>-<arch>/altimate` binary regardless of when it was built, and asserted invariants (embedded NAPI `.node` naming, standalone NODE_PATH-cleared startup) that only hold for a binary compiled from the CURRENT `script/build.ts`. Consequence: any developer with a stale local build — e.g. from a `bun run build:local` several weeks ago — sees 2 red failures on every `bun test` run even though nothing they did is broken. `script/build.ts` is the source of truth for the embed logic; a binary older than it is guaranteed to be checked against invariants that no longer match. Skip in that case with an actionable "run `bun run build:local` to refresh" message instead of failing. CI is unaffected: it either builds fresh or has no `dist/` at all (`findLocalBinary()` returns undefined → the existing "no local build found" skip fires). Verified: with a 2026-06-13 local binary present, all 5 tests now skip cleanly with the new message.
…ed" from child Under CI's bounded SUBPROCESS pass (`--max-concurrency=2`) — and more often locally at default concurrency — the CLI subprocess occasionally exits 1 with `Error: Unexpected error / database is locked` on the first `opencode run` invocation. Session storage opens SQLite at boot, and on cold spawns the WAL checkpoint can collide with the tracer's first write. It's a genuine transient (not a product regression) — the same command succeeds on retry. Wrap `run()` in the `withCliFixture` helper so that a non-zero exit whose stderr matches `/database is locked/i` triggers exactly one retry. Any other failure mode still surfaces immediately — only this specific transient is masked. Cleared: the `--trace writes a session trace artifact` case that consistently flaked under `--max-concurrency=2` locally. Not a change in production code — only the test-helper retry.
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.
Tip: disable this comment in your organization's Code Review settings.
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
1 similar comment
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/opencode/sample-projects/jaffle-shop-duckdb/README.md`:
- Around line 49-55: Update the installation command in the README setup
sequence to also install the separate DuckDB CLI package before the existing
duckdb query command, while preserving the current dbt-duckdb and optional pipx
installation guidance.
In `@packages/opencode/src/altimate/onboarding/materialize.ts`:
- Line 162: Update the HOME/root warning in the materializer error message to
direct users to rerun the CLI without sudo after installation. Remove the
ownership-unsafe `sudo HOME=/Users/you altimate-code` instruction; if privileged
execution must be supported, provide a recovery procedure that restores user
ownership before normal use.
In `@packages/opencode/src/altimate/plugin/altimate.ts`:
- Around line 157-172: Make callback-server initialization atomic in the
authorization startup flow around the shared server state and port-binding loop:
store the in-progress startup operation as a shared promise, have concurrent
authorize() calls await it before using currentCallbackPort, and only expose the
server after binding succeeds. Clear the shared startup promise on startup
failure and during shutdown, while preserving cleanup for success, errors, and
cancellation.
In `@packages/opencode/src/command/template/onboard-connect.txt`:
- Around line 188-195: Update the venv fallback instructions in the onboarding
template to tell users to paste the absolute path to the generated dbt
executable, rather than the tilde-prefixed ~/.venvs/dbt/bin/dbt path. Keep the
existing venv creation and installation commands unchanged, and align the
guidance with option 1’s literal path validation and execution.
In `@packages/opencode/src/util/filesystem.ts`:
- Around line 282-289: Update the docstring near the temporary-write migration
references to link directly to GitHub issue `#1052` instead of the generic issues
list, preserving the existing explanation of the deferred migrations.
In `@packages/opencode/test/install/smoke-test-binary.test.ts`:
- Around line 98-104: Update isBinaryStale() to compare the binary against a
generated build manifest or fingerprint covering all embedded build inputs,
including build.ts, changelog, migrations, skills, model snapshots,
parser/worker outputs, and the pinned altimate-core prebuild. Generate or
refresh this manifest through the existing build flow, and only skip rebuilding
when the binary’s recorded fingerprint matches the current manifest.
In `@packages/opencode/test/lib/cli-process.ts`:
- Around line 285-295: Update the retry logic in the Effect.gen block around
spawn so both attempts share the original timeout budget instead of allowing the
SQLite-lock retry to start another full-duration invocation. Track a common
deadline or derive a reduced timeout for the second spawn, while preserving the
single retry only for “database is locked” failures and returning other results
unchanged.
- Around line 291-294: Update the retry logic around spawn in the CLI process
helper to avoid retrying non-idempotent opencode run invocations after a SQLite
lock; restrict retries to idempotent command-only calls, or reset the relevant
fixture/session state before retrying. Preserve the existing immediate return
behavior for successful and non-lock failures.
In `@packages/opencode/test/mcp/lifecycle.test.ts`:
- Line 251: Update the test setup around homedirSpy so each test creates its
temporary home directory once in beforeEach, stores it in a captured homeDir
variable, and makes the mocked os.homedir return that same value on every call.
Preserve the existing per-test isolation while preventing different calls from
resolving different directories.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: d4cd6a13-bb0d-4b0f-b5f4-6068ec9bbf54
📒 Files selected for processing (13)
docs/docs/getting-started/quickstart-new.mdpackages/opencode/sample-projects/jaffle-shop-duckdb/README.mdpackages/opencode/src/altimate/onboarding/materialize.tspackages/opencode/src/altimate/plugin/altimate.tspackages/opencode/src/altimate/tools/sample-setup.tspackages/opencode/src/command/template/onboard-connect.txtpackages/opencode/src/util/filesystem.tspackages/opencode/test/acp/permission.test.tspackages/opencode/test/cli/tui/phase-label.tui-e2e.test.tspackages/opencode/test/install/smoke-test-binary.test.tspackages/opencode/test/lib/cli-process.tspackages/opencode/test/mcp/lifecycle.test.tspackages/tui/src/component/use-connected.tsx
💤 Files with no reviewable changes (1)
- packages/opencode/test/cli/tui/phase-label.tui-e2e.test.ts
| function isBinaryStale(binaryPath: string): boolean { | ||
| try { | ||
| const buildScript = path.join(PKG_DIR, "script", "build.ts") | ||
| if (!fs.existsSync(buildScript)) return false | ||
| const binMtime = fs.statSync(binaryPath).mtimeMs | ||
| const scriptMtime = fs.statSync(buildScript).mtimeMs | ||
| return binMtime < scriptMtime |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 4 'altimate-core|script/build\.ts|build:local|bun build' packages/opencodeRepository: AltimateAI/altimate-code
Length of output: 50381
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== smoke test relevant section =="
sed -n '1,150p' packages/opencode/test/install/smoke-test-binary.test.ts
echo
echo "== build script top/middle/outlines around bundling =="
sed -n '1,120p' packages/opencode/script/build.ts
sed -n '220,430p' packages/opencode/script/build.ts
sed -n '430,530p' packages/opencode/script/build.ts
echo
echo "== files listed in smoke test and adversarial test imports if present =="
sed -n '1,80p' packages/opencode/test/skill/release-v0.7.1-binary-adversarial.test.tsRepository: AltimateAI/altimate-code
Length of output: 30409
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== changed files/stat =="
git status --short
git diff --stat HEAD^..HEAD 2>/dev/null || true
echo
echo "== relevant diff context =="
git diff HEAD^..HEAD -- packages/opencode/test/install/smoke-test-binary.test.ts packages/opencode/script/build.ts packages/opencode/package.json 2>/dev/null | sed -n '1,240p' || true
echo
echo "== deterministic check of package version pin against script build dependency =="
python3 - <<'PY'
import json, pathlib, re
pkg = json.loads(pathlib.Path("packages/opencode/package.json").read_text())
pkg_dep = pkg.get("dependencies", {}).get("`@altimateai/altimate-core`")
build = pathlib.Path("packages/opencode/script/build.ts").read_text()
m = re.search(r'`@altimateai/altimate-core`@([^\s\'"`]+)', build)
print(f"package.json dependency={pkg_dep}")
print(f"script/build.ts install command dependency={m.group(1) if m else None}")
print(f"match={pkg_dep == m.group(1) if m else False}")
PYRepository: AltimateAI/altimate-code
Length of output: 514
Use a build-manifest fingerprint for binary freshness.
isBinaryStale() only checks the binary against script/build.ts. build.ts also embeds CHANGELOG.md, migration files, .opencode/skills/SKILL.md, src/provider/models-snapshot.ts, parser/worker output, and the pinned @altimateai/altimate-core prebuild, so those changes can leave the build script mtime unchanged while the binary is still stale. Switch to a generated build manifest or fingerprint that covers the embedded inputs before relying on this skip.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/opencode/test/install/smoke-test-binary.test.ts` around lines 98 -
104, Update isBinaryStale() to compare the binary against a generated build
manifest or fingerprint covering all embedded build inputs, including build.ts,
changelog, migrations, skills, model snapshots, parser/worker outputs, and the
pinned altimate-core prebuild. Generate or refresh this manifest through the
existing build flow, and only skip rebuilding when the binary’s recorded
fingerprint matches the current manifest.
There was a problem hiding this comment.
Fair point — the mtime-vs-build.ts guard doesn't cover embedded inputs like CHANGELOG.md, migrations, skills, or the pinned altimate-core prebuild. However, the current guard is strictly better than no guard (the pre-fix state was "always fails on any stale build"). Filed under issue #1052 as a follow-up so we can design a proper build-manifest fingerprint separately.
There was a problem hiding this comment.
@sahrizvi, acknowledged. The current script/build.ts guard reduces stale-binary failures for the changed build logic. GitHub issue #1052 is the correct follow-up for complete build-input fingerprinting.
You are interacting with an AI system.
| const first = yield* spawn(argv, opts) | ||
| if (first.exitCode === 0) return first | ||
| if (!/database is locked/i.test(first.stderr)) return first | ||
| return yield* spawn(argv, opts) |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 5 'withCliFixture|\.opencode\.run\s*\(|\bopencode\.run\s*\(' packages/opencode/testRepository: AltimateAI/altimate-code
Length of output: 11418
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== cli-process relevant sections =="
sed -n '240,330p' packages/opencode/test/lib/cli-process.ts
sed -n '1,80p' packages/opencode/test/lib/cli-process.ts
sed -n '420,470p' packages/opencode/test/lib/cli-process.ts
echo "== opencode.run call sites =="
rg -n -C 4 'opencode\.run\(' packages/opencode/test/cli packages/opencode/test/lib || true
echo "== fixture state / session writes candidates in opencode CLI =="
rg -n -C 3 'session|state|sqlite|locked|run|database|store|write|artifact|output|stdout|fixture|fixtureState|workdir|tmpdir' packages/opencode/src packages/opencode/test/lib packages/opencode/test/cli/run/run-process.test.ts | sed -n '1,220p'Repository: AltimateAI/altimate-code
Length of output: 36005
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== package files and lockfiles =="
fd -a '^(package\.json|bun\.lockb|bun\.lock|pnpm-lock\.yaml|yarn\.lock|package-lock\.json)$' . | sed 's#^\./##' | sort | head -80
echo "== cli index/run command refs =="
rg -n -C 4 'run|Serve\.Default|Session|SessionRegistry|AppRuntime|main|src/index' packages/opencode/src/index.ts packages/opencode/src packages/opencode | sed -n '1,240p'
echo "== session/storage sqlite refs =="
rg -n -C 4 'sqlite|Sqlite|Database|WAL|checkpoint|locked|session|SessionStore|persist|storage|InstanceStore|createWriteStream|mkdtemp|tmpdir|fs\.(rm|remove|unlink|writeFile|appendFile|mkdir)' packages/opencode/src packages/opencode/feature packages/opencode/ 2>/dev/null | sed -n '1,260p' || trueRepository: AltimateAI/altimate-code
Length of output: 42333
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== sqlite lock implementations =="
rg -n -C 6 'database is locked|locked|lock|SQLITE_BUSY|busy|WAL|checkpoint|xWalCheckpoint|SqliteBackend|SqliteNode|open|createConnection|createConnectionSync|`@opencode-ai/core/database`|Database\.defaultLayer' packages packages/opencode packages/core 2>/dev/null | sed -n '1,260p' || true
echo "== RunCommand implementation =="
fd -a 'run\.ts$' packages/opencode/src packages/opencode packages | sed -n '1,40p'
for f in $(fd 'run\.ts$' packages/opencode/src packages/opencode packages 2>/dev/null | head -20); do
echo "--- $f ---"
rg -n -C 8 'class RunCommand|handler:|run\(|Session|message|stdout|events|AppRuntime|trace|Output|Event|session' "$f" | sed -n '1,220p' || true
done
echo "== session event writes =="
rg -n -C 4 'session\.error|session\.success|text|message|append|events|Session' packages/opencode/src/session packages/opencode/src packages/opencode/packages/core/session 2>/dev/null | sed -n '1,260p' || true
echo "== package workspace references =="
sed -n '1,140p' packages/opencode/package.jsonRepository: AltimateAI/altimate-code
Length of output: 50382
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== precise sqlite lock sources =="
rg -n -C 6 'database is locked|wants a lock|LOCK_CONTENTION|is locked|SQLiteError|Sqlite' packages packages/opencode packages/core packages/effect-sqlite-node packages/effect-drizzle-sqlite 2>/dev/null | sed -n '1,180p' || true
echo "== opencode test fixture state cleanup =="
sed -n '213,290p' packages/opencode/test/lib/cli-process.ts
sed -n '310,380p' packages/opencode/test/lib/cli-process.ts
echo "== RunCommand full relevant sections =="
sed -n '377,590p' packages/opencode/src/cli/cmd/run.ts
sed -n '590,820p' packages/opencode/src/cli/cmd/run.ts
echo "== run events/app runtime usage section =="
rg -n -C 4 'session\.(create|list|share|fork)|process\.exit|sessionID|AppRuntime\.runPromise|Session\.Default|GlobalBus\.publish|event\.type|output' packages/opencode/src/cli/cmd/run.ts | sed -n '1,180p' || trueRepository: AltimateAI/altimate-code
Length of output: 47374
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect sqlite error classification and the source of "database is locked".
rg -n -C 8 'classifySqliteError|SQLite_ERROR_LOCK_CONTENTION|wants a lock|locked|LOCK_CONTENTION|message:|message' packages/core/src packages/effect-sqlite-node/src 2>/dev/null | sed -n '1,220p' || true
# Compare current run retry code with exact line numbers from git.
git --no-pager diff -- packages/opencode/test/lib/cli-process.ts | sed -n '1,120p' || true
sed -n '288,300p' packages/opencode/test/lib/cli-process.ts
# Narrow session creation/write side effects in RunCommand.
sed -n '556,840p' packages/opencode/src/cli/cmd/run.ts | sed -n '1,260p'Repository: AltimateAI/altimate-code
Length of output: 30444
Don’t retry non-idempotent opencode run calls on SQLite lock.
All current opencode.run() call sites run the same prompt after session.create, so a first attempt that writes session state and tracing before hitting database is locked can duplicate results or trace output on retry. Limit this retry path to idempotent command-only invocations, or reset the fixture/session state before retried execution.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/opencode/test/lib/cli-process.ts` around lines 291 - 294, Update the
retry logic around spawn in the CLI process helper to avoid retrying
non-idempotent opencode run invocations after a SQLite lock; restrict retries to
idempotent command-only calls, or reset the relevant fixture/session state
before retrying. Preserve the existing immediate return behavior for successful
and non-lock failures.
There was a problem hiding this comment.
Valid concern — the narrow /database is locked/i error-string match already limits the blast radius (a first attempt that errors before session-state write is the only class that triggers retry), but a proper fix would either reset the fixture between attempts or gate retry to command-only invocations. Filed under issue #1052 so we can design it in isolation.
There was a problem hiding this comment.
@sahrizvi, acknowledged. The current narrow error match reduces exposure, but it does not establish that the first invocation had no side effects. Deferring the retry design to #1052 is appropriate.
I will leave this finding unresolved for this PR and track the follow-up in #1052. 🐇
You are interacting with an AI system.
There was a problem hiding this comment.
1 issue found across 13 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/opencode/src/altimate/plugin/altimate.ts">
<violation number="1" location="packages/opencode/src/altimate/plugin/altimate.ts:269">
P2: Copying this URL from an SSH/tmux session to a local browser still redirects to the local workstation's loopback, so sign-in times out unless the user has separately forwarded the selected fallback port. The headless guidance could include an SSH port-forwarding path using the actual bound port, or use a device/non-loopback flow for remote browsers.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| // Remote-SSH, and without a printed URL a headless user gets no path | ||
| // forward and times out staring at "Complete sign-in in your browser". | ||
| await open(authorizeUrl).catch(() => undefined) | ||
| process.stderr.write( |
There was a problem hiding this comment.
P2: Copying this URL from an SSH/tmux session to a local browser still redirects to the local workstation's loopback, so sign-in times out unless the user has separately forwarded the selected fallback port. The headless guidance could include an SSH port-forwarding path using the actual bound port, or use a device/non-loopback flow for remote browsers.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/src/altimate/plugin/altimate.ts, line 269:
<comment>Copying this URL from an SSH/tmux session to a local browser still redirects to the local workstation's loopback, so sign-in times out unless the user has separately forwarded the selected fallback port. The headless guidance could include an SSH port-forwarding path using the actual bound port, or use a device/non-loopback flow for remote browsers.</comment>
<file context>
@@ -221,16 +249,26 @@ export async function AltimateAuthPlugin(_input: PluginInput): Promise<Hooks> {
+ // Remote-SSH, and without a printed URL a headless user gets no path
+ // forward and times out staring at "Complete sign-in in your browser".
await open(authorizeUrl).catch(() => undefined)
+ process.stderr.write(
+ `\nIf your browser didn't open automatically, complete sign-in at:\n ${authorizeUrl}\n\n`,
+ )
</file context>
There was a problem hiding this comment.
Valid — the printed URL alone doesn't help SSH/tmux users unless they've forwarded the port. A device/non-loopback flow is the right long-term answer but out of scope for a release-fix bundle. Filed under issue #1052 for the follow-up work.
…ent OAuth flows Both CodeRabbit (Major) and cubic (P1, confidence 9) flagged the same race in `startCallbackServer()`: `server` was written before `listen()` resolved and `currentCallbackPort` was undefined during the port walk. A second `authorize()` call arriving mid-startup passed the `if (server) return` short-circuit and immediately read `currentCallbackPort ?? CALLBACK_PORT_PREFERRED`, building a redirect to port 7317 — but the first flow may have fallen back to 7318-7325 because 7317 was squatted. The callback from the second flow would then never reach the listener. Coalesce concurrent starts through a shared `startupInFlight` promise. Every caller awaits the same startup and reads the actually-bound `currentCallbackPort` before constructing its redirect. The promise is cleared in a `finally` on both success and failure so a later retry re-runs the port walk cleanly. Fast-path (`if (server && currentCallbackPort !== undefined) return`) still elides the promise dance for the common case of "already bound and healthy" — no perf regression for the single-flow path.
…very text CodeRabbit (Major) and cubic (P2, confidence 9) both flagged the `HOME=/root` error message that this PR introduced: 1. `sudo HOME=/Users/you altimate-code` still writes as root, so a later normal-user run can't modify the materialized sample. 2. `/Users/you` is a macOS path — Linux users get told to run something that's platform-wrong; Windows users doubly so. Rewrite: primary guidance is now "re-run without sudo" (install to a per-user prefix like `~/.local` via `npm i -g --prefix ~/.local`, or use nvm/asdf). Secondary path is `sudo -E HOME="$HOME" altimate-code` which uses the caller's own HOME regardless of platform, with an explicit chown recovery hint for the root-owned files that result. Existing test just asserts the message contains "sudo" — still passes.
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
2 similar comments
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/docs/getting-started/quickstart-new.md`:
- Line 44: Update the scan documentation to state that credentials are not
collected or transmitted, rather than claiming they are not read. In the scan’s
telemetry-summary serialization flow, remove mapped credential fields such as
tokens and private keys before any summary is transmitted, while preserving the
non-sensitive environment summary.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 2e7e65db-62e5-4b8a-82d1-6d67a9f0f34a
📒 Files selected for processing (8)
docs/docs/getting-started/quickstart-new.mdpackages/opencode/sample-projects/jaffle-shop-duckdb/README.mdpackages/opencode/src/altimate/onboarding/materialize.tspackages/opencode/src/altimate/plugin/altimate.tspackages/opencode/src/command/template/onboard-connect.txtpackages/opencode/src/util/filesystem.tspackages/opencode/test/lib/cli-process.tspackages/opencode/test/mcp/lifecycle.test.ts
🚧 Files skipped from review as they are similar to previous changes (6)
- packages/opencode/src/util/filesystem.ts
- packages/opencode/src/command/template/onboard-connect.txt
- packages/opencode/test/lib/cli-process.ts
- packages/opencode/src/altimate/onboarding/materialize.ts
- packages/opencode/src/altimate/plugin/altimate.ts
- packages/opencode/test/mcp/lifecycle.test.ts
|
|
||
| ## Step 2.5: First-run scan (optional) | ||
|
|
||
| Immediately after model setup, a **"Scan your environment?"** Yes/No dialog appears. Say **Yes** and altimate-code reads local config files (`.dbt/profiles.yml`, `dbt_project.yml`, `.git/config`) — no credentials are read or sent, and no schema, model contents, or queries leave your computer. An anonymous environment summary (e.g. "dbt project detected, no warehouse configured") may be included in the standard telemetry stream if telemetry is enabled; disable via `OPENCODE_DISABLE_TELEMETRY=1` or the [telemetry docs](../usage/telemetry.md) if you want a strictly-offline scan. The scan then routes you into one of four branches: |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 8 \
'profiles\.yml|OPENCODE_DISABLE_TELEMETRY|telemetry|environment summary|credential|secret|password|token' \
packages/opencode packages/tui docsRepository: AltimateAI/altimate-code
Length of output: 50381
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'Tracked matching files:\n'
git ls-files 'packages/opencode/**' 'packages/tui/**' 'docs/**' \
| rg 'profiles\.yml|telemetry|scan|config|packages/opencode|packages/tui|docs/docs/getting-started/quickstart-new.md|usage/telemetry.md' \
| head -200
printf '\nCandidate symbols:\n'
rg -n -C 4 \
'profile|profiles\.yml|target-path|catalog|warehouse|host|password|token|pass|credential|secret|telemetry|OPENCODE_DISABLE_TELEMETRY|environment summary' \
packages/opencode packages/tui docs/docs docs/usage 2>/dev/null \
| head -250Repository: AltimateAI/altimate-code
Length of output: 9810
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'File stats and quickstart context:\n'
wc -l docs/docs/getting-started/quickstart-new.md
sed -n '30,55p' docs/docs/getting-started/quickstart-new.md
printf '\nLocate exact mentions in docs only (narrow):\n'
rg -n -C 5 \
'profiles\.yml|OPENCODE_DISABLE_TELEMETRY|telemetry|environment summary|credential|credential fields|secret fields|password|token' \
docs/docs docs/usage 2>/dev/null | head -200
printf '\nFind likely telemetry files:\n'
git ls-files 'packages/opencode/**' 'packages/tui/**' | rg -i 'telem|sentinel|config|scanner|scan|profile|dbt' | head -200Repository: AltimateAI/altimate-code
Length of output: 17431
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'dbt profiles registry:\n'
wc -l packages/opencode/src/altimate/native/connections/dbt-profiles.ts
sed -n '1,260p' packages/opencode/src/altimate/native/connections/dbt-profiles.ts
printf '\nTelemetry core:\n'
wc -l packages/opencode/src/altimate/telemetry/index.ts
sed -n '1,260p' packages/opencode/src/altimate/telemetry/index.ts
rg -n -C 6 \
'OPENCODE_DISABLE_TELEMETRY|telemetry|EnvironmentSummary|profiles|dbt_project|git/config|credential|secret|password|environmentSummary|summary|redact' \
packages/opencode/src/altimate packages/opencode/src/altimate/telemetry.ts packages/opencode/src 2>/dev/null \
| head -350Repository: AltimateAI/altimate-code
Length of output: 46580
Document collection as skipped before transmitting.
Line 44 claims credentials are not read or sent. profiles.yml parsing retains mapped credential fields such as token/private-key fields, so say credentials are not collected or transmitted and update the code to exclude them before serialization if the scan sends telemetry summaries.
🧰 Tools
🪛 LanguageTool
[grammar] ~44-~44: Ensure spelling is correct
Context: ... Yes/No dialog appears. Say Yes and altimate-code reads local config files (`.dbt/pro...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/docs/getting-started/quickstart-new.md` at line 44, Update the scan
documentation to state that credentials are not collected or transmitted, rather
than claiming they are not read. In the scan’s telemetry-summary serialization
flow, remove mapped credential fields such as tokens and private keys before any
summary is transmitted, while preserving the non-sensitive environment summary.
There was a problem hiding this comment.
1 issue found across 8 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="docs/docs/getting-started/quickstart-new.md">
<violation number="1" location="docs/docs/getting-started/quickstart-new.md:44">
P2: The `[telemetry docs](../usage/telemetry.md)` link on line 44 of quickstart-new.md resolves to `usage/telemetry.md` which does not exist (`docs/docs/usage/telemetry.md` not found). The actual Telemetry page lives at `reference/telemetry.md`. Visitors clicking this link from the published docs will hit a 404. Update the relative path to `../reference/telemetry.md` to point to the existing Telemetry reference page.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
|
|
||
| ## Step 2.5: First-run scan (optional) | ||
|
|
||
| Immediately after model setup, a **"Scan your environment?"** Yes/No dialog appears. Say **Yes** and altimate-code reads local config files (`.dbt/profiles.yml`, `dbt_project.yml`, `.git/config`) — no credentials are read or sent, and no schema, model contents, or queries leave your computer. An anonymous environment summary (e.g. "dbt project detected, no warehouse configured") may be included in the standard telemetry stream if telemetry is enabled; disable via `OPENCODE_DISABLE_TELEMETRY=1` or the [telemetry docs](../usage/telemetry.md) if you want a strictly-offline scan. The scan then routes you into one of four branches: |
There was a problem hiding this comment.
P2: The [telemetry docs](../usage/telemetry.md) link on line 44 of quickstart-new.md resolves to usage/telemetry.md which does not exist (docs/docs/usage/telemetry.md not found). The actual Telemetry page lives at reference/telemetry.md. Visitors clicking this link from the published docs will hit a 404. Update the relative path to ../reference/telemetry.md to point to the existing Telemetry reference page.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docs/docs/getting-started/quickstart-new.md, line 44:
<comment>The `[telemetry docs](../usage/telemetry.md)` link on line 44 of quickstart-new.md resolves to `usage/telemetry.md` which does not exist (`docs/docs/usage/telemetry.md` not found). The actual Telemetry page lives at `reference/telemetry.md`. Visitors clicking this link from the published docs will hit a 404. Update the relative path to `../reference/telemetry.md` to point to the existing Telemetry reference page.</comment>
<file context>
@@ -41,7 +41,7 @@ altimate
## Step 2.5: First-run scan (optional)
-Immediately after model setup, a **"Scan your environment?"** Yes/No dialog appears. Say **Yes** and altimate-code reads local config files (no credentials sent, nothing leaves your computer) and routes you into one of four branches:
+Immediately after model setup, a **"Scan your environment?"** Yes/No dialog appears. Say **Yes** and altimate-code reads local config files (`.dbt/profiles.yml`, `dbt_project.yml`, `.git/config`) — no credentials are read or sent, and no schema, model contents, or queries leave your computer. An anonymous environment summary (e.g. "dbt project detected, no warehouse configured") may be included in the standard telemetry stream if telemetry is enabled; disable via `OPENCODE_DISABLE_TELEMETRY=1` or the [telemetry docs](../usage/telemetry.md) if you want a strictly-offline scan. The scan then routes you into one of four branches:
- **Found a warehouse** → offers to add + verify each connection, then index its schema.
</file context>
…lify sample path
Consensus review found the PEP 668 escape hatches were broken.
**M1** — `pipx install dbt-duckdb` and `uv tool install dbt-duckdb`
succeed, but neither exposes a `dbt` binary. `dbt-duckdb` is an
adapter package with no `console_scripts` — the `dbt` entry point
lives in `dbt-core` (a dependency). `pipx install` and `uv tool
install` only expose entry points from the target package, so users
hit "no `dbt` on PATH" at the exact point they'd been redirected TO
after `pip` failed with `externally-managed-environment`.
Fix in `onboard-connect.txt`:
- `pipx install --include-deps dbt-duckdb` (exposes dbt via deps)
- `uv tool install dbt-core --with dbt-duckdb` (dbt-core primary,
adapter as extra)
Sample README expanded with the three-package explanation (dbt-core,
dbt-duckdb, duckdb-cli — different jobs) and a working PEP 668
alternatives block.
**n1** — Sample path was presented as unconditional
(`~/altimate-sample-dbt/`). `findSafeTarget` may pick a suffixed
variant, and `rejectUnsafeHome` errors out entirely for `/root` and
tmp-backed homes. Reworded to "by default" with a note about the
suffix behavior + a pointer to the tool's `path:` output.
…t concurrency comment; symmetric error handler Three related fixes to `altimate.ts`, all surfaced by the consensus review of PR #1053. **M2 (MAJOR)** — The `process.stderr.write(...)` echoing the authorize URL for SSH/tmux users doesn't work. The auth plugin runs inside a TUI worker whose stdio is redirected to the log file at the very top of `packages/opencode/src/cli/tui/worker.ts` (a deliberate guard to prevent library logging from corrupting the TUI render). The write reached the log, never the terminal. Also redundant: `packages/tui/src/component/dialog-provider.tsx:446` already renders the authorize URL as a clickable Link and binds `c` to copy it to the clipboard — the SSH/tmux user can see AND copy the URL from the dialog they're already looking at. Removed. Every sign-in previously wrote a `state`-bearing authorize URL into the log unconditionally (even on successful browser open) — that leak now stops too. **m2 (MINOR)** — My earlier comment claimed keying by `state` "lets two concurrent /auth flows coexist without clobbering each other". The layer above (`ProviderAuth.authorize`) stores one pending flow per provider — a second concurrent Altimate sign-in would overwrite the first's `pending` entry regardless. Rewrote the comment to state the actual invariant (per-state keying handles out-of-order callback arrival; concurrent same-provider sign-ins are unsupported at the layer above). **m10 (MINOR)** — On the successful bind iteration of the port walk, `server.on("error", reject)` stayed wired past success. A later runtime server error would then call `reject()` on an already- resolved promise (silent no-op), swallowing the diagnostic. Switched to a named handler bound with `once()` + explicit `removeListener()` on the success path, with a defensive `removeAllListeners("error")` in `finally` for any future non-error-event rejection.
…icate; drop invented comment history Consensus review m7 + m8: the "is any provider connected" predicate was duplicated verbatim in `use-connected.tsx` and `home/tips.tsx`, and the comment I added in `use-connected.tsx` invented a regression that never existed (claimed the `provider.id !== "opencode" || ...` short-circuit had been "tightened" to exclude legitimate paid providers — but the short-circuit had always exempted non-OpenCode providers, so the described regression was mathematically impossible). Fix: 1. Extract `isAnyProviderConnected(providers)` into `util/connected.ts` with the accurate rationale (why the cost gate is OpenCode-specific, why undefined cost counts as "not paid" for OpenCode only). 2. Both `use-connected.tsx` (welcome-picker gate) and `home/tips.tsx` (first-run tip visibility) call the extracted helper. Cannot silently drift now. 3. Dropped the invented "regression grandfather" narrative — the refactor from `A || B` to `if (A) return true; return B` was and is a faithful no-op; the comment now says only that. Consensus review warning: three separate reviewers repeated the false grandfather history back as established fact. Removing the source prevents that from becoming institutional memory.
…ess guard; drop unreachable sentinel Three fixes from the consensus review of PR #1053. **m3 — cli-process.ts SQLite retry observability**: the retry was silent on the retry path, so a systematic regression from transient lock contention would keep the suite green — defeating the point of the harness. Added a `console.warn` that names the failure class and the "if you see this often, contention has moved from transient to systematic" signal, so a repeated pattern is visible in CI logs. **m5 — smoke-test-binary staleness guard walks src/ + script/**: the prior guard compared only against `script/build.ts`. That catches the rare "build logic changed" case but MISSES the common "src/ changed" case — after a `git pull` that only touches source, the guard would still say the binary is fresh and run assertions against a stale build. Rewrote `isBinaryStale()` to walk both trees, skipping `node_modules` / `.turbo` / `dist` / hidden dirs, and looking at files that actually contribute to the compiled binary (`*.ts{,x}`, `*.json`, `*.txt`, `*.md`). **m6 — sample_setup error metadata: revert suffix: -1 → 0**: the sentinel guarded a collision no consumer can reach. Error-path `output` contains no `suffix:` line at all (it's `status: error\n reason: ...\n\n${message}`), and the template branches on `status: error` first. `success: false` is the true disambiguator for metadata readers. Reverted the sentinel and updated the comment to reflect the actual disambiguation contract.
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
2 similar comments
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
There was a problem hiding this comment.
2 issues found across 9 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/opencode/test/install/smoke-test-binary.test.ts">
<violation number="1" location="packages/opencode/test/install/smoke-test-binary.test.ts:126">
P2: The extension filter includes `.md` files when checking staleness, but `.md` files under `src/` and `script/` are never embedded in the binary — editing a README or AGENTS doc would falsely skip the smoke tests. Drop `.md` from the regex to match the comment's intent (`*.ts / *.tsx / *.json / *.txt`).</violation>
</file>
<file name="packages/opencode/src/altimate/plugin/altimate.ts">
<violation number="1" location="packages/opencode/src/altimate/plugin/altimate.ts:209">
P1: A post-bind `http.Server` error can now crash the TUI worker: this removes the only `error` listener immediately after the bind succeeds, while Node treats an emitted `error` without a listener as uncaught. Keeping a persistent server-level handler after removing the bind-attempt listener would preserve the retry behavior without leaving the live callback server unprotected.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
| } | ||
| server!.once("error", onErr) | ||
| server!.listen(port, "127.0.0.1", () => { | ||
| server!.removeListener("error", onErr) |
There was a problem hiding this comment.
P1: A post-bind http.Server error can now crash the TUI worker: this removes the only error listener immediately after the bind succeeds, while Node treats an emitted error without a listener as uncaught. Keeping a persistent server-level handler after removing the bind-attempt listener would preserve the retry behavior without leaving the live callback server unprotected.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/src/altimate/plugin/altimate.ts, line 209:
<comment>A post-bind `http.Server` error can now crash the TUI worker: this removes the only `error` listener immediately after the bind succeeds, while Node treats an emitted `error` without a listener as uncaught. Keeping a persistent server-level handler after removing the bind-attempt listener would preserve the retry behavior without leaving the live callback server unprotected.</comment>
<file context>
@@ -182,21 +186,45 @@ async function doStartCallbackServer(): Promise<void> {
+ }
+ server!.once("error", onErr)
+ server!.listen(port, "127.0.0.1", () => {
+ server!.removeListener("error", onErr)
+ resolve()
+ })
</file context>
| // Only consider files that actually contribute to the compiled binary | ||
| // — build.ts globs *.ts / *.tsx / *.json / *.txt for embedding. A | ||
| // stray editor swap file (.swp) or backup shouldn't trigger a re-skip. | ||
| if (!/\.(tsx?|json|txt|md)$/.test(entry.name)) continue |
There was a problem hiding this comment.
P2: The extension filter includes .md files when checking staleness, but .md files under src/ and script/ are never embedded in the binary — editing a README or AGENTS doc would falsely skip the smoke tests. Drop .md from the regex to match the comment's intent (*.ts / *.tsx / *.json / *.txt).
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/test/install/smoke-test-binary.test.ts, line 126:
<comment>The extension filter includes `.md` files when checking staleness, but `.md` files under `src/` and `script/` are never embedded in the binary — editing a README or AGENTS doc would falsely skip the smoke tests. Drop `.md` from the regex to match the comment's intent (`*.ts / *.tsx / *.json / *.txt`).</comment>
<file context>
@@ -89,19 +89,59 @@ function resolveNodePath(): string {
+ // Only consider files that actually contribute to the compiled binary
+ // — build.ts globs *.ts / *.tsx / *.json / *.txt for embedding. A
+ // stray editor swap file (.swp) or backup shouldn't trigger a re-skip.
+ if (!/\.(tsx?|json|txt|md)$/.test(entry.name)) continue
+ try {
+ const m = fs.statSync(full).mtimeMs
</file context>
| if (!/\.(tsx?|json|txt|md)$/.test(entry.name)) continue | |
| if (!/\.(tsx?|json|txt)$/.test(entry.name)) continue |
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
…s as paired start/end blocks Marker Guard CI is strict: single-line `// altimate_change — description` comments don't count as protection for the code that follows. My m8 refactor used the single-line form for both the import and the `isAnyProviderConnected` call in `home/tips.tsx`, and the guard on the PR's CI run flagged the `const connected = ...` line as unmarked new code in an upstream-shared file. Rewrap both spots as `// altimate_change start` / `// altimate_change end` blocks so the guard's `computeMarkedLines` coverage map includes the extracted-predicate call site. No behavior change; comment form only.
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/tui/src/feature-plugins/home/tips.tsx (1)
51-53: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winClose the
altimate_changeblock before Line 54.The marker at Line 51 has no matching
altimate_change endbefore the block that starts at Line 54. Add the end marker afterconst connectedto avoid nested markers.Proposed fix
const connected = createMemo(() => isAnyProviderConnected(api.state.provider)) +// altimate_change end // altimate_change start — upstream_fix: restore first-run onboarding state🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/tui/src/feature-plugins/home/tips.tsx` around lines 51 - 53, Add the matching altimate_change end marker immediately after the connected memo declaration in the tips component, closing the marker block before the following block begins and leaving the predicate unchanged.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/tui/src/feature-plugins/home/tips.tsx`:
- Around line 51-53: Add the matching altimate_change end marker immediately
after the connected memo declaration in the tips component, closing the marker
block before the following block begins and leaving the predicate unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 3424b8b9-8f1b-4f1e-9db4-25220700a76f
📒 Files selected for processing (9)
packages/opencode/sample-projects/jaffle-shop-duckdb/README.mdpackages/opencode/src/altimate/plugin/altimate.tspackages/opencode/src/altimate/tools/sample-setup.tspackages/opencode/src/command/template/onboard-connect.txtpackages/opencode/test/install/smoke-test-binary.test.tspackages/opencode/test/lib/cli-process.tspackages/tui/src/component/use-connected.tsxpackages/tui/src/feature-plugins/home/tips.tsxpackages/tui/src/util/connected.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- packages/opencode/test/lib/cli-process.ts
- packages/opencode/sample-projects/jaffle-shop-duckdb/README.md
- packages/tui/src/component/use-connected.tsx
- packages/opencode/src/command/template/onboard-connect.txt
…name in comments Marker Guard step 9 (branding audit, LEAK_PATTERNS regex `/\bOpenCode\b/g`) flagged two mentions of the upstream product name in the new file's docstring comments. Reworded to reference the provider-id string literal (`` `"opencode"` ``, `` `opencode` provider ``) which is code identity, not branding. Same technical content, no product-name leak. The prior mention in `component/use-connected.tsx:6` is untouched — it lives inside an `altimate_change` block, which the branding audit whitelists as intentional fork commentary. Verified locally: `bun run script/upstream/analyze.ts --branding` reports 0 leaks.
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
1 similar comment
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
Added:
- First-run scan + activation menu (bundled 6-provider picker, scan
gate with 4 branches, numbered activation menu wired to real skills).
- Bundled jaffle-shop DuckDB sample project with pre-compiled manifest
so /discover + /review work without dbt-core installed.
Fixed:
- Loopback OAuth port walk 7317-7325 + 15-min pending window +
concurrent-startup coalescing.
- CI test-isolation leak (spyOn(os,"homedir") without restore).
- HOME=/root recovery message: portable + ownership-safe.
- PEP 668 install fallbacks (pipx/uv) actually expose a dbt binary.
- Scan telemetry disclosure honest about anonymous env summary.
- sample_setup error metadata shape (suffix: -1 → 0).
- Auth plugin no longer leaks state-bearing URLs into log files.
Changed:
- useConnected + home-tips share one predicate
(packages/tui/src/util/connected.ts).
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
1 similar comment
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
Summary
Fixes the actionable items from the v0.9.4 pre-release multi-persona review (CTO, PM, Data Engineer, Tech Lead, Support Engineer), plus all findings from the subsequent bot review (CodeRabbit + cubic) and the local consensus review (6 reviewers). Twelve original items; A5 dropped as false positive. Everything requiring more than a 30-min patch was deferred to tracking issue #1052.
Also deletes one flaky TUI e2e file (already CI-skipped) that was emitting noise on every local suite run.
Changes
Original persona-review actionables (A1–A12, 11 commits)
os.homedirspy inmcp/lifecycle.test.ts— root cause of the red TypeScript check on PR #1001.spyOnhad no restore, poisoning six tilde-expansion tests inpermission/next.test.tswhen bun loaded the next file.--target-parentnever existed; users hit "unknown flag". Later refined byB2(portable + ownership-safe wording).A4stderr echo of the authorize URL was later removed — seeM2— after review discovered the worker's stdio redirect swallowed it AND the TUI dialog already renders + copies the URL.)useConnected()clarified. Semantically identical to the pre-refactor code (later extracted to a shared predicate — seem8).~/altimate-sample-dbt/in the menu row; offer PEP 668 alternatives (pipx/uv/ venv) alongside plainpip.quickstart-new.mdrewritten: welcome panel + curated 6-provider picker + Altimate LLM Gateway top row; new Step 2.5 for the first-run scan gate; explicit note that the activation menu is chat text (interactive picker deferred to #1052 / D1).jaffle-shop/README.mdreordered: activation-menu path leads; bare-shell pip flow appendix.sample_setuperror metadata suffix sentinel (later reverted — seem6).writeJsonAtomicdocstring reflects that the call-site sweep is a tracked follow-up.phase-label.tui-e2e.test.ts— flaky locally (bootstrap-span duration races the PTY poll interval), alreadytest.skipin CI.Bot-review round (CodeRabbit + cubic, 4 commits)
startupInFlightpromise so concurrent OAuth flows all use the actually-bound port./Users/youplatform assumption; primary advice = re-run withoutsudo; secondary =sudo -E HOME="$HOME" altimate-codewithchownrecovery hint)./issues/1052inwriteJsonAtomicdocstring;duckdb-cliinstall line in sample README).mkdtempout ofos.homedirmock; retry shares timeout budget).Consensus-review round (6-reviewer local consensus, 4 commits)
pipx install dbt-duckdbanduv tool install dbt-duckdbexpose NOdbtbinary (the entry point ships withdbt-core, a dep). Users hit a second dead end after PEP 668. Fixed topipx install --include-deps dbt-duckdbanduv tool install dbt-core --with dbt-duckdb.stderr.writeof the authorize URL. The auth plugin runs inside a TUI worker whose stdio is redirected to the log file — the write reached the log, never the terminal. Also redundant (dialog-provider.tsx already renders + copies). Removed to stop leaking state-bearing URLs into logs.useConnectedgrandfather history; usesonce()+removeListeneron success too, so a later runtime server error isn't silently swallowed).console.warnon the retry path so a systematic regression stays visible.isBinaryStale()walkssrc/+script/for the newest source mtime instead of justscript/build.ts; catches the common "src edited" case, not just "build logic edited".suffix: -1sentinel insample_setup(the sentinel guarded an unreachable collision).isAnyProviderConnected()topackages/tui/src/util/connected.tssouse-connected.tsxandhome/tips.tsxcan't drift.~/altimate-sample-dbt/is the default, not unconditional).Deferred (tracked in issue #1052)
11 items, including the 3 new deferrals from bot + consensus review:
cli-process.run().Test plan
bun turbo typecheck— 13/13 workspaces greenpackages/opencodeCI-mode suite: CI run on HEAD reportspass=10994 fail=0(job 30607912838)permission/next.test.tstilde-expansion tests), which A1 root-fixesNote on the acp/permission local-only failures
Earlier drafts of this description attributed the 6 local
test/acp/permission.test.tsfailures to "a macOS scheduling flake absent on CI's Linux runner". That was wrong. Commit2cbc1e818croot-caused them:ALTIMATE_CLI_YOLO=truein the developer's shell env (direnv-managed) short-circuitedpackages/opencode/src/acp/permission.ts:57, auto-approving every permission and bypassing every assertion. Fixed by adding an env-hermetic guard in the test file that snapshots + restores the env var. Verified: 6/6 pass with and withoutALTIMATE_CLI_YOLO=truein the parent env.Related
Notes
main(not a feature branch).Summary by CodeRabbit
New Features
Bug Fixes
Documentation