fix: attribute the harness to the real ingress and make Forgejo failures diagnosable #101

Merged
coilysiren merged 1 commit from fix/harness-attribution-and-forgejo-detail into main 2026-08-11 06:55:10 +00:00
Member

Two reported defects, both cases of the runtime asserting something it does not know.

Harness attribution

X-Ward-Harness was the literal string discord on every Agent Proxy request, so an HTTP-only deployment reported a Discord surface it does not have.

That is half of #88, where Deep also described reading a channel it cannot see. The prompt half was already fixed; this is the span and audit half.

The header now follows the deployment's configured ingress. Per-turn transport was already accurate on the turn span as sirens_echo.transport, so this is deployment-level audit attribution rather than a per-call value.

Forgejo failure detail

forgejo.issue.failed logged only a restatement of its own name. Fourteen consecutive failures gave an operator no status, no tool, and no cause, per #89.

The MCP client now returns a typed ForgejoCallError carrying the tool, the HTTP status, and whether the tool itself reported the error rather than the transport. The log emits all three.

The remote response body was already discarded before the error was built, and still is. A test asserts that specifically, because the useful version of this fix and the leaky version look very similar, and the difference is what keeps the telemetry body-safety contract intact.

A test that encoded the bug

TestProxyClientSendsBoundedCommunityRequest asserted the hard-coded discord header. That assertion described the defect rather than the contract, so it now declares its harness explicitly, and the real contract is covered by a separate test over both ingress modes.

Not addressed

#89 raises a second question worth deciding on its own: whether an HTTP-only lane should be able to file issues at all, given issue is populated by the model's own judgement from untrusted conversational input. This PR makes that path diagnosable; it does not narrow it.

#90, the per-turn 400s against both MCP endpoints, is untouched and still open.

Verification

pre-commit run --all-files exit 0, go vet, and go test -count=1 -race ./... all pass.

Two reported defects, both cases of the runtime asserting something it does not know. ## Harness attribution `X-Ward-Harness` was the literal string `discord` on every Agent Proxy request, so an HTTP-only deployment reported a Discord surface it does not have. That is half of https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/88, where Deep also described reading a channel it cannot see. The prompt half was already fixed; this is the span and audit half. The header now follows the deployment's configured ingress. Per-turn transport was already accurate on the turn span as `sirens_echo.transport`, so this is deployment-level audit attribution rather than a per-call value. ## Forgejo failure detail `forgejo.issue.failed` logged only a restatement of its own name. Fourteen consecutive failures gave an operator no status, no tool, and no cause, per https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/89. The MCP client now returns a typed `ForgejoCallError` carrying the tool, the HTTP status, and whether the tool itself reported the error rather than the transport. The log emits all three. **The remote response body was already discarded before the error was built, and still is.** A test asserts that specifically, because the useful version of this fix and the leaky version look very similar, and the difference is what keeps the telemetry body-safety contract intact. ## A test that encoded the bug `TestProxyClientSendsBoundedCommunityRequest` asserted the hard-coded `discord` header. That assertion described the defect rather than the contract, so it now declares its harness explicitly, and the real contract is covered by a separate test over both ingress modes. ## Not addressed https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/89 raises a second question worth deciding on its own: whether an HTTP-only lane should be able to file issues at all, given `issue` is populated by the model's own judgement from untrusted conversational input. This PR makes that path diagnosable; it does not narrow it. https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/90, the per-turn 400s against both MCP endpoints, is untouched and still open. ## Verification `pre-commit run --all-files` exit 0, `go vet`, and `go test -count=1 -race ./...` all pass.
fix: attribute the harness to the real ingress and make Forgejo failures diagnosable
All checks were successful
ci / test (pull_request) Successful in 35s
ci / publish-echo-image (pull_request) Has been skipped
7298ad968b
Two reported defects, both about a runtime asserting something it does not
know.

X-Ward-Harness was the literal string "discord" on every Agent Proxy
request, so an HTTP-only deployment reported a Discord surface it does not
have. That is half of the self-belief problem in issue 88, where Deep also
described reading a channel it cannot see. The header now follows the
deployment's configured ingress. Per-turn transport was already accurate on
the turn span, so this is deployment-level audit attribution rather than a
per-call value.

forgejo.issue.failed logged only a restatement of its own name. Fourteen
consecutive failures gave an operator no status, no tool, and no cause, per
issue 89. The MCP client now returns a typed ForgejoCallError carrying the
tool and the HTTP status, and whether the tool itself reported the error
rather than the transport, and the log emits all three.

The remote response body was already discarded before the error was built
and still is, so nothing from the far side reaches a log. A test asserts
that specifically, because the useful version of this fix and the leaky
version look similar.

An existing test asserted the hard-coded discord header, which encoded the
bug rather than the contract. It now declares its harness and the contract
is covered separately.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo!101
No description provided.