Skip to content

Soft-fail by default inside build hooks so connector errors never break deploys#44

Open
ejntaylor wants to merge 1 commit into
mainfrom
fix-lovable-postbuild-failure
Open

Soft-fail by default inside build hooks so connector errors never break deploys#44
ejntaylor wants to merge 1 commit into
mainfrom
fix-lovable-postbuild-failure

Conversation

@ejntaylor

Copy link
Copy Markdown
Contributor

Why

A Lovable publish failed with script "postbuild" exited with code 1 even though the app build succeeded. The platform's agent had wired "postbuild": "patchstack-connect verify" — a subcommand that has never existed in any release — so the CLI printed its full help to stderr and exited 1, failing the customer's whole deploy. Lovable truncates stderr from the front, so the help wall pushed the actual Unknown command: verify line out of view, making the failure look like config-docs noise.

AI coding agents are the ones wiring this connector into build scripts, and they sometimes get the invocation wrong. A security monitor should degrade gracefully in that position: report the problem, never take the deploy down with it.

Supersedes #34: that PR's PATCHSTACK_SOFT_FAIL was opt-in only, but the broken hooks already in the wild carry no env prefix, so the opt-in never engages. This PR keeps the env var (same semantics, credit to #34) and adds the default that actually covers the incident.

What

  • Errors are soft by default inside build lifecycle hooks. When npm_lifecycle_event is prebuild, build, or postbuild (npm, pnpm, yarn, and bun all set it), the CLI reports the error then exits 0 so the build continues. Manual/interactive runs (including npx, which sets npm_lifecycle_event=npx) keep real exit codes.
  • PATCHSTACK_SOFT_FAIL overrides in either direction1 (or any truthy value) forces soft anywhere; 0/false/no/off restores hard failures even in hooks. Lives in src/config.ts as softFailEnabled(env) with unit tests.
  • Unknown-command output is two short lines with the error printed last, so tail-truncated platform logs show the cause instead of a help wall — plus a did-you-mean suggestion (edit distance ≤ 2) that catches typos and Unicode-dash mangling (mark‑build with U+2011 → did you mean `mark-build`?).
  • Docs: README documents the soft-fail behavior and env var; the AI install prompt and AGENT-INSTALL.md now say to use exactly the documented subcommands and not invent others (naming verify explicitly, since that's what the agent invented).

Release note

The failing project pins "@patchstack/connect": "^0.2.8", which caret-resolves to <0.3.0 — so besides the next 0.3.x, this needs a 0.2.12 patch release cut from the v0.2.11 tag to reach existing installs.

Verification

  • npx vitest run — 131 tests pass; tsc --noEmit clean.
  • Built CLI exercised end-to-end against a replay of the failing project:
    • postbuild verify → prints Unknown command: verify + soft-fail notice, npm run build exits 0
    • node dist/cli.js verify manually → exit 1
    • node dist/cli.js mark‑build (Unicode hyphen) → did you mean `mark-build`?, exit 1
    • PATCHSTACK_SOFT_FAIL=0 on the postbuild → exit 1 (opt-out honored)
    • scan against an unreachable endpoint in a postbuild → prints Error (NETWORK_ERROR): …, exits 0

🤖 Generated with Claude Code

…ak deploys

A Lovable publish failed with `script "postbuild" exited with code 1`: the
platform's agent wired `"postbuild": "patchstack-connect verify"` — a
subcommand that has never existed — so the CLI printed its full help to
stderr and exited 1, taking the customer's whole deploy down. Truncated
platform logs made it worse: the help wall pushed the actual
`Unknown command:` line out of view.

A security monitor must degrade gracefully in that position. Changes:

- Errors are now soft by default inside `prebuild`/`build`/`postbuild`
  lifecycle scripts (detected via `npm_lifecycle_event`, set by npm, pnpm,
  yarn, and bun): the CLI reports the error, then exits 0 so the build
  continues. Manual/interactive runs keep real exit codes.
- `PATCHSTACK_SOFT_FAIL` overrides in either direction (`1` forces soft
  anywhere, `0`/`false`/`no`/`off` restores hard failures even in hooks).
  Supersedes the opt-in-only approach from #34 — the broken hooks already
  in the wild carry no env prefix, so opt-in alone never engages.
- Unknown-command output is now two short lines with the error last (so
  tail-truncated build logs show the cause, not a help wall) and includes
  a did-you-mean suggestion for near-misses like Unicode-dash mangling.
- README + AGENT-INSTALL.md now tell agents to use exactly the documented
  subcommands, and document the soft-fail behavior and env var.

Verified end-to-end against a replay of the failing project: a postbuild
running `verify` now reports the unknown command and exits 0; the same
command manually still exits 1; `PATCHSTACK_SOFT_FAIL=0` in a hook exits 1;
a scan network failure in a hook exits 0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderbuds

coderbuds Bot commented Jul 13, 2026

Copy link
Copy Markdown

Implements soft-fail for build hooks and adds command suggestion for mistyped CLI commands.

🎯 Quality: 93% Elite · 📦 Size: Medium

📈 This month: Your 221st PR — above team average · Averaging Excellent

See how your team is trending →

@ejntaylor

Copy link
Copy Markdown
Contributor Author

/review

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant