@uwmd/core 1.1.2 → 1.3.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.
Files changed (153) hide show
  1. package/README.md +3 -3
  2. package/dist/agents/bancroft.d.ts +22 -1
  3. package/dist/agents/bancroft.d.ts.map +1 -1
  4. package/dist/agents/bancroft.js +86 -60
  5. package/dist/agents/bancroft.js.map +1 -1
  6. package/dist/agents/provider.d.ts +62 -0
  7. package/dist/agents/provider.d.ts.map +1 -0
  8. package/dist/agents/provider.js +28 -0
  9. package/dist/agents/provider.js.map +1 -0
  10. package/dist/agents/providers/anthropic.d.ts +20 -0
  11. package/dist/agents/providers/anthropic.d.ts.map +1 -0
  12. package/dist/agents/providers/anthropic.js +104 -0
  13. package/dist/agents/providers/anthropic.js.map +1 -0
  14. package/dist/agents/providers/replay.d.ts +46 -0
  15. package/dist/agents/providers/replay.d.ts.map +1 -0
  16. package/dist/agents/providers/replay.js +162 -0
  17. package/dist/agents/providers/replay.js.map +1 -0
  18. package/dist/agents/schemas.d.ts +3 -3
  19. package/dist/agents/schemas.d.ts.map +1 -1
  20. package/dist/agents/schemas.js.map +1 -1
  21. package/dist/browser.d.ts +26 -3
  22. package/dist/browser.d.ts.map +1 -1
  23. package/dist/browser.js +23 -3
  24. package/dist/browser.js.map +1 -1
  25. package/dist/calc/builtins.d.ts +10 -0
  26. package/dist/calc/builtins.d.ts.map +1 -1
  27. package/dist/calc/builtins.js +64 -42
  28. package/dist/calc/builtins.js.map +1 -1
  29. package/dist/calc/errors.js +1 -1
  30. package/dist/calc/evaluator.js +6 -2
  31. package/dist/calc/evaluator.js.map +1 -1
  32. package/dist/calc/index.d.ts +7 -0
  33. package/dist/calc/index.d.ts.map +1 -1
  34. package/dist/calc/index.js +13 -1
  35. package/dist/calc/index.js.map +1 -1
  36. package/dist/calc/quantize.d.ts +56 -0
  37. package/dist/calc/quantize.d.ts.map +1 -0
  38. package/dist/calc/quantize.js +116 -0
  39. package/dist/calc/quantize.js.map +1 -0
  40. package/dist/cli-packages.d.ts +11 -0
  41. package/dist/cli-packages.d.ts.map +1 -0
  42. package/dist/cli-packages.js +177 -0
  43. package/dist/cli-packages.js.map +1 -0
  44. package/dist/cli.js +424 -28
  45. package/dist/cli.js.map +1 -1
  46. package/dist/context.js +23 -23
  47. package/dist/deal-package-context.d.ts +52 -0
  48. package/dist/deal-package-context.d.ts.map +1 -0
  49. package/dist/deal-package-context.js +132 -0
  50. package/dist/deal-package-context.js.map +1 -0
  51. package/dist/deal-package-zip.d.ts +36 -0
  52. package/dist/deal-package-zip.d.ts.map +1 -0
  53. package/dist/deal-package-zip.js +132 -0
  54. package/dist/deal-package-zip.js.map +1 -0
  55. package/dist/deal-package.d.ts +82 -0
  56. package/dist/deal-package.d.ts.map +1 -0
  57. package/dist/deal-package.js +189 -0
  58. package/dist/deal-package.js.map +1 -0
  59. package/dist/defaults.d.ts +48 -0
  60. package/dist/defaults.d.ts.map +1 -1
  61. package/dist/defaults.js +512 -0
  62. package/dist/defaults.js.map +1 -1
  63. package/dist/index.d.ts +32 -3
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +27 -3
  66. package/dist/index.js.map +1 -1
  67. package/dist/init.js +1 -1
  68. package/dist/init.js.map +1 -1
  69. package/dist/integrity.d.ts +9 -0
  70. package/dist/integrity.d.ts.map +1 -1
  71. package/dist/integrity.js +12 -2
  72. package/dist/integrity.js.map +1 -1
  73. package/dist/lease-abstract.d.ts +82 -0
  74. package/dist/lease-abstract.d.ts.map +1 -0
  75. package/dist/lease-abstract.js +183 -0
  76. package/dist/lease-abstract.js.map +1 -0
  77. package/dist/lite-bridge.d.ts +58 -0
  78. package/dist/lite-bridge.d.ts.map +1 -0
  79. package/dist/lite-bridge.js +525 -0
  80. package/dist/lite-bridge.js.map +1 -0
  81. package/dist/lite.d.ts +63 -0
  82. package/dist/lite.d.ts.map +1 -0
  83. package/dist/lite.js +362 -0
  84. package/dist/lite.js.map +1 -0
  85. package/dist/modules.d.ts.map +1 -1
  86. package/dist/modules.js +278 -13
  87. package/dist/modules.js.map +1 -1
  88. package/dist/packs/excel-emit.d.ts +18 -1
  89. package/dist/packs/excel-emit.d.ts.map +1 -1
  90. package/dist/packs/excel-emit.js +18 -1
  91. package/dist/packs/excel-emit.js.map +1 -1
  92. package/dist/packs/hospitality.d.ts +3 -0
  93. package/dist/packs/hospitality.d.ts.map +1 -0
  94. package/dist/packs/hospitality.js +122 -0
  95. package/dist/packs/hospitality.js.map +1 -0
  96. package/dist/packs/index.d.ts +5 -1
  97. package/dist/packs/index.d.ts.map +1 -1
  98. package/dist/packs/index.js +13 -1
  99. package/dist/packs/index.js.map +1 -1
  100. package/dist/packs/land.d.ts +3 -0
  101. package/dist/packs/land.d.ts.map +1 -0
  102. package/dist/packs/land.js +124 -0
  103. package/dist/packs/land.js.map +1 -0
  104. package/dist/packs/senior-housing.d.ts +3 -0
  105. package/dist/packs/senior-housing.d.ts.map +1 -0
  106. package/dist/packs/senior-housing.js +123 -0
  107. package/dist/packs/senior-housing.js.map +1 -0
  108. package/dist/packs/student-housing.d.ts +3 -0
  109. package/dist/packs/student-housing.d.ts.map +1 -0
  110. package/dist/packs/student-housing.js +124 -0
  111. package/dist/packs/student-housing.js.map +1 -0
  112. package/dist/parser.d.ts +9 -0
  113. package/dist/parser.d.ts.map +1 -1
  114. package/dist/parser.js +40 -6
  115. package/dist/parser.js.map +1 -1
  116. package/dist/protocol.d.ts +69 -2
  117. package/dist/protocol.d.ts.map +1 -1
  118. package/dist/protocol.js +109 -1
  119. package/dist/protocol.js.map +1 -1
  120. package/dist/receipts.d.ts +216 -0
  121. package/dist/receipts.d.ts.map +1 -0
  122. package/dist/receipts.js +554 -0
  123. package/dist/receipts.js.map +1 -0
  124. package/dist/report.js +165 -165
  125. package/dist/runner.d.ts +13 -0
  126. package/dist/runner.d.ts.map +1 -1
  127. package/dist/runner.js +5 -5
  128. package/dist/runner.js.map +1 -1
  129. package/dist/source-representation.d.ts +40 -0
  130. package/dist/source-representation.d.ts.map +1 -0
  131. package/dist/source-representation.js +114 -0
  132. package/dist/source-representation.js.map +1 -0
  133. package/dist/types.d.ts +9 -0
  134. package/dist/types.d.ts.map +1 -1
  135. package/dist/types.js +34 -0
  136. package/dist/types.js.map +1 -1
  137. package/dist/uwcsv.d.ts.map +1 -1
  138. package/dist/uwcsv.js +10 -78
  139. package/dist/uwcsv.js.map +1 -1
  140. package/dist/uwxml.d.ts.map +1 -1
  141. package/dist/uwxml.js +10 -2
  142. package/dist/uwxml.js.map +1 -1
  143. package/dist/validator.js +10 -10
  144. package/dist/validator.js.map +1 -1
  145. package/dist/version.d.ts +3 -0
  146. package/dist/version.d.ts.map +1 -0
  147. package/dist/version.js +8 -0
  148. package/dist/version.js.map +1 -0
  149. package/dist/zip-safety.d.ts +15 -0
  150. package/dist/zip-safety.d.ts.map +1 -0
  151. package/dist/zip-safety.js +109 -0
  152. package/dist/zip-safety.js.map +1 -0
  153. package/package.json +12 -3
