feat: field-bound @ SAY GET — promotes LOOKUP to full end-to-end (#59)#65
Merged
Conversation
… form-error on rejection
Both BROWSE and forms now declare, enforce, and render LOOKUP end to end, so this is the PR that adds the full command-table entry and the field-binding precedence note to the README.
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.
Summary
Makes
@ SAY GETbind directly to a table column when one matches — the dBASE III behavior WebBase-III's memory-variable-only forms had deviated from until now.Executor.doAtSayGetrecognizes aGETwhose name matches the active table's column (case-insensitive) and binds to it, capturing the record's rowid and prefilling from its current value. Fields take precedence over a memory variable of the same name — the reason them_prefix convention exists. A field-boundGETrequires a current record (** Error: GET <field>: no current recordotherwise — this must be a hard failure, not a silent no-op).LOOKUP, the form renders the same picker BROWSE does; an unresolvable lookup degrades to free entry with a warning, same as everywhere else.form-submitwrites field-bound values by their captured rowid — never by trusting the client's message for which columns exist on the form, mirroringgrid-edit's authoritative re-check. Submission is all-or-nothing: every field is validated (type + fresh lookup re-resolution) before any is written. A rejection sends a newform-errormessage; the client keeps the form open with the bad fields outlined instead of silently discarding the valid ones.FormLayout,Terminal) stopped self-closing the form on submit — it now waits for the server's verdict (view-terminalon success,form-erroron rejection) — and renders<select>s for lookup-bearing fields.One pre-existing test collision surfaced and was fixed: three
tests/Session.test.tscases used a memory variable namedvalin a table that also has a column namedVAL— under the new precedence rule this now binds to the field. Renamed the variable tom_valthroughout (purely mechanical, same asserted outcomes) — verified necessary because the original sequence GETs before any record exists, which would otherwise now throw.This is the PR that promotes
LOOKUPto the full README command reference — both BROWSE and forms now declare, enforce, and render it end to end.Plan:
docs/superpowers/plans/2026-07-11-lookup-columns.md(Tasks 7, 8, 9)Closes #59.
Test plan
npm test— 444/444 vitest passnpm run build— clean typecheck + buildnpx playwright test— 94/94 passtests/FormFieldBinding.test.ts: field binding + prefill + options; fields shadow memvars; fallback to var when no column matches; hard error with no current record (and noform-opensent); lookup degradation still opens the form; all-or-nothing submit (exactform-errorpayload, valid sibling field confirmed NOT written); corrected resubmit succeeds; forged form-submit naming an undeclared column can't write it; DATE type validation on a field;grid-exitclears pending state so a stale resubmit is inert; the Test hardening: strict CREATE TABLE parser, demo schema pins, untested WS message types #50 bare-INPUTregression stays fixed