Skip to content

feat(test): rendered commands at the cli-dispatch proof level (#253) - #266

Merged
ScriptedAlchemy merged 1 commit into
mainfrom
feat/253-rendered-cli-harness
Sep 2, 2026
Merged

feat(test): rendered commands at the cli-dispatch proof level (#253)#266
ScriptedAlchemy merged 1 commit into
mainfrom
feat/253-rendered-cli-harness

Conversation

@ScriptedAlchemy

Copy link
Copy Markdown
Owner

Closes #253. Consumer-harness follow-up to #102 stage 3 (#186): the public agent-bundle/test harness now proves rendered (.tsx) CLI commands at the cli-dispatch proof level.

What changed

  • invokeCli dispatches rendered commands through the product's own shell (runGeneratedCliEntry): when the manifest carries rendered commands, the harness preloads their route modules and installs an in-process render session mirroring the generated executable's worker-backed one — same invocation shape ({ kind: 'cli', props: { args, command } }), same request scope (operationId/surface, cwd-derived workspace per fix(test): honest registry version gate, binary-faithful CLI cwd, README field #206), same validate (resultSchema.parse), and the same synchronous inputSchema.parse inside the render factory so an input rejection stays a usage failure (exit 2), exactly like the generated render bridge in entry-shell.ts.
  • No second rendering path: render.ts gains one shared Flight-dispatcher wiring (createFlightDispatcher + prepareCliRenderHost) used by both renderRoute/renderRouteEvents and the CLI session, including mountManifestState parity with the generated rendered worker (pinned by the fixture's stateMounted: z.literal(true)).
  • New public surface: InvokeCliOptions.tty (explicit interactive mode; piped stays the deterministic default) and cliNdjson(invocation) — the ordered CliRenderedEvent[] a --ndjson run wrote, with honest AgentTestError diagnostics when stdout is not an event stream. CliRenderedEvent is re-exported.
  • Fixture: route-harness/src/cli/report.tsx, a rendered command switchable across success / render-error / invalid-result / wait-for-abort.
  • Projection tests (tests/projection/cli-dispatch-rendered.test.ts, in-process pool — zero cost added to the packed pool): piped Markdown (progress never on stdout), explicit TTY progress-in-place (\r\x1b[2K), canonical --json value, --ndjson with monotonic sequences + terminal complete + no jsonrpc key (CLI dialect purity), mid-render cancellation (Aborted., exit 1), component render error, resultSchema rejection, rendered inputSchema rejection (exit 2 + usage hint), --ndjson on a plain command and --json --ndjson conflicts (exit 2), and honest cliJson/cliNdjson failures on Markdown output.
  • Stale claims removed: the src/test/cli.ts header no longer says rendered routes are an AB4816 compiler error; the module states honestly what this level does not prove (no worker thread, no process framing, no chunk-by-chunk Flight timing — the packed CLI suite owns that). README proof-level table + example and the cli-tool scaffolder template now explain plain vs rendered proof levels.
  • Minor changeset for agent-bundle.

Provenance

Every rendered dispatch stamps proofLevel: 'cli-dispatch'; a pass here is not packed-executable evidence — cli-routes-build.test.ts keeps that claim.

Local gates (all run on this branch)

  • pnpm test:projection — pass (includes the 10 new rendered-dispatch tests)
  • pnpm test:unit — 2366 passed, 5 skipped, 0 failed
  • pnpm test:route-unit — 15 passed
  • pnpm typecheck — clean (root, workbench, create-agent-bundle)
  • pnpm lint — 0 errors, 0 warnings (912 files)

@changeset-bot

changeset-bot Bot commented Sep 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 113aba9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
agent-bundle Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-02T03:04:31.116887Z 113aba9 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@pkg-pr-new

pkg-pr-new Bot commented Sep 2, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle@266
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/create-agent-bundle@266
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@266

commit: 113aba9

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 113aba92f5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (!Number.isInteger(record['sequence'])) {
throw new SyntaxError('NDJSON render events must carry an integer sequence.');
}
switch (record['type']) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Validate NDJSON event payloads before casting

When stdout contains an object such as {"sequence":0,"type":"complete"}—for example from a plain command or a truncated stream—this switch accepts it and casts it to CliRenderedEvent even though the required document is absent. Consumers can then trust the exported union type and fail while accessing its fields; validate the required payload for each discriminator before returning the events.

Useful? React with 👍 / 👎.

Comment on lines +183 to +184
modulePath: firstDescriptor.source,
relativePath: firstDescriptor.relativePath,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Derive provenance from the executed rendered command

In a project with multiple rendered commands, this host permanently takes modulePath and relativePath from the first rendered command. When a later command has an invalid default export or missing schema, prepareCliRenderHost replaces only routeId, so the resulting diagnostic names the invoked route but points to the first route's source file; construct provenance from the current command's manifest descriptor instead.

Useful? React with 👍 / 👎.

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.

Teach the public CLI test harness to exercise rendered commands

1 participant