Skip to content

[WRONG BRANCH] feat: add optional JEV Auto routing - #1

Draft
kingkej wants to merge 185 commits into
review/jev-auto-basefrom
feat/jev-auto-routing
Draft

kingkej wants to merge 185 commits into
review/jev-auto-basefrom
feat/jev-auto-routing

Conversation

@kingkej

@kingkej kingkej commented Sep 21, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Add an optional, credential-only TypeSafe JEV provider and a jev Combo strategy for automatic model selection.
  • Add a jev-auto setup action in the GUI that reuses the existing Combo editor, so users can add, remove, reorder, and inspect the models JEV may choose.
  • Preserve existing model-picker, direct-model, default-provider, and non-JEV Combo behavior. JEV publishes no selectable model and cannot itself be selected as a Combo target.
  • Keep the runtime boundary narrow: one bounded JEV decision request, strict target and reasoning-effort allowlists, fail-open selection, ordinary Combo fallback after retryable selected-target failures, and caller cancellation propagation.
  • Add focused runtime, server E2E, provider, CLI, GUI, structure, docs, and localization coverage.

Privacy and security boundary

JEV receives only bounded task/tool/image-presence signals needed for a routing decision. OpenCodex does not send raw images, tool arguments, request headers, provider credentials, full conversation history, or encrypted reasoning to JEV. The JEV credential is applied only to the canonical TypeSafe destination, and same-named custom providers do not inherit it.

Please give the credential-destination and external-decision boundary explicit security review.

Provider evidence

Fork review staging

This fork-only PR targets review/jev-auto-base, which is pinned exactly to upstream dev commit 1687636193d3559c2bc7cc37f427dea71e693c34. An upstream PR is intentionally deferred until review here is complete.

JEV Auto Combo setup

Verification

  • Original focused root suite: 341 passed, 0 failed; 3,396 expectations across 9 files.
  • Final focused suite on 0307590a0: 117 passed, 0 failed; 532 expectations across 4 files. The same suite then passed three more consecutive repetitions. The large harmless-markup regression measured 18 ms after its pre-fix red run measured 227 ms.
  • Full GUI suite: 2,272 passed, 0 failed; 19,291 expectations across 273 files.
  • Root typecheck, structure single-source-of-truth check, privacy scan, and git diff --check: passed.
  • Root Bun bundle: passed; 1,516 modules bundled.
  • GUI production build: passed (existing large-chunk warning only).
  • GUI i18n lint: passed.
  • Docs build: passed; 497 pages generated.
  • Fresh live smoke on final head 0307590a0 through the actual resolveJevDecision path: JEV returned apply, selected allowlisted sol/gpt-5.6-sol with valid high effort, and completed in 945 ms; credential was process-local, removed afterward, and not persisted.
  • All four Codex review threads were addressed in 0a148c358, replied to with regression evidence, and resolved.
  • Independent post-fix review and a separate final review of the harmless-markup fast path found no remaining actionable findings.
  • Hosted CI on 71aab276b passed the gates, GUI, structure, docs, packaging, Docker, keyring, React Doctor, and test shards 2/4 through 4/4. Test shard 1/4 and macOS 1/2 reproduce the base-level pinnedHttpPost missing-export failure in untouched image-test files.
  • Hosted CI on 0a148c358: React Doctor, gates, docs, structure, packaging, Docker, keyring, desktop, and test shards 2/4 through 4/4 were green. Test shard 1/4 reproduced the same untouched base-level pinnedHttpPost missing-export failure. macOS 1/2 reached the 20-minute job ceiling twice (the original attempt plus one scoped diagnostic rerun), both times stalling at untouched tests/codex-integration/catalog-full-picker-order.test.ts before any JEV test file ran; setup and GUI build passed and no assertion was reported. These two lanes are coverage gaps, not JEV failures or green results.
  • Final-head CI on 0307590a0: React Doctor, gates, docs, structure, packaging, Docker, keyring, desktop, macOS 2/2, and Linux test shards 2/4 through 4/4 passed. Linux test 1/4 reproduced the untouched base pinnedHttpPost missing-export error. macOS 1/2 reached the 20-minute ceiling at the same untouched catalog-full-picker-order.test.ts boundary; together with the original attempt and scoped rerun on 0a148c358, this is the third identical pre-JEV-test stall. The overall workflow is red only because of these two explicitly reported coverage gaps.
  • The repository-wide root suite was also attempted locally, but hit its 900-second Windows lane limit with unrelated EBUSY, process-spawn, ACL, and ownership failures. This is reported as an environment coverage gap, not a passing result; the affected focused tests and the complete GUI suite are green.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, external data sharing, and unsafe defaults.
  • Existing picker, direct selection, default-provider, and non-JEV Combo behavior remains unchanged.
  • The branch is pushed and based on the pinned fork review base.
  • The PR is ready for review.