@@ -0,0 +1,122 @@
1
+ // Canonical hospitality calc pack.
2
+ //
3
+ // Single source of truth for hospitality derived metrics. Hotels size by keys
4
+ // rather than square feet, and their distinctive operating statistics — ADR,
5
+ // RevPAR, occupancy, and GOP margin — are ratios over room nights rather than
6
+ // over area. Available and occupied room nights live in `rent_roll` (the same
7
+ // place self-storage keeps occupied units); `noi_model` carries the USALI-shaped
8
+ // departmental income and the gross operating profit subtotal.
9
+ export const HOSPITALITY_PACK = {
10
+ manifest_version: '1',
11
+ id: 'org.uwmd.pack.hospitality',
12
+ name: 'Hospitality Starter Pack',
13
+ version: '1.0.0',
14
+ description: 'Fourteen derived metrics for hospitality underwriting: cap rate, LTV, LTC, DSCR, debt yield, $/key, loan/key, NOI/key, expense ratio, cash-on-cash, occupancy, ADR, RevPAR, and GOP margin.',
15
+ authors: ['UW Markdown Working Group'],
16
+ license: 'MIT',
17
+ requires_protocol: '^1.0.0',
18
+ requires_format: '^1.1.0',
19
+ requires_tier: 'tier-3-calc-host',
20
+ asset_classes: ['hospitality'],
21
+ calculations: [
22
+ {
23
+ id: 'cap_rate',
24
+ label: 'Cap Rate',
25
+ formula: 'noi_model.net_operating_income / valuation.purchase_price',
26
+ unit: '%',
27
+ deterministic: true,
28
+ },
29
+ {
30
+ id: 'ltv',
31
+ label: 'LTV',
32
+ formula: 'debt_structure.loan_amount / valuation.purchase_price',
33
+ unit: '%',
34
+ deterministic: true,
35
+ },
36
+ {
37
+ id: 'ltc',
38
+ label: 'LTC',
39
+ formula: 'debt_structure.loan_amount / sources_uses.uses.total',
40
+ unit: '%',
41
+ deterministic: true,
42
+ },
43
+ {
44
+ id: 'dscr',
45
+ label: 'DSCR',
46
+ formula: 'noi_model.net_operating_income / debt_structure.annual_debt_service',
47
+ unit: 'x',
48
+ deterministic: true,
49
+ },
50
+ {
51
+ id: 'debt_yield',
52
+ label: 'Debt Yield',
53
+ formula: 'noi_model.net_operating_income / debt_structure.loan_amount',
54
+ unit: '%',
55
+ deterministic: true,
56
+ },
57
+ {
58
+ id: 'price_per_key',
59
+ label: 'Price / Key',
60
+ formula: 'valuation.purchase_price / property.keys',
61
+ unit: '$',
62
+ deterministic: true,
63
+ },
64
+ {
65
+ id: 'loan_per_key',
66
+ label: 'Loan / Key',
67
+ formula: 'debt_structure.loan_amount / property.keys',
68
+ unit: '$',
69
+ deterministic: true,
70
+ },
71
+ {
72
+ id: 'noi_per_key',
73
+ label: 'NOI / Key',
74
+ formula: 'noi_model.net_operating_income / property.keys',
75
+ unit: '$',
76
+ deterministic: true,
77
+ },
78
+ {
79
+ id: 'expense_ratio',
80
+ label: 'Operating Expense Ratio',
81
+ formula: 'noi_model.expenses.total_operating_expenses / noi_model.income.effective_gross_income',
82
+ unit: '%',
83
+ deterministic: true,
84
+ },
85
+ {
86
+ id: 'cash_on_cash',
87
+ label: 'Cash-on-Cash',
88
+ formula: '(noi_model.net_operating_income - debt_structure.annual_debt_service) / sources_uses.sources.sponsor_equity',
89
+ unit: '%',
90
+ deterministic: true,
91
+ },
92
+ {
93
+ id: 'occupancy',
94
+ label: 'Occupancy',
95
+ formula: 'rent_roll.occupied_room_nights / rent_roll.available_room_nights',
96
+ unit: '%',
97
+ deterministic: true,
98
+ },
99
+ {
100
+ id: 'adr',
101
+ label: 'ADR',
102
+ formula: 'noi_model.income.rooms_revenue / rent_roll.occupied_room_nights',
103
+ unit: '$',
104
+ deterministic: true,
105
+ },
106
+ {
107
+ id: 'revpar',
108
+ label: 'RevPAR',
109
+ formula: 'noi_model.income.rooms_revenue / rent_roll.available_room_nights',
110
+ unit: '$',
111
+ deterministic: true,
112
+ },
113
+ {
114
+ id: 'gop_margin',
115
+ label: 'GOP Margin',
116
+ formula: 'noi_model.gross_operating_profit / noi_model.income.effective_gross_income',
117
+ unit: '%',
118
+ deterministic: true,
119
+ },
120
+ ],
121
+ };
122
+ //# sourceMappingURL=hospitality.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hospitality.js","sourceRoot":"","sources":["../../src/packs/hospitality.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,11 @@ export { OFFICE_PACK } from './office.js';
4
4
  export { RETAIL_PACK } from './retail.js';
