@ai-matrx/records 0.54.0 → 0.56.0

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.
@@ -1,10 +1,15 @@
1
1
  "use client";
2
2
  "use strict";
3
3
  "use client";
4
+ var __create = Object.create;
4
5
  var __defProp = Object.defineProperty;
5
6
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
7
  var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
7
9
  var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __esm = (fn, res) => function __init() {
11
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
12
+ };
8
13
  var __export = (target, all) => {
9
14
  for (var name in all)
10
15
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -17,8 +22,2177 @@ var __copyProps = (to, from, except, desc) => {
17
22
  }
18
23
  return to;
19
24
  };
25
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
26
+ // If the importer is in node compatibility mode or this is not an ESM
27
+ // file that has been converted to a CommonJS file using a Babel-
28
+ // compatible transform (i.e. "__esModule" has not been set), then set
29
+ // "default" to the CommonJS "module.exports" for node compatibility.
30
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
31
+ mod
32
+ ));
20
33
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
34
 
35
+ // src/use-cases/alvarado-chen-kitchen-weekly-cooking.ts
36
+ var alvarado_chen_kitchen_weekly_cooking_exports = {};
37
+ __export(alvarado_chen_kitchen_weekly_cooking_exports, {
38
+ default: () => alvarado_chen_kitchen_weekly_cooking_default,
39
+ useCase: () => useCase
40
+ });
41
+ var useCase, alvarado_chen_kitchen_weekly_cooking_default;
42
+ var init_alvarado_chen_kitchen_weekly_cooking = __esm({
43
+ "src/use-cases/alvarado-chen-kitchen-weekly-cooking.ts"() {
44
+ "use strict";
45
+ useCase = {
46
+ id: "alvarado-chen-kitchen-weekly-cooking",
47
+ useCase: "Priya and Daniel Alvarado-Chen cook for a family of five, and they use this to keep the recipes they actually make, the ingredients each one needs, and the weekly shopping list that falls out of the meals they have planned, instead of three notebooks and a text message at the shop.",
48
+ industry: "Household cooking",
49
+ cleanupTag: "use-case:alvarado-chen-kitchen-weekly-cooking",
50
+ business: {
51
+ name: "The Alvarado-Chen Kitchen",
52
+ describes: "A household of five that cooks most nights and shops once a week across three shops.",
53
+ address: {
54
+ line1: "68 Winterbourne Road",
55
+ city: "Oak Park",
56
+ region: "IL",
57
+ postalCode: "60302",
58
+ country: "US"
59
+ },
60
+ phone: "+1 708 555 0126",
61
+ email: "kitchen@alvaradochen.net",
62
+ timezone: "America/Chicago"
63
+ },
64
+ tables: [
65
+ {
66
+ token: "recipes",
67
+ name: "Recipes",
68
+ labelSingular: "Recipe",
69
+ labelPlural: "Recipes",
70
+ type: "entity",
71
+ display: "grid",
72
+ weight: "heavy",
73
+ ordered: false,
74
+ icon: "chef-hat",
75
+ titleField: "title",
76
+ describes: "Every dish the household actually cooks, with who brought it in and how long it takes.",
77
+ fields: [
78
+ { key: "title", label: "Recipe", parityType: "text", required: true, sensitivity: "internal", contextPolicy: "include" },
79
+ { key: "category", label: "Course", parityType: "select", choices: ["Breakfast", "Main Course", "Side Dish", "Soup", "Dessert", "Sauce/Condiment"], sensitivity: "internal", contextPolicy: "include" },
80
+ { key: "cuisine", label: "Cuisine", parityType: "select", choices: ["Mexican", "Chinese", "Italian", "American", "Middle Eastern", "Indian"], sensitivity: "internal", contextPolicy: "include" },
81
+ { key: "prep_minutes", label: "Prep time", parityType: "integer", unit: "min", sensitivity: "internal", contextPolicy: "include" },
82
+ { key: "cook_minutes", label: "Cook time", parityType: "integer", unit: "min", sensitivity: "internal", contextPolicy: "include" },
83
+ { key: "servings", label: "Serves", parityType: "integer", sensitivity: "internal", contextPolicy: "include" },
84
+ { key: "source", label: "Where it came from", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
85
+ { key: "contributed_by", label: "Brought in by", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
86
+ { key: "date_added", label: "Added", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" }
87
+ ],
88
+ rows: [
89
+ { key: "recipe-chilaquiles-verdes", values: { "title": "Chilaquiles Verdes", "category": "Breakfast", "cuisine": "Mexican", "prep_minutes": 15, "cook_minutes": 20, "servings": 4, "source": "Grandma Alvarado's recipe box, card #12", "contributed_by": "Rosa Alvarado", "date_added": "2026-01-08" } },
90
+ { key: "recipe-kung-pao-chicken", values: { "title": "Kung Pao Chicken", "category": "Main Course", "cuisine": "Chinese", "prep_minutes": 20, "cook_minutes": 15, "servings": 4, "source": "Adapted from Fuchsia Dunlop's Land of Fish and Rice", "contributed_by": "Wei Chen", "date_added": "2026-01-15" } },
91
+ { key: "recipe-slow-braised-short-rib-ragu", values: { "title": "Slow-Braised Short Rib Ragu", "category": "Main Course", "cuisine": "Italian", "prep_minutes": 25, "cook_minutes": 210, "servings": 6, "source": "Sunday dinner tradition, no written source", "contributed_by": "Marco Alvarado", "date_added": "2026-02-02" } },
92
+ { key: "recipe-mapo-tofu", values: { "title": "Mapo Tofu", "category": "Main Course", "cuisine": "Chinese", "prep_minutes": 10, "cook_minutes": 15, "servings": 3, "source": "Wei's mother, dictated over the phone", "contributed_by": "Wei Chen", "date_added": "2026-02-10" } },
93
+ { key: "recipe-elote-street-corn-salad", values: { "title": "Elote Street Corn Salad", "category": "Side Dish", "cuisine": "Mexican", "prep_minutes": 15, "cook_minutes": 10, "servings": 6, "source": "Farmers market recipe card", "contributed_by": "Rosa Alvarado", "date_added": "2026-03-01" } },
94
+ { key: "recipe-pozole-rojo", values: { "title": "Pozole Rojo", "category": "Soup", "cuisine": "Mexican", "prep_minutes": 30, "cook_minutes": 180, "servings": 8, "source": "Family recipe, three generations", "contributed_by": "Rosa Alvarado", "date_added": "2026-03-14" } },
95
+ { key: "recipe-hot-and-sour-soup", values: { "title": "Hot and Sour Soup", "category": "Soup", "cuisine": "Chinese", "prep_minutes": 15, "cook_minutes": 20, "servings": 4, "source": "Wei Chen's own recipe", "contributed_by": "Wei Chen", "date_added": "2026-03-22" } },
96
+ { key: "recipe-tres-leches-cake", values: { "title": "Tres Leches Cake", "category": "Dessert", "cuisine": "Mexican", "prep_minutes": 30, "cook_minutes": 35, "servings": 12, "source": "Grandma Alvarado's recipe box, card #4", "contributed_by": "Rosa Alvarado", "date_added": "2026-04-05" } },
97
+ { key: "recipe-cacio-e-pepe", values: { "title": "Cacio e Pepe", "category": "Main Course", "cuisine": "Italian", "prep_minutes": 5, "cook_minutes": 15, "servings": 2, "source": "Weeknight standby, no written source", "contributed_by": "Marco Alvarado", "date_added": "2026-04-12" } },
98
+ { key: "recipe-chana-masala", values: { "title": "Chana Masala", "category": "Main Course", "cuisine": "Indian", "prep_minutes": 15, "cook_minutes": 30, "servings": 4, "source": "Learned from neighbor Priya", "contributed_by": "Wei Chen", "date_added": "2026-05-01" } },
99
+ { key: "recipe-salsa-verde-cruda", values: { "title": "Salsa Verde Cruda", "category": "Sauce/Condiment", "cuisine": "Mexican", "prep_minutes": 10, "cook_minutes": 0, "servings": 8, "source": "Grandma Alvarado's recipe box, card #1", "contributed_by": "Rosa Alvarado", "date_added": "2026-05-10" } },
100
+ { key: "recipe-shakshuka", values: { "title": "Shakshuka", "category": "Breakfast", "cuisine": "Middle Eastern", "prep_minutes": 10, "cook_minutes": 25, "servings": 4, "source": "Ottolenghi's Jerusalem, adapted", "contributed_by": "Marco Alvarado", "date_added": "2026-05-18" } }
101
+ ]
102
+ },
103
+ {
104
+ token: "ingredients",
105
+ name: "Ingredients",
106
+ labelSingular: "Ingredient",
107
+ labelPlural: "Ingredients",
108
+ type: "detail",
109
+ display: "list",
110
+ weight: "light",
111
+ ordered: true,
112
+ icon: "carrot",
113
+ titleField: "ingredient_name",
114
+ describes: "What goes into each recipe, in the amounts the recipe is written for.",
115
+ fields: [
116
+ { key: "recipe", label: "Recipe", parityType: "relation", required: true, relationTarget: "recipes", relationMax: 1, sensitivity: "internal", contextPolicy: "include" },
117
+ { key: "ingredient_name", label: "Ingredient", parityType: "text", required: true, sensitivity: "internal", contextPolicy: "include" },
118
+ { key: "quantity", label: "Quantity", parityType: "integer", sensitivity: "internal", contextPolicy: "include" },
119
+ { key: "unit", label: "Unit", parityType: "select", choices: ["cup", "tbsp", "tsp", "oz", "lb", "clove", "whole", "can", "pinch"], sensitivity: "internal", contextPolicy: "include" },
120
+ { key: "notes", label: "Notes", parityType: "text", sensitivity: "internal", contextPolicy: "include" }
121
+ ],
122
+ rows: [
123
+ { key: "ingredient-corn-tortillas-cut-into-wedges-and-fried", values: { "recipe": "recipe-chilaquiles-verdes", "ingredient_name": "corn tortillas, cut into wedges and fried", "quantity": 12, "unit": "whole", "notes": "day-old tortillas fry crisper" } },
124
+ { key: "ingredient-tomatillos", values: { "recipe": "recipe-chilaquiles-verdes", "ingredient_name": "tomatillos", "quantity": 1, "unit": "lb", "notes": "husked and rinsed" } },
125
+ { key: "ingredient-serrano-peppers", values: { "recipe": "recipe-chilaquiles-verdes", "ingredient_name": "serrano peppers", "quantity": 2, "unit": "whole", "notes": "seeds removed for less heat" } },
126
+ { key: "ingredient-queso-fresco", values: { "recipe": "recipe-chilaquiles-verdes", "ingredient_name": "queso fresco", "quantity": 4, "unit": "oz", "notes": "crumbled for topping" } },
127
+ { key: "ingredient-chicken-thighs-diced", values: { "recipe": "recipe-kung-pao-chicken", "ingredient_name": "chicken thighs, diced", "quantity": 1.5, "unit": "lb", "notes": "boneless, skinless" } },
128
+ { key: "ingredient-dried-red-chilies", values: { "recipe": "recipe-kung-pao-chicken", "ingredient_name": "dried red chilies", "quantity": 8, "unit": "whole", "notes": "adjust to taste" } },
129
+ { key: "ingredient-roasted-peanuts", values: { "recipe": "recipe-kung-pao-chicken", "ingredient_name": "roasted peanuts", "quantity": 0.5, "unit": "cup", "notes": "" } },
130
+ { key: "ingredient-sichuan-peppercorns", values: { "recipe": "recipe-kung-pao-chicken", "ingredient_name": "Sichuan peppercorns", "quantity": 1, "unit": "tsp", "notes": "toasted and cracked" } },
131
+ { key: "ingredient-bone-in-short-ribs", values: { "recipe": "recipe-slow-braised-short-rib-ragu", "ingredient_name": "bone-in short ribs", "quantity": 3, "unit": "lb", "notes": "trimmed of excess fat" } },
132
+ { key: "ingredient-san-marzano-tomatoes", values: { "recipe": "recipe-slow-braised-short-rib-ragu", "ingredient_name": "San Marzano tomatoes", "quantity": 1, "unit": "can", "notes": "28 oz can, crushed by hand" } },
133
+ { key: "ingredient-red-wine", values: { "recipe": "recipe-slow-braised-short-rib-ragu", "ingredient_name": "red wine", "quantity": 1, "unit": "cup", "notes": "something drinkable" } },
134
+ { key: "ingredient-soft-tofu-cubed", values: { "recipe": "recipe-mapo-tofu", "ingredient_name": "soft tofu, cubed", "quantity": 14, "unit": "oz", "notes": "one package" } },
135
+ { key: "ingredient-doubanjiang-fermented-chili-bean-paste", values: { "recipe": "recipe-mapo-tofu", "ingredient_name": "doubanjiang (fermented chili bean paste)", "quantity": 2, "unit": "tbsp", "notes": "Pixian brand preferred" } },
136
+ { key: "ingredient-ground-pork", values: { "recipe": "recipe-mapo-tofu", "ingredient_name": "ground pork", "quantity": 0.5, "unit": "lb", "notes": "" } },
137
+ { key: "ingredient-corn-kernels-charred", values: { "recipe": "recipe-elote-street-corn-salad", "ingredient_name": "corn kernels, charred", "quantity": 4, "unit": "cup", "notes": "grilled or pan-charred" } },
138
+ { key: "ingredient-cotija-cheese", values: { "recipe": "recipe-elote-street-corn-salad", "ingredient_name": "cotija cheese", "quantity": 0.5, "unit": "cup", "notes": "crumbled" } },
139
+ { key: "ingredient-lime", values: { "recipe": "recipe-elote-street-corn-salad", "ingredient_name": "lime", "quantity": 2, "unit": "whole", "notes": "juiced" } },
140
+ { key: "ingredient-pork-shoulder", values: { "recipe": "recipe-pozole-rojo", "ingredient_name": "pork shoulder", "quantity": 3, "unit": "lb", "notes": "cut into large chunks" } },
141
+ { key: "ingredient-hominy", values: { "recipe": "recipe-pozole-rojo", "ingredient_name": "hominy", "quantity": 2, "unit": "can", "notes": "29 oz cans, drained" } },
142
+ { key: "ingredient-guajillo-chilies", values: { "recipe": "recipe-pozole-rojo", "ingredient_name": "guajillo chilies", "quantity": 6, "unit": "whole", "notes": "stemmed and seeded" } },
143
+ { key: "ingredient-wood-ear-mushrooms-dried", values: { "recipe": "recipe-hot-and-sour-soup", "ingredient_name": "wood ear mushrooms, dried", "quantity": 0.25, "unit": "cup", "notes": "rehydrated and sliced" } },
144
+ { key: "ingredient-white-pepper", values: { "recipe": "recipe-hot-and-sour-soup", "ingredient_name": "white pepper", "quantity": 1, "unit": "tsp", "notes": "the 'hot' in hot and sour" } },
145
+ { key: "ingredient-evaporated-milk", values: { "recipe": "recipe-tres-leches-cake", "ingredient_name": "evaporated milk", "quantity": 1, "unit": "can", "notes": "12 oz can" } },
146
+ { key: "ingredient-sweetened-condensed-milk", values: { "recipe": "recipe-tres-leches-cake", "ingredient_name": "sweetened condensed milk", "quantity": 1, "unit": "can", "notes": "14 oz can" } },
147
+ { key: "ingredient-pecorino-romano-grated", values: { "recipe": "recipe-cacio-e-pepe", "ingredient_name": "pecorino romano, grated", "quantity": 1.5, "unit": "cup", "notes": "finely grated, not shredded" } },
148
+ { key: "ingredient-chickpeas", values: { "recipe": "recipe-chana-masala", "ingredient_name": "chickpeas", "quantity": 2, "unit": "can", "notes": "15 oz cans, drained" } },
149
+ { key: "ingredient-garam-masala", values: { "recipe": "recipe-chana-masala", "ingredient_name": "garam masala", "quantity": 1, "unit": "tbsp", "notes": "" } },
150
+ { key: "ingredient-tomatillos-raw", values: { "recipe": "recipe-salsa-verde-cruda", "ingredient_name": "tomatillos, raw", "quantity": 1, "unit": "lb", "notes": "quartered" } },
151
+ { key: "ingredient-eggs", values: { "recipe": "recipe-shakshuka", "ingredient_name": "eggs", "quantity": 6, "unit": "whole", "notes": "cracked directly into sauce" } },
152
+ { key: "ingredient-crushed-tomatoes", values: { "recipe": "recipe-shakshuka", "ingredient_name": "crushed tomatoes", "quantity": 1, "unit": "can", "notes": "28 oz can" } }
153
+ ]
154
+ },
155
+ {
156
+ token: "shopping_lists",
157
+ name: "Shopping lists",
158
+ labelSingular: "Shopping list",
159
+ labelPlural: "Shopping lists",
160
+ type: "entity",
161
+ display: "board",
162
+ weight: "heavy",
163
+ ordered: false,
164
+ icon: "shopping-cart",
165
+ titleField: "list_name",
166
+ describes: "One list per shop per week, built from the recipes planned for that week.",
167
+ fields: [
168
+ { key: "list_name", label: "List", parityType: "text", required: true, sensitivity: "internal", contextPolicy: "include" },
169
+ { key: "week_of", label: "Week of", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
170
+ { key: "store", label: "Shop", parityType: "select", choices: ["Fresh Market Co-op", "Lucky Star Asian Grocery", "Mercado Alvarado", "Costco"], sensitivity: "internal", contextPolicy: "include" },
171
+ { key: "status", label: "Status", parityType: "select", choices: ["Planning", "Ready to Shop", "Shopping", "Done"], sensitivity: "internal", contextPolicy: "include" }
172
+ ],
173
+ rows: [
174
+ { key: "list-week-of-jun-1-mexican-night-weekday-soup", values: { "list_name": "Week of Jun 1 \u2014 Mexican night + weekday soup", "week_of": "2026-06-01", "store": "Mercado Alvarado", "status": "Done" } },
175
+ { key: "list-week-of-jun-8-chinese-takeout-at-home", values: { "list_name": "Week of Jun 8 \u2014 Chinese takeout-at-home", "week_of": "2026-06-08", "store": "Lucky Star Asian Grocery", "status": "Done" } },
176
+ { key: "list-week-of-jun-15-sunday-ragu-easy-weeknights", values: { "list_name": "Week of Jun 15 \u2014 Sunday ragu + easy weeknights", "week_of": "2026-06-15", "store": "Fresh Market Co-op", "status": "Done" } },
177
+ { key: "list-week-of-jun-22-birthday-cake-week", values: { "list_name": "Week of Jun 22 \u2014 Birthday cake week", "week_of": "2026-06-22", "store": "Costco", "status": "Ready to Shop" } },
178
+ { key: "list-week-of-jun-29-pozole-for-the-in-laws", values: { "list_name": "Week of Jun 29 \u2014 Pozole for the in-laws", "week_of": "2026-06-29", "store": "Mercado Alvarado", "status": "Planning" } }
179
+ ]
180
+ },
181
+ {
182
+ token: "shopping_list_items",
183
+ name: "List items",
184
+ labelSingular: "List item",
185
+ labelPlural: "List items",
186
+ type: "detail",
187
+ display: "list",
188
+ weight: "light",
189
+ ordered: true,
190
+ icon: "list-checks",
191
+ titleField: "ingredient_name",
192
+ describes: "What is actually on a list, by aisle, and whether it is already in the trolley.",
193
+ fields: [
194
+ { key: "shopping_list", label: "Shopping list", parityType: "relation", required: true, relationTarget: "shopping_lists", relationMax: 1, sensitivity: "internal", contextPolicy: "include" },
195
+ { key: "ingredient_name", label: "Ingredient", parityType: "text", required: true, sensitivity: "internal", contextPolicy: "include" },
196
+ { key: "quantity", label: "Quantity", parityType: "integer", sensitivity: "internal", contextPolicy: "include" },
197
+ { key: "unit", label: "Unit", parityType: "select", choices: ["cup", "tbsp", "tsp", "oz", "lb", "clove", "whole", "can", "pinch"], sensitivity: "internal", contextPolicy: "include" },
198
+ { key: "aisle", label: "Aisle", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
199
+ { key: "checked", label: "In the trolley", parityType: "select", choices: ["Yes", "No"], sensitivity: "internal", contextPolicy: "include" }
200
+ ],
201
+ rows: [
202
+ { key: "item-tomatillos", values: { "shopping_list": "list-week-of-jun-1-mexican-night-weekday-soup", "ingredient_name": "tomatillos", "quantity": 2, "unit": "lb", "aisle": "Produce", "checked": "Yes" } },
203
+ { key: "item-corn-tortillas", values: { "shopping_list": "list-week-of-jun-1-mexican-night-weekday-soup", "ingredient_name": "corn tortillas", "quantity": 2, "unit": "whole", "aisle": "Bakery", "checked": "Yes" } },
204
+ { key: "item-queso-fresco", values: { "shopping_list": "list-week-of-jun-1-mexican-night-weekday-soup", "ingredient_name": "queso fresco", "quantity": 8, "unit": "oz", "aisle": "Dairy", "checked": "Yes" } },
205
+ { key: "item-chicken-thighs", values: { "shopping_list": "list-week-of-jun-8-chinese-takeout-at-home", "ingredient_name": "chicken thighs", "quantity": 1.5, "unit": "lb", "aisle": "Meat", "checked": "Yes" } },
206
+ { key: "item-dried-red-chilies", values: { "shopping_list": "list-week-of-jun-8-chinese-takeout-at-home", "ingredient_name": "dried red chilies", "quantity": 1, "unit": "oz", "aisle": "International", "checked": "Yes" } },
207
+ { key: "item-sichuan-peppercorns", values: { "shopping_list": "list-week-of-jun-8-chinese-takeout-at-home", "ingredient_name": "Sichuan peppercorns", "quantity": 1, "unit": "oz", "aisle": "International", "checked": "No" } },
208
+ { key: "item-bone-in-short-ribs", values: { "shopping_list": "list-week-of-jun-15-sunday-ragu-easy-weeknights", "ingredient_name": "bone-in short ribs", "quantity": 3, "unit": "lb", "aisle": "Meat", "checked": "Yes" } },
209
+ { key: "item-san-marzano-tomatoes", values: { "shopping_list": "list-week-of-jun-15-sunday-ragu-easy-weeknights", "ingredient_name": "San Marzano tomatoes", "quantity": 2, "unit": "can", "aisle": "Canned Goods", "checked": "Yes" } },
210
+ { key: "item-pecorino-romano", values: { "shopping_list": "list-week-of-jun-15-sunday-ragu-easy-weeknights", "ingredient_name": "pecorino romano", "quantity": 1, "unit": "lb", "aisle": "Dairy", "checked": "No" } },
211
+ { key: "item-evaporated-milk", values: { "shopping_list": "list-week-of-jun-22-birthday-cake-week", "ingredient_name": "evaporated milk", "quantity": 2, "unit": "can", "aisle": "Baking", "checked": "No" } },
212
+ { key: "item-sweetened-condensed-milk", values: { "shopping_list": "list-week-of-jun-22-birthday-cake-week", "ingredient_name": "sweetened condensed milk", "quantity": 2, "unit": "can", "aisle": "Baking", "checked": "No" } },
213
+ { key: "item-pork-shoulder", values: { "shopping_list": "list-week-of-jun-29-pozole-for-the-in-laws", "ingredient_name": "pork shoulder", "quantity": 3, "unit": "lb", "aisle": "Meat", "checked": "No" } },
214
+ { key: "item-hominy", values: { "shopping_list": "list-week-of-jun-29-pozole-for-the-in-laws", "ingredient_name": "hominy", "quantity": 4, "unit": "can", "aisle": "Canned Goods", "checked": "No" } },
215
+ { key: "item-guajillo-chilies", values: { "shopping_list": "list-week-of-jun-29-pozole-for-the-in-laws", "ingredient_name": "guajillo chilies", "quantity": 6, "unit": "oz", "aisle": "International", "checked": "No" } }
216
+ ]
217
+ }
218
+ ],
219
+ relationships: [
220
+ {
221
+ describes: "An ingredient belongs to the recipe it is part of and means nothing without it.",
222
+ fromTable: "ingredients",
223
+ fromField: "recipe",
224
+ toTable: "recipes",
225
+ flavor: "owned",
226
+ cardinality: "one",
227
+ onDelete: "cascade",
228
+ inverseKey: "ingredients"
229
+ },
230
+ {
231
+ describes: "A line on the shopping list belongs to the list it is written on.",
232
+ fromTable: "shopping_list_items",
233
+ fromField: "shopping_list",
234
+ toTable: "shopping_lists",
235
+ flavor: "owned",
236
+ cardinality: "one",
237
+ onDelete: "cascade",
238
+ inverseKey: "items"
239
+ }
240
+ ],
241
+ form: {
242
+ token: "alvarado_chen_add_a_recipe",
243
+ name: "Add a recipe to the family collection",
244
+ describes: "What anyone in the family fills in when a dish is worth keeping \u2014 including the grandparents, which is why it asks who brought it in.",
245
+ audience: "member",
246
+ table: "recipes",
247
+ fields: [
248
+ { fieldKey: "title", label: "What is it called?", required: true },
249
+ { fieldKey: "category", label: "Course", required: true },
250
+ { fieldKey: "cuisine", label: "Cuisine" },
251
+ { fieldKey: "prep_minutes", label: "Prep time in minutes", help: "Chopping and mixing \u2014 everything before it goes on the heat." },
252
+ { fieldKey: "cook_minutes", label: "Cook time in minutes" },
253
+ { fieldKey: "servings", label: "How many does it serve?", required: true },
254
+ { fieldKey: "source", label: "Where did it come from?", help: "A book, a website, or a person. We like knowing." },
255
+ { fieldKey: "contributed_by", label: "Who brought it in?", required: true }
256
+ ],
257
+ submitLabel: "Add it to the collection",
258
+ confirmation: "Added. Put the ingredients in next, and it will start showing up on the shopping list when you plan it for a week."
259
+ },
260
+ pipeline: {
261
+ token: "alvarado_chen_weekly_shop",
262
+ name: "The weekly shop",
263
+ describes: "A list's life is four days long and everybody in the house touches it. The stages exist so nobody buys the same bag of rice twice.",
264
+ table: "shopping_lists",
265
+ stageField: "status",
266
+ stages: [
267
+ { key: "Planning", label: "Planning", describes: "Meals are still being chosen, so the list is still growing. Nobody shops from it yet.", typicalDurationDays: 3 },
268
+ { key: "Ready to Shop", label: "Ready to shop", describes: "The meals are settled and the list is complete. This is the state it is in when somebody picks up their keys.", typicalDurationDays: 1 },
269
+ { key: "Shopping", label: "Shopping", describes: "Somebody is in the shop ticking things off. Anything added now is a genuine omission, not a change of plan.", typicalDurationDays: 1 },
270
+ { key: "Done", label: "Done", describes: "Everything is home. Unticked items roll onto next week rather than being lost." }
271
+ ]
272
+ },
273
+ dashboardQuestion: {
274
+ question: "Which of our recipes can we actually cook on a Tuesday?",
275
+ whyItMatters: "Weeknight cooking fails on time, not on ideas. Knowing the average cook time by course is what stops a two-hour braise being planned for a school night, and it is the number that decides what goes on the list.",
276
+ table: "recipes",
277
+ aggregate: "avg",
278
+ of: "cook_minutes",
279
+ groupBy: "category",
280
+ answerUnit: "minutes"
281
+ },
282
+ documentTemplate: {
283
+ token: "alvarado_chen_recipe_card",
284
+ name: "Printable recipe card",
285
+ describes: "What gets printed and stuck to the fridge door, or sent to someone who asked for the recipe after dinner. It keeps the attribution, because half the collection came from somebody's mother.",
286
+ table: "recipes",
287
+ title: "{{recipe_title}} \u2014 serves {{servings}}",
288
+ body: [
289
+ "{{recipe_title}}",
290
+ "",
291
+ "{{course}} \xB7 {{cuisine}} \xB7 serves {{servings}}",
292
+ "Prep {{prep_time}} minutes, cook {{cook_time}} minutes.",
293
+ "",
294
+ "From {{source}}, brought into the family by {{contributed_by}}.",
295
+ "",
296
+ "Ingredients are on the back. If you halve it, do not halve the salt by the same amount \u2014 taste it instead.",
297
+ "",
298
+ "{{household}} \xB7 printed {{today}}"
299
+ ].join("\n"),
300
+ mergeFields: [
301
+ { key: "recipe_title", from: "title", describes: "The dish." },
302
+ { key: "course", from: "category", describes: "Which part of the meal it is." },
303
+ { key: "cuisine", from: "cuisine", describes: "Where it comes from." },
304
+ { key: "servings", from: "servings", describes: "How many it feeds, so it can be scaled." },
305
+ { key: "prep_time", from: "prep_minutes", describes: "Minutes before it goes on the heat." },
306
+ { key: "cook_time", from: "cook_minutes", describes: "Minutes on the heat." },
307
+ { key: "source", from: "source", describes: "The book, site or person it came from." },
308
+ { key: "contributed_by", from: "contributed_by", describes: "Who brought it into the family." },
309
+ { key: "household", from: "business", describes: "Whose kitchen this is." },
310
+ { key: "today", from: "today", describes: "When the card was printed." }
311
+ ]
312
+ },
313
+ notificationRule: {
314
+ token: "alvarado_chen_list_is_ready",
315
+ name: "The list is ready to shop",
316
+ describes: "The one message this household would genuinely set up: whoever is going to the shop needs to know the list stopped changing, because the whole failure mode is leaving with a list somebody was still editing.",
317
+ when: {
318
+ table: "shopping_lists",
319
+ event: "stage_entered",
320
+ stage: "Ready to Shop"
321
+ },
322
+ audience: "whoever is doing the shop this week",
323
+ channel: "in_app",
324
+ message: "{{list_name}} for the week of {{week_of}} is finished and ready \u2014 {{store}}. Tick things off as you go so nobody buys them twice."
325
+ },
326
+ provenance: {
327
+ kind: "synthesized",
328
+ authoredBy: "data crew (dataset) + lane REAL-DATA (business identity, relationships, form, pipeline, dashboard question, document, notification rule)",
329
+ authoredOn: "2026-09-21",
330
+ noRealPeople: true
331
+ }
332
+ };
333
+ alvarado_chen_kitchen_weekly_cooking_default = useCase;
334
+ }
335
+ });
336
+
337
+ // src/use-cases/birchwood-avenue-renovation-budget.ts
338
+ var birchwood_avenue_renovation_budget_exports = {};
339
+ __export(birchwood_avenue_renovation_budget_exports, {
340
+ default: () => birchwood_avenue_renovation_budget_default,
341
+ useCase: () => useCase2
342
+ });
343
+ var useCase2, birchwood_avenue_renovation_budget_default;
344
+ var init_birchwood_avenue_renovation_budget = __esm({
345
+ "src/use-cases/birchwood-avenue-renovation-budget.ts"() {
346
+ "use strict";
347
+ useCase2 = {
348
+ id: "birchwood-avenue-renovation-budget",
349
+ useCase: "Marguerite Oyelowo is renovating a 1920s house one room at a time, and she uses this to hold every contractor quote against the room it is for and every receipt against the budget she set, so that whether the job is over budget has an answer instead of an argument.",
350
+ industry: "Home renovation",
351
+ cleanupTag: "use-case:birchwood-avenue-renovation-budget",
352
+ business: {
353
+ name: "Birchwood Avenue Renovation",
354
+ describes: "A owner-managed whole-house renovation of a 1920s four-bedroom, run room by room over about a year.",
355
+ address: {
356
+ line1: "417 Birchwood Avenue",
357
+ city: "Providence",
358
+ region: "RI",
359
+ postalCode: "02906",
360
+ country: "US"
361
+ },
362
+ phone: "+1 401 555 0188",
363
+ email: "marguerite@birchwoodreno.net",
364
+ timezone: "America/New_York"
365
+ },
366
+ tables: [
367
+ {
368
+ token: "rooms",
369
+ name: "Rooms",
370
+ labelSingular: "Room",
371
+ labelPlural: "Rooms",
372
+ type: "entity",
373
+ display: "board",
374
+ weight: "heavy",
375
+ ordered: true,
376
+ icon: "door-open",
377
+ titleField: "room_name",
378
+ describes: "The house, room by room: what is being done to each one, when, and for how much.",
379
+ fields: [
380
+ { key: "room_name", label: "Room", parityType: "text", required: true, sensitivity: "internal", contextPolicy: "include" },
381
+ { key: "project_scope", label: "Scope of work", parityType: "long_text", sensitivity: "internal", contextPolicy: "include" },
382
+ { key: "target_start", label: "Target start", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
383
+ { key: "target_end", label: "Target finish", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
384
+ { key: "status", label: "Status", parityType: "select", choices: ["Planning", "Quoting", "In Progress", "Complete", "On Hold"], sensitivity: "internal", contextPolicy: "include" },
385
+ { key: "budget", label: "Budget", parityType: "currency", unit: "USD", format: "currency", sensitivity: "confidential", contextPolicy: "summarize" }
386
+ ],
387
+ rows: [
388
+ { key: "room-kitchen", values: { "room_name": "Kitchen", "project_scope": "Full gut renovation: new cabinets, quartz counters, relocate island, new appliances.", "target_start": "2026-04-01", "target_end": "2026-06-15", "status": "Complete", "budget": 48e3 } },
389
+ { key: "room-primary-bathroom", values: { "room_name": "Primary Bathroom", "project_scope": "Replace tub with walk-in shower, new vanity, heated tile floor.", "target_start": "2026-06-20", "target_end": "2026-08-01", "status": "In Progress", "budget": 22500 } },
390
+ { key: "room-basement", values: { "room_name": "Basement", "project_scope": "Finish unfinished basement into family room and home office, add egress window.", "target_start": "2026-08-10", "target_end": "2026-11-15", "status": "Quoting", "budget": 61e3 } },
391
+ { key: "room-guest-bathroom", values: { "room_name": "Guest Bathroom", "project_scope": "Cosmetic refresh: new vanity, paint, light fixtures.", "target_start": "2026-09-01", "target_end": "2026-09-20", "status": "Planning", "budget": 6500 } },
392
+ { key: "room-backyard-deck", values: { "room_name": "Backyard Deck", "project_scope": "Tear off old wood deck, build composite deck with pergola.", "target_start": "2026-05-01", "target_end": "2026-06-01", "status": "Complete", "budget": 18e3 } },
393
+ { key: "room-garage", values: { "room_name": "Garage", "project_scope": "Epoxy floor, built-in storage, new insulated door.", "target_start": "2026-10-01", "target_end": "2026-10-20", "status": "On Hold", "budget": 9500 } }
394
+ ]
395
+ },
396
+ {
397
+ token: "contractors",
398
+ name: "Contractors",
399
+ labelSingular: "Contractor",
400
+ labelPlural: "Contractors",
401
+ type: "entity",
402
+ display: "list",
403
+ weight: "heavy",
404
+ ordered: false,
405
+ icon: "hard-hat",
406
+ titleField: "company_name",
407
+ describes: "Everyone quoting or working on the job, with the licence and insurance details that matter if something goes wrong.",
408
+ fields: [
409
+ { key: "company_name", label: "Company", parityType: "text", required: true, sensitivity: "internal", contextPolicy: "include" },
410
+ { key: "trade", label: "Trade", parityType: "select", choices: ["General Contractor", "Plumbing", "Electrical", "Flooring", "Painting", "HVAC", "Carpentry"], sensitivity: "internal", contextPolicy: "include" },
411
+ { key: "contact_name", label: "Contact", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
412
+ { key: "phone", label: "Phone", parityType: "phone", format: "phone", sensitivity: "confidential", contextPolicy: "exclude" },
413
+ { key: "email", label: "Email", parityType: "email", format: "email", sensitivity: "confidential", contextPolicy: "exclude" },
414
+ { key: "license_number", label: "Licence number", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
415
+ { key: "insured", label: "Insured", parityType: "select", choices: ["Yes", "No"], sensitivity: "internal", contextPolicy: "include" }
416
+ ],
417
+ rows: [
418
+ { key: "contractor-ferro-sons-construction", values: { "company_name": "Ferro & Sons Construction", "trade": "General Contractor", "contact_name": "Dominic Ferro", "phone": "555-330-1001", "email": "dominic@northshoremail.com", "license_number": "GC-88213-OH", "insured": "Yes" } },
419
+ { key: "contractor-redline-plumbing-co", values: { "company_name": "Redline Plumbing Co.", "trade": "Plumbing", "contact_name": "Tanya Iversen", "phone": "555-330-1002", "email": "tanya@northshoremail.com", "license_number": "PL-44029-OH", "insured": "Yes" } },
420
+ { key: "contractor-voltway-electric", values: { "company_name": "Voltway Electric", "trade": "Electrical", "contact_name": "Emeka Osayande", "phone": "555-330-1003", "email": "emeka@northshoremail.com", "license_number": "EL-90117-OH", "insured": "Yes" } },
421
+ { key: "contractor-hearthstone-flooring", values: { "company_name": "Hearthstone Flooring", "trade": "Flooring", "contact_name": "Bianca Moretti", "phone": "555-330-1004", "email": "bianca@northshoremail.com", "license_number": "FL-22850-OH", "insured": "Yes" } },
422
+ { key: "contractor-clearcoat-painting", values: { "company_name": "Clearcoat Painting", "trade": "Painting", "contact_name": "Sam Delacroix", "phone": "555-330-1005", "email": "sam@northshoremail.com", "license_number": "PT-10442-OH", "insured": "No" } },
423
+ { key: "contractor-northgate-hvac", values: { "company_name": "Northgate HVAC", "trade": "HVAC", "contact_name": "Renata Kowalczyk", "phone": "555-330-1006", "email": "renata@northshoremail.com", "license_number": "HV-77302-OH", "insured": "Yes" } },
424
+ { key: "contractor-millbrook-carpentry", values: { "company_name": "Millbrook Carpentry", "trade": "Carpentry", "contact_name": "Julius Wexford", "phone": "555-330-1007", "email": "julius@northshoremail.com", "license_number": "CP-55671-OH", "insured": "Yes" } }
425
+ ]
426
+ },
427
+ {
428
+ token: "quotes",
429
+ name: "Quotes",
430
+ labelSingular: "Quote",
431
+ labelPlural: "Quotes",
432
+ type: "ledger",
433
+ display: "list",
434
+ weight: "heavy",
435
+ ordered: false,
436
+ icon: "file-text",
437
+ titleField: "quote_amount",
438
+ describes: "What each trade said each room would cost, and whether that price is still good.",
439
+ fields: [
440
+ { key: "room", label: "Room", parityType: "relation", required: true, relationTarget: "rooms", relationMax: 1, sensitivity: "internal", contextPolicy: "include" },
441
+ { key: "contractor", label: "Contractor", parityType: "relation", required: true, relationTarget: "contractors", relationMax: 1, sensitivity: "internal", contextPolicy: "include" },
442
+ { key: "quote_amount", label: "Quote", parityType: "currency", unit: "USD", format: "currency", required: true, sensitivity: "confidential", contextPolicy: "summarize" },
443
+ { key: "quote_date", label: "Quoted on", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
444
+ { key: "status", label: "Status", parityType: "select", choices: ["Pending", "Accepted", "Rejected", "Expired"], sensitivity: "internal", contextPolicy: "include" },
445
+ { key: "valid_until", label: "Valid until", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" }
446
+ ],
447
+ rows: [
448
+ { key: "quote-46500-0", values: { "room": "room-kitchen", "contractor": "contractor-ferro-sons-construction", "quote_amount": 46500, "quote_date": "2026-02-14", "status": "Accepted", "valid_until": "2026-03-14" } },
449
+ { key: "quote-3200-0", values: { "room": "room-kitchen", "contractor": "contractor-redline-plumbing-co", "quote_amount": 3200, "quote_date": "2026-02-20", "status": "Accepted", "valid_until": "2026-03-20" } },
450
+ { key: "quote-2800-0", values: { "room": "room-kitchen", "contractor": "contractor-voltway-electric", "quote_amount": 2800, "quote_date": "2026-02-20", "status": "Accepted", "valid_until": "2026-03-20" } },
451
+ { key: "quote-21000-0", values: { "room": "room-primary-bathroom", "contractor": "contractor-ferro-sons-construction", "quote_amount": 21e3, "quote_date": "2026-05-10", "status": "Accepted", "valid_until": "2026-06-10" } },
452
+ { key: "quote-4100-0", values: { "room": "room-primary-bathroom", "contractor": "contractor-redline-plumbing-co", "quote_amount": 4100, "quote_date": "2026-05-11", "status": "Accepted", "valid_until": "2026-06-11" } },
453
+ { key: "quote-58000-0", values: { "room": "room-basement", "contractor": "contractor-ferro-sons-construction", "quote_amount": 58e3, "quote_date": "2026-07-20", "status": "Pending", "valid_until": "2026-08-20" } },
454
+ { key: "quote-12500-0", values: { "room": "room-basement", "contractor": "contractor-millbrook-carpentry", "quote_amount": 12500, "quote_date": "2026-07-22", "status": "Pending", "valid_until": "2026-08-22" } },
455
+ { key: "quote-6800-0", values: { "room": "room-basement", "contractor": "contractor-northgate-hvac", "quote_amount": 6800, "quote_date": "2026-07-25", "status": "Pending", "valid_until": "2026-08-25" } },
456
+ { key: "quote-1800-0", values: { "room": "room-guest-bathroom", "contractor": "contractor-hearthstone-flooring", "quote_amount": 1800, "quote_date": "2026-07-28", "status": "Pending", "valid_until": "2026-08-28" } },
457
+ { key: "quote-17200-0", values: { "room": "room-backyard-deck", "contractor": "contractor-millbrook-carpentry", "quote_amount": 17200, "quote_date": "2026-03-05", "status": "Accepted", "valid_until": "2026-04-05" } },
458
+ { key: "quote-19800-0", values: { "room": "room-backyard-deck", "contractor": "contractor-ferro-sons-construction", "quote_amount": 19800, "quote_date": "2026-03-02", "status": "Rejected", "valid_until": "2026-04-02" } },
459
+ { key: "quote-2100-0", values: { "room": "room-garage", "contractor": "contractor-clearcoat-painting", "quote_amount": 2100, "quote_date": "2026-01-15", "status": "Expired", "valid_until": "2026-02-15" } }
460
+ ]
461
+ },
462
+ {
463
+ token: "purchases",
464
+ name: "Purchases",
465
+ labelSingular: "Purchase",
466
+ labelPlural: "Purchases",
467
+ type: "ledger",
468
+ display: "list",
469
+ weight: "heavy",
470
+ ordered: false,
471
+ icon: "receipt",
472
+ titleField: "item_description",
473
+ describes: "Every pound spent against the project, so the budget is a fact rather than a feeling.",
474
+ fields: [
475
+ { key: "room", label: "Room", parityType: "relation", required: true, relationTarget: "rooms", relationMax: 1, sensitivity: "internal", contextPolicy: "include" },
476
+ { key: "item_description", label: "What was bought", parityType: "text", required: true, sensitivity: "internal", contextPolicy: "include" },
477
+ { key: "vendor", label: "Vendor", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
478
+ { key: "purchase_date", label: "Bought on", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
479
+ { key: "amount", label: "Amount", parityType: "currency", unit: "USD", format: "currency", sensitivity: "confidential", contextPolicy: "summarize" },
480
+ { key: "category", label: "Category", parityType: "select", choices: ["Materials", "Fixtures", "Labor", "Permits", "Appliances", "Design/Design Fees"], sensitivity: "internal", contextPolicy: "include" },
481
+ { key: "receipt_number", label: "Receipt", parityType: "text", sensitivity: "internal", contextPolicy: "include" }
482
+ ],
483
+ rows: [
484
+ { key: "purchase-custom-shaker-cabinets-painted-alabaster", values: { "room": "room-kitchen", "item_description": "Custom shaker cabinets, painted 'Alabaster'", "vendor": "Millbrook Cabinetry Supply", "purchase_date": "2026-04-05", "amount": 14200, "category": "Materials", "receipt_number": "RCT-10021" } },
485
+ { key: "purchase-quartz-countertop-calacatta-gold-42-sq-ft", values: { "room": "room-kitchen", "item_description": "Quartz countertop, 'Calacatta Gold' 42 sq ft", "vendor": "Stone Depot", "purchase_date": "2026-04-18", "amount": 5900, "category": "Materials", "receipt_number": "RCT-10022" } },
486
+ { key: "purchase-range-refrigerator-dishwasher-package", values: { "room": "room-kitchen", "item_description": "Range, refrigerator, dishwasher package", "vendor": "Coldstream Appliance Center", "purchase_date": "2026-04-22", "amount": 8700, "category": "Appliances", "receipt_number": "RCT-10023" } },
487
+ { key: "purchase-building-permit-kitchen-remodel", values: { "room": "room-kitchen", "item_description": "Building permit \u2014 kitchen remodel", "vendor": "City of Fairmont Permits Office", "purchase_date": "2026-03-28", "amount": 450, "category": "Permits", "receipt_number": "RCT-10024" } },
488
+ { key: "purchase-ferro-sons-final-labor-invoice", values: { "room": "room-kitchen", "item_description": "Ferro & Sons \u2014 final labor invoice", "vendor": "Ferro & Sons Construction", "purchase_date": "2026-06-15", "amount": 15800, "category": "Labor", "receipt_number": "RCT-10025" } },
489
+ { key: "purchase-walk-in-shower-kit-with-frameless-glass", values: { "room": "room-primary-bathroom", "item_description": "Walk-in shower kit with frameless glass", "vendor": "Stone Depot", "purchase_date": "2026-06-25", "amount": 4300, "category": "Fixtures", "receipt_number": "RCT-10026" } },
490
+ { key: "purchase-heated-floor-mat-system-45-sq-ft", values: { "room": "room-primary-bathroom", "item_description": "Heated floor mat system, 45 sq ft", "vendor": "WarmFloor Direct", "purchase_date": "2026-06-28", "amount": 1650, "category": "Materials", "receipt_number": "RCT-10027" } },
491
+ { key: "purchase-floating-double-vanity-60-inch", values: { "room": "room-primary-bathroom", "item_description": "Floating double vanity, 60 inch", "vendor": "Millbrook Cabinetry Supply", "purchase_date": "2026-07-02", "amount": 2200, "category": "Fixtures", "receipt_number": "RCT-10028" } },
492
+ { key: "purchase-composite-decking-600-sq-ft-weathered-teak", values: { "room": "room-backyard-deck", "item_description": "Composite decking, 600 sq ft, 'Weathered Teak'", "vendor": "Deckmaster Supply", "purchase_date": "2026-05-05", "amount": 8900, "category": "Materials", "receipt_number": "RCT-10029" } },
493
+ { key: "purchase-cedar-pergola-kit-12x14", values: { "room": "room-backyard-deck", "item_description": "Cedar pergola kit, 12x14", "vendor": "Deckmaster Supply", "purchase_date": "2026-05-08", "amount": 3200, "category": "Materials", "receipt_number": "RCT-10030" } },
494
+ { key: "purchase-millbrook-carpentry-labor-and-install", values: { "room": "room-backyard-deck", "item_description": "Millbrook Carpentry \u2014 labor and install", "vendor": "Millbrook Carpentry", "purchase_date": "2026-06-01", "amount": 4900, "category": "Labor", "receipt_number": "RCT-10031" } },
495
+ { key: "purchase-design-consultation-fixture-layout", values: { "room": "room-guest-bathroom", "item_description": "Design consultation \u2014 fixture layout", "vendor": "Bianca Moretti Interiors", "purchase_date": "2026-07-30", "amount": 350, "category": "Design/Design Fees", "receipt_number": "RCT-10032" } }
496
+ ]
497
+ }
498
+ ],
499
+ relationships: [
500
+ {
501
+ describes: "A quote is for exactly one room, and it is meaningless once that room is out of scope.",
502
+ fromTable: "quotes",
503
+ fromField: "room",
504
+ toTable: "rooms",
505
+ flavor: "owned",
506
+ cardinality: "one",
507
+ onDelete: "cascade",
508
+ inverseKey: "quotes"
509
+ },
510
+ {
511
+ describes: "A quote comes from one contractor, who goes on existing after the quote is rejected.",
512
+ fromTable: "quotes",
513
+ fromField: "contractor",
514
+ toTable: "contractors",
515
+ flavor: "referenced",
516
+ cardinality: "one",
517
+ onDelete: "restrict",
518
+ inverseKey: "quotes_given"
519
+ },
520
+ {
521
+ describes: "A purchase is charged against the room it was bought for, which is how the budget stays honest.",
522
+ fromTable: "purchases",
523
+ fromField: "room",
524
+ toTable: "rooms",
525
+ flavor: "owned",
526
+ cardinality: "one",
527
+ onDelete: "cascade",
528
+ inverseKey: "purchases"
529
+ }
530
+ ],
531
+ form: {
532
+ token: "birchwood_contractor_details",
533
+ name: "Contractor details and insurance",
534
+ describes: "What a trade fills in before they are allowed to quote. It asks for the licence number and the insurance because those are the two things nobody can produce after something goes wrong.",
535
+ audience: "public",
536
+ table: "contractors",
537
+ fields: [
538
+ { fieldKey: "company_name", label: "Company name", required: true },
539
+ { fieldKey: "trade", label: "Trade", required: true },
540
+ { fieldKey: "contact_name", label: "Who should I ask for?", required: true },
541
+ { fieldKey: "phone", label: "Best number", required: true },
542
+ { fieldKey: "email", label: "Email", required: true },
543
+ { fieldKey: "license_number", label: "Licence number", required: true, help: "I check this with the state board before accepting a quote." },
544
+ { fieldKey: "insured", label: "Do you carry liability insurance?", required: true, help: "I will ask for the certificate before work starts." }
545
+ ],
546
+ submitLabel: "Send my details",
547
+ confirmation: "Thank you. I will check the licence and come back to you about which rooms I would like quoted, usually within a few days."
548
+ },
549
+ pipeline: {
550
+ token: "birchwood_room_progress",
551
+ name: "Room by room",
552
+ describes: "Where each room stands. The board exists because a whole-house renovation is really five small projects at different stages, and the only way to stay sane is to look at them side by side.",
553
+ table: "rooms",
554
+ stageField: "status",
555
+ stages: [
556
+ { key: "Planning", label: "Planning", describes: "Scope is still being decided. Nothing has been priced, so the budget figure is a guess.", typicalDurationDays: 21 },
557
+ { key: "Quoting", label: "Quoting", describes: "Trades are pricing it. Leaves when a quote is accepted \u2014 or when every quote comes back over budget and the scope goes back to Planning.", typicalDurationDays: 21 },
558
+ { key: "In Progress", label: "In progress", describes: "Work has started and receipts are landing against this room. This is where the budget is actually won or lost.", typicalDurationDays: 45 },
559
+ { key: "On Hold", label: "On hold", describes: "Stopped for money, a permit or a lead time. Named honestly so it is not mistaken for progress.", typicalDurationDays: 30 },
560
+ { key: "Complete", label: "Complete", describes: "Finished, paid and signed off. The room's spend is final and can be compared against what was budgeted." }
561
+ ]
562
+ },
563
+ dashboardQuestion: {
564
+ question: "What have I actually spent on each room so far?",
565
+ whyItMatters: "The budget was set room by room, so the only useful comparison is room by room. This is the number that decides whether the next room starts on schedule or waits, and it is the one thing a spreadsheet stops being trusted for once there are more than about thirty receipts.",
566
+ table: "purchases",
567
+ aggregate: "sum",
568
+ of: "amount",
569
+ groupBy: "room",
570
+ answerUnit: "USD"
571
+ },
572
+ documentTemplate: {
573
+ token: "birchwood_quote_acceptance",
574
+ name: "Quote acceptance",
575
+ describes: "Sent to a contractor when their price is accepted. It restates the number, the room and the date the quote was given, because a renovation dispute is almost always about which version of the price was agreed.",
576
+ table: "quotes",
577
+ title: "Accepting your quote of {{amount}}",
578
+ body: [
579
+ "Thank you for quoting.",
580
+ "",
581
+ "I am accepting your price of {{amount}}, quoted on {{quoted_on}} and valid until {{valid_until}}, for the work we discussed.",
582
+ "",
583
+ "Before anything starts I will need a copy of your certificate of insurance. Materials I have bought myself are already on site; anything else is yours to supply and appears on your invoice, not on my receipts.",
584
+ "",
585
+ "If the scope changes once the wall is open \u2014 and on a house this age it usually does \u2014 please price the change and send it to me before carrying it out. I would rather approve a second number than argue about a bigger one later.",
586
+ "",
587
+ "{{project}}",
588
+ "{{project_phone}}",
589
+ "{{today}}"
590
+ ].join("\n"),
591
+ mergeFields: [
592
+ { key: "amount", from: "quote_amount", describes: "The accepted price, restated so there is one version of it." },
593
+ { key: "quoted_on", from: "quote_date", describes: "Which quote this is, when a trade has given several." },
594
+ { key: "valid_until", from: "valid_until", describes: "The date the price was good until." },
595
+ { key: "project", from: "business", describes: "The project name." },
596
+ { key: "project_phone", from: "business", describes: "The number to call back on." },
597
+ { key: "today", from: "today", describes: "The date of acceptance." }
598
+ ]
599
+ },
600
+ notificationRule: {
601
+ token: "birchwood_quote_expiring",
602
+ name: "A quote is about to expire",
603
+ describes: "Quotes are good for thirty days and a renovation moves slower than that, so the default outcome is re-pricing everything at a worse number. A week's warning is what prevents it, and it is the first thing any homeowner would automate.",
604
+ when: {
605
+ table: "quotes",
606
+ event: "due",
607
+ field: "valid_until",
608
+ daysBefore: 7
609
+ },
610
+ audience: "the homeowner",
611
+ channel: "email",
612
+ message: "The quote of {{quote_amount}} expires on {{valid_until}} \u2014 about a week from now. Accept it, or ask for it to be held, before it has to be re-priced."
613
+ },
614
+ provenance: {
615
+ kind: "synthesized",
616
+ authoredBy: "data crew (dataset) + lane REAL-DATA (business identity, relationships, form, pipeline, dashboard question, document, notification rule)",
617
+ authoredOn: "2026-09-21",
618
+ noRealPeople: true
619
+ }
620
+ };
621
+ birchwood_avenue_renovation_budget_default = useCase2;
622
+ }
623
+ });
624
+
625
+ // src/use-cases/harbor-dental-new-patient-intake.ts
626
+ var harbor_dental_new_patient_intake_exports = {};
627
+ __export(harbor_dental_new_patient_intake_exports, {
628
+ default: () => harbor_dental_new_patient_intake_default,
629
+ useCase: () => useCase3
630
+ });
631
+ var useCase3, harbor_dental_new_patient_intake_default;
632
+ var init_harbor_dental_new_patient_intake = __esm({
633
+ "src/use-cases/harbor-dental-new-patient-intake.ts"() {
634
+ "use strict";
635
+ useCase3 = {
636
+ id: "harbor-dental-new-patient-intake",
637
+ useCase: "Renata Okonkwo runs the front desk at Harbor Dental Group, a six-chair family dental practice, and she uses this to take a new patient from the first phone call through forms, insurance verification and a booked first visit without anything falling between the cracks.",
638
+ industry: "Dentistry",
639
+ cleanupTag: "use-case:harbor-dental-new-patient-intake",
640
+ business: {
641
+ name: "Harbor Dental Group",
642
+ legalName: "Harbor Dental Group, PLLC",
643
+ describes: "A six-chair family dental practice doing general dentistry, hygiene and same-day crowns.",
644
+ address: {
645
+ line1: "1840 Waterfront Parkway",
646
+ line2: "Suite 210",
647
+ city: "Bellingham",
648
+ region: "WA",
649
+ postalCode: "98225",
650
+ country: "US"
651
+ },
652
+ phone: "+1 360 555 0142",
653
+ website: "https://harbordentalgroup.com",
654
+ email: "frontdesk@harbordentalgroup.com",
655
+ timezone: "America/Los_Angeles"
656
+ },
657
+ tables: [
658
+ {
659
+ token: "patient",
660
+ name: "Patients",
661
+ labelSingular: "Patient",
662
+ labelPlural: "Patients",
663
+ type: "entity",
664
+ display: "list",
665
+ weight: "heavy",
666
+ ordered: false,
667
+ icon: "user-round",
668
+ titleField: "full_name",
669
+ describes: "Everyone the practice treats, from the first enquiry through to an active chart.",
670
+ fields: [
671
+ {
672
+ key: "full_name",
673
+ label: "Patient name",
674
+ parityType: "text",
675
+ required: true,
676
+ sensitivity: "confidential",
677
+ contextPolicy: "summarize"
678
+ },
679
+ {
680
+ key: "chart_number",
681
+ label: "Chart number",
682
+ parityType: "text",
683
+ required: true,
684
+ sensitivity: "internal",
685
+ contextPolicy: "include",
686
+ help: "Assigned when the chart is opened. Printed on every claim and referral."
687
+ },
688
+ {
689
+ key: "date_of_birth",
690
+ label: "Date of birth",
691
+ parityType: "datetime",
692
+ format: "date",
693
+ sensitivity: "confidential",
694
+ contextPolicy: "exclude",
695
+ help: "Carriers verify eligibility on name plus date of birth, so it has to be exact."
696
+ },
697
+ {
698
+ key: "phone",
699
+ label: "Mobile phone",
700
+ parityType: "phone",
701
+ format: "phone",
702
+ sensitivity: "confidential",
703
+ contextPolicy: "exclude"
704
+ },
705
+ {
706
+ key: "email",
707
+ label: "Email",
708
+ parityType: "email",
709
+ format: "email",
710
+ sensitivity: "confidential",
711
+ contextPolicy: "exclude"
712
+ },
713
+ {
714
+ key: "street",
715
+ label: "Street address",
716
+ parityType: "text",
717
+ sensitivity: "confidential",
718
+ contextPolicy: "exclude"
719
+ },
720
+ {
721
+ key: "city",
722
+ label: "City",
723
+ parityType: "text",
724
+ sensitivity: "internal",
725
+ contextPolicy: "include"
726
+ },
727
+ {
728
+ key: "region",
729
+ label: "State",
730
+ parityType: "text",
731
+ sensitivity: "internal",
732
+ contextPolicy: "include"
733
+ },
734
+ {
735
+ key: "postal_code",
736
+ label: "ZIP",
737
+ parityType: "text",
738
+ sensitivity: "internal",
739
+ contextPolicy: "include"
740
+ },
741
+ {
742
+ key: "intake_stage",
743
+ label: "Intake stage",
744
+ parityType: "select",
745
+ required: true,
746
+ sensitivity: "internal",
747
+ contextPolicy: "include",
748
+ choices: [
749
+ "Enquiry",
750
+ "Forms sent",
751
+ "Forms received",
752
+ "Insurance verified",
753
+ "First visit booked",
754
+ "Active patient"
755
+ ],
756
+ help: "Where this person is between the first call and a chart the hygienist can work from."
757
+ },
758
+ {
759
+ key: "insurance_carrier",
760
+ label: "Insurance carrier",
761
+ parityType: "select",
762
+ sensitivity: "confidential",
763
+ contextPolicy: "summarize",
764
+ choices: ["Delta Dental", "Cigna Dental", "MetLife", "Guardian", "Aetna", "Self-pay"]
765
+ },
766
+ {
767
+ key: "member_id",
768
+ label: "Member ID",
769
+ parityType: "text",
770
+ sensitivity: "restricted",
771
+ contextPolicy: "exclude",
772
+ help: "Never leaves the practice. Needed to verify eligibility before the first visit."
773
+ },
774
+ {
775
+ key: "primary_dentist",
776
+ label: "Primary dentist",
777
+ parityType: "select",
778
+ sensitivity: "internal",
779
+ contextPolicy: "include",
780
+ choices: ["Dr. Alina Reyes", "Dr. Marcus Webb"]
781
+ },
782
+ {
783
+ key: "allergies",
784
+ label: "Known allergies",
785
+ parityType: "multi_select",
786
+ multi: true,
787
+ sensitivity: "confidential",
788
+ contextPolicy: "summarize",
789
+ choices: [
790
+ "Penicillin",
791
+ "Latex",
792
+ "Codeine",
793
+ "Sulfa drugs",
794
+ "Local anaesthetic",
795
+ "None reported"
796
+ ],
797
+ help: "Read out loud at chairside before any injection."
798
+ },
799
+ {
800
+ key: "balance_due",
801
+ label: "Balance due",
802
+ parityType: "currency",
803
+ unit: "USD",
804
+ format: "currency",
805
+ sensitivity: "confidential",
806
+ contextPolicy: "summarize"
807
+ },
808
+ {
809
+ key: "referred_by",
810
+ label: "How they found us",
811
+ parityType: "select",
812
+ sensitivity: "internal",
813
+ contextPolicy: "include",
814
+ choices: [
815
+ "Existing patient referral",
816
+ "Insurance directory",
817
+ "Web search",
818
+ "Walk-in",
819
+ "Employer benefits fair"
820
+ ]
821
+ },
822
+ {
823
+ key: "front_desk_notes",
824
+ label: "Front desk notes",
825
+ parityType: "long_text",
826
+ sensitivity: "confidential",
827
+ contextPolicy: "on_request"
828
+ }
829
+ ],
830
+ rows: [
831
+ {
832
+ key: "patient-rivera-marisol",
833
+ values: {
834
+ full_name: "Marisol Rivera",
835
+ chart_number: "HD-10428",
836
+ date_of_birth: "1988-03-17",
837
+ phone: "+1 360 555 0184",
838
+ email: "m.rivera@northshoremail.com",
839
+ street: "4417 Chuckanut Ridge Road",
840
+ city: "Bellingham",
841
+ region: "WA",
842
+ postal_code: "98229",
843
+ intake_stage: "Active patient",
844
+ insurance_carrier: "Delta Dental",
845
+ member_id: "DD-884201773",
846
+ primary_dentist: "Dr. Alina Reyes",
847
+ allergies: ["Penicillin"],
848
+ balance_due: 0,
849
+ referred_by: "Existing patient referral",
850
+ front_desk_notes: "Prefers early morning. Two children also seen here."
851
+ }
852
+ },
853
+ {
854
+ key: "patient-oyelaran-tunde",
855
+ values: {
856
+ full_name: "Tunde Oyelaran",
857
+ chart_number: "HD-10431",
858
+ date_of_birth: "1975-11-02",
859
+ phone: "+1 360 555 0219",
860
+ email: "toyelaran@baysidedesignco.com",
861
+ street: "902 Eldridge Avenue",
862
+ city: "Bellingham",
863
+ region: "WA",
864
+ postal_code: "98225",
865
+ intake_stage: "Active patient",
866
+ insurance_carrier: "Cigna Dental",
867
+ member_id: "CG-4471209",
868
+ primary_dentist: "Dr. Marcus Webb",
869
+ allergies: ["None reported"],
870
+ balance_due: 142.5,
871
+ referred_by: "Insurance directory",
872
+ front_desk_notes: "Travels for work; wants visits batched into one afternoon."
873
+ }
874
+ },
875
+ {
876
+ key: "patient-halvorsen-britt",
877
+ values: {
878
+ full_name: "Britt Halvorsen",
879
+ chart_number: "HD-10455",
880
+ date_of_birth: "1992-07-26",
881
+ phone: "+1 360 555 0177",
882
+ email: "britt.halvorsen@cascadiaoutfitters.com",
883
+ street: "215 Harris Avenue",
884
+ city: "Bellingham",
885
+ region: "WA",
886
+ postal_code: "98225",
887
+ intake_stage: "First visit booked",
888
+ insurance_carrier: "MetLife",
889
+ member_id: "ML-63902118",
890
+ primary_dentist: "Dr. Alina Reyes",
891
+ allergies: ["Latex"],
892
+ balance_due: 0,
893
+ referred_by: "Web search",
894
+ front_desk_notes: "Latex allergy flagged to the back office; nitrile only."
895
+ }
896
+ },
897
+ {
898
+ key: "patient-nakamura-kenji",
899
+ values: {
900
+ full_name: "Kenji Nakamura",
901
+ chart_number: "HD-10460",
902
+ date_of_birth: "1964-01-09",
903
+ phone: "+1 360 555 0263",
904
+ email: "k.nakamura@harborviewcpa.com",
905
+ street: "1130 Yew Street",
906
+ city: "Bellingham",
907
+ region: "WA",
908
+ postal_code: "98229",
909
+ intake_stage: "Insurance verified",
910
+ insurance_carrier: "Guardian",
911
+ member_id: "GD-20117744",
912
+ primary_dentist: "Dr. Marcus Webb",
913
+ allergies: ["Codeine"],
914
+ balance_due: 0,
915
+ referred_by: "Employer benefits fair",
916
+ front_desk_notes: "Eligibility confirmed through December. Waiting on his schedule to book."
917
+ }
918
+ },
919
+ {
920
+ key: "patient-abadi-leila",
921
+ values: {
922
+ full_name: "Leila Abadi",
923
+ chart_number: "HD-10462",
924
+ date_of_birth: "1997-05-30",
925
+ phone: "+1 360 555 0308",
926
+ email: "leila.abadi@westwindstudio.com",
927
+ street: "77 Fairhaven Parkway",
928
+ city: "Bellingham",
929
+ region: "WA",
930
+ postal_code: "98225",
931
+ intake_stage: "Forms received",
932
+ insurance_carrier: "Aetna",
933
+ member_id: "AE-55823094",
934
+ primary_dentist: "Dr. Alina Reyes",
935
+ allergies: ["None reported"],
936
+ balance_due: 0,
937
+ referred_by: "Existing patient referral",
938
+ front_desk_notes: "Forms in. Needs eligibility checked before we offer a slot."
939
+ }
940
+ },
941
+ {
942
+ key: "patient-delacroix-yvon",
943
+ values: {
944
+ full_name: "Yvon Delacroix",
945
+ chart_number: "HD-10466",
946
+ date_of_birth: "1981-09-14",
947
+ phone: "+1 360 555 0341",
948
+ email: "yvon.delacroix@pugetsoundfreight.com",
949
+ street: "3320 Northwest Avenue",
950
+ city: "Bellingham",
951
+ region: "WA",
952
+ postal_code: "98225",
953
+ intake_stage: "Forms sent",
954
+ insurance_carrier: "Delta Dental",
955
+ member_id: "DD-884977120",
956
+ primary_dentist: "Dr. Marcus Webb",
957
+ allergies: ["None reported"],
958
+ balance_due: 0,
959
+ referred_by: "Insurance directory",
960
+ front_desk_notes: "Packet emailed Tuesday. Follow up if nothing back by Friday."
961
+ }
962
+ },
963
+ {
964
+ key: "patient-strand-ingrid",
965
+ values: {
966
+ full_name: "Ingrid Strand",
967
+ chart_number: "HD-10470",
968
+ date_of_birth: "1955-12-04",
969
+ phone: "+1 360 555 0392",
970
+ email: "ingrid.strand@northshoremail.com",
971
+ street: "618 Alabama Street",
972
+ city: "Bellingham",
973
+ region: "WA",
974
+ postal_code: "98225",
975
+ intake_stage: "Active patient",
976
+ insurance_carrier: "Self-pay",
977
+ member_id: "",
978
+ primary_dentist: "Dr. Alina Reyes",
979
+ allergies: ["Sulfa drugs", "Local anaesthetic"],
980
+ balance_due: 880,
981
+ referred_by: "Walk-in",
982
+ front_desk_notes: "On a payment plan for the crown. Anaesthetic sensitivity \u2014 Dr. Reyes is aware."
983
+ }
984
+ },
985
+ {
986
+ key: "patient-mbeki-sipho",
987
+ values: {
988
+ full_name: "Sipho Mbeki",
989
+ chart_number: "HD-10473",
990
+ date_of_birth: "2001-02-21",
991
+ phone: "+1 360 555 0415",
992
+ email: "sipho.mbeki@wwu-alumni.com",
993
+ street: "1502 Indian Street",
994
+ city: "Bellingham",
995
+ region: "WA",
996
+ postal_code: "98225",
997
+ intake_stage: "Enquiry",
998
+ insurance_carrier: "Self-pay",
999
+ member_id: "",
1000
+ primary_dentist: "Dr. Marcus Webb",
1001
+ allergies: ["None reported"],
1002
+ balance_due: 0,
1003
+ referred_by: "Web search",
1004
+ front_desk_notes: "Called about a chipped incisor. Quoted the emergency exam fee."
1005
+ }
1006
+ },
1007
+ {
1008
+ key: "patient-kowalczyk-agata",
1009
+ values: {
1010
+ full_name: "Agata Kowalczyk",
1011
+ chart_number: "HD-10477",
1012
+ date_of_birth: "1986-06-11",
1013
+ phone: "+1 360 555 0448",
1014
+ email: "a.kowalczyk@evergreenlabsupply.com",
1015
+ street: "2245 Cornwall Avenue",
1016
+ city: "Bellingham",
1017
+ region: "WA",
1018
+ postal_code: "98225",
1019
+ intake_stage: "Active patient",
1020
+ insurance_carrier: "Cigna Dental",
1021
+ member_id: "CG-4488317",
1022
+ primary_dentist: "Dr. Alina Reyes",
1023
+ allergies: ["None reported"],
1024
+ balance_due: 64,
1025
+ referred_by: "Existing patient referral",
1026
+ front_desk_notes: "Night guard impressions taken; lab case out."
1027
+ }
1028
+ },
1029
+ {
1030
+ key: "patient-ferreira-joao",
1031
+ values: {
1032
+ full_name: "Jo\xE3o Ferreira",
1033
+ chart_number: "HD-10481",
1034
+ date_of_birth: "1970-08-19",
1035
+ phone: "+1 360 555 0472",
1036
+ email: "joao.ferreira@harborlinemarine.com",
1037
+ street: "840 Marine Drive",
1038
+ city: "Bellingham",
1039
+ region: "WA",
1040
+ postal_code: "98225",
1041
+ intake_stage: "Insurance verified",
1042
+ insurance_carrier: "MetLife",
1043
+ member_id: "ML-63988402",
1044
+ primary_dentist: "Dr. Marcus Webb",
1045
+ allergies: ["Penicillin", "Latex"],
1046
+ balance_due: 0,
1047
+ referred_by: "Employer benefits fair",
1048
+ front_desk_notes: "Two allergies on file. Wants the first available Thursday."
1049
+ }
1050
+ },
1051
+ {
1052
+ key: "patient-whitehorse-dara",
1053
+ values: {
1054
+ full_name: "Dara Whitehorse",
1055
+ chart_number: "HD-10484",
1056
+ date_of_birth: "1994-04-07",
1057
+ phone: "+1 360 555 0501",
1058
+ email: "dara.whitehorse@salishseaarts.com",
1059
+ street: "506 Girard Street",
1060
+ city: "Bellingham",
1061
+ region: "WA",
1062
+ postal_code: "98225",
1063
+ intake_stage: "First visit booked",
1064
+ insurance_carrier: "Guardian",
1065
+ member_id: "GD-20166018",
1066
+ primary_dentist: "Dr. Alina Reyes",
1067
+ allergies: ["None reported"],
1068
+ balance_due: 0,
1069
+ referred_by: "Web search",
1070
+ front_desk_notes: "Booked for the new patient exam and a cleaning back to back."
1071
+ }
1072
+ },
1073
+ {
1074
+ key: "patient-oconnell-brigid",
1075
+ values: {
1076
+ full_name: "Brigid O'Connell",
1077
+ chart_number: "HD-10489",
1078
+ date_of_birth: "1959-10-23",
1079
+ phone: "+1 360 555 0533",
1080
+ email: "brigid.oconnell@northshoremail.com",
1081
+ street: "3901 Sunset Drive",
1082
+ city: "Bellingham",
1083
+ region: "WA",
1084
+ postal_code: "98229",
1085
+ intake_stage: "Active patient",
1086
+ insurance_carrier: "Delta Dental",
1087
+ member_id: "DD-885013366",
1088
+ primary_dentist: "Dr. Marcus Webb",
1089
+ allergies: ["Codeine"],
1090
+ balance_due: 310.75,
1091
+ referred_by: "Existing patient referral",
1092
+ front_desk_notes: "Crown seat next month. Balance is the patient portion from the last claim."
1093
+ }
1094
+ },
1095
+ {
1096
+ key: "patient-tran-hieu",
1097
+ values: {
1098
+ full_name: "Hieu Tran",
1099
+ chart_number: "HD-10492",
1100
+ date_of_birth: "1990-12-15",
1101
+ phone: "+1 360 555 0566",
1102
+ email: "hieu.tran@baysidedesignco.com",
1103
+ street: "1215 Lakeway Drive",
1104
+ city: "Bellingham",
1105
+ region: "WA",
1106
+ postal_code: "98229",
1107
+ intake_stage: "Forms received",
1108
+ insurance_carrier: "Aetna",
1109
+ member_id: "AE-55901287",
1110
+ primary_dentist: "Dr. Alina Reyes",
1111
+ allergies: ["None reported"],
1112
+ balance_due: 0,
1113
+ referred_by: "Insurance directory",
1114
+ front_desk_notes: "Medical history mentions a heart murmur \u2014 confirm premedication with Dr. Reyes."
1115
+ }
1116
+ },
1117
+ {
1118
+ key: "patient-bergstrom-annika",
1119
+ values: {
1120
+ full_name: "Annika Bergstr\xF6m",
1121
+ chart_number: "HD-10496",
1122
+ date_of_birth: "1983-02-08",
1123
+ phone: "+1 360 555 0590",
1124
+ email: "annika.bergstrom@cascadiaoutfitters.com",
1125
+ street: "705 Samish Way",
1126
+ city: "Bellingham",
1127
+ region: "WA",
1128
+ postal_code: "98225",
1129
+ intake_stage: "Enquiry",
1130
+ insurance_carrier: "Cigna Dental",
1131
+ member_id: "CG-4491550",
1132
+ primary_dentist: "Dr. Marcus Webb",
1133
+ allergies: ["None reported"],
1134
+ balance_due: 0,
1135
+ referred_by: "Walk-in",
1136
+ front_desk_notes: "Came in over lunch asking about whitening. Packet not sent yet."
1137
+ }
1138
+ }
1139
+ ]
1140
+ },
1141
+ {
1142
+ token: "visit",
1143
+ name: "Visits",
1144
+ labelSingular: "Visit",
1145
+ labelPlural: "Visits",
1146
+ type: "entity",
1147
+ display: "calendar",
1148
+ weight: "heavy",
1149
+ ordered: true,
1150
+ icon: "calendar-clock",
1151
+ titleField: "summary",
1152
+ describes: "Every booked chair appointment, what it is for, who is in the chair and who is treating.",
1153
+ fields: [
1154
+ {
1155
+ key: "summary",
1156
+ label: "Appointment",
1157
+ parityType: "text",
1158
+ required: true,
1159
+ sensitivity: "internal",
1160
+ contextPolicy: "include"
1161
+ },
1162
+ {
1163
+ key: "patient",
1164
+ label: "Patient",
1165
+ parityType: "relation",
1166
+ required: true,
1167
+ relationTarget: "patient",
1168
+ relationMax: 1,
1169
+ sensitivity: "confidential",
1170
+ contextPolicy: "summarize"
1171
+ },
1172
+ {
1173
+ key: "appointment_at",
1174
+ label: "Date and time",
1175
+ parityType: "datetime",
1176
+ required: true,
1177
+ sensitivity: "internal",
1178
+ contextPolicy: "include"
1179
+ },
1180
+ {
1181
+ key: "duration_minutes",
1182
+ label: "Chair time",
1183
+ parityType: "integer",
1184
+ unit: "min",
1185
+ sensitivity: "internal",
1186
+ contextPolicy: "include"
1187
+ },
1188
+ {
1189
+ key: "procedure",
1190
+ label: "Procedure",
1191
+ parityType: "select",
1192
+ sensitivity: "confidential",
1193
+ contextPolicy: "summarize",
1194
+ choices: [
1195
+ "New patient exam",
1196
+ "Adult prophylaxis",
1197
+ "Child prophylaxis",
1198
+ "Composite filling",
1199
+ "Crown preparation",
1200
+ "Crown seat",
1201
+ "Root canal",
1202
+ "Extraction",
1203
+ "Emergency exam"
1204
+ ]
1205
+ },
1206
+ {
1207
+ key: "provider",
1208
+ label: "Provider",
1209
+ parityType: "select",
1210
+ sensitivity: "internal",
1211
+ contextPolicy: "include",
1212
+ choices: [
1213
+ "Dr. Alina Reyes",
1214
+ "Dr. Marcus Webb",
1215
+ "Priya Chandra, RDH",
1216
+ "Tomas Lindgren, RDH"
1217
+ ]
1218
+ },
1219
+ {
1220
+ key: "operatory",
1221
+ label: "Operatory",
1222
+ parityType: "select",
1223
+ sensitivity: "internal",
1224
+ contextPolicy: "include",
1225
+ choices: ["Op A", "Op B", "Op C", "Op D", "Op E", "Op F"]
1226
+ },
1227
+ {
1228
+ key: "visit_status",
1229
+ label: "Status",
1230
+ parityType: "select",
1231
+ required: true,
1232
+ sensitivity: "internal",
1233
+ contextPolicy: "include",
1234
+ choices: ["Scheduled", "Confirmed", "Checked in", "Completed", "No-show", "Cancelled"]
1235
+ },
1236
+ {
1237
+ key: "fee",
1238
+ label: "Fee",
1239
+ parityType: "currency",
1240
+ unit: "USD",
1241
+ format: "currency",
1242
+ sensitivity: "confidential",
1243
+ contextPolicy: "summarize"
1244
+ }
1245
+ ],
1246
+ rows: [
1247
+ {
1248
+ key: "visit-rivera-prophy-sep",
1249
+ values: {
1250
+ summary: "Adult cleaning \u2014 M. Rivera",
1251
+ patient: "patient-rivera-marisol",
1252
+ appointment_at: "2026-09-08T08:00:00-07:00",
1253
+ duration_minutes: 50,
1254
+ procedure: "Adult prophylaxis",
1255
+ provider: "Priya Chandra, RDH",
1256
+ operatory: "Op B",
1257
+ visit_status: "Completed",
1258
+ fee: 138
1259
+ }
1260
+ },
1261
+ {
1262
+ key: "visit-oyelaran-crown-prep",
1263
+ values: {
1264
+ summary: "Crown prep, lower right \u2014 T. Oyelaran",
1265
+ patient: "patient-oyelaran-tunde",
1266
+ appointment_at: "2026-09-10T13:30:00-07:00",
1267
+ duration_minutes: 90,
1268
+ procedure: "Crown preparation",
1269
+ provider: "Dr. Marcus Webb",
1270
+ operatory: "Op D",
1271
+ visit_status: "Completed",
1272
+ fee: 1240
1273
+ }
1274
+ },
1275
+ {
1276
+ key: "visit-strand-crown-seat",
1277
+ values: {
1278
+ summary: "Crown seat \u2014 I. Strand",
1279
+ patient: "patient-strand-ingrid",
1280
+ appointment_at: "2026-09-14T10:00:00-07:00",
1281
+ duration_minutes: 60,
1282
+ procedure: "Crown seat",
1283
+ provider: "Dr. Alina Reyes",
1284
+ operatory: "Op A",
1285
+ visit_status: "Completed",
1286
+ fee: 880
1287
+ }
1288
+ },
1289
+ {
1290
+ key: "visit-kowalczyk-prophy",
1291
+ values: {
1292
+ summary: "Adult cleaning \u2014 A. Kowalczyk",
1293
+ patient: "patient-kowalczyk-agata",
1294
+ appointment_at: "2026-09-15T09:00:00-07:00",
1295
+ duration_minutes: 50,
1296
+ procedure: "Adult prophylaxis",
1297
+ provider: "Tomas Lindgren, RDH",
1298
+ operatory: "Op C",
1299
+ visit_status: "Completed",
1300
+ fee: 138
1301
+ }
1302
+ },
1303
+ {
1304
+ key: "visit-oconnell-filling",
1305
+ values: {
1306
+ summary: "Composite filling, upper left \u2014 B. O'Connell",
1307
+ patient: "patient-oconnell-brigid",
1308
+ appointment_at: "2026-09-16T14:00:00-07:00",
1309
+ duration_minutes: 60,
1310
+ procedure: "Composite filling",
1311
+ provider: "Dr. Marcus Webb",
1312
+ operatory: "Op D",
1313
+ visit_status: "Completed",
1314
+ fee: 412
1315
+ }
1316
+ },
1317
+ {
1318
+ key: "visit-mbeki-emergency",
1319
+ values: {
1320
+ summary: "Emergency exam, chipped incisor \u2014 S. Mbeki",
1321
+ patient: "patient-mbeki-sipho",
1322
+ appointment_at: "2026-09-17T16:30:00-07:00",
1323
+ duration_minutes: 30,
1324
+ procedure: "Emergency exam",
1325
+ provider: "Dr. Marcus Webb",
1326
+ operatory: "Op E",
1327
+ visit_status: "No-show",
1328
+ fee: 95
1329
+ }
1330
+ },
1331
+ {
1332
+ key: "visit-rivera-filling",
1333
+ values: {
1334
+ summary: "Composite filling, lower left \u2014 M. Rivera",
1335
+ patient: "patient-rivera-marisol",
1336
+ appointment_at: "2026-09-18T08:30:00-07:00",
1337
+ duration_minutes: 60,
1338
+ procedure: "Composite filling",
1339
+ provider: "Dr. Alina Reyes",
1340
+ operatory: "Op A",
1341
+ visit_status: "Completed",
1342
+ fee: 386
1343
+ }
1344
+ },
1345
+ {
1346
+ key: "visit-halvorsen-new-patient",
1347
+ values: {
1348
+ summary: "New patient exam \u2014 B. Halvorsen",
1349
+ patient: "patient-halvorsen-britt",
1350
+ appointment_at: "2026-09-23T09:00:00-07:00",
1351
+ duration_minutes: 60,
1352
+ procedure: "New patient exam",
1353
+ provider: "Dr. Alina Reyes",
1354
+ operatory: "Op A",
1355
+ visit_status: "Confirmed",
1356
+ fee: 215
1357
+ }
1358
+ },
1359
+ {
1360
+ key: "visit-halvorsen-prophy",
1361
+ values: {
1362
+ summary: "Adult cleaning \u2014 B. Halvorsen",
1363
+ patient: "patient-halvorsen-britt",
1364
+ appointment_at: "2026-09-23T10:00:00-07:00",
1365
+ duration_minutes: 50,
1366
+ procedure: "Adult prophylaxis",
1367
+ provider: "Priya Chandra, RDH",
1368
+ operatory: "Op B",
1369
+ visit_status: "Confirmed",
1370
+ fee: 138
1371
+ }
1372
+ },
1373
+ {
1374
+ key: "visit-whitehorse-new-patient",
1375
+ values: {
1376
+ summary: "New patient exam \u2014 D. Whitehorse",
1377
+ patient: "patient-whitehorse-dara",
1378
+ appointment_at: "2026-09-24T11:00:00-07:00",
1379
+ duration_minutes: 60,
1380
+ procedure: "New patient exam",
1381
+ provider: "Dr. Alina Reyes",
1382
+ operatory: "Op A",
1383
+ visit_status: "Scheduled",
1384
+ fee: 215
1385
+ }
1386
+ },
1387
+ {
1388
+ key: "visit-whitehorse-prophy",
1389
+ values: {
1390
+ summary: "Adult cleaning \u2014 D. Whitehorse",
1391
+ patient: "patient-whitehorse-dara",
1392
+ appointment_at: "2026-09-24T12:00:00-07:00",
1393
+ duration_minutes: 50,
1394
+ procedure: "Adult prophylaxis",
1395
+ provider: "Tomas Lindgren, RDH",
1396
+ operatory: "Op C",
1397
+ visit_status: "Scheduled",
1398
+ fee: 138
1399
+ }
1400
+ },
1401
+ {
1402
+ key: "visit-oconnell-crown-seat",
1403
+ values: {
1404
+ summary: "Crown seat \u2014 B. O'Connell",
1405
+ patient: "patient-oconnell-brigid",
1406
+ appointment_at: "2026-10-06T14:30:00-07:00",
1407
+ duration_minutes: 60,
1408
+ procedure: "Crown seat",
1409
+ provider: "Dr. Marcus Webb",
1410
+ operatory: "Op D",
1411
+ visit_status: "Scheduled",
1412
+ fee: 1180
1413
+ }
1414
+ },
1415
+ {
1416
+ key: "visit-ferreira-new-patient",
1417
+ values: {
1418
+ summary: "New patient exam \u2014 J. Ferreira",
1419
+ patient: "patient-ferreira-joao",
1420
+ appointment_at: "2026-10-08T15:00:00-07:00",
1421
+ duration_minutes: 60,
1422
+ procedure: "New patient exam",
1423
+ provider: "Dr. Marcus Webb",
1424
+ operatory: "Op E",
1425
+ visit_status: "Scheduled",
1426
+ fee: 215
1427
+ }
1428
+ },
1429
+ {
1430
+ key: "visit-nakamura-new-patient",
1431
+ values: {
1432
+ summary: "New patient exam \u2014 K. Nakamura",
1433
+ patient: "patient-nakamura-kenji",
1434
+ appointment_at: "2026-10-09T08:30:00-07:00",
1435
+ duration_minutes: 60,
1436
+ procedure: "New patient exam",
1437
+ provider: "Dr. Marcus Webb",
1438
+ operatory: "Op D",
1439
+ visit_status: "Scheduled",
1440
+ fee: 215
1441
+ }
1442
+ },
1443
+ {
1444
+ key: "visit-tran-child-prophy",
1445
+ values: {
1446
+ summary: "Child cleaning \u2014 H. Tran, daughter",
1447
+ patient: "patient-tran-hieu",
1448
+ appointment_at: "2026-10-13T16:00:00-07:00",
1449
+ duration_minutes: 40,
1450
+ procedure: "Child prophylaxis",
1451
+ provider: "Priya Chandra, RDH",
1452
+ operatory: "Op B",
1453
+ visit_status: "Scheduled",
1454
+ fee: 112
1455
+ }
1456
+ },
1457
+ {
1458
+ key: "visit-kowalczyk-cancelled",
1459
+ values: {
1460
+ summary: "Night guard delivery \u2014 A. Kowalczyk",
1461
+ patient: "patient-kowalczyk-agata",
1462
+ appointment_at: "2026-09-19T11:30:00-07:00",
1463
+ duration_minutes: 30,
1464
+ procedure: "Adult prophylaxis",
1465
+ provider: "Tomas Lindgren, RDH",
1466
+ operatory: "Op C",
1467
+ visit_status: "Cancelled",
1468
+ fee: 0
1469
+ }
1470
+ }
1471
+ ]
1472
+ },
1473
+ {
1474
+ token: "insurance_claim",
1475
+ name: "Insurance claims",
1476
+ labelSingular: "Claim",
1477
+ labelPlural: "Claims",
1478
+ type: "ledger",
1479
+ display: "list",
1480
+ weight: "heavy",
1481
+ ordered: false,
1482
+ icon: "file-text",
1483
+ titleField: "claim_number",
1484
+ describes: "What was billed to a carrier for a completed visit, and what came back.",
1485
+ fields: [
1486
+ {
1487
+ key: "claim_number",
1488
+ label: "Claim number",
1489
+ parityType: "text",
1490
+ required: true,
1491
+ sensitivity: "internal",
1492
+ contextPolicy: "include"
1493
+ },
1494
+ {
1495
+ key: "visit",
1496
+ label: "Visit",
1497
+ parityType: "relation",
1498
+ required: true,
1499
+ relationTarget: "visit",
1500
+ relationMax: 1,
1501
+ sensitivity: "confidential",
1502
+ contextPolicy: "summarize"
1503
+ },
1504
+ {
1505
+ key: "carrier",
1506
+ label: "Carrier",
1507
+ parityType: "select",
1508
+ sensitivity: "internal",
1509
+ contextPolicy: "include",
1510
+ choices: ["Delta Dental", "Cigna Dental", "MetLife", "Guardian", "Aetna"]
1511
+ },
1512
+ {
1513
+ key: "submitted_on",
1514
+ label: "Submitted",
1515
+ parityType: "datetime",
1516
+ format: "date",
1517
+ sensitivity: "internal",
1518
+ contextPolicy: "include"
1519
+ },
1520
+ {
1521
+ key: "billed_amount",
1522
+ label: "Billed",
1523
+ parityType: "currency",
1524
+ unit: "USD",
1525
+ format: "currency",
1526
+ sensitivity: "confidential",
1527
+ contextPolicy: "summarize"
1528
+ },
1529
+ {
1530
+ key: "allowed_amount",
1531
+ label: "Carrier allowed",
1532
+ parityType: "currency",
1533
+ unit: "USD",
1534
+ format: "currency",
1535
+ sensitivity: "confidential",
1536
+ contextPolicy: "summarize"
1537
+ },
1538
+ {
1539
+ key: "patient_portion",
1540
+ label: "Patient portion",
1541
+ parityType: "currency",
1542
+ unit: "USD",
1543
+ format: "currency",
1544
+ sensitivity: "confidential",
1545
+ contextPolicy: "summarize"
1546
+ },
1547
+ {
1548
+ key: "claim_status",
1549
+ label: "Claim status",
1550
+ parityType: "select",
1551
+ required: true,
1552
+ sensitivity: "internal",
1553
+ contextPolicy: "include",
1554
+ choices: ["Prepared", "Submitted", "In review", "Paid", "Denied", "Appealed"]
1555
+ }
1556
+ ],
1557
+ rows: [
1558
+ {
1559
+ key: "claim-rivera-prophy",
1560
+ values: {
1561
+ claim_number: "HD-CLM-24118",
1562
+ visit: "visit-rivera-prophy-sep",
1563
+ carrier: "Delta Dental",
1564
+ submitted_on: "2026-09-09",
1565
+ billed_amount: 138,
1566
+ allowed_amount: 138,
1567
+ patient_portion: 0,
1568
+ claim_status: "Paid"
1569
+ }
1570
+ },
1571
+ {
1572
+ key: "claim-oyelaran-crown-prep",
1573
+ values: {
1574
+ claim_number: "HD-CLM-24123",
1575
+ visit: "visit-oyelaran-crown-prep",
1576
+ carrier: "Cigna Dental",
1577
+ submitted_on: "2026-09-11",
1578
+ billed_amount: 1240,
1579
+ allowed_amount: 1097.5,
1580
+ patient_portion: 142.5,
1581
+ claim_status: "Paid"
1582
+ }
1583
+ },
1584
+ {
1585
+ key: "claim-kowalczyk-prophy",
1586
+ values: {
1587
+ claim_number: "HD-CLM-24131",
1588
+ visit: "visit-kowalczyk-prophy",
1589
+ carrier: "Cigna Dental",
1590
+ submitted_on: "2026-09-16",
1591
+ billed_amount: 138,
1592
+ allowed_amount: 74,
1593
+ patient_portion: 64,
1594
+ claim_status: "Paid"
1595
+ }
1596
+ },
1597
+ {
1598
+ key: "claim-oconnell-filling",
1599
+ values: {
1600
+ claim_number: "HD-CLM-24136",
1601
+ visit: "visit-oconnell-filling",
1602
+ carrier: "Delta Dental",
1603
+ submitted_on: "2026-09-17",
1604
+ billed_amount: 412,
1605
+ allowed_amount: 310.75,
1606
+ patient_portion: 310.75,
1607
+ claim_status: "In review"
1608
+ }
1609
+ },
1610
+ {
1611
+ key: "claim-rivera-filling",
1612
+ values: {
1613
+ claim_number: "HD-CLM-24140",
1614
+ visit: "visit-rivera-filling",
1615
+ carrier: "Delta Dental",
1616
+ submitted_on: "2026-09-19",
1617
+ billed_amount: 386,
1618
+ allowed_amount: 386,
1619
+ patient_portion: 0,
1620
+ claim_status: "Submitted"
1621
+ }
1622
+ },
1623
+ {
1624
+ key: "claim-strand-crown-seat",
1625
+ values: {
1626
+ claim_number: "HD-CLM-24127",
1627
+ visit: "visit-strand-crown-seat",
1628
+ carrier: "Delta Dental",
1629
+ submitted_on: "2026-09-15",
1630
+ billed_amount: 880,
1631
+ allowed_amount: 0,
1632
+ patient_portion: 880,
1633
+ claim_status: "Denied"
1634
+ }
1635
+ },
1636
+ {
1637
+ key: "claim-oyelaran-resubmit",
1638
+ values: {
1639
+ claim_number: "HD-CLM-24144",
1640
+ visit: "visit-oyelaran-crown-prep",
1641
+ carrier: "Cigna Dental",
1642
+ submitted_on: "2026-09-20",
1643
+ billed_amount: 142.5,
1644
+ allowed_amount: 0,
1645
+ patient_portion: 142.5,
1646
+ claim_status: "Appealed"
1647
+ }
1648
+ },
1649
+ {
1650
+ key: "claim-oconnell-crown-predetermination",
1651
+ values: {
1652
+ claim_number: "HD-CLM-24149",
1653
+ visit: "visit-oconnell-crown-seat",
1654
+ carrier: "Delta Dental",
1655
+ submitted_on: "2026-09-21",
1656
+ billed_amount: 1180,
1657
+ allowed_amount: 0,
1658
+ patient_portion: 0,
1659
+ claim_status: "Prepared"
1660
+ }
1661
+ }
1662
+ ]
1663
+ }
1664
+ ],
1665
+ relationships: [
1666
+ {
1667
+ describes: "A visit belongs to the patient who sits in the chair, and it dies with their chart.",
1668
+ fromTable: "visit",
1669
+ fromField: "patient",
1670
+ toTable: "patient",
1671
+ flavor: "owned",
1672
+ cardinality: "one",
1673
+ onDelete: "cascade",
1674
+ inverseKey: "visits"
1675
+ },
1676
+ {
1677
+ describes: "A claim bills exactly one completed visit, and it cannot outlive the visit it bills.",
1678
+ fromTable: "insurance_claim",
1679
+ fromField: "visit",
1680
+ toTable: "visit",
1681
+ flavor: "owned",
1682
+ cardinality: "one",
1683
+ onDelete: "cascade",
1684
+ inverseKey: "claims"
1685
+ }
1686
+ ],
1687
+ form: {
1688
+ token: "harbor_dental_new_patient_intake",
1689
+ name: "Harbor Dental new-patient intake",
1690
+ describes: "The packet the front desk emails after the first call. The patient fills it in before they arrive so the hygienist is not taking a medical history in the chair.",
1691
+ audience: "public",
1692
+ table: "patient",
1693
+ fields: [
1694
+ { fieldKey: "full_name", label: "Your full legal name", required: true, help: "As it appears on your insurance card." },
1695
+ { fieldKey: "date_of_birth", label: "Date of birth", required: true },
1696
+ { fieldKey: "phone", label: "Mobile number", required: true, help: "We text appointment reminders to this number." },
1697
+ { fieldKey: "email", label: "Email", required: true },
1698
+ { fieldKey: "street", label: "Street address", required: true },
1699
+ { fieldKey: "city", label: "City", required: true },
1700
+ { fieldKey: "region", label: "State", required: true },
1701
+ { fieldKey: "postal_code", label: "ZIP", required: true },
1702
+ { fieldKey: "insurance_carrier", label: "Dental insurance carrier", help: "Choose Self-pay if you do not have dental coverage." },
1703
+ { fieldKey: "member_id", label: "Member ID", help: "On the front of your card. We use it to check your benefits before your visit." },
1704
+ { fieldKey: "allergies", label: "Any known allergies", help: "Select all that apply. We read this out before any injection." },
1705
+ { fieldKey: "referred_by", label: "How did you hear about us?" }
1706
+ ],
1707
+ submitLabel: "Send my intake form",
1708
+ confirmation: "Thank you \u2014 we have your forms. We will check your benefits with your carrier and call you within two business days to find a first appointment that works."
1709
+ },
1710
+ pipeline: {
1711
+ token: "harbor_dental_intake_pipeline",
1712
+ name: "New-patient intake",
1713
+ describes: "The six steps between a stranger calling and a chart the hygienist can work from. Renata works this board every morning.",
1714
+ table: "patient",
1715
+ stageField: "intake_stage",
1716
+ stages: [
1717
+ {
1718
+ key: "Enquiry",
1719
+ label: "Enquiry",
1720
+ describes: "They called or walked in. Nothing has been sent yet. Moves on when the intake packet goes out.",
1721
+ typicalDurationDays: 1
1722
+ },
1723
+ {
1724
+ key: "Forms sent",
1725
+ label: "Forms sent",
1726
+ describes: "The packet is with them. Chase at three days; most people fill it in the evening they get it.",
1727
+ typicalDurationDays: 3
1728
+ },
1729
+ {
1730
+ key: "Forms received",
1731
+ label: "Forms received",
1732
+ describes: "Medical history is in. Anything flagged goes to the treating dentist before we book.",
1733
+ typicalDurationDays: 1
1734
+ },
1735
+ {
1736
+ key: "Insurance verified",
1737
+ label: "Insurance verified",
1738
+ describes: "Eligibility and remaining annual maximum confirmed with the carrier, so nobody is surprised by a bill.",
1739
+ typicalDurationDays: 2
1740
+ },
1741
+ {
1742
+ key: "First visit booked",
1743
+ label: "First visit booked",
1744
+ describes: "Exam and cleaning are on the schedule and confirmed. Moves on the day they are seen.",
1745
+ typicalDurationDays: 14
1746
+ },
1747
+ {
1748
+ key: "Active patient",
1749
+ label: "Active patient",
1750
+ describes: "Seen at least once and on recall. They leave this stage only if they transfer out."
1751
+ }
1752
+ ]
1753
+ },
1754
+ dashboardQuestion: {
1755
+ question: "How many people have sent their forms back but still are not on the schedule?",
1756
+ whyItMatters: "Everyone sitting between 'Forms received' and 'First visit booked' is someone who already chose us and is quietly going cold. If the number climbs above about six, Renata blocks an hour to call them before the week gets away.",
1757
+ table: "patient",
1758
+ aggregate: "count",
1759
+ groupBy: "intake_stage",
1760
+ filter: "intake_stage is 'Forms received' or 'Insurance verified'",
1761
+ answerUnit: "patients"
1762
+ },
1763
+ documentTemplate: {
1764
+ token: "harbor_dental_welcome_letter",
1765
+ name: "New patient welcome letter",
1766
+ describes: "Goes out the moment a first visit is booked. It confirms who they will see, what to bring and what the first appointment actually involves, which is the single biggest reason people no-show.",
1767
+ table: "patient",
1768
+ title: "Welcome to {{practice_name}}, {{patient_name}}",
1769
+ body: [
1770
+ "Dear {{patient_name}},",
1771
+ "",
1772
+ "Thank you for choosing {{practice_name}}. Your chart is open under number {{chart_number}} and you will be seeing {{dentist}}.",
1773
+ "",
1774
+ "Your first appointment is a full examination with digital x-rays, followed by a cleaning with one of our hygienists. Together they take about two hours, so please allow for that.",
1775
+ "",
1776
+ "Please bring a photo ID and your {{carrier}} card. We have already checked your benefits, so we can tell you what is covered before any work is agreed \u2014 we do not start treatment you have not said yes to.",
1777
+ "",
1778
+ "If anything about your health has changed since you filled in your forms, tell the front desk when you arrive. It matters more than people expect.",
1779
+ "",
1780
+ "We look forward to meeting you.",
1781
+ "",
1782
+ "{{practice_name}}",
1783
+ "{{practice_phone}}",
1784
+ "{{today}}"
1785
+ ].join("\n"),
1786
+ mergeFields: [
1787
+ { key: "patient_name", from: "full_name", describes: "How we address them in the letter." },
1788
+ { key: "chart_number", from: "chart_number", describes: "So the letter and the chart agree if they call about it." },
1789
+ { key: "dentist", from: "primary_dentist", describes: "The dentist they are assigned to." },
1790
+ { key: "carrier", from: "insurance_carrier", describes: "Tells them which card to bring." },
1791
+ { key: "practice_name", from: "business", describes: "The practice name." },
1792
+ { key: "practice_phone", from: "business", describes: "The front desk number." },
1793
+ { key: "today", from: "today", describes: "The date the letter went out." }
1794
+ ]
1795
+ },
1796
+ notificationRule: {
1797
+ token: "harbor_dental_visit_reminder",
1798
+ name: "Day-before appointment reminder",
1799
+ describes: "A no-show costs the practice the whole chair hour and the hygienist's time. A text the day before is the cheapest thing that prevents it, and it is the first automation any practice turns on.",
1800
+ when: {
1801
+ table: "visit",
1802
+ event: "due",
1803
+ field: "appointment_at",
1804
+ daysBefore: 1
1805
+ },
1806
+ audience: "the patient in the chair",
1807
+ channel: "sms",
1808
+ message: "Harbor Dental: a reminder that you are booked with {{provider}} tomorrow at {{appointment_time}}. Reply C to confirm or call 360 555 0142 if you need to move it."
1809
+ },
1810
+ provenance: {
1811
+ kind: "synthesized",
1812
+ authoredBy: "lane REAL-DATA (records use-case library)",
1813
+ authoredOn: "2026-09-21",
1814
+ noRealPeople: true
1815
+ }
1816
+ };
1817
+ harbor_dental_new_patient_intake_default = useCase3;
1818
+ }
1819
+ });
1820
+
1821
+ // src/use-cases/ridgeline-physical-therapy-plan-of-care.ts
1822
+ var ridgeline_physical_therapy_plan_of_care_exports = {};
1823
+ __export(ridgeline_physical_therapy_plan_of_care_exports, {
1824
+ default: () => ridgeline_physical_therapy_plan_of_care_default,
1825
+ useCase: () => useCase4
1826
+ });
1827
+ var useCase4, ridgeline_physical_therapy_plan_of_care_default;
1828
+ var init_ridgeline_physical_therapy_plan_of_care = __esm({
1829
+ "src/use-cases/ridgeline-physical-therapy-plan-of-care.ts"() {
1830
+ "use strict";
1831
+ useCase4 = {
1832
+ id: "ridgeline-physical-therapy-plan-of-care",
1833
+ useCase: "Sasha Lindqvist runs Ridgeline Physical Therapy single-handed, and she uses this to carry a patient from a physician's referral through a course of visits to a treatment goal that is either met or honestly written off, without losing track of who is overdue for a re-evaluation.",
1834
+ industry: "Physical therapy",
1835
+ cleanupTag: "use-case:ridgeline-physical-therapy-plan-of-care",
1836
+ business: {
1837
+ name: "Ridgeline Physical Therapy",
1838
+ legalName: "Ridgeline Physical Therapy, LLC",
1839
+ describes: "A solo outpatient physical therapy practice doing orthopaedic and post-surgical rehabilitation.",
1840
+ address: {
1841
+ line1: "3114 Foothill Boulevard",
1842
+ line2: "Suite B",
1843
+ city: "Boise",
1844
+ region: "ID",
1845
+ postalCode: "83702",
1846
+ country: "US"
1847
+ },
1848
+ phone: "+1 208 555 0173",
1849
+ website: "https://ridgelinept.com",
1850
+ email: "frontdesk@ridgelinept.com",
1851
+ timezone: "America/Boise"
1852
+ },
1853
+ tables: [
1854
+ {
1855
+ token: "patients",
1856
+ name: "Patients",
1857
+ labelSingular: "Patient",
1858
+ labelPlural: "Patients",
1859
+ type: "entity",
1860
+ display: "list",
1861
+ weight: "heavy",
1862
+ ordered: false,
1863
+ icon: "user-round",
1864
+ titleField: "full_name",
1865
+ describes: "Everyone on the caseload, from referral through discharge.",
1866
+ fields: [
1867
+ { key: "full_name", label: "Patient name", parityType: "text", required: true, sensitivity: "confidential", contextPolicy: "summarize" },
1868
+ { key: "date_of_birth", label: "Date of birth", parityType: "datetime", format: "date", sensitivity: "confidential", contextPolicy: "exclude" },
1869
+ { key: "phone", label: "Phone", parityType: "phone", format: "phone", sensitivity: "confidential", contextPolicy: "exclude" },
1870
+ { key: "email", label: "Email", parityType: "email", format: "email", sensitivity: "confidential", contextPolicy: "exclude" },
1871
+ { key: "referring_physician", label: "Referring physician", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
1872
+ { key: "primary_diagnosis", label: "Primary diagnosis", parityType: "text", sensitivity: "confidential", contextPolicy: "summarize" },
1873
+ { key: "insurance_provider", label: "Insurance", parityType: "select", choices: ["Aetna", "Blue Cross Blue Shield", "UnitedHealthcare", "Cigna", "Medicare", "Self-pay"], sensitivity: "confidential", contextPolicy: "summarize" },
1874
+ { key: "intake_date", label: "Intake date", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
1875
+ { key: "status", label: "Status", parityType: "select", choices: ["Active", "Discharged", "On Hold", "Referred Out"], sensitivity: "internal", contextPolicy: "include" }
1876
+ ],
1877
+ rows: [
1878
+ { key: "patient-nora-castellan", values: { "full_name": "Nora Castellan", "date_of_birth": "1978-03-14", "phone": "555-201-3341", "email": "nora.castellan@northshoremail.com", "referring_physician": "Dr. Amina Reyes", "primary_diagnosis": "Rotator cuff tendinopathy, right shoulder", "insurance_provider": "Aetna", "intake_date": "2026-06-02", "status": "Active" } },
1879
+ { key: "patient-devon-ashworth", values: { "full_name": "Devon Ashworth", "date_of_birth": "1991-11-02", "phone": "555-201-3342", "email": "devon.ashworth@northshoremail.com", "referring_physician": "Dr. Marcus Feld", "primary_diagnosis": "ACL reconstruction, post-op (6 weeks)", "insurance_provider": "Blue Cross Blue Shield", "intake_date": "2026-06-05", "status": "Active" } },
1880
+ { key: "patient-priya-vantana", values: { "full_name": "Priya Vantana", "date_of_birth": "1965-07-22", "phone": "555-201-3343", "email": "priya.vantana@northshoremail.com", "referring_physician": "Dr. Amina Reyes", "primary_diagnosis": "Chronic low back pain, L4-L5 disc bulge", "insurance_provider": "Medicare", "intake_date": "2026-05-19", "status": "Active" } },
1881
+ { key: "patient-isaiah-broome", values: { "full_name": "Isaiah Broome", "date_of_birth": "2002-01-30", "phone": "555-201-3344", "email": "isaiah.broome@northshoremail.com", "referring_physician": "Dr. Lena Ostrowski", "primary_diagnosis": "Grade II ankle sprain, left", "insurance_provider": "UnitedHealthcare", "intake_date": "2026-07-01", "status": "Discharged" } },
1882
+ { key: "patient-marguerite-solano", values: { "full_name": "Marguerite Solano", "date_of_birth": "1954-09-08", "phone": "555-201-3345", "email": "marguerite.solano@northshoremail.com", "referring_physician": "Dr. Marcus Feld", "primary_diagnosis": "Total knee replacement, post-op (3 weeks)", "insurance_provider": "Medicare", "intake_date": "2026-06-20", "status": "Active" } },
1883
+ { key: "patient-tobias-reinholt", values: { "full_name": "Tobias Reinholt", "date_of_birth": "1988-04-17", "phone": "555-201-3346", "email": "tobias.reinholt@northshoremail.com", "referring_physician": "Dr. Lena Ostrowski", "primary_diagnosis": "Cervical radiculopathy, C6", "insurance_provider": "Cigna", "intake_date": "2026-07-10", "status": "Active" } },
1884
+ { key: "patient-odalys-fenmore", values: { "full_name": "Odalys Fenmore", "date_of_birth": "1997-12-25", "phone": "555-201-3347", "email": "odalys.fenmore@northshoremail.com", "referring_physician": "Dr. Amina Reyes", "primary_diagnosis": "Patellofemoral pain syndrome, bilateral", "insurance_provider": "Self-pay", "intake_date": "2026-07-15", "status": "On Hold" } },
1885
+ { key: "patient-wendell-okafor", values: { "full_name": "Wendell Okafor", "date_of_birth": "1972-02-11", "phone": "555-201-3348", "email": "wendell.okafor@northshoremail.com", "referring_physician": "Dr. Marcus Feld", "primary_diagnosis": "Plantar fasciitis, right heel", "insurance_provider": "Aetna", "intake_date": "2026-06-28", "status": "Active" } },
1886
+ { key: "patient-camille-duprez", values: { "full_name": "Camille Duprez", "date_of_birth": "1983-06-04", "phone": "555-201-3349", "email": "camille.duprez@northshoremail.com", "referring_physician": "Dr. Lena Ostrowski", "primary_diagnosis": "Lumbar spinal stenosis", "insurance_provider": "Blue Cross Blue Shield", "intake_date": "2026-05-30", "status": "Active" } },
1887
+ { key: "patient-griffin-alderete", values: { "full_name": "Griffin Alderete", "date_of_birth": "1995-10-19", "phone": "555-201-3350", "email": "griffin.alderete@northshoremail.com", "referring_physician": "Dr. Amina Reyes", "primary_diagnosis": "Achilles tendinopathy, left", "insurance_provider": "UnitedHealthcare", "intake_date": "2026-07-18", "status": "Referred Out" } }
1888
+ ]
1889
+ },
1890
+ {
1891
+ token: "appointments",
1892
+ name: "Visits",
1893
+ labelSingular: "Visit",
1894
+ labelPlural: "Visits",
1895
+ type: "entity",
1896
+ display: "calendar",
1897
+ weight: "heavy",
1898
+ ordered: true,
1899
+ icon: "calendar-clock",
1900
+ titleField: "visit_type",
1901
+ describes: "Every booked appointment, what kind of visit it is and whether it happened.",
1902
+ fields: [
1903
+ { key: "patient", label: "Patient", parityType: "relation", required: true, relationTarget: "patients", relationMax: 1, sensitivity: "internal", contextPolicy: "include" },
1904
+ { key: "appointment_date", label: "Date", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
1905
+ { key: "appointment_time", label: "Time", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
1906
+ { key: "visit_type", label: "Visit type", parityType: "select", required: true, choices: ["Initial Evaluation", "Follow-up", "Re-evaluation", "Discharge Visit"], sensitivity: "internal", contextPolicy: "include" },
1907
+ { key: "therapist_name", label: "Therapist", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
1908
+ { key: "duration_minutes", label: "Length", parityType: "integer", unit: "min", sensitivity: "internal", contextPolicy: "include" },
1909
+ { key: "status", label: "Status", parityType: "select", choices: ["Scheduled", "Completed", "No-show", "Cancelled"], sensitivity: "internal", contextPolicy: "include" },
1910
+ { key: "notes", label: "Visit notes", parityType: "long_text", sensitivity: "confidential", contextPolicy: "on_request" }
1911
+ ],
1912
+ rows: [
1913
+ { key: "appointment-01", values: { "patient": "patient-nora-castellan", "appointment_date": "2026-06-02", "appointment_time": "09:00", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 60, "status": "Completed", "notes": "AROM shoulder flexion limited to 110 deg, pain 6/10 with overhead reach." } },
1914
+ { key: "appointment-02", values: { "patient": "patient-nora-castellan", "appointment_date": "2026-06-09", "appointment_time": "09:00", "visit_type": "Follow-up", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 45, "status": "Completed", "notes": "Progressing isometrics, pain down to 4/10." } },
1915
+ { key: "appointment-03", values: { "patient": "patient-nora-castellan", "appointment_date": "2026-06-16", "appointment_time": "09:00", "visit_type": "Follow-up", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 45, "status": "Scheduled", "notes": "" } },
1916
+ { key: "appointment-04", values: { "patient": "patient-devon-ashworth", "appointment_date": "2026-06-05", "appointment_time": "13:00", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 60, "status": "Completed", "notes": "Quad lag present, effusion mild. Cleared for closed-chain work." } },
1917
+ { key: "appointment-05", values: { "patient": "patient-devon-ashworth", "appointment_date": "2026-06-12", "appointment_time": "13:00", "visit_type": "Follow-up", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 45, "status": "Completed", "notes": "Quad lag resolving, full passive extension achieved." } },
1918
+ { key: "appointment-06", values: { "patient": "patient-devon-ashworth", "appointment_date": "2026-06-19", "appointment_time": "13:00", "visit_type": "Follow-up", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 45, "status": "No-show", "notes": "Patient did not call." } },
1919
+ { key: "appointment-07", values: { "patient": "patient-priya-vantana", "appointment_date": "2026-05-19", "appointment_time": "10:30", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Marcus Reid, DPT", "duration_minutes": 60, "status": "Completed", "notes": "Positive slump test on right, centralization with extension." } },
1920
+ { key: "appointment-08", values: { "patient": "patient-priya-vantana", "appointment_date": "2026-06-02", "appointment_time": "10:30", "visit_type": "Follow-up", "therapist_name": "Dr. Marcus Reid, DPT", "duration_minutes": 45, "status": "Completed", "notes": "Symptoms centralizing, tolerating prone press-ups." } },
1921
+ { key: "appointment-09", values: { "patient": "patient-isaiah-broome", "appointment_date": "2026-07-01", "appointment_time": "15:00", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Marcus Reid, DPT", "duration_minutes": 60, "status": "Completed", "notes": "Grade II sprain, moderate swelling, weight-bearing as tolerated." } },
1922
+ { key: "appointment-10", values: { "patient": "patient-isaiah-broome", "appointment_date": "2026-07-22", "appointment_time": "15:00", "visit_type": "Discharge Visit", "therapist_name": "Dr. Marcus Reid, DPT", "duration_minutes": 30, "status": "Completed", "notes": "Full ROM restored, single-leg balance 30s, discharged to home program." } },
1923
+ { key: "appointment-11", values: { "patient": "patient-marguerite-solano", "appointment_date": "2026-06-20", "appointment_time": "11:00", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 60, "status": "Completed", "notes": "Knee flexion 85 deg, using front-wheel walker." } },
1924
+ { key: "appointment-12", values: { "patient": "patient-marguerite-solano", "appointment_date": "2026-06-27", "appointment_time": "11:00", "visit_type": "Follow-up", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 45, "status": "Completed", "notes": "Flexion improved to 100 deg." } },
1925
+ { key: "appointment-13", values: { "patient": "patient-marguerite-solano", "appointment_date": "2026-07-04", "appointment_time": "11:00", "visit_type": "Follow-up", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 45, "status": "Scheduled", "notes": "" } },
1926
+ { key: "appointment-14", values: { "patient": "patient-tobias-reinholt", "appointment_date": "2026-07-10", "appointment_time": "08:00", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Marcus Reid, DPT", "duration_minutes": 60, "status": "Completed", "notes": "Positive Spurling's test right, numbness in C6 dermatome." } },
1927
+ { key: "appointment-15", values: { "patient": "patient-wendell-okafor", "appointment_date": "2026-06-28", "appointment_time": "16:00", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 60, "status": "Completed", "notes": "Point tenderness at medial calcaneal tubercle, worse first step in AM." } },
1928
+ { key: "appointment-16", values: { "patient": "patient-camille-duprez", "appointment_date": "2026-05-30", "appointment_time": "09:30", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Marcus Reid, DPT", "duration_minutes": 60, "status": "Completed", "notes": "Symptoms improve with flexion-biased posture, neurogenic claudication at 2 blocks." } },
1929
+ { key: "appointment-17", values: { "patient": "patient-griffin-alderete", "appointment_date": "2026-07-18", "appointment_time": "14:00", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Marcus Reid, DPT", "duration_minutes": 60, "status": "Completed", "notes": "Referred to orthopedic surgeon for imaging before continuing PT." } }
1930
+ ]
1931
+ },
1932
+ {
1933
+ token: "treatment_plans",
1934
+ name: "Treatment plans",
1935
+ labelSingular: "Treatment plan",
1936
+ labelPlural: "Treatment plans",
1937
+ type: "entity",
1938
+ display: "board",
1939
+ weight: "heavy",
1940
+ ordered: false,
1941
+ icon: "clipboard-list",
1942
+ titleField: "diagnosis",
1943
+ describes: "The goal each patient is working toward, and whether they have met it.",
1944
+ fields: [
1945
+ { key: "patient", label: "Patient", parityType: "relation", required: true, relationTarget: "patients", relationMax: 1, sensitivity: "internal", contextPolicy: "include" },
1946
+ { key: "diagnosis", label: "Diagnosis", parityType: "text", required: true, sensitivity: "confidential", contextPolicy: "summarize" },
1947
+ { key: "goal", label: "Goal", parityType: "long_text", sensitivity: "confidential", contextPolicy: "summarize" },
1948
+ { key: "start_date", label: "Start date", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
1949
+ { key: "target_date", label: "Target date", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
1950
+ { key: "status", label: "Status", parityType: "select", choices: ["Active", "Met", "Modified", "Discontinued"], sensitivity: "internal", contextPolicy: "include" }
1951
+ ],
1952
+ rows: [
1953
+ { key: "plan-nora-castellan", values: { "patient": "patient-nora-castellan", "diagnosis": "Rotator cuff tendinopathy, right shoulder", "goal": "Restore pain-free overhead reach to 160 deg flexion within 6 weeks.", "start_date": "2026-06-02", "target_date": "2026-07-14", "status": "Active" } },
1954
+ { key: "plan-devon-ashworth", values: { "patient": "patient-devon-ashworth", "diagnosis": "ACL reconstruction, post-op", "goal": "Return to single-leg squat and stair descent without compensation by week 12.", "start_date": "2026-06-05", "target_date": "2026-08-28", "status": "Active" } },
1955
+ { key: "plan-priya-vantana", values: { "patient": "patient-priya-vantana", "diagnosis": "Chronic low back pain, L4-L5 disc bulge", "goal": "Centralize symptoms and tolerate 30-minute walk without radiating pain.", "start_date": "2026-05-19", "target_date": "2026-07-19", "status": "Active" } },
1956
+ { key: "plan-isaiah-broome", values: { "patient": "patient-isaiah-broome", "diagnosis": "Grade II ankle sprain, left", "goal": "Full weight-bearing, return to recreational basketball.", "start_date": "2026-07-01", "target_date": "2026-07-22", "status": "Met" } },
1957
+ { key: "plan-marguerite-solano", values: { "patient": "patient-marguerite-solano", "diagnosis": "Total knee replacement, post-op", "goal": "Achieve 110 deg flexion and walk without assistive device by week 8.", "start_date": "2026-06-20", "target_date": "2026-08-15", "status": "Active" } },
1958
+ { key: "plan-tobias-reinholt", values: { "patient": "patient-tobias-reinholt", "diagnosis": "Cervical radiculopathy, C6", "goal": "Resolve numbness, restore full cervical rotation.", "start_date": "2026-07-10", "target_date": "2026-08-21", "status": "Active" } },
1959
+ { key: "plan-wendell-okafor", values: { "patient": "patient-wendell-okafor", "diagnosis": "Plantar fasciitis, right heel", "goal": "Pain-free first step in the morning, return to daily 3-mile walk.", "start_date": "2026-06-28", "target_date": "2026-08-09", "status": "Active" } },
1960
+ { key: "plan-camille-duprez", values: { "patient": "patient-camille-duprez", "diagnosis": "Lumbar spinal stenosis", "goal": "Increase walking tolerance to 6 blocks without claudication.", "start_date": "2026-05-30", "target_date": "2026-08-01", "status": "Active" } }
1961
+ ]
1962
+ },
1963
+ {
1964
+ token: "exercises_prescribed",
1965
+ name: "Home exercises",
1966
+ labelSingular: "Home exercise",
1967
+ labelPlural: "Home exercises",
1968
+ type: "detail",
1969
+ display: "list",
1970
+ weight: "light",
1971
+ ordered: true,
1972
+ icon: "dumbbell",
1973
+ titleField: "exercise_name",
1974
+ describes: "What each patient was told to do between visits, and how it progresses.",
1975
+ fields: [
1976
+ { key: "treatment_plan", label: "Treatment plan", parityType: "relation", required: true, relationTarget: "treatment_plans", relationMax: 1, sensitivity: "internal", contextPolicy: "include" },
1977
+ { key: "exercise_name", label: "Exercise", parityType: "select", required: true, choices: ["Pendulum Exercise", "Scapular Retraction", "Straight Leg Raise", "Quadriceps Sets", "Heel Slides", "Terminal Knee Extension", "Prone Press-ups (McKenzie)", "Cat-Camel Stretch", "Clamshells", "Bridging", "Standing Hip Abduction", "Wall Sits", "Calf Raises", "Hamstring Curls", "Ankle Pumps", "Chin Tucks"], sensitivity: "internal", contextPolicy: "include" },
1978
+ { key: "sets", label: "Sets", parityType: "integer", sensitivity: "internal", contextPolicy: "include" },
1979
+ { key: "reps", label: "Reps", parityType: "integer", sensitivity: "internal", contextPolicy: "include" },
1980
+ { key: "frequency_per_week", label: "Times per week", parityType: "integer", sensitivity: "internal", contextPolicy: "include" },
1981
+ { key: "progression_notes", label: "Progression notes", parityType: "long_text", sensitivity: "confidential", contextPolicy: "on_request" }
1982
+ ],
1983
+ rows: [
1984
+ { key: "exercises_prescribed-01", values: { "treatment_plan": "plan-nora-castellan", "exercise_name": "Pendulum Exercise", "sets": 3, "reps": 15, "frequency_per_week": 7, "progression_notes": "Started week 1, pain-free arc, add light weight at week 3." } },
1985
+ { key: "exercises_prescribed-02", values: { "treatment_plan": "plan-nora-castellan", "exercise_name": "Scapular Retraction", "sets": 3, "reps": 12, "frequency_per_week": 5, "progression_notes": "Using resistance band, increase band tension at week 4." } },
1986
+ { key: "exercises_prescribed-03", values: { "treatment_plan": "plan-devon-ashworth", "exercise_name": "Quadriceps Sets", "sets": 3, "reps": 10, "frequency_per_week": 7, "progression_notes": "Hold 5 seconds, progressing to straight leg raise next visit." } },
1987
+ { key: "exercises_prescribed-04", values: { "treatment_plan": "plan-devon-ashworth", "exercise_name": "Straight Leg Raise", "sets": 3, "reps": 10, "frequency_per_week": 6, "progression_notes": "No lag observed, add ankle weight 2lb." } },
1988
+ { key: "exercises_prescribed-05", values: { "treatment_plan": "plan-devon-ashworth", "exercise_name": "Terminal Knee Extension", "sets": 3, "reps": 12, "frequency_per_week": 5, "progression_notes": "Using resistance band anchored behind knee." } },
1989
+ { key: "exercises_prescribed-06", values: { "treatment_plan": "plan-priya-vantana", "exercise_name": "Prone Press-ups (McKenzie)", "sets": 2, "reps": 10, "frequency_per_week": 6, "progression_notes": "Symptoms centralizing, hold end range 2 seconds." } },
1990
+ { key: "exercises_prescribed-07", values: { "treatment_plan": "plan-priya-vantana", "exercise_name": "Cat-Camel Stretch", "sets": 2, "reps": 10, "frequency_per_week": 7, "progression_notes": "Morning stiffness reduced." } },
1991
+ { key: "exercises_prescribed-08", values: { "treatment_plan": "plan-isaiah-broome", "exercise_name": "Ankle Pumps", "sets": 3, "reps": 20, "frequency_per_week": 7, "progression_notes": "Early edema control, progressed to standing balance week 2." } },
1992
+ { key: "exercises_prescribed-09", values: { "treatment_plan": "plan-marguerite-solano", "exercise_name": "Heel Slides", "sets": 3, "reps": 10, "frequency_per_week": 7, "progression_notes": "Flexion improving 5 deg/week." } },
1993
+ { key: "exercises_prescribed-10", values: { "treatment_plan": "plan-marguerite-solano", "exercise_name": "Quadriceps Sets", "sets": 4, "reps": 10, "frequency_per_week": 7, "progression_notes": "Hold 5 seconds, no extensor lag." } },
1994
+ { key: "exercises_prescribed-11", values: { "treatment_plan": "plan-tobias-reinholt", "exercise_name": "Chin Tucks", "sets": 3, "reps": 10, "frequency_per_week": 6, "progression_notes": "Reduces referred symptoms into arm during session." } },
1995
+ { key: "exercises_prescribed-12", values: { "treatment_plan": "plan-wendell-okafor", "exercise_name": "Calf Raises", "sets": 3, "reps": 15, "frequency_per_week": 5, "progression_notes": "Eccentric emphasis, 3-second lower." } },
1996
+ { key: "exercises_prescribed-13", values: { "treatment_plan": "plan-camille-duprez", "exercise_name": "Bridging", "sets": 3, "reps": 12, "frequency_per_week": 5, "progression_notes": "Flexion-biased, tolerating well." } },
1997
+ { key: "exercises_prescribed-14", values: { "treatment_plan": "plan-camille-duprez", "exercise_name": "Standing Hip Abduction", "sets": 3, "reps": 12, "frequency_per_week": 5, "progression_notes": "Added ankle weight this week." } }
1998
+ ]
1999
+ }
2000
+ ],
2001
+ relationships: [
2002
+ {
2003
+ describes: "A visit belongs to the patient who attends it, and it dies with their chart.",
2004
+ fromTable: "appointments",
2005
+ fromField: "patient",
2006
+ toTable: "patients",
2007
+ flavor: "owned",
2008
+ cardinality: "one",
2009
+ onDelete: "cascade",
2010
+ inverseKey: "visits"
2011
+ },
2012
+ {
2013
+ describes: "A treatment plan belongs to the patient it sets a goal for.",
2014
+ fromTable: "treatment_plans",
2015
+ fromField: "patient",
2016
+ toTable: "patients",
2017
+ flavor: "owned",
2018
+ cardinality: "one",
2019
+ onDelete: "cascade",
2020
+ inverseKey: "treatment_plans"
2021
+ },
2022
+ {
2023
+ describes: "A home exercise is prescribed under exactly one treatment plan and ends with it.",
2024
+ fromTable: "exercises_prescribed",
2025
+ fromField: "treatment_plan",
2026
+ toTable: "treatment_plans",
2027
+ flavor: "owned",
2028
+ cardinality: "one",
2029
+ onDelete: "cascade",
2030
+ inverseKey: "exercises"
2031
+ }
2032
+ ],
2033
+ form: {
2034
+ token: "ridgeline_new_patient_referral",
2035
+ name: "Ridgeline new-patient referral intake",
2036
+ describes: "What a referred patient fills in before the initial evaluation, so the first visit is spent examining them rather than typing.",
2037
+ audience: "public",
2038
+ table: "patients",
2039
+ fields: [
2040
+ { fieldKey: "full_name", label: "Your full name", required: true },
2041
+ { fieldKey: "date_of_birth", label: "Date of birth", required: true },
2042
+ { fieldKey: "phone", label: "Best number to reach you", required: true },
2043
+ { fieldKey: "email", label: "Email", required: true },
2044
+ { fieldKey: "referring_physician", label: "Who referred you?", required: true, help: "The doctor's name on your referral, so we can send them your plan of care." },
2045
+ { fieldKey: "primary_diagnosis", label: "What are you coming in for?", help: "In your own words is fine \u2014 we will write the clinical version." },
2046
+ { fieldKey: "insurance_provider", label: "Insurance", help: "Choose Self-pay if you would rather not bill insurance." }
2047
+ ],
2048
+ submitLabel: "Send my referral details",
2049
+ confirmation: "Thank you \u2014 we have your details. We will verify your benefits and call you within one business day to book your initial evaluation, which takes about an hour."
2050
+ },
2051
+ pipeline: {
2052
+ token: "ridgeline_plan_of_care",
2053
+ name: "Plan of care",
2054
+ describes: "What happens to a treatment goal once it is written. Sasha reviews this board every Friday, because a plan that sits in Active past its target date is the one that quietly fails.",
2055
+ table: "treatment_plans",
2056
+ stageField: "status",
2057
+ stages: [
2058
+ { key: "Active", label: "Active", describes: "The patient is working toward the goal and attending visits. Leaves when the goal is met, changed or abandoned.", typicalDurationDays: 42 },
2059
+ { key: "Modified", label: "Modified", describes: "Re-evaluation changed the goal or the timeline \u2014 progress was faster or slower than predicted.", typicalDurationDays: 21 },
2060
+ { key: "Met", label: "Met", describes: "The measured goal was reached. This is what discharge is built on and what the referring physician is told." },
2061
+ { key: "Discontinued", label: "Discontinued", describes: "Stopped without meeting the goal \u2014 the patient withdrew, was referred out, or their insurance ran out. Written down honestly rather than left Active." }
2062
+ ]
2063
+ },
2064
+ dashboardQuestion: {
2065
+ question: "How many plans are still Active past the date I said they would be finished?",
2066
+ whyItMatters: "A plan sitting Active past its target date means a patient is being treated without anyone re-checking whether the treatment is working. Every one of those needs a re-evaluation booked this week, or a decision to change the goal.",
2067
+ table: "treatment_plans",
2068
+ aggregate: "count",
2069
+ groupBy: "status",
2070
+ filter: "status is 'Active' and target_date is before today",
2071
+ answerUnit: "treatment plans"
2072
+ },
2073
+ documentTemplate: {
2074
+ token: "ridgeline_plan_of_care_letter",
2075
+ name: "Plan of care letter to the referring physician",
2076
+ describes: "Goes back to the doctor who made the referral, at the start of care and again at discharge. Physicians refer again when they hear what happened to the last patient they sent, which makes this letter the practice's whole marketing plan.",
2077
+ table: "treatment_plans",
2078
+ title: "Plan of care \u2014 {{diagnosis}}",
2079
+ body: [
2080
+ "Thank you for the referral.",
2081
+ "",
2082
+ "Following evaluation I have started a course of treatment for {{diagnosis}}.",
2083
+ "",
2084
+ "Goal: {{goal}}",
2085
+ "",
2086
+ "Care began on {{start_date}} and I expect to reach that goal by {{target_date}}. The plan is currently {{status}}. The patient is on a home exercise programme between visits, and I re-evaluate objectively rather than by report.",
2087
+ "",
2088
+ "I will write again at discharge with the measured outcome. If anything in the history changes at your end, please tell me \u2014 it usually changes the plan.",
2089
+ "",
2090
+ "{{practice_name}}",
2091
+ "{{practice_phone}}",
2092
+ "{{today}}"
2093
+ ].join("\n"),
2094
+ mergeFields: [
2095
+ { key: "diagnosis", from: "diagnosis", describes: "What is being treated." },
2096
+ { key: "goal", from: "goal", describes: "The measurable goal, in the words the physician will be told at discharge." },
2097
+ { key: "start_date", from: "start_date", describes: "When care began." },
2098
+ { key: "target_date", from: "target_date", describes: "When the goal is expected to be met." },
2099
+ { key: "status", from: "status", describes: "Where the plan stands today." },
2100
+ { key: "practice_name", from: "business", describes: "The practice name." },
2101
+ { key: "practice_phone", from: "business", describes: "The number the physician's office calls back on." },
2102
+ { key: "today", from: "today", describes: "The date the letter went out." }
2103
+ ]
2104
+ },
2105
+ notificationRule: {
2106
+ token: "ridgeline_plan_past_target",
2107
+ name: "A plan has passed its target date",
2108
+ describes: "The one automation a solo therapist genuinely needs: nobody else is watching the caseload, so a goal that quietly slips past its date has to come and find her.",
2109
+ when: {
2110
+ table: "treatment_plans",
2111
+ event: "overdue",
2112
+ field: "target_date"
2113
+ },
2114
+ audience: "the treating therapist",
2115
+ channel: "in_app",
2116
+ message: "{{diagnosis}} has passed its target date of {{target_date}} and is still {{status}}. Book a re-evaluation or change the goal."
2117
+ },
2118
+ provenance: {
2119
+ kind: "synthesized",
2120
+ authoredBy: "data crew (dataset) + lane REAL-DATA (business identity, relationships, form, pipeline, dashboard question, document, notification rule)",
2121
+ authoredOn: "2026-09-21",
2122
+ noRealPeople: true
2123
+ }
2124
+ };
2125
+ ridgeline_physical_therapy_plan_of_care_default = useCase4;
2126
+ }
2127
+ });
2128
+
2129
+ // src/use-cases/registry.ts
2130
+ var registry_exports = {};
2131
+ __export(registry_exports, {
2132
+ USE_CASE_LOADERS: () => USE_CASE_LOADERS,
2133
+ listUseCases: () => listUseCases,
2134
+ loadAllUseCases: () => loadAllUseCases,
2135
+ loadUseCase: () => loadUseCase,
2136
+ summarize: () => summarize,
2137
+ useCaseFor: () => useCaseFor,
2138
+ useCaseIds: () => useCaseIds
2139
+ });
2140
+ function useCaseIds() {
2141
+ return Object.keys(USE_CASE_LOADERS).sort();
2142
+ }
2143
+ async function loadUseCase(id) {
2144
+ const loader = USE_CASE_LOADERS[id];
2145
+ if (!loader) {
2146
+ throw new Error(
2147
+ `There is no use case registered as "${id}". Registered: ${useCaseIds().join(", ")}.`
2148
+ );
2149
+ }
2150
+ const module2 = await loader();
2151
+ return module2.useCase;
2152
+ }
2153
+ async function loadAllUseCases() {
2154
+ return Promise.all(useCaseIds().map((id) => loadUseCase(id)));
2155
+ }
2156
+ function summarize(useCase5) {
2157
+ return {
2158
+ id: useCase5.id,
2159
+ useCase: useCase5.useCase,
2160
+ industry: useCase5.industry,
2161
+ businessName: useCase5.business.name,
2162
+ tableCount: useCase5.tables.length,
2163
+ rowCount: useCase5.tables.reduce((total, table) => total + table.rows.length, 0)
2164
+ };
2165
+ }
2166
+ async function listUseCases() {
2167
+ return (await loadAllUseCases()).map(summarize);
2168
+ }
2169
+ function useCaseFor(consumer) {
2170
+ const ids = useCaseIds();
2171
+ let hash = 0;
2172
+ for (let i = 0; i < consumer.length; i += 1) {
2173
+ hash = hash * 31 + consumer.charCodeAt(i) >>> 0;
2174
+ }
2175
+ const id = ids[hash % ids.length];
2176
+ if (!id) {
2177
+ throw new Error(
2178
+ `No use cases are registered, so there is nothing to give "${consumer}". Add one to USE_CASE_LOADERS.`
2179
+ );
2180
+ }
2181
+ return id;
2182
+ }
2183
+ var USE_CASE_LOADERS;
2184
+ var init_registry = __esm({
2185
+ "src/use-cases/registry.ts"() {
2186
+ "use strict";
2187
+ USE_CASE_LOADERS = {
2188
+ "alvarado-chen-kitchen-weekly-cooking": () => Promise.resolve().then(() => (init_alvarado_chen_kitchen_weekly_cooking(), alvarado_chen_kitchen_weekly_cooking_exports)),
2189
+ "birchwood-avenue-renovation-budget": () => Promise.resolve().then(() => (init_birchwood_avenue_renovation_budget(), birchwood_avenue_renovation_budget_exports)),
2190
+ "harbor-dental-new-patient-intake": () => Promise.resolve().then(() => (init_harbor_dental_new_patient_intake(), harbor_dental_new_patient_intake_exports)),
2191
+ "ridgeline-physical-therapy-plan-of-care": () => Promise.resolve().then(() => (init_ridgeline_physical_therapy_plan_of_care(), ridgeline_physical_therapy_plan_of_care_exports))
2192
+ };
2193
+ }
2194
+ });
2195
+
22
2196
  // src/react/index.ts
23
2197
  var react_exports = {};
24
2198
  __export(react_exports, {
@@ -68,6 +2242,7 @@ __export(react_exports, {
68
2242
  TABLE_TYPES: () => TABLE_TYPES,
69
2243
  VALUE_ALTERNATE_KEYS: () => VALUE_ALTERNATE_KEYS,
70
2244
  VALUE_ENVELOPE_KEYS: () => VALUE_ENVELOPE_KEYS,
2245
+ actionRefusals: () => actionRefusals,
71
2246
  archivedByLine: () => archivedByLine,
72
2247
  archivedWhen: () => archivedWhen,
73
2248
  asPermissionLevel: () => asPermissionLevel,
@@ -82,6 +2257,8 @@ __export(react_exports, {
82
2257
  emptyArchiveLine: () => emptyArchiveLine,
83
2258
  emptyPortalArchiveLine: () => emptyPortalArchiveLine,
84
2259
  err: () => err,
2260
+ exampleSpec: () => exampleSpec,
2261
+ exportPageXlsx: () => exportPageXlsx,
85
2262
  fieldKindFor: () => fieldKindFor,
86
2263
  forgetAllOps: () => forgetAllOps,
87
2264
  highestLevel: () => highestLevel,
@@ -251,6 +2428,80 @@ function isRecordsErr(result) {
251
2428
  var ok = (data) => ({ ok: true, data });
252
2429
  var err = (error) => ({ ok: false, error });
253
2430
 
2431
+ // src/grid.ts
2432
+ function actionRefusals(error) {
2433
+ return Array.isArray(error.detail) ? error.detail : [];
2434
+ }
2435
+ function exampleSpec(useCase5) {
2436
+ return {
2437
+ business: useCase5.business.name,
2438
+ tables: useCase5.tables.map((t) => ({
2439
+ token: t.token,
2440
+ name: t.name,
2441
+ labelSingular: t.labelSingular,
2442
+ labelPlural: t.labelPlural,
2443
+ type: t.type,
2444
+ display: t.display,
2445
+ weight: t.weight,
2446
+ ordered: t.ordered,
2447
+ titleField: t.titleField,
2448
+ describes: t.describes,
2449
+ fields: t.fields.map((f) => ({
2450
+ key: f.key,
2451
+ label: f.label,
2452
+ parityType: f.parityType,
2453
+ multi: f.multi,
2454
+ dated: f.dated,
2455
+ required: f.required,
2456
+ unit: f.unit ?? void 0,
2457
+ rules: f.rules,
2458
+ choices: f.choices,
2459
+ source: f.source,
2460
+ computeOn: f.computeOn,
2461
+ relationTarget: f.relationTarget,
2462
+ relationMax: f.relationMax,
2463
+ sensitivity: f.sensitivity,
2464
+ contextPolicy: f.contextPolicy
2465
+ })),
2466
+ rows: t.rows
2467
+ }))
2468
+ };
2469
+ }
2470
+ function exportCellText(value) {
2471
+ if (value === null || value === void 0) return "";
2472
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
2473
+ return JSON.stringify(value);
2474
+ }
2475
+ async function exportPageXlsx(page, labels = {}, sheetLabel = "Records") {
2476
+ const XLSX = await import("xlsx");
2477
+ const header = page.columns.map((c) => labels[c] ?? c);
2478
+ const body = page.rows.map((row) => page.columns.map((c) => exportCellText(row[c])));
2479
+ const workbook = XLSX.utils.book_new();
2480
+ const name = sheetLabel.replace(/[\\/?*[\]:]/g, " ").trim().slice(0, 31) || "Records";
2481
+ XLSX.utils.book_append_sheet(workbook, XLSX.utils.aoa_to_sheet([header, ...body]), name);
2482
+ const withheld = Object.entries(page.withheld ?? {});
2483
+ if (withheld.length > 0) {
2484
+ XLSX.utils.book_append_sheet(
2485
+ workbook,
2486
+ XLSX.utils.aoa_to_sheet([
2487
+ ["Column", "Why it is empty in this export"],
2488
+ ...withheld.map(([k, v]) => [labels[k] ?? k, typeof v === "string" ? v : JSON.stringify(v)])
2489
+ ]),
2490
+ "Withheld columns"
2491
+ );
2492
+ }
2493
+ if (page.page?.next !== null && page.page?.next !== void 0) {
2494
+ XLSX.utils.book_append_sheet(
2495
+ workbook,
2496
+ XLSX.utils.aoa_to_sheet([[
2497
+ `This file holds the first ${page.page.returned} rows. The table has more; export again from row ${page.page.next + 1}.`
2498
+ ]]),
2499
+ "More rows"
2500
+ );
2501
+ }
2502
+ return XLSX.write(workbook, { type: "array", bookType: "xlsx", compression: true });
2503
+ }
2504
+
254
2505
  // src/store.generated.ts
255
2506
  var ACTOR_VOCABULARY = ["user", "agent", "system"];
256
2507
  var RETIRED_ACTOR_WORDS = { "ai": "agent", "code": "system", "human": "user" };
@@ -496,6 +2747,7 @@ var STORE_DOORS = [
496
2747
  { name: "doors_not_deciding_the_record", args: "", returns: "TABLE(function_name text, identity_args text, why text)", security: "invoker" },
497
2748
  { name: "doors_not_masking_fields", args: "", returns: "TABLE(function_name text, identity_args text, why text)", security: "invoker" },
498
2749
  { name: "doors_not_on_one_ladder", args: "", returns: "TABLE(function_name text, identity_args text, why text)", security: "invoker" },
2750
+ { name: "doors_refusing_in_another_doors_name", args: "", returns: "TABLE(function_name text, identity_args text, why text)", security: "invoker" },
499
2751
  { name: "effective_level", args: "p_user_id uuid, p_organization_id uuid, p_id uuid, p_type text DEFAULT 'record'::text", returns: "permission_level", security: "definer" },
500
2752
  { name: "enrich_cells", args: "p_organization_id uuid, p_table_id uuid, p_field_keys text[] DEFAULT NULL::text[], p_record_ids uuid[] DEFAULT NULL::uuid[]", returns: "TABLE(record_id uuid, field_key text, agent_owned boolean, value jsonb, value_version integer, actor text, on_behalf_of text, written_at timestamp with time zone, source jsonb, absent_reason text, alternates jsonb, pinned boolean, stale boolean, due_at timestamp with time zone)", security: "definer" },
501
2753
  { name: "enrich_declare", args: "p_organization_id uuid, p_field_id uuid, p_spec jsonb", returns: "jsonb", security: "definer" },
@@ -538,6 +2790,7 @@ var STORE_DOORS = [
538
2790
  { name: "field_rules", args: "p_field_data jsonb", returns: "TABLE(kind text, spec jsonb)", security: "invoker" },
539
2791
  { name: "field_update", args: "p_organization_id uuid, p_field_id uuid, p_patch jsonb", returns: "uuid", security: "definer" },
540
2792
  { name: "field_value_convert", args: "p_to jsonb, p_value jsonb", returns: "jsonb", security: "invoker" },
2793
+ { name: "field_words", args: "p_organization_id uuid, p_field_id uuid, p_value jsonb", returns: "text", security: "invoker" },
541
2794
  { name: "file_kernel_id", args: "", returns: "uuid", security: "invoker" },
542
2795
  { name: "form_declare", args: "p_organization_id uuid, p_table_id uuid, p_title text, p_questions jsonb, p_presentation jsonb DEFAULT '{}'::jsonb, p_submission_cap integer DEFAULT NULL::integer, p_quarantine_rule_id uuid DEFAULT NULL::uuid, p_notify_rule_id uuid DEFAULT NULL::uuid, p_form_id uuid DEFAULT NULL::uuid, p_slug text DEFAULT NULL::text", returns: "uuid", security: "definer" },
543
2796
  { name: "form_notify", args: "p_organization_id uuid, p_form_id uuid, p_record_id uuid, p_submission_id uuid", returns: "uuid", security: "invoker" },
@@ -629,6 +2882,7 @@ var STORE_DOORS = [
629
2882
  { name: "migrate_merge", args: "p_organization_id uuid, p_winner_id uuid, p_loser_id uuid, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
630
2883
  { name: "migrate_promote", args: "p_organization_id uuid, p_table_id uuid, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
631
2884
  { name: "migrate_purge", args: "p_organization_id uuid, p_table_id uuid DEFAULT NULL::uuid, p_dry_run boolean DEFAULT true", returns: "jsonb", security: "definer" },
2885
+ { name: "migrate_purge_hard", args: "p_organization_id uuid, p_table_id uuid DEFAULT NULL::uuid, p_compliance_reason text DEFAULT NULL::text, p_chunk integer DEFAULT 200, p_dry_run boolean DEFAULT true", returns: "jsonb", security: "definer" },
632
2886
  { name: "migrate_reclass", args: "p_organization_id uuid, p_id uuid, p_to text DEFAULT 'field'::text, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
633
2887
  { name: "migrate_rename", args: "p_organization_id uuid, p_id uuid, p_to text, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
634
2888
  { name: "migrate_reparent", args: "p_organization_id uuid, p_id uuid, p_parent_id uuid, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
@@ -756,6 +3010,7 @@ var STORE_DOORS = [
756
3010
  { name: "record_values_versioned", args: "p_organization_id uuid, p_record_id uuid", returns: "TABLE(field_key text, field_id uuid, value jsonb, value_version integer, source jsonb, absent_reason text, actor text, on_behalf_of text, written_at timestamp with time zone, alternates jsonb)", security: "definer" },
757
3011
  { name: "record_words", args: "p_organization_id uuid, p_record_id uuid, p_noun text DEFAULT NULL::text", returns: "text", security: "definer" },
758
3012
  { name: "record_write", args: "p_organization_id uuid, p_table_id uuid, p_data jsonb", returns: "uuid", security: "definer" },
3013
+ { name: "record_write_graph", args: "p_organization_id uuid, p_table_id uuid, p_parent jsonb, p_edges jsonb DEFAULT '[]'::jsonb, p_children jsonb DEFAULT '[]'::jsonb", returns: "jsonb", security: "definer" },
759
3014
  { name: "record_write_many", args: "p_organization_id uuid, p_table_id uuid, p_rows jsonb[], p_ids uuid[] DEFAULT NULL::uuid[]", returns: "uuid[]", security: "definer" },
760
3015
  { name: "refusals_claiming_a_level_never_asked", args: "", returns: "TABLE(function_name text, identity_args text, why text)", security: "invoker" },
761
3016
  { name: "relation_carry", args: "p_organization_id uuid, p_container_id uuid, p_item_id uuid", returns: "uuid", security: "definer" },
@@ -834,6 +3089,7 @@ var STORE_DOORS = [
834
3089
  { name: "table_declare", args: "p_organization_id uuid, p_spec jsonb", returns: "uuid", security: "definer" },
835
3090
  { name: "table_has_a_visible_record", args: "p_user uuid, p_organization_id uuid, p_table_id uuid", returns: "boolean", security: "definer" },
836
3091
  { name: "table_is_live", args: "p_organization_id uuid, p_table_id uuid", returns: "boolean", security: "invoker" },
3092
+ { name: "table_is_options_table", args: "p_organization_id uuid, p_table_id uuid", returns: "boolean", security: "invoker" },
837
3093
  { name: "table_kernel_id", args: "", returns: "uuid", security: "invoker" },
838
3094
  { name: "table_record_ceiling", args: "", returns: "integer", security: "invoker" },
839
3095
  { name: "table_record_ceiling", args: "p_organization_id uuid", returns: "integer", security: "invoker" },
@@ -847,6 +3103,8 @@ var STORE_DOORS = [
847
3103
  { name: "table_stage_field", args: "p_organization_id uuid, p_table_id uuid", returns: "text", security: "definer" },
848
3104
  { name: "table_storage", args: "p_organization_id uuid, p_table_id uuid", returns: "text", security: "invoker" },
849
3105
  { name: "table_type_field", args: "p_organization_id uuid, p_table_id uuid", returns: "text", security: "definer" },
3106
+ { name: "table_unique_rule_fields", args: "p_organization_id uuid, p_table_id uuid", returns: "jsonb", security: "invoker" },
3107
+ { name: "table_work_kind", args: "p_organization_id uuid, p_table_id uuid", returns: "text", security: "invoker" },
850
3108
  { name: "tables_at_home", args: "p_organization_id uuid, p_home_ids uuid[]", returns: "TABLE(table_id uuid, home_record_id uuid, kind text)", security: "definer" },
851
3109
  { name: "tables_described_without_asking", args: "", returns: "TABLE(function_name text, identity_args text, why text)", security: "invoker" },
852
3110
  { name: "trg_associations_bump_visibility", args: "", returns: "trigger", security: "definer" },
@@ -962,15 +3220,15 @@ var STORE_REFUSAL_CODES = [
962
3220
  { code: "02000", raised_by: "_checklist_instantiate,_portal_invite_payload,_share_write_person,_table_share_invite_payload,checklist_declare,checklist_run,checklist_step_complete,checklist_step_refusal,checklist_template_shape,conversation_scope_bind,dashboard_delete,dashboard_run,doc_letterhead,doc_render_body,doc_render_document,doc_render_read,doc_sign,doc_signature_intact,doc_signature_read,doc_template_delete,doc_template_read,doc_template_save,enrich_pin,entity_field_retire,entity_field_update,entity_record_read,entity_value_write,external_history_event,external_rows,external_stub_upsert,external_writes_set,io_restore,migrate_delete,migrate_extract_parent,migrate_merge,migrate_reclass,migrate_rename,migrate_reparent,migrate_retype,migrate_split,migrate_undo,organization_clear,portal_archive,portal_card,portal_declare,portal_invite,portal_invite_accept,portal_preview,portal_principal_bind,portal_restore,portal_revoke,read_record,record_delete,record_restore,record_restore_preview,record_table,record_update,relation_uncarry,share_access,share_grant,share_lane_set,share_people,share_revoke,sign_request_cancel,sign_request_create,sign_request_remind,sign_request_unchanged,table_archive,table_share_outside_accept,table_share_outside_invite,table_share_outside_resend,table_share_outside_revoke,visibility_as_of,work_approval_decide,work_approval_read,work_approval_request,work_assign,work_record_states,work_set_state" },
963
3221
  { code: "0A000", raised_by: "checklist_step_complete,external_rows,external_source_declare,external_write_through,promote_field,promoted_index_expr,promoted_query_sql,promoted_read,rule_eval,work_assign" },
964
3222
  { code: "22003", raised_by: "context_resolve" },
965
- { code: "22004", raised_by: "_entity_custom_fields_guard,_share_write_person,_value_envelope,actor_word,agg_assert_key,agg_sql,anon_capture,anon_token_issue,anon_write,assert_client_may_reach,booking_declare,capture_submit,checklist_declare,context_resolve,dashboard_block_normalize,dashboard_declare,dashboard_window_sql,doc_render_write,doc_sign,doc_signature_write,doc_template_save,enrich_land,enrich_normalize,external_history_event,external_rows,external_source_declare,external_stub_upsert,external_write_through,external_writes_set,field_history,form_declare,form_submit,home_add,io_comment_write,io_import_begin,io_infer_column,io_outbox_drain,io_restore,migrate_choice_keys,migrate_purge,migrate_reclass,migrate_split,migrate_undo,organization_clear,organization_contents,pipeline_declare,pipeline_gate_preview,portal_declare,portal_invite,portal_principal_bind,provenance_retention_days,provenance_write,query_across_homes,query_by_coordinates,query_rollup,record_delete,record_reparent,record_resolve,record_restore,record_update,record_write,record_write_many,relation_carry,relation_own,rule_declare,share_grant,sign_request_create,sign_request_sign,subscription_declare,table_archive,table_declare,table_share_outside_invite,value_restore,view_declare,work_approval_decide,work_approval_request,work_template_declare" },
3223
+ { code: "22004", raised_by: "_entity_custom_fields_guard,_share_write_person,_value_envelope,actor_word,agg_assert_key,agg_sql,anon_capture,anon_token_issue,anon_write,assert_client_may_reach,booking_declare,capture_submit,checklist_declare,context_resolve,dashboard_block_normalize,dashboard_declare,dashboard_window_sql,doc_render_write,doc_sign,doc_signature_write,doc_template_save,enrich_land,enrich_normalize,external_history_event,external_rows,external_source_declare,external_stub_upsert,external_write_through,external_writes_set,field_history,form_declare,form_submit,home_add,io_comment_write,io_import_begin,io_infer_column,io_outbox_drain,io_restore,migrate_choice_keys,migrate_purge,migrate_purge_hard,migrate_reclass,migrate_split,migrate_undo,organization_clear,organization_contents,pipeline_declare,pipeline_gate_preview,portal_declare,portal_invite,portal_principal_bind,provenance_retention_days,provenance_write,query_across_homes,query_by_coordinates,query_rollup,record_delete,record_reparent,record_resolve,record_restore,record_update,record_write,record_write_graph,record_write_many,relation_carry,relation_own,rule_declare,share_grant,sign_request_create,sign_request_sign,subscription_declare,table_archive,table_declare,table_share_outside_invite,value_restore,view_declare,work_approval_decide,work_approval_request,work_template_declare" },
966
3224
  { code: "22007", raised_by: "dashboard_window_sql" },
967
3225
  { code: "22012", raised_by: "rule_eval" },
968
- { code: "22023", raised_by: "_booking_availability,_entity_custom_fields_guard,_take_op_id,_value_envelope,_work_shape_guard,actor_word,agg_assert_key,agg_sql,anon_token_issue,booking_declare,containment_parent,dashboard_block_normalize,dashboard_window_sql,doc_render_body,doc_render_write,doc_signature_write,enrich_declare,enrich_land,enrich_normalize,enrich_pin,entity_value_write,external_history_event,external_source_declare,external_stub_upsert,external_write_through,field_history,field_update,io_export,io_import_begin,io_import_finish,io_import_plan,io_import_report,io_proposal_accept,list_portals,migrate_merge,migrate_reclass,my_levels,organization_clear,page_size,pin_agent_cells,pipeline_move,portal_declare,provenance_write,query_by_coordinates,query_rollup,read_records_archived,record_update,record_write_many,relation_carry,rule_eval,rule_members,share_grant,share_lane_set,sign_request_create,sign_request_sign,subscription_declare,table_rules,visibility_as_of,work_approval_request,work_list,work_slot_hold" },
3226
+ { code: "22023", raised_by: "_booking_availability,_entity_custom_fields_guard,_take_op_id,_value_envelope,_work_shape_guard,actor_word,agg_assert_key,agg_sql,anon_token_issue,booking_declare,containment_parent,dashboard_block_normalize,dashboard_window_sql,doc_render_body,doc_render_write,doc_signature_write,enrich_declare,enrich_land,enrich_normalize,enrich_pin,entity_value_write,external_history_event,external_source_declare,external_stub_upsert,external_write_through,field_history,field_update,io_export,io_import_begin,io_import_finish,io_import_plan,io_import_report,io_proposal_accept,list_portals,migrate_merge,migrate_reclass,my_levels,organization_clear,page_size,pin_agent_cells,pipeline_move,portal_declare,provenance_write,query_by_coordinates,query_rollup,read_records_archived,record_update,record_write_graph,record_write_many,relation_carry,rule_eval,rule_members,share_grant,share_lane_set,sign_request_create,sign_request_sign,subscription_declare,table_rules,visibility_as_of,work_approval_request,work_list,work_slot_hold" },
969
3227
  { code: "23503", raised_by: "_booking_availability,_checklist_instantiate,_containment_guard,_display_spec_for,_field_document_for,_field_type_parity_guard,_pipeline_stage_key,_record_rule_uses,agg_digest_assemble,anon_publish,anon_rate_take,anon_token_issue,anon_write,assert_organization_wall,booking_cancel,booking_confirm,booking_declare,booking_hold,booking_reschedule,capture_publish,checklist_declare,checklist_steps_table,comment_write,dashboard_declare,delete_rule,doc_sign,doc_template_save,enrich_declare,enrich_due,enrich_land,form_declare,form_submit,home_add,inbound_declare,inbound_mail_land,inbound_set,io_comment_write,io_import_begin,io_import_finish,io_import_report,io_import_rows,io_proposal_accept,migrate_demote,migrate_promote,pipeline_board,pipeline_declare,pipeline_move,pipeline_read,pipeline_transition_refusal,promote_field,promote_table,record_applicability,record_reparent,relation_carry,relation_own,resolve_first_match,rule_applies,rule_declare,rule_eval,rule_members,rule_run,sign_request_create,subscription_mute,subscription_preview,view_declare,work_set_state,work_take_assignment,work_template_instantiate" },
970
3228
  { code: "23505", raised_by: "_share_write_person,_unique_rule_holds,doc_sign,doc_signature_write,entity_field_declare,field_declare,home_add,inbound_declare,io_proposal_accept,relation_carry,relation_own,sign_request_cancel,sign_request_create,table_share_outside_resend,work_approval_decide,work_slot_hold" },
971
- { code: "23514", raised_by: "_checklist_instantiate,_checklist_step_guard,_containment_guard,_dated_values_guard,_derived_fields,_display_spec_for,_entity_custom_fields_guard,_field_class_guard,_field_document_for,_field_shape_guard,_field_type_parity_guard,_merge_field_shape_guard,_merge_field_temporal_guard,_promoted_field_cap_guard,_record_rule_uses,_resolve_choice_words,_rule_shape_guard,_rule_topology_guard,_store_relation_edge_names_its_field,_table_columns_word_guard,_table_shape_guard,_undeclared_key_guard,_value_envelope,_with_display,_work_shape_guard,_workdoors_approval_guard,assert_columns_are_defined,assert_entity_is_organization_scoped,booking_declare,capture_publish,capture_sheet_declare,checklist_declare,checklist_step_complete,doc_sign,doc_signature_write,doc_template_save,entity_field_declare,entity_field_retire,entity_field_update,entity_records_find,entity_table,field_declare,field_retire,field_update,home_add,io_comment_write,io_import_rows,migrate_merge,portal_archive,portal_restore,relation_carry,relation_own,sign_request_create,sign_request_sign,table_declare,validate_value_envelope,validate_values,work_set_state,work_slots_declare,work_take_assignment,work_template_instantiate" },
3229
+ { code: "23514", raised_by: "_checklist_instantiate,_checklist_step_guard,_containment_guard,_dated_values_guard,_derived_fields,_display_spec_for,_entity_custom_fields_guard,_field_class_guard,_field_document_for,_field_shape_guard,_field_type_parity_guard,_merge_field_shape_guard,_merge_field_temporal_guard,_promoted_field_cap_guard,_record_rule_uses,_relation_halves_agree,_resolve_choice_words,_rule_shape_guard,_rule_topology_guard,_store_relation_edge_names_its_field,_table_columns_word_guard,_table_shape_guard,_undeclared_key_guard,_value_envelope,_with_display,_work_shape_guard,_workdoors_approval_guard,assert_columns_are_defined,assert_entity_is_organization_scoped,booking_declare,capture_publish,capture_sheet_declare,checklist_declare,checklist_step_complete,doc_sign,doc_signature_write,doc_template_save,entity_field_declare,entity_field_retire,entity_field_update,entity_records_find,entity_table,field_declare,field_retire,field_update,home_add,io_comment_write,io_import_rows,migrate_merge,migrate_purge_hard,portal_archive,portal_restore,record_write_graph,relation_carry,relation_own,sign_request_create,sign_request_sign,table_declare,validate_value_envelope,validate_values,work_set_state,work_slots_declare,work_take_assignment,work_template_instantiate" },
972
3230
  { code: "40001", raised_by: "has_visibility_at" },
973
- { code: "42501", raised_by: "_doc_render_immutable,_doc_signature_immutable,_field_definition_write,_field_write_door,_rule_definition_write,_store_door,agent_table_claim,anon_capture,anon_inbound_land,anon_publish,anon_token_issue,anon_token_verify,anon_write,assert_client_may_change,assert_client_may_open,assert_client_may_reach,assert_may_know_table,assert_organization_admin,assert_store_door,booking_confirm,booking_declare,booking_hold,capture_submit,checklist_run,comment_write,conversation_scope_bind,conversation_scope_unbind,doc_sign,enrich_declare,enrich_due,enrich_land,enrich_normalize,entity_field_declare,entity_field_retire,entity_field_update,entity_value_write,external_write_through,form_declare,form_submit,inbound_mail_land,io_comment_resolve,io_comment_write,io_import_begin,io_import_finish,io_restore,migrate_purge,migrate_reclass,my_levels,organization_clear,portal_declare,portal_invitation,portal_invite,portal_invite_accept,portal_principal_bind,promote_table,query_visibility_parity,read_record,read_records,read_records_archived,read_records_by_ids,read_records_matching,record_table,share_grant,subscription_mute,subscription_preview,table_share_outside_accept,table_share_outside_invite,table_share_outside_resend,visibility_as_of,work_approval_decide,work_approval_read,work_approval_request,work_person" },
3231
+ { code: "42501", raised_by: "_doc_render_immutable,_doc_signature_immutable,_field_definition_write,_field_write_door,_rule_definition_write,_store_door,agent_table_claim,anon_capture,anon_inbound_land,anon_publish,anon_token_issue,anon_token_verify,anon_write,assert_client_may_change,assert_client_may_open,assert_client_may_reach,assert_may_know_table,assert_organization_admin,assert_store_door,booking_confirm,booking_declare,booking_hold,capture_submit,checklist_run,comment_write,conversation_scope_bind,conversation_scope_unbind,doc_sign,enrich_declare,enrich_due,enrich_land,enrich_normalize,entity_field_declare,entity_field_retire,entity_field_update,entity_value_write,external_write_through,form_declare,form_submit,inbound_mail_land,io_comment_resolve,io_comment_write,io_import_begin,io_import_finish,io_restore,migrate_purge,migrate_purge_hard,migrate_reclass,my_levels,organization_clear,portal_declare,portal_invitation,portal_invite,portal_invite_accept,portal_principal_bind,promote_table,query_visibility_parity,read_record,read_records,read_records_archived,read_records_by_ids,read_records_matching,record_table,record_write_graph,share_grant,subscription_mute,subscription_preview,table_share_outside_accept,table_share_outside_invite,table_share_outside_resend,visibility_as_of,work_approval_decide,work_approval_read,work_approval_request,work_person" },
974
3232
  { code: "42703", raised_by: "entity_table,portal_declare" },
975
3233
  { code: "53400", raised_by: "anon_rate_take,delete_cascade_closure,enrich_due,enrich_land,promote_field" },
976
3234
  { code: "54001", raised_by: "record_delete" },
@@ -2013,6 +4271,21 @@ var OWED_BY = {
2013
4271
  table_propose: "W5-AGENT \u2014 AGT-8, the proposal and its approvers",
2014
4272
  merge_field_resolve: "W5-MERGE-B \u2014 the resolver's server half",
2015
4273
  record_query: "W1-INDEX / W5-SRV \u2014 the promoted-field query path",
4274
+ // Lane GRID-PRIMITIVES (2026-09-22): on the rehearsal branch; they reach the main database at
4275
+ // the chair's 01:00–04:00 PT apply, and `pnpm records:generate` then lists them in
4276
+ // STORE_DOORS. Until then each call answers door_absent naming this line — never a guess.
4277
+ table_decorate: "GRID-PRIMITIVES G1 \u2014 gridprim_a_table_wears_its_colors_and_its_layout.sql (chair's production apply)",
4278
+ table_decorations: "GRID-PRIMITIVES G1 \u2014 gridprim_a_table_wears_its_colors_and_its_layout.sql (chair's production apply)",
4279
+ grid_layout: "GRID-PRIMITIVES G1 \u2014 gridprim_a_table_wears_its_colors_and_its_layout.sql (chair's production apply)",
4280
+ formula_parse: "GRID-PRIMITIVES G3 \u2014 gridprim_a_formula_is_typed_and_the_store_works_it_out.sql (chair's production apply)",
4281
+ action_declare: "GRID-PRIMITIVES G2 \u2014 gridprim_a_row_action_runs_the_whole_selection_at_once.sql (chair's production apply)",
4282
+ row_actions: "GRID-PRIMITIVES G2 \u2014 gridprim_a_row_action_runs_the_whole_selection_at_once.sql (chair's production apply)",
4283
+ action_run: "GRID-PRIMITIVES G2 \u2014 gridprim_a_row_action_runs_the_whole_selection_at_once.sql (chair's production apply)",
4284
+ table_webhook_declare: "GRID-PRIMITIVES G4 \u2014 gridprim_every_row_change_reaches_the_webhook.sql (chair's production apply)",
4285
+ table_webhooks: "GRID-PRIMITIVES G4 \u2014 gridprim_every_row_change_reaches_the_webhook.sql (chair's production apply)",
4286
+ table_webhook_archive: "GRID-PRIMITIVES G4 \u2014 gridprim_every_row_change_reaches_the_webhook.sql (chair's production apply)",
4287
+ table_from_example: "GRID-PRIMITIVES G5 \u2014 gridprim_a_table_can_start_from_a_real_example.sql (chair's production apply)",
4288
+ autonumber_backfill: "GRID-PRIMITIVES G5 \u2014 gridprim_a_table_can_start_from_a_real_example.sql (chair's production apply)",
2016
4289
  rule_declare: "W1-RULE \u2014 `custom.record_write` writes `data_class = 'record'`, so the ONE write door cannot make a Rule record; declaring a Rule (and therefore a DOOR-18 subscription) needs a door of its own"
2017
4290
  };
2018
4291
  var TRUST_SCHEMA = "iam";
@@ -2034,6 +4307,18 @@ var TRUST_DOORS = {
2034
4307
  worldPublishAdmit: "world_publish_admit",
2035
4308
  claimWorldNamespace: "claim_world_namespace"
2036
4309
  };
4310
+ var WORKBENCH_SCHEMA = "workbench";
4311
+ var WORKBENCH_DOORS = {
4312
+ /**
4313
+ * What a page of the OLDER store's relation cells reads, in one round trip.
4314
+ * Same answer shape as `custom.relation_words_many`, same withheld sentence,
4315
+ * and the ladder is asked per record inside it — so batching buys a round
4316
+ * trip and never a disclosure. An id that names nothing comes back as
4317
+ * NOTHING rather than as the withheld sentence, which is what makes an
4318
+ * unresolvable cell distinguishable from a refused one in that store.
4319
+ */
4320
+ udtRowWordsMany: "udt_row_words_many"
4321
+ };
2037
4322
  var DOOR_NAMES = new Set(STORE_DOORS.map((d) => d.name));
2038
4323
  function doorExists(name) {
2039
4324
  return DOOR_NAMES.has(name);
@@ -2086,6 +4371,17 @@ var DOORS = {
2086
4371
  queryTableAsOf: "query_table_as_of",
2087
4372
  recordWrite: "record_write",
2088
4373
  recordWriteMany: "record_write_many",
4374
+ // A PARENT, THE EDGES IT STANDS ON AND THE ROWS THAT BELONG TO IT — ALL OR NOTHING.
4375
+ // `recordWrite` and `recordWriteMany` are each ONE statement, so a caller that needs a
4376
+ // parent, its provenance edge and its child rows to land together had no door at all: a
4377
+ // loop is N transactions, and a failure on child nineteen leaves a parent standing without
4378
+ // the lines it promised. `custom.record_write_graph` is one statement, so it is one
4379
+ // transaction — and it is not a second write path: it CALLS `custom.record_write_many` for
4380
+ // the rows, `public.assoc_add` for an edge that points out of the store, and
4381
+ // `platform.relation_set` for the parent's own declared relation to its children. Every
4382
+ // guard, every trigger and the same editor rung, once. A refusal anywhere refuses the whole
4383
+ // graph, by name, and nothing is written.
4384
+ recordWriteGraph: "record_write_graph",
2089
4385
  recordUpdate: "record_update",
2090
4386
  recordDelete: "record_delete",
2091
4387
  recordRestore: "record_restore",
@@ -2481,6 +4777,20 @@ var DOORS = {
2481
4777
  checklistRuns: "checklist_runs",
2482
4778
  checklistStepComplete: "checklist_step_complete",
2483
4779
  checklistStepRefusal: "checklist_step_refusal",
4780
+ // THE GRID (lane GRID-PRIMITIVES, 2026-09-22) — what the /data grid rebuild calls. See ../grid.ts.
4781
+ tableDecorate: "table_decorate",
4782
+ tableDecorations: "table_decorations",
4783
+ gridLayout: "grid_layout",
4784
+ formulaParse: "formula_parse",
4785
+ actionDeclare: "action_declare",
4786
+ rowActions: "row_actions",
4787
+ actionRun: "action_run",
4788
+ tableWebhookDeclare: "table_webhook_declare",
4789
+ tableWebhooks: "table_webhooks",
4790
+ tableWebhookArchive: "table_webhook_archive",
4791
+ tableFromExample: "table_from_example",
4792
+ autonumberBackfill: "autonumber_backfill",
4793
+ ioExport: "io_export",
2484
4794
  // Declared here BECAUSE they do not exist yet: naming them is what makes the
2485
4795
  // absence visible to `pnpm check:store-registry` and to the suite.
2486
4796
  metadataSearch: "metadata_search",
@@ -2700,6 +5010,15 @@ function createRecordsClient(config) {
2700
5010
  }
2701
5011
  return ok(response.data);
2702
5012
  }
5013
+ async function workbenchDoor(door, args, where) {
5014
+ const response = await config.dataSource.rpc(door, args, { schema: WORKBENCH_SCHEMA });
5015
+ if (response.error) {
5016
+ const refusal = mapPgError(response.error, where);
5017
+ scream({ code: refusal.code, message: refusal.message, ...refusal.hint ? { hint: refusal.hint } : {}, where });
5018
+ return err(refusal);
5019
+ }
5020
+ return ok(response.data);
5021
+ }
2703
5022
  function unfold(document) {
2704
5023
  const raw = document ?? {};
2705
5024
  const hidden = raw._hidden ?? {};
@@ -2739,6 +5058,25 @@ function createRecordsClient(config) {
2739
5058
  "recordWriteMany"
2740
5059
  );
2741
5060
  },
5061
+ async recordWriteGraph({ table_id, parent, children, edges }) {
5062
+ const opId = mintOpId();
5063
+ return callDoor(
5064
+ DOORS.recordWriteGraph,
5065
+ {
5066
+ p_organization_id: org,
5067
+ p_table_id: table_id,
5068
+ p_parent: { ...parent, _op_id: opId },
5069
+ p_edges: edges ?? [],
5070
+ p_children: (children ?? []).map((child) => ({
5071
+ data: child.data,
5072
+ role: child.role,
5073
+ ...child.table_id === void 0 ? {} : { table_id: child.table_id },
5074
+ ...child.position === void 0 ? {} : { position: child.position }
5075
+ }))
5076
+ },
5077
+ "recordWriteGraph"
5078
+ );
5079
+ },
2742
5080
  async recordUpdate({ record_id, patch, expectedVersion }) {
2743
5081
  const result = await callDoor(
2744
5082
  DOORS.recordUpdate,
@@ -3124,16 +5462,26 @@ function createRecordsClient(config) {
3124
5462
  "relationWords"
3125
5463
  );
3126
5464
  },
3127
- async relationWordsMany({ field_id, record_ids }) {
3128
- const result = await callDoor(
5465
+ async relationWordsMany(args) {
5466
+ const older = args.store === "older";
5467
+ const result = older ? await workbenchDoor(
5468
+ WORKBENCH_DOORS.udtRowWordsMany,
5469
+ {
5470
+ p_organization_id: org,
5471
+ p_display: args.display ?? null,
5472
+ p_row_ids: args.record_ids
5473
+ },
5474
+ "relationWordsMany(older)"
5475
+ ) : await callDoor(
3129
5476
  DOORS.relationWordsMany,
3130
- { p_organization_id: org, p_field_id: field_id, p_record_ids: record_ids },
5477
+ { p_organization_id: org, p_field_id: args.field_id, p_record_ids: args.record_ids },
3131
5478
  "relationWordsMany"
3132
5479
  );
3133
5480
  if (!result.ok) return result;
3134
5481
  const map = {};
3135
5482
  for (const row of result.data ?? []) {
3136
- if (row?.record_id && typeof row.words === "string") map[row.record_id] = row.words;
5483
+ const id = row?.record_id ?? row?.row_id;
5484
+ if (id && typeof row.words === "string") map[id] = row.words;
3137
5485
  }
3138
5486
  return { ok: true, data: map };
3139
5487
  },
@@ -4534,6 +6882,132 @@ function createRecordsClient(config) {
4534
6882
  async storeIsOpen() {
4535
6883
  return callDoor(DOORS.storeIsOpen, { p_organization_id: org }, "storeIsOpen");
4536
6884
  },
6885
+ // ── THE GRID (lane GRID-PRIMITIVES) ──────────────────────────────────────
6886
+ async tableDecorate({ table_id, path, value }) {
6887
+ return callDoor(
6888
+ DOORS.tableDecorate,
6889
+ { p_organization_id: org, p_table_id: table_id, p_path: path, p_value: value ?? null },
6890
+ "tableDecorate"
6891
+ );
6892
+ },
6893
+ async tableDecorations({ table_id }) {
6894
+ return callDoor(
6895
+ DOORS.tableDecorations,
6896
+ { p_organization_id: org, p_table_id: table_id },
6897
+ "tableDecorations"
6898
+ );
6899
+ },
6900
+ async gridLayout({ table_id, view_id }) {
6901
+ return callDoor(
6902
+ DOORS.gridLayout,
6903
+ { p_organization_id: org, p_table_id: table_id, p_view_id: view_id ?? null },
6904
+ "gridLayout"
6905
+ );
6906
+ },
6907
+ async formulaParse({ table_id, text }) {
6908
+ return callDoor(
6909
+ DOORS.formulaParse,
6910
+ { p_organization_id: org, p_table_id: table_id, p_text: text },
6911
+ "formulaParse"
6912
+ );
6913
+ },
6914
+ async actionDeclare({ table_id, actions }) {
6915
+ return callDoor(
6916
+ DOORS.actionDeclare,
6917
+ { p_organization_id: org, p_table_id: table_id, p_actions: actions },
6918
+ "actionDeclare"
6919
+ );
6920
+ },
6921
+ async rowActions({ table_id }) {
6922
+ return callDoor(
6923
+ DOORS.rowActions,
6924
+ { p_organization_id: org, p_table_id: table_id },
6925
+ "rowActions"
6926
+ );
6927
+ },
6928
+ async actionRun({ action_id, record_ids }) {
6929
+ return callDoor(
6930
+ DOORS.actionRun,
6931
+ { p_organization_id: org, p_action_id: action_id, p_record_ids: record_ids },
6932
+ "actionRun"
6933
+ );
6934
+ },
6935
+ async tableWebhookDeclare({ table_id, target_url, events, description }) {
6936
+ return callDoor(
6937
+ DOORS.tableWebhookDeclare,
6938
+ {
6939
+ p_organization_id: org,
6940
+ p_table_id: table_id,
6941
+ p_target_url: target_url,
6942
+ p_events: events ?? null,
6943
+ p_description: description ?? null
6944
+ },
6945
+ "tableWebhookDeclare"
6946
+ );
6947
+ },
6948
+ async tableWebhooks({ table_id }) {
6949
+ return callDoor(
6950
+ DOORS.tableWebhooks,
6951
+ { p_organization_id: org, p_table_id: table_id },
6952
+ "tableWebhooks"
6953
+ );
6954
+ },
6955
+ async tableWebhookArchive({ webhook_id }) {
6956
+ return callDoor(
6957
+ DOORS.tableWebhookArchive,
6958
+ { p_organization_id: org, p_webhook_id: webhook_id },
6959
+ "tableWebhookArchive"
6960
+ );
6961
+ },
6962
+ async tableFromExample({ home_id, useCaseId }) {
6963
+ const { loadUseCase: loadUseCase2 } = await Promise.resolve().then(() => (init_registry(), registry_exports));
6964
+ let spec;
6965
+ try {
6966
+ spec = exampleSpec(await loadUseCase2(useCaseId));
6967
+ } catch (e) {
6968
+ const refusal = {
6969
+ code: "invalid_argument",
6970
+ message: e instanceof Error ? e.message : String(e),
6971
+ hint: "Offer an example from useCaseIds() in @ai-matrx/records/use-cases. Nothing was created."
6972
+ };
6973
+ scream({ code: refusal.code, message: refusal.message, ...refusal.hint ? { hint: refusal.hint } : {}, where: "tableFromExample" });
6974
+ return err(refusal);
6975
+ }
6976
+ return callDoor(
6977
+ DOORS.tableFromExample,
6978
+ { p_organization_id: org, p_home_id: home_id, p_example: spec },
6979
+ "tableFromExample"
6980
+ );
6981
+ },
6982
+ async autonumberBackfill({ field_id }) {
6983
+ return callDoor(
6984
+ DOORS.autonumberBackfill,
6985
+ { p_organization_id: org, p_field_id: field_id },
6986
+ "autonumberBackfill"
6987
+ );
6988
+ },
6989
+ async ioExport({ table_id, columns, limit }) {
6990
+ return callDoor(
6991
+ DOORS.ioExport,
6992
+ {
6993
+ p_organization_id: org,
6994
+ p_table_id: table_id,
6995
+ p_columns: columns ?? null,
6996
+ p_limit: limit ?? null,
6997
+ p_required: "viewer"
6998
+ },
6999
+ "ioExport"
7000
+ );
7001
+ },
7002
+ async exportXlsx({ table_id, columns, limit, labels, sheetLabel }) {
7003
+ const page = await client.ioExport({
7004
+ table_id,
7005
+ ...columns !== void 0 ? { columns } : {},
7006
+ ...limit !== void 0 ? { limit } : {}
7007
+ });
7008
+ if (!page.ok) return err(page.error);
7009
+ return ok(await exportPageXlsx(page.data, labels ?? {}, sheetLabel ?? "Records"));
7010
+ },
4537
7011
  async myLevels({ ids, subject }) {
4538
7012
  if (ids.length === 0) return ok([]);
4539
7013
  const answered = await callDoor(
@@ -5248,6 +7722,7 @@ function fieldKindFor(field, kernel) {
5248
7722
  return "text";
5249
7723
  }
5250
7724
  }
7725
+ var UUID_TEXT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
5251
7726
  var TRUE_WORDS = /* @__PURE__ */ new Set(["true", "yes", "y", "1", "\u2713", "x", "checked", "on"]);
5252
7727
  var FALSE_WORDS = /* @__PURE__ */ new Set(["false", "no", "n", "0", "", "unchecked", "off"]);
5253
7728
  function coercionLabel(field) {
@@ -5339,11 +7814,23 @@ function coerceTypedAnswer(field, raw, opts = {}) {
5339
7814
  // id belongs, and every filter, colour and rollup built on that column
5340
7815
  // would stop agreeing with it. So it is refused and the person is told
5341
7816
  // which control does hold it.
7817
+ //
7818
+ // BUT AN ID IS AN IDENTITY (RELATION-TARGETS, 2026-09-23). A Person or File
7819
+ // column holds the kernel Person / File record, and the store itself now
7820
+ // turns the id a writer actually holds — a member's user id, an uploaded
7821
+ // file's id, or the record's own id — into that record at every write door
7822
+ // (`custom.relation_kernel_record`), refusing anything else in its own
7823
+ // words ("… names someone who is not a member of …"). So an import column
7824
+ // of member ids, or an agent handing over the file it just uploaded, is a
7825
+ // value and not a refusal; the store, not this mirror, decides whether the
7826
+ // id is somebody here.
5342
7827
  case "member":
7828
+ if (UUID_TEXT.test(text)) return { value: text.toLowerCase() };
5343
7829
  return {
5344
7830
  refusal: `${label} names a person in this organization, so it is chosen rather than typed. Open it and pick them.`
5345
7831
  };
5346
7832
  case "attachment":
7833
+ if (UUID_TEXT.test(text)) return { value: text.toLowerCase() };
5347
7834
  return {
5348
7835
  refusal: `${label} holds a file, which cannot arrive as typed-in text. Open it and attach the file.`
5349
7836
  };