Skip to content

Postmortem: bloom-mono#332 shipped with failing lint — no /do stage runs project quality gates #41

Description

@tbrownio

Postmortem — Backend /assets consumers fail in native local dev

What we asked for

Fix the Docker-only hard-coded /assets path so native local dev works: a single ASSETS_PATH env var defaulting to /assets, all consumers resolving through it, dev scripts setting it — delivered as a PR that is ready to merge.

What /do delivered vs intended

The functional change was correct and fully verified (all four ACs plus both prevention tests, confirmed by two review passes), but the PR arrived with a failing Lint CI check: golangci-lint's gci rule flagged pkg/sendgrid/template.go:11 and services/pdf.go:9 — the new pkg/env import was placed in the third-party import group instead of the required local-prefix group. A PR that fails CI is not "done"; the human found the failure on review.

Why the gap happened

Skill/agent gap: no pipeline stage owns "run the project's own quality gates before the PR." The defect entered at implement time (Codex placed the import in the wrong group — something gofmt, go build, and go test all accept) and then passed every subsequent stage because no stage runs the repo's lint:

  • The plan's quality-check task listed only go build ./... and go test ... (plan.md Task 8) — lint never became a plan requirement, even though apps/backend/README.md says "Before opening a pull request, run the linter and tests with make".
  • The implementer's report explicitly surfaced the hole and nothing acted on it: "lint: not run (not requested by plan)".
  • The backend-verifier proves ACs and rubric blockers; the backend-api rubric has no "project lint/CI gates pass" item, so lint was out of its scope too.
  • Both code reviewers review for correctness and security, not formatting; the Codex reviewer's read-only sandbox couldn't even run the test suite, let alone lint.
  • /do Step 5 (PR prep) commits, rebases, and pushes with no CI-equivalent gate.

Contributing factor: golangci-lint is not installed on this machine, so even an implementer inclined to run it would have hit a missing tool and needed an instruction on what to do about that (install, or flag as a blocker — not skip silently).

The code defect itself (import grouping in two files) is a symptom — a two-line fix routed through the normal PR flow, not this postmortem.

What to change so it doesn't recur

Proposed (one change): add a quality-gates step to /do Step 5 — the single choke point every implementation path (Codex implementer, frontend-implementer, fix rounds) passes through before a PR exists.

File: tyler/.claude/skills/do/SKILL.md (mirror: ~/.claude/skills/do/SKILL.md), Step 5 first bullet. Proposed edit:

 All commit/PR prep lives here:

+- Run each touched app's own quality gates first — the lint/test entry point
+  its `AGENTS.md`/README/Makefile names (e.g. `make` in `apps/backend`); CI
+  runs these, so the PR is not ready until they pass locally. A missing tool
+  is a blocker to resolve (install it or ask the user), never a step to skip.
 - Commit selectively (only this run's files, never `git add -A`; secret-scan
   the staged diff), message style `type: short imperative summary`. Rebase
   onto the origin default branch; push (`--force-with-lease` on rewrites).

Verdict: pending human approval — not applied.

Alternatives considered and set aside (one change per postmortem): adding lint to the implementer role instructions (misses the frontend-implementer and fix rounds), adding a rubric blocker (rubrics are per-change-type; this gate is universal), and a plan-template quality-gates section (reviewers didn't flag its absence this time, so the plan is a weaker choke point than Step 5).

System change (deferred)

Future: open a GitHub issue against dcouple/skills carrying this note. Off for now.


Work item: bloomapi/bloom-mono#323 · PR: https://github.com/bloomapi/bloom-mono/pull/332

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    postmortemPostmortems from /do runs — root cause + proposed system change

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions