Skip to content

feat(vscode): search instances by process variables - #473

Merged
emaarco merged 7 commits into
cli-default-namesfrom
issue-456
Oct 27, 2026
Merged

emaarco merged 7 commits into
cli-default-namesfrom
issue-456

Conversation

@emaarco

@emaarco emaarco commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

Why

The instance list of a definition can only be searched by business key. Finding an order by customer or amount meant switching to the engine's web app. This adds a search by process variables, in the engine-neutral contract with its conformance laws and in the definition panel.

What

  • Contract: InstanceFilter.variables takes conditions that must all hold:
    • equals, notEquals, greaterThan and lessThan carry valueJson, so big integers stay exact and 42 never matches the text "42".
    • null finds a variable whose value is null, never a missing one.
    • A date comparison carries at, an IsoTimestamp, and compares points in time; text never matches a date.
    • like carries a pattern in which * is the only wildcard.
    • A condition matches a variable of any scope, so task-local variables count.
    • notEquals never finds an instance without the variable, and a value of another type counts as different.
    • Ended instances match, and an empty list constrains nothing.
  • Contract read listVariableNames(definitionId): the names of the variables the instances of a version hold, at any scope, sorted and once each. It is a hint for the dialog, not a complete list.
  • Laws and saboteurs: ORD-1002 of the conformance world now also holds a date (dueAt) and a null variable (giftNote). Fourteen saboteurs prove the laws catch a broken runtime. The shared sabotage helpers moved to test/contract/support/sabotaged-runtime.ts.
  • C7 adapter: VariableConditionMapper maps the conditions to variables of the historic process instance query. It parses values with LosslessJson, sends a date in UTC in the engine's date format (2026-03-15T10:00:00.000+0000, the only form the engine reads as a date), escapes \, % and _ in patterns and turns * into %. VariableNameReader reads the names from the history of the newest 50 instances of the version (historic-variable-instance query --no-deserialize-values).
  • Protocol and core:
    • InstanceListFilter.variables carries up to 5 conditions as text with an optional type.
    • VariableConditionRules handles the types: Automatic, Text, Number, True or false, Date and time, and Null. Automatic implies text for like and a number for >/<. It also labels the chips.
    • MessageGuards drops a condition that does not fit its type.
    • Counts, live counts and select all matching follow the conditions.
    • The cancel confirmation names them in its filter line.
    • suggestVariableNames loads the names of the shown version once into DefinitionView.variableNames. A failed read suggests nothing.
    • A version switch keeps them.
  • Webview:
    • A funnel button ("Filter by variables", the count of conditions beside the icon) opens a modal <dialog> for one condition, with inline errors and focus on the first invalid field.
    • Opening it sends suggestVariableNames. The core reads the names once per version, and the name field offers them in a datalist while it still takes any text.
    • Date and time uses a datetime-local field and offers is after and is before. Null asks for no value and offers is null and is not null. A hint says that JSON and object variables can't be searched.
    • With conditions the filter bar wraps into a second row instead of cutting the chips.
    • Each condition becomes a chip that edits or removes it, and focus returns to whatever opened the dialog.
    • Escape closes only the dialog and keeps the selection.
    • An empty result offers Clear variable conditions.
    • InstanceFilter.compose now keeps the conditions, so a scope change or a business-key search no longer drops them.
  • Docs: ADRs runtime-contract.md, c7-adapter.md (date format, history level AUDIT, JSON and objects not searchable), user-interface.md and architecture.md, the contract README, the architecture overview and docs/vscode/usage.md.

Verification

  • test:engines passes 61/61 against Operaton 2.1.5, CIB seven 2.2.0 and Camunda 7.24.0.
    • A probe first showed that task-local variables match, \_ escaping works, neq skips instances without the variable and number 42 matches an Integer variable but the text "42" does not.
    • A run after the review showed route ≠ 42 finds text values too, which the notEquals law now pins.
    • A type probe showed that the engines compare Short, Integer, Long (exactly beyond 2^53), Double, Boolean, Null and Date. A date is compared only in the yyyy-MM-dd'T'HH:mm:ss.SSS+0000 format. JSON and Object variables match no condition, like included.
  • Root pnpm build, pnpm typecheck, pnpm test, pnpm lint (incl. ratchets, architecture rules, knip) and pnpm format:check pass.
  • pnpm test:mutation scores 84.52 on the changed files, above the threshold of 79.
  • Chromium webview tests cover:
    • the dialog, its errors and focus;
    • chips: edit, remove, focus return, and that they stay visible in a narrow panel;
    • Escape, scope changes and the empty state;
    • a drift test that pins the dialog's constants to VariableConditionRules.
  • I only checked the screens through a temporary browser test.
  • Not run: test:e2e, docs:screenshots and a manual check in the sandbox.