luvs01 and others added 15 commits September 20, 2026 12:20
…e does not fork execPath (lidge-jun#5418)

* fix(cli): probe endpoint liveness in-process so the standalone resolve does not fork execPath

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(cli): prove absence on every loopback host and see refusals inside AggregateError

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* ci: retrigger cross-platform run (macos 1/2 shard hit the 20-minute runner timeout)

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(cli): keep a mixed aggregate out of the absence proof

---------

Co-authored-by: jun <bitkyc08@gmail.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
lidge-jun#5445)

* fix(desktop): name the bootstrap script in the policy the webview is actually served

* fix(desktop): ship the startup surface as one page the policy can name
* feat(desktop): restore detailed usage in a compact tray popup

* fix(desktop): point the popup at the endpoint module this tree has

* fix(desktop): let the popup navigation gate read its own constants

* docs(devlog): record the tray usage popup as built and run on macOS

* fix(gui): clear the React Doctor findings in the tray popup page

The pull_request check runs react-doctor at blocking: warning with no comment,
review comment, or commit status, so nine findings failed the PR while being
readable only inside the run's job summary. Reproduced with the repository's own
pinned scan and fixed at the root rather than suppressed:

- import useI18n from i18n/shared instead of through the barrel
- hoist the hidden-provider and configured-model lookups into Sets in both the
  chart filter and filterUsage, keeping models === null as "all models"
- move the pure incomplete() helper to module scope
- key quota rows by an identity quotaWindows() now assigns

That identity also closes a bug the index key was hiding: a provider may report
two custom windows under one label, and the row key has to stay unique anyway or
React reconciles two different windows onto the same row.

The effect's post-await writes keep the single active() guard, which checks both
disposal and the AbortSignal. The rule cannot see the property through a helper,
so the finding carries a scoped suppression that states the evidence.

* feat(desktop): give the tray popup the native translucent surface

The popup sat next to the WidgetKit widget as a flat #202022 rectangle. macOS now
gets the active HUD window material at a 12-point radius and Windows gets Acrylic,
both through Tauri's own effects builder, so no new dependency is involved.

Linux stays opaque: blur there belongs to the compositor and the effects path does
not support it. That asymmetry is exactly where a transparent stylesheet would
paint a hole instead of a panel, so one cfg constant, VIBRANT_SURFACE, decides both
the native builder and the data-tray-vibrancy hook the page reads. The two cannot
disagree because neither restates the other.

Transparent windows on macOS require the macos-private-api feature and
app.macOSPrivateApi; that forecloses Mac App Store submission, which this
Developer ID DMG channel does not use.

Also restores rustfmt formatting in popup.rs. The desktop shell job failed on the
format step, which gates clippy and the Rust tests, so neither had run since the
popup landed on the branch.

* feat(gui): restyle the tray popup to the widget's vocabulary

The popup and the menu bar widget showed the same numbers in two different visual
languages. The page now uses the material behind a thin scrim, rounded tabular
numerals with the leading figure carrying each section, secondary-tone labels, and
separators only where the subject changes. The scrim is what keeps contrast stable
across wallpapers; without it a light desktop washes the labels out.

Every rule keeps an opaque default and layers the glass on top, so the stylesheet
is correct on a platform that never sets the hook. The appended duplicate rules
that had accumulated at the end of the file are folded into the blocks they were
overriding.

gui-tray-vibrancy-surface.test.ts reads both popup.rs and tray.css and fails if the
dataset flag and the attribute selector drift apart. Nothing in either toolchain
connects them, and a silent rename would either lose the glass or punch a hole.

* fix(gui): keep the quota row identity out of the hardcoded-string gate

The GUI lint rule reads a template literal's leading text as UI copy, so both
"custom:" and the key-shaped "quota.custom." failed the gates job. A custom window
is identified by its own label now, with no literal at all; the de-duplication pass
is what keeps that unique, including against the three fixed keys.

---------

Co-authored-by: Jyun1998 <yjunwoo14@gmail.com>
Co-authored-by: JayYun98 <JayYun98@users.noreply.github.com>
…jun#5462)

* fix(desktop): let the tray's left click reach the usage popup

Attaching a menu to a tray icon makes the left click open that menu, and the
builder never said otherwise. So on macOS and Windows the click never reached
on_tray_icon_event in any visible way: the icon showed the menu, and the menu item
that opens the popup is Linux-only. The popup lidge-jun#5452 added had no way to open at all
on the two platforms where the left click is the whole interaction.

Found by clicking it. The change reads correctly either way, which is why static
review kept missing it — the handler is there, the event fires, and the wrong
surface appears on top.

Linux keeps the default. Its StatusNotifier hosts deliver no usable click event, so
the menu is the entire interaction there and releasing it would remove the only way
in.

The pairing is now a test. Nothing in the type system connects .menu() to
show_menu_on_left_click(), and the failure is quiet, so tray.rs reads its own
production half at compile time and fails if a menu is attached without releasing
the click. It slices the source at the test attribute because the assertions quote
the call names they look for, and scanning the whole file would find the test's own
literals and keep passing after the real calls were gone.

* fix(desktop): give every platform a menu path to the usage popup

Releasing the left click is not enough on macOS, and the reason is upstream:
tray-icon assigns the menu to the NSStatusItem itself, so AppKit pops that menu on
mouse-down before the crate's own click handler runs. show_menu_on_left_click(false)
sets an ivar that handler reads, and the handler never gets the chance. Verified by
reading tray-icon 0.24.2's macOS implementation after a locally built bundle kept
showing the menu with the flag set.

So the icon click cannot be the only way in. The Show Usage item was Linux-only
because Linux hosts differ in whether a click reaches the application at all; that
same reasoning applies to macOS for a different cause, and it leaves Windows as the
only platform the icon alone would have served. The item is unconditional now.

The click release stays: it is correct on Windows, where it does what it says.

The guard covers the item too. Platform-gating it once already left two platforms
with no way to the popup, so the test now fails if any line that mentions the item
sits under a cfg attribute.

* fix(desktop): anchor the menu-opened popup on the tray icon

The menu handler passed a zero anchor, which popup::geometry clamps into the
top-left corner of the work area. That was tolerable while the item was a Linux
fallback; now that the menu is the ordinary way in on macOS, a window in the far
corner reads as misplaced rather than as a menu.

It reads the tray icon's rect and anchors on its centre. A host that cannot report
a rect still gets the clamped corner, which is the best answer available there.

* docs(devlog): record the glass popup opening from the tray menu

Captured from a locally built bundle on macOS, against a runtime started with an
isolated configuration home. The dashboard behind the panel shows through the
material at the left edge, and the window is anchored under the icon rather than
clamped into a corner.

* fix(desktop): satisfy clippy and stop the guard matching its own prose

Two things the format step had been hiding. It gates clippy and the Rust tests, so
neither had run on the popup since it landed.

clippy rejects the nested `if` inside the `Focused(false)` arm; it is a match guard
now, with the same behaviour.

The left-click guard matched the bare call name, and the comments above the menu
explain why that flag is inert on macOS — so the assertion found its own prose
earlier in the file than the builder and concluded the order was wrong. It matches
the call site now. The ordering comparison is gone: it asserted nothing the presence
of the call site does not already say.

cargo test --lib tray:: and popup:: pass locally.
…jun#5451)

* fix(desktop): make the startup surface unable to wait forever

On Linux the bootstrap window drew its six phase rows and then never changed
again: the headline stayed on the markup's default and every row stayed
pending, pixel-identical at 26s and 46s. The page's own handshake deadline is
5s and it never fired, so all three invokes answered — `apply` had been handed
a falsy progress and returned at its first line. Three things made that
reachable.

`startup_snapshot` could answer `None`. The page returns early on a falsy
progress, so the one case it cannot render, a shell with no startup state,
arrived as silence instead of as a diagnostic. It now always answers with a
state, and a missing startup state is reported as a failure the user can read
and copy.

`run` looked up `AppState` before publishing anything, so the sequence could
return having said nothing at all. The first report now happens before any
lookup that can fail.

Nothing enforced the 30-second ceiling. Several returns inside `run` report no
terminal state, and a step that outlives the deadline reports none either, so
the surface kept whatever it was last told for as long as the process lived. A
guard bound to the run now reports a terminal state when the run does not. It
is idempotent and generation-scoped, so it cannot overwrite a result the run
reported and one left over from an earlier run cannot fail the retry that
replaced it, and it waits a short grace past the ceiling so the run's own
failure — which names the endpoint, the home and how the child ended — is the
diagnostic on screen rather than the guard's thinner one.

`Phase::NotStarted` is new and deliberately absent from the checklist the page
draws. The state used to be seeded with `registering`, so a shell that never
began rendered exactly like one that had just begun, on the surface whose whole
job is to tell those apart.

* test(clients): anchor the run oracles on the name, not the signature

`desktop-cli-contracts` sliced the sequence at the literal
`async fn run(app: &AppHandle)`. Giving `run` its start instant changed that
string, `indexOf` answered -1, and `slice(-1)` returns the last character
rather than failing — so every index the case computes became -1 and the four
ordering assertions compared -1 against -1. It did not go quietly only because
the first one is `toBeGreaterThan(-1)`; the rest would have passed on an empty
string.

Both run oracles now anchor on the function name, which is what they are about,
and assert the anchor was found before slicing. A parameter added to the
sequence is not a change to the order these cases pin.
lidge-jun#5467)

* docs(devlog): land the app runtime ownership record and close the unit

The planning record for this batch lived only on an unmerged branch while every
lane it describes was already on dev. The decisions, the contradiction rounds, the
lane split and the re-audit are the reasons the code looks the way it does, so they
belong in the tree beside it. They carry no host detail; 040 says so explicitly,
and a sweep for addresses, mesh names, accounts and absolute user paths finds
nothing beyond loopback in technical prose.

150 records the outcome and the two things worth carrying forward: the single
constant that binds the native translucent surface to the page's CSS hook, and the
defect that no amount of reading would have found — tray-icon assigns the menu to
the NSStatusItem, so AppKit pops it before the crate's click handler runs, and the
popup had no way to open on macOS or Windows.

* docs(devlog): record that the privacy scan skips devlog-only commits

The scan lives in the gates job, which is gated on the ci paths filter, and that
allowlist has no devlog entry. So the one change class where reading devlog
matters is the one where the scan never runs, and the aggregate check goes green
anyway. This pull request is an instance: sixteen devlog files, proven by a hand
sweep rather than by the gate.
@coderabbitai

coderabbitai Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

✅ Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the enhancement New feature or request label Sep 21, 2026
@github-actions github-actions Bot changed the title feat: add optional JEV Auto routing [WRONG BRANCH] feat: add optional JEV Auto routing Sep 21, 2026
@github-actions

github-actions Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

⏳ DRAFT

  • wrong target branch (review/jev-auto-base); retarget to dev.

What to do

  • Retarget this PR to dev — all contributions go to dev.

Its title has been prefixed with [WRONG BRANCH].
This pull request was already a draft. Its draft status will be preserved after every issue above is resolved.

@github-actions
github-actions Bot marked this pull request as draft September 21, 2026 16:47
@kingkej
kingkej requested a lite review from Copilot September 21, 2026 16:48

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

kingkej commented Sep 21, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@lidge-jun @Ingwannu — please review this fork-staging PR, especially the JEV credential destination, bounded external decision payload, strict target/effort allowlisting, and fallback/cancellation behavior.

GitHub cannot add upstream maintainers as formal reviewers on this fork because neither account is a fork collaborator, so this mention is the review request. The target branch is intentionally review/jev-auto-base, pinned exactly to upstream dev at 1687636193d3559c2bc7cc37f427dea71e693c34; the fork's existing dev branch is divergent and was deliberately left untouched. Accordingly, the inherited “wrong branch” draft gate is a staging-only false positive. The PR is mergeable and the implementation is ready for review.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-21T16:58:05.514911Z ab896b9 Manual request
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ab896b94b8

ℹ️ 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".

Comment thread src/combos/jev.ts Outdated
Comment thread src/server/responses/core-combo.ts
Comment thread src/server/responses/core-combo.ts Outdated
Comment thread src/combos/jev.ts

kingkej commented Sep 21, 2026

Copy link
Copy Markdown
Owner Author

@shamblan review requested for follow-up commit 0a148c358. It addresses all four Codex threads with regressions for protected-envelope split boundaries, sentinel effort replacement, post-cooldown eligibility, and bounded outbound JEV requests. Formal reviewer assignment is unavailable because this is a fork-only staging repository.

luvs01 and others added 30 commits September 25, 2026 13:52
…cher hijack (lidge-jun#5789)

* fix(service): pin launchd to package-local Bun/CLI to avoid PATH-launcher hijack

* test(service): assert supplied launcher stays out of launchd command

* docs(service): scope ADR-0030 to the systemd launcher; launchd follows ADR-0100

* test(service): exercise the launchd stale-launcher diagnostic on every platform

---------

Co-authored-by: luvs01 <luvs01@users.noreply.github.com>
Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
* fix(update): stop deleting stale staging paths

* docs(update): match the troubleshooting page to the stale-stage policy

The page still claimed a later update removes owned staging folders.
The install now reports marked stages older than half an hour as ESTALE
and leaves them in place, so the table and the closing note tell the
user to delete a leftover by hand only after confirming nothing runs
from it.

* fix(update): drop the stale sweep log and dead removed list

The sweep no longer deletes anything, so the discardStage message must not promise the next update removes a locked stage, and the result type drops a list nothing fills.

* docs(update): qualify stale-stage ownership, links, and disk claims

* fix(update): say later updates will not remove a leftover stage either

* fix(update): describe staging removal failures neutrally

---------

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
* fix(service): pin elevated scheduler staging paths

* fix(service): reject traversal segments in elevated staging paths

The shared-staging-directory guard used a raw startsWith prefix check, so a
predecessor path containing '..' (e.g. <stageDir>\..\elsewhere\expected.xml)
passed while resolving outside the pinned directory. Reject '..'
segments on either separator for both payloads before comparing prefixes.

Co-Authored-By: Epinephrine <luvs01@hanmail.net>

* docs(service): distinguish ancestor delete-share from payload write/delete-share

* test(windows): assert staged-path lock calls precede elevation

* fix(windows): pin staging parent dir and assert lock ordering

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
…ring systemEnv upgrade (lidge-jun#5792)

* fix(claude): clear legacy _CLAUDE_CODE_ASSUME_FIRST_PARTY_BASE_URL during systemEnv upgrade

* fix(server): unset legacy Claude base-url env whenever it reads 1

---------

Co-authored-by: luvs01 <luvs01@users.noreply.github.com>
Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
* fix(release): fail closed when draft state lookup fails

* fix(release): fail on any draft state other than an explicit false

A successful draft-state query that answers neither true nor false — an
empty body or an unexpected shape — used to skip the publish step and
leave the release a silent draft. Only an explicit false may pass now;
anything else fails the step. The contract test covers the unexpected
value alongside the existing failing-query case.

* test(release): cover fail-closed publication with portable isolated Bash regressions

Keep the existing release workflow fix unchanged. Separate static contracts
from shell execution, find native Git Bash on Windows, and refuse silently
skipped shell coverage on CI. Mock only the expected gh commands in an empty
working directory with no inherited credentials or executable search path.
Assert success paths, command order, six malformed states, and upload/view/edit
failure propagation. Add subprocess time and output bounds.

Local preliminary validation: TypeScript syntax and 12 checks through a Node
adapter invoking actual Bash passed; restoring the original bug or making the
script always fail was detected. Native Bun cross-platform validation pending.

---------

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
lidge-jun#5786)

* fix(release): isolate dev data from bump credentials

* fix(release): keep bump push credentialed and run version checks from trusted root

* ci(version-bump): fail when the chosen version already has a release tag

---------

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
* fix(ci): scan markdown fences in linear time

* fix(ci): handle CRLF line endings when matching closing markdown fences

* fix(ci): pair fence openers by index so an unmatched opener cannot hide a later block

Co-Authored-By: Epinephrine <luvs01@hanmail.net>

* fix(ci): let a shorter closing fence match the way the backreference did

Co-Authored-By: Epinephrine <luvs01@hanmail.net>

* docs(ci): pin closeFor parent-link contract and the fence parity choice

* test(ci): exercise close-length parent chain in fence scan

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
* fix(hooks): stop executing pulled code after merges

The managed post-merge hook ran bun run postmerge on every contributor's
machine after every merge, executing whatever the just-pulled commits
put in package.json. There is no way to keep the feature without
keeping that auto-executed-code path, so the hook is removed outright:

- package.json drops the postmerge script and both hook files
  (post-merge.sh, build-gui-if-changed.ts) are deleted.
- setup-hooks.ts no longer installs hooks at all; it now also retires an
  already-installed post-merge shim by exact content match, the same
  way the retired pre-push shim is handled, so existing contributors
  lose the vector on their next setup run.
- CONTRIBUTING.md, the eight localized docs-site contributing pages,
  and structure/ops/docs-and-release.md describe the retirement and
  point at bun run build:gui for a manual dashboard rebuild.
- The setup-hooks test covers shim retirement for both line endings,
  custom-hook preservation, and no-hook fresh installs.

* test(hooks): cover retiring a stale post-merge from a shared hooksPath

The configured-hooksPath case only placed a stale pre-push. A post-merge shim copied into a shared directory keeps executing pulled code in every repo that resolves it, so the test now installs one and asserts setup removes it.

* fix(hooks): process both managed hooks when one removal fails

A failed read or unlink of pre-push aborted the script before the post-merge retirement ran, leaving the shim that executes pulled code in place. Each retirement now warns and continues.

* fix(hooks): exit nonzero after attempting every managed hook removal

* docs(contributing): note the manual GUI rebuild after merges

* fix(hooks): bound hook-retirement diagnostics and gate the POSIX failure test

---------

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
)

* fix(openai-chat): suppress raw freeform MiMo call echoes

* openai-chat: guard raw tool echo matching

* fix(openai-chat): match JSON freeform echoes safely

* fix(openai-chat): use declared identity for echo matching

* docs: explain MiMo tool-call echo visibility

---------

Co-authored-by: Vadevious <Vadevious@users.noreply.github.com>
… quantifiers (lidge-jun#5774)

* fix(exec): rewrite empty-output wrapper regex without repartitionable quantifiers

Adjacent \n+/\s* quantifiers in EMPTY_EXEC_OUTPUT_REGEX could repartition
a newline block combinatorially — 'Script completed\n' + 200k newlines +
'!' takes ~34s to reject on the old pattern. Each wildcard run is now
pinned to its maximal match via the lookahead-capture idiom; acceptance
is unchanged (25 tests incl. section combinations and a pathological
whitespace case pass, mutation-checked against the old pattern).

Co-Authored-By: Epinephrine <luvs01@hanmail.net>

* test(adapters): pin trimmed empty-output path and reject-input timing

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
…tion (lidge-jun#5775)

* fix(providers): compare rename-migration endpoints with URL normalization

Co-Authored-By: Epinephrine <luvs01@hanmail.net>

* test(providers): pin default-port normalization in rename migration

---------

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
* fix(ollama): bound pending native tool calls

* test(ollama): lower budget cap so name charges alone overflow

* fix(ollama): charge tool-name metadata to shared budget, not per-call allowance

---------

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
…lidge-jun#5762)

* fix(responses): resolve a closed wrapper from the scan's member table

Once an object closed, every later whitespace-only prefix held forever,
so a non-wrapper body's trailing whitespace never reached the client
while completion kept it — and a close plus whitespace arriving in one
chunk previewed nothing at all. Parsing the growing buffer on each
whitespace delta was also provider-controlled quadratic work.

The scan already walks every member, so record each top-level member's
name and string-valuedness (last occurrence winning, JSON.parse's own
duplicate rule) and consult the table once at the close: exactly one
string fallback field is the wrapper's value, anything else streams the
raw text byte-exact through its trailing whitespace. progressiveFreeform
Input never calls JSON.parse on the accumulated buffer anymore — the
classification is entirely the scan's own bounded work — and the 'parse'
flag on hold is gone with it.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(responses): reject a closing brace after a top-level comma

A comma promises another member, so the scan must require a member name
rather than accepting a closing brace as the object close. A trailing
comma is not a completed object: JSON.parse rejects it and completion
hands the text back unchanged, while the member table would have
unwrapped the preview. Require the next non-whitespace character after
a top-level comma to open a member name, matching the nested-member
rule, and cover the case in the fallback-keys test.

---------

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(anthropic): bound retained image position keys

* fix(anthropic): order image-key cache clearing and bound position memory lifetime

* fix(anthropic): keep invalid media types distinct and snapshot emitted positions

---------

Co-authored-by: luvs01 <luvs01@users.noreply.github.com>
Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
Remote Link stack layer, squash-merged into dev at the maintainer's request so the stack can be reviewed on dev. Exact-head CI at 8c41cec: all 23 checks passed.\n\nPlan and audits: devlog/_plan/260925_remote_home_child_link/.
Remote Link stack layer, squash-merged into dev at the maintainer's request so the stack can be reviewed on dev. Exact-head CI at 093e1aa (before the restack onto dev): all 23 checks passed. Restacked onto dev after the parent squash with an identical diff.\n\nPlan and audits: devlog/_plan/260925_remote_home_child_link/.
…jun#5801)

Remote Link stack layer, squash-merged into dev at the maintainer's request so the stack can be reviewed on dev. Exact-head CI at 767dcda (before the restack onto dev): all 23 checks passed. Restacked onto dev after the parent squash with an identical diff.\n\nPlan and audits: devlog/_plan/260925_remote_home_child_link/.
…idge-jun#5803)

Remote Link stack layer, squash-merged into dev at the maintainer's request so the stack can be reviewed on dev. Exact-head CI at a0a5a24 (before the restack onto dev): all 23 checks passed. Restacked onto dev after the parent squash with an identical diff. Security review of the link routes is still owed after merge.\n\nPlan and audits: devlog/_plan/260925_remote_home_child_link/.
Remote Link stack layer, squash-merged into dev at the maintainer's request so the stack can be reviewed on dev. Exact-head CI at 2b47b70 (before the restack onto dev): all 23 checks passed. Restacked onto dev after the parent squash with an identical diff.\n\nPlan and audits: devlog/_plan/260925_remote_home_child_link/.
Co-authored-by: Ingwannu <ingwannu@users.noreply.github.com>
…5818)

Remote Link stack layer, squash-merged into dev at the maintainer's request so the stack can be reviewed on dev. Exact-head CI at 30ff19b: all 24 checks passed. Two GUI commits followed without a fresh CI run at the maintainer's request (CI backlog): the sheet opens centered on desktop, and the SSH alias field uses the shared .input and .field-label styles. Before the merge, the restacked head was checked locally on top of dev: tsc, structure:check, 285 link and gate tests, 41 Remote Link GUI tests, and lint:i18n all passed. Security review of the SSH join, key handling, and the revoke change is still owed after merge.\n\nPlan and audits: devlog/_plan/260925_remote_home_child_link/.
…idge-jun#5802)

* fix(catalog): stop routed rows inheriting the template's comp_hash

Routed rows are cloned from whichever native row a rebuild picks as the
template, and they kept its comp_hash. The template can change between
rebuilds that touch nothing routed, and Codex compacts a thread whenever
the comp_hash of consecutive turns differs, so every active routed thread
compacted on its next turn.

The clone now drops comp_hash beside the context window, and
normalization gives the row the "opencodex" marker. Codex-forward
capability aliases and account-bound native rows keep the native value.

Closes lidge-jun#5796

* fix(catalog): reset comp_hash on routed rows kept from disk

A provider whose discovery is degraded keeps its routed rows from the
catalog on disk. Those rows skip deriveEntry, so one written before the
previous commit could still carry a template's comp_hash until the
provider recovered.

The merge now sets "opencodex" on the opencodex rows it keeps. Custom
rows, Codex-forward aliases included, are rebuilt from config and never
reach that pass, and rows written by other tools keep their own value.
…idge-jun#5822)

Moves the freeform-tool lookup lidge-jun#5804 added out of openai-chat.ts so the adapter is back at its 822-line cap and dev's file-size ratchet passes. No behavior change. Squash-merged without waiting for PR CI at the maintainer's request; locally: file-size ratchet plus 29 openai-chat/chat-compat/MiMo test files (462 pass), tsc, structure:check, privacy:scan.
…only outside quotes) (lidge-jun#5787)

* fix(omp): allow quoted hashes in managed YAML

* fix(integrations): only open YAML quote mode where a scalar may begin

Co-Authored-By: Epinephrine <luvs01@hanmail.net>

* fix(integrations): carry YAML scalar state across lines in the owned-range comment scan

Co-Authored-By: Epinephrine <luvs01@hanmail.net>

* fix(integrations): reset scalar state per sequence item and keep separator blanks

- A '- ' indicator opens a new node: carrying scalarStarted across it made a
  ' #' inside a later quoted item read as a comment and refuse the patch
- A blank after a plain scalar folds only when deeper content follows; a
  shallower next line means the blank is a separator and stays outside the
  leaf range instead of being deleted on refresh/remove

Co-Authored-By: Epinephrine <luvs01@hanmail.net>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…est sandbox (lidge-jun#5830)

Keeps a developer's live OpenCodex credentials (OPENCODEX_API_AUTH_TOKEN, OPENCODEX_ADMIN_AUTH_TOKEN, OCX_API_TOKEN_FILE) out of the test sandbox, and skips POSIX mode-bit checks on Windows in two link tests. Found by running the CI Windows leg sequentially on a Windows 11 machine with OpenCodex installed; every file that failed there passes on this branch with the token still set, and a clean rerun passed shards 1-4 (12,739 tests). Squash-merged without waiting for PR CI at the maintainer's request.
Resolve 19 conflicts against 82 dev commits, keeping both sides:
- combos: NormalizedComboTarget carries dev's lastResort (lidge-jun#5691) next to
  the PR's reasoningEfforts; resolve.ts uses the normalized type
  throughout; core-combo eligibility keeps JEV exclusion and dev's
  protocol-lane gate.
- JEV choices honour cooldownWaitPolicy "before-last-resort": lastResort
  targets are withheld while a normal target is offered (new e2e test).
- GUI: keep dev's optional apiBase (path preview only when set); JEV
  stats falls back to same-origin.
- docs tables merged row by row; request-log, config types, tests and
  test-layout are unions.

Also fix the PR's own gate failures: drop the screenshot committed under
the retired docs-site/public/pr-screenshots, move JEV structure notes so
dashboard-and-usage.md stays within 600 lines, and sync the JEV README
section into all seven locales with refreshed manifest hashes. Document
per-request routing's prompt-cache trade-off and the lastResort rule.

Co-authored-by: kingkej <kingkej@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Verified the integration against TypeSafe's published API docs
(endpoint, Bearer auth, body shape, jev-latest, answers/usage fields all
match). Document what the docs do not promise: no fixed retention period
for submitted state, ZDR only on enterprise plans, and English as Jev's
most accurate language. The jev preset brings the registry to 99
presets (82 key-based); update every guide, quickstart and the ops
record that states the split.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.