@uwmd/core 1.1.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 (214) hide show
  1. package/README.md +79 -0
  2. package/dist/agents/bancroft.d.ts +32 -0
  3. package/dist/agents/bancroft.d.ts.map +1 -0
  4. package/dist/agents/bancroft.js +292 -0
  5. package/dist/agents/bancroft.js.map +1 -0
  6. package/dist/agents/schemas.d.ts +13 -0
  7. package/dist/agents/schemas.d.ts.map +1 -0
  8. package/dist/agents/schemas.js +74 -0
  9. package/dist/agents/schemas.js.map +1 -0
  10. package/dist/bindings.d.ts +85 -0
  11. package/dist/bindings.d.ts.map +1 -0
  12. package/dist/bindings.js +293 -0
  13. package/dist/bindings.js.map +1 -0
  14. package/dist/browser.d.ts +66 -0
  15. package/dist/browser.d.ts.map +1 -0
  16. package/dist/browser.js +53 -0
  17. package/dist/browser.js.map +1 -0
  18. package/dist/calc/builtins.d.ts +4 -0
  19. package/dist/calc/builtins.d.ts.map +1 -0
  20. package/dist/calc/builtins.js +329 -0
  21. package/dist/calc/builtins.js.map +1 -0
  22. package/dist/calc/dependencies.d.ts +34 -0
  23. package/dist/calc/dependencies.d.ts.map +1 -0
  24. package/dist/calc/dependencies.js +101 -0
  25. package/dist/calc/dependencies.js.map +1 -0
  26. package/dist/calc/errors.d.ts +8 -0
  27. package/dist/calc/errors.d.ts.map +1 -0
  28. package/dist/calc/errors.js +18 -0
  29. package/dist/calc/errors.js.map +1 -0
  30. package/dist/calc/evaluator.d.ts +5 -0
  31. package/dist/calc/evaluator.d.ts.map +1 -0
  32. package/dist/calc/evaluator.js +184 -0
  33. package/dist/calc/evaluator.js.map +1 -0
  34. package/dist/calc/index.d.ts +14 -0
  35. package/dist/calc/index.d.ts.map +1 -0
  36. package/dist/calc/index.js +56 -0
  37. package/dist/calc/index.js.map +1 -0
  38. package/dist/calc/parser.d.ts +32 -0
  39. package/dist/calc/parser.d.ts.map +1 -0
  40. package/dist/calc/parser.js +361 -0
  41. package/dist/calc/parser.js.map +1 -0
  42. package/dist/cascade.d.ts +85 -0
  43. package/dist/cascade.d.ts.map +1 -0
  44. package/dist/cascade.js +172 -0
  45. package/dist/cascade.js.map +1 -0
  46. package/dist/cli.d.ts +3 -0
  47. package/dist/cli.d.ts.map +1 -0
  48. package/dist/cli.js +843 -0
  49. package/dist/cli.js.map +1 -0
  50. package/dist/codec.d.ts +25 -0
  51. package/dist/codec.d.ts.map +1 -0
  52. package/dist/codec.js +62 -0
  53. package/dist/codec.js.map +1 -0
  54. package/dist/codecs.d.ts +6 -0
  55. package/dist/codecs.d.ts.map +1 -0
  56. package/dist/codecs.js +12 -0
  57. package/dist/codecs.js.map +1 -0
  58. package/dist/compactor.d.ts +11 -0
  59. package/dist/compactor.d.ts.map +1 -0
  60. package/dist/compactor.js +84 -0
  61. package/dist/compactor.js.map +1 -0
  62. package/dist/context-profiles.d.ts +30 -0
  63. package/dist/context-profiles.d.ts.map +1 -0
  64. package/dist/context-profiles.js +225 -0
  65. package/dist/context-profiles.js.map +1 -0
  66. package/dist/context.d.ts +55 -0
  67. package/dist/context.d.ts.map +1 -0
  68. package/dist/context.js +288 -0
  69. package/dist/context.js.map +1 -0
  70. package/dist/dcf.d.ts +9 -0
  71. package/dist/dcf.d.ts.map +1 -0
  72. package/dist/dcf.js +75 -0
  73. package/dist/dcf.js.map +1 -0
  74. package/dist/debt.d.ts +11 -0
  75. package/dist/debt.d.ts.map +1 -0
  76. package/dist/debt.js +85 -0
  77. package/dist/debt.js.map +1 -0
  78. package/dist/defaults.d.ts +104 -0
  79. package/dist/defaults.d.ts.map +1 -0
  80. package/dist/defaults.js +622 -0
  81. package/dist/defaults.js.map +1 -0
  82. package/dist/derived.d.ts +17 -0
  83. package/dist/derived.d.ts.map +1 -0
  84. package/dist/derived.js +29 -0
  85. package/dist/derived.js.map +1 -0
  86. package/dist/editor.d.ts +76 -0
  87. package/dist/editor.d.ts.map +1 -0
  88. package/dist/editor.js +502 -0
  89. package/dist/editor.js.map +1 -0
  90. package/dist/envelope.d.ts +51 -0
  91. package/dist/envelope.d.ts.map +1 -0
  92. package/dist/envelope.js +213 -0
  93. package/dist/envelope.js.map +1 -0
  94. package/dist/format.d.ts +60 -0
  95. package/dist/format.d.ts.map +1 -0
  96. package/dist/format.js +115 -0
  97. package/dist/format.js.map +1 -0
  98. package/dist/gaps.d.ts +62 -0
  99. package/dist/gaps.d.ts.map +1 -0
  100. package/dist/gaps.js +272 -0
  101. package/dist/gaps.js.map +1 -0
  102. package/dist/index.d.ts +75 -0
  103. package/dist/index.d.ts.map +1 -0
  104. package/dist/index.js +47 -0
  105. package/dist/index.js.map +1 -0
  106. package/dist/init.d.ts +15 -0
  107. package/dist/init.d.ts.map +1 -0
  108. package/dist/init.js +169 -0
  109. package/dist/init.js.map +1 -0
  110. package/dist/integrity-canonical.d.ts +17 -0
  111. package/dist/integrity-canonical.d.ts.map +1 -0
  112. package/dist/integrity-canonical.js +124 -0
  113. package/dist/integrity-canonical.js.map +1 -0
  114. package/dist/integrity.d.ts +54 -0
  115. package/dist/integrity.d.ts.map +1 -0
  116. package/dist/integrity.js +244 -0
  117. package/dist/integrity.js.map +1 -0
  118. package/dist/modules.d.ts +24 -0
  119. package/dist/modules.d.ts.map +1 -0
  120. package/dist/modules.js +322 -0
  121. package/dist/modules.js.map +1 -0
  122. package/dist/negotiation.d.ts +19 -0
  123. package/dist/negotiation.d.ts.map +1 -0
  124. package/dist/negotiation.js +70 -0
  125. package/dist/negotiation.js.map +1 -0
  126. package/dist/opstatement.d.ts +9 -0
  127. package/dist/opstatement.d.ts.map +1 -0
  128. package/dist/opstatement.js +80 -0
  129. package/dist/opstatement.js.map +1 -0
  130. package/dist/packs/excel-emit.d.ts +21 -0
  131. package/dist/packs/excel-emit.d.ts.map +1 -0
  132. package/dist/packs/excel-emit.js +135 -0
  133. package/dist/packs/excel-emit.js.map +1 -0
  134. package/dist/packs/index.d.ts +13 -0
  135. package/dist/packs/index.d.ts.map +1 -0
  136. package/dist/packs/index.js +37 -0
  137. package/dist/packs/index.js.map +1 -0
  138. package/dist/packs/industrial.d.ts +3 -0
  139. package/dist/packs/industrial.d.ts.map +1 -0
  140. package/dist/packs/industrial.js +115 -0
  141. package/dist/packs/industrial.js.map +1 -0
  142. package/dist/packs/multifamily.d.ts +3 -0
  143. package/dist/packs/multifamily.d.ts.map +1 -0
  144. package/dist/packs/multifamily.js +82 -0
  145. package/dist/packs/multifamily.js.map +1 -0
  146. package/dist/packs/office.d.ts +3 -0
  147. package/dist/packs/office.d.ts.map +1 -0
  148. package/dist/packs/office.js +108 -0
  149. package/dist/packs/office.js.map +1 -0
  150. package/dist/packs/retail.d.ts +3 -0
  151. package/dist/packs/retail.d.ts.map +1 -0
  152. package/dist/packs/retail.js +115 -0
  153. package/dist/packs/retail.js.map +1 -0
  154. package/dist/packs/self-storage.d.ts +3 -0
  155. package/dist/packs/self-storage.d.ts.map +1 -0
  156. package/dist/packs/self-storage.js +105 -0
  157. package/dist/packs/self-storage.js.map +1 -0
  158. package/dist/parser.d.ts +15 -0
  159. package/dist/parser.d.ts.map +1 -0
  160. package/dist/parser.js +430 -0
  161. package/dist/parser.js.map +1 -0
  162. package/dist/protocol.d.ts +389 -0
  163. package/dist/protocol.d.ts.map +1 -0
  164. package/dist/protocol.js +714 -0
  165. package/dist/protocol.js.map +1 -0
  166. package/dist/refinement.d.ts +63 -0
  167. package/dist/refinement.d.ts.map +1 -0
  168. package/dist/refinement.js +242 -0
  169. package/dist/refinement.js.map +1 -0
  170. package/dist/renderer.d.ts +22 -0
  171. package/dist/renderer.d.ts.map +1 -0
  172. package/dist/renderer.js +478 -0
  173. package/dist/renderer.js.map +1 -0
  174. package/dist/rentroll.d.ts +21 -0
  175. package/dist/rentroll.d.ts.map +1 -0
  176. package/dist/rentroll.js +256 -0
  177. package/dist/rentroll.js.map +1 -0
  178. package/dist/report.d.ts +29 -0
  179. package/dist/report.d.ts.map +1 -0
  180. package/dist/report.js +924 -0
  181. package/dist/report.js.map +1 -0
  182. package/dist/runner.d.ts +43 -0
  183. package/dist/runner.d.ts.map +1 -0
  184. package/dist/runner.js +288 -0
  185. package/dist/runner.js.map +1 -0
  186. package/dist/sourcesuses.d.ts +14 -0
  187. package/dist/sourcesuses.d.ts.map +1 -0
  188. package/dist/sourcesuses.js +63 -0
  189. package/dist/sourcesuses.js.map +1 -0
  190. package/dist/types.d.ts +248 -0
  191. package/dist/types.d.ts.map +1 -0
  192. package/dist/types.js +15 -0
  193. package/dist/types.js.map +1 -0
  194. package/dist/uwcsv.d.ts +23 -0
  195. package/dist/uwcsv.d.ts.map +1 -0
  196. package/dist/uwcsv.js +877 -0
  197. package/dist/uwcsv.js.map +1 -0
  198. package/dist/uwjson.d.ts +19 -0
  199. package/dist/uwjson.d.ts.map +1 -0
  200. package/dist/uwjson.js +61 -0
  201. package/dist/uwjson.js.map +1 -0
  202. package/dist/uwxml.d.ts +18 -0
  203. package/dist/uwxml.d.ts.map +1 -0
  204. package/dist/uwxml.js +297 -0
  205. package/dist/uwxml.js.map +1 -0
  206. package/dist/validator.d.ts +35 -0
  207. package/dist/validator.d.ts.map +1 -0
  208. package/dist/validator.js +553 -0
  209. package/dist/validator.js.map +1 -0
  210. package/dist/valuation.d.ts +9 -0
  211. package/dist/valuation.d.ts.map +1 -0
  212. package/dist/valuation.js +34 -0
  213. package/dist/valuation.js.map +1 -0
  214. package/package.json +58 -0
