molecule-core/workspace-server
Molecule AI Core-BE 21a5c31b85
Some checks failed
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 5s
sop-tier-check / tier-check (pull_request) Failing after 4s
[core-be-agent]
fix: Treat delivery-confirmed proxy errors as delegation success

Two-part fix for issue #159 — successful delegation responses were
rendered as error banners:

PART 1 — a2a_proxy.go: When io.ReadAll fails mid-stream (e.g., TCP
connection drops after the agent sent its 200 OK response), the prior
code returned (0, nil, BadGateway) discarding both the HTTP status code
and any partial body bytes already received. Fix: return
(resp.StatusCode, respBody, error) so callers can inspect what was
delivered even when the body read failed.

PART 2 — delegation.go: New condition in executeDelegation after the
transient-error retry block:

    if proxyErr != nil && len(respBody) > 0 && status >= 200 && status < 300 {
        goto handleSuccess
    }

When proxyA2ARequest returns a delivery-confirmed error (status 2xx +
non-empty partial body), route to success instead of failure. This
prevents the retry-storm pattern where the canvas shows "error" with
a Restart-workspace suggestion even though the delegation actually
completed and the response is available.

Regression tests (delegation_test.go):
- TestExecuteDelegation_DeliveryConfirmedProxyError_TreatsAsSuccess:
  server sends 200 + partial body then closes; second attempt succeeds.
  Verifies the new condition fires for delivery-confirmed 2xx responses.
- TestExecuteDelegation_ProxyErrorNon2xx_RemainsFailed: server sends
  500 + partial body then closes. Verifies non-2xx routes to failure.
- TestExecuteDelegation_ProxyErrorEmptyBody_RemainsFailed: server
  returns 502 Bad Gateway (empty body, transient). Verifies empty-body
  errors still route to failure (condition len(respBody) > 0 guards it).
- TestExecuteDelegation_CleanProxyResponse_Unchanged: clean 200 OK.
  Verifies baseline (proxyErr == nil path) is unaffected.

Fixes issue #159.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 22:11:54 +00:00
..
cmd chore: reconcile main → staging post-suspension divergence 2026-05-07 14:24:37 -07:00
internal [core-be-agent] 2026-05-09 22:11:54 +00:00
migrations feat(workspaces): update_tier column for canary vs production fan-out 2026-05-08 08:55:19 -07:00
pkg/provisionhook feat(#1957): wire gh-identity plugin into workspace-server 2026-04-24 15:01:41 +00:00
.air.toml feat(local-dev): air-based hot-reload for workspace-server 2026-05-08 08:10:50 -07:00
.ci-force chore: force Platform(Go) CI run on main — validate go vet clean 2026-04-21 15:43:19 +00:00
.gitignore feat(local-dev): containerize platform + canvas stack via docker-compose (closes #126) 2026-05-08 10:53:39 -07:00
.golangci.yaml chore(workspace-server): add golangci.yaml disabling errcheck 2026-04-24 07:16:54 +00:00
Dockerfile fix(ci): apply pre-clone fix to platform Dockerfile too (followup #173) 2026-05-07 13:13:13 -07:00
Dockerfile.dev fix(org-import): use ws.FilesDir as persona-dir lookup, add docker-cli-buildx to dev image 2026-05-08 13:50:46 -07:00
Dockerfile.tenant fix(ci): pre-clone manifest deps in workflow, drop in-image clone (closes #173) 2026-05-07 12:59:46 -07:00
entrypoint-tenant.sh fix(memory-plugin): gate sidecar spawn on cutover-active 2026-05-05 12:39:03 -07:00
go.mod chore: drop github-app-auth + swap GHCR→ECR (closes #157, #161) 2026-05-07 07:48:51 -07:00
go.sum chore: drop github-app-auth + swap GHCR→ECR (closes #157, #161) 2026-05-07 07:48:51 -07:00