Repository navigation
fix(ui): let New project choose a folder without a custom name - #4
Closed
Master-Frank wants to merge 56 commits into
Closed
Master-Frank wants to merge 56 commits into
Master-Frank wants to merge 56 commits into
Conversation
…st only (apache#5985) The health-probe test used one service with probeTimeoutMs: 100 for both the normal HEAD-to-GET fallback and the deliberately stalled request. The budget covers the whole probe, so the fallback's two round trips also had to finish within 100 ms; on a loaded runner the /ready probe timed out (18 of 100 runs under 4x CPU oversubscription locally, 0 of 100 after). Check the fallback with the default probe timeout and keep the 100 ms budget for the stalled request it is meant to bound. Product health-check code is unchanged. Generated-by: Codex test(runtime-host): bound the health probe fallback check at 5 s The fallback check used the 30 s production default, so a regression that hung the GET fallback would stall the test for 30 s before failing. A 5 s budget still sits far above any load-induced latency.
…ailure (apache#5984) WslProcessByteStream forwarded only the ChildProcess error event to the framed transport's failure listener. The bridge's stdin and stdout emit their own error events (EPIPE after wsl.exe dies, a destroyed stream), and nothing listened for them, so a broken bridge pipe escaped as an uncaught exception instead of failing the connection attempt. Route stdin and stdout error events through the same listener. The transport fails once and the connect call rejects with handshake_failed, like the existing cancellation and oversized-stderr paths. stderr is read through an async iterator that already absorbs its errors. Generated-by: Codex test(runtime-host): cover a real WSL bridge EPIPE on a pending write The existing cases destroy a bridge pipe with no write pending. In production the common shape is a reader that goes away while the handshake is being written, where Node reports EPIPE to the write callback and also emits a stdin error event. On main that event escapes uncaught even though the write callback fails the transport. The new case closes the bridge's stdin before connecting, so the handshake write hits a real EPIPE. It fails on main and passes with the stream error routing. The pipe-error cases now use the 10 s handshake budget of their siblings.
…pache#5972) Limit Candidate cleanup to preparation before Kernel.start takes ownership. Keep the root owner held after startup cleanup hits the fail-stop deadline, and cover preparation failure, clean recovery failure, and late cleanup. Generated-by: Codex fix(runtime-host): drop unreachable Candidate authority cleanup The Candidate's preparation catch also closed the access authority, but opening it is the last fallible preparation step. When the open rejects there is no authority to close, and once it resolves only the options literal runs before Kernel.start takes the authority and owns its cleanup. Remove the dead close and note the ordering at the open, so a later edit does not add a fallible step after it. fix(runtime-host): keep Kernel-retained root owned in service startup startExecutionRuntimeHostService closed the State Root owner on every startup failure, including after RuntimeHostKernel.start had taken it. When Kernel cleanup overruns the shutdown deadline, during startup or in the post-start peer-termination close, the Kernel deliberately keeps the owner until process exit, so the service released a root while the composition could still be closing. Release the owner only for failures before Kernel.start, as the Candidate does. Peer endpoint and mesh cleanup stays, since the Kernel adopts those only once its listener set exists. Run the Candidate's clean recovery failure and deadline overrun tests against the service too, and cover a service preparation failure releasing the root.
…pache#5974) Exercise the reader Retry callback through the observation lifecycle and real transcript controller. Cover initial recovery failure, repeated Retry, session handoff, observation replacement, and unmount. Generated-by: Codex fix(desktop): retry history through the active observation Keep the observation controller available before the first transcript publication so Retry can recover after the initial read and automatic recovery fail. Fence retry admission and late errors by session selection and observation identity. Generated-by: Codex fix(desktop): report a failed transcript Retry once The range controller's reload() hands a failure to its recovery, which reports it through the observation's onError (the "Failed to load task" toast and read error), and then rethrows. retryMessages reported the rethrown error again as a refresh failure, so one failed Retry raised two toasts and replaced the read error with the refresh message. Leave the report to the controller, as its own gap and recovery reloads do, and only release the pending Retry. The controller still withholds a reload that lands on the cached transcript, so Retry stays quiet then too. refreshMessages never calls reload() and keeps its own report. The retry test now records error toasts and checks that a failed Retry raises exactly one, keeps the read error, and that a successful Retry raises none. fix(desktop): answer a failed Retry over the cached transcript The range controller does not report a failed reload while it holds the cached transcript Main serves during Host reconnection. Since Retry left reporting to the controller, a Retry clicked there (for example after a refresh had set a load error) failed with no feedback at all. Expose that state as holdsCachedTranscript() on the range controller and its conversation port, reusing the controller's own cached check. When reload() rejects, retryMessages now reports the refresh error itself only if the controller holds the cached transcript and the observation is still current and selected. Every other failure is still reported once, by the controller's onError. The retry test can now answer a read with a cached snapshot. It shows a failed Retry over that snapshot raising one refresh toast, alongside the existing single load toast for the live case. The other conversation test fakes return false for the new method.
…5976) Track initial acquisition alongside reconnect work and complete closed only once all owned cleanup has settled. Register tasks before callbacks can reenter, and keep explicit cancellation out of the fatal error path. Close Desktop candidates that fail admission before handoff, and prevent removed target generations from reactivating or publishing stale failures. Generated-by: Codex test(desktop): cover a replaced Local generation's late failure The ownership guards were only exercised with the manager closed. The initial Local start is not a serialized target mutation, so once it marks its generation invalid, retryLocalStart can replace that generation while the old #markUnavailable still waits on observation teardown. Hold that teardown open from the startCandidate seam, let the retry reach ready, then release the old generation. Its epoch stays inactive and its late unavailable state is not published over the replacement. Without the #publishState ownership guard, the old generation publishes unavailable after the replacement is ready.
… times (apache#5975) Generated-by: Codex fix(runtime-host): stop delivering waiting notifications after expiry A notification fire waiting for a Desktop provider kept its claim after its task expired. The scheduler then polled every five seconds for as long as no provider appeared, and a provider that connected later, or a Host recovering the claim, still delivered the reminder after expiresAt. Expiry already closes due-time and Trigger Now admission, so a native fire that has not crossed delivery admission now settles as blocked once its task expires, which also ends the poll. A once task completes with that blocked run, as an incognito-blocked fire does; a recurring task ends expired. Trigger Now refreshes the retry schedule after persisting a waiting claim. A Store read failure there replaced the provider-unavailable outcome with a generic persistence failure. The refresh failure now drains the Host, whose recovery retries the durable claim, and the caller still receives the provider-unavailable outcome. Tests cover expiry of once and interval notifications, recovery after expiry, the Trigger Now refresh failure, and the next slot of a recurring notification delivered late. test(runtime-host): pin expiry edits replacing a waiting notification The expiry check for a waiting native fire reads the task snapshot held by its claim. That snapshot cannot hold a stale expiresAt: the Store rejects every task edit while a claim exists, and an update first cancels a fire that is still waiting for a provider. The edited task is then claimed again with the new expiry. Cover shortened, added, and extended expiry during a provider wait. A shortened or added expiry blocks the next claim at the new deadline without a late delivery. An extended expiry delivers once a provider connects after the original deadline. With both edit guards removed, all three cases fail because the old claim keeps its stale snapshot. test(runtime-host): cover recurring trigger and bot notification waits Trigger Now on an interval notification without a provider now has coverage. The caller gets the provider-unavailable outcome. The claim retries every five seconds while its wait spans a regular slot, which adds no second claim. After one delivery the task resumes at the next regular slot without catching up. A due bot notification waits for a provider like a local one and is then delivered once through notify_bot with its body, platform, and chat. A stored bot task whose platform has no bot delivery, which create rejects, is blocked at its due time instead of waiting, and a provider that connects later delivers nothing.
…che#5973) Preserve stable identities and source order while SQLite allocates target-local tool journal and message admission keys. Cover populated and fresh imports, cancellation identity, and rollback/retry after a later stable identity conflict. Generated-by: Codex test(storage): derive the import's local-sequence guard from the schema LOCAL_SEQUENCE_COLUMNS is hand-maintained. A later Session table keyed by an INTEGER rowid would be copied verbatim by the import and collide only when importing into a populated workspace, with nothing failing in CI. The new test exports a real Session bundle, migrates a target the way the import opens it, and walks every table the merge copies. Each one keyed by a single INTEGER column must be reallocated through LOCAL_SEQUENCE_COLUMNS or listed in the test's PORTABLE_INTEGER_KEYS with a reason; that allow-list is empty today. A listed column that is not the table's key also fails. So the test reads the merge's own answer rather than a copy of it, the table selection in mergeAttachedBundle moves unchanged into the exported listSessionBundleMergeTables, which the merge now iterates. test(runtime): prove the import's ORDER BY keeps local sequence order tool_journal_events.journal_seq and message_admissions.sequence alias the rowid, so a scan of the attached bundle returns rows in sequence order however they were written. The existing order tests therefore pass with the import-side ORDER BY removed, and rewriting the bundle rows out of order cannot change that. The new test turns on PRAGMA reverse_unordered_selects on the connection the import borrows, imports into a populated workspace, and checks that both tables keep the source order with sequences allocated after the target's own. Without the ORDER BY, either table comes out reversed. An unchanged PRAGMA data_version confirms the import committed through that connection, so the test cannot pass vacuously if the import stops sharing it. Merge remote-tracking branch 'upstream/main' into fix/session-bundle-local-sequences # Conflicts: # packages/storage/src/__tests__/session-bundle-policy.test.ts
…e#5986) Pipe-mode commands are spawned detached, so each leads its own process group and nothing stops it when the Host dies without running cleanup (SIGKILL, crash, OOM kill). The command is reparented and keeps writing to the workspace with no owner left to stop it or record its result. Start each bounded and background pipe command through a small owning supervisor (owned-process-main.js, launched with process.execPath, as Electron in Node mode under Desktop). The supervisor leads the process group, spawns the command into it with the Host's stdio and descriptor payloads inherited directly, and holds a private IPC channel to the Host as a lifetime lease; when the channel disconnects it SIGKILLs its tree. Host-initiated signals still reach the group once, and the command's exit code or signal is mirrored, including SIGPIPE and SIGUSR1, which Node would otherwise ignore or repurpose. Keep the shell run's reported pid the command's own, so `kill <pid>` behaves as before; group signalling uses the supervisor. Require the supervisor entry in CLI release artifacts. Each running pipe command now costs one extra process: about 26 ms per command under Node and 75 ms under Electron on an idle Apple Silicon machine, and 13-15 MB of physical footprint while it runs. Generated-by: Codex Generated-by: Claude Code ci(windows): follow the win32 branch into owned-child-process The Windows recovery path filter must equal the win32-branching closure of the suites that lane runs. The platform branch for spawning pipe-mode commands moved from shell-exec.ts and pipe-process-driver.ts into owned-child-process.ts, so the filter now lists that module instead. fix(runtime): hold supervised command output until admission A supervised command writes to the Host's pipes directly, while its admission arrives over the supervisor's IPC channel, so the Host could read output before `ready` resolved. A foreground Bash aborted on its first output then failed startup with an AbortError instead of returning a cancelled result, as seen on Linux CI. With a direct spawn the spawn event always preceded any output. Pause stdout and stderr until admission has been observed. Release them in the check phase after `ready` resolves, or when startup fails or the supervisor exits. The workspace executor abort test now aborts on the command's first output instead of after a fixed 100 ms, which also had to cover the supervisor's startup on a loaded runner. fix(runtime): harden the command supervisor's exit, signals and launch After the supervisor exits without reporting, its PID may be reaped and reused, so walking its tree could reach unrelated processes. Signal only its POSIX process group, which cannot be reallocated while members remain, and skip taskkill on Windows. Decide such an exit once the IPC channel has drained rather than on `exit`, and report a normal exit without a result as an integrity error instead of the command's status. The command shares the supervisor's process group, so a script that signals its own group could end the supervisor or start its inspector. Ignore HUP, USR1, USR2, QUIT and ALRM in the supervisor on POSIX. Spawn the command in the check phase after the launch message, so a group stop pending in the same turn is handled before the command starts. Tests cover a script trapping and sending group signals, a lost lease, and a setsid descendant of a live command on owner death. ci(windows): run the shell command ownership suites on Windows Every Windows Bash command now runs under the owning supervisor, but no Windows lane ran its suites. Add owned-child-process, shell-owner-death, pipe-process-driver and shell-exec to windows_recovery, and list their Windows-branching test sources in the lane's path filter. fix(runtime): detach the Windows supervisor and keep forced exits quiet The first Windows run showed two problems. On Windows the Host's forced stop is taskkill, which ends the supervisor with an ordinary exit code. Treating every non-zero exit without `completed` as a lost result turned timeouts and aborts into integrity errors. Only a clean exit without a result is reported now. libuv puts non-detached children in a job that is killed with their parent, but not their own children. A non-detached supervisor therefore died with the Host before it could stop anything, and a shell root's child survived, as on main. Detach the supervisor on every platform. It now outlives the Host long enough to stop its whole tree; the command stays in the supervisor's job. Add a `wrapped` owner-death case, a shell root running the script as its child, which fails on main. Skip the stop-requested variant on Windows, where a stop is an immediate forced kill. Accept EOF for a broken stdin pipe on Windows. Drop shell-exec from the Windows lane: its suite uses POSIX shell syntax throughout and fails on Windows without this change. fix(runtime): report supervisor faults and pin the Windows ownership lane A `failed` message means the supervisor is already exiting on its own, so a tree walk from its PID could start after it is reaped. Signal only its process group on that path, as after an exit. On POSIX the Host's own stops end the supervisor by signal, so an exit code without `completed` can only be a supervisor fault. Report it as a lost result there, rather than as the command exiting with that code. Windows keeps only a clean exit, since taskkill also ends with a code. The Windows ownership step now asserts its TAP counts, like the other gates in that job, so a widened POSIX-only skip cannot leave it green while it tests less. fix(runtime): report a supervisor fault before stopping its tree An uncaught exception or rejection in the supervisor stopped its tree with its own group's SIGKILL, so the Host saw a signal exit it could not tell from a forced stop, and reported it as the command being killed. While the lease is still up, report the fault as a failure first, then stop the tree. A one-second fallback stops it even if the report hangs. The test plays the Host against the real supervisor, injecting the fault through a preload rather than a product hook. The Windows ownership step now expects 19 tests, 11 passed, 8 skipped. fix(runtime): start a bounded command's timeout at its admission The bounded runner started its timeout when it spawned the supervisor, so the supervisor's startup consumed part of the command's budget. On a loaded Linux runner a 100 ms timeout fired before the command had run at all, and the escalation test found no heartbeat file. With a direct spawn the budget belonged to the command, and the background runner already arms its timeout after admission. Start the timer once the supervisor admits the command. A supervisor that never admits it still fails through its own startup timeout. fix(runtime): let a faulting supervisor finish its own tree stop Since a fault after admission is reported as `failed`, the Host's immediate group kill on that message hit the supervisor while its own tree walk was still reading the process table, so descendants that had left the group survived. On `failed` after admission the Host now only reports the error and leaves the stop to the supervisor. The group kill on its exit stays the backstop. A spawn failure before admission still signals the group at once. A fault while the `completed` report is in flight no longer sends `failed`, and the Host ignores a `failed` that follows `completed`, so a valid result is never turned into an error. Tests cover the Host leaving a reporting supervisor alive with the backstop still stopping the command, and the supervisor's walk reaching a setsid descendant on a fault. The Windows ownership step now expects 20 tests, 12 passed, 8 skipped. Merge upstream/main into fix/shell-owner-death Main renamed the filesystem worker bundle to .mjs; keep that name and this branch's owned-process-main.js entry in both release file checks. The supervisor runs in the Host's context, outside the Windows sandbox, so the module-type lookup that broke the worker does not apply to it.
) Generated-by: Codex fix(runtime): keep graph stops exact without wedging or widening them Address review of the activation-scoped graph stop: - Public turn.stop, Host shutdown, WorkHub and whole-graph supervisor stops call stopRoot without a scope again, so they keep the Session-level Runtime stop that also reaches a claim whose Run has not attached yet. Only stopAgentGraphActivation asks for { scope: 'run' }. - A hosted graph claim counts as Host-owned only once the Host admission gate admits it. The gate runs in the Session admission lease right before the durable admission and refuses a claim whose local capability was stopped, so a stop between submission and admission cancels the activation instead of failing with "Turn was not admitted" while the child runs on. - A terminal stop target reaches the runtime only while a failed stop still retains cleanup for that exact Run, and a stop that succeeded in this reconciliation is not repeated on later passes or wakes. Historical targets no longer cost a Host stop per wake or fail the pass before new dispatch. - A failed control pass during a live wave schedules a capped backoff wake (100 ms doubling to 5 s), so a stop failure that parks the only running child is retried without another schedule commit. A repeated failure for the same target replaces the earlier one without notifying the supervisor again. Tests cover a public stop before Run attach and a graph stop before durable admission on the real Host, historical and repeated stop targets, and a retry without a wake. Pinning tests record that a graph-supervisor Session stop lets an operator accept its next claim while a user stop does not, and that a failed backend delivery is reported to its stopper while the child's result stays authoritative. fix(runtime): give exact graph Run stops their own Host method An authority that ignored the optional `{ scope: 'run' }` argument of stopRoot still satisfied RuntimeHostedRootAuthority, and a graph activation stop through it would silently widen to a Session stop that also cancels queued sibling claims. TypeScript accepts a function with fewer parameters, so no option shape can catch that. Replace the option with a required stopRootRun(identity, input). An authority without exact-Run support is now a compile error; building the tests caught one more Host fixture that forwarded only stopRoot. RootTurnCoordinator.stopRoot is again byte-for-byte main's Session-level stop, and stopRootRun carries the exact-Run delivery, redelivery and completed-Run cleanup retry. SessionManager.stopAgentGraphActivation is its only caller. fix(runtime): report a stuck graph stop once and keep retrying it A stop whose cleanup keeps failing parks its child, and so its wave, while the backoff retries every 5 s. Each retry replaced the failure silently, so the graph sat parked behind the first failure record. Count consecutive failures per target. The eighth one reaches the supervisor once, through the existing reconciliation failure notification, with a distinct "is stuck after N consecutive failures and is still retrying" reason that also lands in the durable client failure. Eight failures take about 11 s, after the backoff reaches its cap, so a fault that clears during the ramp is never reported as stuck. The stop is never dropped, and a later success clears the failure and resets the count. A driver abort no longer ends the control loop while the wave is still running. Before, the loop stopped retrying on the next wake after an abort, so a child parked behind a transient stop failure kept the aborted reconciliation waiting forever. Repeated control read failures now notify once per streak as well. fix(runtime): report a stuck graph control read once A schedule control read that kept failing notified the supervisor on its first failure and then retried every 5 s in silence while the wave stayed parked, the same silent park the stop path no longer has. Count read failures the same way: notify on the first and, once, on the eighth consecutive failure as stuck and still retrying. A successful read resets the streak and clears the failure. The threshold is now CONTROL_STUCK_FAILURES, shared by stops and reads. test(runtime): pin sibling stops past a stuck provider and the stop quarantine Two review gaps, both test-only. A graph stop pass now stops two children together, one of whose provider neither returns from stop nor ends its send. The cooperative sibling still reaches its aborted terminal while the other stop is pending, so one stuck provider delays only the pass, not its siblings. Serializing the stop calls makes this test fail. A stop whose cleanup cannot persist its terminal keeps the operation retained. An unrelated Turn on that Session, which holds no intent of that stop, is refused as quarantined until a retry settles the cleanup, and then runs. Widening the quarantine bypass to any attached execution makes this test fail. Merge upstream/main into fix/graph-schedule-stop Keep both sides of the graph driver fields: the schedule change listeners from this branch and the session activity projection from main. Main's new coordinator tests build an AgentGraphCoordinatorRuntime without stopAgentGraphActivation, which this branch makes required; give them the same no-op stop the existing tests use.
…#6021) A failed turn's banner and the provider retry notice both passed `container="section"` to Astryx `Banner`. That variant is the page-level, full-bleed, square-cornered surface, so the 800px message column showed a hard-edged block of status color that read as a page alert instead of part of the turn (apache#5799). Drop the prop so both fall back to the default `card` container — the standalone, rounded variant for content inside a column. Nothing else changes: the retry notice keeps its `role="status"` live region with the aria-hidden countdown (stable accessible name, see `ModelProviderRetryIndicator`), and every `.maka-turn-failed-banner` rule in styles.css was audited — all of them set block rhythm or style the `<pre>` diagnostic, none compensate the section shape, so none is dead. Fixes apache#5799 Generated-by: GLM-5.3-Flash (ZCode)
…indow (apache#6023) Follow-up to apache#5890 (merged): the runner passes the same startedAt/settledAt window to the completeness check and to the usage summary, and nothing asserted it - the review noted a later edit could quietly separate the two and re-open the delegated-Session undercount. The coverage stub now records its calls and the residencies test asserts it received exactly the window the usage summary read (100, 200 with the harness clock). Swapping the arguments in the runner turns the assertion red. Implements the non-blocking suggestion from the apache#5890 review. Generated-by: GLM-5.3-Flash (ZCode)
…ache#5498) Generated-by: Codex
`engines.node` was `>=22.19.0`, which semver-accepts Node 23.x. Node 23 never received `node:sqlite` `DatabaseSync.isTransaction` (added in 22.16 / 24.0), so `inspectOperationalStateSchema` in the storage layer reads `undefined`, issues a nested `BEGIN`, and every State Root open fails with `cannot start a transaction within a transaction`. npm does not warn because the range is satisfied. Tighten the range to `^22.19.0 || >=24.0.0`, make the release packaging check reject major 23 explicitly, and align the contributor and CLI docs. Generated-by: Claude Code
- SECURITY.md pointed at `web-search-boundary.test.ts` and `claude-subscription-ipc-boundary.test.ts`, both deleted in apache#1851; name the tests that enforce the IPC token boundary today. - ARCHITECTURE.md described the Desktop conversation projection as "not yet implemented" while the linked document states it is implemented; the Chinese edition was also missing that reading-path entry. - docs/tui-live-ctx-updates.md still said "Status: design" after apache#4550 shipped `tui-context-refresh.ts`, and referenced `session-trace-refresh.ts` at its pre-move path. Generated-by: Claude Code
…ner (apache#5810) Concurrent openInteractiveContextOffloadStoreForWrite calls each awaited the on-disk lease check before claiming or joining the per-lease single flight. Those checks finish in no fixed order, so a later caller with different limits could become the writer and reject the earlier callers. Check the lease synchronously and claim or join the slot before the first await; the root identity is still verified on disk before a writer is returned. The single-flight test now awaits the conflicting open with the others, and a new test replays the race to guard the ordering. Fixes apache#5801 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#6006) Since undici 8 (undici#1247) ProxyAgent forwards plain-HTTP targets to the proxy in absolute form instead of opening a CONNECT tunnel, and that forwarding semantics is the established contract on main: the eval fixture explicitly asserts the absolute-form request line and rejects CONNECT with 403. The reported 8-second hang (apache#5805) does not reproduce on undici 8.11.2 (local scoped-fetch-transport baseline 42/42 green; recent main CI runs green), and cancellation is already covered at the connect level via withSocketCancellation and buildAbortableConnector inside the dispatcher factory. The fake HTTP proxy used by the success-path test answered every request with a fixed 200, so the proxied HTTP path passed without ever exercising a relay. Replace it with a real forwarding proxy that records the absolute-form request line and the proxy-authorization header as the bytes flow through, then relays the raw connection to a live target server over a TCP pipe; the client response can only come from that target. This also pins the credentials-ride-the-forward contract on the HTTP path. Validated the test itself by temporarily self-answering from the proxy (mimicking the old fixture): the relay assertion fails until the pipe is restored. Generated-by: GLM-5.3-Flash (ZCode)
…apache#5050) select_text already returns a snapshot.selectedText payload, but the shared observation type and renderer dropped it, so the model could not confirm what was selected. Surface the field on CuObservation and write it in the observation header, truncated like value and withheld when the focused control is a secure field. Generated-by: pi-coding-agent test(runtime): cover selectedText length cap in observation header The renderer already truncated like value. Review required a test that fails if a 300-character selection is shown in full. Generated-by: pi-coding-agent
Document the removed Trace database-path entry and current Markdown, diagnostic-report, and Session-bundle workflows in English and Chinese. Link the guide from the docs index. Refs apache#4342 Generated-by: OpenAI Codex
Generated-by: OpenAI Codex Signed-off-by: jjj-n <1357598741@qq.com> docs(architecture): scope authority table to baseline and mark Windows evidence non-blocking docs(architecture): refresh workspace schema version Generated-by: OpenAI Codex Signed-off-by: jjj-n <1357598741@qq.com> docs(architecture): refresh workspace schema 18 Generated-by: OpenAI Codex Signed-off-by: jjj-n <1357598741@qq.com> Merge remote-tracking branch 'upstream/main' into codex/maka-3522-managed-workspace-doc-audit docs(architecture): refresh workspace schema 20
…are live (apache#5957) * fix(runtime-host): reject manual archive while WorkHub relationships are live Manual archive committed isArchived without consulting two live relationships. An active WorkHub delegation loses its visible target because WorkHub candidate and result views exclude archived Sessions, and a live ordinary linked child was left behind while the retirement checks only covered turns, messages, interactions, goals, runtime resources, derived effects, Agent Graph state, and scheduled tasks; #readFamilySessionIds has never included ordinary linked children. Guard the manual archive path (#setLifecycle with state 'archived') before retirement admission: a batched active-delegation lookup per revision family and a scan for live ordinary linked children of family members now reject the archive with session_busy, naming the delegated member or the parent of the live child. Removal keeps its existing relationship-aware plan, and unarchive and no-op archives are unaffected. The removal preview fixture and the revision UDS retention flow now retire the live subtask before archiving its parent family. Fixes apache#5956 Generated-by: GLM-5.3-Flash (ZCode) * fix(runtime-host): treat retired WorkHub delegations and finished subtasks as archivable The Astro-Han review of PR apache#5957 narrowed this guard: "live" was defined as the Coordination ledger still holding the delegation row, but that row stays until a delegation is superseded or stopped — finishing its Turn retires the delegation without touching the ledger, so a Session that ever received a delegation could never be archived again. The archive guard now reuses the WorkHub delegation-retirement read (the same one coordination actions run): pending, an active owned root, or a recovering execution still blocks; cancelled, shared, and terminal executions allow the archive. A returnResults delegation whose result has not yet been delivered into the Coordination Session — no root admission receipt — still blocks, because archiving would hide the result's only visible target. A linked child now blocks only while it carries in-flight work (an active or reserved root Turn, queued or in-flight messages, a pending interaction); a finished subtask no longer pins its parent out of the archive. Removal keeps its existing relationship-aware plan, and the shared retirement read is hoisted so both consumers agree on one definition. Regressions cover a completed delegation and a closed subtask archiving successfully; reverting the guard to the ledger/any-child form turns both red again. Fixes apache#5956 Generated-by: GLM-5.3-Flash (ZCode) * fix(desktop): surface archive refusals and retry bulk archive once after the sweep The archive toast swallowed the Host's refusal behind a generic "Could not archive task": the session_busy reason crossed Electron IPC as a bare message with its error class stripped. The sessions:archive handler now re-keys the archive-guard refusals a user can act on — a live WorkHub delegation, an undelivered WorkHub result, a live linked child — into stable session_archive_refused tokens, and the rail maps each to localized copy naming the action that unblocks the archive (stop or replace the delegation / retry in a moment / archive the subtasks first) for zh-CN, zh-TW and en. The bulk sweep archived in selection order, so a parent picked before its own subtask failed on the first pass and stayed failed. One retry after the sweep settles ordering inside the selection without teaching the rail about subtask links; a refusal that was never about ordering fails once more and is reported exactly as before. Focused tests cover the refusal mapping and the retry; the renderer architecture ledger passes --strict-base against 7c90bac. Generated-by: GLM-5.3-Flash (ZCode) * fix(runtime-host): check every active WorkHub assignment, not just the newest Second-round review of apache#5957 found that #assertNoLiveRelationships read only the first row of each readActiveWorkHubAssignmentsByTarget page. The store returns every active assignment for the page's targets, newest first, so a target carrying two delegations was judged by its newest row alone: an older delegation still in flight, or retired but still owing WorkHub its result, was skipped and the archive was let through. Iterate every assignment in the page and apply the same retirement and undelivered-result checks to each; any hit refuses the archive. Regression tests from the reviewer's scratch scenarios: with two assignments on the same target, an older not-retired delegation next to a retired newest one now refuses with the active-delegation error, an older retired delegation with an undelivered result refuses with the undelivered-result error, and all-retired with nothing owed still archives. Red against the old first-row read, green after the loop, red again when reverted. Also rewords two archive-refusal lines the same review flagged, in en, zh-CN and zh-TW: the undelivered-result line no longer suggests retrying in a moment (delivery may be indefinitely pending, so it now points at opening WorkHub or stopping the delegation), and the linked-child line no longer tells the user to archive subtasks the Host itself refuses to archive (it now says to wait for them to finish or stop them). Generated-by: GLM-5.3-Flash (ZCode)
* feat(harness): add local preview capability preflight Showing generated HTML locally depends on four independent things, and each fails differently: the client may have no GUI surface, the embedded browser refuses file:// by policy, the process that writes the file may not share a filesystem with the surface that renders it, and the conversation's own view may not be on screen. Attempting the preview and reading the first error conflates all four. A refused loopback connection is the worst of them — "nothing listening yet", "still starting", and "separate namespace" are indistinguishable at the socket, yet the refusal reads like proof of the last one. preview_preflight answers each capability with verified, unsupported, or unknown, and names the observation behind it. verified needs a positive observation; unsupported is reserved for settled boundaries statable without probing; everything else is unknown and explicitly disclaims a sandbox or isolation cause. A connection outcome can therefore only ever produce verified or unknown, never unsupported. The honesty runs both ways: an endpoint that answers proves only that something listens for this process, not that the embedded browser shares that loopback namespace, and a staging root that round-trips proves only that the main process reaches it. `surface` reports whether this client can display a page at all and stays separate from `endpoint`, which is not_checked when no origin was given; `ready` needs both, and is never inferred from an absent error. The loopback probe settles on every terminal path and owns an absolute deadline. A server answering 101 Switching Protocols makes Node route the exchange to `upgrade` and close the request without emitting `response` or `error`, taking the socket-bound timeout with it; the probe previously outlived both its stated bound and its caller's cancellation. Published as its own desktop_preview offer rather than in the Browser offer: every Browser tool is admitted against an Origin resolved from the view's current URL, so a capability check published there would need a page already loaded and would fail with the very "requires an HTTP origin" error it exists to explain. Generated-by: Claude Opus 5 via Claude Code Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(harness): narrow preview preflight to what it can prove Drop filesystem_visibility. HTML Open always goes through ManagedArtifactPreview, which never touches the staging root, so the capability measured the non-HTML Show in Folder path rather than a preview question. It also let a transient target loss during a reconnect surface as `unsupported`, the status reserved for settled boundaries. The artifactPresentationRoot export, its boot closure, the wiring test and the mkdir side effect inside a `read` tool go with it. Drop `ready`. A listener's answer — a 404 included — proves a listener, not that the page exists or loads, and a readiness flag built from it claimed more than the evidence held. `surface` and `endpoint` stand on their own; page load remains apache#5235's question. Probe with HEAD / against the origin instead of GET on the caller's path, so a capability check cannot trip a dev-server route with side effects. The absolute deadline is now the single catch-all, replacing a `close` arm no real server reaches. Publish the preflight inside desktop_artifact_preview, so the ArtifactPreview route it hands off to is always granted with it, and defer to that tool's description instead of paraphrasing a copy that had already drifted. Report a failed probe as "no usable HTTP response" rather than "nothing answered", since a TLS failure or a reset after accept means something did listen. Rename browser_reachability to browser_view and split the host-less case out as a constant, removing a branch the tool could never reach. Generated-by: Claude Opus 5.5 via Claude Code Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(harness): publish the preview offer through one tested seam Build the desktop_artifact_preview tool set in buildArtifactPreviewOfferTools, so the preflight and the ArtifactPreview route it hands off to are assembled in one place a test can see. A test pins both tools in the offer and that the handoff names only a tool the same offer grants; dropping either tool from the array now fails it. Remove categoryHint and recoveryMode from preview_preflight. The tool is published as a client capability, whose descriptor carries neither, and the Runtime Host assigns both itself, so the declared `read` and `replay_safe` were never in effect and only misled a reader. Say why the headless branch stays although Desktop, the only publisher, never reaches it: GUI availability is part of the classification apache#5235 builds on, and it must answer for a publisher without a view host rather than throw. Generated-by: Claude Opus 5.5 via Claude Code Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…pache#6028) * fix(runtime): keep tool_search activations for the Session lifetime tool_search activations lived on the per-send Turn, so the next Turn started with an empty provider tool list and missed the prompt cache. Share the activation map on AiSdkBackend. tool_search only adds names; Turn end and compaction do not clear them. A rebuilt backend starts empty; activations are not persisted. Refs apache#5879 Generated-by: Cursor * fix(runtime): document shared tool_search activations across concurrent Runs A Session backend can hold several concurrent Runs. They share the activation map, so a search in one Run is visible on a sibling Run's next step. Mention that in the field comment and rename the prepare() isolation test so it no longer describes backend Turns. Refs apache#5879 Generated-by: Cursor --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
…ions (apache#6029) * fix(runtime): keep request_sandbox_boundary visible in sandboxed Sessions Host binds the widening tool only when the Session is not Full access, but tool_search still deferred it. Models then searched for it, activated neighbors, and missed the prompt cache. Pass it through requiredToolNames whenever it is bound so the schema stays on the provider list for the whole Session, without depending on a live boundary prompt. Refs apache#5879 Generated-by: Cursor * fix(runtime): omit required tools from the tool_search inventory Required names are already on the provider list. Leave them out of the search inventory and ranking so an exact-name search does not activate a tool that is already visible. Align the deferred-tools backend helper with apache#6028 so the two PRs rebase without a test-file conflict. Refs apache#5879 Generated-by: Cursor --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
fix(runtime-host): use canonical ASF headers fix(runtime-host): match ASF header policy refactor(retention): share host maintenance guards fix(retention): keep canonical ASF source header style(retention): format maintenance guard docs(runtime): explain fresh process clock floor
…apache#6041) Native Anthropic requests use request-level automatic caching, which places the breakpoint on the last cacheable block. Since apache#5740 that block is the request-only Turn context appended after history, which no later request repeats at that position. Each request therefore paid a cache write that the next step and the next Turn could not read. When the resolved provider options enable Anthropic automatic caching, the model adapter now marks the last replayed history message with the same cache control, so the entry lands on a prefix the next request repeats. The Turn context stays request-only, connections without automatic caching get no marker, and durable message identities are unchanged because the marker is applied to the dispatch copy. Refs apache#6040 Generated-by: Devin Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> refactor(runtime): drop redundant guards from the Anthropic history breakpoint Ablation showed the non-positive count guard and the intermediate locals change no behavior: a count of zero matches no message index. The test now checks that the block marker uses the request-level cache control instead of repeating the request-level assertion that provider conformance already covers. Refs apache#6040 Generated-by: Devin Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> test(runtime): tighten the Anthropic cache breakpoint assertions Generated-by: Devin Refs apache#6040
…he#6046) Second pass over docs/architecture/bot-onboarding-runtime.zh-CN.md, read against the current implementation. All 18 checked claims hold: the BOT_ONBOARDING_PROVIDERS enum (dingtalk/feishu/wecom/wechat/qq, Lark as a feishu brand), the IPC channel names, BotOnboardingService, SettingsStore.updateIf, applySettingsRuntimeEffects, BotRegistry.applySettings, the Feishu and WeCom bridge handshakes and cleanup order, the 15s/10s/1-30s/5s timing figures, the saved_not_connected warning and retryHealth snapshot fields, the masked token/appSecret settings projection, the qrcode dependency, the settings-bots-onboarding e2e fixture, and the apache#4327 tracking link. No drift; the pass only refreshes last_verified and the in-body status date to 2026-10-10. Refs apache#3522 Generated-by: GLM-5.3-Flash (ZCode)
… sites (apache#6003) Two call sites build their own proxy dispatcher and dispose it themselves, so the abort-before-close teardown pattern that the shared transport fix reordered (apache#5900) survives in them: - testProxyConnection's finally aborts the controller and then awaits the dispatcher's graceful close. Behind a real proxy that close never settles, so the call stays pending long past its 8s probe timeout and wedges the serialized settings lane it occupies on the Desktop. Start the dispatcher teardown before the abort and race it against a 1s grace, mirroring the transport pattern. - proxiedFetch's error path awaits the same graceful close after aborting, so a stalled close delays the rejection the caller is owed. Apply the same ordering and bound there. The success path keeps its fire-and-forget close, which owns the streaming body lifecycle and is intentionally not bounded. Regression tests stall ProxyAgent.prototype.close (the same Undici/Node-version-independent technique the transport tests use) and assert both calls still settle; both tests fail on the previous ordering. Refs apache#5978 Generated-by: GLM-5.3-Flash (ZCode) fix(runtime): escalate proxied dispatcher teardown to destroy after the grace expires Root cause: the bounded dispatcher teardown in testProxyConnection and the proxiedFetch error path raced the graceful close against a 1s grace, but when the grace won, the dispatcher was simply abandoned with its close() still pending, leaking the agent (flagged as a P3 inline on apache#6003). Fix: track who wins the grace race and, when it expires, fire-and-forget destroy() with a distinguishing reason. The destroy error is swallowed so teardown can never replace the result or rejection the caller is already owed. The grace duration and its external semantics are unchanged; the success path of proxiedFetch keeps its unbounded close, which owns the streaming body lifecycle. Verified: new regressions in proxy-test.test.ts and proxied-fetch.test.ts stub ProxyAgent#close to never settle and assert destroy is called; both failed before the fix (callCount 0) and pass after. runtime network+bots suites 167/167, biome check clean, check:asf-headers clean. Generated-by: GLM-5.3-Flash (ZCode)
…d fixture (apache#5804) Why: apache#4677 item 4 asks for a Usage settings tab-entry median/p95 number plus renderer-side evidence that the activity table mounts a bounded page instead of every row. Fixture (test infra only): - scenarios-usage.ts pads the 5 handcrafted turns with 394 zero-tool turns (132/131/131 across the three sessions) so the ledger holds exactly 409 activity rows: 399 model rows + 10 tool rows. Synthetic turns reuse the handcrafted generators on the fixed clock (60..453 minutes ago). - e2e-fixture.ts: one catchUpModelCallProjection() pass bounds how many lagging runs it folds, so a padded seed with hundreds of queued runs left most of them unfolded after seeding. Fold in a loop until pendingRuns reaches 0, which is generic for any large canonical seed. Spec (perf/usage-tab-entry.spec.ts): a custom usageWindow fixture injects the settings-usage scenario; the test asserts the bounded mount (DOM rows <= 50 with the tab badge at 409) and then samples 12 warm re-entry rounds entirely inside the renderer with rAF — the clock runs from the synthetic click to the activity table's next painted frame, excluding Playwright round-trips. Results land in $TEMP/usage-tab-entry-results.json. Numbers (this branch, apache/main base): median 103.9 ms, p95 142.6 ms (n=12, p95 = max), first-entry DOM rows 50/409. Reference numbers from apache#4677 (comment issuecomment-5880047554, measured on a feature branch): median 134.1 ms, p95 201.3 ms — same magnitude; the branch difference is noted rather than compared. Generated-by: GLM-5.3-Flash (ZCode) fix(desktop): carry the poll budget into the renderer and fix the even-sample median Two review fixes on the usage-tab-entry perf spec: - Playwright serializes page.evaluate callbacks without their Node-side closure, so the MOUNT_POLL_FRAMES guard referenced an undefined constant inside the renderer: the first poll reaching it threw a ReferenceError from a requestAnimationFrame callback, leaving the surrounding Promise pending forever instead of rejecting after 600 frames. Both the unmount and the entry poll now receive the budget as an explicit evaluate argument, so the slow path rejects as designed. - The 12-round summary picked sorted[n/2], the upper middle value, as the median. For an even-sized sample the median is the mean of the two middle values; the summary now averages sorted[n/2 - 1] and sorted[n/2] for even runs (odd runs keep the single middle value). The PR body's measured numbers were refreshed from a new run of the corrected spec. Refs apache#4677 Generated-by: GLM-5.3-Flash (ZCode) ci: retrigger the cancelled test run Merge remote-tracking branch 'upstream/main' into perf/usage-tab-entry-spec
) The transcript data-plane benchmark called store.readTranscriptPageSnapshot, which apache#4879 removed when Session transcripts moved to the RuntimeEvent ledger; the storage contract kept only readTranscriptHighWaterSnapshot, so the script has crashed on main ever since. Retire rather than repair: the script seeded its fixture through store.appendMessages, and rows written that way never reach the RuntimeEvent ledger the replacement reader pages from, so pointing the same harness at the new reader would page an empty Session. A repair means rebuilding the fixture through the composition's turn pipeline - which is exactly what apache#5800's benchmark:hydration-e2e already measures end to end (subscription.open tail bootstrap, session.transcript.page paging through real handlers, production ClientSessionSubscription decode). Drop the script and its dead benchmark:transcript entry rather than duplicate that harness. Refs apache#4677 Generated-by: GLM-5.3-Flash (ZCode) chore(ci): retrigger the release lanes after the undici advisory The tarball and audit lanes failed on npm resolving undici@7.29.0 for the CLI release tree - GHSA-3wwx-pv8p-q78v was published against that version, and undici 7.29.1 (the fixed release) is out. Tree-identical retrigger so the installer resolves the patched version. Generated-by: GLM-5.3-Flash (ZCode) fix(deps): move undici past GHSA-3wwx-pv8p-q78v The release/audit lanes fail because the lockfile pins undici@7.29.0 (three nested copies) and undici@6.28.0, both in the advisory's range; the release tree installs from the lockfile, so no retrigger helps. Overrides pin each consumer to the fixed release of its own major (7.30.0 / 6.29.0 / 8.11.2), and packages/runtime is pinned to exactly 7.30.0 because @slack/socket-mode's peer demands ^7 while runtime code needs a working WebSocket/fetch/buildConnector (gateway and plugin-client-bridge tests pass on 7.30.0). Generated-by: GLM-5.3-Flash (ZCode) fix(deps): restore lockfile entries dropped by the undici re-resolution The undici overrides update left the lockfile with six dangling dependency edges: gpt-tokenizer, @stylexjs/stylex (plus its styleq / css-mediaquery / loose-envify peers) and invariant were still declared by the astryx packages but their node_modules resolution entries had been dropped, so `npm ci` refused to install at all. A full `npm install` re-resolved them; `npm ci` now passes locally and the undici pins are unchanged. Generated-by: GLM-5.3-Flash (ZCode) fix(deps): declare the squirrel-windows peer the desktop build needs app-builder-lib declares electron-builder-squirrel-windows in its devDependencies and peerDependencies (exact 26.16.1), and npm's tree validation refuses the desktop workspace while that peer has no resolution entry - every npm lane (audit, test, package, tarball) fails with ELSPROBLEMS. The entry was silently dropped by the same re- resolution that trimmed the undici lockfile, and being a peer it never regenerates on its own. Declaring it explicitly in the desktop devDependencies satisfies the peer durably; npm ci passes with the workspace tree clean. Generated-by: GLM-5.3-Flash (ZCode) fix(deps): pin ip-address past its SSRF advisories and re-key the stylex notice The shipped-closure audit now flags ip-address@10.4.0 (GHSA-rpw4-54j3- 4h4q / GHSA-2vr4-cq9g-pvrc, SSRF); an override pins 10.7.2, which both declaring ranges accept. The third-party-notices generator's MIT copyright override for @stylexjs/stylex tracked 0.19.0 while the tree resolves 0.19.1 (same upstream, same copyright line) - the key follows. Generated-by: GLM-5.3-Flash (ZCode) chore(deps): regenerate the third-party notices for the bumped closure The ip-address and undici pins moved the shipped closure; the committed notices files now match it (stylex 0.19.1, ip-address 10.7.2, undici 6.29.0 / 7.30.0 / 8.11.2). Generated-by: GLM-5.3-Flash (ZCode) fix(deps,ci): re-key the release closure and clean the lockfile registry The undici re-key left two references behind: the release packager hardcoded undici@8.10.2 when copying the eval closure and writing the CLI manifest (the tree now resolves 8.11.2), and the regenerated lockfile carried registry.npmmirror.com resolved URLs from a local mirror config where main's entries all use registry.npmjs.org. knip also gained an exemption for electron-builder-squirrel-windows: it satisfies app-builder-lib's peer and is never imported by renderer code, same as the existing fontsource entries. Generated-by: GLM-5.3-Flash (ZCode) style(knip): wrap the ignoreDependencies array for the formatter Generated-by: GLM-5.3-Flash (ZCode) fix(deps): walk the undici bumps back to behavior-preserving versions The aggressive undici re-key broke two real consumers: the eval suite's initialization proxy test saw an unexpected CONNECT through the 7.30.0 ProxyAgent, and the runtime scoped-fetch-transport suite hung on 7.30.0. Walk @ai-sdk/provider-utils back to 7.29.1 (the minimal fixed release) and packages/runtime back to its previous 8.10.2 (already past the advisory line); @electron/get keeps 7.30.0 and the 6.x/8.x leaves keep their resolved versions. Both previously failing suites pass locally (42/42 and 1/1). Generated-by: GLM-5.3-Flash (ZCode) fix(deps): drop the @slack undici override in favor of the nested entry The `@slack/socket-mode` override demanded undici@7.30.0 while the runtime tree deduped to 8.10.2, and npm flagged the mismatch as invalid - which every npm ls consumer (audit, release closure, notices) turned into ELSPROBLEMS. The lockfile's nested `@slack/socket-mode/node_modules/undici@7.30.0` entry already satisfies the ^7 peer with the fixed release, so the override is redundant; dropping it leaves a fully valid tree. Generated-by: GLM-5.3-Flash (ZCode) chore(deps): regenerate the third-party notices for the walked-back closure The undici version walk-back changed the shipped closure again (+7.29.1, +8.10.2 after the @slack nested entry re-landed); the committed notices files now match it, per the lockfile-chain checklist. Generated-by: GLM-5.3-Flash (ZCode) Merge branch 'main' of https://github.com/apache/maka into fix/transcript-benchmark Merge remote-tracking branch 'origin/fix/transcript-benchmark' into fix/transcript-benchmark Merge upstream/main (8648258) Merge remote-tracking branch 'upstream/main' into fix/transcript-benchmark
Generated-by: OpenAI Codex refactor(storage): simplify git-dir validation and share broken-ancestor fixture fix(storage): reject HEAD symrefs whose target is not under refs/ An ancestor with valid .git/objects and .git/refs but HEAD set to `ref: gk` passed isGitDirectory(), while git rev-parse exits 128 on it. resolveProjectLocation() then threw and resolveWorkspaceIdentity() returned workspace_io_failed, so the malformed ancestor still blocked the nested-folder workflows this change is meant to recover. Git itself only accepts HEAD symrefs pointing under refs/ (verified: ref: gk, ref: HEAD, ref: gk/x all exit 128 even with objects/ and refs/ present; ref: refs/... passes even when the branch does not exist yet), so the check matches exactly that and no more. The case is added to the shared broken-metadata fixture as head-symref-no-refs-prefix, covering both the project-catalog and workspace-identity broken-ancestor tests. feat: resolve git dir with git rev-parse --resolve-git-dir fix: git file no read access fix(storage): re-probe rejected .git ancestors under a readable stable snapshot Git's exit-128 rejection of an ancestor .git directory conflates a format verdict with metadata it could not actually read. Trust the verdict only after auditing the inputs is_git_directory consults (HEAD readable, objects/refs searchable) inside a stat snapshot, then re-probe and require the snapshot to be unchanged so repaired or replaced metadata cannot inherit a stale rejection. Entries that cannot be classified — commondir or GIT_OBJECT_DIRECTORY redirection, special files, gitfile/symlink indirection, and any failure on the selected directory's own .git — now surface as errors instead of silently downgrading to folder identity. Generated-by: OpenAI Codex docs(storage): record new git marker and workspace identity Windows exclusions Generated-by: OpenAI Codex fix(storage): anchor git entry probes on the entry directory assertGitEntry ran git -C process.cwd() merely to give Git a place to start; --resolve-git-dir judges gitPath itself. When the host's cwd has been deleted or is unsearchable, -C fails before the probe runs and the generic exit 128 is taken as Git's verdict on the entry. The audit re-probes under the same broken anchor, a valid enclosing repository is skipped, and resolveProjectLocation silently downgrades it to folder:. Anchor -C on parse(gitPath).dir instead — lstat already proved that directory exists — and resolve() the walk start so a relative path can never hand the ambient-cwd dependency back through a relative -C. Generated-by: OpenAI Codex (swe-2)
… directory (apache#4936) Offer to restore archived projects from task entry, project settings, and remote directory registration. Preserve project naming, show loading state, and report add, restore, and refresh failures. Remove the unused app-shell add action and route runtime-host catalog failures through redacted diagnostics. Add regression coverage for archived-project restoration and error handling. Generated-by: Codex fix(desktop): preserve task-entry project restore results Reuse the result-bearing newTasks restore bridge and remove conflicting service and fake definitions. Cover restored-project selection through the Desktop adapter. Generated-by: OpenAI Codex fix(desktop): share archived-project restore across registration callers Extract the register/confirm/restore transaction into resolveProjectRegistration and a render-prop ProjectRegistrationBoundary owning single-flight pending state and staleness fences. Settings and the remote directory picker route through it, so the confirm dialog no longer awaits inside Astryx clickAction transitions. Session workspace recovery moves to useSessionWorkspaceRecovery with request-identity and attempt fencing, and toast confirm gains an onConfirm hook that keeps the dialog open while the accepted operation runs. Generated-by: Codex fix(desktop): preserve archived project names during remote registration Extract shared project registration recovery into a hook and carry the restored result through the remote directory handoff. Align workspace recovery copy with task terminology and expose archived add results in the preload bridge. Generated-by: Codex
Review follow-ups (apache#5274 review): - prepareRevisionSend re-keyed the edit-start snapshot, so quotes the user removed or re-annotated during the edit reappeared on the branch and could be sent. The re-key now lands the plate's current quotes, and the send reads them live (the before-send snapshot retires — the re-key covers its case). - Drops the stale-base footer copy block and a dead regenerate key: no production code on current main references the old footer shape that survived in this branch's base. The no-op gate keeps counting the model-facing comment. Generated-by: GLM-5.3-Flash (ZCode) Merge upstream/main into fix/desktop-revision-structured-context fix(desktop,ui): preserve the quote plate across the in-flight revision send The revision send awaited prepareRevisionSend before reading the plate, and the lifecycle re-keys it mid-send: the plate's current quotes are copied onto the branch child and the source bucket is emptied in place. The still-running sendWithAttachments invocation holds quotesForSend from the render that started the send, so it read the emptied source bucket, got undefined, and submitted the edited replacement without its quotes or their edited annotations (apache#5274 review). Read the plate through the re-keyed owner explicitly: quotesForSend now resolves the bucket by owner key (defaulting to the live draft key for the non-revision send paths), and the revision send passes the prepared draft's session id. The resumed send therefore reads the child bucket the lifecycle just wrote — removals and re-annotations included. The regression test drives beginEditUserMessage → an in-render quotesForSend capture → prepareRevisionSend and asserts the re-keyed plate with its edited annotation still reaches the send; it fails on the previous head with `actual: undefined`. Generated-by: GLM-5.3-Flash (ZCode) fix(desktop,ui): keep quotes added during a cancelled edit Cancelling a revision draft cleared both draft keys wholesale, so quotes the user staged during the edit were lost together with the edit's own restaged set (apache#5274 review: "Cancelling an edit deletes quotes added during it" — on main they stayed in the composer, and adding quotes during an edit is supported). clearQuotes now returns the entries it removed, and clearRevisionStagedContext re-stages whatever lies beyond the edit's beginEdit snapshot (matched per QuoteRef field set, counted as a multiset) onto the source Session the cancel returns to — whether the user added them before or after the branch child was prepared. The edit's own items are still dropped wherever the commit left them. The regression tests drive a cancelled edit with a user-added quote on each side of the prepare step and assert the addition survives on the source key while the composer text rolls back; both fail on the previous head, the first with the edit's restaged quote returned instead of the user's own, the second with no plate restore at all. Generated-by: GLM-5.3-Flash (ZCode) fix(ui): treat negative owned counts as fully user-owned clearRevisionStagedContext drops the edit's own quotes by per-key count: the first N entries matching the beginEdit snapshot are the edit's, and everything past that count is the user's own staging. The kept check compared the remaining count with `=== 0`, so once the counter ran negative the surplus stopped matching: when the user added a second copy of a quote the edit had also staged, the third identical plate entry was dropped despite being the user's. Treat any non-positive count as fully user-owned (`<= 0`), so every entry past the edit's own count survives the cancel. Fixes a P3 raised inline on apache#5274. Generated-by: GLM-5.3-Flash (ZCode) Merge upstream/main (8648258) Brings in the composer-submit extraction (apache#5815) and the allow-unchanged edit-and-resend decision, merged into the revision staged-context feature: - app-shell.tsx keeps the upstream extraction; the staged-context wiring and the apache#5274 re-keyed quotesForSend/clearQuotes semantics move into features/conversation/controller/composer-submit.ts (owner-keyed ports). - app-shell-revision-actions.ts keeps the @maka/ui delegation; TurnRevisionDraftBase drops originalText and the unchanged gate (revisionStagedContextUnchanged) so unchanged resends pass through per upstream apache#5815, while the mixed-context conflict gate stays. - conversation-copy.ts keeps both new locale keys (revisionDraftQuoteConflict, revisionMixedContextUnsupported) on top of upstream's revisionUnchanged removal and apache#5815 copy updates. - renderer-architecture.json regenerated via check-renderer-architecture --write; app-shell.tsx budget drops 12091 -> 11154. Tests: upstream app-shell-revision-resend gains a stagedContext fake; the ui revision suite expectations updated to the allow-unchanged behavior. Generated-by: GLM-5.3-Flash (ZCode) fix(desktop): assemble the revision staged context outside the frozen shell Root cause: upstream apache#5546 extracted app-shell helpers and drove the frozen shell's nonTriviaTokens baseline down to 11129 with zero headroom, so the merge that re-attached this PR's stagedContext wiring (a 7-line factory in the createAppShellRevisionActions ports object, +25 tokens) broke the renderer architecture ratchet: 11129 -> 11154. Fix: assemble the RevisionStagedContext closure inside the desktop useComposerAttachments controller (a feature file outside the debt ledger), right beside the hooks that own the quote/attachment buckets. The frozen shell now forwards one member (stagedContext,) instead of building the factory inline. The restoreAttachments entry the shell only carried for that factory is dropped from its destructure: its sole consumer was the deleted block (RevisionStagedContext declares no such member and nothing in @maka/ui reads it from the staged context). Verification: - check:renderer-architecture --base 6e21e61 --strict-base: red (11129 -> 11154) before, green (11129 == base) after; ledger diff is the single app-shell.tsx nonTriviaTokens line, no other entry moved. - desktop focused suites (app-shell-revision-actions, use-composer-quotes-revision-send, app-shell-revision-resend, new-task-staged-content): 18/18 pass. - packages/ui full suite: 710/710 pass. - typecheck green: ui tsconfig + desktop preload/main/renderer/storybook. - biome lint clean on both touched source files; check:asf-headers green. Generated-by: GLM-5.3-Flash (ZCode) Merge upstream/main (28cc4e6) Resolve the renderer-architecture.json conflict by re-pricing the ledger from the merged tree via check-renderer-architecture.mjs --write (all entries at real merged-tree values, within baseline); drop the trailing blank line at EOF in conversation-copy.ts flagged by diff-check. Merge upstream/main (0aa2707) Resolve renderer-architecture.json by re-pricing from the merged tree via check-renderer-architecture.mjs --write. Merge upstream/main (d6876d7) Resolve the renderer-architecture.json conflict by taking main's ledger (new apache#5851 file entries) as the base and re-pricing every entry from the merged tree via check-renderer-architecture.mjs --write; the check passes against the ratchet baseline. Merge upstream/main (d7dffca) Merge upstream/main (c838e1f) Fourth structural catch-up for apache#5274: carries apache#5868 (Composer staging moved into a persistent ComposerStagingProvider owner) and apache#5884 (task archive timestamps). Conflict resolution ports the revision staged-context semantics onto the new owner structure: ComposerStagingSubmission gains optional owner-key reads/clears (snapshot for captured submissions, live plate for the revision re-key) and ComposerStagingCommands gains stagedContext(); the frozen shell forwards the one composerStaging handle and the revision assembler derives the gate probe and plate reads from it. Merge upstream/main (1e80e3b) into fix/desktop-revision-structured-context # Conflicts: # apps/desktop/renderer-architecture.json Merge upstream/main (c7fa6bb) into fix/desktop-revision-structured-context # Conflicts: # apps/desktop/renderer-architecture.json Merge upstream/main (255ae23) into fix/desktop-revision-structured-context Merge upstream/main (229e1b4) into fix/desktop-revision-structured-context Merge upstream/main (f7633c3) into fix/desktop-revision-structured-context Merge upstream/main (7c90bac) into fix/desktop-revision-structured-context Merge remote-tracking branch 'upstream/main' into fix/desktop-revision-structured-context # Conflicts: # apps/desktop/renderer-architecture.json fix(desktop): drop the stale regenerate footer copy apache#5468 removed the Regenerate feature (87ff279), deleting the footer's `regenerate` label and the `regenerateRunning` / `regenerateAgain` / `regenerate` / `requestRegenerate` keys from the conversation copy. This branch's stale base still carried the block, so the merge-base diff re-adds those keys across the contract type and all three locales (including the zh-TW 本輪迴答 wording) while nothing on current main references them — merging would resurrect dead strings. Drop the block from the type and the zh-CN / zh-TW / en entries, matching the upstream shape exactly; the `lineage.regenerated*` keys are a different, live feature and stay. Generated-by: GLM-5.3-Flash (ZCode)
Generated-by: Codex fix(cli): resume the selected interrupted session Generated-by: Codex fix(cli): separate session attach and resume discovery Generated-by: Codex style(cli): format resume availability flow fix(cli): reject unavailable sessions before switching fix(cli): keep unavailable sessions attachable Merge branch 'main' into fix/cli-resume-discovery Merge branch 'main' into fix/cli-resume-discovery Merge branch 'main' into fix/cli-resume-discovery fix(cli): keep session attachment independent from resume Merge origin/main into fix/cli-resume-discovery fix(cli): preserve no-cwd session guard Generated-by: Codex fix(cli): exclude foreign sessions from resume picker Merge branch 'main' into fix/cli-resume-discovery fix(cli): guard resumable session selection merge: sync resumable session PR with main :bug: bound resume discovery to visible sessions Merge upstream/main into fix/cli-resume-discovery to resolve PR apache#3582 conflicts fix(cli): bound resume candidate discovery Generated-by: Codex Merge upstream/main and fix bounded resume discovery Generated-by: Codex fix(cli): bound resume catalog reads Generated-by: Codex fix(cli): preserve cwd resume candidates fix(cli): filter bounded session catalog results Generated-by: Codex fix(cli): surface incomplete resume discovery Generated-by: Codex fix(cli): guard external imports during active turns Generated-by: Codex fix(cli): preserve partial session discovery results Generated-by: Codex fix(cli): preserve resume candidates at scan limits fix(cli): scope incomplete catalog notice to picker Generated-by: Codex fix(cli): keep resume catalog bounds in sync fix(cli): retry session list after catalog failure Generated-by: Codex
Retry remaining UTF-8 bytes at explicit offsets and report stalled writes as unknown outcomes. Fixes apache#5370 Generated-by: OpenAI Codex Signed-off-by: seekskyworld <djh1813553759@gmail.com> refactor(runtime): clarify complete descriptor write contract Generated-by: OpenAI Codex Signed-off-by: seekskyworld <djh1813553759@gmail.com> docs: explain regression invariants in English Generated-by: OpenAI Codex Signed-off-by: seekskyworld <djh1813553759@gmail.com>
Generated-by: OpenAI Codex Signed-off-by: seekskyworld <djh1813553759@gmail.com> fix(core): preserve indented memory metadata examples Generated-by: OpenAI Codex Signed-off-by: seekskyworld <djh1813553759@gmail.com> docs: explain regression invariants in English Generated-by: OpenAI Codex Signed-off-by: seekskyworld <djh1813553759@gmail.com>
Generated-by: OpenAI Codex Signed-off-by: seekskyworld <djh1813553759@gmail.com> test(core): document calendar DST policy across consecutive fires Generated-by: OpenAI Codex Signed-off-by: seekskyworld <djh1813553759@gmail.com> docs: explain regression invariants in English Generated-by: OpenAI Codex Signed-off-by: seekskyworld <djh1813553759@gmail.com>
executeTool() spelled out the argument-projection policy inline: raw snapshot, permission projection on a private clone, the Computer Use persisted/model views, and two handwritten common-field recipes for the tool_start event and the persisted tool_call message — all inside a method that also owns admission, dispatch identity, T1/T2 and publication (apache#4908, slice of the A06 direction in apache#4726). The call-data rules move to tool-call-snapshot.ts: the recursive snapshot helpers, schema validation, one named buildToolCallArgs() operation that produces the four argument views with the existing guards (direct-only rejection skips validation and projection entirely; an unavailable sandbox-boundary surface defers validation; projection failures come back as permissionArgsError for the refusal path instead of throwing), and one buildToolCallCommonFields() recipe invoked once per record so the event and the message each receive privately owned clones of args and providerOptions. The consolidated recipes were verified to fail the argument-ownership isolation test when a single shared args object leaked across the two records — the exact break the duplication used to make impossible. No public API, event, message or durable format changes. The four argument-view consumers (managed mutation admission, durable preparation, result projection, telemetry/artifacts) read the same named views; their algorithms are untouched. fix(runtime): keep the shared call-field recipe inside the persisted message shape The shared common-field recipe emitted toolUseId as its own key. The tool_start event carries that field, but the persisted tool_call message names the same value `id` and its stored-message schema rejects unknown keys — appendMessages threw 'Invalid stored message schema', the Computer Use history guard generalized it to 'Operation failed', and the remote TUI turn failed before its fixture tool could run (tui-mcp-remote-integration). The recipe no longer emits the call id: the input still carries it, and each record names it at its own site — `toolUseId` on the event, `id` on the message. Reproduced locally through the failing integration test (failed on the refactored build, passed on the pre-refactor module); passes again after the fix along with the four argument-ownership, settlement, model-loop and privacy suites (21/21). refactor(runtime): scope call-data extraction to argument projections Keep call-event construction in executeTool, its sole production owner. Remove the unused common-field wrapper, mirrored identity types, and modelFacingArgs alias. Persistence and model replay retain persistedArgs as their canonical projection. Generated-by: ZCode
…ache#5744) npm's install-scripts approval gate flags seven packages on a fresh clone: two allowlist entries trail the lockfile (esbuild 0.27.7 vs the pinned 0.28.2, @jackwener/opencli 1.8.4 vs 1.8.7), and five packages with install scripts were never allowlisted at all (electron-winstaller, protobufjs, tree-sitter-javascript, @astryxdesign/cli, @astryxdesign/core). Every entry is now the exact version pinned in package-lock.json, verified against node_modules, and a fresh install completes with no unreviewed-script warnings. Generated-by: GLM-5.3-Flash (ZCode) chore: deny the four nonessential install scripts Review follow-up: the @astryxdesign/cli and @astryxdesign/core postinstalls only print setup nudges, protobufjs only checks its version notation, and @jackwener/opencli skips its shell-completion postinstall on this repository's installs and in CI — none produces an artifact Maka needs. Record an explicit deny (which also clears npm's unreviewed-script warning without executing the scripts) and keep approval only for the scripts installation genuinely requires (esbuild's binary install, tree-sitter-javascript's native build, electron-winstaller's arch selection, node-pty's native build). Generated-by: GLM-5.3-Flash (ZCode) chore: allowlist fsevents@2.3.3 install script fsevents@2.3.3 is a darwin-only optional dev dependency with hasInstallScript: true in the lockfile; a fresh install on macOS trips the approval gate exactly like the eight entries this PR already refreshed. The allowlist was scanned on Linux, where the os: ["darwin"] guard keeps the package out of node_modules - that is how it was missed. Generated-by: GLM-5.3-Flash (ZCode) chore(ci): guard allowScripts against lockfile drift npm's install-script approval gate keys approvals on exact name@version, so a routine bump silently stales the map and a new optional script- carrying dependency (fsevents) escapes it entirely. The new check-allow-scripts script fails on any script-carrying lockfile entry the map does not key, any map key trailing the lockfile, and any non-boolean decision; the dependency-audit workflow runs it beside the shipped-closure audit so the drift cannot land. Generated-by: GLM-5.3-Flash (ZCode) Merge remote-tracking branch 'upstream/main' into fix/allow-scripts-versions chore(ci): retrigger after a flaky code-mode run The affected-test lane failed on a single timing-sensitive assertion in code-mode.test.js ("excludes host waiting from the execution budget and preserves dependent Promise.race progress", false !== true). The same test file passes three consecutive local runs (33/33 each) on this exact tree; nothing in this PR touches the runtime. Tree-identical retrigger. Generated-by: GLM-5.3-Flash (ZCode) chore(ci): retrigger the windows packaging lane again The Release Windows package job crashed twice at the same point: the electron-builder icons@1.2.3 icon-tool child process died with 0xC0000005 on the Windows runner (the ico output had already been written). main's own package lane passes on the same sources, so this is runner-side, not this PR. Third attempt; if it crashes at the same point again I will file an issue with the three logs. Generated-by: GLM-5.3-Flash (ZCode) Merge upstream/main (8648258) Brings in the dependency-refresh train through apache#5839/apache#5860. The single conflict was the root allowScripts block: upstream mechanically carried "@jackwener/opencli@1.8.8": true forward from the dependabot bump, while this branch holds the reviewed deny (opencli's skipped shell-completion postinstall produces no artifact Maka needs). Keep the deny decisions and re-key the three bumped versions to the new lockfile: @jackwener/opencli 1.8.7 -> 1.8.8, @astryxdesign/cli and @astryxdesign/core 0.6.2 -> 0.6.3. The other six entries already match. scripts/check-allow-scripts.mjs passes against the merged lockfile (9/9 install-script packages covered) and its suite stays green. Generated-by: GLM-5.3-Flash (ZCode)
…#5820) Issue apache#5537 reported capCodePoints returning nearly the whole string for maxCodePoints <= 0; that helper (packages/core/src/thread-search.ts) was removed with the TypeScript thread-search stack by 8d82007 before the fix could land. The same boundary bug survives in the sibling the issue cites as correct: sanitizeUnicodeText treats a negative cap as uncapped - the loop's early break never fires, the whole input is expanded into the points array, and slice(0, negative) drops only a couple of trailing code points, so 'hello' @-2 came back as 'hel...'. An empty input even came back as the ellipsis suffix, contradicting the "empty input returns ''" contract. Clamp the cap with Math.max(0, ...) so negative budgets behave exactly like 0 (suffix-only for non-empty input, '' for empty), matching truncateUtf16Safe's `maxUnits <= 0` guard; drop the now-always-true `>= 0` check in the loop. No caller passes a negative cap, so existing paths are unchanged. The sanitizeUnicodeText cap boundary had no test coverage; new tests pin the zero-cap and negative-cap cases (both red on the previous code), plus the positive-cap and surrogate-pair paths. Core suite 918/918 after a clean rebuild (a stale cross-branch dist initially failed unrelated files); biome on both touched files and check:asf-headers clean. Fixes apache#5537 Generated-by: GLM-5.3-Flash (ZCode)
… not the set (apache#5862) The digest behind every candidateRef included each eligible Session's `name` and `updatedAt`, and it was taken in presentation order (`updatedAt` descending). Any Session's automatic title commit or timestamp bump therefore rotated every ref in the page, so a delegation into a target that had not moved was rejected with `candidate_set_stale`. That is the apache#4785 flake, and the same race a user loses by opening WorkHub and clicking delegate while an unrelated Session is renamed. `candidateSetId` now digests only the menu: Session id, workspace projection and derived state, in id order. `candidateRef` keeps the full per-Session identity, so a target that really did move still fails closed. The three set-wide equality checks stay, so the tested contract that a stale `candidateSetId` is rejected is untouched. One expectation in the gate suite moves from `candidate_set_stale` to `candidate_unavailable`: `rejects stale candidates before assignment` mutates the target's own `lastMessageAt`, which is now visible only through its ref. Measured at 6e21e61: gate, coordinator, protocol and tool-profile suites 86/86; the named flaky test 3/3; the new regression test passes with the change and fails with only the gate file reverted, emitting `candidate_set_stale`. Sunrioa's second reproduction, where the target's own `updatedAt` catches up after its turn reports completed, is deliberately not addressed here: `updatedAt` is still in the ref, so that window still conflicts, and clearing it needs a call on whether a completing turn should invalidate a delegation into it. Generated-by: Qoder (AI assistant)
…rift (apache#5867) Re-creation of apache#4899 without the disclosed Grok-generated content, per the maintainer guidance on that PR. apache#5172 already landed the bulk of the Computer Use audit on main; two code-anchored corrections from that review remain outstanding: - foundation-contract: the intervention/lock/stop matrix row still said FAIL with no Desktop production event producer, but the idle-input and screen-lock guards are wired via apps/desktop/src/main/desktop-native-capability-assembly.ts and mapped to user_intervened/screen_locked in packages/computer-use/src/maka-cu-backend.ts. The row is PARTIAL now; there is still no attributable macOS event-tap producer. - model-loop-foundation: keyboard actions were listed as disabled and fail closed alongside the coordinate and pixel paths, but press_key is a semantic action and type/key are implemented in maka-cu-backend.run under the 6.4 focus-binding rules. Refs apache#3522 Refs apache#4899 Generated-by: GLM-5.3-Flash (ZCode)
…to the protocol codec (apache#5887) turn.ts、message.ts、session-continuity.ts 各自维护一份逐字相同的 requireEncodedByteLimit 私有副本,与 protocol/codec.ts 的公共实现并存。 三处改为从 codec.js 导入公共实现,删除私有副本(3 files, +3/-36)。 行为披露:超限时的协议错误 message 文本从 `Invalid <label>` 变为 `<label> exceeds byte limit`(codec 公共实现的既有文案)。接受/拒绝 判定、错误类型(RuntimeHostProtocolError)与 code(invalid_frame)均 不变;全仓无测试或消费方断言旧文案。JSON.stringify 失败与 undefined 两条路径两版本文案本就逐字相同。 apache#5038 读写放大清单的 byte-limit helper 整合项。packages/core 的 skill-invocation.ts 存在变体副本(无 label 参数、UTF8.encode 计长), 因依赖方向(core 不依赖 runtime-host)不在本单范围。 Refs apache#5038 Generated-by: GLM-5.3-Flash (ZCode) Merge remote-tracking branch 'upstream/main' into refactor/byte-limit-integration chore(runtime-host): declare the byte-limit consolidation as a protocol-compatible change The epoch guard counts the three touched protocol files as a protocol change and demands an epoch past 201. The change deletes three private requireEncodedByteLimit copies in favor of the shared codec implementation: no wire shape, field, key, error code, or accepted value changes; the only observable difference is the over-limit error message wording, which no test or consumer pins. Declared per the protocol-compatible-changes README instead of burning an epoch. Refs apache#5038 Generated-by: GLM-5.3-Flash (ZCode)
Preserve immediate socket cancellation while bounding dispatcher destruction to avoid wedging shared transport callers. Cover successful HTTPS CONNECT and stalled dispatcher teardown. Generated-by: Codex (gpt-6.1-sol) fix(runtime): retire dispatchers before aborting h2 tunnels Exercise negotiated HTTP/2 CONNECT teardown and retain the bounded destroy safety net. Generated-by: Codex (gpt-6.1-sol)
…lure (apache#5922) A candidate that loses the launch election proves another candidate owns the root and is still coming up. The client reported that loss as the Host's own failure instead, and stopped probing. With a transcript store large enough to keep the winner out of registration past the moment it is asked about, the desktop saw a failure about a second after it asked, and every retry saw the same thing - the permanent unavailability in apache#5843. A lost election is now evidence to keep waiting on: the election runs its window and keeps reconnecting to the candidate that won. The launch throttle is left alone, so a root whose winner dies is still rescued by the next attempt rather than stranded, and the loser's startup diagnostic stays on disk because that trace is what made the storm visible in the first place. Generated-by: Qoder (AI assistant) fix(runtime-host): stop the lost election from ending the window path too CI on 807a9b4 failed exactly one test, and it was the new one: "a candidate that loses the launch election is waited on, not replaced". The in-loop guard is not the only exit — once the window is spent, the end-of-election path returns whatever startup failure was recorded without asking what it was. On Linux the loser's report resolves after the deadline, so the in-loop guard never sees it and the terminal path still reported launch_election_lost. Both exits now go through one predicate, and the test asserts only the property that must hold on either: a lost election never decides the outcome. Three local repeats exercised just the in-loop exit; this case is CI's, not mine. Generated-by: Qoder (AI assistant) fix(desktop): wait the client's election window before replacing a candidate The Desktop gave up on a starting Host at 45s while the client elects for 75s (connect-or-spawn.ts DEFAULT_ELECTION_DEADLINE_MS, raisable through MAKA_RUNTIME_HOST_ELECTION_DEADLINE_MS). With a 45s manager-side window under a 75s election window the manager can declare a candidate dead while the election it lost is still inside its legitimate window, which is the replace-and- reshuffle amplifier in apache#5843: a large transcript store keeps the winner out of registration past 45s, the manager swaps, and every replacement loses again. The 45_000 arrived with the parity sweep apache#2216 as a plain fallback carrying no alignment argument. Rather than add a second magic number, the Desktop fallback now resolves through the channel the client already honours - caller value, then MAKA_RUNTIME_HOST_ELECTION_DEADLINE_MS, then the client's own default, which is exported for that purpose - so both windows are derived from one constant and cannot drift apart again. Verified on this host (Windows, scoped suites, no Electron runtime launched): - tsc -b packages/runtime-host and tsc -p apps/desktop/tsconfig.main.json: rc=0, zero errors. - dist/main/__tests__/runtime-host-desktop-candidate.test.js: 27 pass / 0 fail. Baseline measured before the change was 26 pass / 0 fail. - Counterfactual: putting `electionDeadlineMs ?? 45_000` back in the resolver body makes the new test fail with `45000 !== 75000` at 1 fail / 26 pass, so it discriminates on the value, not on a missing symbol. - packages/runtime-host scoped set (connect-or-spawn-env, managed-deployment, wait-for-ready, startup-error, host-profile, candidate-startup-failure): 60 pass / 0 fail. - biome check on all four changed files: exit 0, no diagnostics. - Hook payloads run by hand, because spawnSync on node_modules\.bin\biome.cmd dies with EINVAL here (errno -4071): asf-license-headers check-staged rc=0, protocol-epoch-check --staged rc=0 at epoch 202, git diff --cached --check rc=0. biome-staged-check.mjs crashes on that spawn rather than reporting a finding; its substance is the biome check above. Deliberately unchanged, and measured rather than assumed: - host-profile.ts:595 and wsl-environment.ts:57-58 keep their own 45s defaults. connectRuntimeHostProfile has exactly one production caller, the Desktop candidate at :501, and it now always supplies readyTimeoutMs, so neither fallback is on the Desktop path any more. Widening a shared library default for callers that do not exist today is a bigger call than this issue. - candidate-startup-failure.ts:27 still classifies launch_election_lost as permanent, per the reasoning on apache#5843. - startup-diagnostic.test.js fails `54 !== 0` here both with and without this change, proven by rebuilding from HEAD's copies of the two client files, so it is a pre-existing host failure and not a regression. The full runtime-host suite was not run and no full-suite number should be read from this commit. Generated-by: Qoder (AI assistant)
apache#5938) Prepare and decode the sidebar-preview backdrop before yielding the native WorkHub view, and retain it until native restoration is acknowledged. Cover cancellation, stale responses, and popup removal without blocking presentation commands. Generated-by: OpenAI Codex test(desktop): stabilize WorkHub preview and wheel interactions Restore sidebar row hover after preview dismissal before clicking its hover-only action. Compare native floating-window bounds during wheel dragging, rather than intrinsic button widths that legitimately change when the model label updates. Generated-by: OpenAI Codex
…#5943) Generated-by: OpenAI Codex
- Bold closed right after a full-width colon and before a letter is not right-flanking under CommonMark, so GitHub and npm print the asterisks. Move the colon outside the emphasis in the CLI Chinese README, the agent-graph scheduling draft, and the Chinese Nightly npm notice. - ARCHITECTURE.zh-CN.md: `Runtime Runner` -> `RuntimeKernel`, and `[ENGLISH]` -> `[English]`. - agent-swarm.md: `AiSdkTurn`, not `AiSdkBackend`, appends the swarm prompt. - README native/ entry: name the Windows Runtime Host task launcher. - DESIGN.md: drop `info-light`/`info-dark` (the document states there is no info colour), correct `surface-overlay-dark` to the derived 0.223, and repair the unparseable `--warning` sentence. - ui README: five export surfaces, not four. - cli-npm-release: drop the stray `version=0.1.0` from the dist-tags step. - ACP README: state the 175 -> 176 epoch bump as past (apache#5386). - eval README: `machine path ... is unavailable` means the env var is unset; refresh stale install-preflight line references. - website README: the published .asf.yaml also sets `staging.profile: ~`. Fixes apache#5624 Generated-by: Claude Code Co-Authored-By: Claude Code <noreply@anthropic.com>
…pache#6045) Part of the apache#3522 docs-verification campaign (Sandbox and privacy group). All four documents were checked claim-by-claim against the code; the group is in good shape and needed only targeted corrections: - workspace-privacy-context: the cited example file runtime-host-search-ipc-main.ts was removed by apache#5531 — replaced with the live queryRuntimePolicy consumer runtime-host-settings-ipc-main.ts; last_verified refreshed (content changed via apache#5742). - permission-onboarding-plan: the permissions-actions.ts line reference pointed at a pre-ASF-header line number (now a type-union member); it now cites the deep-link/openExternal block (lines 61-90). - windows-sandbox-rfc (EN+ZH): the §6.5 status date corrected to the apache#3722 merge date (2026-08-25); the "typed unavailable reasons are deferred" wording now distinguishes the readiness-probe-level collapse from the transform layer, which already emits unsupported_platform / backend_not_available / invalid_request; last_verified refreshed. Refs apache#3522 Generated-by: ZCode
Bumps [smol-toml](https://github.com/squirrelchat/smol-toml) from 1.8.0 to 1.9.0. - [Release notes](https://github.com/squirrelchat/smol-toml/releases) - [Commits](squirrelchat/smol-toml@v1.8.0...v1.9.0) --- updated-dependencies: - dependency-name: smol-toml dependency-version: 1.9.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com>
… (apache#6042) Part of the apache#3522 docs-verification campaign (Tools and capabilities group). All three documents were checked claim-by-claim against the code; the stale ones are corrected: - MCP architecture draft: the suggestion catalog with third-party brand SVGs is live on the MCP page (apache#5603/apache#5638), so the "no catalog or brand assets" passage is replaced; ToolDiscoveryState -> ToolRefreshState and ToolSnapshot -> McpToolSnapshot (the shapes were right, the names were not); successful tool results are bounded and fail-closed (apache#4915). - Skill catalog policy: the "Context Inspector" per-project prompt-build cache does not exist — the catalog snapshot reports contextStatus unknown before a prompt is built and surfaces render the enabled fallback; the Needs review marker renders in the Skills panel over IPC; deletion runs through the durable catalog transaction (intent, tombstone, deletionFacts). - Web search capability: DeepSeek native execution is disabled (implemented: false since apache#2972; replay-only via apache#5824; re-enablement tracked in apache#3689), so the matrix row and the dual-wire narrative are marked historical; the removed anthropic-compatible provider type is replaced by custom + resolved apiProtocol (apache#5684). - last_verified refreshed to 2026-10-10 on all three. Refs apache#3522 Generated-by: ZCode docs: scope the deepseek status note and sharpen two pass-3 wordings Automated-review P3s: the native-search disablement applies to the deepseek provider type on the Responses wire (a custom anthropic-messages connection still executes), apache#2972's original reason was the open-responses function-tool serialization with the web_search-ignore reason arriving via apache#5824, and the catalog snapshot never carries a prompt-build rank at all (contextStatus 'unknown' is only for enabled/valid/unshadowed items). Also credits the McpToolCallError fail-closed path and places both budget checks inside callTool. Generated-by: ZCode
Mount the existing WorkHub enablement provider instead of passing the retired enabled prop. This restores Desktop compilation after apache#5938 met the provider-owned switch from apache#5936 without changing production behavior. Generated-by: Maka (gpt-6.1-sol)
…pache#6051) * refactor(workhub): simplify coordination and execution configuration Use the coordinating agent directly, persist WorkHub model settings, scope delegated permissions to executions, and separate steering from stop and delegation. Preserve historical recovery records and return worker missing information through ordinary follow-up messages. Generated-by: Codex * fix(workhub): propagate delegated execution policy and steering questions Preserve delegated permissions across child and graph execution lineage, restore scoped policy from durable Host facts, and update question handling when steering an existing backend. Generated-by: Codex * fix(runtime): support frozen stores in delegated execution policy Use an independent proxy facade so bound methods and permission read overrides do not violate invariants on frozen Host stores. Exercise the production frozen facade shape in the scoped-policy regression test. Generated-by: Codex * feat(desktop): route remote chats through shared WorkHub Add remote message handling settings, durable source-aware replies, and compact interaction choice answers. Generated-by: Codex * fix(core): simplify remote message source labels Generated-by: Codex * fix(desktop): keep message copy actions visible Generated-by: Codex * fix(desktop): size WorkHub rails to message bubbles Generated-by: Codex * feat(workhub): preserve intent and show clarification handoffs Generated-by: Codex * fix(workhub): link result replies to their source task rails Result notification turns had no links unless they delegated again. Derive their Host-scoped task identity from the durable result origin so rails and filters also cover tool-free result summaries. Generated-by: Codex * feat(workhub): add wn current-work and next-prompt shortcut Generated-by: Codex * fix(workhub): show progress and next steps for three recent works Generated-by: Codex * feat(workhub): place concise wn suggestions in composer draft Generated-by: Codex * fix(workhub): simplify answer summaries and balance result spacing Generated-by: Codex * style(workhub): reduce spacing before result notices to 4px Generated-by: Codex * refactor(ui): share transcript disclosure for selected answers and completion Generated-by: Codex * style(workhub): remove handoff content disclosure Generated-by: Codex * style(workhub): remove gap before result notices Generated-by: Codex * style(ui): highlight focused choice instead of picker outline Generated-by: Codex * fix(ui): confirm question answers on option click Generated-by: Codex * fix(desktop): localize WorkHub remote handling settings through catalog Generated-by: Codex * fix(ci): refresh surface inventory for shared transcript disclosure Generated-by: Codex * test(desktop): retain pending choices with keyboard selection Generated-by: Codex * fix(desktop): align story geometry with rails and timestamp sizing Check WorkHub rails against bubble bounds after the shorter-rail design. Give localized usage timestamps 8px more room so Linux font metrics fit without weakening the overflow assertion. Generated-by: Codex * fix(workhub): preserve steering policy across physical successors Resolve the latest durable policy for each physical continuation, including steered ordinary admissions with no sourceMessages. Add production composition coverage proving successor inheritance and restoration on a later user Turn. Use compatibility epoch 214 to distinguish this contract from the open epoch-213 changes. Generated-by: Codex * test(desktop): reconcile WorkHub fixtures after main rebase Provide the shared WorkHub enablement context to the new dock backdrop fixture and refresh the merged UI inventory totals. Generated-by: Codex * fix(protocol): assign WorkHub an unused compatibility epoch Epoch 214 is also declared by open PR apache#5548. Verified all 188 current open PR heads: apache#5394 and apache#5969 use 213, apache#5548 and this PR use 214, and 215 is unused. Move WorkHub to 215; allocation must be rechecked at integration because the base-only CI guard cannot reserve numbers across open branches. Generated-by: Codex
…pache#6043) Part of the apache#3522 docs-verification campaign (Managed workspace group). Scope note: three of the group's five documents (runtime-managed-workspace-baseline-open-v1, -execution-admission-v1, -owner-v1) no longer exist — they were removed intentionally by apache#4174 (refactor: remove dormant Git workspace write path) together with the GitWorkspaceService/ManagedWorkspaceOwner implementation they described. This PR therefore covers the two surviving documents; the group checklist on the tracking issue needs the same correction. Both surviving documents verified clean against main: every symbol, SQLite table (runtime_workspace_epochs/versions/heads, reservations, storage root binding), schema 7-20 narrative, failpoint set, and CI non-blocking claim checked out. Metadata only: - runtime-workspace-version-authority-v1: add front matter (translation_status, last_verified) and refresh the update date (apache#4718 changed content after it). - managed-dependency-storage-authority-v1: last_verified 2026-09-04 -> 2026-10-10 (apache#4718 updated the document without bumping it). Refs apache#3522 Generated-by: ZCode docs: place the ASF license comment directly after the frontmatter Same ASF source-header policy fix as the recovery-resume pass: no blank line between the closing frontmatter delimiter and the license comment. Generated-by: ZCode
…pache#3522) (apache#6038) Part of the apache#3522 docs-verification campaign (Recovery and resume group). Every claim in the group was checked against the code; the stale ones are corrected: - PR B has landed: runtime_continuation_claims, continuation_start_v2, AgentRunLineage, and replayManifestDigest replace the planned events.length high-water, in-process claim, and continuationSource header (which survives only in the legacy run-header decoder). The PR ladder and follow-up gaps now say so. - Storage is SQLite-only: the phase0/phase1 contracts and the main architecture doc no longer describe JSONL as current or SQLite as future; the retired legacy JSONL import is called out as retired. - Runtime Host compatibility epoch 57 -> 206; the desktop code-reading map path to use-shell-resume.ts fixed; the Chinese-only sentence claiming a system reminder after outcome_unknown removed (the system prompt stays byte-stable); the EN doc now mentions the supervisor-wake recovery its translation already described. - The phase1 storage-boundary section, phase3-4 design notes, and the extraction ledger no longer describe file-backed stores as current; the ledger carries a dated erratum for its historical tables. - last_verified refreshed to 2026-10-10 (main docs updated; phase0 and phase1 gain the marker). Refs apache#3522 Generated-by: ZCode docs: address automated review findings on the recovery docs pass - Restore the compatibility epoch's historical value (57 at the apache#3506 change) instead of naming a live epoch that drifts. - Keep PR C in the PR ladder and follow-up gaps; only PR B is marked merged, and the EN/ZH pair stays in sync. - Phase 1: T1/T2 bracket the side effect without making it transactional; operationId is live, not a later phase. - Phase 0: the committed prefix is a runtime_events prefix, and the store the contract runs against is the SQLite RuntimeEvent store. - Ledger erratum: AgentRunLineage lives in packages/runtime; the ADR implementation note names RuntimeBoundaryCursor (V1|V2). Generated-by: ZCode docs: fix the phase0 future-work attribution and sync the zh flowchart The former future work this contract narrated was the SQLite tool journal, not the RuntimeEvent store; phase0 now says it runs against the canonical SQLite RuntimeEvent store with the tool journal since landed. The zh flowchart gains the merged status label its EN counterpart has, and phase0/phase1 move last_verified into front matter. Generated-by: ZCode docs: place the ASF license comment directly after the frontmatter The ASF source-header policy check requires the license comment to immediately follow the closing frontmatter delimiter, without a blank line, matching the convention of the docs that already carry frontmatter. Generated-by: ZCode
Creating a project required typing a name before Choose folder would enable. An empty name is a valid choice: the catalog already names the project after the folder when projects.add is called without one. Leave the name field optional, keep Choose folder available, and pass a trimmed name through only when one was typed. Update en / zh-CN / zh-TW copy to match. Fixes apache#6047
cursor
Bot
force-pushed
the
cursor/optional-new-project-name-e179
branch
from
October 11, 2026 06:17
760b9c6 to
db21e8f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Creating a project in the desktop app required a custom name before Choose folder would enable. An empty name is a valid choice and means “name this project after the folder I pick.”
NewProjectDialognow submits with the name field empty. Choose folder stays available either way. A typed name is still trimmed and applied in the sameprojects.addstep; a blank name is omitted so the existing folder-basename fallback inprojects.addapplies. The en / zh-CN / zh-TW copy no longer says the name has to come first.Fixes apache#6047
Verification
npx biome checkon the changed filesnpm --workspace @maka/ui run buildandnode --test packages/ui/dist/__tests__/new-project-dialog.test.js(4 pass)node --test packages/ui/dist/__tests__/conversation-copy.test.js(7 pass)npm run check:locale-hygienetsc -p apps/desktop/tsconfig.renderer.json --noEmit)node --test --test-force-exit apps/desktop/dist/main/__tests__/project-add-restore.test.js apps/desktop/dist/main/__tests__/task-entry-provider-scope.test.js apps/desktop/dist/main/__tests__/task-entry-controller.test.js(80 pass), including the new “Settings Add with a blank name still opens the folder picker” caseNot run: Electron desktop app / folder-picker UI. Native directory choosers are not available in this environment, so the behavior is checked through the dialog and Settings registration tests rather than a live window.
AI use
Select exactly one:
Tool(s) and scope:
Cursor Grok 4.6 implemented the dialog, copy, caller wiring, and tests from the issue’s planned direction. A human should review before merge. CONTRIBUTING currently asks not to use Grok for Maka contributions pending terms clarification (apache#5746); this PR discloses that use rather than hiding it.
Checklist
Does this PR entail a change in behavior?