@@ -0,0 +1,55 @@
1
+ import type { ParsedUWFile, UWFrontmatter, PipelineStatus } from './types.js';
2
+ import { type ContextProfile, type ContextResult } from './context-profiles.js';
3
+ export interface LayerDefinition {
4
+ id: string;
5
+ layer: number;
6
+ name: string;
7
+ reads: string[];
8
+ writes: string[];
9
+ pipelineStateKey: string;
10
+ /**
11
+ * Normative context profile this layer consumes (Protocol §XI).
12
+ * Conformance Tier-4 verifies a host requests exactly this profile when
13
+ * preparing the layer's input. Phase 4 default; Phase 5 layers (L0a/L0b)
14
+ * declare their own.
15
+ */
16
+ consumed_profile: ContextProfile;
17
+ }
18
+ export declare const BANCROFT_LAYERS: LayerDefinition[];
19
+ export interface AgentContext {
20
+ agentId: string;
21
+ layer: LayerDefinition;
22
+ frontmatter: UWFrontmatter;
23
+ sections: Record<string, unknown>;
24
+ prose: Record<string, string>;
25
+ missingRequired: string[];
26
+ missingOptional: string[];
27
+ customCalculations: unknown[];
28
+ customScenarios: unknown[];
29
+ extensions: Record<string, unknown>;
30
+ flags: string[];
31
+ blockingFlags: string[];
32
+ validationIssues?: unknown[];
33
+ pipelineState: Record<string, PipelineStatus>;
34
+ chatContext: string;
35
+ chatTokenEstimate: number;
36
+ /**
37
+ * Normative context payload built from the layer's `consumed_profile`
38
+ * (Protocol §XI). Hosts SHOULD send this — not `chatContext` — to the
39
+ * agent when running under the conformance contract.
40
+ */
41
+ profileContext: ContextResult;
42
+ }
43
+ export declare function buildAgentContext(parsed: ParsedUWFile, agentId: string, opts?: {
44
+ includeValidation?: boolean;
45
+ maxChatTokens?: number;
46
+ }): AgentContext;
47
+ export interface BancroftPrompt {
48
+ systemPrompt: string;
49
+ userMessage: string;
50
+ outputSchemaDescription: string;
51
+ }
52
+ export declare function buildAgentPrompt(context: AgentContext, userInstructions?: string): BancroftPrompt;
53
+ export declare function isContextReady(context: AgentContext): boolean;
54
+ export declare function getLayerDependencies(layerId: string): string[];
55
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAW,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGvF,OAAO,EAAgB,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAI9F,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,gBAAgB,EAAE,cAAc,CAAC;CAClC;AAED,eAAO,MAAM,eAAe,EAAE,eAAe,EAkF5C,CAAC;AAIF,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,eAAe,CAAC;IACvB,WAAW,EAAE,aAAa,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,kBAAkB,EAAE,OAAO,EAAE,CAAC;IAC9B,eAAe,EAAE,OAAO,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAE9C,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,cAAc,EAAE,aAAa,CAAC;CAC/B;AAID,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE;IAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GACjE,YAAY,CA2Ed;AAMD,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,uBAAuB,EAAE,MAAM,CAAC;CACjC;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,YAAY,EACrB,gBAAgB,CAAC,EAAE,MAAM,GACxB,cAAc,CAsChB;AAuED,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAM7D;AAKD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAa9D"}
@@ -0,0 +1,288 @@
1
+ // .uw.md context builder — curates what each Bancroft agent layer receives
2
+ //
3
+ // Each Bancroft layer has a defined set of sections it reads and writes.
4
+ // This module builds the minimal, focused context an agent needs — not the
5
+ // full file. Prevents agents from having to parse the raw .uw.md themselves,
6
+ // and ensures each layer only sees the sections it depends on.
7
+ //
8
+ // Spec: UW_FORMAT_SPEC_v1.md §1.3 (Bancroft layer ↔ section mapping)
9
+ import { getSection } from './parser.js';
10
+ import { render } from './renderer.js';
11
+ import { buildContext } from './context-profiles.js';
12
+ export const BANCROFT_LAYERS = [
13
+ {
14
+ id: 'L0',
15
+ layer: 0,
16
+ name: 'Document Ingestion',
17
+ reads: [], // L0 reads raw documents, not sections
18
+ writes: ['rent_roll', 'operating_statement', 'lease_schedule'],
19
+ pipelineStateKey: 'L0_ingestion',
20
+ consumed_profile: 'summary',
21
+ },
22
+ {
23
+ id: 'L0a',
24
+ layer: 0,
25
+ name: 'Scope',
26
+ reads: ['property'],
27
+ writes: ['market_analysis', 'noi_model', 'debt_structure', 'valuation', 'quick_metrics', 'gaps'],
28
+ pipelineStateKey: 'L0a_scope',
29
+ consumed_profile: 'summary',
30
+ },
31
+ {
32
+ id: 'L0b',
33
+ layer: 0,
34
+ name: 'Scope Refinement',
35
+ reads: ['*'],
36
+ writes: ['property', 'noi_model', 'debt_structure', 'gaps'],
37
+ pipelineStateKey: 'L0b_refinement',
38
+ consumed_profile: 'compact',
39
+ },
40
+ {
41
+ id: 'L1',
42
+ layer: 1,
43
+ name: 'Screening',
44
+ reads: ['deal_context', 'property', 'ownership'],
45
+ writes: ['screening', 'preliminary_sizing'],
46
+ pipelineStateKey: 'L1_screening',
47
+ consumed_profile: 'summary',
48
+ },
49
+ {
50
+ id: 'L2',
51
+ layer: 2,
52
+ name: 'Underwriting',
53
+ reads: ['deal_context', 'property', 'rent_roll', 'operating_statement', 'borrower_sponsor'],
54
+ writes: ['noi_model', 'valuation', 'market_analysis'],
55
+ pipelineStateKey: 'L2_underwriting',
56
+ consumed_profile: 'relevant',
57
+ },
58
+ {
59
+ id: 'L4',
60
+ layer: 4,
61
+ name: 'Structuring',
62
+ reads: ['deal_context', 'property', 'noi_model', 'valuation', 'market_analysis', 'borrower_sponsor', 'sources_uses'],
63
+ writes: ['debt_structure', 'sources_uses', 'covenants'],
64
+ pipelineStateKey: 'L4_structuring',
65
+ consumed_profile: 'relevant',
66
+ },
67
+ {
68
+ id: 'L5',
69
+ layer: 5,
70
+ name: 'Compliance',
71
+ reads: ['deal_context', 'property', 'ownership', 'borrower_sponsor', 'debt_structure', 'valuation'],
72
+ writes: ['compliance'],
73
+ pipelineStateKey: 'L5_compliance',
74
+ consumed_profile: 'relevant',
75
+ },
76
+ {
77
+ id: 'L6',
78
+ layer: 6,
79
+ name: 'Risk Rating',
80
+ reads: ['deal_context', 'property', 'noi_model', 'valuation', 'debt_structure', 'market_analysis', 'borrower_sponsor', 'stress_tests', 'dcf', 'compliance'],
81
+ writes: ['risk_assessment'],
82
+ pipelineStateKey: 'L6_risk',
83
+ consumed_profile: 'relevant',
84
+ },
85
+ {
86
+ id: 'L7',
87
+ layer: 7,
88
+ name: 'Assembly',
89
+ reads: ['*'], // reads everything
90
+ writes: ['pipeline_log', 'deal_context'], // writes ai_synthesis to deal_context
91
+ pipelineStateKey: 'L7_assembly',
92
+ consumed_profile: 'live',
93
+ },
94
+ ];
95
+ // ─── Main context builder ─────────────────────────────────────────────────────
96
+ export function buildAgentContext(parsed, agentId, opts = {}) {
97
+ const layer = resolveLayer(agentId);
98
+ const sectionsToRead = layer.layer === 7 ? getAllSectionIds(parsed) : layer.reads;
99
+ // Collect section content
100
+ const sections = {};
101
+ const prose = {};
102
+ const missingRequired = [];
103
+ const missingOptional = [];
104
+ for (const sectionId of sectionsToRead) {
105
+ const block = getSection(parsed, sectionId);
106
+ if (block) {
107
+ sections[sectionId] = block.content;
108
+ if (parsed.prose[sectionId])
109
+ prose[sectionId] = parsed.prose[sectionId];
110
+ }
111
+ else {
112
+ // Check multi-variant
113
+ const variantEntry = parsed.sections[sectionId];
114
+ if (variantEntry && !('annotation' in variantEntry)) {
115
+ sections[sectionId] = Object.fromEntries(Object.entries(variantEntry).map(([v, b]) => [v, b.content]));
116
+ }
117
+ else if (isRequired(layer, sectionId)) {
118
+ missingRequired.push(sectionId);
119
+ }
120
+ else {
121
+ missingOptional.push(sectionId);
122
+ }
123
+ }
124
+ }
125
+ // Always include deal_context for all layers (orientation)
126
+ if (!sections['deal_context']) {
127
+ const dc = getSection(parsed, 'deal_context');
128
+ if (dc) {
129
+ sections['deal_context'] = dc.content;
130
+ if (parsed.prose['deal_context'])
131
+ prose['deal_context'] = parsed.prose['deal_context'];
132
+ }
133
+ }
134
+ const pipelineState = (parsed.frontmatter.pipeline_state ?? {});
135
+ // Build chat context string for Claude API injection
136
+ const chatResult = render(parsed, {
137
+ format: 'chat',
138
+ maxTokens: opts.maxChatTokens ?? 8000,
139
+ });
140
+ // Build the normative profile context per the layer's declared consumption.
141
+ // For 'relevant', pass layer.reads as the section filter so the host receives
142
+ // exactly the documented contract.
143
+ const profileContext = buildContext(parsed, layer.consumed_profile, {
144
+ sections: layer.consumed_profile === 'relevant' ? sectionsToRead : undefined,
145
+ maxTokens: opts.maxChatTokens,
146
+ });
147
+ return {
148
+ agentId,
149
+ layer,
150
+ frontmatter: parsed.frontmatter,
151
+ sections,
152
+ prose,
153
+ missingRequired,
154
+ missingOptional,
155
+ customCalculations: parsed.custom_calculations.map(b => b.content),
156
+ customScenarios: parsed.custom_scenarios.map(b => b.content),
157
+ extensions: Object.fromEntries(Object.entries(parsed.extensions).map(([k, v]) => [k, v.content])),
158
+ flags: parsed.frontmatter.flags ?? [],
159
+ blockingFlags: parsed.frontmatter.blocking_flags ?? [],
160
+ pipelineState,
161
+ chatContext: chatResult.content,
162
+ chatTokenEstimate: chatResult.estimatedTokens ?? 0,
163
+ profileContext,
164
+ };
165
+ }
166
+ export function buildAgentPrompt(context, userInstructions) {
167
+ const layer = context.layer;
168
+ const missingWarn = context.missingRequired.length > 0
169
+ ? `\n\n⚠ MISSING REQUIRED INPUT SECTIONS: ${context.missingRequired.join(', ')}. Proceed with available data only — mark confidence as "low" and set human_review_required: true for fields that depend on missing inputs.`
170
+ : '';
171
+ const systemPrompt = `You are ${layer.id} — ${layer.name} — a specialized agent in the Bancroft CRE underwriting pipeline.
172
+
173
+ Your role: ${getLayerDescription(layer.id)}
174
+
175
+ ## Your Output Contract
176
+
177
+ You must return a single JSON object that will be written as a .uw.md section block. The object must:
178
+ - Begin with a "_meta" object (see spec §2.5)
179
+ - Include all required fields for the section(s) you write: ${layer.writes.join(', ')}
180
+ - Set confidence to "high" / "medium" / "low" based on available data quality
181
+ - Set human_review_required: true if any field is uncertain, estimated, or depends on missing inputs
182
+ - Never calculate financial figures — report what the data shows; the deterministic engine owns the math
183
+ - Set flags[] for any anomalies, policy concerns, or data quality issues you observe
184
+
185
+ ## Available Input Sections
186
+ ${Object.keys(context.sections).map(s => `- ${s}`).join('\n')}
187
+ ${missingWarn}
188
+
189
+ ## Blocking Flags
190
+ ${context.blockingFlags.length > 0 ? context.blockingFlags.map(f => `- ${f}`).join('\n') : 'None — pipeline is clear to proceed'}`;
191
+ const userMessage = `${context.chatContext}
192
+
193
+ ---
194
+
195
+ ${userInstructions ? `Additional instructions:\n${userInstructions}\n\n---\n\n` : ''}Return your output as a single JSON block for section(s): ${layer.writes.join(', ')}`;
196
+ return {
197
+ systemPrompt,
198
+ userMessage,
199
+ outputSchemaDescription: getOutputSchemaDescription(layer.id),
200
+ };
201
+ }
202
+ // ─── Layer resolution ─────────────────────────────────────────────────────────
203
+ function resolveLayer(agentId) {
204
+ // Match by prefix: "L0", "L0-01", "L2-CRE-11", etc.
205
+ const prefix = agentId.match(/^(L\d+)/)?.[1];
206
+ if (prefix) {
207
+ const layer = BANCROFT_LAYERS.find(l => l.id === prefix);
208
+ if (layer)
209
+ return layer;
210
+ }
211
+ // Default: treat as L7 (reads everything)
212
+ return BANCROFT_LAYERS[BANCROFT_LAYERS.length - 1];
213
+ }
214
+ // Sections that must be present for each layer to produce meaningful output.
215
+ // Absent required sections set context.missingRequired and block isContextReady().
216
+ const REQUIRED_BY_LAYER = {
217
+ L0: [],
218
+ L0a: ['property'],
219
+ L0b: [], // operates on whatever L0a produced
220
+ L1: ['property'],
221
+ L2: ['property', 'rent_roll'],
222
+ L4: ['noi_model', 'valuation'],
223
+ L5: ['property', 'borrower_sponsor'],
224
+ L6: ['noi_model', 'debt_structure', 'valuation'],
225
+ L7: [], // L7 reads everything but can always proceed
226
+ };
227
+ function isRequired(layer, sectionId) {
228
+ const required = REQUIRED_BY_LAYER[layer.id] ?? [];
229
+ return required.includes(sectionId);
230
+ }
231
+ function getAllSectionIds(parsed) {
232
+ return Object.keys(parsed.sections);
233
+ }
234
+ // ─── Layer descriptions ───────────────────────────────────────────────────────
235
+ function getLayerDescription(layerId) {
236
+ const descriptions = {
237
+ L0: 'You extract structured data from raw uploaded documents (rent rolls, T-12 operating statements, lease schedules). Output must represent exactly what the documents say — no inference, no interpolation.',
238
+ L0a: 'You produce an initial scoped .uw.md from minimal user input by walking the fallback cascade. Every defaulted value MUST be stamped provisional. Your output is a triage view, not a commitment.',
239
+ L0b: 'You iteratively ask the user the smallest set of questions that meaningfully tighten the deal\u2019s output ranges. Wraps refinement.ts in a conversational loop. See L0b-prompt.md for the full system prompt.',
240
+ L1: 'You perform initial deal screening — flag red flags, assess deal feasibility against standard thresholds, and produce a preliminary sizing. You are the gatekeeper before full underwriting begins.',
241
+ L2: 'You perform full underwriting analysis — NOI reconstruction, market positioning, valuation, and borrower assessment. You are the primary analytical layer.',
242
+ L4: 'You structure the debt — size the loan, build the sources and uses table, design term sheet terms, and identify covenants. You work from the underwritten NOI and value.',
243
+ L5: 'You run compliance checks — OFAC screening, CRA assessment, regulatory requirements, and policy flag review. You are a hard gate: blocking flags must be cleared before proceeding.',
244
+ L6: 'You produce the risk rating — aggregate all section inputs into a scored assessment, stress test the structure, and make a recommendation.',
245
+ L7: 'You assemble the final package — synthesize all sections into a coherent narrative, generate the AI synthesis for deal_context, and prepare output artifacts.',
246
+ };
247
+ return descriptions[layerId] ?? 'You are a specialized underwriting agent.';
248
+ }
249
+ function getOutputSchemaDescription(layerId) {
250
+ const schemas = {
251
+ L0: 'rent_roll: { units[], gross_potential_rent, total_units } | operating_statement: { income{}, expenses{}, noi } | lease_schedule: { leases[] }',
252
+ L1: 'screening: { status, flags[], notes, recommendation } | preliminary_sizing: { max_loan_amount, dscr_estimate, ltv_estimate }',
253
+ L2: 'noi_model: { line_items{}, noi, vacancy_rate, opex_ratio } | valuation: { purchase_price, cap_rate, value_per_unit } | market_analysis: { market_vacancy, asking_rents, supply_pipeline }',
254
+ L4: 'debt_structure: { loan_amount, rate, term, ltv, dscr } | sources_uses: { sources{}, uses{}, equity_required }',
255
+ L5: 'compliance: { ofac_status, cra_eligible, flags[], blocking_flags[], notes }',
256
+ L6: 'risk_assessment: { overall_rating, risk_score, key_risks[], recommendation, stress_test_summary }',
257
+ L7: 'deal_context (ai_synthesis field): { summary, key_risks[], key_strengths[], overall_impression }',
258
+ };
259
+ return schemas[layerId] ?? '{ _meta: {}, ...section fields }';
260
+ }
261
+ // ─── Context readiness check ──────────────────────────────────────────────────
262
+ // Returns true if the context has enough data to run the agent.
263
+ export function isContextReady(context) {
264
+ // Blocking flags always halt
265
+ if (context.blockingFlags.length > 0)
266
+ return false;
267
+ // Missing required sections halt
268
+ if (context.missingRequired.length > 0)
269
+ return false;
270
+ return true;
271
+ }
272
+ // ─── Pipeline dependency graph ────────────────────────────────────────────────
273
+ // Returns the layers that must complete before a given layer can run.
274
+ export function getLayerDependencies(layerId) {
275
+ const deps = {
276
+ L0: [],
277
+ L0a: [],
278
+ L0b: ['L0a'],
279
+ L1: ['L0'],
280
+ L2: ['L0', 'L1'],
281
+ L4: ['L2'],
282
+ L5: ['L2', 'L4'],
283
+ L6: ['L2', 'L4', 'L5'],
284
+ L7: ['L0', 'L1', 'L2', 'L4', 'L5', 'L6'],
285
+ };
286
+ return deps[layerId] ?? [];
287
+ }
288
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
package/dist/dcf.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { type DerivedField } from './derived.js';
2
+ type Row = Record<string, unknown>;
3
+ export interface DCFDerivation {
4
+ fields: DerivedField[];
5
+ }
6
+ /** Foot a dcf content block. Pure: never mutates `content`. */
7
+ export declare function deriveDCF(content: Row): DCFDerivation;
8
+ export {};
9
+ //# sourceMappingURL=dcf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dcf.d.ts","sourceRoot":"","sources":["../src/dcf.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAEvE,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAKnC,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,EAAE,CAAC;CACxB;AAED,+DAA+D;AAC/D,wBAAgB,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,aAAa,CA+DrD"}
package/dist/dcf.js ADDED
@@ -0,0 +1,75 @@
1
+ // Deterministic DCF footing — the relationships inside a `dcf` block that follow
2
+ // unambiguously from the block's own stored inputs are footed here, so the editor,
3
+ // CLI, and Excel converter never disagree (invariant #4); plain arithmetic, never
4
+ // AI math (invariant #1).
5
+ //
6
+ // Scope is deliberately narrow and self-contained, in the same spirit as
7
+ // deriveValuation. We foot only what is an identity over stored fields:
8
+ //
9
+ // Per projection year (annual_cash_flows[i]):
10
+ // net_cash_flow_levered = net_operating_income − annual_debt_service
11
+ // cash_on_cash_return = net_cash_flow_levered / cumulative_equity_invested
12
+ //
13
+ // Exit waterfall (exit_analysis):
14
+ // disposition_costs = exit_value_gross × assumptions.disposition_costs_pct
15
+ // exit_value_net = exit_value_gross − disposition_costs
16
+ // net_proceeds_to_equity = exit_value_net − loan_balance_at_exit
17
+ //
18
+ // Left as INPUTS on purpose (no unambiguous identity from stored fields):
19
+ // - exit_value_gross — capitalizes a *forward* NOI by convention (year N+1),
20
+ // which the block doesn't store; the trailing exit_noi alone can't foot it.
21
+ // - returns.* (IRR / NPV / equity multiple) — depend on a cash-flow timing /
22
+ // terminal-value convention; computing them here would invite silent drift.
23
+ // - per-unit / per-sqft exit values — need the property section.
24
+ import { collector, numOrNull } from './derived.js';
25
+ const num = numOrNull;
26
+ const isObj = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
27
+ /** Foot a dcf content block. Pure: never mutates `content`. */
28
+ export function deriveDCF(content) {
29
+ const c = collector();
30
+ // ─── Per-year levered cash flow + cash-on-cash ──────────────────────────────
31
+ const flows = content['annual_cash_flows'];
32
+ if (Array.isArray(flows)) {
33
+ flows.forEach((row, i) => {
34
+ if (!isObj(row))
35
+ return;
36
+ const noi = num(row['net_operating_income']);
37
+ const ads = num(row['annual_debt_service']);
38
+ if (noi == null || ads == null)
39
+ return;
40
+ const levered = noi - ads;
41
+ c.add(`annual_cash_flows.${i}.net_cash_flow_levered`, `Year ${labelYear(row, i)} — Levered Cash Flow`, 'currency', levered);
42
+ const equity = num(row['cumulative_equity_invested']);
43
+ if (equity != null && equity > 0) {
44
+ c.add(`annual_cash_flows.${i}.cash_on_cash_return`, `Year ${labelYear(row, i)} — Cash-on-Cash`, 'rate', levered / equity);
45
+ }
46
+ });
47
+ }
48
+ // ─── Exit waterfall ─────────────────────────────────────────────────────────
49
+ const exit = isObj(content['exit_analysis']) ? content['exit_analysis'] : null;
50
+ const assumptions = isObj(content['assumptions']) ? content['assumptions'] : null;
51
+ if (exit) {
52
+ const gross = num(exit['exit_value_gross']);
53
+ const dispPct = assumptions ? num(assumptions['disposition_costs_pct']) : null;
54
+ let dispCosts = num(exit['disposition_costs']);
55
+ if (gross != null && dispPct != null) {
56
+ dispCosts = Math.round(gross * dispPct);
57
+ c.add('exit_analysis.disposition_costs', 'Disposition Costs', 'currency', dispCosts);
58
+ }
59
+ let net = num(exit['exit_value_net']);
60
+ if (gross != null && dispCosts != null) {
61
+ net = gross - dispCosts;
62
+ c.add('exit_analysis.exit_value_net', 'Exit Value (net of costs)', 'currency', net);
63
+ }
64
+ const loanAtExit = num(exit['loan_balance_at_exit']);
65
+ if (net != null && loanAtExit != null) {
66
+ c.add('exit_analysis.net_proceeds_to_equity', 'Net Sale Proceeds to Equity', 'currency', net - loanAtExit);
67
+ }
68
+ }
69
+ return { fields: c.fields };
70
+ }
71
+ function labelYear(row, i) {
72
+ const y = num(row['year']);
73
+ return y ?? i + 1;
74
+ }
75
+ //# sourceMappingURL=dcf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dcf.js","sourceRoot":"","sources":["../src/dcf.ts"],"names":[],"mappings":"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"}
package/dist/debt.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ import { type DerivedField } from './derived.js';
2
+ type Row = Record<string, unknown>;
3
+ export interface DebtDerivation {
4
+ fields: DerivedField[];
5
+ /** True when the loan is interest-only (no amortizing payment). */
6
+ interestOnly: boolean;
7
+ }
8
+ /** Foot a debt_structure content block. Pure: never mutates `content`. */
9
+ export declare function deriveDebt(content: Row): DebtDerivation;
10
+ export {};
11
+ //# sourceMappingURL=debt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debt.d.ts","sourceRoot":"","sources":["../src/debt.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAEvE,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAInC,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,mEAAmE;IACnE,YAAY,EAAE,OAAO,CAAC;CACvB;AAoCD,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,OAAO,EAAE,GAAG,GAAG,cAAc,CA6BvD"}
package/dist/debt.js ADDED
@@ -0,0 +1,85 @@
1
+ // Deterministic debt-service footing — the loan terms (amount, rate, amortization,
2
+ // IO) are the inputs; monthly and annual debt service foot from them. Same role
3
+ // for the debt_structure section that deriveRentRoll / deriveOperatingStatement
4
+ // play for their sections: one source of truth so the editor, CLI, and Excel
5
+ // converter never disagree (invariant #4).
6
+ //
7
+ // This is plain deterministic arithmetic — the standard mortgage payment formula,
8
+ // not AI math (invariant #1). The pmt() here is byte-identical to the calc
9
+ // engine's `pmt` builtin (calc/builtins.ts) so a footed annual_debt_service equals
10
+ // what `evaluateCalc` would produce from the same inputs.
11
+ //
12
+ // Conventions:
13
+ // - Amortizing loan: monthly_debt_service = pmt(rate/12, amort_years*12, loan);
14
+ // annual_debt_service = monthly * 12. This is the *fully-amortizing* payment —
15
+ // the conservative figure DSCR/debt-yield are sized against — even when the
16
+ // loan carries an initial interest-only period.
17
+ // - Interest-only loan: annual_debt_service = loan * rate; monthly = annual / 12.
18
+ // - Field-name tolerance: the rate is read from the first present of several
19
+ // conventions (interest_rate, all_in_rate_at_close, note_rate_at_close, …);
20
+ // IO is detected from amortization === "interest_only" or a missing/zero
21
+ // amortization term.
22
+ import { collector, numOrNull } from './derived.js';
23
+ const num = numOrNull;
24
+ const RATE_KEYS = [
25
+ 'interest_rate',
26
+ 'all_in_rate_at_close',
27
+ 'note_rate_at_close',
28
+ 'interest_rate_at_close',
29
+ ];
30
+ const AMORT_KEYS = ['amortization_years', 'amortization_period_years'];
31
+ function firstNum(row, keys) {
32
+ for (const k of keys) {
33
+ const n = num(row[k]);
34
+ if (n != null)
35
+ return n;
36
+ }
37
+ return null;
38
+ }
39
+ /** Standard mortgage payment — positive periodic payment for present value `pv`
40
+ * at periodic `rate` over `n` periods. Identical to calc/builtins.ts `pmt`. */
41
+ function pmt(rate, n, pv) {
42
+ if (n === 0)
43
+ return 0;
44
+ if (rate === 0)
45
+ return pv / n;
46
+ return (pv * rate) / (1 - (1 + rate) ** -n);
47
+ }
48
+ /** Is this an interest-only loan (no amortizing payment)? */
49
+ function isInterestOnly(content) {
50
+ const amortStr = content['amortization'];
51
+ if (typeof amortStr === 'string' && amortStr.toLowerCase().replace(/[\s-]/g, '_') === 'interest_only') {
52
+ return true;
53
+ }
54
+ const amortYears = firstNum(content, AMORT_KEYS);
55
+ return amortYears == null || amortYears <= 0;
56
+ }
57
+ /** Foot a debt_structure content block. Pure: never mutates `content`. */
58
+ export function deriveDebt(content) {
59
+ const c = collector();
60
+ const loan = num(content['loan_amount']);
61
+ const rate = firstNum(content, RATE_KEYS);
62
+ const interestOnly = isInterestOnly(content);
63
+ if (loan == null || rate == null) {
64
+ return { fields: c.fields, interestOnly };
65
+ }
66
+ let monthly;
67
+ let annual;
68
+ if (interestOnly) {
69
+ // Interest-only: annual = loan × rate is the authoritative figure; monthly
70
+ // is just annual / 12 (rounded for whole-dollar display).
71
+ annual = loan * rate;
72
+ monthly = annual / 12;
73
+ }
74
+ else {
75
+ // Amortizing: files store a whole-dollar monthly payment with annual = 12 ×
76
+ // that, so the two always foot together; round monthly first.
77
+ const amortYears = firstNum(content, AMORT_KEYS) ?? 0;
78
+ monthly = Math.round(pmt(rate / 12, amortYears * 12, loan));
79
+ annual = monthly * 12;
80
+ }
81
+ c.add('monthly_debt_service', 'Monthly Debt Service', 'currency', monthly);
82
+ c.add('annual_debt_service', 'Annual Debt Service', 'currency', annual);
83
+ return { fields: c.fields, interestOnly };
84
+ }
85
+ //# sourceMappingURL=debt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debt.js","sourceRoot":"","sources":["../src/debt.ts"],"names":[],"mappings":"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"}