Skip to content

Build shows failure outcomes without reasons #41

Description

@ryandmonk

Found during merged-main verification of #40 (c046ef8) by an adversarial sweep. Recording only — no scope expansion during the merge closeout.

The Build view renders what happened but not why, on every failure path. foldBuildEvents captures progress.report (which carries the emitter's verbatim refusal, per-attempt adapterError, and the S3 findings), and the view never reads them.

Failure What the user sees What was available
Emit refusal (failed-gate) — the dominant real-model failure three green gates + outcome: failed-gate the verbatim refusal in report.emitted
Adapter failure (model not pulled, Ollama down, non-JSON) outcome: failed-adapter the typed error in report.attempts[].adapterError
Governance (S3) failure on the deciding attempt S3 FAIL with an empty tooltip rule id, message and rationale in the streamed findings
Accept refused server-side Accept failed: agent replied 422 the full findings array in the 422 body

Two mechanisms:

  1. apps/composer/app/views/build-view.tsx:87-92 renders outcome: and only progress.error (set by RUN_ERROR/dspack.error, never by a pipeline failure outcome). packages/composer-core/src/build.ts:108-113 stores the report but the fold exposes no reason field.
  2. apps/composer/app/agent-client.ts:47 — the shared post<T> helper maps any non-2xx to { ok: false, error: payload.error ?? "agent replied " + status }. saveExample deliberately answers 422 { ok: false, findings: [...] } with no error key, so state.tsx's findings-aware branch never runs and the gate reasons are discarded.

Related: lintSurface records S1/S2 problems as gate errors and S3 as findings, so the repair transcript rendered verbatim in Build reads "violates 0 governance rule finding(s)" whenever the failure was S1/S2 — technically accurate, actively confusing as the visible proof of the governed repair loop.

Server-side correctness is unaffected and tested (the 422 refusal writes nothing; e2e/composer-build.spec.ts:142). This is purely the diagnostic surface.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions