Skip to content

Every presentation a command declares is required - #171

Merged
wmadden merged 4 commits into
mainfrom
presentations-required
Aug 13, 2026
Merged

Every presentation a command declares is required#171
wmadden merged 4 commits into
mainfrom
presentations-required

Conversation

@wmadden-electric

@wmadden-electric wmadden-electric commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Presentations made stdout, json and next optional, so a command that omitted json got its --json contract by accident: the engine published the handler's internal data object as the envelope's result. The surface machine consumers script against was set by omission rather than by choice.

All four are now required in the type. Every command states what it publishes on each surface.

Behaviour is preserved exactly

Where a command had no json, it now returns what the handler passes as data, because that is what the envelope carried. Where it had no stdout or next, it returns an empty array, because that is what it wrote. The point is to make each surface a stated choice, so a wrong one can then be corrected one command at a time — not to change any output here.

The engine's settlement fallback is gone: result is the json presentation, not a substitution for a missing one, and a new test pins that by making a command's data and json differ.

Two runtime shims, and a correction

materializePresentation still calls stdout and next optionally. @prisma/orm-toolchain is built against engine 0.0.9, where three of the four were optional, and its commands took that up — migration list declares human and json and neither of the others. Calling them unconditionally makes it exit 2: stdout in human mode, next in both.

An earlier revision of this PR claimed stdout was safe to require. That was wrong, and the way it was wrong matters: I checked it against tests/orm-mount.test.ts, which runs in json mode — and json mode never calls stdout. The test could not have detected the failure it was cited as ruling out. Human mode, the default for anyone at a terminal, would have exited 2 across 18 ORM commands.

The mount test now runs the same command in both formats, with a comment saying why: the two formats call different presentation functions, so a run in one proves nothing about the other.

json stays strict. Every ORM command declares one, and a missing json presentation is the defect this change exists to remove.

The shims are temporary, and the real fix is ours

This is version skew in our own code, not a foreign contract. @prisma/orm-toolchain lives in prisma/prisma and pins @prisma/cli-engine@0.0.9. Declaring the missing presentations there — 18 files lack stdout, 16 lack next — and building it against this engine makes the type refuse to compile without them, which is where the enforcement belongs. Both ?.() come out when that version is pinned here.

Scope

156 call sites: 95 in the engine (93 of them test fixtures that declared only human) and 61 in the CLI, concentrated in src/commands/service/presentation.ts — the service group was written after this change was first attempted on a branch that never merged.

Four auth commands and the shared env-file presentation needed care rather than a mechanical edit: their builders take a derived object, not the handler's data, so returning the builder's own parameter would have changed the --json output. They now take the result explicitly.

A hazard for whoever runs the tests

npm test fails at random on this repo, and it is not this change. Both package test scripts begin with pnpm run build, so turbo runs the engine's build while the CLI's vitest imports the dist it is rewriting. npx turbo run test --concurrency=1 passes all 94 files every time. Already recorded in deferred.md under S6.

Verified: build, lint, typecheck clean; 60 CLI test files and 34 engine test files pass serially.

wmadden-electric and others added 2 commits August 12, 2026 20:01
`Presentations` made `stdout`, `json` and `next` optional, so a command
that omitted `json` got its `--json` contract by accident: the engine
published the handler's internal `data` object as the envelope's
`result`. The surface machine consumers depend on was set by omission
rather than by choice.

All four are now required, and every command states what it publishes on
each surface. Behaviour is preserved exactly: where a command had no
`json` it now returns what the handler passes as `data`, because that is
what the envelope carried; where it had no `stdout` or `next` it returns
an empty array, because that is what it wrote.

The engine's settlement fallback is gone — `result` is the json
presentation, not a substitution.

One fallback stays, and it is commented where it lives:
`materializePresentation` still calls `next` optionally, because
@prisma/orm-toolchain@8.0.0-rc.1-dev.40 is compiled against an earlier
engine and declares no `next` for `migration list`. Requiring it makes
that command exit 2. `stdout` and `json` are required at runtime, which
both published families already satisfy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Both package test scripts now begin with pnpm run build, so turbo runs
the engine's build while the CLI's vitest imports the dist it is
rewriting. The failure is "Cannot find package
'@prisma/cli-engine/testing'" at file level, and the count varies: 13,
34 and 43 across three runs of one branch. Serial turbo and a direct
vitest run both pass all 60.

The existing entry said the CLI script was a bare vitest run and that
turbo was therefore honest. The build step has since been added to both
scripts, which is what created the race.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
@pkg-pr-new

pkg-pr-new Bot commented Aug 12, 2026

Copy link
Copy Markdown

Open in StackBlitz

npx https://pkg.pr.new/@prisma/cli@171
npx https://pkg.pr.new/@prisma/cli-engine@171

commit: 2a66b84

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

Summary by CodeRabbit

  • New Features

    • Added consistent machine-readable JSON output across authentication, project, database, service, environment, bucket, Git, and agent commands.
    • Command results now expose complete structured data for scripting and automation.
    • Added standardized handling for standard output and follow-up actions, including empty responses where no additional content is available.
  • Bug Fixes

    • Improved result handling so JSON responses consistently reflect the command’s actual result.
    • Preserved human-readable output while adding reliable support for alternative output formats.

Walkthrough

The presentation contract now requires human, stdout, json, and next handlers. Engine execution invokes JSON and stdout handlers directly, while legacy next handling remains optional. Completed results use the JSON presentation without a data fallback. CLI command presentations now expose command results through JSON and provide empty handlers where required. Engine and CLI test fixtures define the complete presentation shape. Deferred test-race documentation now describes concurrent engine builds.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely states the main change: all declared command presentations are required.
Description check ✅ Passed The description directly explains the required presentation fields, compatibility shims, behavior, scope, and test status.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch presentations-required
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch presentations-required

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.drive/projects/prisma-cli-v8/deferred.md:
- Line 168: Consolidate the duplicate shared-dist build-race documentation by
keeping one canonical entry and removing or merging the redundant entry around
the documented race. Align the canonical entry’s reproduction command, observed
failure message, and remediation with the corresponding details in the other
entry, preserving the recommendation to eliminate concurrent builds of the
shared dist directory.

In `@packages/cli-engine/src/execution/command-context.ts`:
- Around line 58-59: Complete the comment describing the next field’s
compatibility behavior: state that next is the only field that may be absent at
runtime while the other fields remain required, and preserve the surrounding
Presentations requirement.
- Around line 77-83: Update the presentation materialization flow to pass
outcome.data into materializePresentation, and in the returned presentation
object invoke json and stdout presenters optionally to support legacy
Presentations objects. Preserve the existing outputs while defaulting missing
stdout to [] and avoiding runtime errors when json or stdout is absent.

In `@packages/cli-engine/src/execution/settlement.ts`:
- Line 74: Add or update a regression test for the settlement flow around the
JSON presentation handler, using distinct `data` and `json` fixture values and
asserting that the completed JSON envelope’s `result` matches the JSON handler’s
returned value. Ensure the test would fail if the implementation regresses to
using presented.data.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c65e6df2-870f-4a44-8ca7-a9a7777b109b

📥 Commits

Reviewing files that changed from the base of the PR and between 55193f7 and 06abf70.

