feat(ide): engine lens schema CLI and a schema-driven Steps renderer (BACKLOG #235) - #226
Open
wshallwshall wants to merge 5 commits into
Open
feat(ide): engine lens schema CLI and a schema-driven Steps renderer (BACKLOG #235)#226wshallwshall wants to merge 5 commits into
lens schema CLI and a schema-driven Steps renderer (BACKLOG #235)#226wshallwshall wants to merge 5 commits into
Conversation
…t widgets (BACKLOG #235) The Steps editor's per-op input widgets are now derived from the transform vocabulary's own Python type hints, instead of a hand-maintained IDE-side table that drifts from the signatures. Engine (new messagefoundry/lens_schema.py + a `lens schema [--json]` CLI): - op_param_schema() derives {op -> [param]} from actions.__all__ and diagnostics.__all__ via stdlib inspect + typing (eval_str=True) -- no new runtime dependency (ADR 0076 section 6.5). Covers BOTH sources, so no row kind bypasses the schema-driven renderer (the diagnostic ops log_note/checkpoint included). - The `lens schema` subcommand lazy-imports the module and starts no server, mirroring `hl7schema --json`. - Per-param contract: {name, kind, required, keyword_only} plus optional choices (enum), nullable (X | None), and default (JSON scalar only -- a non-serializable sentinel like code_lookup's _UNSET is omitted so json.dumps never raises). IDE (cli.ts / stepsView.ts / stepsModel.ts / stepsWebview.js): - cli.ts shells `lens schema` (execFile, the same path as `lens parse`); stepsView fetches it once and threads an optional schema through the render chain (undefined keeps byte-identical text inputs, so every existing caller is unchanged). - A pure resolveWidget() maps kind -> widget for EDITABLE params only (gating unchanged, ADR 0076 section 5): int/float -> number input, enum -> select, everything else and any unmapped op -> the current text input. code/control rows stay read-only. - Retype fix: a number field posts a JS number, preserved through buildEditRequest to the engine, so `lens rewrite` renders an int literal (6) rather than retyping it to a string ("6") -- a latent corruption on the currently-editable int args. Tests: tests/test_lens_schema.py (derivation, dual-source coverage, CLI smoke, and the committed-fixture sync guard) and ide steps-schema.test.ts (renderer + widget-resolver + edit round-trip), each falsified against a planted defect. Full pytest -q green (10346 passed, 843 skipped); IDE Extension Host suite green (648). Deliberate scope: did NOT touch ADD_MENU_CATALOG/TOOLBAR_INSERT_DEFAULTS (structural insert templates with no Python signature to derive from); did NOT narrow the four closed-set str params to Literal[...] (owner-gated -- so enum -> dropdown is built but dormant until an op emits an enum kind). NOT-DEPLOYED beta: no prior schema contract to preserve, so no compatibility shim.
…t (BACKLOG #235) Flip #235's status banner only, from not-started to in-progress: the engine-emitted param schema (the `lens schema` CLI) and the schema-driven IDE renderer are built and committed (64a0e12). The item is NOT closed -- the enum-to-dropdown widget is dormant until the owner rules on OQ1 (narrowing the four closed-set str params to Literal). Scope: only #235's banner line under its own heading changed. The ranked table and the four census distribution lines were NOT touched, and the census was NOT recomputed (not-started -> in-progress is open -> open, so the distribution is unchanged anyway).
…ps renders enum dropdowns (BACKLOG #235) OQ1 follow-on to the engine-emitted Steps param schema: narrow the closed-set string arguments to Literal[...] so `lens schema` projects them as `enum` (with their choice list) and the IDE renders a dropdown instead of a text input -- the item's headline widget, previously built but dormant. - actions.py: convert_case mode -> Literal["upper","lower","title"]; pad_field side -> Literal["left","right"]; arith_field op -> Literal["+","-","*","/"]; date_diff_field unit -> Literal["days","years","hours","minutes"]. The runtime if/elif ValueError guards are kept: the Literal defends the author-time typed caller and drives the dropdown; the guard still catches a dynamically-supplied bad value at run time. The intentional two-layer overlap is documented once in the module docstring. - Regenerated ide/src/test/fixtures/lens-schema/op-schema.json (the four ops now carry kind "enum" + choices); test_ide_fixture_in_sync keeps it faithful. - New test_closed_set_param_becomes_enum pins the enum derivation (falsified: reverting a Literal flips kind enum->str and reds the test). No test_actions.py change needed: CI mypy is `mypy messagefoundry messagefoundry_webconsole` (tests/ is not type-checked) and Literal is not enforced at run time, so the negative-guard tests still raise ValueError and pass unchanged. stepsModel.ts already prepends an out-of-set literal as the selected <option>, so a hand-authored value outside the choice set displays correctly. Verify: ruff + ruff format clean; mypy messagefoundry clean (the 21 remaining are pre-existing optional-extra import errors, none in touched files); IDE Extension Host suite 649 passing; full pytest 10346 passed / 843 skipped. The one full-suite failure (test_installed_coord_hooks push_guard.py: installed-vs-committed hash mismatch) is PRE-EXISTING and environmental -- a concurrent edit of the shared coord hook by another session; proven independent of this change by a control arm (it fails identically with all OQ1 changes stashed, and its hashes moved between two runs 22 min apart).
…wing (BACKLOG #235) Flip #235's status banner only, from in-progress to closed. With OQ1 landed (48b829b), all the item's widgets are live: int-to-number, the retype-trap fix, and enum-to-dropdown for the four closed-set ops. The code-set picker is N/A (no editable code-set literal to attach to) and code/control rows stay read-only, so the item's scope is complete. Scope: only #235's banner line under its own heading changed. The ranked table and the four census distribution lines were NOT touched, and the census was NOT recomputed (in-progress -> closed; the coordinator reconciles the distribution).
wshallwshall
enabled auto-merge (squash)
August 6, 2026 00:40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes BACKLOG #235. Adds an engine
lens schemaCLI and an IDE renderer driven by it, including OQ1 enum dropdowns.The schema is emitted by the engine rather than duplicated in the IDE, so the two cannot drift -- a second hand-maintained copy of a parameter schema is a divergence waiting to happen, and the renderer reading the engine's own output removes the possibility rather than documenting against it.
BACKLOG #248 is queued behind this merging -- brief at
.git/mefor-coord/brief-248-NOTE-ROW.md.Per-lane notes, owner decisions and merge notes:
.git/mefor-coord/handoff/LANE-HANDOVER-backlog-session-2e228e.md(not published).Verified: 11 files;
merge-treeagainstorigin/mainreports 0 conflicts; working tree clean at handoff.