Green · worked reach study
Choose notification channels for maximum reach.
This tutorial exposes the full TURF contract: what each option means, who answers, the exact binary questions, the respondent-by-item incidence matrix, every candidate combination, and the tie-breaking rule.
1. State what “reach” means
green init --type turf \
--description "Channels customers would accept for time-sensitive subscription delivery updates"
green next
A respondent is reached by a portfolio when they select at least one item in it. Here an item is a notification channel, and “selected” means the customer says that channel would appeal to them for these updates.
2. Define respondent-facing option labels
green item add channels email sms push in_app \
--label email="Email delivery updates" \
--label sms="SMS text delivery updates" \
--label push="Mobile push notifications" \
--label in_app="In-app delivery inbox"
green item list channels
green validate
Show identity versus display
stable item_id respondent-facing label
email Email delivery updates
sms SMS text delivery updates
push Mobile push notifications
in_app In-app delivery inboxStable IDs drive imported rows and portfolio sets. Labels define what respondents see. The project description supplies the common use case, so “email” is never fielded without context.
3. Define respondents—there is no implicit panel
green agent-list create panel
green agent add panel --id mobile_first \
--persona "Mobile-first customer who keeps push notifications enabled" \
--trait primary_device=phone
green agent add panel --id inbox_manager \
--persona "Customer who organizes purchases and receipts through email" \
--trait email_use=high
green agent add panel --id privacy_cautious \
--persona "Privacy-conscious customer who limits lock-screen notifications" \
--trait notification_tolerance=low
green agent add panel --id text_reliant \
--persona "Customer who relies on text messages for urgent logistics" \
--trait sms_use=high
green agent-list show panel
These four records become four EDSL agents exactly as written. They demonstrate package construction; they do not constitute a representative customer sample.
4. Build and inspect the binary Survey
green field build --job-name reach --agent-list panel
ep inspect jobs.ep
ep inspect agent_list.ep
ep surveys questions survey.ep
Show actual question structure
turf_email · multiple_choice
Study context: Channels customers would accept for time-sensitive
subscription delivery updates
Option: Email delivery updates
Would this option appeal to you?
Options: Yes, No
turf_in_app … Option: In-app delivery inbox
turf_push … Option: Mobile push notifications
turf_sms … Option: SMS text delivery updatesquestion-map.json maps each question back to its item ID. Four options create four calls per model respondent.
5. Review, then choose administration
ep jobs cost jobs.ep --model gpt-5.4-mini
green plan field --job-name reach
Show fielding arithmetic
4 agents × 4 binary questions = 16 external model calls
requires approval: true
expected output: results.ep# Model path—only after explicit approval
ep run jobs.ep --model gpt-5.4-mini --output results.ep
# Human path
ep humanize preview --survey survey.ep
ep humanize create --survey survey.ep \
--schema humanize-schema.json --name "Delivery update channels"
6. Normalize to respondent-item incidence
green data import-edsl results.ep \
--job-name reach --name field_run_1
green data quality field_run_1
Show normalized rows
respondent_id,item_id,selected
mobile_first,email,true
mobile_first,sms,false
mobile_first,push,true
mobile_first,in_app,falseOne row is one respondent-item decision. TURF does not use how many selected items a person has as reach; it uses whether a portfolio contains at least one of them.
7. Reproduce the checked-in fixture
green data import-turf examples/turf/responses.csv --name channel_use
green data quality channel_use
green report turf channel_use --max-items 2
Show the binary incidence matrix
respondent email sms push in_app
r1 1 0 1 0
r2 1 1 0 0
r3 0 1 1 0
r4 0 0 1 1
r5 1 0 0 1
r6 0 1 0 1The six-respondent fixture reproduces analysis locally. It is not output from the four illustrative agents and is not a population estimate.
8. See the set calculation
Reached(S) = union of respondents selecting any item in set S
Reach rate = |Reached(S)| / number of respondents
Show all one- and two-item outcomes
portfolio reached reach rate
email 3 50.0%
sms 3 50.0%
push 3 50.0%
in_app 3 50.0%
email + in_app 5 83.3%
email + push 5 83.3%
email + sms 5 83.3%
in_app + push 5 83.3%
in_app + sms 5 83.3%
push + sms 5 83.3%Every pair ties in this deliberately symmetric fixture. Green sorts by reach, then smaller set size, then item IDs; therefore email + in_app is the deterministic first row, not a uniquely superior portfolio. The other ties remain in solutions.
9. Understand the search boundary
--max-items 2 enumerates every nonempty combination of size one or two. With four items that is 4 + 6 = 10 portfolios. Larger candidate sets grow combinatorially, and Green currently returns the first 25 sorted solutions in the report payload.
number of evaluated sets through size k
= C(n,1) + C(n,2) + … + C(n,k)
10. Save the decision artifact
green report save --name channel_portfolio \
--kind turf --input channel_use --max-items 2
green report list
green validate --require-report turf
Show saved interpretation
best returned set email + in_app
people reached 5 of 6
reach rate 83.3%
equally reaching two-item alternatives 5The saved JSON retains all returned solutions and provenance. A deployment decision should also consider channel cost, fatigue, deliverability, and legal constraints; unweighted TURF optimizes reach alone.