📒 Files selected for processing (69)
  • .drive/projects/prisma-cli-v8/deferred.md
  • packages/cli-engine/src/execution/command-context.ts
  • packages/cli-engine/src/execution/settlement.ts
  • packages/cli-engine/src/presentation.ts
  • packages/cli-engine/src/telemetry/commands.ts
  • packages/cli-engine/tests/blocks.test.ts
  • packages/cli-engine/tests/clack-isolation.test.ts
  • packages/cli-engine/tests/clack-prompts.test.ts
  • packages/cli-engine/tests/command-capabilities.test-d.ts
  • packages/cli-engine/tests/command-families.test.ts
  • packages/cli-engine/tests/config.test.ts
  • packages/cli-engine/tests/credential-manager.test.ts
  • packages/cli-engine/tests/engine.type-test.ts
  • packages/cli-engine/tests/events.test.ts
  • packages/cli-engine/tests/execution.test.ts
  • packages/cli-engine/tests/interaction-affordances.test.ts
  • packages/cli-engine/tests/lifetimes.test.ts
  • packages/cli-engine/tests/management-api.test.ts
  • packages/cli-engine/tests/package-install-matrix.test.ts
  • packages/cli-engine/tests/package-operations.test.ts
  • packages/cli-engine/tests/palette.test.ts
  • packages/cli-engine/tests/prompts.test.ts
  • packages/cli-engine/tests/redirects.test.ts
  • packages/cli-engine/tests/run-hooks.test.ts
  • packages/cli-engine/tests/spawn.test.ts
  • packages/cli-engine/tests/telemetry-payload.test.ts
  • packages/cli-engine/tests/telemetry-run.test.ts
  • packages/cli/src/commands/agent/presentation.ts
  • packages/cli/src/commands/auth/login.ts
  • packages/cli/src/commands/auth/logout.ts
  • packages/cli/src/commands/auth/whoami.ts
  • packages/cli/src/commands/auth/workspace-logout.ts
  • packages/cli/src/commands/auth/workspace-use.ts
  • packages/cli/src/commands/branch/list.ts
  • packages/cli/src/commands/bucket/create.ts
  • packages/cli/src/commands/bucket/delete.ts
  • packages/cli/src/commands/bucket/key-create.ts
  • packages/cli/src/commands/bucket/key-delete.ts
  • packages/cli/src/commands/bucket/key-list.ts
  • packages/cli/src/commands/bucket/list.ts
  • packages/cli/src/commands/feedback.ts
  • packages/cli/src/commands/git/connect.ts
  • packages/cli/src/commands/git/disconnect.ts
  • packages/cli/src/commands/init/presentation.ts
  • packages/cli/src/commands/postgres/backup-list.ts
  • packages/cli/src/commands/postgres/connection-create.ts
  • packages/cli/src/commands/postgres/connection-list.ts
  • packages/cli/src/commands/postgres/connection-remove.ts
  • packages/cli/src/commands/postgres/connection-rotate.ts
  • packages/cli/src/commands/postgres/create.ts
  • packages/cli/src/commands/postgres/list.ts
  • packages/cli/src/commands/postgres/remove.ts
  • packages/cli/src/commands/postgres/restore.ts
  • packages/cli/src/commands/postgres/show.ts
  • packages/cli/src/commands/postgres/usage.ts
  • packages/cli/src/commands/project/env-add.ts
  • packages/cli/src/commands/project/env-remove.ts
  • packages/cli/src/commands/project/env-shared.ts
  • packages/cli/src/commands/project/env-update.ts
  • packages/cli/src/commands/project/presentation.ts
  • packages/cli/src/commands/project/remove.ts
  • packages/cli/src/commands/project/rename.ts
  • packages/cli/src/commands/project/show.ts
  • packages/cli/src/commands/project/transfer.ts
  • packages/cli/src/commands/service/presentation.ts
  • packages/cli/tests/auth.test.ts
  • packages/cli/tests/golden-rendering.test.ts
  • packages/cli/tests/mount-coverage.test.ts
  • packages/cli/tests/whoami.test.ts

Comment thread .drive/projects/prisma-cli-v8/deferred.md Outdated
Comment thread packages/cli-engine/src/execution/command-context.ts Outdated
Comment thread packages/cli-engine/src/execution/command-context.ts Outdated
Comment thread packages/cli-engine/src/execution/settlement.ts
Every fixture passed the same value as `data` and as the json
presentation, so none of them could tell which one the envelope
published. A new fixture makes them differ, and the test fails if
settlement goes back to publishing `data`.

Verified by making settlement publish `data` and watching it fail,
after rebuilding — the engine's own tests resolve the engine through
`dist`, so a source edit alone proves nothing.

Also restores the deferred entry about a single filter reporting green
against a stale engine build, which the previous commit deleted by
mistake. The concurrency race it was replaced with was already recorded
under S6, in more detail; that entry gains the second error message and
the varying failure count seen here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
wmadden-electric added a commit that referenced this pull request Aug 13, 2026
…answers to

Spec R7 requires product-repo e2e in prisma/prisma and composer, and
says nothing about the grammar this binary ships.

The binary answers to 89 commands, counted by walking --help from the
root through every group. 40 have an e2e test. 49 do not.

26 of the 49 come from other packages — 22 from orm-toolchain, 4 from
composer — and none of them is run by this repo's e2e suite at all,
though it is this binary that breaks when a mount breaks. #171 found
that the hard way: requiring next at runtime made migration list exit 2,
caught only by an in-process mount test.

The other 23 are this repo's own, listed with what each needs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
… human mode

I reported that requiring `stdout` at runtime was safe because the ORM
mount test passed. That test runs in json mode, and json mode never
calls `stdout` — so it could not have detected the failure it was cited
as ruling out.

orm-toolchain's `migration list` declares `human` and `json` and neither
of the other two. In human mode, the default for a user at a terminal,
the strict call made it exit 2.

`stdout` now uses the same optional call as `next`. `json` stays strict:
every ORM command declares one, and a missing json presentation is the
defect this change removes.

The mount test gains a human-mode run of the same command, because the
two formats call different presentation functions and a run in one
proves nothing about the other.

The real fix is not this shim. orm-toolchain is our code; declaring the
missing presentations there and building it against this engine makes
the type refuse to compile without them. Both `?.()` come out when that
version is pinned here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
@wmadden
wmadden merged commit 2f58c38 into main Aug 13, 2026
13 checks passed
@wmadden
wmadden deleted the presentations-required branch August 13, 2026 13:44
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.

2 participants