molecule-core/workspace-server/internal/bundle
Hongming Wang 56149f8a24 fix(bundle): markFailed sets last_sample_error + AST gate
Closes the bug class surfaced by Canvas E2E #2632: a workspace ends up
status='failed' with last_sample_error=NULL, and operators (or the
E2E poll loop) see the useless "Workspace failed: (no last_sample_error)"
with no triage signal.

Two pieces:

1. **bundle/importer.go markFailed** — the UPDATE was setting only
   status, leaving last_sample_error NULL. Same incident class as the
   silent-drop bugs in PRs #2811 + #2824, different code path.
   markProvisionFailed in workspace_provision_shared.go has set the
   message column for a long time; this writer drifted the convention.
   Fix: include last_sample_error in the SET clause + the broadcast.

2. **AST drift gate** (db/workspace_status_failed_message_drift_test.go)
   — Go AST walk that finds every db.DB.{Exec,Query,QueryRow}Context
   call whose argument list binds models.StatusFailed and asserts the
   SQL literal contains last_sample_error. Catches the next caller
   that drifts the same convention. Verified to FAIL against the bug
   shape (reverted importer.go temporarily — gate flagged the exact
   line) and PASS against the fix.

Why an AST gate vs a regex: pre-fix attempt with a regex over UPDATE
statements flagged status='online' / status='hibernating' / status=
'removed' UPDATEs as false positives. Walking the AST and only
flagging calls that pass the StatusFailed constant eliminates that.

Out of scope (filed separately if needed):
- The Canvas E2E that surfaced the missing message (#2632) is now a
  required check on staging via PR #2827. Once this fix lands the
  next staging push should re-run #2632's failing case and produce
  a meaningful last_sample_error.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 21:08:08 -07:00
..
exporter.go fix(ci): golangci-lint errcheck failures on staging 2026-04-21 01:49:03 +00:00
importer.go fix(bundle): markFailed sets last_sample_error + AST gate 2026-05-04 21:08:08 -07:00
types.go chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00