{
  "observed_at": "2026-10-14T20:25:13.148733+00:00",
  "repository": "OpenHands/software-agent-sdk",
  "scope": "PRs authored by enyst with a head branch starting claude/umbrella-bug-fixes-, including merged and closed PRs.",
  "writing": "ASD-STE100-inspired plain English; not certified controlled English.",
  "sources": "Summaries of public PR descriptions; not independent code reviews or test reruns.",
  "prs": [
    {
      "number": 5973,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5973",
      "title": "fix(agent-server): answer 409 and keep state when a write loses ownership",
      "category": "Conversation state",
      "heading": "Keep refused writes out of memory",
      "summary": "The server returns 409 when another server owns the conversation. It keeps the previous title, tags and secrets when it cannot save a change.",
      "state": "OPEN",
      "created_at": "2026-10-14T03:47:01Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T18:38:57Z",
      "decision_needed": false
    },
    {
      "number": 5972,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5972",
      "title": "fix(agent-server): post full webhook batches off the event's publish",
      "category": "Events and streaming",
      "heading": "Keep slow webhooks from blocking runs",
      "summary": "The server sends full webhook batches in the background. A slow receiver no longer keeps a finished run busy.",
      "state": "OPEN",
      "created_at": "2026-10-14T03:37:48Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T15:25:09Z",
      "decision_needed": true
    },
    {
      "number": 5968,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5968",
      "title": "fix(agent-server): answer 409 when a continued gateway run waits for confirmation",
      "category": "Gateway and ACP",
      "heading": "Report a paused gateway run at once",
      "summary": "A continued chat request returns 409 when the agent pauses or needs confirmation. The client no longer waits for a timeout.",
      "state": "OPEN",
      "created_at": "2026-10-14T03:04:56Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T03:42:30Z",
      "decision_needed": false
    },
    {
      "number": 5967,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5967",
      "title": "fix(agent-server): report real usage buckets in telemetry outcome events",
      "category": "Configuration and telemetry",
      "heading": "Report known usage in telemetry",
      "summary": "The server reads token and cost totals before it sends the run outcome. Telemetry reports usage ranges instead of “unknown” when totals are available.",
      "state": "OPEN",
      "created_at": "2026-10-14T03:04:52Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T04:30:43Z",
      "decision_needed": false
    },
    {
      "number": 5966,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5966",
      "title": "fix(sdk): keep streamed deltas out of RemoteConversation.state.events",
      "category": "Events and streaming",
      "heading": "Keep token chunks out of saved history",
      "summary": "The Python remote client sends streaming chunks to listeners without adding them to state.events. Its cached history matches the server’s stored events.",
      "state": "OPEN",
      "created_at": "2026-10-14T03:04:16Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T03:45:11Z",
      "decision_needed": false
    },
    {
      "number": 5965,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5965",
      "title": "fix(sdk): deliver streamed deltas to RemoteConversation token_callbacks",
      "category": "Events and streaming",
      "heading": "Deliver remote token callbacks",
      "summary": "The Python remote client calls token_callbacks as token chunks arrive. Applications can display the agent’s text while it is generated.",
      "state": "OPEN",
      "created_at": "2026-10-14T03:00:45Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T03:42:54Z",
      "decision_needed": false
    },
    {
      "number": 5964,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5964",
      "title": "fix(agent-server): describe the secret-key fallback of TelemetrySpec.salt",
      "category": "Configuration and telemetry",
      "heading": "Explain when telemetry IDs stay the same",
      "summary": "The API description explains that telemetry uses the server secret when no salt is set. Operators can see why conversation IDs remain linkable across restarts.",
      "state": "OPEN",
      "created_at": "2026-10-14T02:59:25Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T04:00:42Z",
      "decision_needed": false
    },
    {
      "number": 5958,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5958",
      "title": "fix(agent-server): reject a create whose agent tool module cannot be imported",
      "category": "Tools and extensions",
      "heading": "Reject tools the server cannot load",
      "summary": "The server rejects a new conversation if it cannot import a required custom tool module. It no longer accepts the conversation and fails on its first message.",
      "state": "OPEN",
      "created_at": "2026-10-14T02:34:24Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T04:42:12Z",
      "decision_needed": true
    },
    {
      "number": 5957,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5957",
      "title": "fix(typescript-client): type GitChange.status with the server's wire values",
      "category": "TypeScript client",
      "heading": "Match Git status types to the API",
      "summary": "The TypeScript client uses the Git status values that the server sends, such as UPDATED. Applications can compare these values without incorrect type errors.",
      "state": "OPEN",
      "created_at": "2026-10-14T02:30:20Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T03:28:38Z",
      "decision_needed": false
    },
    {
      "number": 5956,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5956",
      "title": "fix(typescript): resolve updateConversation with the updated conversation",
      "category": "TypeScript client",
      "heading": "Return the updated conversation",
      "summary": "The TypeScript updateConversation method returns the updated conversation data. Callers receive its ID and title instead of only a success flag.",
      "state": "OPEN",
      "created_at": "2026-10-14T02:29:17Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T03:20:31Z",
      "decision_needed": true
    },
    {
      "number": 5955,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5955",
      "title": "fix(agent-server): reserve the run slot before a gateway turn saves its message",
      "category": "Gateway and ACP",
      "heading": "Avoid duplicate messages after a busy response",
      "summary": "The gateway reserves a run slot before it saves a continued chat message. A refused request returns 429 without adding a message that a retry would duplicate.",
      "state": "OPEN",
      "created_at": "2026-10-14T02:29:10Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T03:30:41Z",
      "decision_needed": true
    },
    {
      "number": 5954,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5954",
      "title": "fix(agent-server): answer /run 409 without waiting for the state lock",
      "category": "Conversation state",
      "heading": "Respond quickly when a run is already active",
      "summary": "The run endpoint returns 409 without waiting for a long tool call to finish. The Python remote client can then wait for the existing run without a trigger timeout.",
      "state": "OPEN",
      "created_at": "2026-10-14T02:28:26Z",
      "review_decision": "REVIEW_REQUIRED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T03:36:05Z",
      "decision_needed": false
    },
    {
      "number": 5953,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5953",
      "title": "fix(agent-server): post webhook events that fill the buffer during an in-flight batch",
      "category": "Events and streaming",
      "heading": "Send webhook batches that fill during a send",
      "summary": "The server checks the webhook buffer after a batch finishes sending. It sends another full batch at once instead of waiting for a timer or new events.",
      "state": "OPEN",
      "created_at": "2026-10-14T02:27:21Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T03:52:35Z",
      "decision_needed": false
    },
    {
      "number": 5951,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5951",
      "title": "fix(agent-server): let OH_*_IS_NONE=1 clear a config file value",
      "category": "Configuration and telemetry",
      "heading": "Let environment settings clear file values",
      "summary": "An OH_*_IS_NONE=1 setting clears a nullable value from the configuration file. The file value no longer overrides an explicit request for null.",
      "state": "OPEN",
      "created_at": "2026-10-14T02:25:48Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T03:22:16Z",
      "decision_needed": false
    },
    {
      "number": 5950,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5950",
      "title": "fix(sdk): pass events missed during a WebSocket reconnect to RemoteConversation callbacks",
      "category": "Events and streaming",
      "heading": "Deliver events missed during reconnect",
      "summary": "The Python remote client calls listeners for stored events recovered after a WebSocket reconnect. A live display no longer misses those events.",
      "state": "OPEN",
      "created_at": "2026-10-14T02:25:36Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T04:27:30Z",
      "decision_needed": false
    },
    {
      "number": 5949,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5949",
      "title": "fix(agent-server): report deferred_init true from initialized deferred pods",
      "category": "Configuration and telemetry",
      "heading": "Identify pods that started with deferred setup",
      "summary": "Telemetry keeps the pod’s original deferred_init flag after initialization. Operators can distinguish these pods from servers that started normally.",
      "state": "OPEN",
      "created_at": "2026-10-14T02:25:29Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T16:01:51Z",
      "decision_needed": true
    },
    {
      "number": 5948,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5948",
      "title": "fix(agent-server): refuse overlapping chat turns on one conversation with 409",
      "category": "Gateway and ACP",
      "heading": "Refuse overlapping turns in one chat",
      "summary": "The gateway returns 409 if another request already uses the same conversation. Each accepted request receives the answer to its own turn.",
      "state": "OPEN",
      "created_at": "2026-10-14T02:24:27Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T03:42:56Z",
      "decision_needed": true
    },
    {
      "number": 5945,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5945",
      "title": "fix(agent-server): remove the per-server TMUX_TMPDIR on shutdown",
      "category": "Configuration and telemetry",
      "heading": "Remove temporary tmux folders",
      "summary": "The server removes the tmux folder it created when it shuts down normally. Repeated starts no longer leave those folders behind.",
      "state": "MERGED",
      "created_at": "2026-10-14T02:23:50Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": "2026-10-14T18:30:41Z",
      "closed_at": "2026-10-14T18:30:41Z",
      "updated_at": "2026-10-14T18:30:45Z",
      "decision_needed": true
    },
    {
      "number": 5944,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5944",
      "title": "fix(agent-server): report a failed skills sync fetch as an error",
      "category": "Tools and extensions",
      "heading": "Report a failed skills sync",
      "summary": "The sync endpoint reports an error when it cannot fetch repository updates. It no longer describes use of an old cached copy as a successful sync.",
      "state": "MERGED",
      "created_at": "2026-10-14T02:22:51Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": "2026-10-14T15:49:41Z",
      "closed_at": "2026-10-14T15:49:41Z",
      "updated_at": "2026-10-14T15:49:44Z",
      "decision_needed": true
    },
    {
      "number": 5943,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5943",
      "title": "fix(agent-server): correct WebhookSpec base_url and flush_delay descriptions",
      "category": "Configuration and telemetry",
      "heading": "Correct the webhook API descriptions",
      "summary": "The API description gives the actual event URL, including the conversation ID. It also explains that new events do not restart the flush timer.",
      "state": "OPEN",
      "created_at": "2026-10-14T02:22:05Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T02:58:36Z",
      "decision_needed": false
    },
    {
      "number": 5931,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5931",
      "title": "fix(agent-server): answer uploads onto a directory or below a file with 400",
      "category": "Files and Git",
      "heading": "Report invalid upload targets as client errors",
      "summary": "An upload returns 400 if its target is a directory or a parent is a regular file. The client can distinguish an invalid path from a server failure.",
      "state": "MERGED",
      "created_at": "2026-10-14T02:11:11Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": "2026-10-14T20:24:23Z",
      "closed_at": "2026-10-14T20:24:23Z",
      "updated_at": "2026-10-14T20:24:26Z",
      "decision_needed": false
    },
    {
      "number": 5929,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5929",
      "title": "fix(agent-server): tie uvicorn proxy_headers to trust_forwarded_headers",
      "category": "Browser and app backends",
      "heading": "Apply the forwarded-header trust setting",
      "summary": "The server only lets proxy headers change the request scheme when trust_forwarded_headers allows it. Untrusted headers no longer change the app bridge’s origin check.",
      "state": "MERGED",
      "created_at": "2026-10-14T01:59:49Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": "2026-10-14T18:28:08Z",
      "closed_at": "2026-10-14T18:28:08Z",
      "updated_at": "2026-10-14T18:28:11Z",
      "decision_needed": true
    },
    {
      "number": 5927,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5927",
      "title": "fix(agent-server): answer 409 for meta-profile activation over a corrupted settings file",
      "category": "Profiles and secrets",
      "heading": "Report unreadable settings during activation",
      "summary": "Meta-profile activation returns 409 when the settings file is corrupt or uses another encryption key. The response no longer exposes the file path in an unhandled error.",
      "state": "OPEN",
      "created_at": "2026-10-14T01:58:39Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T02:54:55Z",
      "decision_needed": false
    },
    {
      "number": 5924,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5924",
      "title": "fix(agent-server): apply enable_browser to /server_info usable_tools",
      "category": "Tools and extensions",
      "heading": "Hide a disabled browser from usable tools",
      "summary": "The server leaves the browser out of server_info.usable_tools when enable_browser is false. Clients no longer offer a tool that conversations cannot use.",
      "state": "OPEN",
      "created_at": "2026-10-14T01:53:24Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T14:58:26Z",
      "decision_needed": true
    },
    {
      "number": 5921,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5921",
      "title": "fix(agent-server): leave web-researcher out of sub-agents when the browser is disabled",
      "category": "Tools and extensions",
      "heading": "Hide the browser-only sub-agent when disabled",
      "summary": "The server leaves web-researcher out of the sub-agent list when the browser is disabled. Clients no longer offer a sub-agent with no usable tool.",
      "state": "MERGED",
      "created_at": "2026-10-14T01:49:25Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": "2026-10-14T20:19:55Z",
      "closed_at": "2026-10-14T20:19:55Z",
      "updated_at": "2026-10-14T20:19:57Z",
      "decision_needed": true
    },
    {
      "number": 5920,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5920",
      "title": "fix(agent-server): stop bridging to a crashed Canvas backend",
      "category": "Browser and app backends",
      "heading": "Stop forwarding to a crashed app backend",
      "summary": "The app bridge detects a dead backend before it forwards requests or creates sessions. Clients receive a backend status error instead of a misleading container error.",
      "state": "MERGED",
      "created_at": "2026-10-14T01:47:57Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": "2026-10-14T15:45:38Z",
      "closed_at": "2026-10-14T15:45:38Z",
      "updated_at": "2026-10-14T15:45:41Z",
      "decision_needed": true
    },
    {
      "number": 5918,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5918",
      "title": "fix(agent-server): keep the client's body framing in proxied requests",
      "category": "Browser and app backends",
      "heading": "Preserve request body framing through the proxy",
      "summary": "The proxy preserves the client’s body length or chunked framing. Backends that read Content-Length can receive the full request body.",
      "state": "MERGED",
      "created_at": "2026-10-14T01:46:42Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": "2026-10-14T18:45:37Z",
      "closed_at": "2026-10-14T18:45:37Z",
      "updated_at": "2026-10-14T18:45:40Z",
      "decision_needed": false
    },
    {
      "number": 5917,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5917",
      "title": "fix(agent-server): refuse a non-gzip canvas backend artifact with 409",
      "category": "Browser and app backends",
      "heading": "Reject invalid app backend archives",
      "summary": "Backend preparation returns 409 when an artifact is not a valid gzip tar archive. The client receives a reason instead of an unhandled 500 error.",
      "state": "OPEN",
      "created_at": "2026-10-14T01:46:14Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T02:53:09Z",
      "decision_needed": false
    },
    {
      "number": 5916,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5916",
      "title": "fix(agent-server): drop upstream Date and Server from proxied responses",
      "category": "Browser and app backends",
      "heading": "Remove duplicate proxy response headers",
      "summary": "The proxy removes the upstream Date and Server headers before the server adds its own. Responses no longer contain duplicate dates or disclose the backend’s server header.",
      "state": "OPEN",
      "created_at": "2026-10-14T01:45:21Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T02:46:44Z",
      "decision_needed": false
    },
    {
      "number": 5909,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5909",
      "title": "fix(sdk): accept the documented github:owner/repo/<path> install source",
      "category": "Tools and extensions",
      "heading": "Accept the documented GitHub install path",
      "summary": "Extension installation accepts github:owner/repo/path. Users can select a folder within the repository through the documented shorthand.",
      "state": "MERGED",
      "created_at": "2026-10-14T01:27:53Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": "2026-10-14T18:28:41Z",
      "closed_at": "2026-10-14T18:28:42Z",
      "updated_at": "2026-10-14T18:28:45Z",
      "decision_needed": true
    },
    {
      "number": 5908,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5908",
      "title": "fix(tools): find Playwright Chromium under PLAYWRIGHT_BROWSERS_PATH",
      "category": "Tools and extensions",
      "heading": "Find Chromium in the configured Playwright folder",
      "summary": "The browser tool checks PLAYWRIGHT_BROWSERS_PATH for Chromium. Containers and CI systems can use the browser they installed there.",
      "state": "OPEN",
      "created_at": "2026-10-14T01:27:25Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T03:02:02Z",
      "decision_needed": false
    },
    {
      "number": 5907,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5907",
      "title": "fix(agent-server): don't advertise a VS Code URL while VS Code is not running",
      "category": "Browser and app backends",
      "heading": "Do not offer a dead VS Code link",
      "summary": "The server returns no VS Code URL when VS Code is not running. It no longer offers a broken link that contains a session token.",
      "state": "MERGED",
      "created_at": "2026-10-14T01:24:24Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": "2026-10-14T18:48:50Z",
      "closed_at": "2026-10-14T18:48:50Z",
      "updated_at": "2026-10-14T18:48:53Z",
      "decision_needed": true
    },
    {
      "number": 5906,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5906",
      "title": "fix(agent-server): answer 400/422 when refreshing an unfetchable skill or plugin",
      "category": "Tools and extensions",
      "heading": "Report skill and plugin refresh errors clearly",
      "summary": "Refresh returns 400 or 422 for an unavailable source, invalid content or a local installation. These cases no longer appear as unhandled server failures.",
      "state": "OPEN",
      "created_at": "2026-10-14T01:22:53Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T03:15:02Z",
      "decision_needed": true
    },
    {
      "number": 5905,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5905",
      "title": "fix(sdk): name a manifest-less git repository plugin after the repository",
      "category": "Tools and extensions",
      "heading": "Give plugins a stable repository name",
      "summary": "A Git plugin without a root manifest takes its name from the repository. Its installed name no longer includes the clone cache’s URL hash.",
      "state": "MERGED",
      "created_at": "2026-10-14T01:21:35Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": "2026-10-14T20:17:14Z",
      "closed_at": "2026-10-14T20:17:14Z",
      "updated_at": "2026-10-14T20:17:16Z",
      "decision_needed": true
    },
    {
      "number": 5904,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5904",
      "title": "fix(agent-server): keep the managed-key refresh hook after an LLM switch",
      "category": "Profiles and secrets",
      "heading": "Keep managed-key refresh after a model switch",
      "summary": "A replacement LLM receives the managed-key refresh hook. A model switch no longer disables the configured refresh and retry after an authentication failure.",
      "state": "OPEN",
      "created_at": "2026-10-14T01:20:48Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T03:07:27Z",
      "decision_needed": false
    },
    {
      "number": 5903,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5903",
      "title": "fix(agent-server): clear the skills marketplace cache on sync",
      "category": "Tools and extensions",
      "heading": "Refresh the marketplace list after sync",
      "summary": "Skills sync clears the marketplace cache. The next catalog request can show the updated repository instead of an old or empty list.",
      "state": "MERGED",
      "created_at": "2026-10-14T01:20:40Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": "2026-10-14T20:14:37Z",
      "closed_at": "2026-10-14T20:14:37Z",
      "updated_at": "2026-10-14T20:14:39Z",
      "decision_needed": false
    },
    {
      "number": 5902,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5902",
      "title": "fix(agent-server): make file upload overwrites atomic",
      "category": "Files and Git",
      "heading": "Protect existing files during uploads",
      "summary": "The server writes an upload to a temporary file before replacing the destination. A failed overwrite no longer truncates the previous file.",
      "state": "OPEN",
      "created_at": "2026-10-14T01:20:29Z",
      "review_decision": "REVIEW_REQUIRED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T02:22:50Z",
      "decision_needed": false
    },
    {
      "number": 5901,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5901",
      "title": "fix(sdk): reject skill installs with unparsable frontmatter as invalid",
      "category": "Tools and extensions",
      "heading": "Reject invalid skill metadata cleanly",
      "summary": "The installer treats unreadable YAML frontmatter as an invalid skill. The API returns 422 instead of exposing an unhandled parser error.",
      "state": "OPEN",
      "created_at": "2026-10-14T01:18:35Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T13:26:24Z",
      "decision_needed": false
    },
    {
      "number": 5898,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5898",
      "title": "fix(agent-server): map profile-store errors in scoped secrets list",
      "category": "Profiles and secrets",
      "heading": "Handle profile errors when listing scoped secrets",
      "summary": "The secrets endpoint maps invalid agent profiles to 400 and a busy profile store to 503. These cases no longer return an unhandled 500 error.",
      "state": "OPEN",
      "created_at": "2026-10-14T01:14:51Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T12:16:14Z",
      "decision_needed": false
    },
    {
      "number": 5892,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5892",
      "title": "fix(agent-server): report applied=false when meta-profile activation cannot route",
      "category": "Profiles and secrets",
      "heading": "Report when a meta-profile was not applied",
      "summary": "Activation reports applied=false when the agent cannot use model routing. Clients no longer receive an apparent success for a profile that was not activated.",
      "state": "OPEN",
      "created_at": "2026-10-14T01:11:32Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T02:03:17Z",
      "decision_needed": true
    },
    {
      "number": 5891,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5891",
      "title": "fix(sdk): keep edge whitespace on the original side of a git diff",
      "category": "Files and Git",
      "heading": "Preserve whitespace on both sides of a diff",
      "summary": "The SDK keeps indentation and trailing blank lines in the original Git content. An unchanged file no longer shows a false diff.",
      "state": "MERGED",
      "created_at": "2026-10-14T01:09:30Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": "2026-10-14T20:01:27Z",
      "closed_at": "2026-10-14T20:01:27Z",
      "updated_at": "2026-10-14T20:01:30Z",
      "decision_needed": true
    },
    {
      "number": 5887,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5887",
      "title": "fix(agent-server): refuse meta-profiles that can never route",
      "category": "Profiles and secrets",
      "heading": "Reject a router with no routing choices",
      "summary": "The server rejects a meta-profile that cannot select a destination. It no longer stores a configuration that makes a paid classifier call with no usable choices.",
      "state": "OPEN",
      "created_at": "2026-10-14T01:02:27Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T01:53:49Z",
      "decision_needed": true
    },
    {
      "number": 5886,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5886",
      "title": "fix(agent-server): answer gateway errors when OpenAI device login fails upstream",
      "category": "Gateway and ACP",
      "heading": "Report upstream device-login failures",
      "summary": "The OpenAI device-login endpoints return gateway errors for upstream connection failures, timeouts and error responses. Clients can distinguish a provider problem from a local server failure.",
      "state": "OPEN",
      "created_at": "2026-10-14T01:01:52Z",
      "review_decision": "REVIEW_REQUIRED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T12:14:52Z",
      "decision_needed": true
    },
    {
      "number": 5885,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5885",
      "title": "fix(sdk): drop Bedrock-only ids from the supported model list",
      "category": "Profiles and secrets",
      "heading": "Remove Bedrock-only models from direct-provider lists",
      "summary": "The model list excludes Bedrock-only IDs when AWS credentials are unavailable. Users of a direct provider no longer select an ID that requires AWS.",
      "state": "OPEN",
      "created_at": "2026-10-14T01:00:47Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T11:17:12Z",
      "decision_needed": false
    },
    {
      "number": 5884,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5884",
      "title": "fix(sdk): expand ~ in OH_PERSISTENCE_DIR for the meta-profile store",
      "category": "Profiles and secrets",
      "heading": "Use the home folder for meta-profile storage",
      "summary": "The meta-profile store expands ~ in OH_PERSISTENCE_DIR. It writes beside the other settings instead of creating a folder literally named ~.",
      "state": "OPEN",
      "created_at": "2026-10-14T01:00:24Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T10:25:04Z",
      "decision_needed": false
    },
    {
      "number": 5877,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5877",
      "title": "fix(ts-client): match agent-profile payload types to the server models",
      "category": "TypeScript client",
      "heading": "Match agent-profile types to server data",
      "summary": "The TypeScript client adds the profile fields the server sends and removes incorrect requirements. Profile editors can read and save the actual API payloads.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:48:37Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T10:30:30Z",
      "decision_needed": true
    },
    {
      "number": 5876,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5876",
      "title": "fix(agent-server): keep agent profile identity for .json-suffixed names",
      "category": "Profiles and secrets",
      "heading": "Keep profile identity for names ending in .json",
      "summary": "The server treats a profile name with or without .json as the same name. Saving it again preserves its ID and keeps active references valid.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:47:29Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T08:55:37Z",
      "decision_needed": true
    },
    {
      "number": 5875,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5875",
      "title": "fix(agent-server): honor UTC offsets in bash event timestamp filters",
      "category": "Commands",
      "heading": "Respect time zones in command event filters",
      "summary": "Bash event searches apply the UTC offset in each timestamp. Different timestamp forms for the same instant return the same events.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:44:42Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T09:11:06Z",
      "decision_needed": false
    },
    {
      "number": 5874,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5874",
      "title": "fix(agent-server): describe the real materialize report in the seed docstring",
      "category": "Profiles and secrets",
      "heading": "Correct the default-profile setup description",
      "summary": "The source documentation names the actual materialize result for a missing default LLM profile. It no longer tells readers to look for a field that is not returned.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:44:04Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T09:08:31Z",
      "decision_needed": false
    },
    {
      "number": 5869,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5869",
      "title": "fix(sdk): classify a BadRequestError carrying HTTP 401/403 as an auth error",
      "category": "Profiles and secrets",
      "heading": "Classify HTTP 401 and 403 as authentication failures",
      "summary": "The SDK recognizes authentication status codes even when the provider library calls them BadRequestError. A bad key no longer appears as a general request error.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:36:58Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T08:34:48Z",
      "decision_needed": false
    },
    {
      "number": 5868,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5868",
      "title": "fix(agent-server): guard LLM profile delete through the .json alias",
      "category": "Profiles and secrets",
      "heading": "Apply profile deletion guards to .json aliases",
      "summary": "Deleting an LLM profile through its .json name checks existing references. Rename and delete also update active pointers through that alias.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:36:52Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T07:22:32Z",
      "decision_needed": true
    },
    {
      "number": 5867,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5867",
      "title": "fix(agent-server): reject MCP OAuth callback URLs with a bad port as 400",
      "category": "Tools and extensions",
      "heading": "Reject invalid OAuth callback ports",
      "summary": "The MCP OAuth callback endpoint returns 400 for a non-numeric or out-of-range port. Invalid URLs no longer cause an unhandled server error.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:36:15Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T07:41:01Z",
      "decision_needed": false
    },
    {
      "number": 5866,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5866",
      "title": "fix(agent-server): answer replayed MCP OAuth callbacks with the job status",
      "category": "Tools and extensions",
      "heading": "Handle repeated OAuth callbacks",
      "summary": "The MCP OAuth callback endpoint returns the job status after the job ends. Repeated submissions no longer try to contact a closed callback server.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:35:21Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T06:47:24Z",
      "decision_needed": true
    },
    {
      "number": 5864,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5864",
      "title": "fix(agent-server): skip the workspaces save when a write changes nothing",
      "category": "Files and Git",
      "heading": "Skip workspace writes that change nothing",
      "summary": "The workspace registry does not rewrite its file for a no-op request. Deleting an unknown path no longer creates a file or fails because storage is read-only.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:32:41Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T01:13:42Z",
      "decision_needed": false
    },
    {
      "number": 5865,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5865",
      "title": "fix(agent-server): refuse PATCH /api/settings pointers to missing profiles",
      "category": "Profiles and secrets",
      "heading": "Reject settings that name missing profiles",
      "summary": "The settings endpoint checks active agent and meta-profile references before saving them. It no longer accepts a pointer to a profile that does not exist.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:32:41Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T06:22:45Z",
      "decision_needed": true
    },
    {
      "number": 5859,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5859",
      "title": "fix(agent-server): URL-encode the VS Code URL's folder and token",
      "category": "Browser and app backends",
      "heading": "Encode VS Code folders and tokens in links",
      "summary": "The server URL-encodes the folder and token query values. Spaces, ampersands and hash signs no longer make VS Code open the wrong folder.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:26:20Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T01:44:12Z",
      "decision_needed": true
    },
    {
      "number": 5858,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5858",
      "title": "fix(sdk): persist a mid-step switch_llm before it returns",
      "category": "Conversation state",
      "heading": "Save a model switch before confirming it",
      "summary": "A model or profile switch made during an agent step is saved before the endpoint returns. Reads and restarts no longer see the previous model after an acknowledged switch.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:24:19Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T05:37:41Z",
      "decision_needed": false
    },
    {
      "number": 5857,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5857",
      "title": "fix(sdk): diff a working-tree-deleted file against its base text",
      "category": "Files and Git",
      "heading": "Show diffs for deleted working files",
      "summary": "The SDK compares a deleted file with its original Git content. The Changes view can show the deletion instead of returning “file does not exist”.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:23:36Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T01:36:05Z",
      "decision_needed": false
    },
    {
      "number": 5856,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5856",
      "title": "fix(agent-server): report the uploaded file_size in the upload response",
      "category": "Files and Git",
      "heading": "Return the uploaded byte count",
      "summary": "The upload response includes file_size. Python and TypeScript callers can report how many bytes they wrote instead of receiving no size.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:23:25Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T04:27:55Z",
      "decision_needed": false
    },
    {
      "number": 5855,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5855",
      "title": "fix(agent-server): accept the workspace cookie on the Docker-mode workspace root",
      "category": "Browser and app backends",
      "heading": "Accept the workspace cookie without a trailing slash",
      "summary": "In Docker mode, the workspace root accepts its session cookie with or without a trailing slash. Embedded workspace pages no longer fail authentication on the shorter URL.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:23:01Z",
      "review_decision": "REVIEW_REQUIRED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T12:19:39Z",
      "decision_needed": false
    },
    {
      "number": 5854,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5854",
      "title": "fix(agent-server): describe nested-repository resolution in archive params",
      "category": "Files and Git",
      "heading": "Explain which folder an archive contains",
      "summary": "The archive API description explains its nested-repository selection. Users can see when files beside the selected repository will be left out.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:22:31Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T01:07:46Z",
      "decision_needed": true
    },
    {
      "number": 5853,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5853",
      "title": "fix(agent-server): page search_subdirs past names that differ only by case",
      "category": "Files and Git",
      "heading": "Advance folder pages past case-only name differences",
      "summary": "Directory search uses a cursor that distinguishes names such as Foo and foo. Clients can load the next page without repeating the same folder forever.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:21:43Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T01:26:41Z",
      "decision_needed": false
    },
    {
      "number": 5852,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5852",
      "title": "fix(sdk): install the edited profile when switch_profile re-switches",
      "category": "Profiles and secrets",
      "heading": "Use the latest saved profile when switching",
      "summary": "Switching back to a profile loads its current configuration. A conversation no longer reuses an old model or key cached before the profile was edited.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:21:17Z",
      "review_decision": "REVIEW_REQUIRED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T06:03:56Z",
      "decision_needed": true
    },
    {
      "number": 5851,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5851",
      "title": "fix(agent-server): document 422 for an invalid secret name",
      "category": "Profiles and secrets",
      "heading": "Document the correct invalid-secret status",
      "summary": "The API description says an invalid secret name returns 422. It now matches the status the GET and DELETE endpoints already return.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:20:46Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T01:07:36Z",
      "decision_needed": false
    },
    {
      "number": 5850,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5850",
      "title": "fix(agent-server): keep conversations with running scoped bash commands loaded",
      "category": "Commands",
      "heading": "Keep running commands alive during idle cleanup",
      "summary": "The server keeps a conversation loaded while a scoped Bash command runs. Idle cleanup no longer kills the command before it reports an exit code.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:17:26Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T04:19:12Z",
      "decision_needed": false
    },
    {
      "number": 5848,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5848",
      "title": "fix(sdk): list git changes of a repository subdirectory relative to it",
      "category": "Files and Git",
      "heading": "Use one path base for subfolder Git changes",
      "summary": "Git changes requested from a repository subfolder are relative to that subfolder. The response no longer mixes repository paths with subfolder paths.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:16:53Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T01:00:06Z",
      "decision_needed": true
    },
    {
      "number": 5842,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5842",
      "title": "fix(agent-server): apply bash order__gt filter before paging",
      "category": "Commands",
      "heading": "Filter command events before making pages",
      "summary": "Bash event search applies order__gt before the page limit. Polling clients can receive later output chunks and the command’s exit code.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:10:01Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T20:23:03Z",
      "decision_needed": false
    },
    {
      "number": 5840,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5840",
      "title": "fix(agent-server): answer 422 for a malformed id on scoped bash routes",
      "category": "Commands",
      "heading": "Reject malformed conversation IDs on Bash routes",
      "summary": "Conversation-scoped Bash endpoints return 422 when an ID is not a UUID. They no longer read missing request state and fail with 500.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:08:56Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T03:23:06Z",
      "decision_needed": false
    },
    {
      "number": 5832,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5832",
      "title": "fix(agent-server): keep resumed goal loops within max_iterations",
      "category": "Conversation state",
      "heading": "Keep resumed goal loops within their limit",
      "summary": "Resuming a goal does not add agent rounds beyond max_iterations. An interrupted judge call no longer causes the agent to exceed the user’s limit.",
      "state": "OPEN",
      "created_at": "2026-10-14T00:01:15Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T04:22:09Z",
      "decision_needed": false
    },
    {
      "number": 5830,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5830",
      "title": "fix(sdk): refuse a live ACP switch to a model the session does not offer with 400",
      "category": "Gateway and ACP",
      "heading": "Reject an unavailable live ACP model",
      "summary": "A live ACP model switch returns 400 if the session does not offer that model. Clients no longer see a server error for a model choice that cannot work.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:56:02Z",
      "review_decision": "REVIEW_REQUIRED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T02:44:06Z",
      "decision_needed": true
    },
    {
      "number": 5827,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5827",
      "title": "fix(agent-server): ignore pending credential bindings for non-ACP conversations",
      "category": "Gateway and ACP",
      "heading": "Ignore ACP credentials for non-ACP conversations",
      "summary": "Pending runtime credential bindings are not applied to regular conversations. Those conversations no longer become blocked on credentials they do not use.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:55:32Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T02:52:02Z",
      "decision_needed": true
    },
    {
      "number": 5826,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5826",
      "title": "fix(agent-server): read agent_final_response from the active branch",
      "category": "Conversation state",
      "heading": "Read the final answer from the active branch",
      "summary": "The final-response endpoint reads only the conversation’s current branch. After navigation, it no longer returns an answer from an abandoned branch.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:54:23Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T03:18:49Z",
      "decision_needed": false
    },
    {
      "number": 5821,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5821",
      "title": "fix(agent-server): answer 409 when condense has no request-handling condenser",
      "category": "Conversation state",
      "heading": "Explain when context condensation is unavailable",
      "summary": "The condense endpoint returns 409 if the agent has no condenser that can handle the request. Clients can distinguish this configuration limit from a server failure.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:47:33Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T00:40:56Z",
      "decision_needed": true
    },
    {
      "number": 5819,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5819",
      "title": "fix(agent-server): return 404 from ask_agent for an unknown conversation",
      "category": "Conversation state",
      "heading": "Return 404 for questions to unknown conversations",
      "summary": "The ask_agent endpoint returns 404 when the conversation does not exist. A missing conversation no longer looks like a model or server failure.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:45:38Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T00:33:55Z",
      "decision_needed": false
    },
    {
      "number": 5818,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5818",
      "title": "fix(sdk): publish a user message before its last_user_message_id update",
      "category": "Events and streaming",
      "heading": "Publish user messages in stored order",
      "summary": "The SDK publishes a user message before the state update that refers to it. Clients that resume from event sequence numbers no longer risk skipping the message.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:44:07Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T02:17:05Z",
      "decision_needed": false
    },
    {
      "number": 5817,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5817",
      "title": "fix(agent-server): return 404/null for an unknown event id",
      "category": "Events and streaming",
      "heading": "Handle missing event IDs without failing the batch",
      "summary": "A single missing event returns 404. A batch keeps the other events and returns null in the missing event’s position.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:42:07Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T00:39:17Z",
      "decision_needed": false
    },
    {
      "number": 5816,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5816",
      "title": "fix(agent-server): refuse switch_llm/switch_profile on ACP conversations",
      "category": "Gateway and ACP",
      "heading": "Refuse SDK model switches on ACP conversations",
      "summary": "The server rejects switch_llm and switch_profile for ACP conversations. It no longer reports a successful switch that cannot change the subprocess’s model.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:41:21Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T00:46:27Z",
      "decision_needed": true
    },
    {
      "number": 5815,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5815",
      "title": "fix(sdk): keep one copy of a plugin's hooks when it is loaded twice",
      "category": "Tools and extensions",
      "heading": "Load a plugin’s hooks only once",
      "summary": "Loading the same plugin twice keeps one copy of its hooks. A retry no longer makes each hook run twice for a user message.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:41:15Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T00:35:01Z",
      "decision_needed": false
    },
    {
      "number": 5814,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5814",
      "title": "fix(agent-server): return 404 for unknown ids on pause, interrupt, PATCH and DELETE",
      "category": "Conversation state",
      "heading": "Use 404 for unknown conversation actions",
      "summary": "Pause, interrupt, update and delete return 404 for an unknown conversation ID. Clients no longer receive a misleading bad request or successful update response.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:40:25Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T00:24:13Z",
      "decision_needed": false
    },
    {
      "number": 5812,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5812",
      "title": "docs(typescript): describe the pre-run 200-and-defer switchAcpModel behaviour",
      "category": "Gateway and ACP",
      "heading": "Document ACP model changes before the first run",
      "summary": "The TypeScript documentation explains that a pre-run model switch returns 200 and saves the choice for later. It no longer describes a 409 response that the server does not send.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:37:56Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T00:19:45Z",
      "decision_needed": false
    },
    {
      "number": 5811,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5811",
      "title": "fix(sdk): refuse a blank ACP model before the first run",
      "category": "Gateway and ACP",
      "heading": "Reject a blank ACP model before the first run",
      "summary": "The SDK rejects empty or whitespace-only model IDs before an ACP session starts. It no longer saves a model choice that a live session would refuse.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:37:48Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T00:06:01Z",
      "decision_needed": false
    },
    {
      "number": 5805,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5805",
      "title": "fix(agent-server): reject non-user roles on POST events with 422",
      "category": "Conversation state",
      "heading": "Reject non-user input messages before initialization",
      "summary": "The events endpoint returns 422 for assistant, system or tool input roles. It rejects them before creating a system prompt or initializing the agent.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:31:06Z",
      "review_decision": "REVIEW_REQUIRED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T04:23:16Z",
      "decision_needed": true
    },
    {
      "number": 5803,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5803",
      "title": "fix(agent-server): stamp callback events when they are appended",
      "category": "Events and streaming",
      "heading": "Timestamp callback events when they enter the log",
      "summary": "The server timestamps callback events when it appends them. Timestamp-based history reads no longer miss updates created earlier but stored later.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:29:37Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T00:12:31Z",
      "decision_needed": false
    },
    {
      "number": 5802,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5802",
      "title": "fix(agent-server): reject a whitespace-only conversation title on PATCH",
      "category": "Conversation state",
      "heading": "Reject titles that contain only whitespace",
      "summary": "The update endpoint returns 422 for a whitespace-only title. It no longer clears the existing title and prevents automatic title generation.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:27:33Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T00:04:17Z",
      "decision_needed": false
    },
    {
      "number": 5798,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5798",
      "title": "fix(sdk): refuse a non-object discriminated-union input with a ValidationError",
      "category": "Profiles and secrets",
      "heading": "Reject secret values with the wrong JSON shape",
      "summary": "The SDK reports a validation error when a discriminated-union value is not an object. Invalid secret strings, numbers, booleans or null produce 422 instead of an internal error.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:22:08Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T23:53:36Z",
      "decision_needed": true
    },
    {
      "number": 5797,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5797",
      "title": "fix(agent-server): apply init-delivered allow_cors_origins to CORS",
      "category": "Configuration and telemetry",
      "heading": "Apply CORS origins delivered during initialization",
      "summary": "The server updates its browser-origin checks from the initialization settings. Browsers from those allowed origins can pass the preflight request.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:20:51Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T23:51:57Z",
      "decision_needed": false
    },
    {
      "number": 5796,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5796",
      "title": "fix(agent-server): reject MCP servers with neither command nor url",
      "category": "Tools and extensions",
      "heading": "Reject MCP entries with no command or URL",
      "summary": "The settings endpoint rejects an MCP server with neither command nor url. One empty entry no longer prevents tools from valid neighboring entries from loading.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:18:02Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T01:33:13Z",
      "decision_needed": true
    },
    {
      "number": 5795,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5795",
      "title": "fix(agent-server): refuse more than 99 batch-get ids with a 422",
      "category": "Conversation state",
      "heading": "Validate the conversation batch size",
      "summary": "Batch conversation lookup returns 422 when a request exceeds 99 IDs. The API publishes the limit and enforces it even when Python assertions are disabled.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:16:12Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T23:41:13Z",
      "decision_needed": false
    },
    {
      "number": 5794,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5794",
      "title": "fix(agent-server): keep the server responsive while a profile store lock is held",
      "category": "Profiles and secrets",
      "heading": "Keep profile lock waits off the event loop",
      "summary": "A request waiting for a profile-store lock no longer blocks unrelated requests and sockets. The server can still answer health checks while the store is busy.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:13:33Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T23:57:35Z",
      "decision_needed": false
    },
    {
      "number": 5793,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5793",
      "title": "fix(sdk): fail extension installs whose ref a cached clone cannot check out",
      "category": "Tools and extensions",
      "heading": "Reject an install when the requested Git ref is absent",
      "summary": "The installer fails if a cached clone cannot check out the requested ref. It no longer replaces an extension with another commit while reporting success.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:13:01Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T08:04:26Z",
      "decision_needed": false
    },
    {
      "number": 5792,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5792",
      "title": "fix(agent-server): scope the workspace session cookie to the root path",
      "category": "Browser and app backends",
      "heading": "Scope workspace cookies to the configured URL prefix",
      "summary": "The workspace cookie includes the server’s path prefix. Browsers behind a prefix proxy can authenticate embedded workspace pages.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:12:49Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T23:52:04Z",
      "decision_needed": true
    },
    {
      "number": 5788,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5788",
      "title": "fix(agent-server): persist secret, policy and analyzer changes in base_state",
      "category": "Conversation state",
      "heading": "Save secrets and security settings across restarts",
      "summary": "The SDK saves secret, confirmation-policy and security-analyzer changes in conversation state. Resume no longer restores old creation-time values or loses the last secret update.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:07:31Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T01:43:02Z",
      "decision_needed": true
    },
    {
      "number": 5787,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5787",
      "title": "fix(agent-server): treat IPv6 loopback Host as a secure context",
      "category": "Browser and app backends",
      "heading": "Accept IPv6 loopback as a secure browser context",
      "summary": "The workspace-session endpoint recognizes ::1 correctly. Browsers on IPv6 loopback receive a cookie they can use for workspace embeds.",
      "state": "MERGED",
      "created_at": "2026-10-13T23:06:31Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": "2026-10-14T18:56:25Z",
      "closed_at": "2026-10-14T18:56:25Z",
      "updated_at": "2026-10-14T18:56:28Z",
      "decision_needed": false
    },
    {
      "number": 5786,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5786",
      "title": "fix(agent-server): reject blank and redacted provider-connection api_key",
      "category": "Profiles and secrets",
      "heading": "Reject empty and masked provider keys",
      "summary": "Provider connection create and update reject blank keys and the redacted placeholder. Clients no longer clear a shared key or save the mask as a real key by accident.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:03:12Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T23:33:32Z",
      "decision_needed": false
    },
    {
      "number": 5783,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5783",
      "title": "fix(ts): honor maxIterations and stuckDetection in ConversationManager.createConversation",
      "category": "TypeScript client",
      "heading": "Send conversation limits from the manager",
      "summary": "The TypeScript manager sends maxIterations and stuckDetection when it creates a conversation. The server no longer silently uses defaults instead of the caller’s choices.",
      "state": "OPEN",
      "created_at": "2026-10-13T23:01:17Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T23:28:03Z",
      "decision_needed": true
    },
    {
      "number": 5782,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5782",
      "title": "fix(git): keep file names verbatim in git changes and commit changes",
      "category": "Files and Git",
      "heading": "Keep Git filenames unchanged",
      "summary": "Git change lists preserve spaces and non-ASCII characters in filenames. One such name no longer breaks the whole Changes view or appears in a damaged escaped form.",
      "state": "OPEN",
      "created_at": "2026-10-13T22:47:45Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T23:19:34Z",
      "decision_needed": false
    },
    {
      "number": 5781,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5781",
      "title": "fix(agent-server): serve trajectories from the init-time conversations path",
      "category": "Files and Git",
      "heading": "Download histories from the initialized storage path",
      "summary": "Trajectory downloads use the conversation folder chosen during server initialization. Deferred-init servers no longer look in the old launch-time folder.",
      "state": "OPEN",
      "created_at": "2026-10-13T22:47:32Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T23:19:08Z",
      "decision_needed": false
    },
    {
      "number": 5780,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5780",
      "title": "fix(agent-server): log failed runs without rendering a rich traceback on the loop",
      "category": "Conversation state",
      "heading": "Keep error logging from freezing the server",
      "summary": "The server avoids slow rich traceback rendering on the event loop when a run fails. Other requests and sockets can remain responsive during error reporting.",
      "state": "OPEN",
      "created_at": "2026-10-13T22:45:51Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T20:23:08Z",
      "decision_needed": true
    },
    {
      "number": 5779,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5779",
      "title": "fix(sdk): install the posted LLM when switch_llm targets a registered usage_id",
      "category": "Profiles and secrets",
      "heading": "Apply a posted model even when its usage ID is known",
      "summary": "The SDK installs the new LLM configuration when switch_llm uses an existing usage_id. The endpoint no longer reports success while keeping the old model.",
      "state": "OPEN",
      "created_at": "2026-10-13T22:43:24Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T20:23:05Z",
      "decision_needed": false
    },
    {
      "number": 5778,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5778",
      "title": "fix(agent-server): return the whole output from execute_bash_command",
      "category": "Commands",
      "heading": "Return all command output chunks",
      "summary": "The synchronous Bash endpoint collects all stored output and the final exit code. Large output no longer loses earlier chunks or appears successful before completion.",
      "state": "OPEN",
      "created_at": "2026-10-13T22:43:02Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T20:23:07Z",
      "decision_needed": true
    },
    {
      "number": 5777,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5777",
      "title": "fix(agent-server): re-read meta.json when loading a persisted conversation",
      "category": "Conversation state",
      "heading": "Reload conversation metadata before takeover",
      "summary": "A server reads the latest saved metadata when it loads a conversation. It no longer overwrites another server’s newer title, tags or secrets with its startup copy.",
      "state": "OPEN",
      "created_at": "2026-10-13T22:37:38Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T23:38:21Z",
      "decision_needed": false
    },
    {
      "number": 5776,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5776",
      "title": "fix(sdk): persist state changes made while a step waits on the model",
      "category": "Conversation state",
      "heading": "Save state changes while the model is responding",
      "summary": "The SDK saves changes such as pause while a model call is still in progress. API reads and restarts can see the acknowledged change without waiting for the model.",
      "state": "OPEN",
      "created_at": "2026-10-13T22:34:18Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T09:29:54Z",
      "decision_needed": false
    },
    {
      "number": 5775,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5775",
      "title": "fix(agent-server): refuse activating or re-saving a profile under a changed cipher key",
      "category": "Profiles and secrets",
      "heading": "Protect profiles when the encryption key changes",
      "summary": "The server refuses to activate or overwrite a profile whose encrypted key is unreadable. It preserves the encrypted value so restoring the original key can recover it.",
      "state": "OPEN",
      "created_at": "2026-10-13T22:31:59Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T05:50:00Z",
      "decision_needed": true
    },
    {
      "number": 5774,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5774",
      "title": "fix(agent-server): reap Canvas backends orphaned by a crashed server",
      "category": "Browser and app backends",
      "heading": "Clean up app backends after a server crash",
      "summary": "The server tracks backend processes across restarts and removes verified orphans. A crash no longer leaves an old backend running beside a new copy on the same data.",
      "state": "MERGED",
      "created_at": "2026-10-13T22:24:49Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": "2026-10-14T18:59:17Z",
      "closed_at": "2026-10-14T18:59:18Z",
      "updated_at": "2026-10-14T18:59:20Z",
      "decision_needed": false
    },
    {
      "number": 5773,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5773",
      "title": "fix(agent-server): accept short event kinds in events search and count",
      "category": "Events and streaming",
      "heading": "Accept the documented short event names",
      "summary": "Event search and count accept names such as MessageEvent. Clients following the API description no longer receive an empty history for existing events.",
      "state": "OPEN",
      "created_at": "2026-10-13T22:18:08Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T22:44:25Z",
      "decision_needed": false
    },
    {
      "number": 5772,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5772",
      "title": "fix(agent-server): mark a goal loop left active at restart as interrupted",
      "category": "Conversation state",
      "heading": "Mark unfinished goals as interrupted after restart",
      "summary": "The server records an interrupted goal when no loop remains after restart. Clients no longer display that goal as running forever.",
      "state": "OPEN",
      "created_at": "2026-10-13T22:16:30Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T20:23:04Z",
      "decision_needed": false
    },
    {
      "number": 5771,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5771",
      "title": "fix(sdk): resume a conversation whose custom tool module is gone",
      "category": "Tools and extensions",
      "heading": "Resume history after a custom tool module disappears",
      "summary": "The SDK skips unavailable custom tools and unrecognized stored event types with warnings during resume. A missing module no longer prevents the conversation from loading.",
      "state": "OPEN",
      "created_at": "2026-10-13T22:15:30Z",
      "review_decision": "REVIEW_REQUIRED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T23:14:22Z",
      "decision_needed": true
    },
    {
      "number": 5770,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5770",
      "title": "fix(sdk): keep discriminated-union validation from mutating its input",
      "category": "Conversation state",
      "heading": "Leave validation input unchanged",
      "summary": "Discriminated-union validation no longer removes kind from the supplied object. Repeated reads of remote agent and security settings remain valid.",
      "state": "OPEN",
      "created_at": "2026-10-13T21:49:33Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T22:21:27Z",
      "decision_needed": false
    },
    {
      "number": 5769,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5769",
      "title": "fix(typescript): use the global WebSocket in the callback socket clients",
      "category": "TypeScript client",
      "heading": "Use the available global WebSocket",
      "summary": "The TypeScript callback clients use globalThis.WebSocket when available. They can deliver events in modern Node without calling require inside an ES module.",
      "state": "OPEN",
      "created_at": "2026-10-13T21:45:39Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T20:23:11Z",
      "decision_needed": true
    },
    {
      "number": 5768,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5768",
      "title": "fix(agent-server): bound profile pre-flight and reject exhausted quotas",
      "category": "Profiles and secrets",
      "heading": "Bound profile checks and reject exhausted quotas",
      "summary": "Profile validation uses a short request and retry policy. It also treats an exhausted budget or quota as invalid instead of reporting a usable key.",
      "state": "OPEN",
      "created_at": "2026-10-13T21:43:05Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T20:23:10Z",
      "decision_needed": true
    },
    {
      "number": 5767,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5767",
      "title": "fix(agent-server): load skills marketplace from .plugin manifest first",
      "category": "Tools and extensions",
      "heading": "Read the real marketplace manifest",
      "summary": "The server checks the .plugin marketplace manifest before the old fallback path. The Marketplace tab can list the public extensions repository instead of showing no skills.",
      "state": "OPEN",
      "created_at": "2026-10-13T21:32:33Z",
      "review_decision": "REVIEW_REQUIRED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T22:09:33Z",
      "decision_needed": true
    },
    {
      "number": 5766,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5766",
      "title": "fix(agent-server): give each trajectory download its own temp zip",
      "category": "Files and Git",
      "heading": "Give each history download its own archive",
      "summary": "Each trajectory download uses a separate temporary ZIP file. Parallel downloads no longer overwrite or delete the file another response is sending.",
      "state": "OPEN",
      "created_at": "2026-10-13T21:31:41Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T22:07:49Z",
      "decision_needed": true
    },
    {
      "number": 5765,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5765",
      "title": "fix(sdk): keep the source's cipher and secrets on a forked conversation",
      "category": "Profiles and secrets",
      "heading": "Keep credentials when branching a conversation",
      "summary": "The SDK carries the source cipher and secrets into a fork. A new branch no longer loses its stored LLM key and fails on its first turn.",
      "state": "OPEN",
      "created_at": "2026-10-13T21:28:36Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T22:25:43Z",
      "decision_needed": true
    },
    {
      "number": 5764,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5764",
      "title": "fix(typescript): keep reconnecting when a refused handshake fires only error",
      "category": "TypeScript client",
      "heading": "Retry WebSocket handshakes that emit only errors",
      "summary": "The TypeScript event stream schedules another connection attempt after an error-only handshake failure. It can recover when a server is down or restarting.",
      "state": "OPEN",
      "created_at": "2026-10-13T21:23:40Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T21:57:40Z",
      "decision_needed": true
    },
    {
      "number": 5763,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5763",
      "title": "fix(agent-server): negotiate WebSocket subprotocols through the app-backend bridge",
      "category": "Browser and app backends",
      "heading": "Forward WebSocket subprotocols through the app bridge",
      "summary": "The bridge negotiates a subprotocol with the backend before accepting the browser connection. Apps that require a protocol can complete the handshake.",
      "state": "OPEN",
      "created_at": "2026-10-13T21:19:15Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T21:45:58Z",
      "decision_needed": true
    },
    {
      "number": 5762,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5762",
      "title": "fix(ts-client): keep binary bytes in RemoteWorkspace downloads",
      "category": "TypeScript client",
      "heading": "Preserve binary downloads",
      "summary": "The TypeScript remote workspace reads downloads as bytes. Binary files no longer pass through UTF-8 text decoding and return corrupted content.",
      "state": "OPEN",
      "created_at": "2026-10-13T21:14:41Z",
      "review_decision": "REVIEW_REQUIRED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T22:07:23Z",
      "decision_needed": true
    },
    {
      "number": 5761,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5761",
      "title": "fix(agent-server): report per-request usage on continued chat completions",
      "category": "Gateway and ACP",
      "heading": "Report token usage for each continued chat request",
      "summary": "The gateway returns the tokens used by the current request, including streamed usage. Clients no longer count all earlier turns again.",
      "state": "OPEN",
      "created_at": "2026-10-13T21:14:20Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T04:23:21Z",
      "decision_needed": true
    },
    {
      "number": 5758,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5758",
      "title": "fix(agent-server): support cipher key rotation and refuse writes under a lost key",
      "category": "Profiles and secrets",
      "heading": "Support encryption-key rotation without losing secrets",
      "summary": "The server supports key rotation and refuses writes that would erase values encrypted with a lost key. Existing encrypted settings remain recoverable instead of being replaced with null.",
      "state": "OPEN",
      "created_at": "2026-10-13T21:09:15Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T05:55:15Z",
      "decision_needed": true
    },
    {
      "number": 5757,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5757",
      "title": "fix(agent-server): close conversation sockets on delete and sandbox pause",
      "category": "Events and streaming",
      "heading": "Close sockets when a conversation is removed or paused",
      "summary": "The server closes event and session sockets on delete or sandbox pause. Clients can detect the change and reconnect rather than staying attached to a discarded service.",
      "state": "OPEN",
      "created_at": "2026-10-13T21:08:50Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T08:20:59Z",
      "decision_needed": true
    },
    {
      "number": 5756,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5756",
      "title": "fix(sdk): drop a since-disabled ambient plugin's skills and MCP servers on resume",
      "category": "Tools and extensions",
      "heading": "Remove disabled plugin contributions on resume",
      "summary": "The SDK removes a disabled ambient plugin’s skills and MCP servers when it resumes a conversation. It no longer restores those contributions from old saved agent state.",
      "state": "OPEN",
      "created_at": "2026-10-13T20:58:43Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-14T07:24:15Z",
      "decision_needed": true
    },
    {
      "number": 5755,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5755",
      "title": "fix(agent-server): resolve provider connection in profile validate",
      "category": "Profiles and secrets",
      "heading": "Use the linked provider key during profile validation",
      "summary": "Validation resolves a draft profile’s saved provider connection. A profile without an inline key can pass the same key check used during activation.",
      "state": "OPEN",
      "created_at": "2026-10-13T20:53:28Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T21:23:59Z",
      "decision_needed": true
    },
    {
      "number": 5753,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5753",
      "title": "fix(sdk): list changes of a repository below a non-repository path",
      "category": "Files and Git",
      "heading": "Find Git changes below the workspace root",
      "summary": "Git change lookup checks for a repository below a non-repository folder. A Changes view using the workspace root no longer misses edits in that repository.",
      "state": "OPEN",
      "created_at": "2026-10-13T20:45:39Z",
      "review_decision": "APPROVED",
      "is_draft": false,
      "merged_at": null,
      "closed_at": null,
      "updated_at": "2026-10-13T21:17:41Z",
      "decision_needed": false
    },
    {
      "number": 5926,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5926",
      "title": "fix(agent-server): read an unreachable OpenAI refresh as disconnected",
      "category": "Gateway and ACP",
      "heading": "Report an offline OpenAI login as disconnected",
      "summary": "The subscription status endpoint reports connected=false if OpenAI cannot be reached during a token refresh. It keeps the saved credentials so the connection can recover when the network returns.",
      "state": "MERGED",
      "is_draft": false,
      "review_decision": "APPROVED",
      "merged_at": "2026-10-14T13:48:46Z",
      "closed_at": "2026-10-14T13:48:47Z",
      "updated_at": "2026-10-14T13:48:51Z",
      "decision_needed": false
    },
    {
      "number": 5923,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5923",
      "title": "fix(agent-server): forward ?path= on the bare Canvas app-backend root route",
      "category": "Browser and app backends",
      "heading": "Preserve the path query on app root requests",
      "summary": "The app bridge forwards a path query parameter as query data on the root route. It no longer mistakes that value for the backend URL path.",
      "state": "MERGED",
      "is_draft": false,
      "review_decision": "APPROVED",
      "merged_at": "2026-10-14T14:02:14Z",
      "closed_at": "2026-10-14T14:02:14Z",
      "updated_at": "2026-10-14T14:02:17Z",
      "decision_needed": false
    },
    {
      "number": 5759,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5759",
      "title": "fix(agent-server): re-probe a Canvas App backend after a missed health probe",
      "category": "Browser and app backends",
      "heading": "Check backend health again after a slow response",
      "summary": "The server checks a live backend again after a failed health probe. A temporary delay no longer leaves a recovered app marked unhealthy until restart.",
      "state": "MERGED",
      "is_draft": false,
      "review_decision": "APPROVED",
      "merged_at": "2026-10-13T22:37:51Z",
      "closed_at": "2026-10-13T22:37:51Z",
      "updated_at": "2026-10-13T22:37:53Z",
      "decision_needed": false
    },
    {
      "number": 5754,
      "url": "https://github.com/OpenHands/software-agent-sdk/pull/5754",
      "title": "fix(sdk): skip sub-agents whose skill is missing instead of failing",
      "category": "Tools and extensions",
      "heading": "Skip sub-agents with missing skills",
      "summary": "The SDK skips a sub-agent definition that names a missing skill and logs a warning. Other sub-agents still load, and the missing skill no longer breaks the conversation.",
      "state": "MERGED",
      "is_draft": false,
      "review_decision": "APPROVED",
      "merged_at": "2026-10-13T21:39:48Z",
      "closed_at": "2026-10-13T21:39:48Z",
      "updated_at": "2026-10-13T21:39:51Z",
      "decision_needed": true
    }
  ]
}
