Skip to content

feat(workbench): schema-driven route input editors over a static manifest inputSchema (#105 stage 2) - #224

Merged
ScriptedAlchemy merged 2 commits into
mainfrom
wave5/105-s2
Sep 1, 2026
Merged

feat(workbench): schema-driven route input editors over a static manifest inputSchema (#105 stage 2)#224
ScriptedAlchemy merged 2 commits into
mainfrom
wave5/105-s2

Conversation

@ScriptedAlchemy

Copy link
Copy Markdown
Owner

First #105 stage-2 slice, per the stage-1 handoff: the compiled route inputSchema goes on the wire as a NEW optional field on RouteManifestRoute, with the routeSchema strict decoder in route-manifest-client.ts extended in the same PR (no other status/artifact DTO widened), and the Routes page renders generated input editors with validation before invoke.

Static projection — modules are still never executed

  • The bounded zod-AST machinery behind the Generate CLI, MCPorter, and script projections from the compiled route graph #102 argv grammar moved to routes/input-schema.ts; cli-argv.ts consumes it with byte-identical AB4814 diagnostics and argv output (existing tests unchanged).
  • extractInputSchema projects any conventional route module's export const inputSchema into a deterministic, deep-frozen JSON-Schema draft-2020-12 subset (type/properties/required/additionalProperties:false; scalar string|number|boolean, enum, array-of-scalar items, default, description). Validation-only refinements stay uninterpreted by design — the module's real zod schema still validates at execution.
  • Out-of-grammar schemas (rich MCP tool schemas referencing shared operation schemas) produce NO diagnostic and simply omit the field — only CLI routes keep their existing grammar diagnostics.
  • CompiledAgentRoute.inputSchema joins the graph identity/digest deterministically; routeManifestFor passes it through.

Workbench editors

  • Routes-page entries with a schema get a generated editor: string/number fields, boolean checkboxes, enum selects, repeatable array rows, required markers, defaults prefilled, descriptions shown, inline per-field validation errors, and an honest note that full validation runs at execution. Schemaless routes get a labeled raw-JSON fallback.
  • Tool routes: validated input hands off to the existing MCP page via typed hash-navigation state — server, tool (route id's last segment), and arguments arrive prefilled with a visible "nothing runs automatically" callout; the real session, consent, and call controls are unchanged (extend, don't fork).
  • CLI routes: validated input renders a copyable shell-quoted argv invocation; usage strings now come from one shared formatter (cliCommandUsage) matching the generated CLI help conventions landed in fix(workbench): route catalog review fixes from #211 (usage arity, empty server surfaces, stale-repair e2e) #222.
  • The flagship example's inventory_sources tool now declares its schema as an in-grammar literal mirroring the operation contract exactly (source/report?/strict? + describes), so the catalog demonstrates a projectable tool schema.

Verification

  • pnpm typecheck + all example typechecks: clean. pnpm lint: 859 files, 0 issues.
  • Unit: 2042 passed / 4 skipped (extractor grammar edges, digest determinism, manifest pass-through, strict client decode incl. unknown-field rejection, editor validation, prefill round-trip). Route-unit: 11 passed.
  • Browser (real Chrome, 1440×900): examples-real.e2e.test.ts 5/5 — the flagship journey now covers generated editor fields, a validation error, the enabled MCP handoff with prefilled server/tool/arguments, the CLI argv line, then the stale→repair legs from fix(workbench): route catalog review fixes from #211 (usage arity, empty server surfaces, stale-repair e2e) #222.

Stage-2's Agent Document stage (render-event stream for route runs) follows in the next PR; stages 3–4 (lifecycle replay, host inventory) remain per #107.

Project bounded route schemas into the manifest so Routes can validate inputs, hand tool calls to existing MCP sessions, and render CLI argv without executing route modules.
Mirror the flagship tool's real operation schema and retain the canonical generated-CLI usage format after rebasing the editor slice.
@changeset-bot

changeset-bot Bot commented Sep 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f36462e

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 1, 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-01T22:24:54.713925Z f36462e 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.

@ScriptedAlchemy
ScriptedAlchemy merged commit 101e70b into main Sep 1, 2026
9 checks passed
@ScriptedAlchemy
ScriptedAlchemy deleted the wave5/105-s2 branch September 1, 2026 22:22

@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: f36462e3bc

ℹ️ 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".

}
return typeof schema.default === 'boolean' ? schema.default : String(schema.default);
}
if (schema.type === 'boolean') return false;

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 Preserve the unset state for optional booleans

For an optional boolean such as the new strict: z.boolean().optional(), initializing the draft to false makes validateRouteInput treat the field as present and hand off { strict: false } even when the user never touched the checkbox. This changes the route input from an omitted property to an explicit false value, which is observable by handlers and defeats optional/default semantics; the draft needs an unset state distinct from false.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in #226 (6901324): an optional boolean without a schema default now stays out of the draft and renders as a three-state (omitted)/true/false select, so an untouched field is omitted from the validated arguments and the MCP prefill while an explicit false still travels as false. Required and defaulted booleans keep the checkbox. The flagship e2e asserts strict is absent from the prefill unless explicitly set.

Comment on lines +1097 to +1098
const [toolName, setToolName] = useState(initialToolPrefill?.toolName ?? '');
const [toolArguments, setToolArguments] = useState<ImmutableJsonRecord>(initialToolPrefill?.arguments ?? {});

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 Do not fall back to another tool for stale prefills

When a prefill names a tool that the opened server no longer advertises—for example, when handing off from the explicitly supported stale route catalog—this nonempty toolName fails the lookup at selectedTool, which then silently falls back to tools[0] while retaining the prefilled arguments. The resulting call control can therefore invoke an unrelated first tool with arguments intended for the missing tool; reject or clear a mismatched prefill instead of allowing that fallback.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in #226 (6901324): a non-empty tool selection the live session does not advertise no longer falls back to tools[0] — the prefill aside states the server no longer advertises that tool and no call control renders, so the prepared arguments can never attach to a different tool; manual selection of an advertised tool starts with empty arguments. The plain manual flow (empty selection defaults to the first tool) is unchanged.

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