5
5
  export { INDUSTRIAL_PACK } from './industrial.js';
6
6
  export { SELF_STORAGE_PACK } from './self-storage.js';
7
- export { emitFromAst, emitExcelFormula, ExcelEmitError, type ExcelEmitOptions, } from './excel-emit.js';
7
+ export { HOSPITALITY_PACK } from './hospitality.js';
8
+ export { SENIOR_HOUSING_PACK } from './senior-housing.js';
9
+ export { STUDENT_HOUSING_PACK } from './student-housing.js';
10
+ export { LAND_PACK } from './land.js';
11
+ export { emitFromAst, emitExcelFormula, emitCalcExcelFormula, ExcelEmitError, type ExcelEmitOptions, } from './excel-emit.js';
8
12
  /**
9
13
  * Look up the built-in calc pack for an asset class. Returns null when no pack
10
14
  * is registered (callers may fall back to the multifamily pack or skip metrics).
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/packs/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAOrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC;AAezB;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAE/E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/packs/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAWrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC;AAmBzB;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAE/E"}
@@ -9,12 +9,20 @@ import { OFFICE_PACK } from './office.js';
9
9
  import { RETAIL_PACK } from './retail.js';
10
10
  import { INDUSTRIAL_PACK } from './industrial.js';
11
11
  import { SELF_STORAGE_PACK } from './self-storage.js';
12
+ import { HOSPITALITY_PACK } from './hospitality.js';
13
+ import { SENIOR_HOUSING_PACK } from './senior-housing.js';
14
+ import { STUDENT_HOUSING_PACK } from './student-housing.js';
15
+ import { LAND_PACK } from './land.js';
12
16
  export { MULTIFAMILY_PACK } from './multifamily.js';
13
17
  export { OFFICE_PACK } from './office.js';
14
18
  export { RETAIL_PACK } from './retail.js';
15
19
  export { INDUSTRIAL_PACK } from './industrial.js';
16
20
  export { SELF_STORAGE_PACK } from './self-storage.js';
17
- export { emitFromAst, emitExcelFormula, ExcelEmitError, } from './excel-emit.js';
21
+ export { HOSPITALITY_PACK } from './hospitality.js';
22
+ export { SENIOR_HOUSING_PACK } from './senior-housing.js';
23
+ export { STUDENT_HOUSING_PACK } from './student-housing.js';
24
+ export { LAND_PACK } from './land.js';
25
+ export { emitFromAst, emitExcelFormula, emitCalcExcelFormula, ExcelEmitError, } from './excel-emit.js';
18
26
  /**
19
27
  * Built-in calc packs keyed by the asset class they target. Mirrors the
20
28
  * defaults REGISTRY in `defaults.ts`. Third-party / module-loaded packs are out
@@ -26,6 +34,10 @@ const PACK_REGISTRY = Object.freeze({
26
34
  retail: RETAIL_PACK,
27
35
  industrial: INDUSTRIAL_PACK,
28
36
  self_storage: SELF_STORAGE_PACK,
37
+ hospitality: HOSPITALITY_PACK,
38
+ senior_housing: SENIOR_HOUSING_PACK,
39
+ student_housing: STUDENT_HOUSING_PACK,
40
+ land: LAND_PACK,
29
41
  });
30
42
  /**
31
43
  * Look up the built-in calc pack for an asset class. Returns null when no pack
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/packs/index.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,EAAE;AACF,8EAA8E;AAC9E,+EAA+E;AAC/E,4EAA4E;AAC5E,wEAAwE;AAGxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,cAAc,GAEf,MAAM,iBAAiB,CAAC;AAEzB;;;;GAIG;AACH,MAAM,aAAa,GAA6C,MAAM,CAAC,MAAM,CAAC;IAC5E,WAAW,EAAE,gBAAgB;IAC7B,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,WAAW;IACnB,UAAU,EAAE,eAAe;IAC3B,YAAY,EAAE,iBAAiB;CAChC,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAmB;IACtD,OAAO,aAAa,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC;AAC5C,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/packs/index.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,EAAE;AACF,8EAA8E;AAC9E,+EAA+E;AAC/E,4EAA4E;AAC5E,wEAAwE;AAGxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,GAEf,MAAM,iBAAiB,CAAC;AAEzB;;;;GAIG;AACH,MAAM,aAAa,GAA6C,MAAM,CAAC,MAAM,CAAC;IAC5E,WAAW,EAAE,gBAAgB;IAC7B,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,WAAW;IACnB,UAAU,EAAE,eAAe;IAC3B,YAAY,EAAE,iBAAiB;IAC/B,WAAW,EAAE,gBAAgB;IAC7B,cAAc,EAAE,mBAAmB;IACnC,eAAe,EAAE,oBAAoB;IACrC,IAAI,EAAE,SAAS;CAChB,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAmB;IACtD,OAAO,aAAa,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ModuleManifest } from '../protocol.js';
2
+ export declare const LAND_PACK: ModuleManifest;
3
+ //# sourceMappingURL=land.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"land.d.ts","sourceRoot":"","sources":["../../src/packs/land.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,eAAO,MAAM,SAAS,EAAE,cAoGvB,CAAC"}
@@ -0,0 +1,124 @@
1
+ // Canonical land calc pack.
2
+ //
3
+ // Land is the one asset class here that is NOT an income property, and the pack
4
+ // is shaped by that fact.
5
+ //
6
+ // The seven income classes all derive from a positive NOI: cap rate, DSCR, and
7
+ // debt yield are the core of every one of their packs. Land has no stabilized
8
+ // income. Its `noi_model` carries carry costs (taxes, assessments, insurance,
9
+ // site security) against at most incidental interim income (grazing, billboard,
10
+ // laydown), so its net operating income is normally NEGATIVE.
11
+ //
12
+ // This pack therefore DELIBERATELY OMITS `cap_rate`, `dscr`, and `debt_yield`.
13
+ // Dividing a negative NOI by a purchase price yields a number that is
14
+ // arithmetically valid and financially meaningless — a "-1.6% cap rate" reads as
15
+ // a yield when it is really a carry burden, and a DSCR below zero reads as
16
+ // distress when the loan is an interest-only entitlement facility being carried
17
+ // out of an equity reserve by design. Emitting those metrics would produce
18
+ // confidently wrong output, which is worse than producing none.
19
+ //
20
+ // Land is instead underwritten on basis and density: what the dirt costs per
21
+ // acre and per buildable unit, how much of it is actually usable, what it costs
22
+ // to carry, and what share of the eventual sellout the land basis represents.
23
+ // `land.test.ts` pins the omission so a future contributor cannot add cap_rate
24
+ // back by pattern-matching the other packs.
25
+ export const LAND_PACK = {
26
+ manifest_version: '1',
27
+ id: 'org.uwmd.pack.land',
28
+ name: 'Land Starter Pack',
29
+ version: '1.0.0',
30
+ description: 'Twelve derived metrics for land underwriting: $/acre, $/usable acre, $/buildable unit, usable-land ratio, density, LTV, LTC, loan/acre, basis per buildable unit, carry ratio, carry cost per acre, and land-to-sellout ratio. Deliberately omits cap rate, DSCR, and debt yield — land has no stabilized income.',
31
+ authors: ['UW Markdown Working Group'],
32
+ license: 'MIT',
33
+ requires_protocol: '^1.0.0',
34
+ requires_format: '^1.1.0',
35
+ requires_tier: 'tier-3-calc-host',
36
+ asset_classes: ['land'],
37
+ calculations: [
38
+ {
39
+ id: 'price_per_acre',
40
+ label: 'Price / Gross Acre',
41
+ formula: 'valuation.purchase_price / property.gross_acres',
42
+ unit: '$',
43
+ deterministic: true,
44
+ },
45
+ {
46
+ id: 'price_per_usable_acre',
47
+ label: 'Price / Usable Acre',
48
+ formula: 'valuation.purchase_price / property.usable_acres',
49
+ unit: '$',
50
+ deterministic: true,
51
+ },
52
+ {
53
+ id: 'price_per_buildable_unit',
54
+ label: 'Price / Buildable Unit',
55
+ formula: 'valuation.purchase_price / property.entitled_units',
56
+ unit: '$',
57
+ deterministic: true,
58
+ },
59
+ {
60
+ id: 'usable_land_ratio',
61
+ label: 'Usable Land Ratio',
62
+ formula: 'property.usable_acres / property.gross_acres',
63
+ unit: '%',
64
+ deterministic: true,
65
+ },
66
+ {
67
+ id: 'density_per_usable_acre',
68
+ label: 'Density / Usable Acre',
69
+ formula: 'property.entitled_units / property.usable_acres',
70
+ unit: 'x',
71
+ deterministic: true,
72
+ },
73
+ {
74
+ id: 'ltv',
75
+ label: 'LTV',
76
+ formula: 'debt_structure.loan_amount / valuation.purchase_price',
77
+ unit: '%',
78
+ deterministic: true,
79
+ },
80
+ {
81
+ id: 'ltc',
82
+ label: 'LTC',
83
+ formula: 'debt_structure.loan_amount / sources_uses.uses.total',
84
+ unit: '%',
85
+ deterministic: true,
86
+ },
87
+ {
88
+ id: 'loan_per_acre',
89
+ label: 'Loan / Gross Acre',
90
+ formula: 'debt_structure.loan_amount / property.gross_acres',
91
+ unit: '$',
92
+ deterministic: true,
93
+ },
94
+ {
95
+ id: 'basis_per_buildable_unit',
96
+ label: 'All-In Basis / Buildable Unit',
97
+ formula: 'sources_uses.uses.total / property.entitled_units',
98
+ unit: '$',
99
+ deterministic: true,
100
+ },
101
+ {
102
+ id: 'carry_ratio',
103
+ label: 'Annual Carry Ratio',
104
+ formula: 'noi_model.expenses.total_operating_expenses / valuation.purchase_price',
105
+ unit: '%',
106
+ deterministic: true,
107
+ },
108
+ {
109
+ id: 'carry_cost_per_acre',
110
+ label: 'Annual Carry Cost / Gross Acre',
111
+ formula: 'noi_model.expenses.total_operating_expenses / property.gross_acres',
112
+ unit: '$',
113
+ deterministic: true,
114
+ },
115
+ {
116
+ id: 'land_to_sellout_ratio',
117
+ label: 'Land Basis / Projected Sellout',
118
+ formula: 'valuation.purchase_price / valuation.projected_gross_sellout',
119
+ unit: '%',
120
+ deterministic: true,
121
+ },
122
+ ],
123
+ };
124
+ //# sourceMappingURL=land.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"land.js","sourceRoot":"","sources":["../../src/packs/land.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ModuleManifest } from '../protocol.js';
2
+ export declare const SENIOR_HOUSING_PACK: ModuleManifest;
3
+ //# sourceMappingURL=senior-housing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"senior-housing.d.ts","sourceRoot":"","sources":["../../src/packs/senior-housing.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,eAAO,MAAM,mBAAmB,EAAE,cAoHjC,CAAC"}
@@ -0,0 +1,123 @@
1
+ // Canonical senior-housing calc pack.
2
+ //
3
+ // Single source of truth for senior-housing derived metrics. Like hospitality,
4
+ // senior housing is an operating business rather than a lease: a large share of
5
+ // revenue is care fees rather than rent, and labor is the dominant expense. The
6
+ // class-distinctive metrics are therefore RevPOR (revenue per occupied unit per
7
+ // month), the labor ratio, and the care-revenue share — the three numbers that
8
+ // tell an underwriter whether the operator, not the real estate, is carrying the
9
+ // deal. Sizing is per unit, as in multifamily.
10
+ export const SENIOR_HOUSING_PACK = {
11
+ manifest_version: '1',
12
+ id: 'org.uwmd.pack.senior_housing',
13
+ name: 'Senior Housing Starter Pack',
14
+ version: '1.0.0',
15
+ description: 'Fourteen derived metrics for senior-housing underwriting: cap rate, LTV, LTC, DSCR, debt yield, $/unit, loan/unit, NOI/unit, expense ratio, cash-on-cash, occupancy, RevPOR, labor ratio, and care-revenue ratio.',
16
+ authors: ['UW Markdown Working Group'],
17
+ license: 'MIT',
18
+ requires_protocol: '^1.0.0',
19
+ requires_format: '^1.1.0',
20
+ requires_tier: 'tier-3-calc-host',
21
+ asset_classes: ['senior_housing'],
22
+ calculations: [
23
+ {
24
+ id: 'cap_rate',
25
+ label: 'Cap Rate',
26
+ formula: 'noi_model.net_operating_income / valuation.purchase_price',
27
+ unit: '%',
28
+ deterministic: true,
29
+ },
30
+ {
31
+ id: 'ltv',
32
+ label: 'LTV',
33
+ formula: 'debt_structure.loan_amount / valuation.purchase_price',
34
+ unit: '%',
35
+ deterministic: true,
36
+ },
37
+ {
38
+ id: 'ltc',
39
+ label: 'LTC',
40
+ formula: 'debt_structure.loan_amount / sources_uses.uses.total',
41
+ unit: '%',
42
+ deterministic: true,
43
+ },
44
+ {
45
+ id: 'dscr',
46
+ label: 'DSCR',
47
+ formula: 'noi_model.net_operating_income / debt_structure.annual_debt_service',
48
+ unit: 'x',
49
+ deterministic: true,
50
+ },
51
+ {
52
+ id: 'debt_yield',
53
+ label: 'Debt Yield',
54
+ formula: 'noi_model.net_operating_income / debt_structure.loan_amount',
55
+ unit: '%',
56
+ deterministic: true,
57
+ },
58
+ {
59
+ id: 'price_per_unit',
60
+ label: 'Price / Unit',
61
+ formula: 'valuation.purchase_price / property.total_units',
62
+ unit: '$',
63
+ deterministic: true,
64
+ },
65
+ {
66
+ id: 'loan_per_unit',
67
+ label: 'Loan / Unit',
68
+ formula: 'debt_structure.loan_amount / property.total_units',
69
+ unit: '$',
70
+ deterministic: true,
71
+ },
72
+ {
73
+ id: 'noi_per_unit',
74
+ label: 'NOI / Unit',
75
+ formula: 'noi_model.net_operating_income / property.total_units',
76
+ unit: '$',
77
+ deterministic: true,
78
+ },
79
+ {
80
+ id: 'expense_ratio',
81
+ label: 'Operating Expense Ratio',
82
+ formula: 'noi_model.expenses.total_operating_expenses / noi_model.income.effective_gross_income',
83
+ unit: '%',
84
+ deterministic: true,
85
+ },
86
+ {
87
+ id: 'cash_on_cash',
88
+ label: 'Cash-on-Cash',
89
+ formula: '(noi_model.net_operating_income - debt_structure.annual_debt_service) / sources_uses.sources.sponsor_equity',
90
+ unit: '%',
91
+ deterministic: true,
92
+ },
93
+ {
94
+ id: 'occupancy',
95
+ label: 'Occupancy',
96
+ formula: 'rent_roll.occupied_units / property.total_units',
97
+ unit: '%',
98
+ deterministic: true,
99
+ },
100
+ {
101
+ id: 'revpor',
102
+ label: 'RevPOR (Monthly)',
103
+ formula: 'noi_model.income.effective_gross_income / (rent_roll.occupied_units * 12)',
104
+ unit: '$',
105
+ deterministic: true,
106
+ },
107
+ {
108
+ id: 'labor_ratio',
109
+ label: 'Labor Ratio',
110
+ formula: 'noi_model.total_labor_expense / noi_model.income.effective_gross_income',
111
+ unit: '%',
112
+ deterministic: true,
113
+ },
114
+ {
115
+ id: 'care_revenue_ratio',
116
+ label: 'Care Revenue Ratio',
117
+ formula: 'noi_model.income.care_revenue / noi_model.income.effective_gross_income',
118
+ unit: '%',
119
+ deterministic: true,
120
+ },
121
+ ],
122
+ };
123
+ //# sourceMappingURL=senior-housing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"senior-housing.js","sourceRoot":"","sources":["../../src/packs/senior-housing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ModuleManifest } from '../protocol.js';
2
+ export declare const STUDENT_HOUSING_PACK: ModuleManifest;
3
+ //# sourceMappingURL=student-housing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"student-housing.d.ts","sourceRoot":"","sources":["../../src/packs/student-housing.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,eAAO,MAAM,oBAAoB,EAAE,cAmHlC,CAAC"}
@@ -0,0 +1,124 @@
1
+ // Canonical student-housing calc pack.
2
+ //
3
+ // Single source of truth for student-housing derived metrics. The class looks
4
+ // like multifamily but is not underwritten like it: leases are signed per BED,
5
+ // not per unit, so every sizing and occupancy metric is keyed off
6
+ // `property.total_beds`. The defining metric is the pre-lease rate — the share
7
+ // of beds already committed for the coming academic year. Student housing
8
+ // re-leases essentially its entire rent roll on one date, so pre-lease velocity
9
+ // is the leading indicator of next year's revenue in a way no trailing
10
+ // occupancy figure can be.
11
+ export const STUDENT_HOUSING_PACK = {
12
+ manifest_version: '1',
13
+ id: 'org.uwmd.pack.student_housing',
14
+ name: 'Student Housing Starter Pack',
15
+ version: '1.0.0',
16
+ description: 'Fourteen derived metrics for student-housing underwriting: cap rate, LTV, LTC, DSCR, debt yield, $/bed, loan/bed, NOI/bed, expense ratio, cash-on-cash, occupancy, pre-lease rate, revenue per bed, and monthly rent per bed.',
17
+ authors: ['UW Markdown Working Group'],
18
+ license: 'MIT',
19
+ requires_protocol: '^1.0.0',
20
+ requires_format: '^1.1.0',
21
+ requires_tier: 'tier-3-calc-host',
22
+ asset_classes: ['student_housing'],
23
+ calculations: [
24
+ {
25
+ id: 'cap_rate',
26
+ label: 'Cap Rate',
27
+ formula: 'noi_model.net_operating_income / valuation.purchase_price',
28
+ unit: '%',
29
+ deterministic: true,
30
+ },
31
+ {
32
+ id: 'ltv',
33
+ label: 'LTV',
34
+ formula: 'debt_structure.loan_amount / valuation.purchase_price',
35
+ unit: '%',
36
+ deterministic: true,
37
+ },
38
+ {
39
+ id: 'ltc',
40
+ label: 'LTC',
41
+ formula: 'debt_structure.loan_amount / sources_uses.uses.total',
42
+ unit: '%',
43
+ deterministic: true,
44
+ },
45
+ {
46
+ id: 'dscr',
47
+ label: 'DSCR',
48
+ formula: 'noi_model.net_operating_income / debt_structure.annual_debt_service',
49
+ unit: 'x',
50
+ deterministic: true,
51
+ },
52
+ {
53
+ id: 'debt_yield',
54
+ label: 'Debt Yield',
55
+ formula: 'noi_model.net_operating_income / debt_structure.loan_amount',
56
+ unit: '%',
57
+ deterministic: true,
58
+ },
59
+ {
60
+ id: 'price_per_bed',
61
+ label: 'Price / Bed',
62
+ formula: 'valuation.purchase_price / property.total_beds',
63
+ unit: '$',
64
+ deterministic: true,
65
+ },
66
+ {
67
+ id: 'loan_per_bed',
68
+ label: 'Loan / Bed',
69
+ formula: 'debt_structure.loan_amount / property.total_beds',
70
+ unit: '$',
71
+ deterministic: true,
72
+ },
73
+ {
74
+ id: 'noi_per_bed',
75
+ label: 'NOI / Bed',
76
+ formula: 'noi_model.net_operating_income / property.total_beds',
77
+ unit: '$',
78
+ deterministic: true,
79
+ },
80
+ {
81
+ id: 'expense_ratio',
82
+ label: 'Operating Expense Ratio',
83
+ formula: 'noi_model.expenses.total_operating_expenses / noi_model.income.effective_gross_income',
84
+ unit: '%',
85
+ deterministic: true,
86
+ },
87
+ {
88
+ id: 'cash_on_cash',
89
+ label: 'Cash-on-Cash',
90
+ formula: '(noi_model.net_operating_income - debt_structure.annual_debt_service) / sources_uses.sources.sponsor_equity',
91
+ unit: '%',
92
+ deterministic: true,
93
+ },
94
+ {
95
+ id: 'occupancy',
96
+ label: 'Occupancy (by Bed)',
97
+ formula: 'rent_roll.occupied_beds / property.total_beds',
98
+ unit: '%',
99
+ deterministic: true,
100
+ },
101
+ {
102
+ id: 'pre_lease_rate',
103
+ label: 'Pre-Lease Rate',
104
+ formula: 'rent_roll.preleased_beds / property.total_beds',
105
+ unit: '%',
106
+ deterministic: true,
107
+ },
108
+ {
109
+ id: 'revenue_per_bed',
110
+ label: 'Revenue / Bed',
111
+ formula: 'noi_model.income.effective_gross_income / property.total_beds',
112
+ unit: '$',
113
+ deterministic: true,
114
+ },
115
+ {
116
+ id: 'rent_per_bed_monthly',
117
+ label: 'Rent / Bed (Monthly)',
118
+ formula: 'noi_model.income.gross_potential_rent / (property.total_beds * 12)',
119
+ unit: '$',
120
+ deterministic: true,
121
+ },
122
+ ],
123
+ };
124
+ //# sourceMappingURL=student-housing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"student-housing.js","sourceRoot":"","sources":["../../src/packs/student-housing.ts"],"names":[],"mappings":"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"}
package/dist/parser.d.ts CHANGED
@@ -11,5 +11,14 @@ export declare class UWMDParseError extends Error {
11
11
  export declare function parseUWFile(content: string, options?: ParseOptions): ParsedUWFile;
12
12
  export declare function getSection(parsed: ParsedUWFile, sectionId: string): UWBlock | null;
13
13
  export declare function getSectionVariant(parsed: ParsedUWFile, sectionId: string, variant: string): UWBlock | null;
14
+ /** True if `segment` must not be read from or written to a document object. */
15
+ export declare function isBlockedSegment(segment: string): boolean;
16
+ /**
17
+ * One step of path navigation, own-properties only. A blocked segment or an
18
+ * inherited member resolves to `undefined` — the same answer a missing path
19
+ * gives, which callers already handle (protocol §VIII.2: a missing path
20
+ * resolves to null, not an error).
21
+ */
22
+ export declare function getPathSegment(current: unknown, segment: string): unknown;
14
23
  export declare function deepGet(obj: unknown, path: string): unknown;
15
24
  //# sourceMappingURL=parser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,OAAO,EAIP,YAAY,EAEZ,YAAY,EAEb,MAAM,YAAY,CAAC;AAsDpB,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;gBACd,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO;CAO1F;AAmJD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,YAAY,CAqHrF;AAwGD,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAKlF;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,GAAG,IAAI,CAIhB;AAMD,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAQ3D"}
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,OAAO,EAIP,YAAY,EAEZ,YAAY,EAEb,MAAM,YAAY,CAAC;AAsDpB,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;gBACd,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO;CAO1F;AAwJD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,YAAY,CAqHrF;AAwGD,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAKlF;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,GAAG,IAAI,CAIhB;AAUD,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAKzE;AAMD,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAQ3D"}