Insights route→loader map (which workflow fills the grid, per form)¶
Status: VERIFIED in the Dev app (2026-06-05). The model below was confirmed end-to-end by building and importing packages and watching the panel in Aareon Mobile. First proof point: Unvented Hot Water Storage v9 is Active in Dev with the insights panel populating from the Repair Works Order. Read insights-piece.md for anatomy and insights-rollout-plan.md for the recipes.
The model (confirmed)¶
A form's insights grid populates only if the task the form runs in has its
GenBPInsight group filled (via $QL_Property_Insights$ / [Versaa].[usp_all_insights],
keyed on GenBP_Key_PropertyId). There are three ways that happens — the third was
discovered during in-app testing and is the most important correction:
| Pattern | How the group gets filled | Recipe for the form |
|---|---|---|
| Loader-route | the launch/load workflow runs the insight query into the task | display + switch (data already there) |
| Inherited (sub-task of a loaded master) | the form runs inside a parent task (e.g. an RWO) whose loader already filled GenBPInsight; the sub-task shares/inherits that group |
display + switch ONLY — do NOT add a self-loader |
| Self-trigger | the form fires *.AppendPropertyInsights itself (a RequestPropertyInsights request + an autoSend RequestButtonElement) |
display + switch + self-loader |
⚠️ The duplication rule (learned the hard way)¶
The Append Property Insights handler appends rows; it does not replace. So if a task
receives insights from two sources, you get duplicate rows. This is exactly what
happened on the Unvented Hot Water Storage pilot: it is a sub-task opened inside the
Repair Works Order task (note the form header still reads "Repair Works Order"), the RWO
already loaded insights, and adding the self-loader appended a second copy. Neither
autoSendOnceOnly=True nor hiding the trigger button fixed it, because the two copies came
from two different sources. Fix: for inherited sub-tasks, ship display-only (no loader).
So the decisive question per form is not "which loader" but: does the task this form runs in already have insights? If yes → display-only. If no → add the self-loader.
Loader inventory — workflows that DO load insights (XML-confirmed)¶
Each runs a GetTableDataWorkflowStep with queryData="$QL_Property_Insights$" into
GenBPInsight:
| Loader workflow | Launch route it serves |
|---|---|
Property+Search_57 |
generic Property Search launches (gated by $Insights_OnSwitch$ == true) |
FRA+Property+Search_20 / _23 |
FRA property search |
Repair+Works+Order+QL+Data_16 |
the RWO master task's data load — feeds its sub-tasks (UvHWS, NIBE, Damp & Mould) by inheritance |
ClientVisitBasicLoad_13 / _17 |
the Client Visit master task's data load |
Estate+Search_40 |
estate search (explicitly maps Tap Flushing Check) |
Order+Appointment_9 |
appointment-ordered tasks ("Get Insight Data" step) |
Append+Property+Insights_15 |
the reusable handler — message-start *.AppendPropertyInsights, needs only GenBP_Key_PropertyId. Target of the self-trigger. |
Launchers that do NOT load insights: Create+Jobs_3 (creates Void Survey, Void Post
Inspection, Repair Post Inspection), Property+Check+Appoint+LoadDat_30 (PCA data load —
PCA itself does not push insights; the appointment path does via Order+Appointment_9).
Worklist — category per form (corrected after testing)¶
| Form | Dev v | Runs in / launched by | Task already has insights? | Recipe | Status |
|---|---|---|---|---|---|
| Unvented Hot Water Storage | 9 (Active, Dev) | sub-task inside RWO | Yes (inherits) | display + switch only | ✅ verified in app 2026-06-05 |
| NIBE | 4 | sub-task inside RWO | Yes (inherits) | display + switch only | to build (same as UvHWS) |
| Damp & Mould Inspection | 60 | sub-task inside RWO | Yes (inherits) | display + switch only | to build (same as UvHWS) |
| Void Survey | 30 | Create Jobs (own task, no insight loader) | No | display + switch + self-loader | to build/verify (confirm property id present) |
| Tap Flushing Check | 40 | Estate Search (loads insights) | likely yes | display + switch (verify) | later |
| Succession Inspection | 4 | separate task from Client Visit | unknown — verify | likely self-loader | later |
| Relinquishment Inspection | 4 | separate task from Client Visit, no property context | n/a | C — skip / standalone Insights | later |
| Mobility Scooter Assessment | 6 | separate task from Client Visit (11 uses/5 yrs) | n/a | C — skip (negligible) | Peter: "probably not" |
| Complaint | 13 | QL worktray (own task) | verify property context | self-loader or C | later |
| EAI ×5 | — | Estate process | Estate Search loads insights — verify | maybe display-only; else C | later |
Corrections this testing made to the earlier (XML-only) prediction¶
- RWO sub-tasks (UvHWS, NIBE, Damp & Mould) are NOT "Category B data-push". They run inside the RWO task and inherit its insights → display-only. The earlier map predicted they'd need a master→sub-task push or a self-loader; in-app testing showed the data is already there and a self-loader duplicates it.
- The injector was missing the on-screen Show/Hide switch. The toggle data item
z_Insights_Switchwas added but no display control, so the panel showed unconditionally with no toggle. Fixed by addingswitch_control.frag(anOptionsListRadioButtonElement). - The insights grid must have
showAdd=False(no Add button — users can't add insight rows) andshowEdit=True(users can tap a row to view detail). Per Mark in the catch-up: "we don't need the show ad… not going to be adding anything to it" and "they want to edit because it allows them to go into it and have a look inside." - Management Studio assigns its own sequential version on import — the manifest version
number in the
.ftpackageis cosmetic; MS takes the next number. (Five pilot imports of a "v5" package became Dev versions 5→9.)
Build recipe (what goes in each package)¶
Built with versaa-rag/insights_injector/ against a fresh Dev pull:
- Inheriting forms (RWO sub-tasks):
inject.py "<Form>_<v>"(no flag) → display group + grid (showAdd=False,showEdit=True) +z_Insights*toggle items + switch control. - Non-inheriting forms (e.g. Void Survey):
inject.py "<Form>_<v>" --with-trigger→ all of the above plus theRequestPropertyInsightsrequest + anautoSendRequestButtonElement. (The auto-fire must be configured like Mark's Asbestos Data button — fire once, self-hide after load — to avoid the append-duplicate trap; settle this in-app for Void Survey.) - Wrap with
build_package.py; import to Dev as a new version; test in app; then activate and migrate Dev→Test→Live.
Reference DONE forms (for templates)¶
| Form | Populates via |
|---|---|
| Repair Works Order v74 | RWO QL Data loader — the master feeding UvHWS / NIBE / Damp & Mould |
| Routine Tenancy Visit | Property Search loader (canonical source of the display fragments) |
| Family Survey 2 MW v73/74 | the form-side AppendPropertyInsights self-trigger pattern |
| Asbestos Data v42 | the autoSend (fire-on-open, self-hiding) button pattern |
Related¶
- forms/insights-rollout-plan.md — recipes, worklist, sequence
- forms/insights-piece.md — anatomy, data-load gate, the switch + grid settings
- deployment/dev-to-live.md — migration + version comments