Out of scope / Follow-ups

  • No atLeast/atMost operators in v1.
  • The value field stays editable before a name is set. A disabled field would drop out of the tab order without saying why, and Apply already names a missing name.
  • JSON and object variables stay unsearchable: the C7 family stores them serialized and its query cannot read them.
  • The webview's dialog repeats the operator table, the number and date patterns and the cap of VariableConditionRules as constants, because the webview may import the protocol only as types. A test holds them equal. Sending them in the view model would remove the copy.

Closes #456

@netlify

netlify Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for spectacular-cobbler-f6c85b ready!

Name Link
🔨 Latest commit 499b879
🔍 Latest deploy log https://app.netlify.com/projects/spectacular-cobbler-f6c85b/deploys/6ae0a04fb674b08ab204b19c
😎 Deploy Preview https://deploy-preview-473--spectacular-cobbler-f6c85b.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@emaarco
emaarco changed the base branch from main to cli-default-names October 27, 2026 12:11
InstanceFilter takes AND-combined variable conditions (equals, notEquals,
greaterThan, lessThan with a valueJson, like with a * pattern). Nine read
laws pin the semantics on the fake and on Operaton, CIB seven and Camunda 7,
nine saboteurs prove they bite. The C7 adapter maps them to variables of
the historic process instance query.

Refs #456
…core

InstanceListFilter carries up to five variable conditions as text with an
optional type. VariableConditionRules holds the type inference, the operators
per type and the chip label for the guard, the core and the webview alike.
Counts, select all matching and the cancel confirmation follow the
conditions, and a version switch keeps them.

Refs #456
A Variables button in the filter bar opens a modal dialog for one
condition: name, compare as, operator and value. Each condition becomes a
chip that edits or removes it; the conditions survive scope changes, the
element filter and the business-key search. Escape closes the dialog
without clearing the selection, and an empty result offers to clear the
conditions. Core labels the chips; the dialog's operator table, number
pattern and cap are held equal to the protocol's rules by a test.

Closes #456
- Keep the variable chips below 760 px, so a narrow panel still shows, edits
  and removes every condition.
- Move focus to the first invalid field after the errors render, and back to
  the chip that opened the dialog when it closes.
- Pin that notEquals finds a value of another type, as all three engines do,
  with a law and a saboteur.
- Say in the empty list that an engine without variable history finds none.
- Derive the guard's operators and types from VariableConditionRules, reuse
  the view's labels in the cancel confirmation, cap the name at 255 like the
  guard, and record the protocol change in architecture.md.

Refs #456
Compare as offers Date and time and Null besides text, number and true or
false. A date condition carries an IsoTimestamp in the contract and compares
points in time; C7 sends it in UTC in the engine's date format, the only form
the engine reads as a date. Null compares with null and never finds a missing
variable. The dialog says that JSON and object variables cannot be searched,
because the engine keeps their value serialized. Two laws, two saboteurs and a
date and a null variable on ORD-1002 pin it on all three engines. With
conditions the filter bar wraps into a second row instead of cutting the chips.

Refs #456
The filter bar opens the variable dialog from a funnel button named "Filter by
variables", with the count of conditions beside the icon. Opening it sends
suggestVariableNames; the core reads listVariableNames once per version and
puts the names into the view, and the name field offers them in a datalist
while it still takes any text. listVariableNames is a new read of the
contract: the names of the variables the instances of a version hold, at any
scope, sorted and once each, pinned by a law and two saboteurs. C7 reads them
from the history of the newest 50 instances.

Refs #456
@emaarco
emaarco added this pull request to stack #485 October 27, 2026 12:27
@emaarco
emaarco marked this pull request as ready for review October 27, 2026 12:28
@emaarco
emaarco merged commit fe142c9 into main Oct 27, 2026
30 checks passed
@emaarco
emaarco deleted the issue-456 branch October 27, 2026 13:11
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.

[Feature]: VS Code extension: search instances by process variables, not only by business key

1 participant