Commit Graph

1085 Commits

Author SHA1 Message Date
Peter Steinberger
83a4208aed fix(codex): full-auto approvals survive relay unavailability, typed failure classification, usage line after fallback (#108626)
* fix(codex): full-auto approvals survive relay unavailability, typed failure classification, usage line after fallback

- full-auto (approvalPolicy never + danger-full-access) exec approvals no
  longer get declined when the native hook relay is unreachable BEFORE
  invocation; an invoked relay's explicit deny, malformed output, or nonzero
  exit still fails closed (#107447)
- startup timeout/abort and request-timeout classification use typed error
  discriminants instead of message prose; EPIPE detection walks error causes;
  compaction keeps the message-based thread-not-found gate because codex-rs
  exposes no dedicated code (its own contract test asserts the message) and
  the generic -32600 would over-match unrelated invalid requests (#99270)
- /status keeps the Codex usage/quota line for sessions whose persisted
  agentHarnessId is codex even when the effective runtime fell back to
  OpenClaw Default; never-codex sessions remain excluded (#105184)

* chore(codex): keep startup error reason type module-local
2026-07-15 22:12:35 -07:00
Peter Steinberger
513200125d feat(channels): render live plan checklists from typed update_plan snapshots (#108597)
* feat(channels): render live plan checklists from typed update_plan snapshots

Codex, Copilot, CLI, and embedded update_plan events now carry typed
{step, status} snapshots end to end instead of flattened strings. Slack,
Discord, Telegram, Matrix, and MS Teams render a live checklist in
progress drafts; Slack native task cards show the real plan with
position-keyed rows and id reconciliation. The embedded update_plan tool
is default-on for every model (tools.experimental.planTool: false opts
out). The shipped onPlanUpdate steps: string[] SDK field stays populated
during a deprecation window alongside the canonical planSteps.

* fix(auto-reply): align plan bridge types with SDK callback contract

* fix(auto-reply): split agent event bridge module and fix plan type boundaries

* fix(channels): satisfy oxlint on plan checklist helpers
2026-07-15 22:00:21 -07:00
Peter Steinberger
7f9d519fcb fix(ci): repair provider fold validation (#108564)
* fix(ci): repair provider fold validation

* fix(qa): model debugger web entry
2026-07-15 19:49:02 -07:00
Peter Steinberger
d42dfed3f2 chore(codex): format usage module, fix marker import in test 2026-07-16 03:06:48 +01:00
Peter Steinberger
7864a6e6ad fix(codex): import ProviderUsageSnapshot from provider-usage 2026-07-16 03:06:47 +01:00
Peter Steinberger
7eeb1096db fix(codex): re-home app-server usage reporting on the harness seam
The deleted text provider's usage hook was the only source for the /status
Codex subscription usage line. Harnesses can now contribute an optional
usage snapshot (provider hooks keep priority; only distinct synthetic hook
owners fall through), and the codex harness reports app-server rate limits
via account/rateLimits/read with the same conversion and account identity
as before. No text provider resurrected; deadcode and SDK surface gates
clean.
2026-07-16 03:06:47 +01:00
Peter Steinberger
6bcb561012 fix(codex): repair identity-fold CI fan-out
- null-vs-undefined runtime record type at the provider-move helper
- gateway models.list fixtures expect the new agentRuntime intent field
  (codex/implicit for policy-backed OpenAI routes, openclaw/implicit for
  synthetic routes without provider policy)
- split doctor cron legacy-repair into its own module to satisfy the
  max-lines gate without suppressions; callers import directly
2026-07-16 03:06:43 +01:00
Peter Steinberger
3c8269ca52 refactor(codex)!: fold the codex text provider into openai with a doctor migration
The live codex text provider was a redundant projection of the openai
catalog (exclusive provider ownership; the openai plugin's ChatGPT OAuth
discovery already serves gpt-5.6-* route-aware). Folding it:

- extensions/codex no longer registers a text provider, catalog entry, or
  synthetic text auth; provider.ts/provider-catalog.ts/provider-discovery.ts
  and the route-blind model-name heuristics are deleted; the narrow
  post-harness reasoning fallback moves to an app-server-owned module
- openai thinking policy keys on explicit selected-route provenance
  (api === openai-chatgpt-responses) instead of value-shape inference
- models.list gains an optional additive agentRuntime field (configured
  intent); session agentHarnessId remains the execution proof
- doctor --fix migrates the shipped codex/* config shape end to end:
  every model slot, provider-config merge with blocker-aware conflict
  handling, sessions, cron payloads (two-phase: runtime policy persists
  before cron refs rewrite), transcripts; migrated refs carry model-scoped
  agentRuntime.id=codex preserving the shipped wizard semantics; auto
  runtime policies normalize to codex with sibling fields preserved;
  blocked provider conflicts retain the whole legacy namespace fail-closed
  with an actionable warning
- the stale openai:default profile cleanup (#91352) was deliberately
  deferred to a follow-up after review showed it needs per-agent identity
  proofs; doctor keeps warning about unusable profiles

Fixes #105561
Fixes #84637
Fixes #90420
2026-07-16 03:06:43 +01:00
Josh Avant
8e6f966482 fix(codex): continue turns after progress replies (#108487)
* fix(codex): defer omitted source reply finality

* test(codex): refresh source reply prompt snapshots
2026-07-15 16:27:28 -07:00
Peter Steinberger
8aa2392003 refactor(deadcode): harden unused export coverage (#108484) 2026-07-15 15:49:30 -07:00
Peter Steinberger
28d30e9dae ci: stabilize release validation tests (#108420)
* test(codex): remove turn-watch timing race

* ci: pin workflow sanity shellcheck

* ci: run workflow sanity on blacksmith

* ci: serialize workflow sanity lint

* ci: bound workflow lint stalls

* ci: cap actionlint process fanout

* ci: report stalled workflow shellcheck

* ci: stabilize release validation checks

* ci: restore release workflow shellcheck

* test: preserve codex turn watch reset proof
2026-07-15 13:22:31 -07:00
Peter Steinberger
ff8a015981 test: tighten additional async polling (#108450) 2026-07-15 13:14:35 -07:00
Peter Steinberger
b4b6afadd3 refactor(codex): split app-server thread lifecycle (#108414)
* refactor(codex): split thread lifecycle

* refactor(codex): keep lifecycle types internal
2026-07-15 11:23:47 -07:00
Peter Steinberger
09ce4afd16 test(codex): bound guarded shared-client requests (#108363) 2026-07-15 08:39:23 -07:00
Peter Steinberger
9d4610cbd1 fix(codex): settle plugin activation, align plugin/list with codex 0.144, bound discovery per turn (#108311)
* fix(codex): settle plugin activation, align plugin/list with codex 0.144, bound discovery per turn

- plugin/list curated queries omit cwds and marketplaceKinds (0.144 semantics:
  explicit kinds disable the automatic global remote catalog; cwds:[] never
  suppressed it), and the missing-marketplace check recognizes the current
  openai-curated-remote wire name via the shared predicate (#107305)
- curated plugin/list snapshots settle in a process-local metadata cache
  (coalesced, invalidated on install/identity change/restart, 1h freshness
  window matching the app-inventory cache) so a missing marketplace or plugin
  no longer re-runs blocking discovery RPCs on every embedded-Codex turn;
  fail-open local-only responses (upstream warns without a load error when the
  remote catalog fetch fails) are never cached, and workspace-directory
  queries stay live because external activation has no invalidation signal
- the whole plugin-config build shares one bounded startup deadline with
  remaining-budget propagation per RPC and a deny-all apps fallback, so a hung
  plugin/list cannot consume the turn (#107305)
- guarded thread requests (start/resume/fork under the native-config fence)
  must carry a finite timeout or abort signal, closing the unbounded-fence-hold
  window for raw callers (#106719 hardening)

* chore(codex): keep plugin metadata types and deadline builder module-local

Deadline behavior tests exercise the production provider composition instead
of a test-only export.
2026-07-15 06:40:29 -07:00
marchpure
69ef3ca980 fix(codex): make loop relay optional (#97224)
Move the Codex-specific PreToolUse loop relay switch into the Codex
plugin, preserve policy relays, and cover both normal and side turns.

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: marchpure <marchpure@users.noreply.github.com>
2026-07-15 05:29:20 -07:00
Peter Steinberger
1a27e7f3ec fix(codex): model-scoped usage-limit blocks, structural 429 classification, no silent API-key billing (#108254)
* test(codex): use allowlisted placeholder for auth-bridge api-key fixture

* fix(codex): model-scoped usage-limit blocks, structural 429 classification, no silent API-key billing

- usage-limit blocks written from Codex rate-limit resets are model-scoped via
  a persisted blockedScope marker: healthy sibling models on the same auth
  profile stay usable; a different/unknown model failing widens the block
  profile-wide and never narrows back; legacy rows without the marker stay
  profile-wide until they expire (#100556)
- Codex usage-limit failures now surface as status-429 Error objects at both
  ingress paths (turn-start and streamed turn failure, wrapped at the event
  projector), so core failover classification is structural instead of
  matching message wording; profile blocking uses only rate-limit data whose
  revision advanced during the turn
- usage-limit detection requires the structured codexErrorInfo signal; the
  over-broad "usage limit" substring match that misclassified unrelated
  errors as subscription limits is gone (#96815)
- subscription/OAuth routes can no longer silently fall back to env/auth.json
  API keys: ambient key fallback is restricted to explicit api-key routes,
  native-auth subscription routes verify the account is chatgpt-backed via
  account/read, and shared app-server clients are partitioned by auth
  requirement so pooled clients cannot cross billing modes (#106375)
- integrated e2e regression: usage-limit promptError -> same-model sibling
  profile rotation -> model fallback with reason rate_limit

* chore(codex): keep CodexUsageLimitErrorResult type local
2026-07-15 04:10:57 -07:00
Peter Steinberger
6eda184f27 refactor: simplify native session executable resolution (#108169) 2026-07-15 01:49:45 -07:00
Peter Steinberger
2afa9de438 fix(codex): structured abort detection, tool-schema repair, native-result middleware relay (#108105)
* fix(codex): use structured turn status for aborts, repair tool schemas, relay native results to middleware

- turn aborts are detected from the correlated turn/completed status instead
  of byte-matching private codex-rs prose; the <turn_aborted> marker remains a
  non-terminal user-interrupt hint (tags only, wording-independent) because the
  app-server collapses all abort reasons into "interrupted" (#99268)
- dynamic-tool schemas are repaired before projection via the shared OpenAI
  normalizer: annotation nulls stripped, type:null inferred from object/array
  shape hints; unrepairable null constraints stay quarantined instead of
  widening the schema (#106277, #97913)
- Codex-native tool results now flow through agentToolResultMiddleware at the
  post_tool_use relay boundary (observe-only: the Codex PostToolUse contract
  cannot replace a native tool response) (#95597)

* test(codex): regenerate prompt snapshots for normalized dynamic-tool schemas

The shared OpenAI strict-compat normalization now runs on Codex dynamic tools,
so empty object schemas gain additionalProperties:false and required:[] in the
snapshot payloads, matching what the OpenAI provider family sends.
2026-07-15 00:51:24 -07:00
Yuval Dinodia
7974def3fd fix(codex): restore shell for restricted turns (#92294)
* fix(codex): keep OpenClaw exec when native surface has no environment (#92238)

* chore: keep release note in PR

* fix(codex): keep shell tool type internal

Co-authored-by: yetval <yetvald@gmail.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-15 00:37:04 -07:00
Peter Steinberger
80e1509fe8 fix(codex): keep parent binding on cross-key handoff and stop foreign-transcript mirror warns (#108042)
- session_end with a provably different nextSessionKey (dashboard "New Chat",
  fork child) no longer permanently retires the still-live parent Codex
  binding; same-key rollovers, unknown-key ends, and terminal ends retire as
  before (#106778)
- mirrored session-history reads treat well-formed non-Codex transcripts as an
  empty mirror instead of a read failure, so codex harness hooks stop warning
  on every non-Codex model run; corrupted session headers stay on the warn
  path (#106556)
2026-07-14 23:50:01 -07:00
Peter Steinberger
7f1baa6d75 refactor(codex): trim session catalog exports (#108045)
* refactor(codex): privatize session catalog helpers

* chore(deadcode): refresh export baseline
2026-07-14 22:59:46 -07:00
Kyle Klouzal
2333bd59db fix: keep yielded parent turns nonterminal (#95996)
* fix: keep yielded parent turns nonterminal

* fix: type chat final stop reasons

* test: isolate yielded session reconciliation

* fix: refresh yielded lifecycle generated surfaces

* test: register Codex lifecycle test shard

---------

Co-authored-by: FullerStackDev <263060202+fuller-stack-dev@users.noreply.github.com>
2026-07-14 20:35:33 -06:00
Peter Steinberger
57d926b4fd fix: connect resumed native terminals reliably (#107688)
* fix: render resumed paired-node terminals

* fix(control-ui): connect native catalog terminals reliably

* chore: keep release notes in PR body

* fix(control-ui): require terminal reconnect cancellation

* fix(gateway): cancel timed-out terminal opens safely

* fix(control-ui): recover stalled terminal opens

* chore(ui): refresh i18n fallback baseline

* fix: preserve login shell path for resumed terminals

* refactor(plugin-sdk): avoid extra resolver export

* fix(gateway): normalize terminal open failures

* test(control-ui): split terminal readiness coverage

* docs: explain catalog terminal PATH restoration

* fix(control-ui): complete terminal readiness release gates

* fix(ci): remove unused shell resolver exports

* chore(plugin-sdk): refresh API baseline after rebase
2026-07-14 19:18:19 -07:00
Shakker
4887cf55b4 fix: classify Codex tool results through shared contract (#107807)
Successful Codex dynamic-tool results now use the shared failure classifier, preventing Skill Workshop and plugin lifecycle metadata from being persisted as failed calls.

Refs #107684.
Prepared head SHA: e5bfcdb085
Co-authored-by: Shakker <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
2026-07-14 23:24:36 +01:00
Peter Steinberger
a6a0716486 feat(setup): rename Crestodian to OpenClaw system agent
User-facing name is now OpenClaw (the system speaks); internal code name is
system-agent. Gateway methods crestodian.* -> openclaw.chat/openclaw.setup.*,
agent tool -> openclaw, reserved agent ids openclaw + retired crestodian.
openclaw setup routes: onboarding flags -> onboard, -m/--yes -> system agent,
bare configured interactive -> OpenClaw chat, unconfigured -> onboarding.
Hidden crestodian CLI and /crestodian TUI aliases kept; docs moved to
docs/cli/openclaw.md with redirect stub. macOS/Android strings in lockstep.

Refs #107237
2026-07-14 11:03:02 -07:00
Peter Steinberger
e20c029efd refactor(codex): split app-server event projection (#107680)
* refactor(codex): split app-server event projector

* fix(codex): preserve raw event projection ordering

* chore(codex): remove projector max-lines exemption

* refactor(codex): split stateful projector owners
2026-07-14 11:00:08 -07:00
Jesse Merhi
00364ee777 improve: warn before non-ClawHub plugin installs (#102197)
Merged via squash.

Prepared head SHA: e08d9e737d
Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>
Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>
Reviewed-by: @jesse-merhi
2026-07-15 03:25:36 +10:00
Peter Steinberger
f81f9d8570 chore: enforce max-lines suppression ratchet (#107315)
* ci: enforce max-lines suppression ratchet

* chore: prune stale max-lines suppression

* fix: close max-lines ratchet enforcement gaps

* fix: harden max-lines ratchet checks

* fix(ci): satisfy max-lines ratchet checks

* style: format max-lines declarations

* fix(ci): match oxlint suppression grammar

* test: isolate max-lines git fixtures

* chore: prune resolved max-lines debt

* test: skip newline path fixture on Windows

* fix: harden max-lines suppression ratchet

* chore: refresh max-lines baseline

* fix: close max-lines ratchet bypasses

* fix: derive ratchet base from PR merge tree

* fix: support older Git in staged ratchet

* fix: align max-lines declarations and baseline

* chore: refresh max-lines baseline for current main

* fix: exclude generated wizard locales from max-lines

* chore: prune resolved max-lines debt
2026-07-14 09:27:02 -07:00
pash-openai
cbbccb8952 Recover large Codex app-server messages (#107369) 2026-07-14 07:07:52 -07:00
Ayaan Zaidi
8b66fe773f feat(mcp): deliver requester-scoped MCP to shared-thread harnesses
Requester-scoped servers never enter harness-native MCP config: Codex
thread and CLI user-MCP projections partition them out (fail-closed,
static-partition fingerprints stay sender-independent so shared threads
never rotate). Codex delivers them as per-attempt dynamic tools through
a scoped-only runtime path on the same core manager, with a
session-stable advertised catalog so authed and unauthed senders share
one spec surface; unauthed calls get a clean not-connected tool error.
New SDK seam materializeRequesterScopedMcpToolsForHarnessRun lets any
future harness consume the same contract.
2026-07-14 17:09:53 +05:30
Peter Steinberger
0604903f88 fix(session-catalog): authorize paired-node reads (#107410) 2026-07-14 04:19:09 -07:00
Peter Steinberger
e488dc0012 feat(sessions): signal watchers when an adopted upstream disappears (#107356) 2026-07-14 03:51:20 -07:00
Peter Steinberger
bb6874fddf feat(sessions): upstream liveness for adopted catalog sessions (#107009) 2026-07-14 01:09:05 -07:00
Peter Steinberger
644d4c3d23 fix: explain and control native session discovery (#107162)
* fix: make native session discovery configurable

* refactor: split native session discovery helpers

* chore: keep release notes in PR body

* fix: refresh generated session protocol models

* test(ui): avoid shared lazy-element mock race
2026-07-14 00:18:18 -07:00
Peter Steinberger
69eb20871d chore(codex): update Codex CLI to 0.144.4 (#107208)
* chore(codex): update Codex CLI to 0.144.4

* fix(codex): validate interrupt params through request map
2026-07-13 23:58:19 -07:00
Peter Steinberger
6625ea92f0 refactor(codex): evaluate startup deadlines first 2026-07-13 23:40:39 -07:00
Peter Steinberger
c953d8ec41 fix(codex): gate startup phases before deadlines 2026-07-13 23:40:39 -07:00
Peter Steinberger
d8d2f83cc1 feat(terminal): open Codex/Claude catalog sessions in a terminal on their owning host
Catalog session rows (sidebar context menu + click), the built-in viewer
header, and a new "Open Codex/Claude sessions in" preference can launch the
native CLI (codex resume / claude --resume) in the operator terminal on the
machine that owns the session.

- Gateway-local sessions spawn through the existing terminal launch policy
  (sandbox/enabled gates preserved) with the resume command in the session cwd.
- Paired-node sessions run through a new seq-ordered node PTY relay: a
  duplex node-host command streams PTY output via node.invoke.progress and
  receives keystrokes/resize via a new node.invoke.input event, behind the
  unchanged terminal.* client protocol (TerminalSessionManager gains a backend
  abstraction; node relay reuses the streaming-invoke controller).
- Owner boundary: each plugin owns its resume command and builds argv from a
  validated thread id; the gateway routes node opens through the node command
  allowlist and plugin invoke policy (no advertisement-only trust), and nodes
  re-verify session eligibility before spawning.
- UI setting catalogOpenTarget + canOpenTerminal capability gate every entry
  point; capability requires the owning host to actually have the CLI.

Node PATH is normalized before command-availability probes, Windows .cmd/.bat
shims spawn via ComSpec, and catalog terminal opens reattach persisted tabs
before opening the new tab.
2026-07-13 22:20:50 -07:00
Peter Steinberger
111b3a157e refactor(codex): use native SemVer floor comparison 2026-07-13 21:42:23 -07:00
Peter Steinberger
27f2a45c54 fix(onboarding): harden live inference handoff (#107041)
* fix(onboarding): harden live inference handoff

* fix(crestodian): preserve auto runtime probes

* fix(ci): restore current main lint gates
2026-07-13 21:15:36 -07:00
Peter Steinberger
4da0eb19c5 fix(state): converge legacy startup migrations (#107002)
* fix(state): converge legacy startup migrations

Co-authored-by: Eva <eva@100yen.org>

* refactor(state): split legacy migration helpers

* fix(memory): persist legacy source acknowledgements

* fix(state): remove stale migration imports

* fix(memory): recognize numbered migration archives

* fix(matrix): downgrade archived migration residue

* fix(memory): satisfy migration lint

---------

Co-authored-by: Eva <eva@100yen.org>
2026-07-13 20:05:24 -07:00
Peter Steinberger
877af700bf feat(codex): continue paired-node Codex catalog sessions from the Control UI (#106927)
* feat(codex): continue paired-node Codex catalog sessions from the Control UI

Codex catalog rows on paired nodes were view-only. Node rows are now
continuable when the node advertises and permits the codex threads.list,
thread.turns.list, and cli.session.resume commands. Continue adopts the
session into a locked codex OpenClaw session (deterministic
harness:codex:node-session key, bounded native-history import, two-phase
initializing marker) and installs a webchat conversation binding
(codex-cli-node-session) through the new generic
bindPluginSessionConversation seam with attempt-ID guarded rollback, so
each web turn runs codex exec resume on the owning node via the existing
inbound_claim path. Local continue/archive semantics are unchanged;
archived rows are no longer offered as continuable.

* fix(plugins): serialize plugin session binds per session

Review P2: the bind rollback checked the attempt id and then awaited the
unbind, so a concurrent Continue could install a newer binding between the
two and lose it to the older attempt's rollback. All session binds for one
session key now queue through an in-process tail, so a failing attempt can
only ever roll back its own binding; the attempt-id guard stays as defense
against out-of-band rebinds.

* refactor(codex): extract node-continue and session-bind modules for the LOC ratchet

Pure movement to satisfy the changed-file TypeScript size ratchet: the
paired-node continue flow moves to session-catalog-node-continue.ts and
session-catalog-node-adoption.ts, catalog paging/parsing helpers to
session-catalog-parsing.ts, the Control UI session-bind seam to
session-conversation-binding.ts (+ session-key helpers), and the internal
conversation-id/channel-prefix helpers to utils. transcript-mirror.ts is
restored to main byte-for-byte; the node history builder constructs a plain
CodexThread (only id is required) instead of widening signatures.

* fix(plugins): satisfy preserve-caught-error in the session-bind rollback

* fix(codex): gate node continue on operator.admin and resume by CLI session id

Second review round: (1) bound node turns pass canMutateCodexHost only for
owners/admins, while sessions.catalog.continue is operator.write — a
write-scoped Control UI client could adopt a node session whose every turn
would then be rejected. The gateway now forwards the caller's scopes to the
provider (SessionCatalogContinueProviderParams.clientScopes) and codex fails
node continues closed without operator.admin, before the dedupe join so a
non-admin cannot ride an admin's in-flight operation. (2) The node binding
stored the app-server threadId, but codex exec resume takes the CLI session
id and forked threads share a session tree where the two differ; the binding
now prefers record.sessionId.

* fix(codex): defer node-session restore until the binding is durable

Third review round: continuing an archived adopted node session unarchived
it before the gateway installed the conversation binding, so a failed bind
left a visible session with no node routing. The unarchive now rides
afterConversationBound; finalizeNodeAdoptedSession already covers both the
initializing and finalized marker states, so the eager restore helper is
deleted.
2026-07-13 19:54:31 -07:00
Peter Steinberger
5c9e09af3a style(codex): format prompt projection 2026-07-13 15:32:59 -07:00
Peter Steinberger
51fece4960 fix(codex): preserve failure-path ownership 2026-07-13 15:32:59 -07:00
Peter Steinberger
323a9fbe29 refactor(codex): split app server run attempt 2026-07-13 15:32:59 -07:00
Peter Steinberger
4319ddbe8c feat(control-ui): import Codex and Claude Code memory (#106406)
* feat(control-ui): import coding assistant memory

* test(migrate): clean memory import temp dirs

* chore: move memory import note to PR body

* build: refresh memory import generated artifacts

* fix(control-ui): complete memory import checks

* build(control-ui): localize memory recovery labels

* fix(control-ui): harden memory import recovery

* refactor(migrate): keep memory import surfaces bounded

* fix(control-ui): use canonical agent row type

* fix(codex): drop dead migration type exports

* fix(migrate): restrict imported memory permissions

* fix(control-ui): preserve memory import recovery state

* fix(control-ui): retain memory import results

* build(control-ui): preserve translation memory history

* fix(control-ui): bind memory import state to agent

* fix(control-ui): unlock memory import after refresh

* test(gateway): preserve memory method suffix

* fix(migrate): bind reviewed memory imports

* fix(migrate): make memory imports retry-safe

* perf(ui): keep memory import lazy

* build: refresh generated artifacts after rebase

* chore: keep migration runtime within LOC guard

* build: refresh Swift protocol model
2026-07-13 15:30:06 -07:00
Peter Steinberger
db02a96c4c refactor(process): route bounded commands through Execa (#106495)
* refactor(process): centralize bounded command execution

* refactor(process): migrate core one-shot commands

* refactor(plugins): migrate one-shot commands

* fix(process): await Windows tree termination

* chore(plugin-sdk): refresh process runtime surface

* refactor(process): migrate remaining bounded commands

* refactor(process): normalize command result handling

* refactor(process): split execution responsibilities

* chore(plugin-sdk): refresh API baseline

* chore(process): remove release-owned changelog entry

* fix(process): narrow binary command input checks

* fix(process): cap sandbox command output

* fix(qa-lab): preserve exact node probe env

* chore(ci): refresh dead export baseline

* fix(process): preserve force-kill command deadlines

* fix(process): avoid post-exit timeout reclassification

* test(process): update scp staging wrapper mock

* test(process): update remaining wrapper mocks

* refactor(qa-lab): preserve Execa tar execution
2026-07-13 11:07:35 -07:00
Peter Steinberger
e8290c699e refactor(codex): split app-server attempt helpers (#106550)
* refactor(codex): split app-server attempt helpers

* fix(codex): mark harness imports type-only
2026-07-13 09:58:01 -07:00
Peter Steinberger
fc4b6a4254 feat(codex): show the account email with app-server usage windows (#106500)
* feat(codex): read the account email with app-server usage

The Codex-harness usage snapshot now carries the account identity: the
usage fetch runs account/rateLimits/read and account/read over one
app-server session (new withCodexAppServerJsonClient seam, which the
single-request helper now delegates to), so the email is guaranteed to
belong to the same account as the windows. Identity stays best-effort;
rate limits survive an account read failure.

* style(test): scanner-safe app-server marker fixture

* test(codex): keep scanner-neutral hunks around app-server marker literals

* fix(codex): bound the best-effort account read within the usage deadline

Review P2: account/read shared the outer usage deadline, so a slow or hung
identity read could reject the whole snapshot with a timeout instead of
returning the already-fetched rate-limit windows. Race the account read
against a local timer bounded to min(4s, usageTimeoutMs/3) and drop the
identity on timeout; a regression test hangs account/read and asserts the
windows still return.

* fix(codex): send account/read params and bound identity by the remaining deadline

Second review round: account/read (GetAccount) requires a params object per
the app-server protocol, so send an empty {} (refreshToken defaults false);
without it a real app-server rejects the request. Bound the best-effort
identity read by the time left before the shared usage deadline (minus a
margin) instead of the original budget, so a slow rate-limit read can no
longer let the identity read trip the outer timeout and discard the
already-fetched windows.

* fix(codex): reserve the isolated shutdown budget in the usage deadline

Third review round: withCodexAppServerJsonClient awaits the isolated
client's closeAndWait inside the outer timeout, so a hung account/read
could reach the deadline during force-kill/exit cleanup and discard the
already-fetched windows. The usage read now passes a cheap isolatedShutdown
(force-kill 200ms + exit 300ms) and the identity bound reserves that plus a
250ms margin (750ms) of the remaining deadline, so cleanup always finishes
before the outer timeout.

* style(codex): rename scoped-request generic to avoid shadowing
2026-07-13 09:56:47 -07:00