faf-mcp 1.0.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 (207) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/CLAUDE.md +73 -0
  3. package/LICENSE +22 -0
  4. package/README.md +165 -0
  5. package/assets/Project-faf-pckg-json-README.png +0 -0
  6. package/assets/icons/faf-icon-128.png +0 -0
  7. package/assets/icons/faf-icon-256.png +0 -0
  8. package/assets/icons/faf-icon-48.png +0 -0
  9. package/assets/icons/faf-icon-512.png +0 -0
  10. package/assets/icons/orange-smiley.svg +6 -0
  11. package/dist/src/compiler/index.d.ts +7 -0
  12. package/dist/src/compiler/index.js +24 -0
  13. package/dist/src/compiler/index.js.map +1 -0
  14. package/dist/src/compiler/scorer.d.ts +53 -0
  15. package/dist/src/compiler/scorer.js +189 -0
  16. package/dist/src/compiler/scorer.js.map +1 -0
  17. package/dist/src/compiler/slot-validator.d.ts +32 -0
  18. package/dist/src/compiler/slot-validator.js +293 -0
  19. package/dist/src/compiler/slot-validator.js.map +1 -0
  20. package/dist/src/compiler/type-detector.d.ts +62 -0
  21. package/dist/src/compiler/type-detector.js +388 -0
  22. package/dist/src/compiler/type-detector.js.map +1 -0
  23. package/dist/src/config/visibility.d.ts +41 -0
  24. package/dist/src/config/visibility.js +158 -0
  25. package/dist/src/config/visibility.js.map +1 -0
  26. package/dist/src/faf-core/commands/audit.d.ts +21 -0
  27. package/dist/src/faf-core/commands/audit.js +83 -0
  28. package/dist/src/faf-core/commands/audit.js.map +1 -0
  29. package/dist/src/faf-core/commands/auto.d.ts +25 -0
  30. package/dist/src/faf-core/commands/auto.js +74 -0
  31. package/dist/src/faf-core/commands/auto.js.map +1 -0
  32. package/dist/src/faf-core/commands/bi-sync.d.ts +26 -0
  33. package/dist/src/faf-core/commands/bi-sync.js +157 -0
  34. package/dist/src/faf-core/commands/bi-sync.js.map +1 -0
  35. package/dist/src/faf-core/commands/doctor.d.ts +17 -0
  36. package/dist/src/faf-core/commands/doctor.js +198 -0
  37. package/dist/src/faf-core/commands/doctor.js.map +1 -0
  38. package/dist/src/faf-core/commands/enhance.d.ts +46 -0
  39. package/dist/src/faf-core/commands/enhance.js +360 -0
  40. package/dist/src/faf-core/commands/enhance.js.map +1 -0
  41. package/dist/src/faf-core/commands/formats.d.ts +22 -0
  42. package/dist/src/faf-core/commands/formats.js +117 -0
  43. package/dist/src/faf-core/commands/formats.js.map +1 -0
  44. package/dist/src/faf-core/commands/init.d.ts +26 -0
  45. package/dist/src/faf-core/commands/init.js +114 -0
  46. package/dist/src/faf-core/commands/init.js.map +1 -0
  47. package/dist/src/faf-core/commands/innit.d.ts +7 -0
  48. package/dist/src/faf-core/commands/innit.js +13 -0
  49. package/dist/src/faf-core/commands/innit.js.map +1 -0
  50. package/dist/src/faf-core/commands/migrate.d.ts +15 -0
  51. package/dist/src/faf-core/commands/migrate.js +86 -0
  52. package/dist/src/faf-core/commands/migrate.js.map +1 -0
  53. package/dist/src/faf-core/commands/quick.d.ts +16 -0
  54. package/dist/src/faf-core/commands/quick.js +184 -0
  55. package/dist/src/faf-core/commands/quick.js.map +1 -0
  56. package/dist/src/faf-core/commands/score.d.ts +47 -0
  57. package/dist/src/faf-core/commands/score.js +49 -0
  58. package/dist/src/faf-core/commands/score.js.map +1 -0
  59. package/dist/src/faf-core/commands/sync.d.ts +16 -0
  60. package/dist/src/faf-core/commands/sync.js +210 -0
  61. package/dist/src/faf-core/commands/sync.js.map +1 -0
  62. package/dist/src/faf-core/commands/update.d.ts +12 -0
  63. package/dist/src/faf-core/commands/update.js +46 -0
  64. package/dist/src/faf-core/commands/update.js.map +1 -0
  65. package/dist/src/faf-core/commands/validate.d.ts +21 -0
  66. package/dist/src/faf-core/commands/validate.js +81 -0
  67. package/dist/src/faf-core/commands/validate.js.map +1 -0
  68. package/dist/src/faf-core/compiler/faf-compiler.d.ts +138 -0
  69. package/dist/src/faf-core/compiler/faf-compiler.js +794 -0
  70. package/dist/src/faf-core/compiler/faf-compiler.js.map +1 -0
  71. package/dist/src/faf-core/engines/dependency-tsa.d.ts +88 -0
  72. package/dist/src/faf-core/engines/dependency-tsa.js +361 -0
  73. package/dist/src/faf-core/engines/dependency-tsa.js.map +1 -0
  74. package/dist/src/faf-core/engines/fab-formats-processor.d.ts +166 -0
  75. package/dist/src/faf-core/engines/fab-formats-processor.js +1274 -0
  76. package/dist/src/faf-core/engines/fab-formats-processor.js.map +1 -0
  77. package/dist/src/faf-core/engines/faf-dna.d.ts +159 -0
  78. package/dist/src/faf-core/engines/faf-dna.js +554 -0
  79. package/dist/src/faf-core/engines/faf-dna.js.map +1 -0
  80. package/dist/src/faf-core/engines/relentless-context-extractor.d.ts +100 -0
  81. package/dist/src/faf-core/engines/relentless-context-extractor.js +625 -0
  82. package/dist/src/faf-core/engines/relentless-context-extractor.js.map +1 -0
  83. package/dist/src/faf-core/fix-once/colors.d.ts +104 -0
  84. package/dist/src/faf-core/fix-once/colors.js +236 -0
  85. package/dist/src/faf-core/fix-once/colors.js.map +1 -0
  86. package/dist/src/faf-core/fix-once/types.d.ts +257 -0
  87. package/dist/src/faf-core/fix-once/types.js +26 -0
  88. package/dist/src/faf-core/fix-once/types.js.map +1 -0
  89. package/dist/src/faf-core/fix-once/yaml.d.ts +57 -0
  90. package/dist/src/faf-core/fix-once/yaml.js +172 -0
  91. package/dist/src/faf-core/fix-once/yaml.js.map +1 -0
  92. package/dist/src/faf-core/generators/faf-generator-championship.d.ts +16 -0
  93. package/dist/src/faf-core/generators/faf-generator-championship.js +462 -0
  94. package/dist/src/faf-core/generators/faf-generator-championship.js.map +1 -0
  95. package/dist/src/faf-core/utils/balance-visualizer.d.ts +37 -0
  96. package/dist/src/faf-core/utils/balance-visualizer.js +197 -0
  97. package/dist/src/faf-core/utils/balance-visualizer.js.map +1 -0
  98. package/dist/src/faf-core/utils/championship-style.d.ts +109 -0
  99. package/dist/src/faf-core/utils/championship-style.js +219 -0
  100. package/dist/src/faf-core/utils/championship-style.js.map +1 -0
  101. package/dist/src/faf-core/utils/chrome-extension-detector.d.ts +73 -0
  102. package/dist/src/faf-core/utils/chrome-extension-detector.js +268 -0
  103. package/dist/src/faf-core/utils/chrome-extension-detector.js.map +1 -0
  104. package/dist/src/faf-core/utils/fafignore-parser.d.ts +20 -0
  105. package/dist/src/faf-core/utils/fafignore-parser.js +178 -0
  106. package/dist/src/faf-core/utils/fafignore-parser.js.map +1 -0
  107. package/dist/src/faf-core/utils/file-utils.d.ts +112 -0
  108. package/dist/src/faf-core/utils/file-utils.js +846 -0
  109. package/dist/src/faf-core/utils/file-utils.js.map +1 -0
  110. package/dist/src/faf-core/utils/native-file-finder.d.ts +115 -0
  111. package/dist/src/faf-core/utils/native-file-finder.js +211 -0
  112. package/dist/src/faf-core/utils/native-file-finder.js.map +1 -0
  113. package/dist/src/faf-core/utils/platform-detector.d.ts +30 -0
  114. package/dist/src/faf-core/utils/platform-detector.js +218 -0
  115. package/dist/src/faf-core/utils/platform-detector.js.map +1 -0
  116. package/dist/src/faf-core/utils/technical-credit.d.ts +35 -0
  117. package/dist/src/faf-core/utils/technical-credit.js +286 -0
  118. package/dist/src/faf-core/utils/technical-credit.js.map +1 -0
  119. package/dist/src/faf-core/utils/yaml-generator.d.ts +41 -0
  120. package/dist/src/faf-core/utils/yaml-generator.js +360 -0
  121. package/dist/src/faf-core/utils/yaml-generator.js.map +1 -0
  122. package/dist/src/handlers/behavioral-instruction.d.ts +16 -0
  123. package/dist/src/handlers/behavioral-instruction.js +43 -0
  124. package/dist/src/handlers/behavioral-instruction.js.map +1 -0
  125. package/dist/src/handlers/championship-tools.d.ts +113 -0
  126. package/dist/src/handlers/championship-tools.js +2602 -0
  127. package/dist/src/handlers/championship-tools.js.map +1 -0
  128. package/dist/src/handlers/engine-adapter.d.ts +28 -0
  129. package/dist/src/handlers/engine-adapter.js +603 -0
  130. package/dist/src/handlers/engine-adapter.js.map +1 -0
  131. package/dist/src/handlers/fileHandler.d.ts +36 -0
  132. package/dist/src/handlers/fileHandler.js +246 -0
  133. package/dist/src/handlers/fileHandler.js.map +1 -0
  134. package/dist/src/handlers/resources.d.ts +18 -0
  135. package/dist/src/handlers/resources.js +78 -0
  136. package/dist/src/handlers/resources.js.map +1 -0
  137. package/dist/src/handlers/tool-registry.d.ts +23 -0
  138. package/dist/src/handlers/tool-registry.js +68 -0
  139. package/dist/src/handlers/tool-registry.js.map +1 -0
  140. package/dist/src/handlers/tool-types.d.ts +167 -0
  141. package/dist/src/handlers/tool-types.js +7 -0
  142. package/dist/src/handlers/tool-types.js.map +1 -0
  143. package/dist/src/handlers/tools.d.ts +25 -0
  144. package/dist/src/handlers/tools.js +1168 -0
  145. package/dist/src/handlers/tools.js.map +1 -0
  146. package/dist/src/index.d.ts +2 -0
  147. package/dist/src/index.js +17 -0
  148. package/dist/src/index.js.map +1 -0
  149. package/dist/src/server.d.ts +28 -0
  150. package/dist/src/server.js +179 -0
  151. package/dist/src/server.js.map +1 -0
  152. package/dist/src/test-all-functions.d.ts +15 -0
  153. package/dist/src/test-all-functions.js +163 -0
  154. package/dist/src/test-all-functions.js.map +1 -0
  155. package/dist/src/types/mcp-tools.d.ts +53 -0
  156. package/dist/src/types/mcp-tools.js +77 -0
  157. package/dist/src/types/mcp-tools.js.map +1 -0
  158. package/dist/src/types/project-types.d.ts +22 -0
  159. package/dist/src/types/project-types.js +85 -0
  160. package/dist/src/types/project-types.js.map +1 -0
  161. package/dist/src/types/slots.d.ts +39 -0
  162. package/dist/src/types/slots.js +162 -0
  163. package/dist/src/types/slots.js.map +1 -0
  164. package/dist/src/types/tool-visibility.d.ts +36 -0
  165. package/dist/src/types/tool-visibility.js +510 -0
  166. package/dist/src/types/tool-visibility.js.map +1 -0
  167. package/dist/src/utils/auto-path-detection.d.ts +26 -0
  168. package/dist/src/utils/auto-path-detection.js +198 -0
  169. package/dist/src/utils/auto-path-detection.js.map +1 -0
  170. package/dist/src/utils/championship-format.d.ts +30 -0
  171. package/dist/src/utils/championship-format.js +79 -0
  172. package/dist/src/utils/championship-format.js.map +1 -0
  173. package/dist/src/utils/cli-detector.d.ts +20 -0
  174. package/dist/src/utils/cli-detector.js +230 -0
  175. package/dist/src/utils/cli-detector.js.map +1 -0
  176. package/dist/src/utils/display-protocol.d.ts +57 -0
  177. package/dist/src/utils/display-protocol.js +131 -0
  178. package/dist/src/utils/display-protocol.js.map +1 -0
  179. package/dist/src/utils/faf-file-finder.d.ts +59 -0
  180. package/dist/src/utils/faf-file-finder.js +139 -0
  181. package/dist/src/utils/faf-file-finder.js.map +1 -0
  182. package/dist/src/utils/fuzzy-detector.d.ts +56 -0
  183. package/dist/src/utils/fuzzy-detector.js +221 -0
  184. package/dist/src/utils/fuzzy-detector.js.map +1 -0
  185. package/dist/src/utils/path-resolver.d.ts +51 -0
  186. package/dist/src/utils/path-resolver.js +214 -0
  187. package/dist/src/utils/path-resolver.js.map +1 -0
  188. package/dist/src/utils/type-guards.d.ts +9 -0
  189. package/dist/src/utils/type-guards.js +27 -0
  190. package/dist/src/utils/type-guards.js.map +1 -0
  191. package/dist/src/utils/username-detector.d.ts +27 -0
  192. package/dist/src/utils/username-detector.js +90 -0
  193. package/dist/src/utils/username-detector.js.map +1 -0
  194. package/dist/src/utils/visual-style.d.ts +62 -0
  195. package/dist/src/utils/visual-style.js +164 -0
  196. package/dist/src/utils/visual-style.js.map +1 -0
  197. package/dist/src/version.d.ts +9 -0
  198. package/dist/src/version.js +37 -0
  199. package/dist/src/version.js.map +1 -0
  200. package/package.json +114 -0
  201. package/scripts/discord-sync-curated.js +233 -0
  202. package/scripts/discord-sync-final.js +218 -0
  203. package/scripts/discord-sync-simple.js +175 -0
  204. package/scripts/discord-sync-working.js +187 -0
  205. package/scripts/discord-sync.js +181 -0
  206. package/scripts/postinstall.js +46 -0
  207. package/skill/SKILL.md +385 -0
