Skip to content

Fix/windows acceptance - #132

Merged
deepagent-ai merged 13 commits into
devfrom
fix/windows-acceptance
Sep 27, 2026
Merged

deepagent-ai merged 13 commits into
devfrom
fix/windows-acceptance

Conversation

@deepagent-ai

Copy link
Copy Markdown
Contributor

Issue for this PR

Closes #

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Please provide a description of the issue, the changes you made to fix it, and why they work. It is expected that you understand why your changes work and if you do not understand why at least say as much so a maintainer knows how much to value the PR.

If you paste a large clearly AI generated description here your PR may be IGNORED or CLOSED!

How did you verify your code works?

Screenshots / recordings

If this is a UI change, please include a screenshot or recording.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

If you do not follow this template your PR will be automatically rejected.

electron-builder compiles installer.nsh twice (installer pass and
BUILD_UNINSTALLER pass) and elevates makensis warnings to errors.
The installer pass emitted both RemovePathSegment variants but only
references the non-un. one (and vice versa), so the unreferenced
variant failed the build with warning 6010. Emit only the variant
each pass references. This is the root cause of the desktop-build.yml
failures on dev.
… creation

Search.release() fails the wait gate when a picker is still being created,
but the creating fiber went on to register the completed picker anyway:
release had already run and the layer finalizer only destroys what is
registered at dispose time, so the picker's native watcher thread outlived
disposal against process exit.

Found during the Windows physical acceptance segfault investigation: the
creator now checks whether its gate is still the wait-mapped one before
registering, destroys the fresh picker uninterruptibly when it is not, and
the ensuring cleanup destroys any created-but-unregistered picker on fiber
interruption. Every path now ends with the picker either registered or
destroyed.
The Windows physical-acceptance CLI crashed non-deterministically
(~50% of short-lived commands) with 'panic(main thread): Segmentation
fault'. The uploaded bun.report for the crash shows the fault inside
mimalloc free during a JSC GC sweep of an ArrayBuffer — heap corruption
in the embedded runtime, not product code.

Reproduced the matrix on the acceptance machine (session/agent/packs/
oversight/mcp list, real state): bun 1.3.14-built binary crashes across
runs; the same tree rebuilt with bun 1.4.2 passes 15/15 with zero crashes
and zero hangs. bun.report itself flags 1.3.14 as outdated against 1.4.2.

package.json's packageManager is the single version source for CI
(setup-bun action, desktop-build bun-version-file) and the release
compile, so bumping it here fixes every publish path.
…g files

The M-CRED startup migration persisted the rewritten (handle-only) config
through Config.update, which wrote <project>/config.json — a file no config
loader merges, so the plaintext stayed in its origin file forever and the
migration re-ran on every startup.

migrateOnStartup now rewrites only the servers that moved, each in the config
file it was merged from (cfg.mcp_origins), via jsonc-parser so comments and
sibling keys survive — the same mechanism mcp add/remove/edit use. Non-file
origins (remote well-known/console config, inline env content) warn and keep
their plaintext: those sources are admin-controlled and re-supply it anyway.

Config.update itself wrote to that same dead layer, so instance-scope config
updates (HTTP config.update) silently vanished on reload; it now writes the
project deepagent-code.json, which ConfigPaths.files actually merges.
A failed or interrupted previous app build left stale hashed chunks in
packages/app/dist; the embed scan picked up both generations and shipped them
inside the binary. Remove dist up front so the embedded file map contains
exactly what this build produced.
… after migration

global.ts imports util/log to surface the D-W1 migration report, and util/log
statically imported global for its log directory — a cycle in which whichever
module evaluates first sees the other's exports uninitialized. The CLI bundle
loads log first, so on Windows every migration skip (already-migrated on each
post-migration launch, data-home-exists) or error hit Log.Default.warn while
still undefined and crashed the process at startup (exit 1, TypeError). POSIX
never reaches the warn (the migration hook returns undefined off-win32), which
is why dev runs never saw it.

util/log only needs the log directory once logging initializes, long after both
modules have evaluated; resolve it with a dynamic import there and drop the
static back-import, removing the cycle entirely.
…onfig file

mcp_origins records the merge source of each MCP entry, which is a file path
for project configs but the config DIRECTORY for the global layer — its loader
folds several files into a single merge step. The origin rewrite from the
previous commit treated that directory as a file and failed (EISDIR), so
plaintext survived in the global config; verified live on the acceptance box.

Directory origins now resolve to the loader's candidate files (config.json,
deepagent-code.json(c), canonical config.jsonc last) and the entry is
rewritten in whichever file declares the server. Absent candidates return
false instead of throwing so a missing legacy file is not logged as a failure.
… bun 1.4.2

