Skip to content

feat(agent): ship gate — checks run at the push, not on request - #838

Merged
patroza merged 2 commits into
mainfrom
feat/agent-ship-gate
Aug 3, 2026
Merged

patroza merged 2 commits into
mainfrom
feat/agent-ship-gate

Conversation

@patroza

@patroza patroza commented Aug 3, 2026

Copy link
Copy Markdown
Member

Why

Validation that depends on an agent remembering to run it produces both failure modes at once: skipped when it matters, and re-run repeatedly through a task when it doesn't. Neither is what you want — the goal is reliability without burning cycles re-proving the same commit.

What

The macs-scanner ship gate, minus everything that doesn't apply to a library monorepo.

  • .githooks/pre-push — no-op for humans, and for draft / no-PR pushes. Full gate on ready PRs, fail-closed when PR state can't be resolved. Drafts stay free so sharing early costs nothing.
  • The gate is pnpm checkpnpm lintpnpm test — exactly what ci.yml runs, deliberately not a superset. No application to stand up, no browser suite: here the unit run (pnpm -r --no-bail test:run) is the whole gate, and is the closest analogue of the E2E stage the product repos gate on.
  • Publishing is gated, not forbidden. pnpm pr:ready is explicit; plain gh pr ready reaches the same place because .tools/bin/gh runs the gate first and passes through when green.
  • The validated HEAD SHA is cached in .run/agent-ship-gate.json, so one commit is validated once however often it is pushed or published. AGENT_SHIP_GATE_FORCE=1 overrides.

AGENTS.md now says plainly not to hand-run these checks as routine verification, and that narrow targeted proof while iterating is the right tool instead.

How

Two details carried over from porting this to three other repos, each of which was a real bug there:

  • The gate supplies its own PATH (node_modules/.bin). pnpm and the hook both provide it, so the dependency stays invisible until something runs the gate from a bare process — which the gh shim does — and it dies with "command not found".
  • The hook scrubs git's local env vars before running, so nested git commands discover their own repository rather than inheriting the outer push's GIT_DIR.

The shim is generated by install-git-hooks.mjs rather than committed, because it embeds the checkout's absolute path; .envrc puts it on PATH, so it applies only inside this repository. Run direnv allow once after cloning.

Remarks

Verified live: the shim intercepted gh pr ready, ran the gate, and correctly refused on a dirty worktree.

Same rule now stated in macs-scanner, t3code and macs-configurator.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

@patroza
patroza marked this pull request as ready for review August 3, 2026 18:19
patroza and others added 2 commits August 3, 2026 20:22
Ports the agent ship gate from macs-scanner, minus everything that does not
apply to a library monorepo.

`.githooks/pre-push` is a no-op for humans and for draft / no-PR pushes, and runs
the full gate on ready PRs. Drafts stay free so sharing early costs nothing.
Publishing is gated rather than forbidden: `pnpm pr:ready` is the explicit path
and plain `gh pr ready` reaches the same place, because `.tools/bin/gh` runs the
gate first and passes the command through when it is green. Nothing to remember,
and no way around it.

The gate is `pnpm check` -> `pnpm lint` -> `pnpm test`: exactly what ci.yml runs,
deliberately not a superset. There is no application to stand up and no browser
suite here, so the unit run is the whole gate — `pnpm -r --no-bail test:run` is
the closest analogue of the E2E stage the product repos gate on.

The validated HEAD SHA is cached under `.run/`, so a commit is validated once
however often it is pushed or published, and AGENTS.md now says plainly not to
hand-run these checks as routine verification. Repeatedly re-proving one commit
is the cost the gate exists to remove, not to add.

Two details carried over from what the other ports taught:

- The gate supplies its own PATH (node_modules/.bin). pnpm and the hook both
  provide it, so the dependency stays invisible until something runs the gate
  from a bare process — which the gh shim does — and it dies with "command not
  found".
- The hook scrubs git's local env vars before running, so nested git commands
  discover their own repository instead of inheriting the outer push's GIT_DIR.

Verified: the shim intercepts `gh pr ready`, runs the gate, and refuses on a
dirty worktree.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`pnpm exec` runs a dependency-status check before the command. When the lockfile
has moved — a rebase does it — pnpm decides node_modules must be purged and
reinstalled, then aborts because a git hook has no TTY:

    ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY

The push then fails with a pnpm error that says nothing about the gate, because
the gate never started. Invoke node directly instead; the gate already puts
node_modules/.bin on PATH itself, so pnpm was not providing anything still
needed.

Same class as the other headless failures this work surfaced: a tool changing
behaviour based on TTY or CI detection breaks in a hook, and does it
confusingly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@patroza
patroza force-pushed the feat/agent-ship-gate branch from 0a18f8a to 067f372 Compare August 3, 2026 18:24
@pkg-pr-new

pkg-pr-new Bot commented Aug 3, 2026

Copy link
Copy Markdown

Open in StackBlitz

@effect-app/cli

npm i https://pkg.pr.new/effect-app/libs/@effect-app/cli@838

effect-app

npm i https://pkg.pr.new/effect-app/libs/effect-app@838

@effect-app/eslint-codegen-model

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-codegen-model@838

@effect-app/eslint-shared-config

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-shared-config@838

@effect-app/infra

npm i https://pkg.pr.new/effect-app/libs/@effect-app/infra@838

@effect-app/vue

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue@838

@effect-app/vue-components

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue-components@838

commit: 067f372

@patroza
patroza merged commit a0ab39c into main Aug 3, 2026
6 checks passed
@patroza
patroza deleted the feat/agent-ship-gate branch August 3, 2026 20:18
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