@@ -0,0 +1,794 @@
1
+ "use strict";
2
+ /**
3
+ * 🏎️ FAF Scoring Compiler
4
+ * Deterministic, multi-pass compiler for .faf scoring
5
+ *
6
+ * Philosophy: Like Svelte, we compile away the complexity
7
+ * Result: Pure, traceable, reproducible scores
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.FafCompiler = void 0;
44
+ exports.compile = compile;
45
+ exports.compileWithTrace = compileWithTrace;
46
+ exports.verify = verify;
47
+ const yaml_1 = require("../fix-once/yaml");
48
+ const crypto = __importStar(require("crypto"));
49
+ const chrome_extension_detector_1 = require("../utils/chrome-extension-detector");
50
+ const fab_formats_processor_1 = require("../engines/fab-formats-processor");
51
+ const path = __importStar(require("path"));
52
+ // ============================================================================
53
+ // Main Compiler Class
54
+ // ============================================================================
55
+ class FafCompiler {
56
+ static VERSION = '3.0.0-compiler';
57
+ diagnostics = [];
58
+ trace;
59
+ ir;
60
+ constructor() {
61
+ this.trace = {
62
+ version: FafCompiler.VERSION,
63
+ timestamp: new Date().toISOString(),
64
+ inputHash: '',
65
+ passes: []
66
+ };
67
+ this.ir = {
68
+ version: FafCompiler.VERSION,
69
+ slots: [],
70
+ metadata: {}
71
+ };
72
+ }
73
+ /**
74
+ * Main compilation pipeline
75
+ */
76
+ async compile(fafPath) {
77
+ // Reset state for new compilation
78
+ this.diagnostics = [];
79
+ this.trace.passes = [];
80
+ this.ir.slots = [];
81
+ try {
82
+ // PASS 1: Parse
83
+ const source = await this.readSource(fafPath);
84
+ const ast = this.parse(source);
85
+ // PASS 2: Analyze
86
+ const analyzed = this.analyze(ast);
87
+ // PASS 3: Optimize (with discovery)
88
+ const optimized = await this.optimize(analyzed, fafPath);
89
+ // PASS 4: Generate
90
+ const result = this.generate(optimized);
91
+ // Add final checksum
92
+ const checksum = this.calculateChecksum(result);
93
+ return {
94
+ ...result,
95
+ trace: this.trace,
96
+ diagnostics: this.diagnostics,
97
+ ir: this.ir,
98
+ checksum
99
+ };
100
+ }
101
+ catch (error) {
102
+ const message = error instanceof Error ? error.message : String(error);
103
+ this.addDiagnostic('error', `Compilation failed: ${message}`);
104
+ throw error;
105
+ }
106
+ }
107
+ // ============================================================================
108
+ // PASS 1: Parser
109
+ // ============================================================================
110
+ async readSource(fafPath) {
111
+ const start = Date.now();
112
+ const fs = await import('fs/promises');
113
+ try {
114
+ const source = await fs.readFile(fafPath, 'utf-8');
115
+ this.trace.inputHash = crypto.createHash('md5').update(source).digest('hex');
116
+ this.recordPass('read', start, fafPath, source.length, [
117
+ `Read ${source.length} bytes from ${fafPath}`
118
+ ]);
119
+ return source;
120
+ }
121
+ catch (error) {
122
+ const message = error instanceof Error ? error.message : String(error);
123
+ this.addDiagnostic('error', `Cannot read file: ${fafPath}`, undefined, message);
124
+ throw error;
125
+ }
126
+ }
127
+ parse(source) {
128
+ const start = Date.now();
129
+ try {
130
+ const ast = (0, yaml_1.parse)(source);
131
+ if (!ast || typeof ast !== 'object') {
132
+ this.addDiagnostic('error', 'Invalid YAML: must be an object');
133
+ return {};
134
+ }
135
+ this.recordPass('parse', start, source.length, ast, [
136
+ `Parsed YAML into AST with ${Object.keys(ast).length} top-level keys`
137
+ ]);
138
+ return ast;
139
+ }
140
+ catch (error) {
141
+ const message = error instanceof Error ? error.message : String(error);
142
+ this.addDiagnostic('error', `Parse error: ${message}`);
143
+ return {};
144
+ }
145
+ }
146
+ // ============================================================================
147
+ // PASS 2: Analyzer
148
+ // ============================================================================
149
+ analyze(ast) {
150
+ const start = Date.now();
151
+ const analyzed = { ...ast };
152
+ const changes = [];
153
+ // Validate and normalize structure
154
+ if (!analyzed.project) {
155
+ analyzed.project = {};
156
+ changes.push('Added missing project section');
157
+ }
158
+ if (!analyzed.stack) {
159
+ analyzed.stack = {};
160
+ changes.push('Added missing stack section');
161
+ }
162
+ if (!analyzed.human_context) {
163
+ analyzed.human_context = {};
164
+ changes.push('Added missing human_context section');
165
+ }
166
+ // Type validation
167
+ this.validateTypes(analyzed);
168
+ // Check for deprecated fields
169
+ if (analyzed.ai_score !== undefined) {
170
+ this.addDiagnostic('warning', 'Embedded ai_score is deprecated and will be ignored');
171
+ delete analyzed.ai_score;
172
+ changes.push('Removed deprecated ai_score');
173
+ }
174
+ this.recordPass('analyze', start, ast, analyzed, changes);
175
+ return analyzed;
176
+ }
177
+ validateTypes(data) {
178
+ // Project validation
179
+ if (data.project?.name && typeof data.project.name !== 'string') {
180
+ this.addDiagnostic('error', 'project.name must be a string', {
181
+ line: 0, column: 0, field: 'project.name'
182
+ });
183
+ }
184
+ // Stack validation
185
+ const stackFields = ['frontend', 'backend', 'database', 'hosting'];
186
+ for (const field of stackFields) {
187
+ if (data.stack?.[field] && typeof data.stack[field] !== 'string') {
188
+ this.addDiagnostic('error', `stack.${field} must be a string`, {
189
+ line: 0, column: 0, field: `stack.${field}`
190
+ });
191
+ }
192
+ }
193
+ // Human context validation
194
+ const humanFields = ['who', 'what', 'why', 'where', 'when', 'how'];
195
+ for (const field of humanFields) {
196
+ const value = data.human_context?.[field];
197
+ if (value && typeof value !== 'string' && typeof value !== 'object') {
198
+ this.addDiagnostic('warning', `human_context.${field} should be a string or object`);
199
+ }
200
+ }
201
+ }
202
+ // ============================================================================
203
+ // PASS 3: Optimizer (with Discovery)
204
+ // ============================================================================
205
+ async optimize(ast, fafPath) {
206
+ const start = Date.now();
207
+ const optimized = { ...ast };
208
+ const changes = [];
209
+ // Discovery phase
210
+ if (fafPath) {
211
+ try {
212
+ const projectDir = path.dirname(fafPath);
213
+ const discovered = await this.discover(projectDir);
214
+ // Apply discovered values WITHOUT mutation
215
+ optimized._discovered = discovered;
216
+ changes.push(`Discovered ${Object.keys(discovered).length} items`);
217
+ }
218
+ catch (error) {
219
+ const message = error instanceof Error ? error.message : String(error);
220
+ this.addDiagnostic('warning', `Discovery failed: ${message}`);
221
+ }
222
+ }
223
+ // Remove None/Unknown values (optimization)
224
+ this.removeDefaults(optimized, changes);
225
+ this.recordPass('optimize', start, ast, optimized, changes);
226
+ return optimized;
227
+ }
228
+ async discover(projectDir) {
229
+ const processor = new fab_formats_processor_1.FabFormatsProcessor();
230
+ const analysis = await processor.processFiles(projectDir);
231
+ const discovered = {};
232
+ if (analysis.context) {
233
+ const ctx = analysis.context;
234
+ // Map discovered items (WITHOUT modifying original)
235
+ if (ctx.projectName)
236
+ discovered.projectName = ctx.projectName;
237
+ if (ctx.mainLanguage)
238
+ discovered.mainLanguage = ctx.mainLanguage;
239
+ if (ctx.framework)
240
+ discovered.framework = ctx.framework;
241
+ if (ctx.database)
242
+ discovered.database = ctx.database;
243
+ if (ctx.backend)
244
+ discovered.backend = ctx.backend;
245
+ if (ctx.hosting)
246
+ discovered.hosting = ctx.hosting;
247
+ if (ctx.buildTool)
248
+ discovered.buildTool = ctx.buildTool;
249
+ }
250
+ return discovered;
251
+ }
252
+ removeDefaults(data, changes) {
253
+ const defaults = ['None', 'Unknown', 'Not specified', 'N/A'];
254
+ const removeFromObject = (obj, path) => {
255
+ for (const key in obj) {
256
+ const value = obj[key];
257
+ const fullPath = path ? `${path}.${key}` : key;
258
+ if (defaults.includes(value)) {
259
+ delete obj[key];
260
+ changes.push(`Removed default value at ${fullPath}`);
261
+ }
262
+ else if (typeof value === 'object' && value !== null) {
263
+ removeFromObject(value, fullPath);
264
+ }
265
+ }
266
+ };
267
+ removeFromObject(data, '');
268
+ }
269
+ // ============================================================================
270
+ // PASS 4: Generator
271
+ // ============================================================================
272
+ generate(ast) {
273
+ const start = Date.now();
274
+ // Build IR first
275
+ const ir = this.buildIR(ast);
276
+ this.ir = {
277
+ version: FafCompiler.VERSION,
278
+ slots: ir,
279
+ metadata: { compiled: new Date().toISOString() }
280
+ };
281
+ // Calculate from IR
282
+ const slots = this.calculateSlots(ir);
283
+ const score = this.calculateScore(slots);
284
+ const result = {
285
+ score: Math.round(score),
286
+ filled: slots.filled,
287
+ total: slots.total,
288
+ breakdown: slots.breakdown
289
+ };
290
+ this.recordPass('generate', start, ast, result, [
291
+ `Generated score: ${result.score}% (${result.filled}/${result.total} slots)`
292
+ ]);
293
+ return result;
294
+ }
295
+ buildIR(ast) {
296
+ const slots = [];
297
+ // Detect project type to determine applicable stack slots
298
+ const projectType = this.detectProjectTypeFromContext(ast);
299
+ if (process.env.FAF_DEBUG) {
300
+ console.log(`\n[DEBUG] Project type detected: ${projectType}`);
301
+ }
302
+ const isFrontendProject = this.requiresFrontendStack(projectType);
303
+ const isBackendProject = this.requiresBackendStack(projectType);
304
+ // Auto-fill project.main_language for n8n workflows BEFORE reading slots
305
+ if (projectType === 'n8n-workflow') {
306
+ if (!ast.project)
307
+ ast.project = {};
308
+ if (!ast.project.main_language) {
309
+ ast.project.main_language = ast.tech_stack?.primary_language || 'JSON (workflow definition)';
310
+ }
311
+ }
312
+ // Project slots (3)
313
+ this.addSlot(slots, 'project.name', ast.project?.name, 'string', 'original', 1);
314
+ this.addSlot(slots, 'project.goal', ast.project?.goal, 'string', 'original', 1);
315
+ this.addSlot(slots, 'project.main_language', ast.project?.main_language, 'string', 'original', 1);
316
+ // Chrome Extension auto-fill: If it's a Chrome Extension, intelligently fill slots
317
+ if (projectType === 'chrome-extension') {
318
+ // Auto-fill Chrome Extension technical context
319
+ if (!ast.stack)
320
+ ast.stack = {};
321
+ if (!ast.stack.runtime)
322
+ ast.stack.runtime = 'Chrome/Browser';
323
+ if (!ast.stack.hosting)
324
+ ast.stack.hosting = 'Chrome Web Store';
325
+ if (!ast.stack.api_type)
326
+ ast.stack.api_type = 'Chrome Extension APIs';
327
+ if (!ast.stack.backend)
328
+ ast.stack.backend = 'Service Worker';
329
+ if (!ast.stack.database)
330
+ ast.stack.database = 'chrome.storage API';
331
+ if (!ast.deployment)
332
+ ast.deployment = 'Web Store Upload';
333
+ // Add Chrome Extension specific slots
334
+ this.addSlot(slots, 'stack.runtime', ast.stack.runtime, 'string', 'discovered', 1);
335
+ this.addSlot(slots, 'stack.hosting', ast.stack.hosting, 'string', 'discovered', 1);
336
+ this.addSlot(slots, 'stack.api_type', ast.stack.api_type, 'string', 'discovered', 1);
337
+ this.addSlot(slots, 'stack.backend', ast.stack.backend, 'string', 'discovered', 1);
338
+ this.addSlot(slots, 'stack.database', ast.stack.database, 'string', 'discovered', 1);
339
+ this.addSlot(slots, 'stack.deployment', ast.deployment, 'string', 'discovered', 1);
340
+ // Also include frontend framework if specified (e.g., Svelte Chrome Extension)
341
+ if (ast.stack?.frontend) {
342
+ this.addSlot(slots, 'stack.frontend', ast.stack.frontend, 'string', 'original', 1);
343
+ }
344
+ if (ast.stack?.build) {
345
+ this.addSlot(slots, 'stack.build', ast.stack.build, 'string', 'original', 1);
346
+ }
347
+ }
348
+ // Static HTML auto-fill: If it's a static HTML site, intelligently fill slots
349
+ if (projectType === 'static-html' || projectType === 'landing-page') {
350
+ if (!ast.stack)
351
+ ast.stack = {};
352
+ if (!ast.stack.frontend)
353
+ ast.stack.frontend = 'HTML/CSS/JavaScript';
354
+ if (!ast.stack.runtime)
355
+ ast.stack.runtime = 'Browser';
356
+ if (!ast.stack.hosting)
357
+ ast.stack.hosting = 'Static Hosting';
358
+ if (!ast.stack.build)
359
+ ast.stack.build = 'None';
360
+ this.addSlot(slots, 'stack.frontend', ast.stack.frontend, 'string', 'discovered', 1);
361
+ this.addSlot(slots, 'stack.runtime', ast.stack.runtime, 'string', 'discovered', 1);
362
+ this.addSlot(slots, 'stack.hosting', ast.stack.hosting, 'string', 'discovered', 1);
363
+ this.addSlot(slots, 'stack.build', ast.stack.build, 'string', 'discovered', 1);
364
+ // Leave backend, database, cicd as "None" - legitimate for static sites
365
+ }
366
+ // n8n Workflow auto-fill: Map n8n-specific fields to standard 21-slot system
367
+ if (projectType === 'n8n-workflow') {
368
+ // Map n8n context to existing stack slots (efficient, no slot inflation)
369
+ if (!ast.stack)
370
+ ast.stack = {};
371
+ // Runtime = workflow engine
372
+ if (!ast.stack.runtime) {
373
+ ast.stack.runtime = ast.tech_stack?.workflow_engine || 'n8n';
374
+ }
375
+ // Backend = n8n server runtime
376
+ if (!ast.stack.backend) {
377
+ ast.stack.backend = 'Node.js (n8n server)';
378
+ }
379
+ // API type = n8n trigger types
380
+ if (!ast.stack.api_type) {
381
+ ast.stack.api_type = 'Webhooks + HTTP';
382
+ }
383
+ // Database = vector DB or workflow state
384
+ if (!ast.stack.database) {
385
+ ast.stack.database = ast.tech_stack?.infrastructure?.vector_db || 'Workflow State';
386
+ }
387
+ // Hosting = deployment location
388
+ if (!ast.stack.hosting) {
389
+ ast.stack.hosting = 'n8n Cloud';
390
+ }
391
+ // Build tool = how workflows are created
392
+ if (!ast.stack.build) {
393
+ ast.stack.build = 'n8n Visual Editor';
394
+ }
395
+ // Connection = integrations (maps to stack.connection slot)
396
+ if (!ast.stack.connection && ast.tech_stack?.integrations) {
397
+ ast.stack.connection = Array.isArray(ast.tech_stack.integrations)
398
+ ? ast.tech_stack.integrations.join(', ')
399
+ : String(ast.tech_stack.integrations);
400
+ }
401
+ // Add n8n-specific slots (maps to standard 21-slot system)
402
+ // Backend slots (5)
403
+ this.addSlot(slots, 'stack.runtime', ast.stack.runtime, 'string', 'discovered', 1);
404
+ this.addSlot(slots, 'stack.backend', ast.stack.backend, 'string', 'discovered', 1);
405
+ this.addSlot(slots, 'stack.api_type', ast.stack.api_type, 'string', 'discovered', 1);
406
+ this.addSlot(slots, 'stack.database', ast.stack.database, 'string', 'discovered', 1);
407
+ this.addSlot(slots, 'stack.connection', ast.stack.connection, 'string', 'original', 1);
408
+ // Frontend slots (4) - n8n workflows don't have frontend, but we still count them
409
+ this.addSlot(slots, 'stack.frontend', ast.stack?.frontend, 'string', 'original', 1);
410
+ this.addSlot(slots, 'stack.css_framework', ast.stack?.css_framework, 'string', 'original', 1);
411
+ this.addSlot(slots, 'stack.ui_library', ast.stack?.ui_library, 'string', 'original', 1);
412
+ this.addSlot(slots, 'stack.state_management', ast.stack?.state_management, 'string', 'original', 1);
413
+ // Universal slots (3) will be added below (hosting, build, cicd)
414
+ }
415
+ // Stack slots - only add relevant ones based on project type
416
+ if (isFrontendProject) {
417
+ this.addSlot(slots, 'stack.frontend', ast.stack?.frontend, 'string', 'original', 1);
418
+ this.addSlot(slots, 'stack.css_framework', ast.stack?.css_framework, 'string', 'original', 1);
419
+ this.addSlot(slots, 'stack.ui_library', ast.stack?.ui_library, 'string', 'original', 1);
420
+ this.addSlot(slots, 'stack.state_management', ast.stack?.state_management, 'string', 'original', 1);
421
+ }
422
+ if (isBackendProject) {
423
+ this.addSlot(slots, 'stack.backend', ast.stack?.backend, 'string', 'original', 1);
424
+ this.addSlot(slots, 'stack.api_type', ast.stack?.api_type, 'string', 'original', 1);
425
+ this.addSlot(slots, 'stack.runtime', ast.stack?.runtime, 'string', 'original', 1);
426
+ this.addSlot(slots, 'stack.database', ast.stack?.database, 'string', 'original', 1);
427
+ this.addSlot(slots, 'stack.connection', ast.stack?.connection, 'string', 'original', 1);
428
+ }
429
+ // Universal stack slots (apply to all project types)
430
+ this.addSlot(slots, 'stack.hosting', ast.stack?.hosting, 'string', 'original', 1);
431
+ this.addSlot(slots, 'stack.build', ast.stack?.build, 'string', 'original', 1);
432
+ this.addSlot(slots, 'stack.cicd', ast.stack?.cicd, 'string', 'original', 1);
433
+ // Human context slots (6) - always applicable
434
+ this.addSlot(slots, 'human.who', ast.human_context?.who, 'string', 'original', 1);
435
+ this.addSlot(slots, 'human.what', ast.human_context?.what, 'string', 'original', 1);
436
+ this.addSlot(slots, 'human.why', ast.human_context?.why, 'string', 'original', 1);
437
+ this.addSlot(slots, 'human.where', ast.human_context?.where, 'string', 'original', 1);
438
+ this.addSlot(slots, 'human.when', ast.human_context?.when, 'string', 'original', 1);
439
+ this.addSlot(slots, 'human.how', ast.human_context?.how, 'string', 'original', 1);
440
+ // Discovered slots (if any)
441
+ if (ast._discovered) {
442
+ const discovered = ast._discovered;
443
+ const mapping = {
444
+ 'projectName': 'project.name',
445
+ 'mainLanguage': 'project.main_language',
446
+ 'framework': 'stack.frontend',
447
+ 'database': 'stack.database',
448
+ 'backend': 'stack.backend',
449
+ 'hosting': 'stack.hosting',
450
+ 'buildTool': 'stack.build'
451
+ };
452
+ for (const [key, path] of Object.entries(mapping)) {
453
+ if (discovered[key] && !this.hasValue(ast, path)) {
454
+ this.addSlot(slots, `discovery.${path}`, discovered[key], 'string', 'discovered', 1);
455
+ }
456
+ }
457
+ }
458
+ return slots;
459
+ }
460
+ addSlot(slots, path, value, type, source, weight) {
461
+ // Deduplication: Check if slot path already exists
462
+ const exists = slots.some(slot => slot.path === path);
463
+ if (exists) {
464
+ if (process.env.FAF_DEBUG) {
465
+ console.log(`[DEBUG] Skipped duplicate slot: ${path}`);
466
+ }
467
+ return; // Skip duplicate slot
468
+ }
469
+ const filled = this.isSlotFilled(value);
470
+ if (process.env.FAF_DEBUG) {
471
+ const valueStr = JSON.stringify(value) || '';
472
+ console.log(`[DEBUG] Added slot: ${path} | filled: ${filled} | value: ${valueStr.substring(0, 50)}`);
473
+ }
474
+ slots.push({
475
+ id: `slot_${slots.length + 1}`,
476
+ path,
477
+ value,
478
+ type,
479
+ source,
480
+ weight,
481
+ filled
482
+ });
483
+ }
484
+ isSlotFilled(value) {
485
+ // Handle null, undefined, false explicitly
486
+ if (value === null || value === undefined || value === false)
487
+ return false;
488
+ if (typeof value === 'string') {
489
+ // Also treat string representations of null/undefined as empty
490
+ const empty = ['', 'None', 'Unknown', 'Not specified', 'N/A', 'null', 'undefined', '~'];
491
+ // Also reject generic placeholders that provide no real context
492
+ const genericPlaceholders = [
493
+ 'Development teams',
494
+ 'Software development solution',
495
+ 'Improve development efficiency',
496
+ 'Cloud platform',
497
+ 'Ongoing development',
498
+ 'Modern development practices',
499
+ 'Development teams building next-generation software',
500
+ 'AI-powered development infrastructure with trust-driven workflows'
501
+ ];
502
+ const trimmed = value.trim();
503
+ return !empty.includes(trimmed) && !genericPlaceholders.includes(trimmed);
504
+ }
505
+ if (typeof value === 'number') {
506
+ // Numbers are valid unless they're NaN or Infinity
507
+ return !isNaN(value) && isFinite(value);
508
+ }
509
+ if (typeof value === 'object') {
510
+ // Arrays and objects need content
511
+ if (Array.isArray(value))
512
+ return value.length > 0;
513
+ return Object.keys(value).length > 0;
514
+ }
515
+ return true;
516
+ }
517
+ hasValue(ast, path) {
518
+ const parts = path.split('.');
519
+ let current = ast;
520
+ for (const part of parts) {
521
+ if (!current || !current[part])
522
+ return false;
523
+ current = current[part];
524
+ }
525
+ return this.isSlotFilled(current);
526
+ }
527
+ detectProjectTypeFromContext(ast) {
528
+ // Check for explicit project type
529
+ if (ast.project?.type)
530
+ return ast.project.type;
531
+ // Infer from goal and context
532
+ const goal = (ast.project?.goal || '').toLowerCase();
533
+ const what = (ast.human_context?.what || '').toLowerCase();
534
+ const mainLanguage = (ast.project?.main_language || '').toLowerCase();
535
+ // CLI tool indicators (check BEFORE Chrome Extension to avoid false positives)
536
+ if (goal.includes('cli') || what.includes('cli') ||
537
+ goal.includes('command line') || what.includes('command line')) {
538
+ return 'cli-tool';
539
+ }
540
+ // Chrome Extension detection with fuzzy matching (only if not CLI)
541
+ const goalDetection = chrome_extension_detector_1.ChromeExtensionDetector.detect(goal);
542
+ const whatDetection = chrome_extension_detector_1.ChromeExtensionDetector.detect(what);
543
+ if (goalDetection.detected || whatDetection.detected ||
544
+ ast.stack?.framework === 'Chrome Extension') {
545
+ return 'chrome-extension';
546
+ }
547
+ // Library indicators
548
+ if (goal.includes('library') || what.includes('library') ||
549
+ goal.includes('package') || what.includes('npm package')) {
550
+ return 'library';
551
+ }
552
+ // API/Backend indicators
553
+ if (goal.includes('api') || what.includes('api') ||
554
+ goal.includes('backend') || what.includes('backend') ||
555
+ ast.stack?.backend && !ast.stack?.frontend) {
556
+ return 'backend-api';
557
+ }
558
+ // Frontend indicators
559
+ if (ast.stack?.frontend || ast.stack?.css_framework || ast.stack?.ui_library) {
560
+ return ast.stack?.backend ? 'fullstack' : 'frontend';
561
+ }
562
+ // Language-based defaults
563
+ if (mainLanguage === 'python') {
564
+ if (ast.stack?.frontend)
565
+ return 'fullstack';
566
+ return 'python-app'; // Could be CLI, API, or data science
567
+ }
568
+ return 'generic';
569
+ }
570
+ requiresFrontendStack(projectType) {
571
+ const frontendTypes = ['frontend', 'fullstack', 'svelte', 'react', 'vue', 'angular'];
572
+ // Chrome extensions don't need traditional frontend stack
573
+ return frontendTypes.includes(projectType) && projectType !== 'chrome-extension';
574
+ }
575
+ requiresBackendStack(projectType) {
576
+ const backendTypes = ['backend-api', 'fullstack', 'cli-tool', 'library', 'python-app', 'node-api'];
577
+ // Chrome extensions don't need traditional backend stack
578
+ return backendTypes.includes(projectType) && projectType !== 'chrome-extension';
579
+ }
580
+ calculateSlots(ir) {
581
+ const sections = {
582
+ project: { filled: 0, total: 0, slots: [] },
583
+ stack: { filled: 0, total: 0, slots: [] },
584
+ human: { filled: 0, total: 0, slots: [] },
585
+ discovery: { filled: 0, total: 0, slots: [] }
586
+ };
587
+ for (const slot of ir) {
588
+ const [section] = slot.path.split('.');
589
+ const sectionKey = section === 'human' ? 'human' :
590
+ section === 'discovery' ? 'discovery' :
591
+ section === 'project' ? 'project' : 'stack';
592
+ const sec = sections[sectionKey];
593
+ sec.total++;
594
+ if (slot.filled)
595
+ sec.filled++;
596
+ sec.slots.push({
597
+ id: slot.id,
598
+ value: slot.value,
599
+ filled: slot.filled,
600
+ source: slot.source,
601
+ points: slot.filled ? slot.weight : 0
602
+ });
603
+ }
604
+ // Calculate percentages
605
+ const breakdown = {
606
+ project: {
607
+ ...sections.project,
608
+ percentage: sections.project.total > 0
609
+ ? Math.round((sections.project.filled / sections.project.total) * 100)
610
+ : 0
611
+ },
612
+ stack: {
613
+ ...sections.stack,
614
+ percentage: sections.stack.total > 0
615
+ ? Math.round((sections.stack.filled / sections.stack.total) * 100)
616
+ : 0
617
+ },
618
+ human: {
619
+ ...sections.human,
620
+ percentage: sections.human.total > 0
621
+ ? Math.round((sections.human.filled / sections.human.total) * 100)
622
+ : 0
623
+ },
624
+ discovery: {
625
+ ...sections.discovery,
626
+ percentage: sections.discovery.total > 0
627
+ ? Math.round((sections.discovery.filled / sections.discovery.total) * 100)
628
+ : 0
629
+ }
630
+ };
631
+ const filled = Object.values(sections).reduce((sum, sec) => sum + sec.filled, 0);
632
+ const total = Object.values(sections).reduce((sum, sec) => sum + sec.total, 0);
633
+ return { filled, total, breakdown };
634
+ }
635
+ calculateScore(slots) {
636
+ if (slots.total === 0)
637
+ return 0;
638
+ return (slots.filled / slots.total) * 100;
639
+ }
640
+ // ============================================================================
641
+ // Utilities
642
+ // ============================================================================
643
+ calculateChecksum(result) {
644
+ const data = JSON.stringify({
645
+ score: result.score,
646
+ filled: result.filled,
647
+ total: result.total,
648
+ version: FafCompiler.VERSION
649
+ });
650
+ return crypto.createHash('md5').update(data).digest('hex').slice(0, 8);
651
+ }
652
+ recordPass(name, startTime, input, output, changes) {
653
+ this.trace.passes.push({
654
+ name,
655
+ duration: Date.now() - startTime,
656
+ input: this.sanitize(input),
657
+ output: this.sanitize(output),
658
+ changes
659
+ });
660
+ }
661
+ sanitize(data) {
662
+ // Limit size for trace
663
+ const str = JSON.stringify(data);
664
+ if (str.length > 1000) {
665
+ return { _truncated: true, size: str.length };
666
+ }
667
+ return data;
668
+ }
669
+ addDiagnostic(severity, message, location, suggestion) {
670
+ this.diagnostics.push({ severity, message, location, suggestion });
671
+ }
672
+ // ============================================================================
673
+ // Public API
674
+ // ============================================================================
675
+ /**
676
+ * Compile with trace output
677
+ */
678
+ async compileWithTrace(fafPath) {
679
+ const result = await this.compile(fafPath);
680
+ this.printTrace(result);
681
+ return result;
682
+ }
683
+ /**
684
+ * Verify a checksum
685
+ */
686
+ async verify(fafPath, checksum) {
687
+ const result = await this.compile(fafPath);
688
+ return result.checksum === checksum;
689
+ }
690
+ /**
691
+ * Get intermediate representation
692
+ */
693
+ async getIR(fafPath) {
694
+ const result = await this.compile(fafPath);
695
+ return result.ir;
696
+ }
697
+ /**
698
+ * Print diagnostic report
699
+ */
700
+ printDiagnostics() {
701
+ if (this.diagnostics.length === 0) {
702
+ console.log('✓ No issues found');
703
+ return;
704
+ }
705
+ const byType = {
706
+ error: this.diagnostics.filter(d => d.severity === 'error'),
707
+ warning: this.diagnostics.filter(d => d.severity === 'warning'),
708
+ info: this.diagnostics.filter(d => d.severity === 'info')
709
+ };
710
+ if (byType.error.length > 0) {
711
+ console.log(`\n❌ ${byType.error.length} Errors:`);
712
+ byType.error.forEach(d => {
713
+ console.log(` ${d.message}`);
714
+ if (d.suggestion)
715
+ console.log(` → ${d.suggestion}`);
716
+ });
717
+ }
718
+ if (byType.warning.length > 0) {
719
+ console.log(`\n⚠️ ${byType.warning.length} Warnings:`);
720
+ byType.warning.forEach(d => {
721
+ console.log(` ${d.message}`);
722
+ if (d.suggestion)
723
+ console.log(` → ${d.suggestion}`);
724
+ });
725
+ }
726
+ if (byType.info.length > 0) {
727
+ console.log(`\nℹ️ ${byType.info.length} Info:`);
728
+ byType.info.forEach(d => {
729
+ console.log(` ${d.message}`);
730
+ });
731
+ }
732
+ }
733
+ /**
734
+ * Print compilation trace
735
+ */
736
+ printTrace(result) {
737
+ console.log('\n📊 FAF Compilation Trace');
738
+ console.log('═'.repeat(60));
739
+ console.log(`Version: ${result.trace.version}`);
740
+ console.log(`Input Hash: ${result.trace.inputHash}`);
741
+ console.log(`Checksum: ${result.checksum}`);
742
+ console.log();
743
+ console.log('Compilation Passes:');
744
+ result.trace.passes.forEach((pass, i) => {
745
+ console.log(` ${i + 1}. ${pass.name.toUpperCase()} (${pass.duration}ms)`);
746
+ pass.changes.forEach(change => {
747
+ console.log(` → ${change}`);
748
+ });
749
+ });
750
+ console.log();
751
+ console.log('Result:');
752
+ console.log(` Score: ${result.score}%`);
753
+ console.log(` Filled: ${result.filled}/${result.total} slots`);
754
+ console.log();
755
+ console.log('Breakdown:');
756
+ console.log(` Project: ${result.breakdown.project.filled}/${result.breakdown.project.total} (${result.breakdown.project.percentage}%)`);
757
+ console.log(` Stack: ${result.breakdown.stack.filled}/${result.breakdown.stack.total} (${result.breakdown.stack.percentage}%)`);
758
+ console.log(` Human: ${result.breakdown.human.filled}/${result.breakdown.human.total} (${result.breakdown.human.percentage}%)`);
759
+ if (result.breakdown.discovery.total > 0) {
760
+ console.log(` Discovery: ${result.breakdown.discovery.filled}/${result.breakdown.discovery.total} (${result.breakdown.discovery.percentage}%)`);
761
+ }
762
+ if (result.diagnostics.length > 0) {
763
+ console.log();
764
+ this.printDiagnostics();
765
+ }
766
+ console.log('═'.repeat(60));
767
+ }
768
+ }
769
+ exports.FafCompiler = FafCompiler;
770
+ // ============================================================================
771
+ // Export convenience functions
772
+ // ============================================================================
773
+ /**
774
+ * Compile a .faf file
775
+ */
776
+ async function compile(fafPath) {
777
+ const compiler = new FafCompiler();
778
+ return compiler.compile(fafPath);
779
+ }
780
+ /**
781
+ * Compile with trace output
782
+ */
783
+ async function compileWithTrace(fafPath) {
784
+ const compiler = new FafCompiler();
785
+ return compiler.compileWithTrace(fafPath);
786
+ }
787
+ /**
788
+ * Verify a checksum
789
+ */
790
+ async function verify(fafPath, checksum) {
791
+ const compiler = new FafCompiler();
792
+ return compiler.verify(fafPath, checksum);
793
+ }
794
+ //# sourceMappingURL=faf-compiler.js.map