flowengine-cli 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -2,9 +2,37 @@
2
2
 
3
3
  [![RSpec](https://github.com/kigster/flowengine-cli/actions/workflows/rspec.yml/badge.svg)](https://github.com/kigster/flowengine-cli/actions/workflows/rspec.yml) [![RuboCop](https://github.com/kigster/flowengine-cli/actions/workflows/rubocop.yml/badge.svg)](https://github.com/kigster/flowengine-cli/actions/workflows/rubocop.yml)
4
4
 
5
- Terminal-based interactive wizard runner for [FlowEngine](https://github.com/kigster/flowengine) flows. Define your flow once, run it in the terminal with rich TTY prompts, export Mermaid diagrams, and validate flow definitions -- all from the command line.
5
+ FlowEngine CLI is a UI adapter that sits on top of the pure-Ruby `flowengine` core gem. The core gem knows nothing about terminals, databases, or web frameworks.
6
6
 
7
- FlowEngine CLI is a UI adapter that sits on top of the pure-Ruby `flowengine` core gem. The core gem knows nothing about terminals, databases, or web frameworks. This gem provides the terminal interface.
7
+ > [!IMPORTANT]
8
+ > This gem provides the ANSI terminal CLI interface to data collection defined by [`flowengine`](https://rubygems.org/gems/flowengine)'s DSL flows.
9
+
10
+ The gem `flowengine` allows you to define complex flows that are meant to be the basis of multi-question wizards with arbitrary branching logic, and support for LLMs to shorten the wizard if the user describe their parameters in free form text. LLM then attempts to extract the structured information from that text, assigning answers to some of the questions in the flow. This allows the engine to skip some of the questions and arrive to the data completion much faster.
11
+
12
+ > [!IMPORTANT]
13
+ > At the moment the output of the data collection process it a multi-level JSON file. It is up to you to render it in a more user friendly way, or show it to the user as is, or save it to the database as the JSONB record.
14
+
15
+ This gem — `flowengine-cli`, as we mentioned, — is an adapter, a wrapper so to speak, around the `flowengine`, which adds the ANSI terminal support, prompts and CLI UI based on some of the gems from the [TTY Toolkit](https://ttytoolkit.org/).
16
+
17
+ The CLI gem allows you to:
18
+
19
+ * Run the CLI in the terminal with the rich TTY prompts, and upon user answering the questions save the ansnwers to a JSOM file.
20
+
21
+ * Export the logic of the DSL questions into a flow-chart as a Mermaid diagram
22
+
23
+ * Validate the flow definitions DSL.
24
+
25
+ There are multiple examples of the DSL in the `examples` folder.
26
+
27
+ Run it like so:
28
+
29
+ ```bash
30
+ flow run \
31
+ --output answers.json \
32
+ examples/07_loan_application.rb
33
+ ```
34
+
35
+ ---
8
36
 
9
37
  ## Installation
10
38
 
@@ -20,10 +48,23 @@ Or install directly:
20
48
  gem install flowengine-cli
21
49
  ```
22
50
 
51
+ > [!IMPORTANT]
52
+ > This installs two executables: `flowengine-cli` (for consistency) and also `flow` which is much easier to type.
53
+ >
54
+ > ```bash
55
+ > $ flow --help
56
+ > Commands:
57
+ > flow graph FLOW_FILE # Export a flow definition as a Mermaid diagram
58
+ > flow run FLOW_FILE # Run a flow definition interactively
59
+ > flow validate FLOW_FILE # Validate a flow definition file
60
+ > flow version # Print version information
61
+ > ```
62
+
63
+
23
64
  ### Requirements
24
65
 
25
66
  - Ruby >= 4.0.1
26
- - [flowengine](https://github.com/kigster/flowengine) ~> 0.1
67
+ - [flowengine](https://github.com1/kigster/flowengine) ~> 0.1
27
68
 
28
69
  ## Quick Start
29
70
 
@@ -31,6 +72,9 @@ gem install flowengine-cli
31
72
 
32
73
  Create a file called `intake.rb`:
33
74
 
75
+ > [!NOTE]
76
+ > We'll use examples from the tax information collection that a professional preparer might want to collect before speaking with their customer, and save a chunk of time asking basic questions that would already be answered if their customer went through this intake process.
77
+
34
78
  ```ruby
35
79
  FlowEngine.define do
36
80
  start :filing_status
@@ -70,21 +114,7 @@ end
70
114
  flowengine-cli run intake.rb
71
115
  ```
72
116
 
73
- The CLI walks you through each step interactively, rendering the appropriate TTY prompt for each step type. When complete, it outputs the collected answers as JSON:
74
-
75
- ```json
76
- {
77
- "flow_file": "intake.rb",
78
- "path_taken": ["filing_status", "income_types", "business_details", "summary"],
79
- "answers": {
80
- "filing_status": "Married",
81
- "income_types": ["W2", "Business"],
82
- "business_details": { "LLC": 2, "SCorp": 1, "CCorp": 0 }
83
- },
84
- "steps_completed": 4,
85
- "completed_at": "2026-02-26T20:15:00-08:00"
86
- }
87
- ```
117
+ The CLI walks you through each step interactively, rendering the appropriate TTY prompt for each step type. When complete, it outputs the collected answers as JSON.
88
118
 
89
119
  ### 3. Save results to a file
90
120
 
@@ -116,18 +146,18 @@ Loads a flow definition, presents each step as an interactive terminal prompt, a
116
146
 
117
147
  ```
118
148
  ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
119
- ┃ FlowEngine Interactive Wizard
149
+ ┃ FlowEngine Interactive Wizard
120
150
  ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
121
151
 
122
152
  Step 1: filing_status
123
- ────────────────────────────────────
153
+ ────────────────────────────────────────
124
154
  What is your filing status? (Use ↑/↓ arrow keys, press Enter to select)
125
155
  > Single
126
156
  Married
127
157
  HeadOfHousehold
128
158
 
129
159
  Step 2: income_types
130
- ────────────────────────────────────
160
+ ────────────────────────────────────────
131
161
  Select all income types that apply: (Use ↑/↓ arrow keys, press Space to select)
132
162
  ◯ W2
133
163
  > ◉ 1099
@@ -136,19 +166,43 @@ Loads a flow definition, presents each step as an interactive terminal prompt, a
136
166
  ◯ Rental
137
167
 
138
168
  Step 3: business_details
139
- ────────────────────────────────────
169
+ ────────────────────────────────────────
140
170
  How many of each business type?
141
171
 
142
172
  LLC: 2
143
173
  SCorp: 1
144
174
  CCorp: 0
145
175
 
176
+ Step 4: summary
177
+ ────────────────────────────────────────
178
+
179
+ Thank you for completing the intake!
180
+ Press any key to continue...
181
+
146
182
  ┌ SUCCESS ─────────────────────────────────────────────────────────┐
147
183
  │ Flow completed! │
148
184
  └──────────────────────────────────────────────────────────────────┘
149
- { ... JSON output ... }
150
185
  ```
151
186
 
187
+ Then the JSON output is printed to stdout (and optionally saved to a file):
188
+
189
+ ```json
190
+ {
191
+ "flow_file": "intake.rb",
192
+ "path_taken": ["filing_status", "income_types", "business_details", "summary"],
193
+ "answers": {
194
+ "filing_status": "Single",
195
+ "income_types": ["1099", "Business"],
196
+ "business_details": { "LLC": 2, "SCorp": 1, "CCorp": 0 },
197
+ "summary": null
198
+ },
199
+ "steps_completed": 4,
200
+ "completed_at": "2026-02-26T20:15:00-08:00"
201
+ }
202
+ ```
203
+
204
+ > **Note:** Display steps (like `summary`) record `null` in the answers since they are informational only.
205
+
152
206
  ---
153
207
 
154
208
  ### `graph` -- Export Mermaid Diagram
@@ -189,6 +243,7 @@ Save to a file and render with any Mermaid-compatible tool (GitHub, VS Code, mer
189
243
 
190
244
  ```bash
191
245
  flowengine-cli graph intake.rb -o flow.mmd
246
+ # => Diagram written to flow.mmd
192
247
  ```
193
248
 
194
249
  ---
@@ -301,12 +356,15 @@ transition to: :special_path,
301
356
  )
302
357
  ```
303
358
 
304
- ## Full Example: Tax Intake Flow
359
+ ## In-Depth Walkthrough: Tax Intake
360
+
361
+ This section walks through a realistic 17-step tax preparation intake flow, showing four different user journeys through the same flow definition. Each scenario demonstrates different branching paths, and the resulting collected data.
362
+
363
+ ### The Flow Definition
305
364
 
306
- Here is a realistic 17-step tax preparation intake flow demonstrating conditional branching, composite rules, and multiple paths:
365
+ Save this as `tax_intake.rb`:
307
366
 
308
367
  ```ruby
309
- # tax_intake.rb
310
368
  FlowEngine.define do
311
369
  start :filing_status
312
370
 
@@ -427,25 +485,570 @@ FlowEngine.define do
427
485
  end
428
486
 
429
487
  step :review do
488
+ type :display
489
+ question "Thank you! Your intake is complete. We will be in touch shortly."
490
+ end
491
+ end
492
+ ```
493
+
494
+ Now let's see how four different users travel through this flow, and what the collected data looks like for each.
495
+
496
+ ---
497
+
498
+ ### Scenario 1: Simple W2 Filer
499
+
500
+ A single person with only W2 income, no investments, no businesses -- the simplest path.
501
+
502
+ **Terminal session:**
503
+
504
+ ```
505
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
506
+ ┃ FlowEngine Interactive Wizard ┃
507
+ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
508
+
509
+ Step 1: filing_status
510
+ ────────────────────────────────────────
511
+ What is your filing status for 2025?
512
+ > single
513
+ married_filing_jointly
514
+ married_filing_separately
515
+ head_of_household
516
+
517
+ Step 2: dependents
518
+ ────────────────────────────────────────
519
+ How many dependents do you have? 0
520
+
521
+ Step 3: income_types
522
+ ────────────────────────────────────────
523
+ Select all income types that apply to you in 2025.
524
+ > ◉ W2
525
+ ◯ 1099
526
+ ◯ Business
527
+ ◯ Investment
528
+ ◯ Rental
529
+ ◯ Retirement
530
+
531
+ Step 4: state_filing
532
+ ────────────────────────────────────────
533
+ Which states do you need to file in?
534
+ > ◉ California
535
+ ◯ NewYork
536
+ ◯ Texas
537
+ ◯ Florida
538
+ ◯ Illinois
539
+ ◯ Other
540
+
541
+ Step 5: foreign_accounts
542
+ ────────────────────────────────────────
543
+ Do you have any foreign financial accounts?
544
+ yes
545
+ > no
546
+
547
+ Step 6: deduction_types
548
+ ────────────────────────────────────────
549
+ Which additional deductions apply to you?
550
+ ◯ Medical
551
+ ◯ Charitable
552
+ ◯ Education
553
+ ◯ Mortgage
554
+ > ◉ None
555
+
556
+ Step 7: contact_info
557
+ ────────────────────────────────────────
558
+ Please provide your contact information (name, email, phone).
559
+ Jane Smith, jane@example.com, 415-555-1234
560
+
561
+ Step 8: review
562
+ ────────────────────────────────────────
563
+
564
+ Thank you! Your intake is complete. We will be in touch shortly.
565
+ Press any key to continue...
566
+
567
+ ┌ SUCCESS ─────────────────────────────────────────────────────────┐
568
+ │ Flow completed! │
569
+ └──────────────────────────────────────────────────────────────────┘
570
+ ```
571
+
572
+ **Collected data (`-o simple_w2.json`):**
573
+
574
+ ```json
575
+ {
576
+ "flow_file": "tax_intake.rb",
577
+ "path_taken": [
578
+ "filing_status",
579
+ "dependents",
580
+ "income_types",
581
+ "state_filing",
582
+ "foreign_accounts",
583
+ "deduction_types",
584
+ "contact_info",
585
+ "review"
586
+ ],
587
+ "answers": {
588
+ "filing_status": "single",
589
+ "dependents": 0,
590
+ "income_types": ["W2"],
591
+ "state_filing": ["California"],
592
+ "foreign_accounts": "no",
593
+ "deduction_types": ["None"],
594
+ "contact_info": "Jane Smith, jane@example.com, 415-555-1234",
595
+ "review": null
596
+ },
597
+ "steps_completed": 8,
598
+ "completed_at": "2026-02-26T14:30:00-08:00"
599
+ }
600
+ ```
601
+
602
+ **Steps skipped:** `business_count`, `complex_business_info`, `business_details`, `investment_details`, `crypto_details`, `rental_details`, `foreign_account_details`, `charitable_amount`, `charitable_documentation` -- 9 of 17 steps skipped because the user's answers didn't trigger those branches.
603
+
604
+ ---
605
+
606
+ ### Scenario 2: Business Owner with Crypto
607
+
608
+ A single person who owns 1 business and has crypto investments.
609
+
610
+ **Terminal session:**
611
+
612
+ ```
613
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
614
+ ┃ FlowEngine Interactive Wizard ┃
615
+ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
616
+
617
+ Step 1: filing_status
618
+ ────────────────────────────────────────
619
+ What is your filing status for 2025?
620
+ > single
621
+
622
+ Step 2: dependents
623
+ ────────────────────────────────────────
624
+ How many dependents do you have? 0
625
+
626
+ Step 3: income_types
627
+ ────────────────────────────────────────
628
+ Select all income types that apply to you in 2025.
629
+ ◉ W2
630
+ ◯ 1099
631
+ > ◉ Business
632
+ ◉ Investment
633
+ ◯ Rental
634
+ ◯ Retirement
635
+
636
+ Step 4: business_count
637
+ ────────────────────────────────────────
638
+ How many total businesses do you own or are a partner in? 1
639
+
640
+ Step 5: business_details
641
+ ────────────────────────────────────────
642
+ How many of each business type do you own?
643
+
644
+ RealEstate: 0
645
+ SCorp: 0
646
+ CCorp: 0
647
+ Trust: 0
648
+ LLC: 1
649
+
650
+ Step 6: investment_details
651
+ ────────────────────────────────────────
652
+ What types of investments do you hold?
653
+ ◉ Stocks
654
+ ◯ Bonds
655
+ > ◉ Crypto
656
+ ◯ RealEstate
657
+ ◯ MutualFunds
658
+
659
+ Step 7: crypto_details
660
+ ────────────────────────────────────────
661
+ Describe your cryptocurrency transactions (exchanges, approximate transaction count).
662
+ Coinbase and Kraken, approximately 150 trades in 2025
663
+
664
+ Step 8: state_filing
665
+ ────────────────────────────────────────
666
+ Which states do you need to file in?
667
+ > ◉ California
668
+ ◯ NewYork
669
+ ◯ Texas
670
+ ◯ Florida
671
+ ◯ Illinois
672
+ ◯ Other
673
+
674
+ Step 9: foreign_accounts
675
+ ────────────────────────────────────────
676
+ Do you have any foreign financial accounts?
677
+ yes
678
+ > no
679
+
680
+ Step 10: deduction_types
681
+ ────────────────────────────────────────
682
+ Which additional deductions apply to you?
683
+ ◯ Medical
684
+ ◯ Charitable
685
+ ◯ Education
686
+ ◯ Mortgage
687
+ > ◉ None
688
+
689
+ Step 11: contact_info
690
+ ────────────────────────────────────────
691
+ Please provide your contact information (name, email, phone).
692
+ Alex Rivera, alex@startup.io, 510-555-9876
693
+
694
+ Step 12: review
695
+ ────────────────────────────────────────
696
+
697
+ Thank you! Your intake is complete. We will be in touch shortly.
698
+ Press any key to continue...
699
+
700
+ ┌ SUCCESS ─────────────────────────────────────────────────────────┐
701
+ │ Flow completed! │
702
+ └──────────────────────────────────────────────────────────────────┘
703
+ ```
704
+
705
+ **Collected data (`-o business_crypto.json`):**
706
+
707
+ ```json
708
+ {
709
+ "flow_file": "tax_intake.rb",
710
+ "path_taken": [
711
+ "filing_status",
712
+ "dependents",
713
+ "income_types",
714
+ "business_count",
715
+ "business_details",
716
+ "investment_details",
717
+ "crypto_details",
718
+ "state_filing",
719
+ "foreign_accounts",
720
+ "deduction_types",
721
+ "contact_info",
722
+ "review"
723
+ ],
724
+ "answers": {
725
+ "filing_status": "single",
726
+ "dependents": 0,
727
+ "income_types": ["W2", "Business", "Investment"],
728
+ "business_count": 1,
729
+ "business_details": {
730
+ "RealEstate": 0,
731
+ "SCorp": 0,
732
+ "CCorp": 0,
733
+ "Trust": 0,
734
+ "LLC": 1
735
+ },
736
+ "investment_details": ["Stocks", "Crypto"],
737
+ "crypto_details": "Coinbase and Kraken, approximately 150 trades in 2025",
738
+ "state_filing": ["California"],
739
+ "foreign_accounts": "no",
740
+ "deduction_types": ["None"],
741
+ "contact_info": "Alex Rivera, alex@startup.io, 510-555-9876",
742
+ "review": null
743
+ },
744
+ "steps_completed": 12,
745
+ "completed_at": "2026-02-26T15:45:00-08:00"
746
+ }
747
+ ```
748
+
749
+ Notice how selecting "Business" at `income_types` triggered the `business_count` -> `business_details` branch, and selecting "Investment" continued the flow into `investment_details`. Since the user selected "Crypto" there, the `crypto_details` step was reached. The engine evaluated transitions top-to-bottom, taking the first match.
750
+
751
+ ---
752
+
753
+ ### Scenario 3: Married Investor with Rentals and Foreign Accounts
754
+
755
+ A married person filing jointly, with investments, rental properties, and foreign bank accounts.
756
+
757
+ **Collected data (`-o married_investor.json`):**
758
+
759
+ ```json
760
+ {
761
+ "flow_file": "tax_intake.rb",
762
+ "path_taken": [
763
+ "filing_status",
764
+ "dependents",
765
+ "income_types",
766
+ "investment_details",
767
+ "rental_details",
768
+ "state_filing",
769
+ "foreign_accounts",
770
+ "foreign_account_details",
771
+ "deduction_types",
772
+ "charitable_amount",
773
+ "contact_info",
774
+ "review"
775
+ ],
776
+ "answers": {
777
+ "filing_status": "married_filing_jointly",
778
+ "dependents": 2,
779
+ "income_types": ["W2", "Investment", "Rental"],
780
+ "investment_details": ["Stocks", "Bonds", "MutualFunds"],
781
+ "rental_details": {
782
+ "Residential": 2,
783
+ "Commercial": 0,
784
+ "Vacation": 1
785
+ },
786
+ "state_filing": ["California", "NewYork"],
787
+ "foreign_accounts": "yes",
788
+ "foreign_account_details": 3,
789
+ "deduction_types": ["Medical", "Charitable", "Mortgage"],
790
+ "charitable_amount": 3500,
791
+ "contact_info": "Maria & Carlos Reyes, reyes@email.com, 212-555-4567",
792
+ "review": null
793
+ },
794
+ "steps_completed": 12,
795
+ "completed_at": "2026-02-26T16:20:00-08:00"
796
+ }
797
+ ```
798
+
799
+ Key branching decisions in this path:
800
+
801
+ 1. **`income_types`** -- No "Business" was selected, so `business_count`/`business_details` were skipped entirely. "Investment" was the first matching rule, so the flow went to `investment_details`.
802
+ 2. **`investment_details`** -- No "Crypto", but "Rental" was in `income_types`, so the flow continued to `rental_details`.
803
+ 3. **`foreign_accounts`** -- User answered "yes", triggering the `foreign_account_details` step.
804
+ 4. **`deduction_types`** -- "Charitable" was selected, activating the `charitable_amount` step. But the amount (3,500) was not greater than 5,000, so `charitable_documentation` was skipped.
805
+
806
+ ---
807
+
808
+ ### Scenario 4: Complex Multi-Business Filer with Charitable Donations
809
+
810
+ A head of household with 4 businesses, investments, rentals, foreign accounts, and over $5,000 in charitable giving -- the longest possible path through the flow.
811
+
812
+ **Collected data (`-o complex_filer.json`):**
813
+
814
+ ```json
815
+ {
816
+ "flow_file": "tax_intake.rb",
817
+ "path_taken": [
818
+ "filing_status",
819
+ "dependents",
820
+ "income_types",
821
+ "business_count",
822
+ "complex_business_info",
823
+ "business_details",
824
+ "investment_details",
825
+ "crypto_details",
826
+ "rental_details",
827
+ "state_filing",
828
+ "foreign_accounts",
829
+ "foreign_account_details",
830
+ "deduction_types",
831
+ "charitable_amount",
832
+ "charitable_documentation",
833
+ "contact_info",
834
+ "review"
835
+ ],
836
+ "answers": {
837
+ "filing_status": "head_of_household",
838
+ "dependents": 3,
839
+ "income_types": ["W2", "1099", "Business", "Investment", "Rental", "Retirement"],
840
+ "business_count": 4,
841
+ "complex_business_info": "Primary EIN: 12-3456789. Two LLCs (consulting, real estate), one S-Corp (software), one C-Corp (manufacturing)",
842
+ "business_details": {
843
+ "RealEstate": 1,
844
+ "SCorp": 1,
845
+ "CCorp": 1,
846
+ "Trust": 0,
847
+ "LLC": 2
848
+ },
849
+ "investment_details": ["Stocks", "Bonds", "Crypto", "RealEstate", "MutualFunds"],
850
+ "crypto_details": "Binance and Coinbase, ~400 transactions. Includes DeFi staking and NFT sales.",
851
+ "rental_details": {
852
+ "Residential": 3,
853
+ "Commercial": 1,
854
+ "Vacation": 0
855
+ },
856
+ "state_filing": ["California", "Texas", "Florida"],
857
+ "foreign_accounts": "yes",
858
+ "foreign_account_details": 5,
859
+ "deduction_types": ["Medical", "Charitable", "Education", "Mortgage"],
860
+ "charitable_amount": 12000,
861
+ "charitable_documentation": "Red Cross $5,000; Habitat for Humanity $4,000; Local food bank $3,000",
862
+ "contact_info": "David Park, dpark@enterprise.com, 650-555-8901",
863
+ "review": null
864
+ },
865
+ "steps_completed": 17,
866
+ "completed_at": "2026-02-26T17:05:00-08:00"
867
+ }
868
+ ```
869
+
870
+ This user hit all 17 steps -- every branch was activated:
871
+
872
+ | Branch Trigger | Rule | Steps Activated |
873
+ |---|---|---|
874
+ | "Business" selected in `income_types` | `contains(:income_types, "Business")` | `business_count` |
875
+ | `business_count` > 2 | `greater_than(:business_count, 2)` | `complex_business_info` |
876
+ | "Investment" selected in `income_types` | `contains(:income_types, "Investment")` | `investment_details` |
877
+ | "Crypto" selected in `investment_details` | `contains(:investment_details, "Crypto")` | `crypto_details` |
878
+ | "Rental" selected in `income_types` | `contains(:income_types, "Rental")` | `rental_details` |
879
+ | "yes" for `foreign_accounts` | `equals(:foreign_accounts, "yes")` | `foreign_account_details` |
880
+ | "Charitable" selected in `deduction_types` | `contains(:deduction_types, "Charitable")` | `charitable_amount` |
881
+ | `charitable_amount` > 5000 | `greater_than(:charitable_amount, 5000)` | `charitable_documentation` |
882
+
883
+ ---
884
+
885
+ ### Comparing the Paths
886
+
887
+ | | Scenario 1 | Scenario 2 | Scenario 3 | Scenario 4 |
888
+ |---|---|---|---|---|
889
+ | **Persona** | Simple W2 | Business + Crypto | Married Investor | Complex Filer |
890
+ | **Steps completed** | 8 | 12 | 12 | 17 (all) |
891
+ | **Steps skipped** | 9 | 5 | 5 | 0 |
892
+ | **Business branch** | -- | Yes (1 biz) | -- | Yes (4 biz + complex) |
893
+ | **Investment branch** | -- | Yes | Yes | Yes |
894
+ | **Crypto sub-branch** | -- | Yes | -- | Yes |
895
+ | **Rental branch** | -- | -- | Yes | Yes |
896
+ | **Foreign accounts** | -- | -- | Yes | Yes |
897
+ | **Charitable branch** | -- | -- | Partial (< $5k) | Full (> $5k) |
898
+
899
+ ## In-Depth Walkthrough: Customer Onboarding
900
+
901
+ Tax intake isn't the only use case. Here is a customer onboarding flow showing different step types.
902
+
903
+ Save as `onboarding.rb`:
904
+
905
+ ```ruby
906
+ FlowEngine.define do
907
+ start :welcome
908
+
909
+ step :welcome do
910
+ type :display
911
+ question "Welcome to Acme Corp onboarding! We'll collect a few details to get you set up."
912
+ transition to: :account_type
913
+ end
914
+
915
+ step :account_type do
916
+ type :single_select
917
+ question "What type of account are you creating?"
918
+ options %w[Personal Business Enterprise]
919
+ transition to: :company_info, if_rule: any(
920
+ equals(:account_type, "Business"),
921
+ equals(:account_type, "Enterprise")
922
+ )
923
+ transition to: :personal_info
924
+ end
925
+
926
+ step :company_info do
927
+ type :text
928
+ question "What is your company name?"
929
+ transition to: :team_size
930
+ end
931
+
932
+ step :team_size do
933
+ type :number
934
+ question "How many team members will use the platform?"
935
+ transition to: :features
936
+ end
937
+
938
+ step :personal_info do
430
939
  type :text
431
- question "Thank you! Please review your information. Type 'confirm' to submit."
940
+ question "What is your full name?"
941
+ transition to: :features
942
+ end
943
+
944
+ step :features do
945
+ type :multi_select
946
+ question "Which features are you interested in?"
947
+ options %w[Analytics Reporting API Integrations Support]
948
+ transition to: :enterprise_sla, if_rule: all(
949
+ equals(:account_type, "Enterprise"),
950
+ contains(:features, "Support")
951
+ )
952
+ transition to: :confirm
953
+ end
954
+
955
+ step :enterprise_sla do
956
+ type :boolean
957
+ question "Do you require an SLA agreement?"
958
+ transition to: :confirm
959
+ end
960
+
961
+ step :confirm do
962
+ type :display
963
+ question "All set! Your account will be provisioned shortly."
432
964
  end
433
965
  end
434
966
  ```
435
967
 
436
- Run it:
968
+ **Run and save:**
437
969
 
438
970
  ```bash
439
- flowengine-cli run tax_intake.rb -o tax_results.json
971
+ flowengine-cli run onboarding.rb -o onboarding_result.json
972
+ ```
973
+
974
+ **Example: Enterprise user who wants Support + SLA:**
975
+
976
+ ```json
977
+ {
978
+ "flow_file": "onboarding.rb",
979
+ "path_taken": [
980
+ "welcome",
981
+ "account_type",
982
+ "company_info",
983
+ "team_size",
984
+ "features",
985
+ "enterprise_sla",
986
+ "confirm"
987
+ ],
988
+ "answers": {
989
+ "welcome": null,
990
+ "account_type": "Enterprise",
991
+ "company_info": "Globex Corporation",
992
+ "team_size": 50,
993
+ "features": ["Analytics", "API", "Support"],
994
+ "enterprise_sla": true,
995
+ "confirm": null
996
+ },
997
+ "steps_completed": 7,
998
+ "completed_at": "2026-02-26T18:00:00-08:00"
999
+ }
440
1000
  ```
441
1001
 
442
- Visualize it:
1002
+ **Example: Personal user:**
1003
+
1004
+ ```json
1005
+ {
1006
+ "flow_file": "onboarding.rb",
1007
+ "path_taken": [
1008
+ "welcome",
1009
+ "account_type",
1010
+ "personal_info",
1011
+ "features",
1012
+ "confirm"
1013
+ ],
1014
+ "answers": {
1015
+ "welcome": null,
1016
+ "account_type": "Personal",
1017
+ "personal_info": "Jordan Lee",
1018
+ "features": ["Analytics", "Reporting"],
1019
+ "confirm": null
1020
+ },
1021
+ "steps_completed": 5,
1022
+ "completed_at": "2026-02-26T18:05:00-08:00"
1023
+ }
1024
+ ```
1025
+
1026
+ The Personal user skipped `company_info`, `team_size`, and `enterprise_sla` entirely -- those steps were never reached because the transition rules didn't match.
1027
+
1028
+ ## Graph Visualization Examples
1029
+
1030
+ ### Validate, then visualize
1031
+
1032
+ A typical workflow is to validate first, then export the graph:
443
1033
 
444
1034
  ```bash
445
- flowengine-cli graph tax_intake.rb -o tax_flow.mmd
1035
+ $ flowengine-cli validate tax_intake.rb
1036
+ Flow definition is valid!
1037
+ Start step: filing_status
1038
+ Total steps: 17
1039
+ Steps: filing_status, dependents, income_types, business_count,
1040
+ complex_business_info, business_details, investment_details,
1041
+ crypto_details, rental_details, state_filing, foreign_accounts,
1042
+ foreign_account_details, deduction_types, charitable_amount,
1043
+ charitable_documentation, contact_info, review
1044
+
1045
+ $ flowengine-cli graph tax_intake.rb -o tax_flow.mmd
1046
+ Diagram written to tax_flow.mmd
446
1047
  ```
447
1048
 
448
- The Mermaid output renders as:
1049
+ ### Full Mermaid diagram for tax intake
1050
+
1051
+ The exported Mermaid diagram for the 17-step tax intake:
449
1052
 
450
1053
  ```mermaid
451
1054
  flowchart TD
@@ -493,9 +1096,11 @@ flowchart TD
493
1096
  charitable_documentation --> contact_info
494
1097
  contact_info["Please provide your contact information..."]
495
1098
  contact_info --> review
496
- review["Thank you! Please review your information."]
1099
+ review["Thank you! Your intake is complete."]
497
1100
  ```
498
1101
 
1102
+ Paste this into [mermaid.live](https://mermaid.live), a GitHub Markdown file, or any Mermaid-compatible renderer to see the flow as a visual graph.
1103
+
499
1104
  ## Architecture
500
1105
 
501
1106
  ```
@@ -528,6 +1133,43 @@ The core `flowengine` gem has **zero UI dependencies**. It provides the DSL, rul
528
1133
  3. **Drives** the engine loop until completion
529
1134
  4. **Outputs** results as structured JSON
530
1135
 
1136
+ ### JSON Output Structure
1137
+
1138
+ Every `run` command produces JSON with a consistent structure:
1139
+
1140
+ ```json
1141
+ {
1142
+ "flow_file": "path/to/flow.rb",
1143
+ "path_taken": ["step_a", "step_b", "step_c"],
1144
+ "answers": {
1145
+ "step_a": "<value depends on step type>",
1146
+ "step_b": "<value depends on step type>"
1147
+ },
1148
+ "steps_completed": 3,
1149
+ "completed_at": "2026-02-26T20:15:00-08:00"
1150
+ }
1151
+ ```
1152
+
1153
+ | Field | Type | Description |
1154
+ |-------|------|-------------|
1155
+ | `flow_file` | `String` | The flow definition file that was executed |
1156
+ | `path_taken` | `Array<String>` | Ordered list of step IDs the user visited |
1157
+ | `answers` | `Hash` | Map of step ID to the user's answer (type varies by step) |
1158
+ | `steps_completed` | `Integer` | Total number of steps the user went through |
1159
+ | `completed_at` | `String` | ISO 8601 timestamp of when the flow finished |
1160
+
1161
+ **Answer types by step:**
1162
+
1163
+ | Step Type | Answer Type | Example |
1164
+ |-----------|-------------|---------|
1165
+ | `:single_select` | `String` | `"Married"` |
1166
+ | `:multi_select` | `Array<String>` | `["W2", "Business"]` |
1167
+ | `:number_matrix` | `Hash<String, Integer>` | `{"LLC": 2, "SCorp": 1}` |
1168
+ | `:text` | `String` | `"Jane Smith, jane@example.com"` |
1169
+ | `:number` | `Integer` | `42` |
1170
+ | `:boolean` | `Boolean` | `true` |
1171
+ | `:display` | `null` | `null` |
1172
+
531
1173
  ## Development
532
1174
 
533
1175
  ```bash