All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
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.
- First-run scan + activation menu. Fresh installs land on a curated 6-provider picker with Altimate LLM Gateway on top, then a Yes/No "Scan your environment?" gate that reads local config files (
.dbt/profiles.yml,dbt_project.yml,.git/config) and routes into one of four branches — warehouse found, dbt-only, git-repo-no-dbt, nothing yet. The last branch offers to materialize a bundled jaffle-shop DuckDB sample dbt project (~/altimate-sample-dbt/by default; a suffixed variant if the name is taken) so a user with no warehouse can try Altimate against real data, real dbt models, without touching production. Every branch ends on a numbered "What would you like to do?" menu wired to real skills. (#1001) - Bundled jaffle-shop DuckDB sample project. Ships with a pre-compiled
target/manifest.jsonso/discoverand/reviewwork without dbt-core / dbt-duckdb installed.dbt buildneedspip install dbt-duckdb duckdb-cli(orpipx install --include-deps dbt-duckdb/uv tool install dbt-core --with dbt-duckdbif you hit PEP 668). (#1001)
- Loopback OAuth sign-in is resilient to port collisions and long-SSO windows. The Altimate LLM Gateway callback server now walks 7317-7325 on
EADDRINUSE(a squatting dev tool on 7317 no longer wedges sign-in) and reports the actual bound port in the redirect. The pending-flow window extended from 5 min to 15 min so corporate SSO + MFA can finish. Twoauthorize()calls arriving concurrently now share one startup promise — both see the actually-bound port instead of one racing past on a stale/undefined value. (#1053) - CI test-isolation leak that turned six
permission/next.test.tstilde-expansion tests red.mcp/lifecycle.test.tswas spying onos.homedir()inbeforeEachwith nomockRestore; the mock leaked forward into the next test file bun loaded, poisoning the tilde-expansion suite with a tmp path. Captured the spy handle and restored it inafterEach. Root-fix on the class, not the symptom. (#1053) HOMErecovery message is portable and doesn't tell users to write as root. The prior text pointed at/Users/you altimate-code(macOS-only) and suggestedsudo HOME=…which writes root-owned files a normal-user run then can't modify. Primary guidance is now "re-run without sudo" (install to a per-user prefix, or use nvm/asdf); secondary issudo -E HOME="$HOME" altimate-codewith an explicitchownrecovery hint. (#1053)- PEP 668 install fallbacks actually expose a
dbtbinary.pipx install dbt-duckdbanduv tool install dbt-duckdbboth succeed but neither publishes thedbtentry point (it ships withdbt-core, a dependency). Users who followed the fallback afterpiprefused withexternally-managed-environmenthit a second dead end at their point of maximum frustration. Fixed topipx install --include-deps dbt-duckdbanduv tool install dbt-core --with dbt-duckdb. The venv option also now asks for the absolute path —~/.venvs/dbt/bin/dbtwouldn't expand under the CLI's single-quoted validation. (#1053) - Scan disclosure is honest about telemetry. The first-run scan's docs previously claimed "nothing leaves your computer". The scan itself doesn't send credentials, model contents, queries, or schema — but it does emit an anonymous environment summary (dbt-detected, warehouse-configured, etc.) through the standard telemetry pipeline if telemetry is enabled. Disclosure updated;
OPENCODE_DISABLE_TELEMETRY=1remains the offline-strict switch. (#1053) sample_setuperror metadata no longer collides with success shape. The unreachablesuffix: -1sentinel was reverted to0;success: falseis the disambiguator for metadata consumers, and the erroroutputstring separately beginsstatus: errorfor the LLM template's failure branch. (#1053)- The auth plugin no longer leaks state-bearing authorize URLs into log files. An earlier revision wrote the authorize URL to
process.stderras a fallback for SSH/tmux users; the auth plugin runs inside a TUI worker whose stdio is redirected to the log file (packages/opencode/src/cli/tui/worker.ts), so the write never reached the terminal it was written for. Removed. The TUI's auth dialog already renders the URL as a clickable link and bindscto copy it to the clipboard. (#1053)
useConnectedand the home-tips visibility gate now share one predicate. The "is any provider connected?" logic was duplicated incomponent/use-connected.tsxandfeature-plugins/home/tips.tsx; both now callisAnyProviderConnectedfrompackages/tui/src/util/connected.tsso a future edit to one can't drift them apart. Behavior unchanged (a semantically identical refactor). Non-opencodeproviders count as connected regardless ofcostmetadata (BYOK / self-hosted / custom-registration path); theopencodeprovider still requires a nonzero-cost model to count. (#1053)
Focused polish on the altimate review dbt PR reviewer — plus TUI startup UX
and audit-trail hardening on the signed verdict envelope.
- Grain-key
not_nullcompleteness detector. For every column named in aunique_combination_of_columnstest (or thedbt_utilsequivalent), the reviewer now checks that anot_nulltest or constraint exists on the same column — without it, a NULL grain value silently passes the uniqueness guardrail. Supports contracted models (constraints:withcontract.enforced: true), column-leveldata_tests:/tests:, and model-level primary-key constraints. Case-folds column names for Snowflake compatibility. Delivered +11 real findings on the internal 5-PR corpus. (#1029) --explain-tierflag. Pass--explain-tierto surface the classifier's tier-reason list on the verdict envelope so you can see why a diff was ratedtrivial,lite, orfull. Full-tier verdicts also now include the reason line in the PR comment by default (no flag required), so aREQUEST_CHANGESon a schema.yml diff is never unexplained. (#1027)--force-tierflag. [EXPERIMENTAL / bench debug] Bypass the classifier with--force-tier=trivial|lite|full. The signed envelope carriestierForced: trueand the classifier's original decision, so an auditor always sees the bypass — the flag can't be used silently. (#1027)riskTierPathTokensconfig in.altimate/review.yml. Configure named token categories (includingpreset:finopsfor the built-in cost/billing keyword list) to promote matching files to full review tier. Previously the FinOps preset was hardcoded and always on; it is now opt-in via this config. A typo in a category value surfaces in both stderr and the verdict envelopetierReasons[](and the PR comment) so it can't kill your opt-in silently. (#1028)engine.cliVersionin the signed verdict envelope. The altimate-code release that generated each verdict is now stamped intoengine.cliVersionand covered by the HMAC signature — auditors reconstructing decisions from stored envelopes months later can identify which policy version applied.staleManifestflag on the verdict envelope. When a change-affecting source file has been modified after the manifest was written, the signed envelope now carriesstaleManifest: true. A stderr warning alone is easy for CI to swallow; the envelope field is durable and part of the signed body.- Bootstrap phase labels in the TUI. While the agent initializes, the busy spinner now shows what it is actually doing ("Loading config…", "Discovering tools…", "Thinking…") matching the convention users already know from other agent UIs. Phase events are also emitted as trace spans for server-side latency profiling. (#1002)
- Risky dbt metadata surfaces never auto-approve. PRs that touch
data_tests:,tests:,constraints:,contract:, orunique_combination_of_columnsin schema.yml undermodels/marts/— or files under any configuredriskTierPathTokenscategory — are always promoted tofullreview tier. A small metadata diff can no longer slip through ontrivialclassification. Grounded in a corpus study where two PRs auto-approved with 8–11 human-visible findings each. CI ingatemode may see exit-code changes on affected PRs. (#1028) --no-aiflag now actually disables the LLM lane. A yargsboolean-negationconflict caused a bare--no-aito silently fall into the help path (exit 0, no review ran). The flag is fixed; CI scripts using--no-aisince v0.8.x should verify behavior on upgrade — those runs may have been executing the AI lane and getting billed. (#1027)altimate reviewauto-discoverstarget/manifest.json. When--manifestis not passed and the config-relative path doesn't resolve, the reviewer walks up fromcwdto the nearestdbt_project.ymland uses its adjacenttarget/manifest.json. Discovery is logged to stderr; explicit--manifeststill wins. Removes the most common "review did nothing" support case for mono-repo invocations. (#1027)- schema.yml test-removal detection is now column-aware. The detector parses both sides of the diff structurally (YAML parse rather than diff-line pattern) and keys removals by
(model, column, test)— eliminating false cancellations where a sibling column re-added the same test type. (#1027) - Stale-manifest detection now runs for local working-tree reviews too. Previously gated behind
--head, so the local workflow "dbt compileonce, edit for an hour, thenaltimate review" — where staleness bites in practice — silently under-warned. The check is limited to files that could materially change the manifest (models, schema.yml, seeds, macros, dbt config) so noise stays bounded.
- Snowflake Cortex:
claude-sonnet-5,claude-opus-4-8, and OpenAI GPT-5.4 (openai-gpt-5.4,-mini,-nano) in the model picker. All verified live against Cortex, including prompt caching and tool calling on the new Claude models. - Human-readable tool-call titles and source badges. Tool calls now render dbt-aware labels — "Reading customers model", "Searching **/*.sql" — instead of raw paths, and every call carries an authoritative source badge (
builtin/altimate/mcp) stamped server-side so all clients (chat webview, TUI) display consistent origins. (#980)
- Snowflake Cortex model catalog refreshed against the live service (2026-07-20). Removed models Snowflake has deprecated (July 8, 2026:
deepseek-r1,mistral-large,llama3.1-405b,snowflake-llama-3.3-70b) or delisted (claude-3-7-sonnet,claude-3-5-sonnet,openai-gpt-5-chat,llama4-scout,mixtral-8x7b,snowflake-llama-3.1-405b,gemini-3.1-pro) — requests to these now hard-fail on Cortex. If your config pins one of these IDs, the next request fails withModel not found: snowflake-cortex/<model>. Did you mean: ...?— switch to a current model, or re-register the ID viaaltimate-code.json(see the providers docs). Locally registered models are unaffected.
- Snowflake Cortex prompt caching now activates for Claude models. Cortex only honors caching markers placed inside content blocks (
messages[].content[].cache_control), but requests carried them as message-level fields — so every request billed the full input rate (cache_read_input/cache_write_inputstayed NULL inTOKENS_GRANULAR). The provider now relocates the markers into content blocks (system prompt + trailing messages, max 4 breakpoints), so repeated prefixes bill at Snowflake's reduced cached-input rate — savings are workload-dependent and largest on long agent sessions with big stable prefixes. If a Cortex account rejects the marked shape, the request is retried once without markers and marker injection pauses for a 5-minute cooldown. Note for Snowflake admins:cache_read_input/cache_write_inputinTOKENS_GRANULARbegin populating for these workloads (previously always NULL) — update any dashboard queries that assumed those columns were NULL. (#1009) - Legacy documentation links canonicalized.
docs.altimate.sh,datamates-docs.myaltimate.com, andwww.altimate.sh/benchmarksreferences (including the TUI's docs links and system prompts) now point tohelp.altimate.aiandaltimate.ai/benchmarks. (#1004)
This release rebases altimate-code onto upstream OpenCode v1.17.9 (bridged up from v1.4.0 — ~165 upstream commits) behind the fork's own fixes and hardening. It is a larger-than-usual jump from 0.8.10; the upgrade is automatic and in-place (see Upgrading from 0.8.10 below).
- MCP tool calls now correctly enforce the permission check. During the v1.17.9 re-home, the MCP tool wrapper awaited a permission
Effectwithout running it, so an MCP tool could execute without going through the permission prompt. It was caught in pre-release review and never reached a published stable release; upgrading closes the gap. Users who loosened permissions expecting MCP tools to run unprompted will now see the prompt they were always meant to go through. (e7ec6a9b29) - The
sensitive_writeguard now actually fires on paths it previously let through by defaulting open. (#209 follow-up)
- Bearer-auth remote MCP servers via
headersCommand. A remote MCP entry can now compute header values by running a command (argv form, run viaexecFile— no shell), re-resolved on every connect so short-lived bearer tokens refresh automatically. This unlocks token-gated servers such as Microsoft Fabric Core MCP and Azure Entra ID without a local proxy. When anAuthorizationheader is present (statically or viaheadersCommand) andoauthis not explicitly configured, OAuth auto-detection is disabled so the bearer token isn't overridden; servers that returnnulltool-annotation hints (Fabric) are tolerated. See the MCP servers docs. (#793, #791, #792) - A
sourcefield onsession_starttelemetry, so extension-spawned sessions sharing onealtimate serveprocess are distinguishable. (#968)
- Upstream OpenCode v1.4.0 → v1.17.9 bridge merge. Config validation moved from Zod to Effect
Schema, the MCP layer was rewritten onto Effect, and session persistence moved to the coreSessionTable. Existing config files and local databases are migrated/adapted automatically on first launch. (#964) - Background auto-upgrade now only auto-applies patch releases. A minor/major release (like this one) shows a notification instead — run
altimate upgradeexplicitly to move onto 0.9.x. This bounds exposure to large jumps. - Model reasoning ("thinking") is collapsed by default. It could previously render expanded for existing users, which risked showing pasted secrets in the reasoning trace. Toggle full visibility back on with
/thinking. (e695b536f4)
- Upgrade-path database-migration hardening. Fixed a duplicate-column crash on legacy databases created by older binaries, a fresh-install crash, and unbounded migration-journal row growth — so a 0.8.10 database migrates cleanly and idempotently to 0.9.1. (
cf62f1f512,57584ed4d8,27c490515a) - TUI and runtime fixes carried in from the bridge: clicking a truncated URL opens the full URL (#976); Ctrl+A/Ctrl+E and history recall restored in the prompt (#973, #975);
/mcpsautocomplete de-duplicated and the MCP auth command surfaced (#971, #972, #974); reviewer mode made usable (#978); session traces pruned by modification time rather than filename.
- No manual steps required. First launch on 0.9.1 runs an automatic, idempotent database migration (validated against mixed old/new-binary databases).
- Config validation is now stricter (Effect
Schema). If configured providers, agents, or MCP servers appear to disappear after upgrading, your global config may have failed validation and fallen back to defaults — check the logs for the offending key and report it. - As a precaution before a jump this large, you may back up
~/.local/share/altimate-code/opencode.dbfor a rollback path.
- Merge-resolution correctness: Fabric annotation-hint tolerance was folded into the gated
listToolsfallback (keyed off the Zod issue-payload shape to avoid false-positive retries), andheadersCommandwas added to the Effect-SchemaMCP config. Conflict resolutions were verified via Codex deep-review, the fullpackages/opencodesuite (10,647 pass), and a v0.9.1 adversarial suite. - Release infra: the release version derives from the fork package; prerelease tags publish to the npm
betachannel; auto-generated release notes now diff against the last stable ancestor tag. - Deferred review findings filed as #995–#1000.
- The daily date no longer invalidates the cached system prompt across midnight. The volatile "Today's date" line was the first entry in the cache-controlled system prefix, so a session left open across midnight within the cache TTL dropped its entire cached system prompt and paid to rebuild it. The date now rides the trailing user message — off the long-lived system-prefix cache and onto the rolling per-turn breakpoint that is rewritten every turn anyway — so the cached system bytes stay date-invariant and the agent still receives today's date each turn. (#950, fixes #949)
- The Windows installer Pester suite is deterministic on the updated
windows-latestrunner. The harness now appliesPROCESSOR_*overrides inside the childpwshsession instead of relying on Process-scope inheritance, which the new runner image re-initialized for the loader-managedPROCESSOR_ARCHITECTURE(it arrived blank → a spuriousUnsupported OS/Archfailure). Test-only: the shippedinstall.ps1and the v0.8.9 binaries are unaffected — real users always have a populatedPROCESSOR_ARCHITECTURE. (#959, fixes #958) - Added a v0.8.10 adversarial + coverage suite that closes the prior test gap on the date fix — it exercises the trailing-user-message path (date reaches the model, only the last user turn is tagged, no accumulation across turns, survives an all-ignored user turn) plus a static regression guard on the Windows installer harness. (#950, #959)
- The non-interactive
runguard no longer mis-handles a blank env var. A blank/whitespaceALTIMATE_NON_INTERACTIVE=is now treated as unset, so it can't silently reintroduce the headlessrunhang that #937 fixed. (#937 follow-up) - Session transcript boolean query flags accept the common falsey strings.
thinking,toolDetails, andassistantMetadatanow treatfalse/0/no/off(case-insensitive) as false, not just the literal"false". (#941 follow-up) - Writing an MCP server entry refuses to clobber an unparseable config (detected via
parse()with an error sink, not the error-tolerantparseTree()), andupdatedAtis preserved through config normalization so the datamate reconnect signal survives. (#893 follow-up) - dbt error bubbling strips the full ANSI escape family (cursor/erase sequences from progress spinners), not just SGR color codes. (#933 follow-up)
- The headless
servestartup upgrade check is jittered (base + random, ~1–6s) so a fleet restarting together doesn't stampede the unauthenticated GitHub releases API in the same instant. (#940 follow-up)
- Diverged upstream constants are wrapped in
altimate_changemarkers (DEFAULT_CHUNK_TIMEOUT, the question-tooloutputfield) so they survive upstream merges. (#844, #937) - Added a v0.8.9 adversarial test suite covering the shipping code and the review fixes under hostile input (question-tool env matrix, MCP config parse-guard, startup-upgrade fail-safety + jitter).
- Windows now has a one-line PowerShell installer.
irm https://www.altimate.sh/install.ps1 | iexdownloads the standalone binary from GitHub releases (AVX2-aware, with a baseline fallback), adds it to your userPATH, and supports-Version,-NoPathUpdate, and-ForceBaseline.altimate upgradeuses the same path on Windows. (#930) - IDE-aware datamate transport, MCP enabled-state persistence, and a
/mcpscommand. The active IDE'smcp.jsondatamate entry/URL is mirrored intoaltimate-code.jsonand reconnected when it changes; enabled/disabled state for MCP servers now persists to disk;/mcpslists and toggles servers; projectmcp.jsonfiles are discovered recursively (project-scoped servers are discovered disabled, never auto-connected). (#893) - Session transcript REST endpoint for the datamates extension.
GET /session/:id/transcriptreturns the full conversation as formatted Markdown, withthinking,toolDetails, andassistantMetadataquery flags. (#941)
- Headless
servenow checks for and applies updates on startup. Whenautoupdateis unset (the default) and a supported install method is present,serveperforms a one-shot, best-effort self-upgrade shortly after start. It never restarts the running process and can never crashserve(errors are swallowed). Opt out withautoupdate: falseor"notify"in config, orOPENCODE_DISABLE_AUTOUPDATE=1. (#940) - The per-chunk streaming watchdog timeout was raised from 2 minutes to 5 minutes so slow warehouse/LLM streams are not aborted prematurely. (#844)
dbt show/compilefailures now surface the real dbt error instead of a generic "Could not parse", with inline SQL redacted from the message so secrets/PII don't leak into logs. (#933)- The question tool no longer hangs in non-interactive contexts.
altimate runis detected as headless and returns "Unanswered" (letting the agent decide) rather than blocking forever;ALTIMATE_AUTO_ANSWER=first|last|<label>can pre-answer. (#937) - Windows release archives are verified by checksum in both installers before extraction, and latest-version resolution is more resilient to transient fetch failures. (#942, #946)
servelogs the trace directory on startup so operators can find session traces. (#929)- Added a release-validation regression suite covering the merged PRs. (#952)
- Verified query optimization —
altimate_core_rewritenow proves a rewrite is safe before suggesting it. A newverify_equivalencemode composes the rewrite engine with the equivalence checker: a candidate rewrite is labeled VERIFIED only when the engine affirmatively returnsequivalent === true; everything else (including the no-schema case) is still returned but labeled "review before applying." This is the gated core for one-click verified query optimization, so an optimization that silently changes results is never presented as safe. (#918) - Per-turn tool retrieval trims the tool-definition context flood. Three flag-gated, default-off agent-loop reliability features: a per-turn tool subset (always-on core tools + lexical top-k, never dropping a tool referenced mid-trajectory) that cuts the ~78-tool definition payload sent each turn; grammar/JSON-Schema constrained decoding for local models (vLLM/LM Studio/llama.cpp); and a pluggable pre-execution critic gate for side-effecting tools. All default off, so the existing agent path is unchanged unless explicitly enabled. (#858)
- Upgraded the SQL engine
@altimateai/altimate-core0.4.0→0.5.1and wired its new equivalence capabilities into the dbt PR reviewer. The reviewer now forwards the project's SQL dialect hint to the equivalence engine, so dialect-specific compiled warehouse SQL (e.g. Snowflake semi-structuredcol:field) parses and the comparison is decided instead of abstaining on a syntax error, and it honors the engine's new authoritativedecidableflag — abstaining when the engine itself says it could not decide, rather than guessing. An empty/auto-detect dialect is coerced to "no hint" so the engine is never handed an unknown dialect. (#925, #928)
- The dbt PR reviewer is more reliable and less noisy. Demo-parity hardening: tighter PII-review precision, reduced safe-refactor review noise, schema YAML catalog rules now run in review, and added DuckDB data-diff end-to-end coverage. (#919)
- dbt review no longer misclassifies YAML files. Schema/property YAML files are classified correctly so the right rules apply to them. (#920)
- The
release-v0.8.5adversarial test gate is pinned to a constant version so it stops breaking on every subsequent release. (#923)
- Centralized code-review dispatch on PR ready. A gated loop dispatches a centralized OCR/Gemini review when a pull request is marked ready for review. (#914)
- Session traces now work in headless
servemode — your VS Code "Altimate Code" chat sessions show up in/tracesjust like terminal sessions. Sessions driven overaltimate serve(the server behind the VS Code chat panel) had no TUI worker observing the event stream, so trace files were never written and/traceswas always empty after a chat. The per-session tracing logic is now a sharedTraceConsumerwired into both the TUI worker andserve, so IDE chat sessions produce the same incrementalses_<id>.jsonfiles — full multi-turn waterfall, recorded prompt, tool-call log, cost, and timing.servenow registersSIGINT/SIGTERM/beforeExithandlers that drain and finalize in-flight traces on shutdown (so a serve trace ends ascompleted, notrunning, and the process exits with signal-conventional codes), finalizes a session as soon as it is deleted, and finalizes all open sessions concurrently so a busy server isn't cut off mid-write by a container shutdown grace period. (#886)
- The
github/reviewcomposite action can be downloaded by GitHub Actions again. The release tree contained three VS Code image symlinks whose removed targets caused GitHub's action downloader to reject the entire archive before the review step started. The images are now self-contained files and a release-critical test prevents dangling links from returning. - A valid dbt manifest is no longer mislabeled as a lint-only run. Manifest availability is now checked independently from changed-model lookup, so new models and other valid manifests receive the correct full-run status.
- The release-version lookup is rate-limit resilient and never caches a floating
latest. The composite action now authenticates its GitHub release-API call with the workflow token (lifting the 60→1,000 req/hr unauthenticated limit) and skips the binary cache entirely when the version resolves tolatest, so a single rate-limited or offline lookup can no longer pin a stale binary across all subsequent runs. - Session traces survive worker restarts, concurrency, and long sessions without corruption or false alarms. Three reliability follow-ups to the v0.8.4 trace-durability fix: reconstructed in-flight spans are marked
interruptedand render with an amber "⚠" instead of red (and are excluded from the session error count) so a restart isn't misread as a failure (#901);getOrCreateTraceno longer resurrects aTraceinto a cache that a concurrent stream switch already cleared, preventing an orphan writer under a dead stream (#902); and the on-diskses_<id>.jsonprojection is bounded toMAX_SERIALIZED_SPANS(default 5000, override viaALTIMATE_TRACE_MAX_SPANS), keeping head + tail and eliding the middle so long sessions no longer grow the file without bound or pay O(n²) write cost (#903).
- Direct GitHub onboarding and a live dbt review demo. The GitHub App installer now opens GitHub's repository-selection screen directly, and the README/docs link to the public
dbt-pr-review-demopull requests.
- The hosted Altimate API key is no longer placed on the
jqprocess arg list. The credential write reads the key from the environment inside thejqprogram, keeping it out ofargv(which is visible to other processes and printed verbatim whenACTIONS_STEP_DEBUGenablesset -x).
A trace-durability patch. Open /traces mid-session and you'd see a rich waterfall — then the moment the agent finished its turn the view collapsed to a single "system-prompt" span, the Summary tab's "What was asked" showed "No prompt recorded", and the Chat tab dropped every user turn but the last. The data was genuinely gone from disk, not just hidden in the viewer. This release stops the on-disk trace from being overwritten after each turn and makes the file authoritative across worker restarts. A five-persona pre-release review drove a follow-up wording fix so a reconstructed trace isn't misread as a failed run.
- Session traces no longer lose their data after every agent turn — the waterfall, summary prompt, and chat tab all stay intact. A
session.status === "idle"handler in the shared TUI worker fired once per turn (not once per session), ending theTraceand evicting it from cache; the next event reconstructed a freshTracewhose near-empty initial state overwrote the richses_<id>.jsonon disk with a one-span file. Symptoms: the Waterfall collapsed to a lone "system-prompt" span, the Summary tab's "What was asked" went to "No prompt recorded", and the Chat tab kept only the last user turn. The destructive idle handler is removed (sessions are long-lived — finalization happens on shutdown andMAX_TRACESeviction only), trace reconstruction now rehydrates from the on-disk file before falling back to a fresh start, and each user prompt is recorded as its ownuser-messagespan so multi-turn sessions render every turn in order. Authored-text scoping keeps synthetic parts (MCP banners, decoded file contents, reminders) out of the prompt and chat surfaces. Distinct from the v0.8.1 trace-corruption fix (#865), which addressed intra-instance concurrency — this is the worker-level cache lifecycle. (#895) - A trace reconstructed after a restart no longer reads as a failed run. When the on-disk trace is rehydrated (worker restart or
MAX_TRACESeviction), any generation span still in flight is closed and marked so its boundary stays visible in the waterfall. The status message now states plainly that altimate-code restarted before the step finished recording and that this is not an agent failure — so an on-call reader debugging from a trace isn't sent chasing a phantom incident. (#895)
A plan-mode reliability patch for the hosted gateway and other non-Anthropic models. Ask the plan agent to plan something benign — "plan a feature to add a verify-output button" — on altimate-backend/altimate-default (GPT-5.x) and it could refuse outright with "I'm sorry, but I cannot assist with that request." This release fixes the refusal at its source, hardens the fix against prompt-injection, and rewrites a warning that was misdiagnosing the symptom.
- Plan mode no longer refuses benign requests on
altimate-defaultand other non-Anthropic models. The root cause was how altimate-code delivers its own plan instructions: a<system-reminder>-wrapped block attached as user-role text. Claude is trained to read that tag as authoritative system guidance, but GPT-5.x, Gemini, and other non-Anthropic models pattern-matched the same block — carryingSTRICTLY FORBIDDEN/ZERO exceptions/MUSTlanguage — as a prompt-injection attempt and declined, returning "I'm sorry, but I cannot assist with that request." for ordinary developer tasks. altimate-code now hoists those self-injected reminders into properrole:"system"messages for non-Anthropic models, so they arrive as instructions rather than suspect user input; Anthropic models are unchanged. The hoist is scoped by provenance to altimate-code's own reminder parts — user-supplied files, MCP-resource bodies, anddata:-URL content can never gain system-role priority, even when they begin with<system-reminder>. Gateway models are routed bymodel.family(via a sharedfamilyVendorclassifier) so a Claude- or Gemini-backed gateway model lands on the right base prompt instead of an Anthropic-style fallback. (#887, #888) - The "plan agent used no tools" warning is accurate — and no longer false-fires. Previously the warning blamed the model's tool-use capability (misleading — these models are fully tool-capable) and could fire on the final text-only step of a successful multi-step plan session, making a working session look broken. The trip-wire now scans the conversation history for prior tool calls, so a session that already explored the codebase isn't flagged. When it does fire, the copy describes the observed symptom only ("stopped without calling any tools"), lists the likely causes, and offers concrete recoveries — ask it to investigate first, rephrase, or, if it keeps refusing,
/modelto a tier more eager to explore. The plan agent is also now instructed to read or search the codebase before drafting any plan, with an explicit escape hatch for trivial, fully-specified changes. See Plan mode and Troubleshooting. (#888)
A small correctness patch. The dbt PR reviewer's deterministic engine never required an altimate API key — but two tool descriptions said it did, which could push the reviewer into lint-only mode and send users chasing a key they don't need. This release corrects that and documents what "lint-only" actually means.
dbt_pr_reviewno longer implies it needs an altimate API key. The nativealtimate-coreengine behind the reviewer (column-lineage blast radius, query equivalence, PII classification, A–F grade) runs fully offline via the bundled napi binary — there is noaltimate_core.initand no API-key gate in that path. Two tool descriptions (altimate_core_column_lineage,altimate_core_track_lineage) still carried a stale Python-bridge-era line claiming "Requiresaltimate_core.init()with API key", so a stuck lint-only run was mis-diagnosed as missing auth. The descriptions now state the tools run offline with no key. Lint-only actually means the dbtmanifest.jsondidn't resolve (wrong path, stale manifest, or wrong working directory) — the dbt PR Review docs now spell out how to fix it. The only thing that ever needs a key is the optional advisory LLM lane, which can never block a verdict. (#882)
A reliability + correctness patch on top of 0.8.0. Highlights: 8 new Snowflake Cortex models (with a config escape-hatch so you never wait for a release again), a trace-corruption fix for long-running sessions, and a behavior change to the dbt PR reviewer — it now always posts a GitHub comment and never a formal approval.
- Snowflake Cortex — 8 new selectable models. Closes the drift between altimate-code's hardcoded Cortex model list and Snowflake's current regional-availability matrix: adds
claude-opus-4-7,openai-gpt-5.1,openai-gpt-5.2,llama4-scout,llama3.3-70b,snowflake-llama-3.1-405b,mixtral-8x7b, andgemini-3.1-pro(Claude + OpenAI tool-capable; the rest chat-only, the conservative default until tool calling is verified on Cortex). When Cortex adds a model before the next release, you can now add it yourself underprovider["snowflake-cortex"].modelsinaltimate-code.jsonand it merges into the picker — no fork, no waiting. See Snowflake Cortex provider docs. (#866)
- dbt PR reviewer never posts a formal GitHub Approve — behavior change. The reviewer's
APPROVEverdict now posts a GitHub COMMENT review event (the "approved — no findings" outcome is in the comment body), never a formal Approve. A review bot must not be able to satisfy branch protection / required reviews and let a PR merge without human sign-off (observed on a real PR where the bot had auto-approved). The no-formal-approval invariant is now enforced at compile time. Migration: to block merges, gate on the verdict check (--mode gate), not on requiring this bot as a reviewer — if your branch protection previously required the altimate bot's approval, remove that requirement or those merges will stay blocked. (#870, #872) - Trace corruption in long-running sessions. Two concurrency bugs in the observability tracer are fixed: bursty turns (an LLM step firing many tool calls back-to-back) could drop the tail of a burst from the trace file when the process exited in the debounce gap (M2), and a crash during a large trace export could be overwritten by the in-flight export and show a stale terminal status instead of
crashed(M3). Trace files now reliably reflect what actually happened, scoped per session in the shared TUI worker. (#865)
Headlined by dbt PR Review — a Cloudflare-style, dbt/SQL-specialized code reviewer that emits a single signed verdict (APPROVE / COMMENT / REQUEST_CHANGES) where every blocking finding is backed by a deterministic altimate-core engine call over parsed SQL ASTs, not a model's opinion. An optional LLM lane adds advisory context but can never block. This release also adds a native Trino driver, the opt-in completion-gate validators, and reliability/cost fixes. A five-persona pre-release review drove a security hardening pass on the new reviewer agent (see Security).
- dbt PR Review — signed, deterministic verdicts on dbt pull requests. New
altimate reviewCLI command and a composite GitHub Action (github/review). The deterministic engine (column-lineage / DAG blast radius, query equivalence on before/after model SQL, PII classification, A–F grade + anti-pattern lint) is the only layer that can block; an optional LLM reviewer is clamped to ≤ warning and excluded from the gate, so aREQUEST_CHANGESis always provable and replayable. Runs in CI with zero warehouse access (consumesdbt compileartifacts), and the verdict is HMAC-signable and tamper-evident.commentmode never blocks;gatemode fails the check onREQUEST_CHANGES. The advisory model/credentials are configured on the Action (hostedaltimate_api_key, or bring-your-ownmodel+model_api_key); omit them to run deterministic-only. See dbt PR Review docs and the copy-paste workflow ingithub/review/examples/. Depends on@altimateai/altimate-core≥ 0.4.0. (#856) - Native Trino driver. First-class Trino support over HTTP(S) with catalog/schema introspection and None / Basic / Bearer-token auth. Migration note: the dbt
trinoadapter previously mapped to the PostgreSQL driver; it now uses the native driver. Existing profiles are auto-aliased (database→catalog,token→access_token) and otherwise compatible.trino-clientis an optional dependency — install it (npm install trino-client) to use Trino. (#795) - Completion-gate validator framework. A new opt-in harness-side check
that runs after the LLM declares
finish === "stop". Two built-in validators for dbt projects:dbt-tests-pass(runsaltimate-dbt testagainst modified models) anddbt-schema-verify(runsaltimate-dbt schema-verifyagainst modified models). On failure, the framework injects a synthetic user turn so the agent gets one more chance to fix the issue, bounded by a per-session retry budget. Two opt-in modes:ALTIMATE_VALIDATORS_ENABLED=1(enforcement + retries) andALTIMATE_VALIDATORS_SHADOW=1(telemetry-only — measure "would have caught" rates without blocking). Default is off with zero overhead. Two new telemetry events (validator_check,validator_retries_exhausted). Configuration viaALTIMATE_VALIDATORS_{MAX_RETRIES,TIMEOUT_MS,CONCURRENCY,DEBUG}. See Validators docs for the full reference, performance characteristics, and the phased rollout plan. (#849)
cancel()race / idle-on-clean-exit. A cancel arriving during normal loop teardown could leave a session without asession.status:idleevent, leaving callers waiting on idle stuck. Idle is now emitted correctly on both the abort and clean-exit paths. (#845)- Prompt caching on the
altimate-backendprovider. Enabled thecache_controltrigger for the hosted provider so the litellm Anthropic fallback caches repeated prompt prefixes — cheaper and faster repeat turns (no-op on providers that ignore the marker). (#850)
revieweragent hardened to deny bash. The v0.8.0 pre-release review found that the newrevieweragent — advertised as "read-only" — had a bash allowlist (git log *,cat *,ls *) that was bypassable: shell redirects rode inside a matched command (git log -p > ~/.ssh/authorized_keyswas allowed) andcat *could read arbitrary files (e.g.~/.altimate/altimate.json) and exfiltrate them through the PR comment the agent posts. Bash is now denied for the reviewer (it uses the structuredread/grep/globtools + the verdict engine, which does its own diffing); the agent description was corrected; and the reviewer prompt now treats PR content as untrusted input. The CI Action path was never affected — its LLM lane runs with no tools. (#856)
A telemetry-driven hardening release. Five P0 fixes merged from a telemetry-analysis-2026-05-21 pass — every one tied to a measured failure number from the App Insights pipeline. The headline wins are user-visible: finops_* tools now work without an explicit warehouse= parameter (auto-pick the first compatible connection); project_scan no longer crashes on hosts where git isn't in PATH (the silent 437-user regression was masked by the PII filter collapsing the binary name to ? in error messages); and webfetch caches 404/410/451 responses for up to 30 minutes so the agent stops re-asking dead URLs. Two telemetry-only fixes (build-agent name normalization, Anthropic token-count semantics) clean up dashboard mis-bucketing without changing user-visible behavior.
A five-persona pre-release review drove a second hardening pass: HTTPS basic-auth credentials are now stripped from git remote get-url origin output before it reaches LLM-visible metadata or session transcripts; raw git stderr is routed through Telemetry.maskString to redact embedded emails and bearer tokens; normalizeAgentName gained C0 control-char stripping + NFKC normalization + a 64-char cap to neutralize log-injection and homoglyph-bucket attacks via custom agent configs; the webfetch failure cache now also drops auth-bearing query params (token, api_key, signature, x-amz-signature, etc.) from the cache key so presigned-URL secrets can't sit in an in-memory Map for 30 minutes; cache-hit error messages are prefixed with (cached failure, Nm ago) so an agent debugging a fast failure can tell cache vs. live network apart; and 34 adversarial tests pin every one of these regression classes plus the warehouse_filter / warehouse parameter disambiguation that caused LLM confusion.
tokens_input_total is now always emitted on generation telemetry events (previously omitted when zero/null). Dashboards reading tokens_input to compute volume will under-report on Anthropic-cache-hit sessions — switch any "total input tokens consumed" queries to tokens_input_total. The old tokens_input field is preserved and reports uncached input tokens (clamped at zero so inconsistent provider counts can't produce negative cost). The two fields satisfy the invariant tokens_input + tokens_cache_read + tokens_cache_write === tokens_input_total.
finops_*tools auto-pick a warehouse when omitted. All six finops tools (finops_analyze_credits,finops_expensive_queries,finops_query_history,finops_role_*,finops_unused_resources,finops_warehouse_advice) previously required an explicitwarehouse=<connection-name>argument. Telemetry showed them at a 100% error rate because the LLM consistently guessed unconfigured warehouse names and got dead-end "Credit analysis is not available for unknown warehouses" errors with no enumeration of what was configured. The newresolveFinopsWarehousehelper centralizes resolution: if no warehouse is requested, it auto-picks the first configured connection whose driver type supports the operation (snowflake/bigquery/databricksfor credit/sizing/usage tools; broader for query history; Snowflake-only for role-hierarchy). Errors now enumerate configured warehouse names and point atwarehouse_addwhen nothing is configured. Trim is applied on the requested name (LLM whitespace edge cases) and type matching is case-insensitive ("Snowflake"/"snowflake"/"SNOWFLAKE"resolve identically). (#828, closes #827)project_scanno longer crashes whengitis missing from PATH. Telemetry showed a 32% failure rate across 437 users with the masked error"Executable not found in $PATH: ?"— the binary name was being collapsed to?by the PII filter, hiding the real cause for two months.Bun.spawnSyncthrows when a binary isn't found (not just non-zero exit), andproject_scanwas running the throw unguarded. The newsafeSpawnSyncwrapper catches it cleanly and returnsnull, anddetectGitdistinguishes three states viaGitInfo.gitAvailable+gitError:git missing(binary not in PATH — surface install hint),git present but degraded(non-128 exit code — corrupted.git, permission denied; surfaces exit code + masked stderr), andgit present, not a repo(clean exit 128 — render "Not a git repository"). Themetadata.degradedarray always emits even when empty, sorted and deduplicated, so dashboard queries never have to null-coalesce. (#831, closes #830)- Build agent telemetry no longer reports 0% completion. A rename from
"build"→"builder"in the agent registry left three writer sites still emitting the legacy name: the TUI sentagent: "build"on session start, the plan-exit synthetic message wrotelastUser.agent = "build", and theagent_outcomeevent read from that. The agent execution alias atAgent.get()masked the issue at runtime, but every dashboard saw a phantom"build"bucket with 0% completion alongside the real"builder"bucket. The newnormalizeAgentNamehelper is the single source of truth — used by bothsession_startandagent_outcomeemits so they can never drift, case-insensitive against the legacy name, plus C0-control-char strip + NFKC + 64-char cap so a malicious or hand-edited config can't inject newlines into App Insights or create a cardinality bomb. The TUI and plan tool now write"builder"directly. (#833, closes #832) - Anthropic
tokens_inputis no longer always 0 in telemetry.Session.getUsagepreviously assumed OpenAI-style accounting (whereinputTokensis the inclusive total including cached) — but Anthropic returnsinputTokensexclusive of cached, so the subtractioninputTokens - cacheRead - cacheWriteproduced 0 (or negative) on every cache-hit session. The new branch testsmetadata.anthropic || metadata.bedrockand skips the subtraction for those providers.tokens_input_totalis now always emitted as the inclusive total (so dashboards have a clean denominator), andtokens.inputis clamped at zero — inconsistent provider counts (e.g.inputTokens=1000, cachedInputTokens=2000) can no longer leak negative cost into App Insights or session totals. Venice metadata path (metadata.venice.usage.cacheCreationInputTokens) is now covered with the same treatment as Anthropic/Bedrock. (#837, closes #836) webfetchfailure cache now persists known-bad URLs for 30 minutes (5 min for 451) and collapses LLM-generated URL variations. Telemetry showed 486 residual webfetch 404 retries across the 14-day window (down from March's 2,222 but still meaningful) — the LLM kept fetching the same dead URL with different tracking parameters, fragments, and case variations and getting fresh 404s each time. The cache key is now the normalized URL: tracking params (utm_*,fbclid,gclid,mc_*,_ga,_gl,igshid,mibextid, HubSpot_hsenc/_hsmi, Marketomkt_tok, Adobes_cid/s_kwcid, Piwik/Matomopk_*/piwik_*,__cf_chl_*) are stripped, query params are sorted by (key, value), the host is lowercased, the fragment is dropped, and HTTPS basic-auth userinfo (user:pass@) is removed. The functionalrefparam is deliberately preserved (GitHub raw URLs and git APIs use it to select branches/tags). Auth-bearing query params (token,access_token,api_key,apikey,signature,sig,x-amz-signature,x-amz-credential,x-amz-security-token,x-goog-signature,x-goog-credential) are dropped from the cache key only — the actualfetch()still uses the raw URL — so an S3 presigned URL that 404s doesn't leak its signature into the in-memoryMapfor 30 minutes. 451 uses a shorter 5-min TTL because it's observer-conditional (VPN swap unblocks). Cache-hit errors now prefix with(cached failure, Nm ago)so an agent debugging a fast failure can tell cache vs. live network apart. LRU re-touch on repeated failures viadelete-then-setso a frequently-failing URL doesn't sit at the head of the FIFO and get evicted first under pressure (cache size cap is 500). (#839, closes #838)
git remote get-url originoutput is now credential-stripped before it reaches LLM-visible metadata or session transcripts. Pre-fix,metadata.git.remoteUrlshipped the URL verbatim — including embedded HTTPS basic-auth likehttps://x-access-token:ghp_xxx@github.com/...orhttps://user:pass@gitlab.internal/...— which then flowed to the LLM provider on everyproject_scancall and was preserved in the session transcript. The newstripGitRemoteCredentialshelper setsusernameandpasswordto empty on parseable URLs, preserves SSH-form remotes (git@github.com:owner/repo.githas no userinfo concept), and drops unparseable URLs entirely rather than risk leaking embedded creds. Flagged by the v0.7.3 compliance/chaos review.gitError.stderris masked viaTelemetry.maskStringbefore persisting. Git stderr on auth failures and bad-object errors contains embedded HTTPS remote URLs (with userinfo), commit emails, and/Users/<realname>/paths. The masker (already redactingsk-,Bearer, and<email>in error strings elsewhere) now runs before the stderr is sliced to 240 chars and assigned tometadata.git.gitError.stderr. Mask-before-slice order is pinned by adversarial test so a refactor can't reorder them and surface a half-redacted email.normalizeAgentNamehardens against adversarial input. Strips C0 control characters (\x00-\x1f+ DEL) — a custom-agent config withname: "x\nfake_event=hello"would have split App Insights into two events; NFKC-normalizes so fullwidth/homoglyph agent names ("builder") don't create separate telemetry buckets; caps length at 64 chars because agent names are slugs and anything larger is a cardinality bomb. Three new pinning tests guarantee each invariant.
warehouse_filterparameter description disambiguated fromwarehouse. Withwarehousenow optional, the previous description ("Filter to a specific Snowflake warehouse") was ambiguous next to the connection-namewarehouseparameter. New description: "Filter result rows by an in-warehouse Snowflake compute name (NOT the connection name). Distinct fromwarehouse:warehousepicks which connection to query;warehouse_filternarrows which Snowflake virtual warehouse's queries are returned in the result set. Snowflake only." Applied to bothfinops_analyze_creditsandfinops_query_history. End-user persona flagged the LLM-confusion risk during pre-release review.DEFAULT_FINOPS_TYPESis the canonical "supported by any cloud warehouse" type list. Pre-fix, three handlers (credit-analyzer,unused-resources,warehouse-advisor) each declared the same["snowflake", "bigquery", "databricks"]literal as a localconst. Now exported fromwarehouse-resolver.ts; adding a fourth driver (e.g. Redshiftaccount_usage) is one edit, not three.docs/docs/data-engineering/tools/finops-tools.mdupdated for the auto-pick behavior. Pre-fix, the doc saidwarehouse (required): Connection name— directly contradicting the v0.7.3 code. Now listswarehouseas optional with the auto-pick semantics, includes a top-of-filev0.7.3+note about the change, and shows the bare (no-warehouse) invocation form in at least one example. PM persona flagged the doc/code drift as P0 pre-release.
- 34 adversarial tests in
release-v0.7.3-adversarial.test.tspin the regression classes:- finops auto-pick — code/doc/tool-description alignment (no
warehouse (required)left in docs; "Optional" appears in tool descriptions;warehouse_filterdescription disambiguates fromwarehouse;DEFAULT_FINOPS_TYPESis single source of truth; resolver trims whitespace; resolver auto-picks on empty/undefined/whitespace). - project_scan privacy —
stripGitRemoteCredentialspresent + setsusername/passwordempty;gitError.stderrruns throughTelemetry.maskString; mask-before-slice order;safeSpawnSyncreturns null on missing binary;GitInfo.gitAvailable+gitErrordistinguish three states; output line distinguishes "binary missing" from "not a repo". - normalizeAgentName — single declaration site (single source of truth); case-folds before "build" compare; strips C0 control chars; NFKC-normalizes; length-caps at 64; both
session_startandagent_outcomeroute through the helper. - webfetch cache key —
AUTH_PARAMS_FOR_CACHE_KEYenumeratestoken/access_token/api_key/apikey/signature/sig/x-amz-signature/x-amz-credential/x-goog-signature; presigned-S3 URLs with different signatures collapse; api_key/token variants all collapse; functional params (page,q) are NOT stripped; auth-param strip is case-insensitive; cache-hit error prefix wording is distinguishable;isUrlCachedFailureexposesageMs; 451 has shorter TTL than 404/410. - URL normalization privacy invariants — userinfo stripped from cache key; utm/fbclid/mc_ tracking collapses; normalization is idempotent; invalid URL passes through verbatim.
- CHANGELOG presence — release-skill backstop that catches a release commit without a 0.7.3 entry + all 5 merged PR numbers referenced.
- finops auto-pick — code/doc/tool-description alignment (no
- #840 Surface auto-picked warehouse name in
finops_*tool output (currentlyautoPicked: trueis computed but not rendered). - #841 Audit: webfetch failure cache crosses logical sessions in
altimate servedaemon mode. - #842 Route the three compaction-summary
lastUser.agentwrites throughnormalizeAgentName(currently only the emit boundary is normalized; persisted state can still record legacy"build"). - #843 Audit: cost telemetry retention + re-identification policy (
tokens_input_total+costare now always emitted per generation event; document TTL and TOS alignment).
A focused hotfix for v0.7.1's broken install endpoint plus a defensive pass on the upgrade fetch surface. v0.7.1 documented and embedded https://altimate.ai/install in the curl install path and in altimate upgrade's in-place upgrader — that host is the marketing-site SPA and returns an HTML 404 for /install, so every curl install and every curl-installed user's altimate upgrade silently failed end-to-end. v0.7.2 swaps the host to https://www.altimate.sh/install (apex altimate.sh is still not routed to the Amplify Next.js app — tracked separately, drop the www. once apex DNS is fixed), wraps the upgrader fetch with a 15s bounded timeout, replaces the raw AbortError: The operation was aborted with an actionable error that names the URL, prints the manual re-install one-liner, and points at the GitHub releases fallback. Realigns the published GitHub Action (github/action.yml) with the v0.7.1 binary rename (altimate-code → altimate) and new install directory (~/.altimate/bin) — pre-fix, every Action consumer hit the broken URL on cache miss and then a missing binary even if the URL had worked. 30 adversarial tests pin the regression classes (URL eradication, cross-file host consistency, named-constant invariants, error-surface invariants, action.yml alignment, marker integrity, migration recovery surface, CHANGELOG presence).
If you installed v0.7.1 via curl, your altimate upgrade will still fail until you re-install manually once:
curl -fsSL https://www.altimate.sh/install | bashAfter that, v0.7.2 and forward self-heal.
Installation.upgradeCurl()now fetches fromhttps://www.altimate.sh/installinstead of the unreachablehttps://altimate.ai/install. v0.7.1 had pointed the in-place upgrader at the marketing site, which routes everything through a React Router SPA —/installrendered an HTML 404 page, the upgrader'sfetchsucceeded with a 200, the response body was the 404 HTML, andbasheither executed the HTML and failed cryptically or hung mid-stream. The matching curl install one-liner ininstall --help,README.md, anddocs/docs/reference/troubleshooting.md(three references) was broken the same way. www.altimate.sh now serves the install script via a Next.js route handler withContent-Type: text/x-shellscript. (#825, closes #309)- Published GitHub Action (
github/action.yml) realigned with the v0.7.1 binary rename. v0.7.1 renamed the curl-installed binaryaltimate-code→altimateand moved the install directory~/.altimate-code/bin→~/.altimate/bin, but the Action's cachepath:,$GITHUB_PATHaddition, and finalrun:step still referenced the legacyaltimate-codename and path. Combined with the broken install URL, every Action consumer hit a 404 on cache miss followed by an empty$PATHand aaltimate-code: command not foundeven after the install "succeeded". All four references updated in lockstep. altimate upgrade(curl method) no longer hangs indefinitely on a stalled CDN/origin. The fetch is bounded byAbortSignal.timeout(UPGRADE_FETCH_TIMEOUT_MS)(15s) so a TLS-rewriting corporate proxy, a hung CloudFront edge, or a slow-loris-style stall fails fast instead of blocking the user's terminal for minutes. Surfaced via CodeRabbit review on #825.
- Curl-upgrade fetch failures now surface an actionable error instead of
AbortError: The operation was aborted. Pre-fix, a timeout, a 404, a DNS failure, or a connection refused would propagate asDOMException: The operation was aborted(timeout) orError: Not Found(HTTP non-2xx) — neither named the URL, the recovery path, or the fallback. The fetch is now wrapped intry/catchand the rethrown error reads:"Could not download install script from https://www.altimate.sh/install: <cause>. Re-run the install manually: curl -fsSL https://www.altimate.sh/install | bash — or download a release binary directly from https://github.com/AltimateAI/altimate-code/releases/latest". HTTP non-2xx now also includes the numeric status (HTTP 404 Not Foundinstead of justNot Found). UPGRADE_INSTALL_URLandUPGRADE_FETCH_TIMEOUT_MSextracted as named constants inside thealtimate_changeblock inpackages/opencode/src/installation/index.ts. Pre-fix, the URL and timeout were duplicated string + literal across the source and the test assertion. A future timeout tune (15s → 20s) would have required three coordinated edits; now it's one. The adversarial test asserts the existence of the named constant separately from the literal value so the regression guard isn't brittle to constant extraction itself.altimate_changemarker block ininstallation/index.tsextended. The v0.7.1 release did not mark the line whereupgradeCurl()fetches the install script; v0.7.2 wraps the URL + timeout constants and the entire fetch+wrap block in a single marker pair so the next upstream bridge merge sees the intent and doesn't silently revert the URL or strip the timeout.
- 30 adversarial tests in
release-v0.7.2-adversarial.test.tspinning the v0.7.2 surface:- URL eradication — 5 surfaces (
installation/index.ts,install,README.md,troubleshooting.md,github/action.yml) each negative-asserted to not containaltimate.ai/install. The intentionalaltimate.ai/discordlink indocs/mkdocs.ymlis positively asserted as still present (different path, marketing-site contact info, intentionally out of scope). - Cross-file host consistency — the host used in the source
UPGRADE_INSTALL_URLis automatically compared against every other reference in README, troubleshooting docs, install script, and action.yml. A future "drop the www." that updates the source but misses README will fail loudly. install --helpexamples — both examples in the--helpblock asserted (a previous half-fix had updated only the first); negative assertion against the legacy host on the help block specifically.- Bounded timeout —
AbortSignal.timeout(is wired,UPGRADE_FETCH_TIMEOUT_MS = 15_000is a named constant, the fetch references the constant by name, and a rawAbortSignal.timeout(15_000)literal is forbidden (would mean someone reverted the constant extraction). - Error surface — the fetch lives inside a try/catch, the rethrown error message names the URL, includes the manual re-install one-liner with the URL templated through the constant, points at the GitHub releases fallback, and surfaces HTTP status codes (
HTTP ${res.status} ${res.statusText}). github/action.ymlalignment — install URL, cache path,$GITHUB_PATHaddition, and final binary invocation all match the v0.7.1 rename; negative assertions against every legacy form. Action file existence asserted atgithub/action.yml(not.github/action.yml) since moving it would silently break every downstream consumer.- Marker integrity — URL/timeout constants live inside an
altimate_changeblock; try/catch wrapper lives inside analtimate_changeblock; balanced start/end count across the file. - Migration recovery surface — troubleshooting doc still has the install-path section with the new URL; README curl one-liner matches the source's
UPGRADE_INSTALL_URLhost. - CHANGELOG presence — release-skill backstop that catches a release commit without a 0.7.2 entry.
- URL eradication — 5 surfaces (
A focused provider-error pass plus the standalone-binary fix: the curl-installed binary now starts (previously crashed with Cannot find module '@altimateai/altimate-core'), is renamed to match the npm primary bin (altimate-code → altimate for the curl path only), and Alpine + Windows-on-ARM hit a clear early-exit instead of a cryptic gzip failure. Two 5-persona pre-release reviews (provider-error pass, then binary-fix + rename pass) drove the surface — 86 adversarial tests total pin the regression classes.
- Curl-installed standalone binary no longer crashes with
Cannot find module '@altimateai/altimate-core'on first run. Thescript/build.tsmarked altimate-core asexternal(NAPI native modules can't live inside Bun's single-file bunfs), and the release archive shipped only the raw Bun binary — no companionnode_modules, no NODE_PATH-aware wrapper. CI smoke tests hid the bug by pre-setting NODE_PATH against the developer checkout before invoking the binary. The fix stages a per-target copy of altimate-core whose loader is rewritten to a one-line shimmodule.exports = require('./altimate-core.<platform>.node'), drops the matching.nodefile next to it, and uses aBun.buildonResolveplugin to redirect every@altimateai/altimate-coreimport to that shim. Bun statically sees a single require and embeds that one.nodeinto bunfs. Result: ~176 MB self-contained binary, no companion files, no NODE_PATH dance. CI smoke tests now run withNODE_PATHcleared from$RUNNER_TEMP, plus an independentstrings-based content assertion that exactly one platform.nodeis embedded — the v0.5.10 / v0.7.0 class of regression is pinned by three independent guards. (#820) - Alpine Linux (musl) and Windows on ARM64 install paths now fail fast with actionable messages instead of silent 404 → tar/unzip errors. Pre-fix,
curl … | bashon an unsupported target would write GitHub's 404 HTML to disk and die "not in gzip format". The curlinstallscript, the npm bin wrapper (packages/opencode/bin/altimate), the npmpostinstall.mjs, andscript/build.tsall detect these platforms early and point toapk add gcompat(Alpine) or x64 emulation / WSL (Windows ARM). The musl-detection logic is alsopipefail-safe (ldd --versionexits non-zero on musl by design; the previous pipeline-form inherited that failure and silently missed every non-Alpine musl distro). (#820) - Curl install
--failon both download paths. A 404 / WAF block / TLS-rewriting corporate proxy no longer writes the error page to disk and gets unzipped as a binary;curl --failexits non-zero and the install bails cleanly. (#820) script/build.ts --target-index=Nfor an out-of-range index exits non-zero. Pre-fix, after the musl/win32-arm64 cull, an invalid index silently produced zero artifacts and CI "succeeded" with no binary. (#820)script/build.ts --singleon a musl-linux host refuses to build the unrunnable glibc target. Pre-fix the build would succeed but the resulting binary couldn't load on the host. (#820)Installation.method()recognises~/.altimate/binas a curl install. The same release that renames the curl-install dir would have brokenaltimate upgradefor curl-installed users without this; the.opencode/binand.local/binbranches stay for back-compat. (#820)- Provider 4xx errors now show the inner error message instead of a raw JSON dump. When any provider returned the standard
{error: {message, type, code}}shape (OpenAI, Azure OpenAI, OpenRouter, etc.),parseAPICallError's extraction chain short-circuited on the truthy parenterrorobject, thetypeof errMsg === "string"guard rejected it, and the parser fell through to dumping the raw response body — which appeared asAPIError: Bad Request: {?:?}after telemetry redaction collapsed string values to?. Telemetry caught users retrying broken model selections 3+ times in the same session because the surfaced error gave no clue about the cause. Users now see actionable text such asAPIError: Bad Request: The model 'gpt-5-codex' does not exist or you do not have access to it.The OR-chain is replaced with explicit-typeof ternaries that mirrorparseStreamError's pattern, so a truthy non-string at any tier cannot block a valid string further down the chain. (#789, closes #788) - Bedrock / AWS Lambda
errorMessageshape is now extracted. AWS APIs that return{errorMessage: "...", errorType: "..."}(Lambda style) previously fell through the OpenAI/Anthropic-shaped chain to a raw-body dump. Addedbody.errorMessageto the extraction ladder in bothparseAPICallErrorandparseStreamError. - Streaming error path no longer dumps
Unknown: {"type":"error",...}for non-OpenAI codes.parseStreamErrorpreviously handled only 4 OpenAI error codes (context_length_exceeded,insufficient_quota,usage_not_included,invalid_prompt); everything else fell through toJSON.stringify(e). Added a default fallback that runs the same string-typeof chain asparseAPICallError, so any extractable provider message becomes a clean api_error. model_not_foundno longer triggers a silent retry storm. OpenAI 404s are forced retryable in general (some legitimate models 404 transiently), buterror.code === "model_not_found"now short-circuits toisRetryable: false— the user sees the actionable error on attempt 1 instead of after 5 silent retries.
altimate modelsdiscoverability hint on model-not-found errors. Whenerror.code === "model_not_found", the surfaced message now ends withRun \altimate models` to see available models.` so the next step is one command away.- Provider-API-Errors troubleshooting reference at
docs/docs/reference/troubleshooting.mdcovering model-not-found, unauthorized, rate-limited, context-overflow, and HTML-page error classes. - Install-path troubleshooting section at
docs/docs/reference/troubleshooting.mdcovering "standalone binary not found after curl install" (thealtimate-code→altimaterename), the legacyCannot find module '@altimateai/altimate-core'crash with recovery instructions, Alpine/musl unsupported (withapk add gcompatworkaround), and Windows-on-ARM unsupported (with WSL workaround). README also documents the curl-install option alongside the npm one.
- Curl-installed binary renamed
altimate-code→altimateto match the npm package's primarybinentry. The npm path continues to expose bothaltimateandaltimate-code, so existingnpm install -g/pnpm i -gusers see no behavioural change. Homebrew installs are unchanged (the formula installsaltimateand symlinksaltimate-codefor back-compat). Only the standalone (curl … | bash) channel is affected — it now ships a single self-containedaltimatebinary to~/.altimate/bin/(was~/.altimate-code/bin/altimate-code). CI users with scripts that calledaltimate-codeafter the curl install should switch toaltimateor install via npm. The install script removes any stale~/.altimate/bin/altimate-codeleft over from a pre-v0.7.1 install. (#820) check_versionprobes bothaltimateandaltimate-codeon PATH so an upgrade from v0.7.0 doesn't always re-download even when the version already matches. (#820)- Curl install final banner mirrors the npm postinstall:
altimate,altimate run "hello",altimate --help, and the samehttps://altimate-code.devdocs URL. Rosetta-detected x64 → arm64 swap now emits a one-line muted notice instead of being silent. (#820) Installation.method()upgrade detection recognises~/.altimate/binas a curl install (in addition to the legacy~/.opencode/binand~/.local/binpaths). (#820)_requiredExportsliteral extracted from@altimateai/altimate-core/index.jsis JSON.parsed and shape-checked before being inlined into the per-target staged shim. Pre-fix, the regex match group was inlined verbatim — a malicious altimate-core that published anindex.jswhose_requiredExports = ["x"]; <attacker JS>; const _foo = [form would have embedded attacker JavaScript into every shipped binary. The validator now requires a pure JSON array of non-empty short string literals; anything else aborts the build. (#820)build.tsasserts the on-disk@altimateai/altimate-coreversion matchespackage.jsondeclaration afterbun install --os=* --cpu=*. Catches the stale-hoist scenario where a previous version lingers innode_modules/.bun/and the new build silently embeds yesterday's.node. (#820)- Per-target staging dir is wiped before each build (pre-loop cleanup), not just after, so a previous build that crashed between staging and post-build cleanup can never leak a stale
.altimate-core-staged/into the next build's resolution. (#820) - Curl install extracts only the expected binary member from tar/zip archives (
tar --no-same-owner -xzf … "$binary_name"/unzip … "$binary_name"), so a future build mistake that tars a directory of attacker-controlled paths can't write them outside the explicit member. (#820) install_from_binaryguards against cp-on-self:--binary ~/.altimate/bin/altimateno longer truncates the destination to empty via POSIXcpsemantics. (#820)- Build matrix and standalone install matrix now align — only platforms with a published
@altimateai/altimate-coreNAPI prebuild produce a release archive. (#820)
linux-arm64-musl,linux-x64-musl,linux-x64-baseline-musl, andwin32-arm64archives from the release build matrix.@altimateai/altimate-corehas no NAPI prebuild for these targets; archives for them were never going to work. The npm wrapper (bin/altimate) and npmpostinstall.mjshard-error on these platforms with the sameapk add gcompat/ WSL workarounds the curl-install script uses. Re-added when upstream prebuilds ship. (#820)
Telemetry.maskStringnow redacts email addresses and internal hostnames. Pre-fix, the JSON-quote masking rule incidentally collapsed everything inside provider error JSON to?. The provider-error fix unwraps that JSON, which means provider-side identifiers (caller emails, internal*.local/*.internal/ RFC1918 / IPv6 loopback / ULA / link-local / AWS IMDS endpoints) now flow as plain English. Added explicit redaction patterns so they're masked before reaching telemetry, the share backend, or local session storage. The masker is kept in sync withparseAPICallError'smaskInternalHost(same internal-endpoint coverage); query-string and fragment characters (+,#,,,;) are inside the trailing char class so secrets past the<internal-host>marker don't survive.sk-…andBearer …token redaction is unchanged.metadata.urlonMessageV2.APIErrormasks internal hosts and strips basic-auth userinfo. Whenerror.urlpoints atlocalhost,*.local,*.internal, an RFC1918 IPv4, IPv6 loopback / ULA / link-local, or the AWS IMDS address (169.254.169.254), the host is rewritten tointernal-host.redactedbefore the URL lands on the parsed error. Basic-auth userinfo (user:pass@…) is stripped on every URL — internal or public — since a credential in a public-host URL is at least as risky as one in an internal proxy. Public-host URLs are otherwise preserved verbatim for debugging.responseBodyis capped at 4KB at theparseAPICallErrorboundary. Without this, a hostile or verbose gateway could persist a 100KB+ body into local storage and (for shared sessions) the share backend.
- 46 adversarial tests covering JSON-scalar bodies, prototype-pollution attempts, 100KB error messages, malformed JSON, every-tier null/numeric extraction, Bedrock
errorMessageprecedence, theparseStreamErrorfallback for unknown codes, themodel_not_foundretry-storm carve-out, thealtimate modelshint, the responseBody cap, the metadata.url internal-host masking (incl. IPv6 loopback/ULA/link-local, AWS IMDS, public-host basic-auth userinfo strip, RFC1918 boundary checks, lookalike-hostname guards), and the new email / internal-hostmaskStringpatterns (incl. IMDS, IPv6, and query-fragment leak guards). - 48 adversarial tests in
release-v0.7.1-binary-adversarial.test.tspinning the binary-fix + rename surface — install-method upgrade-path detection (.altimate/.opencode/.localtriple-cover), curl-install hardening (Rosetta notice, cp-on-self guard, stalealtimate-codecleanup, explicit tar/zip member extraction, dualcheck_versionprobe, musl + npm gcompat messaging,--failon both curl paths,pipefail-safe ldd capture, no musl target-suffix construction),_requiredExportsJSON.parse + shape-check rejection, altimate-core version pinning + actionable rebuild hint, staging-dir pre-loop wipe + post-build cleanup, empty-targets and musl-host build guards, build matrix excluding linux-musl + win32-arm64, smoke-test hermeticity (host-platformfindLocalBinaryfilter + tmpdir cwd + content-levelstringsassertion), npm-wrapper + postinstall fail-fast parity for musl + win32-arm64, troubleshooting and README doc surface, archive-name + bin-rename cross-file invariants, andrelease.ymlhermetic CI smoke tests + narrowedpublish-npmpermissions. Tests run together with the provider-error suite as the release-critical gate (test/branding/ test/install/ test/skill/release-v0.7.1*). - Smoke tests (
test/install/smoke-test-binary.test.ts) gained: hermeticNODE_PATH-cleared invocation from a fresh tmpdir (so Bun's compiled binary cannot walk the worktree fornode_modules), and a content-levelstrings-based assertion that exactly one platform.nodeis embedded in the compiled binary — independent of any runtime resolution path, so a silentonResolveregression that embeds 5 platforms' worth of.nodefiles would fire here even if the runtime test passes by accident. (#820)
- 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.tstool 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 carryingaltimate_changemarkers (61 files), keepkeepOursfiles unchanged (65 files), and drop excludedskipFiles(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) - 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 removedServiceMapin favor ofContext). Held back@ai-sdk/*,@openrouter/ai-sdk-provider, and@opentui/*from upstream's bumps. Restored upstream'ssolid-js@1.9.10patchedDependencies declaration (Solid Transition correctness, issue #2046).
--dangerously-skip-permissionsflag onaltimate run(upstream PR #21266 backport). Aliased to our existing--yolo/ALTIMATE_CLI_YOLObranch. Strictly safer than upstream's version:--yolohonors explicitdenyrules in session config, upstream's auto-approves anything not denied with no notion of deny rules. Documented indocs/docs/usage/cli.md.variant_listTUI keybind (upstream PR #21185 backport). Opens the "Switch model variant" dialog (/variants); hidden when no variants are configured. Schema entry inconfig.ts; documented indocs/docs/configure/keybinds.md.- Plain-text rate-limit retry detection (upstream PR #21355 backport).
session/retry.tsnow retries Alibaba/DashScope and other providers that return non-JSON 429 responses. - Telemetry diagnostic fields on
agent_outcome.final_tool,error_class, andreasonare now populated for non-completed outcomes (was empty in ~30% ofabandoned/aborted/errorruns).reasonis PII-masked at extraction (capped 500 chars forerror, 200 foraborted);final_toolincludes MCP-namespaced names (e.g.mcp__atlassian__getJiraIssue);error_classderives fromclassifyErrorpatterns. Documented indocs/docs/reference/telemetry.md. bridge-guardskill (.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#].
- Permission split-brain — infinite ask loop. v1.4.0 introduced an Effect-TS
Permissionservice insrc/permission/index.ts, but every runtime ask site still calledPermissionNext.askfrom the older module insrc/permission/next.ts. The two modules each owned their own pending map: asks landed inPermissionNext'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 plusGET /permissiontoPermissionNext. Pinned with 4 static-text invariants, 1 tree-wide import scan, and 3 runtime end-to-end deadlock tests. mcp addlost its 7-flag non-interactive mode. Bridge merge overwroteMcpAddCommandwith upstream's interactive-only version. Scripts/CI callingmcp 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 --globalflag block with markers.mcp removecommand (andrmalias) restored — entirely lost during v1.4.0 merge.mcp remove <not-found>now exits non-zero (was exiting 0 becauseprocess.exit(1)inside the async Effect chain was swallowed).SessionStatus.set/cancelasync drift. v1.4.0 made these async but six callers inprompt.tsandprocessor.tswere unawaited, racing the idle-state flush on shutdown. All call sites now await;defer(cancel)switched toawait using.tool/plan.tsPlanExitTool reject semantics. v1.4.0 changed reject fromanswer !== "Yes"toanswer === "No", so dialog cancel / dismiss / network drop silently confirmed the agent transition (unsafe). Reverted to "reject on anything but explicit Yes".- SQLite
IMMEDIATEtransaction was silentlyDEFERRED.Database.transaction()wrapper didn't accept thebehavioroption, soSyncEvent.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. - 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. - HTML escaping in OAuth/codex callback templates.
${error}was interpolated raw inmcp/oauth-callback.ts(real XSS) andplugin/codex.ts. AddedescapeHtml()helper, applied at every interpolation. - Symlink escape in
containsPathboundary checks.project/instance.tsandplugin/shared.tsreverted toFilesystem.contains()(lexical) during the bridge merge; restored toFilesystem.containsReal()(resolves symlinks before checking project boundary). - Effect Service identifier collision (
@opencode/Account).account/index.tsandaccount/service.tsboth registered the same id with two parallel ManagedRuntimes (undefined merge behaviour). Deleted deadeffect/runtime.tsandaccount/service.ts; renamedauth/index.tsto@opencode/Auth.clito disambiguate from the liveauth/service.ts. chat.paramsmaxOutputTokenshook silently ignored.session/llm.tscomputedmaxOutputTokensafter the hook fired and never read back fromparams.maxOutputTokens— codex/copilot's ownoutput.maxOutputTokens = undefinedwas a no-op, and any third-party plugin altering this field did nothing. Now matches upstream PRs #21220 + #21225.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 apendingpromise and awaits it on call.MessageV2.fromErrorregressions. "OAuth token refresh failed" now returnsMessageV2.AuthErrorinstead ofUnknownError.errorMessage()surfaces stack location for empty-message Error instances. Context-overflow detection added for OpenAI-stylecontext_length_exceededcodes.workspace-router-middleware.tstypeerror underOPENCODE_EXPERIMENTAL_WORKSPACES=1. Adaptor API was renamedfetch → targetin v1.4.0; rewrote toadaptor.target()+ServerProxy.http()and skip routing for local targets.Truncate.init()lost fromproject/bootstrap.ts. Hourly scheduler that prunesGlobal.Path.data/tool-output/tool_*never re-registered, so the directory grew unboundedly. Restored.provider/models.tssetTimeout(…, 0)deferral on initial refresh. Removed during merge, re-introducing the circular-dep risk fixed by altimate980efaab64. Restored.- TUI mid-render display corruption.
clipboard.ts,dialog-workspace-list.tsx,dialog-mcp.tsxhadconsole.logwriting directly to the terminal mid-render. Restored structuredLog.Default.debugcalls and removed a stray workspace-resultJSON.stringifydebug-print. - Workspace SSE reconnect loop killed by transient network blips.
control-plane/workspace.tslost its defensive.catch(() => undefined)and areturnfrom the local-workspace branch was permanent rather than per-iteration. Restored both. - Branding restoration after v1.4.0 leaks. Fixed in three batches: cycle-7 audit (196 leaks across 66 files:
$schemaURLs, system prompts, repo references, generated SDK strings, route descriptions); ASCII logo (ALTIMATE | CODEblock letters were swapped forOPEN | CODE); brand colors on the startup logo (theme.primarywarm orange +theme.accentpurple were replaced with monochrome grey/white);attach.tsBasic-auth username (wasopencode:, broke authentication against altimate-code servers);cli/cmd/github.tsAGENT_USERNAME / WORKFLOW_FILE / GitHub App slug / OIDC audience / branch prefix; CLI describe text in 8+ subcommands;mcpresolveConfigPath order (altimate-code.jsonprecedence withopencode.jsonfallback for existing installs); plugin install path (.altimate-code/for new installs, keep.opencode/if it exists). - API-key leakage in masked strings.
maskStringonly redacted quoted spans. Added unquoted-API-key (sk-,sk-ant-,sk-proj-) andBearer …patterns with a 20-char length floor (avoids false positives on short identifiers likesk-foo). All 9 existingmaskStringconsumers pick this up. ERROR_PATTERNScoverage for HTTP 5xx + rate-limit prose. Real provider errors likeAPIError: Service unavailable (503)andRate limit exceeded. Retry after 60swere classifying asunknownbecause patterns only matched the prefixed forms. Added phrases:service unavailable,rate limit,rate_limit,retry after,too many requests,503,502,504to thehttp_errorclass.marker-guardstrict mode on bridge-merge pushes to main. PR-side guard already runs non-strict forupstream/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)
- API-key redaction at the diagnostic surface.
Telemetry.deriveAgentOutcomeReason()appliesmaskStringto botherrorandabortedreasons before they enter theagent_outcome.reasonfield (which surfaces in our backend telemetry).prompt.tsextracts onlyerr.data.messageinstead ofJSON.stringify(error.data)(which leakedresponseBody/responseHeaders/ metadata). - 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).
- Three-layer regression backstop for bridge merges. (1)
script/upstream/analyze.ts --brandingnow catches bareopencodestrings in user-visible contexts (yargsdescribe, console output, MCPclientInfo.name, User-Agent, OIDC audiences, GitHub workflow YAML,spawnbinary names); skips lines insidealtimate_changeblocks. (2) NewMergeConfig.requireMarkersallowlist of 38 files known to hold altimate behavioral patches;bridge-merge.tstreats them askeepOursand hard-aborts the merge if any is missing markers. (3) Retroactive marker sweep added markers to 14 previously-unmarked files. CI runs--brandingand--require-markers --stricton every PR. - 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). tracing.tsflushSyncvs asyncsnapshotrace. Crashed-trace file could be clobbered by an in-flight async snapshot completing itsfs.renameafterflushSync's sync write. Added acrashedflag with two checkpoint reads on the async path. PlusRecap.flush()helper to replacesetTimeout(50)waits in tests on slow CI runners.- GitGuardian whitelisting.
.gitguardian.yamlpaths-ignore for theprotected.tsdeny-list (filenames like.pgpass/id_rsa/credentials.jsonare filenames, not credentials); split filename literals viaDOT + "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. .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.globalThis.fetchleak insession-proxy-middleware.test.ts. Test stubbedfetchbut never restored it, cascading into ~15 unrelated test failures (OAuth, ECONNRESET, HttpExporter, Discovery, live-trace-viewer). Now snapshots and restores inafterEach.- Restored
.github/TEAM_MEMBERS. Bridge merge replaced our 30-name list with upstream's 15-name list, removing 28 altimate maintainers includinganandgupta42—pr-standards.ymlwas flagging every team member's PR withneeds:title/needs:complianceand auto-closing after 2 hours.
- 200+ new tests pinning every audit-cycle fix: static-text invariants for service identifiers, async signatures, marker integrity, branding; runtime tests for
Database.transactionIMMEDIATE serialization,BusEvent.defineidempotency,SyncEvent⊆BusEventregistry bridge,PlanExitToolreject semantics, plugin trigger isolation; property-based fuzz ofmaskString(5×500 random iterations on unicode/control-chars/emoji),deriveAgentOutcomeReasonfield bounds; chaos: 100 parallelderiveAgentOutcomeReasoncalls, regex DoS resistance with relative-budget thresholds; E2E: spawns the CLI as a real user (bun run src/index.ts <args>with isolatedXDG_*env vars) and visually inspects--version,--help,mcp --help, theme schemas, system-prompt files, etc. - Hardened flaky tests against parallel-suite contention. Extracted pure helpers from
tui/thread.tsto removemock.module()calls that leaked across files. Replaced FIFO request-matching queue insession/llm.test.tswith a path-keyed Map (out-of-order requests no longer resolve another test's deferred). Added explicit30_000mstimeouts to slow-SDK tests. Local full suite: 7965 pass / 0 fail.
- 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-parityand/dbt-unit-testsquick-demo examples, inline list of the 19 built-in skills. Source of truth is CHANGELOG.md; bullets are condensed restatements. (#784)
- BigQuery finops tools were broken — now work, in any region.
finops_query_historywas failing 100% on BigQuery withUnrecognized name: error_message at [11:5]. Three separate bugs in theINFORMATION_SCHEMA.JOBStemplate: (a)error_messageanderror_codewere read as top-level columns but they only exist inside theerror_resultstruct — now readserror_result.messageanderror_result.reason; (b)total_rowsis aPARTITIONScolumn, notJOBS— replaced withCAST(NULL AS INT64) AS rows_produced; (c) BigQuery'sstatereturns'DONE', not'SUCCESS', so the summary loop was reporting every completed job as FAILED — now derivesexecution_statusfromerror_result IS NULL. Every successful BQ job now reports as SUCCESS. (#739, closes #738) - BigQuery finops unusable outside US region. All five finops modules (
finops_query_history,finops_analyze_credits,finops_expensive_queries,finops_warehouse_advice,finops_unused_resources,finops_role_grants) hardcoded`region-US.INFORMATION_SCHEMA.*`. Now reads the BigQuery connection's configuredlocation(e.g.us,eu,us-central1,asia-northeast1), sanitised via an[a-z0-9-]allowlist with a 64-char cap and hyphen trim. Iflocationis unset the tool defaults tous— setlocationexplicitly on the BigQuery connection for non-US projects or you will query the wrong region. Snowflake and Databricks paths are unchanged. (#739)
@altimateai/altimate-core0.3.0 → 0.3.1 — upstream patch release of the native SQL type-checker used byaltimate_core_validateand the cross-dialect data-parity engine.
- New showcase page (
docs/examples/) with 12 end-to-end workflow demos — dbt peer review, column-level lineage diff, MS SQL → Fabric migration, Fabric platform admin, upstream schema change, NYC Taxi, Olist, Spotify, and more. (#742) locationfield documented on the BigQuery connection and called out on the finops tools page.
finops_query_history,finops_analyze_credits, andfinops_warehouse_advicereaduser_email(BigQuery),user_name(Snowflake / Databricks / ClickHouse), and rawquery_textfrom warehouse system views. Results are returned to the agent and enter the LLM context window. No telemetry or backend upload. Review your tenant's data-handling policy before enabling finops tools in regulated (PII / PHI / PCI) environments.finops_unused_resourceson BigQuery readsINFORMATION_SCHEMA.TABLE_STORAGE, which is an org-level view. Project-scoped service accounts typically requirebigquery.resourceAdminat the org to avoid a permission error.
anti-slopCI workflow is now advisory — labels + comments still fire on blocked-term hits, but the workflow no longer auto-closes PRs. Root cause: the repo's pull-request template embeds an HTML comment instructing AI to insert "PINEAPPLE", whichanti-slop.ymlalso blocklists — every AI-assisted team-member PR was auto-closing within two minutes. (#741, closes #740)- Marker-guard hotfix: the
isValidDatabricksHostenv-fallback path added in v0.6.0 straddled the post-push Marker Guard's-U5diff window; wrapped in an inlinealtimate_changemarker pair to keep strict mode green.
- New adversarial tests for v0.6.1 in
packages/opencode/test/skill/release-v0.6.1-adversarial.test.ts:sanitizeBqRegioninjection vectors (CRLF, null bytes, backticks, path traversal, Unicode homoglyphs, prototype-pollution-adjacent inputs),interpolateBqRegionidempotency and multi-placeholder safety,bqRegionForregistry edge cases, BIGQUERY_HISTORY_SQL column-name regression guards (all four #739 bugs), cross-module "every BQ template uses{region}" guard, and full-pipelinebuildHistoryQuerybehaviour including Snowflake / Databricks no-regression guards.
- Data parity (
data_difftool + skill) — compare tables or SQL-query results row-by-row across Postgres, Snowflake, BigQuery, Databricks, ClickHouse, MySQL, Redshift, SQL Server, Microsoft Fabric, DuckDB, SQLite, and Oracle. Five algorithms:auto(JoinDiff same-dialect, HashDiff cross-dialect),joindiff(FULL OUTER JOIN),hashdiff(bisecting checksums — works at any scale without pulling data out),profile(column-level statistics, no row values leave the database), andcascade(profile first, then HashDiff on diverging columns). Partitioning supports date (day/week/month/year), numeric (bucket_size), and categorical (distinct values) modes so 100M+ row tables diff in independent batches. Auto-discovers comparable columns frominformation_schema, excludes audit/timestamp columns by name pattern AND by catalog default (NOW(),CURRENT_TIMESTAMP,GETDATE(),SYSDATE,SYSTIMESTAMP), and confirms exclusions with the user before diffing. (#493) - MSSQL and Microsoft Fabric support in data-parity — dialect-aware date truncation (
DATETRUNC), locale-safe date literals (CONVERT(DATE, ..., 23)), and seven Azure AD / Entra ID authentication flows (password, access-token, service-principal-secret, MSI-VM, MSI-app-service, default credential chain, token-credential) delegated totedious. Upgradesmssqlv11 → v12 with explicitConnectionPoolisolation and correct handling of unnamed-column result sets. (#705) - Databricks AI Gateway provider — connect to Databricks serving endpoints (Foundation Model APIs) via PAT auth (
workspace-host::token), with fallback toDATABRICKS_HOST/DATABRICKS_TOKENenvironment variables. Registers 11 foundation models — Meta Llama 3.1 (405B / 70B / 8B), Claude Sonnet / Opus 4.6, GPT-5.4 / GPT-5 Mini, Gemini 3.1 Pro, DBRX Instruct, and Mixtral 8x7B. Host regex restricts credentials to*.cloud.databricks.com,*.azuredatabricks.net, and*.gcp.databricks.com. (#649, closes #602) - Amazon Bedrock custom-endpoints guide — dedicated docs page covering bearer-token auth, AWS credential chain,
baseURLconfiguration, cross-region model-ID prefixing, and troubleshooting. Provider key corrected frombedrocktoamazon-bedrockacross quickstart, providers, and models pages. (#706) - User-facing docs for the new features — Databricks AI Gateway section in
configure/providers.mdand a fulldata-engineering/guides/data-parity.mdcovering supported warehouse pairs, algorithms, partition modes, Azure AD auth matrix for Fabric, and compliance guidance.
@altimateai/altimate-core0.2.6 → 0.3.0 — enables the cross-dialect data-parity engine, T-SQL dialect support for MSSQL/Fabric, and refined hashdiff bisection. Rebuilt native binaries published for all five supported platforms. (#717, closes #716)- Altimate connect dialog polish —
/connectnow acceptsinstance-name::api-keydirectly (default URLhttps://api.myaltimate.com). The three-partapi-url::instance-name::api-keyform still works for custom and self-hosted instances. Provider display name "Altimate" → "Altimate AI"; default model display "Altimate AI" → "Altimate LLM Gateway". The internal provider ID (altimate-backend) and model ID (altimate-default) are preserved — existingmodel.jsonfavorites, recents, and pinnedmodel:entries inopencode.jsoncontinue to work without migration. (#724)
- Text contrast on light terminal backgrounds — dark foreground (
#1a1a1aorpalette[0]when available) replaces the near-invisiblepalette[7]on light-mode system themes, and inline code blocks now render on an opaque background instead of transparent. EagerCOLORFGBGenv-var detection narrowed tobg === 7 || bg === 15skips the 1-second OSC 11 query altogether on light terminals that don't support it (urxvt, gnome-terminal). (#712, closes #704) - Historical
tool_useblocks after agent switches or MCP disconnects — the LiteLLM-only_noopworkaround is replaced by a general fix: tool names are extracted from bothtool-callandtool-resultblocks in message history (usingObject.hasOwn()for prototype-pollution safety), validated against/^[a-zA-Z0-9_-]{1,64}$/, and registered as stubs that return "tool no longer available" if the model attempts to call them. Eliminates the Anthropic API 400 error "Requests with 'tool_use' and 'tool_result' blocks must include tool definition." (#703, closes [AI-678]) /docscommand and config links point todocs.altimate.sh— the TUI "Open docs" action, Cloudflare AI Gateway help text, Anthropic system prompt, andConfig.command/Config.agentschema descriptions previously linked to the wrong domain. Also updates paths to the/configure/prefix that matches the actual mkdocs site. (#715, closes #714)
- Databricks host validation hardened — new
isValidDatabricksHosthelper rejects CRLF/whitespace (JS regex$matches before\nby default), and the env-fallback path now validates host before constructing thebaseURL. - Tool-name validation — stub registration ignores names with shell metacharacters, ANSI escapes, control characters, or lengths > 64, guarding against tampered session-file replays.
- Restricted
azinherited env —az account get-access-tokenis invoked with a whitelisted environment (PATH,HOME,AZURE_*, locale) so unrelated secrets (DATABRICKS_TOKEN, cloud provider keys) are not inherited byazor anyazextension.
- 38 new adversarial tests covering Databricks host validation (CRLF, anchoring, attacker suffixes), PAT parsing edge cases, body transform, tool-name tainted-input guards, and
data_difftool-description release contract. - 139-test consolidation across dbt helpers, file status, project-scan, session/llm, and MCP discovery — symlink cache round-trips, seed/test node exclusion, JSON array edge cases, sessionId sanitization, pagination boundary math, and connection-string masking. Two broken
${VAR}-in-MCP-commandtests removed (resolution was always restricted toenvandheaders). (#709)
data_diff includes up to 5 sample diff rows in its tool output, which becomes part of the LLM conversation. For PII / PHI / PCI data, use algorithm: "profile" — column statistics compare without sending row values. The data-parity skill asks for explicit confirmation before running row-level diffs against tables whose names match common regulated patterns (customers, patients, orders, payments, accounts, users). A hard env-var opt-out for sample values is tracked in #729.
mssqlupgraded to v12. Users withmssql@^11pinned at the application level will see "mssql.ConnectionPool is not available" on first SQL Server connection. Pin to^12or let altimate resolve.- SQL Server result sets now expose
_-prefixed columns. The internalstartsWith("_")column filter (introduced for partition-discovery noise suppression) was removed because it also stripped legitimate aliases like_pused by the partition engine. Queries that relied on this implicit filtering will see the extra columns in results.
- Automated dbt unit test generation — generate dbt unit tests (v1.8+) from your terminal with
/dbt-unit-testsor thedbt_unit_test_gentool. Detects testable SQL constructs (CASE/WHEN, JOINs, NULLs, window functions, division, incremental models) and assembles complete YAML with type-correct mock data across 7 dialects. Includesinput: thismocks for incremental models,format: sqlfor ephemeral deps, and handles seeds/snapshots as first-classref()deps. Five-phase skill workflow: Analyze → Generate → Refine → Validate → Write. Requires dbt-core 1.8+. (#673) - Manifest parse cache —
loadRawManifest()caches by path+mtime so large manifests (100MB+) are parsed once per session, not once per tool call. - Model/source descriptions in manifest —
DbtModelInfoandDbtSourceInfonow surface descriptions fromschema.yml, giving downstream tools richer semantic context. adapter_typeonDbtManifestResult— exposes the dbt adapter type (snowflake, bigquery, etc.) from manifest metadata for dialect auto-detection.
- MCP env-var
$${VAR}escape and chain-injection vulnerability — the two-layer env-var resolution design allowed$${VAR}escapes to be re-resolved (breaking literal${VAR}passthrough) and enabled variable-chain injection whereEVIL_VAR="${SECRET}"could exfiltrate secrets the config never referenced. Collapsed to a single resolution pass scoped toenvandheadersfields only. (#697, relates to #656) - MCP server environment variables passed as literals —
${VAR},${VAR:-default}, and{env:VAR}patterns in MCP serverenvblocks were passed as literal strings to child processes, causing auth failures for tools likegitlab-mcp-server. (#666, closes #656) sql_explainandaltimate_core_validateinput hardening — reject empty/placeholder SQL and warehouse names before hitting the warehouse.sql_explainnow generates dialect-aware EXPLAIN statements for 12+ warehouse types. Driver errors are translated into actionable guidance (e.g., "No warehouses configured — runwarehouse_add").altimate_core_validatenow runs even without a schema (previously hard-failed), with a(no schema)indicator and clear instructions for providing schema context. (#693, closes #691)sql_explainalternatives for unsupported warehouses — BigQuery, Oracle, and SQL Server now return specific guidance (dry-run API,DBMS_XPLAN,SET SHOWPLAN_TEXT ON) instead of a generic "not supported" message.
- Altimate model auto-selection — when Altimate credentials are configured and no model is explicitly chosen,
altimate-backend/altimate-defaultis selected automatically. Respects theproviderfilter in config if set. No manual/modelselection needed for first-time Altimate users. (#665)
- Connection string passwords with special characters — passwords containing
@,#,:,/, or other URI-reserved characters are now automatically percent-encoded inconnection_stringconfigs. Previously these caused cryptic authentication failures because the URI parser split on the wrong delimiter. Already-encoded passwords (%XX) are left untouched. Affects all URI-based drivers (PostgreSQL, MongoDB, ClickHouse). (#597, closes #589) trace listpagination —trace listnow supports--offsetfor navigating large trace histories, displays "Showing X-Y of N" with a next-page hint, and caps the TUI trace dialog at 500 items (up from 50) with an overflow message pointing to the CLI for the full set. (#596, closes #418)- ClickHouse edge-case hardening — added tests for
LowCardinality(Nullable(...))nullability detection,Map/Tuplewrapper handling, undefined type fallback, and SQL comment/string-escape edge cases in the LIMIT injection guard. (#599, closes #592)
- 31 new adversarial tests covering connection string sanitization (injection, encoding edge cases, ReDoS, Unicode, null bytes), pagination boundary math (Infinity, NaN, fractional, negative inputs), and
Provider.parseModeledge cases.
${VAR}environment variable interpolation in configs — use shell/dotenv-style${DB_PASSWORD},${MODE:-production}(with defaults), or$${VAR}(literal escape) anywhere inaltimate.jsonand MCP server configs. Values are JSON-escape-safe so passwords containing quotes or backslashes can't corrupt your config structure. The existing{env:VAR}syntax continues to work for raw text injection. (#655, closes #635)
- Plan agent warns when the model refuses to tool-call — if the plan agent's model returns text without invoking any tools, altimate-code now surfaces a one-shot TUI warning suggesting you switch models via
/modelinstead of silently hanging. Telemetry eventplan_no_tool_generationemitted for session-level diagnosis. (#653) - GitLab MR review: large-diff guard & prompt-injection hardening — MRs exceeding 50 files or 200 KB of diff text are truncated upfront with a user-visible warning, and the review prompt explicitly frames MR content as untrusted input. (#648)
- Atomic trace file writes —
FileExporternow writes to a temp file and renames, preventing partial/corrupt trace JSON on crash or SIGKILL. Stale.tmp.*artifacts older than 1 hour are swept during prune. (#646) - 15s timeout on credential validation —
AltimateApi.validateCredentials()no longer hangs indefinitely if the auth endpoint stalls. (#648) - Shadow-mode SQL pre-validation telemetry — measures catch-rate for structural errors (missing columns, tables) against cached schema before enabling user-visible blocking in a future release. Fire-and-forget, zero impact on the
sql_executehot path. No raw SQL, schema identifiers, or validator error text transmitted. (#643, #651) - GitLab docs rewrite — replaced "work in progress" warning with a complete guide: quick-start, authentication, self-hosted instances, model selection, CI example. (#648)
- 25 new adversarial tests covering env-var interpolation (JSON-escape safety, single-pass substitution, ReDoS, escape hatch, defaults), atomic write hygiene (race conditions, tmp sweep, sessionId sanitization), and telemetry identifier-leak guards. New ClickHouse finops/profiles/registry coverage. (#624)
- Native GitLab MR review — review merge requests directly from your terminal with
altimate gitlab review <MR_URL>. Supports self-hosted GitLab instances, nested group paths, and comment deduplication (updates existing review instead of posting duplicates). RequiresGITLAB_PERSONAL_ACCESS_TOKENorGITLAB_TOKENenv var. (#622) - Altimate LLM Gateway provider — connect to Altimate's managed model gateway via the TUI provider dialog (select a provider → "Altimate"). Credentials validated before save, stored at
~/.altimate/altimate.jsonwith0600permissions. (#606)
- Glob tool: timeout, home/root blocking, default exclusions — glob searches now timeout after 30s (returning partial results) instead of hanging indefinitely. Scanning
/or~is blocked with a helpful message. Common directories (node_modules,.git,dist,.venv) are excluded by default. (#637) - MCP config normalization — configs using
mcpServers(Claude Code, Cursor format) are auto-converted tomcpat load time. External server entries withcommand+args+envare transformed to altimate-code's native format. (#639) - Light theme readability — fixed white-on-white text in light terminal themes by adding explicit foreground colors to markdown and code blocks. (#640)
- Custom dbt
profiles.ymlpath resolution — Altimate Code now resolvesprofiles.ymlusing dbt's standard priority: explicit path →DBT_PROFILES_DIRenv var → project-localprofiles.yml→~/.dbt/profiles.yml. Teams usingDBT_PROFILES_DIRin CI get zero-friction auto-discovery. Jinja{{ env_var('NAME') }}patterns are resolved automatically. A warning is shown whenDBT_PROFILES_DIRis set but the file is not found. (#605)
- ClickHouse: SQL comment injection bypass — Comments could previously mask write statements from the read-only LIMIT guard. String literals are now stripped before comment removal to prevent false matches. (#591)
- ClickHouse:
LowCardinality(Nullable(...))nullability — Schema inspection previously reported these columns as non-nullable; now correctly detected as nullable. (#591) - ClickHouse: connection lifecycle guards — All query methods now throw a clear error if called before
connect(), preventing cryptic TypeErrors. (#591) - ClickHouse:
bindsparameter handling — Queries with parameterized binds no longer throw a driver error; the parameter is safely ignored (ClickHouse usesquery_paramsnatively). (#591) - Stale file retry loops on WSL and network drives —
FileTime.read()now uses filesystem mtime instead of wall-clock, eliminating 782-iteration retry loops caused by clock skew on WSL (NTFS-over-9P), NFS, and CIFS mounts. SetOPENCODE_DISABLE_FILETIME_CHECK=trueas escape hatch if needed. (#611) - Error classification:
file_stalesplit and keyword fix —file_staleis now a distinct error class; HTTP 4xx errors no longer misclassify as validation failures; restored"does not exist"keyword for SQL errors like"column foo does not exist". (#611, #614)
- ClickHouse support — Connect to ClickHouse Cloud, self-hosted clusters, or local Docker instances running ClickHouse 23.3+. Supports HTTP/HTTPS, TLS mutual auth, and dbt-clickhouse adapter auto-discovery. Includes MergeTree optimization guidance, materialized view design, partition pruning analysis, and query history via
system.query_log. Requiresnpm install @clickhouse/client(#574)
- Agent loop detection — The agent now detects when a single tool is called 30+ times in a session (a pattern seen with runaway tool loops) and pauses for confirmation before continuing. Complements the existing same-input repetition detection (#587)
- Improved error diagnostics — Tool failures now report more specific error categories (
not_configured,file_not_found,edit_mismatch,resource_exhausted) instead of generic "unknown" classification, improving support triage (#587) - Session environment metadata —
session_starttelemetry now includesos,arch, andnode_versionfor environment-based segmentation (#587)
- Plan agent two-step approach — outline first, confirm, then expand; plan refinement loop with edit-in-place (capped at 5 revisions); approval phrase detection ("looks good", "proceed", "lgtm") (#556)
- Feature discovery & progressive disclosure — contextual suggestions after warehouse connection (schema, SQL, lineage, PII); dbt auto-detection recommending
/dbt-develop,/dbt-troubleshoot(#556)
- SQL classifier fallback security hardening — invert fallback to whitelist reads (not blacklist writes), handle multi-statement SQL, strip line comments, fix
HARD_DENY_PATTERN\s→\b; fixcomputeSqlFingerprintreferencing undefinedcoreafter safe-import refactor (#582) - Edit tool nearest-match error messages —
buildNotFoundMessagewith Levenshtein similarity search shows closest file content whenoldStringnot found, helping LLM self-correct (#582) - Webfetch failure caching and actionable errors — session-level URL failure cache (404/410/451) with 5-min TTL; status-specific error messages telling the model whether to retry; URL sanitization in errors to prevent token leakage (#582)
- Nested
node_modulesinNODE_PATH—@altimateai/altimate-coreNAPI resolution now works for npm's hoisted and nested layouts (#576) - Null guards across 8 tool formatters — prevent literal
undefinedin user-facing output for sql-analyze, schema-inspect, sql-translate, dbt-manifest, finops, and warehouse tools; DuckDB auto-retry ondatabase is locked(#571) - Telemetry error classification — add
http_errorclass, expand connection/validation/permission patterns, redact sensitive keys in input signatures (#566) - Pre-release review findings — remove dead code, fix
classifySkillTrigger()unknown trigger handling, add null guards in lineage/translate tools (#580) - Binary alias hard copy — use
cpinstead of symlink foraltimate-codebinary alias to fix cross-platform compatibility (#578)
- Verdaccio sanity suite: 50 new tests across 3 phases, added to CI and release workflows (#560, #562)
- 12 new tests for
buildNotFoundMessage,computeSqlFingerprint, and webfetch error messages (#582)
- MongoDB driver support — 11th supported database with full MQL command set (find, aggregate, CRUD, indexes), BSON type serialization, schema introspection via document sampling, and cross-database queries; includes 90 E2E tests (#482)
- Skill follow-up suggestions — contextual "What's Next?" suggestions after skill completion to reduce first-run churn; maps 12 skills to relevant follow-ups with warehouse discovery nudge (#546)
altimate-dbt buildwithout--model— builds the entire dbt project viaunsafeBuildProjectImmediately, replacing the separatebuild-projectcommand (#546)upstream_fix:marker convention — new tag for temporary upstream bug fixes with--audit-fixescommand to review carried fixes before upstream merges (#555)- Verdaccio-based sanity suite — local npm registry test harness for real install verification, smoke tests, and upgrade scenarios (#503)
- Locale duration days/hours swap —
Locale.duration()for values ≥24h showed wrong days/hours (total hours instead of remainder); e.g., 25h now correctly shows1d 1h(#529) - Dispatcher
reset()not clearing lazy registration hook —reset()only cleared handlers but left_ensureRegisteredalive, causing flaky test failures (#529) - Impact analysis showing project-wide test count — was using
manifest.test_count(all tests in project) instead of counting only tests referencing the target model (#529) - Prototype pollution in
SkillFollowups.get()—FOLLOWUPS["__proto__"]traversedObject.prototype; fixed withObject.hasOwn()guard (#558) - Shallow freeze in
SkillFollowups.get()—Object.freeze()on array didn't freeze nested objects, allowing shared state mutation; fixed with deep copy (#558) - CI Bun segfault resilience — Bun 1.3.x crashes during test cleanup now handled by checking actual pass/fail summary instead of exit code (#555)
- 52 adversarial tests for v0.5.14 release:
SkillFollowupsinjection/boundary/immutability,Locale.durationtier transitions,Dispatcher.resethook cleanup (#558) - Consolidated 39 test PRs — 1,173 new tests across session, provider, MCP, CLI stats, bus, and utility modules (#498, #514, #545)
- Pin
@altimateai/altimate-coreto exact version — prevents npm from resolving stale cached binaries during install (#475) - Flaky
dbt Profiles Auto-Discoverytests in CI — stabilized tests that failed intermittently due to timing issues
- Bump
yamlfrom 2.8.2 to 2.8.3 — dependency update inpackages/opencode(#473)
altimate-dbtauto-discover config —altimate-dbtcommands now auto-detectdbt_project.ymland Python from the current directory without requiringaltimate-dbt initfirst; supports Windows paths (Scripts/,.exe,path.delimiter) (#464)- Local E2E sanity test harness — Docker-based test suite (
test/sanity/) for install verification, smoke tests, upgrade scenarios, and resilience checks; runnable viabun run sanity(#461)
altimate-dbtcommands fail with hardcoded CI path — published binary contained a baked-in/home/runner/work/...path for the Python bridge;copy-python.tsnow patches__dirnameto useimport.meta.dirnameat runtime (#467)
- 42 adversarial tests for config auto-discovery and dbt resolution:
findProjectRootedge cases (deep nesting, symlinks, nonexistent dirs),discoverPythonwith broken symlinks and malicious env vars,resolveDbtwith conflicting env vars and priority ordering,validateDbttimeout/garbage handling, Windows constant correctness,path.delimiterusage,buildDbtEnvmutation safety - 484-line adversarial test suite for the
__dirnamepatch: regex edge cases, ReDoS protection, mutation testing, idempotency, CI smoke test parity, bundle runtime structure validation
- README changelog gap — updated README to reflect releases v0.5.1 through v0.5.11; previous README only listed up to v0.5.0
- npm publish transient 404s — added retry logic (3 attempts with backoff) to
publish.tsfor concurrent scoped package publishes that hit npm registry race conditions
altimate-code checkCLI command — deterministic SQL checks (linting, formatting, style) that run without an LLM, suitable for CI pipelines and pre-commit hooks (#453)- Data-viz skill improvements — lazy initialization, data-code separation, color contrast rules, icon semantics, field validation, and pre-delivery checklist (#434)
- Snowflake Cortex not visible before authentication — provider now appears in the provider list even when not yet authenticated (#447)
- New user detection race condition — first-run welcome flow and telemetry events could fire out of order or be skipped entirely (#445)
- 52 CI test failures from
mock.moduleleaking across files — test isolation fix for the newcheckcommand e2e tests (#460) - Missing
altimate_changemarker — added required upstream marker onisStatelessCommandguard to pass Marker Guard CI (#457)
- Rename Recap back to Trace — reverted the Recap branding to Trace across 29 files for better AI model comprehension of session recording concepts (#443)
- Consolidated 12 hourly test PRs into single batch: slugify, hints sort, skill formatting, batch tools, filesystem utilities, wildcard matching — 1,680 new test lines (#439)
altimate-code checkunit + e2e test suites (1,687 lines) (#453)- Snowflake Cortex provider visibility tests (#447)
- Codespaces support — skip machine-scoped
GITHUB_TOKENthat lacks repo access, cap provider retries to prevent infinite loops, fix phantom/discover-and-add-mcpscommand that was missing from builtin commands (#415) sql_analyzereports "unknown error" for successful analyses — tool returned error status even when analysis completed successfully (AI-5975) (#426)- Remove
semverdependency from upgrade path — replaced with zero-dependency version comparison to prevent users getting locked on old versions whensemverfails to load (#421) - Ship
discover-and-add-mcpsas a builtin command — moved from.opencode/command/config directory to embedded template so it works out of the box (#409)
- Comprehensive upgrade decision tests covering version comparison, downgrade prevention, and edge cases (#421)
- Codespace E2E tests for
GITHUB_TOKENfiltering, retry caps, and provider initialization (#415)
- dbt commands crash with
SyntaxError: Cannot use import statement— bundleddbt-tools/was missingpackage.jsonwith"type": "module", causing Node to default to CJS and reject ESM imports. Broken since v0.5.3. (#407) - Publish script idempotency — re-running
publish.tswithout cleaningdist/would crash because the synthesizeddbt-tools/package.json(noname/version) polluted the binary glob scan (#407) - Skill builder
ctrl+ikeybind — ESC navigation and dialog lifecycle fixes in TUI skill management (#386) - Upgrade notification silently skipped — multiple scenarios where the upgrade check was bypassed (#389)
- Phantom
sql_validatetool — removed non-existent tool reference from analyst agent permissions, replaced withaltimate_core_validate(#352) - CI test suite stability — eliminated 29 pre-existing test failures: added
duckdbdevDependency, fixed native binding contention with retry logic andbeforeAllconnections, increased timeouts for slow bootstrap operations, added--timeout 30000to CI workflow (#411)
- Trace (session recording) — session trace with loop detection and enhanced viewer (#381)
- ESM bundling regression tests — 9 e2e tests verifying Node can load
altimate-dbtvia symlink, wrapper, and direct invocation paths
- 133 new tests across 9 modules: finops role access, tool lookup, config path parsing, ID generation, file ignore/traversal, patch operations, session instructions/messages/summaries, shell utilities (#403)
- SQL validation adversarial + e2e test suites (#352)
- Provider error classification — overflow detection and message extraction (#375)
- Impact analysis DAG traversal and training import parsing (#384)
- RPC client protocol and
abortAfter/abortAfterAnycoverage (#382) - Color, signal, and defer utility coverage (#379)
- MCP config CRUD + Locale utility coverage (#369)
- Impact analysis tool — analyze downstream blast radius of dbt model/column changes across the DAG with severity classification (SAFE/LOW/MEDIUM/HIGH) and actionable recommendations (#350)
- Training import tool — bulk import training entries from markdown style guides, glossaries, and playbooks with dry-run preview and capacity management (#350)
- CI check command —
/ci-checktemplate for pre-merge SQL validation that analyzes changed files, checks dbt integrity, and generates CI-friendly reports (#350) --max-turnsbudget limit — CLI option to cap agent steps for CI/enterprise governance (#350)- LM Studio provider — local Qwen model support via LM Studio (#340)
- Improved onboarding — first-time user hints on home screen, beginner-focused tips, practical quickstart examples (#350)
- Expanded
/discover— detects additional cloud warehouse credentials (Snowflake, BigQuery, PostgreSQL, Databricks, Redshift) (#350) - Automated test discovery —
/test-discoverycommand for hourly test generation with critic validation (#364, #365, #366, #367)
- Yolo mode now respects explicit deny rules from session config instead of auto-approving everything (#350)
- Training limits increased from 20→50 entries per kind and 16KB→48KB budget for enterprise teams (#350)
- E2E tests for trace viewer with adversarial cases (#353)
- Bash tool PATH injection tests (#366)
fn()wrapper andskillSourcetrust classification tests (#367)AsyncQueue/work()utility andState.invalidatecoverage (#364)
- Skill CLI command — new top-level
altimate-code skillwithlist,create,test,show,install,removesubcommands for managing AI agent skills and paired CLI tools (#342) .opencode/tools/auto-discovery — executables in.opencode/tools/(project) and~/.config/altimate-code/tools/(global) are automatically prepended to PATH in BashTool and PTY sessions (#342)- TUI skill management —
/skillsdialog with domain-grouped skill browser,ctrl+aaction picker (show, edit, test, remove),ctrl+ncreate,ctrl+iinstall from GitHub (#342) - Skill install from GitHub —
altimate-code skill install owner/repoclones and installs skills; supports GitHub web URLs, shorthand, local paths, and--globalflag (#342) - Skill cache invalidation —
State.invalidate()andSkill.invalidate()withGET /skill?reload=trueendpoint for cross-thread cache clearing (#342) - Snowflake Cortex AI provider — use Snowflake Cortex as an AI provider for LLM completions (#349)
- Telemetry for skill operations —
skill_created,skill_installed,skill_removedevents (#342) - E2E smoke tests — committed tests for skill lifecycle, git-tracked protection, symlink safety, GitHub URL normalization (#363)
- Symlink traversal protection during skill install — uses
fs.lstatto skip symlinks and prevent file disclosure from malicious repos (#342) - Git-tracked skills cannot be removed via
skill removeor TUI — prevents accidental deletion of repo-managed skills (#342) - GitHub web URLs (e.g.,
https://github.com/owner/repo/tree/main/path) correctly normalized to clonable repo URLs (#342) .gitsuffix stripped from install source to prevent double-append (#342)- TUI skill operations use
sdk.directory+gitRoot()instead ofInstance/Globalwhich only exist in the worker thread (#342) - TUI install uses async
Bun.spawninstead of blockingBun.spawnSyncto keep UI responsive (#342) - Missing
altimate_changemarkers indialog-skill.tsxandskill.ts(#341, #344)
- Auto-discover MCP servers from external AI tool configs (VS Code, Cursor, GitHub Copilot, Claude Code, Gemini CLI, Claude Desktop) — discovered project-scoped servers are disabled by default and require explicit approval; home-directory configs are auto-enabled (#311)
- Security FAQ documentation for MCP auto-discovery — covers trust model, security hardening, and how to disable (#346)
auto_mcp_discoverynow defaults totruein config schema viaz.boolean().default(true)— matches existing runtime behavior (#345)
- Add missing
altimate_changemarkers forexperimentalblock inopencode.jsonc— fixes Marker Guard CI failure on main (#344)
- Show update-available indicator in TUI footer — when a newer version is available, the footer displays
↑ version · altimate upgradewith responsive layout for narrow terminals (#175) - Track per-generation token usage in telemetry — emit
generationevent with flat token fields (tokens_input,tokens_output,tokens_reasoning,tokens_cache_read,tokens_cache_write) for Azure App Insights compatibility (#336)
- Replace
better-sqlite3withbun:sqlitefor schema cache and SQLite driver — fixesschema_index,schema_search,schema_cache_status, and SQLite driver for all users on the released CLI binary (#323) - Fix marker guard diff parser bug — context lines now correctly update
altimate_changemarker state, preventing false negatives that allowed marker leaks to pass CI (#338) - Extend marker guard CI to run on push-to-main with zero-SHA guard — closes the gap where individual PRs pass but combined state of
mainhas missing markers (#338) - Add
import.meta.mainguard toanalyze.tsso test imports don't trigger CLI side effects (#338) - Add 21 unit tests for marker diff parser and run them in CI (#338)
- Bundle skills, dbt-tools, and altimate-setup in shipped npm binary — skills now work in all distribution channels (npm, Homebrew, AUR, Docker) without relying on
postinstallfilesystem copies (#316) - Exclude 220MB of unused
.nodebinaries from dbt-tools bundle (#320) - Documentation about warehouse connections updated (#318)
- Added
altimate_changemarkers to upstream-shared files and marker removal detection to CI — prevents markers from being silently stripped (#322)
- Trace history dialog (
/tracecommand) — browse, search, and open past session traces from the TUI (#297) - Docs showcase examples with screenshots (#292)
- TUI trace dialog now respects custom
tracing.dirconfig — previously always used default directory (#307) - WebFetch
clearTimeoutleak — DNS failures no longer leak timer handles (#307) - WebFetch User-Agent strategy inverted to honest-bot-first — reduces 403 blocks from TLS fingerprint mismatch (#303)
- Snowflake SDK stdout log noise suppressed in TUI via
additionalLogToConsole: false(#305, #301) cleanTitlefallback in trace dialog no longer returns empty string (#307)- Error logging added to
openTraceInBrowserfor debuggability (#307) altimate_changemarkers added towebfetch.tsfor upstream merge compatibility (#307)
- Snowflake SDK minimum version bumped to
^2.0.3for log suppression support (#305) - Removed brew from docs and README (#299)
- Fixed README typo (
altimate→altimate-code) (#293)
- Simplified agent modes: 3 primary modes (
builder,analyst,plan) replacing 7 — cleaner UX with focused roles (#282) - SQL write access control —
builderprompts for approval on write queries,analystblocks them entirely, destructive SQL (DROP DATABASE,TRUNCATE) hard-blocked (#282) core_failuretelemetry with PII-safe input signatures — captures tool failures with masked SQL literals and redacted secrets (#245)peerDependenciesfor database drivers in published npm packages (#273)- Comprehensive docs restructuring with new Changelog, Getting Started, and Tools reference pages (#284)
- Replace
escapeSqlStringwith parameterized query binds infinops/schemamodules (#277) - Driver error messages now suggest
npm installinstead ofbun add(#273) - System prompt traced only once per session to avoid duplication (#287)
- Bump
@altimateai/altimate-coreto 0.2.5 — adds Rust-side failure telemetry with PII masking - Removed 5 agent prompts:
executive,migrator,researcher,trainer,validator(#282) - README cleanup and updated branding (#288)
- Smooth streaming mode for TUI response rendering (#281)
- Ship builtin skills to customers via
postinstall(#279) /configure-claudeand/configure-codexbuilt-in commands (#235)
- Brew formula stuck at v0.3.1 — version normalization in publish pipeline (#286)
- Harden auth field handling for all warehouse drivers (#271)
- Suppress console logging that corrupts TUI display (#269)
- Script to build and run compiled binary locally (#262)
- Snowflake auth — support all auth methods (
password,keypair,externalbrowser,oauth), fix field name mismatches (#268) - dbt tool regression — schema format mismatch, silent failures, wrong results (#263)
altimate-dbt compile,execute, and children commands fail with runtime errors (#255)Cannot find module @altimateai/altimate-coreonnpm install(#259)- Dispatcher tests fail in CI due to shared module state (#257)
- CI: parallel per-target builds — 12 jobs, ~5 min wall clock instead of ~20 min (#254)
- CI: faster release — build parallel with test, lower compression, tighter timeouts (#251)
- Docker E2E tests skip in CI unless explicitly opted in (#253)
- Python engine eliminated — all 73 tool methods now run natively in TypeScript. No Python, pip, venv, or
altimate-engineinstallation required. Fixes #210.
@altimateai/driversshared workspace package with 10 database drivers (Snowflake, BigQuery, PostgreSQL, Databricks, Redshift, MySQL, SQL Server, Oracle, DuckDB, SQLite)- Direct
@altimateai/altimate-corenapi-rs bindings — SQL analysis calls go straight to Rust (no Python intermediary) - dbt-first SQL execution — automatically uses
profiles.ymlconnection when in a dbt project - Warehouse telemetry (5 event types: connect, query, introspection, discovery, census)
- 340+ new tests including E2E tests against live Snowflake, BigQuery, and Databricks accounts
- Encrypted key-pair auth support for Snowflake (PKCS8 PEM with passphrase)
- Comprehensive driver documentation at
docs/docs/drivers.md
- Python bridge connection failures for UV, conda, and non-standard venv setups (#210)
- SQL injection in finops/schema queries (parameterized queries + escape utility)
- Credential store no longer saves plaintext passwords
- SSH tunnel cleanup on SIGINT/SIGTERM
- Race condition in connection registry for concurrent access
- Databricks DATE_SUB syntax
- Redshift describeTable column name
- SQL Server describeTable includes views
- Dispatcher telemetry wrapped in try/catch
- Flaky test timeouts
packages/altimate-engine/— entire Python package (~17,000 lines)packages/opencode/src/altimate/bridge/— JSON-RPC bridge.github/workflows/publish-engine.yml— PyPI publish workflow
- Local-first tracing system replacing Langfuse (#183)
- Engine not found when user's project has
.venvin cwd — managed venv now takes priority (#199) - Missing
[warehouses]pip extra causing FinOps tools to fail with "snowflake-connector-python not installed" (#199) - Engine install trusting stale manifest when venv/Python binary was deleted (#199)
- Extras changes not detected on upgrade — manifest now tracks installed extras (#199)
- Windows path handling for dev/cwd venv resolution (#199)
- Concurrent bridge startup race condition — added
pendingStartmutex (#199) - Unhandled spawn
errorevent crashing host process on invalid Python path (#199) - Bridge hung permanently after ping failure — child process now cleaned up (#199)
restartCountincorrectly incremented on signal kills, prematurely disabling bridge (#199)- TUI prompt corruption from engine bootstrap messages writing to stderr (#180)
- Tracing exporter timeout leaking timers (#191)
- Feedback submission failing when repo labels don't exist (#188)
- Pre-release security and resource cleanup fixes for tracing (#197)
- Data-viz skill for data storytelling and visualizations (#170)
- AI Teammate training system with learn-by-example patterns (#148)
- Sidebar shows "OpenCode" instead of "Altimate Code" after upstream merge (#168)
- Prevent upstream tags from polluting origin (#165)
- Show welcome box on first CLI run, not during postinstall (#163)
- Engine version bumped to 0.4.0
- Database migration crash when upgrading from v0.2.x — backfill NULL migration names for Drizzle beta.16 compatibility (#161)
- Install banner not visible during
npm install— moved output from stdout to stderr (#161) - Verbose changelog dump removed from CLI startup (#161)
altimate upgradedetection broken —method()andlatest()referenced upstreamopencode-aipackage names instead of@altimateai/altimate-code(#161)- Brew formula detection and upgrade referencing
opencodeinstead ofaltimate-code(#161) - Homebrew tap updated to v0.3.0 (was stuck at 0.1.4 due to expired
HOMEBREW_TAP_TOKEN) (#161) .opencode/memory/references in docs updated to.altimate-code/memory/(#161)- Stale
@opencode-ai/pluginreference in CONTRIBUTING.md (#161)
- CI now uses path-based change detection to skip unaffected jobs (saves ~100s on non-TS changes) (#161)
- Release workflow gated on test job passing (#157)
- Upstream merge restricted to published GitHub releases only (#150)
- AI-powered prompt enhancement (#144)
- Altimate Memory — persistent cross-session memory with TTL, namespaces, citations, and audit logging (#136)
- Upstream merge with OpenCode v1.2.26 (#142)
- Sentry review findings from PR #144 (#147)
- OAuth token refresh retry and error handling for idle timeout (#133)
- Welcome banner on first CLI run after install/upgrade (#132)
@altimateai/altimate-codenpm package name restored after upstream rebase- Replace
mock.module()withspyOn()to fix 149 test failures (#153)
- Rebrand user-facing references to Altimate Code (#134)
- Bump
@modelcontextprotocol/sdkdependency (#139) - Engine version bumped to 0.3.0
/feedbackcommand andfeedback_submittool for in-app user feedback (#89)- Datamate manager — dynamic MCP server management (#99)
- Non-interactive mode for
mcp addcommand with input validation mcp removecommand- Upstream merge with OpenCode v1.2.20
- TUI crash after upstream merge (#98)
GitlabAuthPlugintype incompatibility in plugin loader (#92)- All test failures from fork restructure (#91)
- CI/CD workflow paths updated from
altimate-codetoopencode - Fallback to global config when not in a git repo
- PR standards workflow
TEAM_MEMBERSref corrected fromdevtomain(#101)
- Removed self-hosted runners from public repo CI (#110)
- Migrated CI/release to ARC runners (#93, #94)
- Reverted Windows tests to
windows-latest(#95) - Engine version bumped to 0.2.5
- E2E tests for npm install pipeline: postinstall script, bin wrapper, and publish output (#50)
- Postinstall welcome banner and changelog display after upgrade (#48)
- Security: validate well-known auth command type before execution, add confirmation prompt (#45)
- CI/CD: SHA-pin all GitHub Actions, per-job least-privilege permissions (#45)
- MCP: fix copy-paste log messages, log init errors, prefix floating promises (#45)
- Session compaction: clean up compactionAttempts on abort to prevent memory leak (#45)
- Telemetry: retry failed flush events once with buffer-size cap (#45, #46)
- Telemetry: flush events before process exit (#46)
- TUI: resolve worker startup crash from circular dependency (#47)
- CLI: define ALTIMATE_CLI build-time constants for correct version reporting (#41)
- Address 4 issues found in post-v0.2.2 commits (#49)
- Address remaining code review issues from PR #39 (#43)
- CI/CD: optimize pipeline with caching and parallel builds (#42)
- Add security FAQ (#44)
- Telemetry init:
Config.get()failure outside Instance context no longer silently disables telemetry - Telemetry init: called early in CLI middleware and worker thread so MCP/engine/auth events are captured
- Telemetry init: promise deduplication prevents concurrent init race conditions
- Telemetry: pre-init events are now buffered and flushed (previously silently dropped)
- Telemetry: user email is SHA-256 hashed before sending (privacy)
- Telemetry: error message truncation standardized to 500 chars across all event types
- Telemetry:
ALTIMATE_TELEMETRY_DISABLEDenv var now actually checked in init - Telemetry: MCP disconnect reports correct transport type instead of hardcoded
stdio - Telemetry:
agent_outcomenow correctly reports"error"outcome for failed sessions
- Auth telemetry events use session context when available instead of hardcoded
"cli"
- Comprehensive telemetry instrumentation: 25 event types across auth, MCP servers, Python engine, provider errors, permissions, upgrades, context utilization, agent outcomes, workflow sequencing, and environment census
- Telemetry docs page with event table, privacy policy, opt-out instructions, and contributor guide
- AppInsights endpoint added to network firewall documentation
categorizeToolName()helper for tool classification (sql, schema, dbt, finops, warehouse, lineage, file, mcp)bucketCount()helper for privacy-safe count bucketing
- Command loading made resilient to MCP/Skill initialization failures
- CLI binary renamed from
altimate-codetoaltimate
- Context management: auto-compaction with overflow recovery, observation masking, and loop protection
- Context management: data-engineering-aware compaction template preserving warehouse, schema, dbt, and lineage context
- Context management: content-aware token estimation (code, JSON, SQL, text heuristics)
- Context management: observation masking replaces pruned tool outputs with fingerprinted summaries
- Context management: provider overflow detection for Azure OpenAI patterns
- CLI observability: telemetry module with session, generation, tool call, and error tracking
/discovercommand for data stack setup with project_scan tool- User documentation for context management configuration
- ContextOverflowError now triggers automatic compaction instead of a dead-end error
isOverflow()correctly reserves headroom for models with separate input/output limitsNamedError.isInstance()no longer crashes on null input- Text part duration tracking now preserves original start timestamp
- Compaction loop protection: max 3 consecutive attempts per turn, counter resets between turns
- Negative usable context guard for models where headroom exceeds base capacity
- Removed cost estimation and complexity scoring bindings
- Docs: redesigned homepage with hero, feature cards, and pill layouts
- Docs: reorganized sidebar navigation for better discoverability
- Build: resolve @opentui/core parser.worker.js via import.meta.resolve for monorepo hoisting
- Build: output binary as
altimate-codeinstead ofopencode - Publish: update Docker/AUR/Homebrew references from anomalyco/opencode to AltimateAI/altimate-code
- Publish: make Docker/AUR/Homebrew steps non-fatal
- Bin wrapper: look for
@altimateai/altimate-code-*scoped platform packages - Postinstall: resolve
@altimateaiscoped platform packages - Dockerfile: update binary paths and names
- Build: fix solid-plugin import to use bare specifier for monorepo hoisting
- CI: install warehouse extras for Python tests (duckdb, boto3, etc.)
- CI: restrict pytest collection to tests/ directory
- CI: fix all ruff lint errors in Python engine
- CI: fix remaining TypeScript test failures (agent rename, config URLs, Pydantic model)
- Update theme schema URLs and documentation references to altimate-code.dev
- Rename npm scope from
@altimateto@altimateaifor all packages - Wrapper package is now
@altimateai/altimate-code(no-aisuffix)
- CI: test fixture writes config to correct filename (
altimate-code.json) - CI: add
devoptional dependency group to Python engine for pytest/ruff
- Improve TUI logo readability: redesign M, E, T, I letter shapes
- Add two-tone logo color: ALTIMATE in peach, CODE in purple
- Release: npm publish glob now finds scoped package directories
- Release: PyPI publish skips existing versions instead of failing
- Anthropic OAuth plugin ported in-tree
- Docs site switched from Jekyll to Material for MkDocs
- Build script: restore
.trim()on models API JSON to prevent syntax error in generatedmodels-snapshot.ts - Build script: fix archive path for scoped package names in release tarball/zip creation
- Initial open-source release
- SQL analysis and formatting via Python engine
- Column-level lineage tracking
- dbt integration (profiles, lineage,
+operator) - Warehouse connectivity (Snowflake, BigQuery, Databricks, Postgres, DuckDB, MySQL)
- AI-powered SQL code review
- TUI interface with Solid.js
- MCP (Model Context Protocol) server support
- Auto-bootstrapping Python engine via uv