feat(workflow): data-reference chips (upstream-scoped, byte-safe)#2604
Open
simlarsen wants to merge 1 commit into
Open
feat(workflow): data-reference chips (upstream-scoped, byte-safe)#2604simlarsen wants to merge 1 commit into
simlarsen wants to merge 1 commit into
Conversation
…upstream-scoped insert
Referencing another step's output used to mean picking from a full-screen
modal that string-appended a raw {{local.components.…}} token you then had to
read and manage by hand. This adds an inline chip experience for text
arguments:
- Existing tokens in the value render as friendly, removable chips
("Error · from Send to Slack"), turning red when the referenced step or
output no longer exists.
- A new reference is inserted from an inline menu scoped to UPSTREAM steps
(with a "Show all steps" escape), so you can't reference data that won't
exist at runtime.
- Variables still use the existing VariableModal.
Deliberately NOT a contentEditable editor: the stored value stays a plain
string (tokens are appended / index-spliced), so a workflow round-trips
byte-for-byte and the executor is untouched. This also makes it fully
unit-testable — the parse/describe/append/remove logic is pure (TokenUtils),
and the token format is byte-identical to what ComponentValuePickerModal /
VariableModal already produce.
Only text-like fields get the chip footer; JSON editors keep the existing
modal-based picker. The set of fields that show a data-reference footer is
unchanged from before — only the footer's UI changed.
Tests: TokenUtils (14 pure-logic cases incl. byte-exact occurrence removal and
adjacent-duplicate disambiguation) + DataReferenceInput (4 RTL cases: chip
render, broken-reference flag, precise removal, upstream-scoped insert +
show-all). 48 workflow tests pass; tsc + eslint clean. Verified byte-safety
and the value-sync chain via an adversarial review pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
Author
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
This was referenced Jul 8, 2026
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.
The last and highest-risk piece of the workflow-builder simplification: turning the raw
{{…}}data references into chips. Stacked on #2602 (GitHub retargets tomasteronce the stack merges).The problem
Referencing another step's output meant opening a full-screen modal that string-appended a raw token like
{{local.components.slack-1.returnValues.error}}into the field — which you then had to read and manage by hand. No readability, no removal, no validation that the referenced step actually runs before this one.What changed
For text arguments, the footer is now an inline data-reference helper:
Error · from Send to Slack— that turn red when the referenced step or output no longer exists.VariableModal.Why this design (and not contentEditable)
The stored value stays a plain string — tokens are appended / index-spliced — so a workflow round-trips byte-for-byte and the executor is untouched. A rich
contentEditablechip editor was deliberately avoided: it risks corrupting saved workflows and, critically, jsdom can't test it, so it couldn't be verified with the component-testing approach used here. Keeping the string as the source of truth makes all the logic pure and fully testable.buildComponentToken/ variable tokens are byte-identical to whatComponentValuePickerModal/VariableModalalready produce.Verification
TokenUtils.test.ts(14): parse/classify/describe/append + byte-exactremoveTokenOccurrence(correct occurrence among adjacent duplicates, surrounding text preserved, out-of-range no-op).DataReferenceInput.test.tsx(4, RTL/jsdom): chips render, broken-reference flagged, precise removal, upstream-scoped insert + show-all.tsc✓,eslint✓.setFieldValue → onChange → setComponent → props.fields → useAsyncEffect), confirmed the token formats byte-for-byte against the pickers and executor, and found no real bug or regression — only two theoretical nits that match pre-existing behavior.🤖 Generated with Claude Code