The interactive TUI crashed deterministically (5/5) on Windows with a native
segfault inside opentui.dll at first draw, in both source and compiled-exe
forms, PTY or not — while every non-TUI command stayed clean, because only
the TUI render path loads the native module. opentui 0.3.2's win32 binary is
incompatible with the bun 1.4.2 runtime; the darwin dylib is fine, which is
why mac dev never saw it. Verified live on the acceptance box: 0.3.2 crashes,
0.5.12 boots clean under bun 1.4.2.

Bumped via script/upgrade-opentui.ts. API drift was three call sites:
DialogPrompt's description prop takes a direct element (two callers unwrapped,
plugin adapter calls its lazy element), and the session error banner renders
the keyed Show error's message.
…on Loading

The terminal auto-create lifecycle gates on runtimeId, but runtimeId was only
resolved by a single fire-and-forget health call on TerminalProvider mount
(plus a conditional poll that only re-ensured while terminals already
existed). A cold page load whose one-shot health call lands inside the
server's instance bootstrap fails silently, leaves runtimeId unset, and the
panel deadlocks on "Loading terminal..." forever — reproduced deterministically
on the Windows acceptance box (fresh reloads after a serve restart never fire
pty.create; toggling the panel tab away and back creates a terminal because
by then the earlier ensure had resolved).

The poll now also retries while runtimeId is unset, so the panel recovers
within one poll interval (5s) instead of never.
…dlocked on Loading

The auto-create lifecycle gates its active() on runtimeId !== undefined, but
runtimeId was a plain closure variable: on a cold load with a persisted-open
terminal panel, the gate's single evaluation runs before the one-shot health
probe resolves, and nothing can ever retrigger the effect (terminal.all()
stays empty). The panel then shows "Loading terminal..." forever —
reproduced deterministically on the Windows acceptance box where every fresh
reload after a serve restart never even sent pty.create, while SPA
navigations and tab toggles worked because the probe had resolved by then.

runtimeId is now a signal, so the gate re-evaluates the moment the health
probe resolves and auto-create fires. Verified on the box: 3/3 fresh cold
loads mount the terminal within 3s and execute commands end-to-end.

Combined with the previous commit (retry the probe while unresolved), both
failure shapes of this gate — probe-failed and probe-not-yet-resolved —
recover automatically.
… in release CI

bun cross-compilation with the large embedded web UI produced non-starting
Windows PEs when the build host was macOS (verified on the acceptance box:
cross darwin->win embed builds fail to load; native Windows builds of the
same tree run the full acceptance suite clean). Rather than triage
cross-compile per build host, the release pipeline now builds the Windows
targets natively: build-cli (ubuntu) drops its win32 targets via the new
--exclude-win32 flag and uploads the ephemeral release-owner public key, and
a new build-cli-windows job on the existing windows-2025 runner builds
--single --baseline with the same release identity pinned, then uploads the
deepagent-code-cli-windows artifact the signing, desktop-electron, and
publish jobs already consume — no downstream changes. The build script's own
smoke test executes the exe on the runner, so a non-starting Windows build
now fails CI instead of shipping.
…d-load fix, secret migration, native Windows CI builds
2.0.2 is merged to dev but has not been released (no v2.0.x tag exists), so
these fixes ship as part of 2.0.2 itself rather than a new version.
@github-actions

Copy link
Copy Markdown

Hey! Your PR title Fix/windows acceptance doesn't follow conventional commit format.

Please update it to start with one of:

  • feat: or feat(scope): new feature
  • fix: or fix(scope): bug fix
  • docs: or docs(scope): documentation changes
  • chore: or chore(scope): maintenance tasks
  • refactor: or refactor(scope): code refactoring
  • test: or test(scope): adding or updating tests

Where scope is the package name (e.g., app, desktop, deepagent-code).

See CONTRIBUTING.md for details.

@github-actions

Copy link
Copy Markdown

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • No "Type of change" checkbox is checked. Please select at least one.
  • No issue referenced. Please add Closes #<number> linking to the relevant issue.
  • "How did you verify your code works?" section is empty. Please explain how you tested.
  • Not all checklist items are checked. Please confirm you have tested locally and have not included unrelated changes.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

@deepagent-ai
deepagent-ai merged commit 88fe5b7 into dev Sep 27, 2026
4 of 17 checks passed
@deepagent-ai
deepagent-ai deleted the fix/windows-acceptance branch September 27, 2026 16:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant