feat: [v1.17.9] bridge merge upstream OpenCode v1.4.0 → v1.17.9#964
feat: [v1.17.9] bridge merge upstream OpenCode v1.4.0 → v1.17.9#964anandgupta42 wants to merge 149 commits into
Conversation
…on (checkpoint) Bridge overlay of upstream OpenCode v1.4.0 -> v1.17.9 (3254 commits, no common ancestor). This is a WIP checkpoint on the merge branch; NOT ready to merge. Done: - Overlaid 1850 upstream files via bridge-merge.ts; reapplied PR #18186 anthropic. - Restored altimate bits in packages/opencode/package.json (name, bin altimate/ altimate-code, deps @altimateai/altimate-core, @altimateai/drivers, @opencode-ai/util, yaml; test script without --only-failures). - Pruned root workspaces (drop console/slack/stats), fixed repository URL. - Dropped packages/stats (hosted dashboard) + added to skipFiles. - Vendored 5 TUI attention mp3s into packages/tui; repointed @opencode-ai/ui audio. - Deleted 246 confirmed-stale upstream files (present in v1.4.0, removed by v1.17.9, unmarked) via in-v1.4.0 discriminator; kept 174 fork-origin files. - bun install GREEN; packages/core + packages/tui typecheck GREEN. Remaining (tracked): re-derive ~72 kept marker/requireMarkers files onto v1.17.9 + re-apply altimate_change blocks; migrate server/tui/util-extracted customizations; effect beta.43->beta.74 API drift; update fork test suite to v1.17.9 APIs; apply branding transforms to overlaid files; re-evaluate 62 upstream_fix markers.
…ook (checkpoint 2) - Add fork-local Log shim at altimate/util/log.ts (upstream removed util/log.ts in the Effect-logging migration); repoint 16 altimate/memory imports to it. - Repoint Flag -> @opencode-ai/core/flag/flag, Global -> @opencode-ai/core/global. - Persist deep impact analysis: .github/meta/merge-v1179/PLAYBOOK.md (10-phase reconciliation runbook) + migrate/fix verdict JSON. Also copied to obsidian. Remaining per PLAYBOOK (the heavy systemic rewrites): Effect-API call-site migration (Config/Provider/LLM/MCP Promise wrappers removed), Tool API rewrite across 77 altimate/memory tools (zod->Effect Schema, execute->Effect), re-home 34 marker files into packages/tui + packages/server, apply 7 KEEP + 13 KEEP-BRANDING upstream_fixes, DROP 2, delete ~150 stale files, then typecheck/test green.
…ema re-apply (checkpoint 3) Resolves the §2 Effect-only API migration for the altimate consumer surface by restoring thin Promise wrappers (backed by the instance-bound `makeRuntime` bridge, so reads stay per-workspace) instead of churning 100+ call sites: - `Config`: restore get/getGlobal/getConsoleState/update/invalidate/directories Promise wrappers (40+ `await Config.get()` callers, upstream-shared + altimate). - `MCP`: restore status/tools/add/connect/disconnect wrappers; repoint datamate's `MCP.remove` -> `MCP.disconnect` (session-runtime removal; config purge is separate). - `Skill`: restore `all()` wrapper for project-scan's environment census. Mechanical §2 repoints (all fork-original altimate files): - `Installation.VERSION` -> `InstallationVersion` (@opencode-ai/core/installation/version). - glob -> `@opencode-ai/core/util/glob`; post-filter ignore dirs (core Glob.Options dropped the `ignore` field). - `Config.Mcp` -> `ConfigMCPV1.Info` (@opencode-ai/core/v1/config/mcp). - project-scan: removed Flag experimental keys -> direct process.env census reads. Config-schema fidelity (core v1/config/config.ts, re-applied from main): - top-level `tracing` block (enabled/dir/maxFiles/exporters), zod -> Effect Schema. - experimental toggles dropped by the overlay: auto_enhance_prompt, env_fingerprint_skill_selection, auto_mcp_discovery. Also lands the prior-session Tool-API adapter shim (altimate/tool-zod-compat.ts) referenced by tool/tool.ts — the recipe to bridge the 77 old-shape zod/Promise tools onto the new Effect Tool API without rewriting each. altimate/ typecheck surface: 37 -> 3 errors (the 3 remaining are the §2.12 Tool-API rewrites in altimate-core-rewrite.ts + tool-lookup.ts). Package total 3181 -> 3040; the remainder is the stale-file delete (§3.4) + TUI/server re-home (§4) phases. Marker guard --strict still fails on pre-existing broad-overlay debt (125 unmarked sites across sdk/turbo/etc untouched here); my additions are balanced and marked.
…point 4) Closes the last 3 typecheck errors in the fork's own src/altimate/** tree via the tool-zod-compat adapter (§2.12): - altimate-core-rewrite.ts: annotate execute return as the shim's `LegacyResult` so the legacy `Tool.define` overload's metadata type (M) infers cleanly. This tool's execute omits the `ctx` param, so M was being inferred from a complex multi-branch return union and failing overload resolution. `args` still types from `parameters`. - tool-lookup.ts: upstream's Tool rewrite made `info.init()` an Effect (was a Promise) and `parameters` an Effect Schema (was zod). Run the init Effect via `Effect.runPromise` and describe parameters from `Def.jsonSchema` (JSON Schema, populated for both native tools and our legacy zod tools) instead of the removed zod introspection. New `describeJsonSchema`/`inferJsonType` replace the zod walkers. src/altimate/** now typechecks with 0 errors (was 37 at the start of this resume). Package total 3040 -> 3037; the remainder is upstream-shared restructure: stale-file deletion (§3.4) + TUI/server re-home (§4) + Effect migration of survivor files.
…ages/tui (checkpoint 5) The TUI was extracted upstream to packages/tui (live) from cli/cmd/tui/** (dead — no @tui alias resolves it). Re-apply the fork customizations into the live package, preserving altimate_change markers. packages/tui + packages/core both typecheck GREEN. Re-homed (functional + branding): - context/sdk.tsx — smooth-streaming delta pre-merge (ALTIMATE_SMOOTH_STREAMING). Adapted to v2 GlobalEvent (discriminant nested under `.payload`, not top-level). - routes/session/footer.tsx — YOLO-mode badge (ALTIMATE_CLI_YOLO). - routes/session/sidebar.tsx — "Altimate Code" branding (uses InstallationVersion). - component/logo.tsx — restore brand colors (primary/accent vs textMuted/text) in the rewritten 8-arg renderLine call-site. - component/dialog-status.tsx — `altimate mcp auth` branding fix. - component/error-component.tsx — `altimate-code: fatal:` title + AltimateAI/altimate-code issue URL (was anomalyco/opencode brand leak). - context/route.tsx — restore dropped navigate debug log (console.debug; tui has no structured logger). Flag re-home (packages/core/src/flag/flag.ts): added ALTIMATE_CALM_MODE, ALTIMATE_SMOOTH_STREAMING, ALTIMATE_CLI_YOLO getters + altTruthy helper, since packages/tui depends on @opencode-ai/core (not opencode) and could not otherwise see the fork flags. MOOT (not re-applied — upstream issue gone): dialog-mcp / dialog-workspace-list logger fixes (tui uses console.* throughout, has no structured logger, the old console.log/debug prints don't exist in the rewritten files). DEFERRED (tracked, code re-architected into other owner files — next pass): - theme #704 light-fg + code-block/inline-code bg → packages/tui/src/theme/index.ts (generateSystem/getSyntaxRules). One human decision: inline-code backgroundElement vs upstream's new background. - beginner/first-time tips + onboarding hint → feature-plugins/home/{tips,tips-view}.tsx (home is now a plugin-slot shell). - UpgradeIndicator: component + utils exist only in the old tree, not ported → blocks the footer + home upgrade-indicator blocks until ported into packages/tui/src/component. - sidebar trace section → sidebar_content plugin slot. OLD cli/cmd/tui/** files untouched (deleted later in §3.4 after all re-homing verified).
… flags (checkpoint 6) Second re-homing wave into packages/tui (live TUI). packages/tui + packages/core both typecheck GREEN. Re-homed (functional): - context/sync.tsx — full streaming feature set: yolo auto-approve (adapted to the new permission.reply API: workspace arg + reply:"once"), smooth-streaming direct-path delta update, and the complete line-streaming buffer feature (lineBuffer + flushLineBuffer + flushAllBuffersForMessage + the 5 event-handler hooks). event.type/.properties is correct here (useEvent unwraps GlobalEvent.payload, unlike sdk.tsx). - routes/session/index.tsx — `builder` agent name on plan_exit, smooth-streaming scroll (toBottom 0ms), calm-mode content width cap (maxWidth via ALTIMATE_CONTENT_MAX_WIDTH). - theme/index.ts — light-mode fg fallback (#704), code-block + inline-code backgrounds for light-theme contrast. NOTE: inline-code uses theme.backgroundElement vs upstream's new theme.background — flagged inline for the next merge's human review. - feature-plugins/home/tips-view.tsx — fork DE-specific tips (/discover, /cost-report, /dbt-docs, /sql-review, /migrate-sql, lineage, anti-patterns) folded into the new Tip pool. Flags re-homed into packages/core/src/flag/flag.ts (tui depends on core, not opencode): ALTIMATE_LINE_STREAMING, ALTIMATE_CONTENT_MAX_WIDTH (+ numberEnv helper), joining the ALTIMATE_CALM_MODE/SMOOTH_STREAMING/CLI_YOLO added in checkpoint 5. MOOT (upstream v1.17.9 shipped equivalents — dropped per upstream_fix rule): - prompt skills-dialog keybind → upstream `prompt_skills` keybind. - session workspace-gate, smooth-streaming memoize, light-theme md fg (upstream ships fg=markdownText + bg=background). DEFERRED — architectural (tracked): enhance feature (enhance-prompt.ts), dialog-provider (AltimateApi), dialog-skill (skill-helpers + keymap port). All three depend on opencode-package code unreachable from packages/tui — need the shared code moved into @opencode-ai/core, routed via SDK/server, or implemented as tui plugins. Real features; not dropped. DEFERRED — render-rewritten: session/index TextPart code-during-streaming, tips first-time-only behavior, sidebar trace section (sidebar_content slot), footer/home UpgradeIndicator (component not yet ported into packages/tui). OLD cli/cmd/tui/** files untouched (deleted in §3.4 after all re-homing verified).
…ckpoint 7) app.tsx re-home into packages/tui/src/app.tsx + UpgradeIndicator component port. packages/tui + packages/core both typecheck GREEN. app.tsx (5 applied): - terminal-detection: created fork-original packages/tui/src/terminal-detection.ts (detectModeFromCOLORFGBG, #704) + eager COLORFGBG light-mode short-circuit in the theme-detection path (avoids the 1s waitForThemeMode delay). - branding: docs URL opencode.ai/docs -> docs.altimate.sh; DialogAlert update message "OpenCode v…" -> "Altimate Code v…". app.tsx MOOT (2): variant_list keybind (upstream v1.17.9 shipped PR #21185 natively); disableStdoutInterception (opentui API removed; renderer externalOutputMode handles it). app.tsx DEFERRED (7): trace-viewer feature — depends on opencode-side altimate/observability (Trace/renderTraceViewer/DialogTraceList), unreachable from packages/tui. Same architectural blocker as the dialogs/enhance (task: expose opencode deps to tui). UpgradeIndicator port (fork-original, was deferred — now unblocked since it only needed Installation.VERSION = InstallationVersion in core): - packages/tui/src/component/upgrade-indicator{,-utils}.tsx — repointed imports to the tui layout, Installation.VERSION -> InstallationVersion. Added semver + @types/semver to packages/tui (were opencode-only deps). - routes/session/footer.tsx — wired <UpgradeIndicator /> back into the session footer. (home-screen UpgradeIndicator still deferred — lives in the new feature-plugins/home/footer plugin, a different surface.) OLD cli/cmd/tui/** files untouched (deleted in §3.4 after remaining re-homing/decisions).
…(checkpoint 8) The old TUI tree packages/opencode/src/cli/cmd/tui/** (31 files) is dead: the live TUI is packages/tui (@opencode-ai/tui), launched via cli/cmd/tui.ts; opencode has no @tui path alias so the old tree never resolved. All its fork customizations were re-homed into packages/tui (checkpoints 5-7) or documented as architecturally-deferred; the originals remain on main + git history for reference. - Repoint the one live cross-import: server/routes/session.ts formatTranscript now imports from @opencode-ai/tui/util/transcript (the util moved to packages/tui). Added the ./util/transcript entry to packages/tui's exports map. - git rm -r packages/opencode/src/cli/cmd/tui (31 files). opencode typecheck: 3037 -> 2582 errors (-455, the dead TUI tree). CORRECTION to the earlier deletion plan: server/server.ts is NOT stale — cli/cmd/serve.ts loads it as the live server (it is the Hono server; upstream's httpapi tree is unused here). So the server cluster (~282 errors) is SURVIVOR reconciliation (restore the hono dep, repoint moved imports util/log/bus/error/permission-schema), not deletion. Next cluster.
hono + hono-openapi were dropped from packages/opencode/package.json during the overlay (present on main as catalog: refs, still in the workspace catalog). The live Hono server (server/server.ts, loaded by cli/cmd/serve.ts) and its routes need them. Re-added both as catalog: deps. opencode typecheck: 2582 -> 2486 (-96; 27 direct hono module errors + cascades resolved). Remaining are per-file survivor reconciliation: moved-module repoints (util/log, @/bus, ../error → core/shims) and Effect-API migration in survivor files (provider/server/session), plus the test suite. No more dropped-dep batch wins (only bun-pty left, 2 errors in a stale pty file that moved to core).
…ckpoint 10) Restore re-export shims at the old util/* paths upstream deleted when those utils moved to @opencode-ai/core, so survivor + test importers resolve without per-file repoints (the established §2.13 shim pattern, same as error/token/locale): - src/util/log.ts -> @/altimate/util/log (fork Log successor) - src/util/glob.ts -> @opencode-ai/core/util/glob (Glob) - src/util/flock.ts -> @opencode-ai/core/util/flock (Flock) opencode typecheck: 2582 -> 2431 across checkpoints 8-10 (TUI delete -455, hono dep -96, util/log shim -39, glob/flock shims -16). Remaining ~2431 = heavy per-file survivor reconciliation (no more batch wins): @/bus API change (BusEvent->EventV2), server route modules, provider/session Effect-API migration, and the test suite (~1446) which tracks src once src is green.
…scaffold (checkpoint 11) Architectural decision for the v1.17.9 TUI extraction: fork TUI features that depend on opencode-package code (AltimateApi, enhance-prompt, observability) are implemented as host-registered TuiPlugins living in opencode-side fork-owned files — NOT as edits inside upstream packages/tui. This keeps upstream packages/tui byte-for-byte upstream (clean future merges) while the plugins retain their opencode deps and render via TuiPluginApi (slots/command/keymap/dialog/client). Full rationale + per-feature re-home plan: docs/internal/2026-06-23-tui-fork-features-as-plugins-adr.md. - New: packages/opencode/src/plugin/tui/altimate/index.ts — altimateTuiPlugins() aggregator. - Wire: plugin/tui/internal.ts appends altimateTuiPlugins(...) to the builtin plugin list (the host already composes the TUI plugin set, so this is the natural injection point). Compiles clean (opencode typecheck unchanged at 2431). The 4 deferred features (provider-credentials, skill-ops, prompt-enhance, trace-viewer) are ported into this directory next, per the ADR; their pre-merge sources are preserved on main.
…checkpoint 12)
Per the ADR (docs/internal/2026-06-23-tui-fork-features-as-plugins-adr.md), the fork TUI
features that depend on opencode-package code are now plugins in
packages/opencode/src/plugin/tui/altimate/, registered via altimateTuiPlugins() into the host
plugin list. Upstream packages/tui stays untouched. opencode typecheck unchanged at 2431 (all
4 plugins compile clean).
- provider-credentials.tsx — palette cmd "Connect altimate-backend" → credential DialogPrompt
backed by AltimateApi.{parseAltimateKey,validateCredentials,saveCredentials}.
- skill-ops.tsx — "/skills" list (api.client.app.skills + detectToolReferences categorization),
create/install/test/show/edit/remove ops, ctrl+a/n/i → registered commands.
- trace-viewer.tsx — "/trace" command + trace-list dialog + open-in-browser, with the
Bun.serve trace viewer server kept opencode-side (renderTraceViewer/Trace.* from
altimate/observability). This is exactly why it belongs in an opencode-side plugin.
- prompt-enhance.tsx — "enhance prompt" command + enhancePrompt logic ready; the prompt
read/write is gated on a small plugin-API extension (api.prompt.active(): TuiPromptRef) that
TuiPluginApi doesn't yet expose — tracked as the next step to fully restore it.
Each file is fork-owned and fully wrapped in altimate_change markers. Documented per-plugin
deferrals (all needing a typed SDK/api addition, none a feature drop): skill cache-reload flag,
per-dialog keybind scoping, provider in-list trigger, prompt active-ref accessor.
…extension (checkpoint 13)
Completes the prompt-enhance fork feature. The plugin api had no accessor for the active prompt
input, so the enhance read/write was deferred (ckpt 12). Added the sanctioned plugin-contract
extension (the designed extension point — not inline edits scattered through upstream render code):
- packages/plugin/src/tui.ts — add `prompt: { active(): TuiPromptRef | undefined }` to TuiPluginApi.
- packages/tui/src/plugin/adapters.tsx — implement it from the host's usePromptRef context
(PromptRef is structurally TuiPromptRef); thread promptRef through the adapter Input.
- packages/tui/src/app.tsx — pass the already-available promptRef into createTuiApiAdapters.
- packages/opencode/src/plugin/tui/runtime.ts — pass api.prompt through the scoped legacy host api.
- packages/opencode/test/fixture/tui-plugin.ts — add prompt.active() to the test api mock.
- altimate/prompt-enhance.tsx — the "Enhance prompt" command now reads api.prompt.active().current.input,
awaits enhancePrompt(), and writes back via ref.set(). Auto-enhance-before-submit stays deferred
(needs a pre-submit hook; isAutoEnhanceEnabled kept ready).
All four fork TUI plugins are now functional. packages/tui + packages/core + packages/plugin green;
opencode unchanged at 2431. All additions altimate_change-marked.
…oint 14) Re-export shims for util modules upstream moved into @opencode-ai/core: - src/util/hash.ts -> @opencode-ai/core/util/hash - src/util/which.ts -> @opencode-ai/core/util/which - src/file/ripgrep.ts -> @opencode-ai/core/ripgrep opencode 2431 -> 2428. Cheap module-shim wins are now exhausted: remaining importers fail on deeper Effect-API breaks too, so shimming one import no longer makes a file green. The rest of task #7 (provider.ts 106, session/prompt 73, session/index 72, server/* — Auth/Env makeRuntime compat wrappers + @/bus EventV2 migration + dep drift LanguageModelV2->V3) is per-file survivor reconciliation. util/fn, util/context, util/abort, util/lock, shell/shell still need locating (moved out of the dropped @opencode-ai/util package, not yet found in core).
…kpoint 15) Same proven makeRuntime compat-wrapper pattern as Config/MCP/Skill (ckpt 3): upstream removed the imperative Promise wrappers on Auth and Env in the Effect-only migration, but survivor files (provider/provider.ts, session/llm.ts, server/server.ts + provider tests) still call `await Auth.get()` / `Env.set()` etc. Both Services retain get/all/set/remove as Effect methods with self-contained defaultLayers, so the wrappers are a clean restore (instance-bound runtime keeps reads/writes scoped): - src/auth/index.ts — restore get/all/set/remove Promise wrappers. - src/env/index.ts — restore get/all/set/remove Promise wrappers. opencode 2428 -> 2298 (-130). Both modules typecheck clean. Confirms compat wrappers are the high-leverage lever for the remaining survivor Effect-API breaks (next: Provider.defaultModel/ getModel/getSmallModel, LLM.stream).
Env is backed by process.env (no async IO) and fork callers read it synchronously (provider/provider.ts: `const env = Env.all(); env[key]`, and `Env.get()` assigned to string). The previous async Promise wrappers (ckpt 15) produced Promise-vs-value type errors. Switch the Env wrappers to makeRuntime runSync, returning plain values — matching the pre-merge sync Env API. (Auth stays async: it does file IO.) opencode 2298 -> 2284. Env module clean.
…eckpoint 17) Upstream moved the version constant to InstallationVersion (@opencode-ai/core/installation/version). Add `export const VERSION = InstallationVersion` to src/installation/index.ts so the many survivor callers of Installation.VERSION resolve without per-file repoints (single-line shim; the module already imports InstallationVersion). opencode 2284 -> 2240 (-44). Session-resume cumulative: 3181 -> 2240 (-941).
…code-ai/util imports (ckpt 18)
The @opencode-ai/util package was removed in the extraction; survivor files still imported from it.
- Restore src/util/fn.ts (the zod fn() helper, from main) — it has no @opencode-ai/core home.
- Repoint across 14 survivor files: @opencode-ai/util/{error,slug,lazy} -> @opencode-ai/core/util/*;
@opencode-ai/util/fn -> @/util/fn.
opencode 2240 -> 2226.
…ll shim (ckpt 19)
- Restore src/util/{context,abort,lock}.ts from main (self-contained fork utils with no
@opencode-ai/core home — context uses AsyncLocalStorage, abort/lock have no imports).
- src/shell/shell.ts re-export shim: `export * as Shell from "@opencode-ai/core/shell"` (core
ships flat exports; fork callers import the Shell namespace).
opencode 2226 -> 2216. Remaining module-not-found is mostly @/bus (a real BusEvent->EventV2
migration, not a shim) + per-file survivor work.
…ckpoint 20) The fork keeps the Bus pattern (bus-event.ts BusEvent.define + bus/global.ts GlobalBus both survive, and ~14 files + 60+ call sites use the Bus namespace), but bus/index.ts was dropped in the overlay. Restored it from main and fixed the one Effect-version drift: ServiceMap.Service -> Context.Service (ServiceMap was removed from effect; matches the env/config Service pattern). opencode 2216 -> 2197. bus/index.ts typechecks clean; resolves the @/bus import + Bus.publish/ subscribe call sites across server/session/provider.
…fix (checkpoint 21) - src/util/schema.ts re-export shim: `export * from "@opencode-ai/core/schema"` (withStatics et al moved to core). - src/provider/schema.ts: new Effect Schema brand constructor is `.make()` not `.makeUnsafe()`. Fixed the 15 ProviderID/ModelID brand constructions. The fork keeps its branded ProviderID/ModelID (callers use ProviderID.make()/.opencode etc.) — only the internal Schema API updated. opencode 2197 -> 2109 (-88; the brand fix cascades across all provider/model-ID usages in provider.ts, session/prompt.ts, share-next.ts, tool/batch.ts). Session-resume: 3181 -> 2109.
…shims (checkpoint 22) Re-export shims for modules moved to @opencode-ai/core: - src/permission/schema.ts -> core/permission/schema - src/project/schema.ts -> core/project/schema - src/filesystem.ts -> core/filesystem - src/npm/index.ts -> core/npm opencode 2109 -> 2108 (low net — resolving these imports exposes the importing files' deeper type errors). Module-not-found shims now largely exhausted; remaining ~2108 is per-file type work (TS2339 Service/branded, TS2345/2322 type mismatches, Effect call sites) + ~1240 tests.
Delete 7 test files that import the deleted cli/cmd/tui tree (upgrade-indicator, theme light-mode #704, worker, thread). The features they covered were re-homed into packages/tui / the fork plugins; these tests are unrunnable here. Recoverable from main; test coverage should be re-homed to packages/tui in a follow-up. opencode 2108 -> 2093 (src 788 / test 1302). Remaining is deep per-file Effect-API migration in the session/provider/server survivors + the test suite tracking those API changes.
… core (checkpoint 24)
session/project Drizzle table definitions moved to @opencode-ai/core/{session,project}/sql; some
survivor files still imported the old ./session.sql / ./project.sql paths (which now resolve to
the raw `*.sql` ambient module, hence the "no exported member MessageTable" errors). Repointed
message-v2.ts, session/projectors.ts, server/projectors.ts, project/project.ts to the core paths.
opencode 2093 -> 2091. Cross-cutting wins now exhausted; remaining is deep per-file Effect/Schema/
Drizzle migration in the session/provider/server survivors + their tests.
…(checkpoint 25)
Four highest-error survivor files driven to 0 (3 via parallel subagents + provider by hand);
src 788 -> 653, total 2091 -> 1977.
- provider/provider.ts (106->0 cumulative): LanguageModelV2->V3 alias, ./sdk/copilot ->
@opencode-ai/core/github-copilot/copilot-provider, @gitlab/gitlab-ai-provider ->
gitlab-ai-provider (upstream rename, dep already present), NamedError.create zod->Effect Schema
fields (+ import Schema), interleaved.field enum += "reasoning".
- session/message-v2.ts (28->0): zod NamedError kept via @opencode-ai/util/error; local zod brand
schemas for SessionID/MessageID/PartID (.zod dropped on core brands); inline LSP.Range/FileDiff
zod mirrors; convertToModelMessages now async (Effect.promise).
- session/index.ts (43->0): restored fork ProjectID (src/project/schema.ts) + re-added fork ID
statics .zod/.make/.ascending (src/session/schema.ts) — unblocks ~10 consumer files; re-brand at
the core-drizzle Project.ID<->ProjectID boundary; Storage.read via AppRuntime+Service.
- server/server.ts (20->0): restored dropped flat Hono routes + lsp/index.ts + server/error.ts +
control-plane/schema.ts + util/effect-zod.ts from main; Promise wrappers on Vcs/Command/Agent/
Format; WorkspaceID re-based on core WorkspaceV2.ID; zod() AST-walker at HTTP schema call sites.
NOTE: the restored flat route files (routes/{mcp,question,experimental,...}.ts) carry their own
internal API errors (why the overlay dropped them) — server.ts imports now resolve; their internals
are follow-up. All fork additions altimate_change-marked.
…eckpoint 26)
session/prompt, cli/cmd/run + run/tool, account/index, project/project, acp/service + directory,
tool/registry, session/session, session/processor — all driven to 0. Total 1977 -> 1757
(src 653 -> 451). Session-resume cumulative: 3181 -> 1757.
Patterns applied (all marker-wrapped): Promise-wrapper restores on more Service modules
(Agent.get/defaultAgent, SessionRevert.cleanup, SessionStatus.set/get, SessionSummary.summarize,
Command.get, MCP.readResource, Config.waitForDependencies, Snapshot.track/patch, Instruction
facade); EventV2 publish/subscribe via Bus shim / EventV2Bridge; Effect Tool-API exec loop
(AppRuntime.runPromise of init()/execute, ToolJsonSchema.fromTool, legacyToInit fromPlugin bridge);
ProviderV2/ModelV2/Project.ID <-> fork brand re-mapping with .make() at core-drizzle boundaries;
restored dropped fork tools tool/{ls,codesearch}.ts from main.
KNOWN STRUCTURAL FOLLOW-UP (surfaced by 4 agents): Provider / Plugin / Project / ToolRegistry are
fork namespace/Promise modules, but consumers (agent/agent.ts, project/instance-store, app-runtime,
session/tools) expect Effect Services (.Service/.defaultLayer/.node). Decide: migrate those modules
to Services vs adapt consumers. This is the next major cluster (agent.ts ~10 errs gated on it).
…heckpoint 27)
6-agent batch: server/routes/{session,mcp,experimental,question} + tool/batch + mcp/discover +
skill/discovery + plugin/openai/ws all -> 0. Total 1757 -> 1602 (src 451 -> 358). Session-resume
cumulative: 3181 -> 1602.
Patterns: zod() AST-walker (util/effect-zod) at resolver()/validator() sites for Effect-Schema
Info types; many more Promise wrappers (MCP.{resources,supportsOAuth,startAuth,finishAuth,
authenticate,removeAuth}, Worktree.{create,list,remove,reset}, Question.{list,reply,reject},
SessionStatus.list, Todo.get, SessionSummary.diff, SessionRevert.{revert,unrevert}); restored
fork PermissionID brand + ResponseStreamError/HeaderTimeoutError (provider/error.ts) + ConfigPaths
env-substitution helpers; Tool-API legacy form for BatchTool; ConfigMCPV1.Info; Project.ID brand
boundaries.
REMAINING (~358 src) is now dominated by task #9: ~10 core modules (Provider, Plugin, Project,
SessionPrompt, SessionCompaction, ShareNext, Worktree, ToolRegistry, LLM, SessionProcessor,
InstanceBootstrap) are fork namespaces but the new upstream consumers (app-runtime AppLayer,
httpapi handlers, control-plane, share/session, provider/auth, agent.ts) need them as Effect
Context.Services. That migration is the critical path for the bulk of the rest.
…ionPrompt/SessionCompaction (ckpt 28) Task #9 (the AppLayer/Service cluster) — facade approach validated via 4 parallel agents. Each adds an Effect Context.Service (+ layer/defaultLayer/node) that DELEGATES to the existing namespace functions (Effect.promise/Effect.sync wrap), so the new upstream consumers (app-runtime AppLayer, httpapi handlers, control-plane, share/session, github.handler, instance-store) compile while behavior is preserved and all existing namespace exports + Promise wrappers stay intact. Project recovered its exact Interface + Project.NotFoundError tagged error + UpdateInput/UpdatePayload from upstream git history (commit 3e1972fd92). opencode 1602 -> 1503 (src 358 -> 305). app-runtime now needs only Plugin/Provider/SessionProcessor/ LLM/ToolRegistry (next wave). Facade modules themselves clean (residual share-next *.sql + compaction brand are pre-existing, separate). All additions altimate_change-marked.
…olRegistry/SessionProcessor (ckpt 29) Completes the task #9 Service-facade migration (2nd wave, 5 parallel agents). Each adds an Effect Context.Service (+ layer/defaultLayer/node) delegating to the existing namespace functions, preserving all fork logic (Provider keeps altimate-backend/gitlab/snowflake/databricks loaders intact) and the Promise wrappers. Interfaces recovered from upstream git history (9581bf0670, 2638e2acfa, 3e1972fd92). LLM facade adapted to Effect 4.0 beta.74 Stream API + the fork's LLMEvent adapter. Result: src/effect/app-runtime.ts 10 -> 1 error (only Discovery.node left), agent/agent.ts 10 -> 2. opencode 1503 -> 1477 (src 305 -> 248). Session-resume cumulative: 3181 -> 1477. Long tail remaining: Discovery facade (app-runtime:108), agent.ts brand/2, a few pre-existing in-file errors (plugin state loop, provider NoModelsError/toPublicInfo/defaultModelIDs additions), missing runtime assets (event.sql, max-steps.txt), then ~1226 tests.
…checkpoint 30) 7-parallel-agent batch over ~40 files cleared the post-Service-cluster long tail. Total 1477->1277, src 248 -> 52. Session-resume cumulative: opencode 3181 -> 1277 (src now ~52). No duplicate-export conflicts from the concurrent shared-file work. Highlights: - Restored dropped fork files from main: server/routes/event.ts, server/middleware.ts, sync/event.sql.ts, session/prompt/max-steps.txt (runtime assets), permission/permission.sql.ts, Ripgrep async-generator namespace (file/ripgrep.ts). - Effect Tool-API: extended tool-zod-compat for the deferred-factory Tool.define form (skill/task/ bash tools); assertExternalDirectoryLegacy for ls/glob. - bootstrap.ts rewritten to the Effect-Service form (InstanceBootstrap.defaultLayer/.node) — cleared ripples in instance-store/layer, app-runtime, worktree, control-plane/workspace. - More Promise wrappers (Vcs.diff/defaultBranch, Question.ask, Skill.get/available, Config.updateGlobal, provider/auth methods/authorize/callback); Provider additions NoModelsError/toPublicInfo/ defaultModelIDs/ListResult; Project.InfoSchema; pty -> @opencode-ai/core/pty + PtyID shim. - zod() AST-walker across remaining Hono routes; ProviderV2/ModelV2<->fork brand re-maps; lsp/index rewritten to the new context-aware LSPServer/LSPClient API; ServiceMap->Context in auth services. - Deleted stale duplicate config/migrate-tui-config.ts. Remaining ~52 src across ~20 files (<=5 each) + ~1222 tests.
…e dir) The 37 MCP test "failures" seen off-CI were not a merge regression — the rewritten client is correct. `discoverExternalMcp` (and `MCP.defaultLayer` auto-discovery) read the home-scoped global config (`~/.claude.json`, VS Code / Cursor / Copilot configs). The discover/lifecycle tests never isolated the home dir, so on any dev machine with a populated `~/.claude.json` the real MCP servers leaked into hermetic "returns empty" / mock-server-count assertions. CI stayed green only because its HOME is clean. Fix: spy `os.homedir()` onto a fresh empty temp dir per test (bun's `os.homedir()` caches `$HOME` at process start, so `process.env.HOME` can't be overridden at runtime — matches the existing `spyOn(os, "homedir")` pattern in the editor-context tests). Full `test/mcp/` now 196 pass / 0 fail with a populated real HOME (was 159/37). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The v1.17.9 merge rewrote `defaultModelFromConfig` in `acp/service.ts` and dropped the fork's model-selection preference: when the user has `altimate-backend` configured but hasn't pinned a model, ACP sessions (Zed and other editor clients) should default to `altimate-backend/altimate-default`. The rewritten version fell straight through to the `opencode` provider, routing ACP clients away from altimate's own backend. main carried this in `acp/agent.ts`'s `defaultModel()` (marked `capture provider filter` + `default to altimate-backend when configured and no model chosen yet`); the ACP split into per-file modules preserved the yolo + auth-branding customizations but lost this one. - Restore the altimate-backend preference between the configured-model check and the opencode fallback, honoring an explicit `provider` allowlist (skip only if the user configured `provider` and left altimate-backend out) — faithful to main's logic. - Thread the user config's `provider` filter through from the caller. - Export the (previously private) pure helper and add `test/acp/default-model.test.ts` (5 cases: preference, opencode fallback, allowlist include/exclude, configured wins). Found via a marker-count differential (main vs HEAD) over fork-customized files. Full `test/acp/` 124 pass / 0 fail. Typecheck + marker guard clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 89eaf01882
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…startup crash The two DB layers over one sqlite file (packages/core migrations + packages/opencode `storage/db.ts`) can collide on mixed old/new-binary databases. The legacy storage layer adds columns via a guarded `addColumn` (e.g. `project.icon_url_override`) WITHOUT recording the corresponding core migration in the core `migration` journal. When the schema is not fully current (`currentSchemaApplied` returns false), `applyOnly` then re-runs the core migration's unguarded `ALTER TABLE project ADD icon_url_override` → SQLite throws `duplicate column name: icon_url_override` → startup crashes. Reproduced live: `bun run src ... run` against a real legacy `opencode-local.db` failed with the duplicate-column error before app start; fresh installs and the shipped binary's own (fully-current) db are unaffected. Same class as the already-fixed `session ADD metadata` collision that `adoptCoreOwnedDatabase` handles — this closes the additive-column gap. Fix (`applyOnly` per-migration loop): SQLite has no `ADD COLUMN IF NOT EXISTS`, so when a migration fails with a "schema object already exists" error (`duplicate column name` / `already exists`), treat it as already-applied — record the id and continue. Robust to both Effect failures and defects (`Effect.exit` + `Cause.pretty`); any other error re-raises faithfully via `Effect.failCause`, so real migration breakage still crashes loudly. Tests (`database-migration.test.ts`): adopt-when-column-exists (red before the fix: `SQLiteError: duplicate column name: icon_url_override`) + a negative test proving a genuine migration error still throws. Full migration suite 21 pass / 0 fail. Core typecheck + marker guard clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`share-next.fullSync` synced an empty `session_diff` to the shared web view. The facade
`Session.diff` (session/index.ts) reads the persisted `["session_diff", sessionID]` storage
key, which main's `summarize` wrote after each turn but the v1.17.9 merge's summarize no
longer does — so shared sessions showed no file changes.
Route `fullSync` to `SessionSummary.diff({ sessionID })`, which computes the full-session
diff on read (restored in b5715e7), instead of the facade that reads the now-unwritten
key. Avoids touching the after-every-turn `summarize` hot path.
Found via a codex adversarial subsystem audit; verified against `main` and the live wiring
(`ShareNext` node registered, `session share` command + routes active). share + session
suites: 728 pass / 0 fail. Typecheck + marker guard clean.
Note: aggregate session summary counts (additions/deletions/files) remain 0 after turns —
cosmetic/internal only (the TUI renders file lists via SessionSummary.diff, not the aggregate
count), left as a follow-up to avoid hot-path risk.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`substitute()` in config/paths.ts still computed the env-substitution stats
(dollar_refs/unresolved/defaulted/escaped, legacy_brace_*) but the v1.17.9 merge dropped the
`Telemetry.track({ type: "config_env_interpolation" })` emit — the stats were computed and
discarded, and the only remaining reference to the event was its telemetry schema definition.
Restore the single emit site (dynamic import to avoid the circular dep with @/altimate/telemetry),
matching main. Observability-only — config interpolation itself was unaffected.
Found via codex adversarial audit (pass 2: tool/cli/config/snapshot/flag/util — no other drops).
config + telemetry suites green. Typecheck + marker guard clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…a proxy) The workspace HttpApi group is declared at `/experimental/workspace` (the v2 SDK generates `experimental.workspace.list/status/adapter/create/warp` against that exact path — no `/api` prefix, unlike every other endpoint). But `Server.createApp` only bridged `/api/*` to the HttpApi, so workspace requests fell through to the legacy Hono catch-all, which proxies unknown paths to app.altimate.ai → HTTP 500. The legacy `WorkspaceRoutes` that used to serve this path was removed during the merge, and the gating comment in experimental.ts referenced a `control-plane/workspace.ts` typecheck blocker that is now stale (monorepo typecheck is green; the HttpApi actively uses that service). Net effect: the TUI's workspace list/status/create silently failed (calls are wrapped in `.catch(() => undefined)`, so no crash — workspaces just never appeared). Fix: bridge `/experimental/workspace` and `/experimental/workspace/*` to `httpApiBridge` before the legacy `/experimental` routes. The handler worked all along — it was simply unrouted; no control-plane reconciliation needed. Verified on the rebuilt binary via `serve`: `GET /experimental/workspace?directory=…` → 200 `[]` (was 500), `/experimental/workspace/status` → 200. Found via codex adversarial audit (pass 3). Server suite 276 pass / 0 fail. Typecheck + marker guard clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 555ac7fbd6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…sks, webfetch allowed The reviewer agent's `*: deny` (last-match-wins) clobbered the defaults' `external_directory: ask`, so `read`/`grep`/`glob` on paths outside the project (sibling repos, `~/.claude/skills`) hard-failed instead of prompting. `bash: deny` also made reviewing a PR by URL impossible (`gh pr view` is the primary path). - `external_directory`: use `readonlyExternalDirectory` (ask + whitelisted dirs allow), same pattern as the `explore` agent - `bash`: `deny` → `ask` — every command still requires explicit user approval; DDL safety denials still win via `userWithSafety` - allow `webfetch`/`websearch`/`list` for read-only PR/issue review - update reviewer prompt tool list to match - regression test: external dir asks, gh pr view asks, DROP still denied, edit/sql_execute_write still denied
…om a non-empty prompt - `input.line.home` / `input.line.end` were defined in keybind config and the keymap command list but nothing dispatched them for the prompt editor — register prompt-local commands so `Ctrl+A`/`Ctrl+E` jump to line start/end (#973) - Up/Down now browse prompt history whenever the cursor is on the first/last line, not only when the prompt is empty (#975); the in-progress draft is stashed on entry and restored when navigating back past the newest entry - extracted testable helpers to `prompt/navigation.ts` + `movePromptHistory` in `prompt/history.tsx`; unit tests added
…ommand, calm /feedback - #971: autocomplete concatenated TUI palette slash entries with server commands without a collision check, so `/mcps` showed twice. Dedupe generically by command name; the TUI entry wins (opens `DialogMcp`) while typed `/mcps` / `/mcps enable <name>` still reaches the server direct handler - #972: MCP surfaces now show how to authenticate — `DialogMcp` rows and the `/mcps` status table both render `Needs authentication (run: altimate mcp auth <name>)`, matching `/status`; formatter extracted as `SessionPrompt.formatMcpStatusForDisplay` with unit tests - #974: `/feedback` template now asks at most ONE round of clarifying questions and only for essential missing fields; keeps the category/label follow-up; drops the confirm-before-filing and separate session-context interview steps
Session output either linkified only the visible (truncated) text or let the terminal auto-detect links from truncated display text. Add `util/terminal-link.tsx`: - markdown (assistant + reasoning): attach a chunk transform that keeps the full URL as the link target while middle-ellipsizing the display text to the available width - shell + generic tool output: wrap detected URLs in explicit link elements with the full `href` from the untruncated source text Unit tests cover full-target preservation when display text is shortened or collapsed.
…keybind (merge drops) Post-merge audit findings: - explore agent lost `codesearch: "allow"` in the v1.17.9 merge — the tool gates on that permission, so explore silently degraded to local grep whenever codesearch was available - `prompt_skills` keybind was declared and mapped to `prompt.skills` but the prompt palette gather list never included it, so configuring it had no effect
…#978 ask design CI (TypeScript job) failures: - `cli/cmd/db.ts` read-only guard (c87d59d) opened an `altimate_change start` block but never closed it — four marker integrity/discipline suites failed. Add the missing `end`. - v0.8.0 adversarial + carry-forward pin tests asserted the reviewer's old `bash: deny`. #978 relaxed bash to `ask`; update the pins to the real invariant: NO bash command ever evaluates to "allow" (redirect writes, credential reads, plain git all ask), destructive DDL stays hard-denied, edit/write stay denied.
…e (audit findings) Post-merge audit found fork features re-homed into TUI plugins with "deferred" gaps that regressed pre-merge behavior: - auto_enhance_prompt: docs promised auto-rewrite before sending but the submit path never called it. New fork endpoint `POST /altimate/prompt/enhance` (no-op unless `experimental.auto_enhance_prompt: true`, returns original text on failure) called from the TUI submit path before pasted-text expansion. Internal `SessionPrompt.prompt` callers are not rewritten. - Altimate provider connect: selecting `altimate-backend` in the provider list now dispatches `altimate.provider.connect` (validation + save via `AltimateApi`), and a new `dialog.openModel(providerID)` plugin-API seam restores the bootstrap + model-picker handoff after save. - skill create/install: server skill cache is invalidated again via the raw generated client (`GET /skill?reload=true`, no SDK regen); success toasts only fire after reload verification, otherwise an explicit error names the skills that failed to appear. Guard tests extended in `test/upstream/fork-feature-guards.test.ts` so a future merge dropping these handoffs fails CI.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ae163389dd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…unch row growth) Found by the v0.8.10 -> v1.17.9 upgrade-path test: `__drizzle_migrations` gained one row on every launch. `adoptCoreOwnedDatabase` re-marks entries each boot, and `markDrizzleEntriesApplied` used `INSERT OR IGNORE` on a table with no unique constraint, so nothing was ever ignored. The guarded DDL never re-ran (no crash, no data change) but the journal leaked rows unbounded. - mark via `INSERT ... SELECT ... WHERE NOT EXISTS (name)` — idempotent - `dedupeDrizzleJournal` self-heals existing duplicate rows (keep MIN(id) per name), guarded, runs after name backfill and before migrate() - regression test: two simulated boots keep the journal row count stable; a seeded duplicate is collapsed. Fails without the fix.
…regressions) Code-level gates (typecheck/unit/CI) passed while every tester-filed regression (dead keybinds, /mcps dupe, reviewer perms, truncated URLs) shipped — because they are emergent behaviors of the compiled artifact. This suite drives the real binary in tmux with a hermetic mock LLM and carries one named journey per issue. - OPENCODE_TEST_CLI-gated: skips entirely in normal CI (13 skip); run locally against a built binary - 10 passing journeys: clean boot, ctrl+p palette, Tab agent switch, /models, prompt round-trip + trace file, ctrl+c keeps session alive, #971 (single /mcps row), #973 (Ctrl+A/E), #975 (history recall w/ draft) - 3 documented test.todo with FINDING notes + unit-test pointers where a full journey isn't hermetically feasible: #972 (needs real OAuth MCP → covered by mcps-command.test.ts), #976 (direct-mode OSC8 capture), #978 (mock harness doesn't render the permission dialog → rules covered by agent.test.ts + agent-safety.test.ts) - also adds the v0.8.10->v1.17.9 upgrade-path test report Run: OPENCODE_TEST_CLI="$PWD/dist/.../altimate-code" bun test test/tui-journeys
There was a problem hiding this comment.
💡 Codex Review
altimate-code/packages/tui/src/context/local.tsx
Lines 511 to 516 in 972df32
The MCP dialog toggles servers through legacy /mcp/:name/connect and /mcp/:name/disconnect clients, but the standalone server does not register any MCP group. In the packaged TUI, trying to enable, retry, or disable an MCP server from this dialog always fails at the HTTP call and leaves the UI state unchanged; add served V2 MCP routes or hide these actions for this server.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…indings) The v1.17.9 bridge merge silently reverted several upstream behaviors the fork depends on. Found by the systematic merge audit (Contract-1), verified as real split-brains (fork consumers present, producer dropped): - session/compaction.ts: tail-preserving compaction was dead — consumers read `tail_start_id` (session.ts, message-v2.ts) but no writer set it. Restore upstream's tail-selection (`select`/`preserveRecentBudget`/`turns`) so recent turns are preserved across compaction. - share/share-next.ts: restore `catch`/`try` around background full-sync and flush — an unawaited `fullSync` could reject unhandled on share failure. - session/retry.ts: restore retrying transient 5xx API errors even when the SDK marks them non-retryable. - session/llm.ts: restore `includeRawChunks` for the github-copilot provider — Copilot billing (`totalNanoAiu`) only populates via raw chunks; the consumer path existed but the flag was dropped. Each wrapped in `altimate_change upstream_fix` markers, each with a regression test that fails without the fix.
…nt calls)
Lower-severity merge drops the fork wants, from the Contract-1/2 audit:
- util/filesystem.ts: restore Windows path normalization (`windowsPath()`
for Git Bash/Cygwin/WSL styles) — HEAD had only `realpathSync.native`.
- cli/cmd/mcp.ts: prefer `altimate-code.json` in CONFIG_FILENAMES so CLI
MCP installs default to the fork's config name (opencode.json still
discovered for compatibility).
- tui first-run onboarding: restore the dropped beginner-tips / `isFirstTime`
home hint ("Get started: /connect … /discover … Ctrl+P") for new users.
- branding: fix user-visible "OpenCode config" leak in the core initialize
template; add markers to unmarked fork branding in footer/uninstall.
Each with a test. Skipped (documented in MERGE-VALIDATION-MATRIX.md): the
`opencode.internal` internal routing-key inconsistency — not user-visible,
works today, and changing it risks in-process routing breakage for no gain.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7232b3474d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Review-comment triage: resolving 136 codex comments as not-applicable to the shipped runtimeI went through all 136 unresolved, non-outdated codex review threads. None target
These are legitimate observations about upstream's in-progress V2 restructure, but they don't affect the artifact this PR ships. Resolving as not-applicable. If the standalone V2 server / V2 tool set is promoted to the shipped path in a future change, this is the backlog to revisit. Un-resolve any you'd like to keep open. |
…cking) Release-evaluation board (build/packaging perspective) found the release workflow pinned Bun 1.3.10 at all 4 setup-bun steps, but the build/publish scripts throw unless Bun satisfies ^1.3.14 (package.json packageManager + packages/script guard). CI was already bumped to 1.3.14; release.yml was missed — so every tag release would fail before producing artifacts.
…s (release board) Release-evaluation board (upstream-adoption + integration-seam perspectives) found upstream v1.17.9 work the bridge merge reverted or left unwired — the "don't lose upstream work" axis. All restored with upstream_fix markers + tests: - provider/provider.ts: Cloudflare AI Gateway unified provider now receives `apiKey` (authenticated unified-model calls were failing) — upstream 8fd5753f76. - provider/transform.ts: Devstral detection uses locale-safe `toLowerCase()` (was `toLocaleLowerCase()`) — upstream babe5070e2. - project/project.ts: session project-migration preserves `time_updated` (schema `$onUpdate` was silently rewriting session recency) — upstream c5c9a1d435. - config/tui.ts + tui-migrate.ts: managed TUI config is loaded + migrated again (existing managed tui.json / legacy theme+keybinds were ignored after upgrade). - config/paths.ts: restore main's `.jsonc`-before-`.json` same-dir precedence. - plugin/index.ts: wire the Azure / DigitalOcean / xAI auth plugins into INTERNAL_PLUGINS (files were merged in but never registered, so users could not authenticate to those providers) — matches upstream's internalPlugins(). - cli/cmd/run.ts: attach the basic-auth header to in-process `run` requests so local run still reaches the embedded server when OPENCODE_SERVER_PASSWORD is set (was 401ing) — upstream 632f94fa68.
Release-evaluation board (safety perspective) found the #209 sensitive-write guard was neutralized at runtime. The guard calls `ctx.ask({ permission: "sensitive_write" })` before writing a sensitive target (.env / .ssh / .git / ...), but `sensitive_write` was never configured, so it fell through to the builder's `"*": "allow"` default and silently auto-approved — defeating the guard the fork deliberately restored. Pre-existing (present on main too), not a merge regression, but a real bypass. Default `sensitive_write: "ask"` in the agent defaults so sensitive writes prompt (users can still override to "allow"). Write-restricted agents (analyst/reviewer/plan) keep their later `"*": "deny"`. Regression test asserts builder=ask, analyst/reviewer=deny.
Follow-up to the release-board processor.ts finding. Server-side (provider-executed) tool calls were already NOT re-executed locally — native-runtime.ts skips ToolRuntime.dispatch when event.providerExecuted is set. The remaining gap: the processor didn't propagate that flag onto the tool part's metadata, so rendering/serialization couldn't distinguish a provider-executed tool from a client-executed one. Tag `providerExecuted: true` in the tool part metadata on the tool-call event (mirrors upstream's part-tagging). Assertion added to the existing provider-executed test. Remaining scoped follow-up (not done — telemetry-only, entangled with HEAD's different settlement-event architecture): emit `provider.executed` on the Tool.Failed/Completed settlement events (the sibling test stays `.todo`, blocked on the documented injected-LLM harness limitation).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e3a160ae0e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
What does this PR do?
Bridges the fork from upstream OpenCode v1.4.0 → v1.17.9 (a no-common-ancestor tree-overlay merge of ~1850 files) and reconciles all fork customizations on top.
Highlights:
Context.Service/Layer/Effect-Schema rewrite (Service facades +makeRuntimePromise wrappers;zod()↔Effect-Schema bridges; new Tool API viatool-zod-compat).withStaticsinfinite recursion + a re-entrant runtime build that prevented the agent from running at all.bun@1.3.14but CI/pre-push stayed on1.3.10, which couldn't boot the merged CLI as a subprocess (748 false failures). All 6 CI pins → 1.3.14.CREATE TABLEmigrations against an already-current schema (table \project` already exists, ~324 cascading fails).applyOnly()` now adopts the current schema when the journal diverges; test-DB reset preserves schema; boot-time project-copy refresh isolated. Production is unaffected (single-process boot migrates once — proven by 88/88 real-model e2e).server_errorretryable, content-filter→error, snapshot pre-capture,compaction.auto:false, shell expansion, signed-reasoning spacing, stop-with-tools continuation).run --trace) wrote no artifacts andskill listexited 1 — both threwInstanceRef not providedbecause the instance ALS isn't bridged for plain-async CLI facade calls (the instance AsyncLocalStorage is duplicated across the module boundary). Both now read through the in-process server client (sdk.config.get()/sdk.app.skills()), which holds the resolved instance. Verified in the built binary; regression tests added.Type of change
Issue for this PR
Closes #963
How did you verify your code works?
bun test= 10,455 pass / 0 functional fail after the DB-race fix (was ~324 inherent fails masked as the prior over-stated "1 fail"). Independently re-verified; 0SQLiteError/database is locked/disk I/Oresidue. (One test was a local-only artifact — a dev's gcloud ADC madeconfig.providers()return a google-vertex provider whose modelvariants/release_datefail the generated SDK'sDeclarationschema; the preload now isolates Google creds so local matches CI.)/apierror flood.Checklist
// altimate_changemarkers)Known remaining work (tracked, non-blocking)
config.providers()returns model data (variants,release_date,experimentalOver200K) richer than the generated SDK'sDeclarationresponse schema for providers like google-vertex — the SDK schema/codegen should be regenerated to match (route works in production; only the strict SDK response-validator is behind).opencode(renaming needs a config-compat alias).Full validation artifacts under
.github/meta/night-run/:NIGHT2-STATUS.md,DBRACE-FIX.md,WS3-VISUAL-FINDINGS.md,TUI-UPSTREAM-DIFF.md,e2e/GPT55-BINARY-RESULTS.md.Post-merge tester-found regressions fixed (2026-07-01)
Real-world testing by @shreyastelkar (2026-06-30) surfaced regressions; all fixed on this branch, plus a post-merge audit that restored more silently-dropped fork behavior:
*: denyclobberedexternal_directory: ask(last-match-wins), hard-failing reads outside the project; bash hard-deny blockedgh pr view. Now: external reads prompt, bash asks, webfetch allowed; writes still denied.mcpsslash command is listed twice in the list when searching/mcp#971 —/mcpsappeared twice in slash autocomplete (TUI palette entry + server command); deduped generically by command name./mcpslist should show the command to authenticate the MCP similar to/status#972 —DialogMcprows and the/mcpsstatus table now showNeeds authentication (run: altimate mcp auth <name>), matching/status.Ctrl+AandCtrl+E(emacs keybindings) don't work in the prompt — must use arrow keys #973 — Ctrl+A / Ctrl+E in the prompt: keybinds existed but nothing dispatchedinput.line.home/endfor the prompt editor; prompt-local commands restored./feedbackcommand asks too many follow-up questions before submitting #974 —/feedbackasks at most one round of clarifying questions; keeps the label follow-up.codesearch: allow(was silently degrading to grep);prompt_skillskeybind is now actually gathered.experimental.auto_enhance_promptruns on submit again (newPOST /altimate/prompt/enhance), selecting Altimate AI in the provider list runs the fork credential validation + model-picker flow again, and skill create/install invalidates the server skill cache (GET /skill?reload=true) with reload verification. Guard tests added so a future merge dropping these fails CI.altimate_changeblock incli/cmd/db.tsand updated the v0.8.0 reviewer pin tests to the new invariant (no bash pattern ever auto-runs; DDL stays hard-denied).🤖 Generated with Claude Code