Repository navigation
FE-1990: Add a reusable way to run flows end to end - #10052
Merged
kostandinang merged 12 commits intoOct 19, 2026
Merged
kostandinang merged 12 commits into
kostandinang merged 12 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
3 Skipped Deployments
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #10052 +/- ##
==========================================
- Coverage 68.13% 68.02% -0.12%
==========================================
Files 1995 2000 +5
Lines 205556 205894 +338
Branches 8708 8782 +74
==========================================
Hits 140053 140053
- Misses 63838 64176 +338
Partials 1665 1665
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
kostandinang
force-pushed
the
kostandin/fe-1990-add-a-reusable-way-to-run-flows-end-to-end
branch
from
October 19, 2026 11:52
da0c287 to
a66207e
Compare
CiaranMn
previously approved these changes
Oct 19, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Oct 19, 2026
Moves the local runner into apps/hash-ai-worker-ts/scripts/flow-scenarios with the Array actions scenario. It writes the scenario's definition as a Flow Definition entity in the user's web, then starts the run by its id like the startFlow resolver. Co-authored-by: Amp <[email protected]>
…eated Co-authored-by: Amp <[email protected]>
Split the start-up checks and the run into named steps, compare a stored Flow Definition the way seeding does, default every step expectation to COMPLETED, use the resolved payload types instead of a cast, and honour HASH_TEMPORAL_UI_PORT in the run link. Co-authored-by: Amp <[email protected]>
…entity uuids are now unique across webs Co-authored-by: Cursor <[email protected]>
A step only waits for the steps whose outputs it takes, so a flow can't query for the entities it creates. Runs start one after another, and a tag unique to each time the scenario runs lets a later run find only the entities an earlier one created. A step inside a forEach is reported once per item. Co-authored-by: Cursor <[email protected]>
…t, and say why a run failed when no step did - A worker from a sibling folder whose path starts with this checkout's no longer passes as this checkout. - Step ids in expectations are checked against the flow: a forEach step isn't run itself, and a step inside one runs as <stepId>~<index>. - A run still going at the timeout is terminated, so it can't change the graph after the scenario has moved on. - When a run fails outside its steps, such as naming the run without an Anthropic key, the report gives the activity and its error. Co-authored-by: Cursor <[email protected]>
… scenario A scenario can list entities for the runner to create in the user's web before the first run, tagged with the run tag. They're all checked against their types first, naming any value that doesn't fit, so that a mistake creates nothing. The Query entities scenario finds seeded Docs by tag, then filters, sorts and aggregates them on properties read from the graph, and checks the graph's own sorting and limit. Co-authored-by: Cursor <[email protected]>
Runs steps once per item, with one item feeding two steps and a step only some items run, checks the results are collected in item order, and that a forEach over an empty list completes with nothing collected. The report shows a nested step that ran for no item as such. Co-authored-by: Cursor <[email protected]>
Co-authored-by: Cursor <[email protected]>
…rting is ignored Co-authored-by: Cursor <[email protected]>
…s out Co-authored-by: Cursor <[email protected]>
…unner Co-authored-by: Cursor <[email protected]>
kostandinang
force-pushed
the
kostandin/fe-1990-add-a-reusable-way-to-run-flows-end-to-end
branch
from
October 19, 2026 16:42
b212d21 to
5976485
Compare
CiaranMn
approved these changes
Oct 19, 2026
kostandinang
deleted the
kostandin/fe-1990-add-a-reusable-way-to-run-flows-end-to-end
branch
October 19, 2026 17:22
This branch was successfully deployed
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.
🌟 Purpose
Flow actions only have unit tests. This adds a way to run flows end to end on the local stack: a scenario is one or more flow runs, each a flow definition, its inputs and the expected outputs, optionally with entities to create first.
run-flow-scenarioruns them through Temporal, checks every step and prints a report for the PR.It comes with three scenarios for what's on
main:forEachover an empty list completes with nothing collected.🔍 How it works
Everything is in
apps/hash-ai-worker-ts/scripts/flow-scenarios/, and its README covers starting the stack and writing a scenario.🧐 To review
hweb. An entity uuid can only be used in one web, so the definition's uuid is derived from the scenario'sflowDefinitionIdand the user.seedandinputsto mark the entities and query for exactly those.main, the only action that creates entities ispersistEntity(ies), which may update a similar existing entity (matched by OpenAI embeddings) instead of creating one. Seeding through the graph keeps the scenario exact.🚫 Out of scope
Scenarios for actions not yet on
maincome with those actions: an entity round trip is ready to go with #10060. CI comes after FE-1904.🛡 Tests
On a local stack (the
aiworker needs a realANTHROPIC_API_KEYin.env.local, since every run asks a model to name itself):tsc --noEmitand ESLint pass.Array actions run report
Flow scenario: Array actions on a list of numbers
Chains Filter List, Order By, Take First and Aggregate, branches on the total with If, and checks the untaken branch is skipped.
Local stack at
b212d219fd, started through Temporal. Run taged46c55f-d26b-4574-b1e0-198675487623.Run 1 of 1: Array actions run
873ffc25-39d0-4a3b-b24b-268dea35b845: COMPLETEDpassingmatching: 4 × Number [72,90,50,99]nonMatching: 3 × Number [45,8,30]passingCountresult: Number 4rankeditems: 4 × Number [99,90,72,50]topitems: 2 × Number [99,90]totalresult: Number 189isBigtrue: Number 189whenSmallfirstLowmatch: Number 8Expectations: 20 of 20 met
passingis COMPLETEDpassing.matchingpassing.nonMatchingpassingCountis COMPLETEDpassingCount.resultrankedis COMPLETEDranked.itemstopis COMPLETEDtop.itemstotalis COMPLETEDtotal.resultisBigis COMPLETEDisBig.trueisBig.falsenot producedwhenSmallis SKIPPEDfirstLowis COMPLETEDfirstLow.matchtotalfirstLowExpectations: 20 of 20 met
Query entities run report
Flow scenario: Query entities on seeded Docs
Finds seeded Docs by the run's tag with Query entities, filters, sorts and aggregates them on properties read from the graph, and checks the graph's own sorting and limit.
Local stack at
b212d219fd, started through Temporal. Run tagd01bc29b-15d0-4e22-9dd0-8da2285e4a66, 3 entities seeded.Run 1 of 1: Query tagged docs
fd4d37ed-6d9a-4fef-9e69-52397f0f8e0f: COMPLETEDfoundentities: 3 × EntityId ["cbf261a6-8a16-4436-ba51-2dd64e67aeddc019806b-9474-4e05-b147-22f7d8615332","cbf261a6-8a16-4436-ba51-2dd64e67aedd40396128-b155-421d-8786-…foundCountresult: Number 3totalPagesresult: Number 168longmatching: 2 × EntityId ["cbf261a6-8a16-4436-ba51-2dd64e67aeddc019806b-9474-4e05-b147-22f7d8615332","cbf261a6-8a16-4436-ba51-2dd64e67aedd898ac73e-049c-4fda-a4a2-…nonMatching: 1 × EntityId ["cbf261a6-8a16-4436-ba51-2dd64e67aedd~40396128-b155-421d-8786-89b0f50e47d5"]longCountresult: Number 2earliestLongYearresult: Number 2021byYearitems: 2 × EntityId ["cbf261a6-8a16-4436-ba51-2dd64e67aedd898ac73e-049c-4fda-a4a2-d6daf4a44d9c","cbf261a6-8a16-4436-ba51-2dd64e67aeddc019806b-9474-4e05-b147-…earliestLongitems: 1 × EntityId ["cbf261a6-8a16-4436-ba51-2dd64e67aedd~898ac73e-049c-4fda-a4a2-d6daf4a44d9c"]earliestLongPagesresult: Number 40shortmatch: EntityId "cbf261a6-8a16-4436-ba51-2dd64e67aedd~40396128-b155-421d-8786-89b0f50e47d5"shortPagesresult: Number 8hugewhenHugefirstTwoByTitleentities: 2 × EntityId ["cbf261a6-8a16-4436-ba51-2dd64e67aeddc019806b-9474-4e05-b147-22f7d8615332","cbf261a6-8a16-4436-ba51-2dd64e67aedd898ac73e-049c-4fda-a4a2-…firstTwoByTitlePagesresult: Number 160Expectations: 31 of 31 met
foundis COMPLETEDfoundCountis COMPLETEDfoundCount.resulttotalPagesis COMPLETEDtotalPages.resultlongis COMPLETEDlongCountis COMPLETEDlongCount.resultearliestLongYearis COMPLETEDearliestLongYear.resultbyYearis COMPLETEDearliestLongis COMPLETEDearliestLongPagesis COMPLETEDearliestLongPages.resultshortis COMPLETEDshortPagesis COMPLETEDshortPages.resulthugeis COMPLETEDhuge.matchnot producedwhenHugeis SKIPPEDfirstTwoByTitleis COMPLETEDfirstTwoByTitlePagesis COMPLETEDfirstTwoByTitlePages.resultfoundCounttotalPageslongCountearliestLongYearearliestLongPagesshortPagesfirstTwoByTitlePagesExpectations: 31 of 31 met
forEach run report
Flow scenario: forEach
Runs steps once per item in parallel, with one item feeding two steps and a step that only some items run, collects the results in item order, and completes a forEach over an empty list with nothing collected.
Local stack at
b212d219fd, started through Temporal. Run tagbeb6ed95-2b01-4e19-8b41-0395b5fb4375.Run 1 of 1: forEach run
b7750508-4020-4668-abe1-a870d75032b9: COMPLETEDpassed~0true: Number 72passed~1false: Number 8passed~2true: Number 99passed~3false: Number 30keepPassing~0items: 1 × Number [72]keepPassing~1keepPassing~2items: 1 × Number [99]keepPassing~3wrap~0items: 1 × Number [72]wrap~1items: 1 × Number [8]wrap~2items: 1 × Number [99]wrap~3items: 1 × Number [30]totalresult: Number 209hugematching: 0 × Number []nonMatching: 4 × Number [72,8,99,30]wrapHuge~<index>hugeCountresult: Number 0Expectations: 38 of 38 met
passed~0is COMPLETEDpassed~0.truepassed~0.falsenot producedpassed~1is COMPLETEDpassed~1.falsepassed~1.truenot producedpassed~2is COMPLETEDpassed~2.truepassed~2.falsenot producedpassed~3is COMPLETEDpassed~3.falsepassed~3.truenot producedkeepPassing~0is COMPLETEDkeepPassing~0.itemskeepPassing~1is SKIPPEDkeepPassing~2is COMPLETEDkeepPassing~2.itemskeepPassing~3is SKIPPEDwrap~0is COMPLETEDwrap~0.itemswrap~1is COMPLETEDwrap~1.itemswrap~2is COMPLETEDwrap~2.itemswrap~3is COMPLETEDwrap~3.itemstotalis COMPLETEDtotal.resulthugeis COMPLETEDhuge.matchinghuge.nonMatchinghugeCountis COMPLETEDhugeCount.resultcollectedtotalcollectedFromNonehugeCountExpectations: 38 of 38 met