progmune-runtime 2.1.6 → 3.2.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 (356) hide show
  1. package/README.md +108 -468
  2. package/dist/ablation-study.js +144 -0
  3. package/dist/ablation-study.test.js +18 -0
  4. package/dist/action-runtime.js +3 -1
  5. package/dist/active-learning.js +211 -0
  6. package/dist/analytics.js +139 -0
  7. package/dist/asset-factory.js +309 -0
  8. package/dist/asset-growth.js +244 -0
  9. package/dist/asset-promotion.js +382 -0
  10. package/dist/asset-quality.js +550 -0
  11. package/dist/audit/business-translator.js +285 -0
  12. package/dist/audit/cli.js +66 -0
  13. package/dist/audit/formatters/html.js +379 -0
  14. package/dist/audit/formatters/json.js +11 -0
  15. package/dist/audit/formatters/markdown.js +192 -0
  16. package/dist/audit/formatters/terminal.js +189 -0
  17. package/dist/audit/index.js +25 -0
  18. package/dist/audit/report-builder.js +318 -0
  19. package/dist/audit/types.js +8 -0
  20. package/dist/audit.js +3 -3
  21. package/dist/auto-benchmark-generator.js +137 -0
  22. package/dist/auto-benchmark-generator.test.js +45 -0
  23. package/dist/auto-protocol-synthesizer.js +362 -0
  24. package/dist/auto-protocol-synthesizer.test.js +82 -0
  25. package/dist/autonomous-patch.js +175 -0
  26. package/dist/autonomous-patch.test.js +128 -0
  27. package/dist/badge/badge-server.js +98 -0
  28. package/dist/behavior-miner.js +442 -0
  29. package/dist/belief-layer.js +475 -0
  30. package/dist/benchmark-count.js +5 -0
  31. package/dist/benchmark-generator.js +211 -0
  32. package/dist/benchmark-harness.js +201 -0
  33. package/dist/benchmark-pass-rate.js +7 -0
  34. package/dist/benchmark-report.js +8 -3
  35. package/dist/benchmark-save.js +14 -1
  36. package/dist/bootstrap-validation.js +197 -0
  37. package/dist/bootstrap-validation.test.js +51 -0
  38. package/dist/branch-ledger.js +1 -1
  39. package/dist/capability-gap.js +130 -0
  40. package/dist/certify-html.js +351 -0
  41. package/dist/certify.js +326 -0
  42. package/dist/check.js +4 -4
  43. package/dist/compliance-miner.js +447 -0
  44. package/dist/continuous-benchmark.js +194 -0
  45. package/dist/continuous-benchmark.test.js +116 -0
  46. package/dist/corpus-stats.js +173 -0
  47. package/dist/counterfactual-engine.js +288 -0
  48. package/dist/coverage-dashboard.js +109 -0
  49. package/dist/coverage-system.test.js +205 -0
  50. package/dist/cross-repo-precision.js +352 -0
  51. package/dist/cve-benchmark.js +180 -0
  52. package/dist/cve-benchmark.test.js +28 -0
  53. package/dist/cve-collector.js +73 -0
  54. package/dist/data-quality.js +141 -0
  55. package/dist/decision-engine.js +388 -0
  56. package/dist/derive-metadata.js +250 -0
  57. package/dist/difficulty-active.test.js +198 -0
  58. package/dist/difficulty-map.js +244 -0
  59. package/dist/discovery-analytics.js +125 -0
  60. package/dist/discovery-model.js +149 -0
  61. package/dist/discovery-optimize.test.js +199 -0
  62. package/dist/discovery-trace.js +276 -0
  63. package/dist/discovery-trace.test.js +97 -0
  64. package/dist/emitter.js +83 -1
  65. package/dist/enterprise-dashboard.js +405 -0
  66. package/dist/eval-hardening.js +297 -0
  67. package/dist/eval-hardening.test.js +85 -0
  68. package/dist/evaluation-campaign.js +359 -0
  69. package/dist/evaluation-campaign.test.js +181 -0
  70. package/dist/evidence-growth.js +143 -0
  71. package/dist/evidence-repository.js +209 -0
  72. package/dist/evidence-system.js +441 -0
  73. package/dist/execute.js +15 -7
  74. package/dist/experimental/software-physics.js +291 -0
  75. package/dist/experimental/state-inference.js +516 -0
  76. package/dist/experimental/unsupervised-physics.js +230 -0
  77. package/dist/extract-ir-python.js +54 -7
  78. package/dist/extract-ir.js +376 -12
  79. package/dist/failure-collector.js +2 -2
  80. package/dist/failure-corpus.js +322 -9
  81. package/dist/feedback.js +16 -5
  82. package/dist/feedback.test.js +49 -0
  83. package/dist/file-lock.js +1 -1
  84. package/dist/flywheel-batch.js +292 -0
  85. package/dist/frameworks/express-cli.js +237 -0
  86. package/dist/frameworks/express-detector.js +445 -0
  87. package/dist/frameworks/express-detector.test.js +206 -0
  88. package/dist/frameworks/index.js +30 -0
  89. package/dist/frameworks/nestjs-detector.js +302 -0
  90. package/dist/frameworks/trpc-detector.js +161 -0
  91. package/dist/frameworks/version-awareness.js +179 -0
  92. package/dist/function-synonyms.js +164 -0
  93. package/dist/function-synonyms.test.js +68 -0
  94. package/dist/generalization.test.js +352 -0
  95. package/dist/goal-annotator.js +113 -0
  96. package/dist/goal-planner.js +563 -0
  97. package/dist/gold-cve.js +164 -0
  98. package/dist/gold-cve.test.js +104 -0
  99. package/dist/gold-quality.js +206 -0
  100. package/dist/gold-tiers.js +241 -0
  101. package/dist/governance-dashboard.js +327 -0
  102. package/dist/graph-viz.js +240 -0
  103. package/dist/guided-frontier.js +195 -0
  104. package/dist/hierarchical-planner.js +148 -0
  105. package/dist/identifier-parser.js +260 -0
  106. package/dist/immune-metrics.js +93 -0
  107. package/dist/immune-receiver.js +158 -0
  108. package/dist/immune-reporter.js +1 -1
  109. package/dist/improvement-orchestrator.js +206 -0
  110. package/dist/inject-p0-vocabulary.js +300 -0
  111. package/dist/intent-parser.js +218 -0
  112. package/dist/invariant-algebra.js +476 -0
  113. package/dist/invariant-calculus.js +533 -0
  114. package/dist/ir-utils.js +70 -0
  115. package/dist/ir-utils.test.js +50 -0
  116. package/dist/knowledge-api.js +312 -0
  117. package/dist/knowledge-evolution.js +452 -0
  118. package/dist/knowledge-explorer.js +506 -0
  119. package/dist/knowledge-flywheel.js +274 -0
  120. package/dist/knowledge-governance.js +338 -0
  121. package/dist/knowledge-governance.test.js +150 -0
  122. package/dist/knowledge-graph.js +181 -0
  123. package/dist/knowledge-guided-synth.js +246 -0
  124. package/dist/knowledge-loop.test.js +77 -0
  125. package/dist/knowledge-object.js +316 -0
  126. package/dist/knowledge-package.js +98 -0
  127. package/dist/kpi-dashboard.js +561 -0
  128. package/dist/l3-cross-function.js +280 -0
  129. package/dist/learning-ranker.js +148 -0
  130. package/dist/learning-ranker.test.js +291 -0
  131. package/dist/ledger/accountability.js +322 -0
  132. package/dist/ledger/chain-builder.js +185 -0
  133. package/dist/ledger/cli.js +222 -0
  134. package/dist/ledger/index.js +13 -0
  135. package/dist/ledger/signatures.js +193 -0
  136. package/dist/ledger/types.js +9 -0
  137. package/dist/llm.js +74 -3
  138. package/dist/load-benchmarks.js +8 -3
  139. package/dist/logger.js +66 -0
  140. package/dist/logger.test.js +37 -0
  141. package/dist/logistic-reward.js +339 -0
  142. package/dist/logistic-reward.test.js +180 -0
  143. package/dist/macro-graph.js +193 -0
  144. package/dist/macro-repair.js +183 -0
  145. package/dist/mcp-server.mjs +1202 -483
  146. package/dist/memory-layer.js +42 -5
  147. package/dist/multi-repo-precision.js +422 -0
  148. package/dist/name-free-protocol.js +425 -0
  149. package/dist/name-free-protocol.test.js +170 -0
  150. package/dist/name-scrambling.js +138 -0
  151. package/dist/name-scrambling.test.js +16 -0
  152. package/dist/p3-observability.test.js +281 -0
  153. package/dist/p5-orchestrator.test.js +225 -0
  154. package/dist/pairwise-preference.js +294 -0
  155. package/dist/pairwise-preference.test.js +140 -0
  156. package/dist/planner-constraints.js +104 -0
  157. package/dist/planner-prompts.js +155 -0
  158. package/dist/planner-telemetry.js +415 -0
  159. package/dist/planner-trace.js +214 -0
  160. package/dist/planner.js +162 -167
  161. package/dist/plsb/artifact.js +116 -0
  162. package/dist/plsb/cli.js +71 -0
  163. package/dist/plsb/index.js +19 -0
  164. package/dist/plsb/leaderboard.js +249 -0
  165. package/dist/plsb/report-md.js +156 -0
  166. package/dist/plsb/schema.js +179 -0
  167. package/dist/plsb-benchmark.js +284 -0
  168. package/dist/plsb-benchmark.test.js +119 -0
  169. package/dist/policy/cli.js +134 -0
  170. package/dist/policy/engine.js +333 -0
  171. package/dist/policy/index.js +12 -0
  172. package/dist/policy/types.js +59 -0
  173. package/dist/policy-miner.js +505 -0
  174. package/dist/precision-analyze.js +229 -0
  175. package/dist/precision-benchmark.js +147 -0
  176. package/dist/precision-label-c.js +134 -0
  177. package/dist/precision-label.js +193 -0
  178. package/dist/precision-report-c.js +149 -0
  179. package/dist/precision-report.js +246 -0
  180. package/dist/progmune-status.js +108 -0
  181. package/dist/proof-engine.js +479 -0
  182. package/dist/proof-provenance.js +315 -0
  183. package/dist/protocol-coverage.js +294 -0
  184. package/dist/protocol-detector.js +1189 -0
  185. package/dist/protocol-embedding-expanded.js +297 -0
  186. package/dist/protocol-embedding-expanded.test.js +97 -0
  187. package/dist/protocol-embedding.js +195 -0
  188. package/dist/protocol-embedding.test.js +82 -0
  189. package/dist/protocol-extractor-v2.js +354 -0
  190. package/dist/protocol-extractor-v2.test.js +140 -0
  191. package/dist/protocol-extractor.js +310 -0
  192. package/dist/protocol-extractor.test.js +113 -0
  193. package/dist/protocol-foundation.js +322 -0
  194. package/dist/protocol-foundation.test.js +163 -0
  195. package/dist/protocol-frontier.js +243 -0
  196. package/dist/protocol-frontier.test.js +92 -0
  197. package/dist/protocol-gap-analyzer.js +228 -0
  198. package/dist/protocol-gap-analyzer.test.js +49 -0
  199. package/dist/protocol-invariants.js +276 -0
  200. package/dist/protocol-invariants.test.js +111 -0
  201. package/dist/protocol-knowledge.js +464 -0
  202. package/dist/protocol-miner.js +343 -0
  203. package/dist/protocol-mining.js +207 -0
  204. package/dist/protocol-mining.test.js +37 -0
  205. package/dist/protocol-registry.js +1 -1
  206. package/dist/protocol-security-benchmark.js +222 -0
  207. package/dist/protocol-vulnerability.js +257 -0
  208. package/dist/protocol-vulnerability.test.js +60 -0
  209. package/dist/python-benchmark.js +120 -0
  210. package/dist/python-emitter.js +163 -45
  211. package/dist/python-protocol-extractor.js +187 -0
  212. package/dist/python-protocol-extractor.test.js +116 -0
  213. package/dist/realworld-benchmark.js +646 -0
  214. package/dist/realworld-benchmark.test.js +36 -0
  215. package/dist/repair-arch.test.js +411 -0
  216. package/dist/repair-evolution.test.js +454 -0
  217. package/dist/repair-executor.js +719 -0
  218. package/dist/repair-proposal.js +4 -4
  219. package/dist/repair-ranker.js +141 -0
  220. package/dist/repair-strategies.js +419 -0
  221. package/dist/repair-taxonomy.js +234 -0
  222. package/dist/repair-types.js +12 -0
  223. package/dist/repo-evaluator.js +250 -0
  224. package/dist/repo-evaluator.test.js +128 -0
  225. package/dist/resource-abstraction.js +242 -0
  226. package/dist/resource-detector.js +211 -0
  227. package/dist/result.test.js +43 -0
  228. package/dist/reward-system.js +411 -0
  229. package/dist/reward-system.test.js +175 -0
  230. package/dist/risk-model.js +215 -0
  231. package/dist/rule-miner.js +234 -7
  232. package/dist/rule-specificity.js +254 -0
  233. package/dist/runtime-types.js +27 -0
  234. package/dist/scaffold.js +208 -0
  235. package/dist/scale-collector.test.js +101 -0
  236. package/dist/scale-trajectory-collector.js +128 -0
  237. package/dist/sdk.js +250 -0
  238. package/dist/search-planner.js +4 -41
  239. package/dist/semantic-snapshot.js +1 -1
  240. package/dist/semantic-topology.js +121 -0
  241. package/dist/semantic-trace.js +310 -317
  242. package/dist/sequence-extractor.js +343 -0
  243. package/dist/skill-library.js +245 -0
  244. package/dist/skill-planner.test.js +189 -0
  245. package/dist/software-physics.js +291 -0
  246. package/dist/software-physics.test.js +81 -0
  247. package/dist/ssg-precision.js +478 -0
  248. package/dist/ssg-validator.js +71 -21
  249. package/dist/state-inference-doubleblind.test.js +160 -0
  250. package/dist/state-inference.js +516 -0
  251. package/dist/state-inference.test.js +115 -0
  252. package/dist/state-machine-fingerprint.js +345 -0
  253. package/dist/state-machine-fingerprint.test.js +120 -0
  254. package/dist/state-miner.js +386 -0
  255. package/dist/state-name-inference.js +213 -0
  256. package/dist/state-name-inference.test.js +69 -0
  257. package/dist/strategy-planner.js +262 -96
  258. package/dist/strategy-planner.test.js +135 -0
  259. package/dist/telemetry-analytics.test.js +402 -0
  260. package/dist/terminal-format.js +68 -0
  261. package/dist/terminal-format.test.js +83 -0
  262. package/dist/topology-factory.js +196 -0
  263. package/dist/topology-representation.js +242 -0
  264. package/dist/topology-representation.test.js +27 -0
  265. package/dist/trajectory-augmentation.js +254 -0
  266. package/dist/trajectory-augmentation.test.js +63 -0
  267. package/dist/trajectory-corpus.js +440 -0
  268. package/dist/trajectory-corpus.test.js +32 -0
  269. package/dist/trajectory-feedback.test.js +116 -0
  270. package/dist/transition-synthesizer.js +286 -0
  271. package/dist/transition-synthesizer.test.js +123 -0
  272. package/dist/trust/api-semantic-mapper.js +809 -0
  273. package/dist/trust/call-graph-propagator.js +225 -0
  274. package/dist/trust/cli.js +122 -0
  275. package/dist/trust/compliance-scorer.js +283 -0
  276. package/dist/trust/confidence-calculator.js +261 -0
  277. package/dist/trust/engine.js +1145 -0
  278. package/dist/trust/explainability.js +85 -0
  279. package/dist/trust/formatters/ci.js +42 -0
  280. package/dist/trust/formatters/json.js +11 -0
  281. package/dist/trust/formatters/terminal.js +152 -0
  282. package/dist/trust/index.js +39 -0
  283. package/dist/trust/phase1-verify.js +171 -0
  284. package/dist/trust/protocol-domain-validator.js +697 -0
  285. package/dist/trust/score-calculator.js +282 -0
  286. package/dist/trust/ssg-bridge.js +641 -0
  287. package/dist/trust/ssg-bridge.test.js +269 -0
  288. package/dist/trust/types.js +67 -0
  289. package/dist/trust/violation-trace.js +335 -0
  290. package/dist/trust-api.js +179 -0
  291. package/dist/trust-calibration.js +279 -0
  292. package/dist/unknown-protocol-discovery.js +339 -0
  293. package/dist/unknown-protocol-discovery.test.js +102 -0
  294. package/dist/unsupervised-physics.js +230 -0
  295. package/dist/unsupervised-physics.test.js +95 -0
  296. package/dist/utils.test.js +37 -0
  297. package/dist/validator.js +187 -10
  298. package/dist/verification-intelligence.js +475 -0
  299. package/dist/verify-api.js +432 -0
  300. package/dist/vi-impact-report.js +293 -0
  301. package/dist/wl-fingerprint.js +162 -0
  302. package/dist/wl-fingerprint.test.js +130 -0
  303. package/dist/zeroshot-strategy.js +139 -0
  304. package/docs/Progmune_/346/212/225/350/265/204/344/272/272/347/231/275/347/232/256/344/271/246_v2.0.html +576 -0
  305. package/docs/Progmune_/351/241/271/347/233/256/345/205/250/350/247/243.html +710 -0
  306. package/package.json +74 -7
  307. package/protocols.json +1956 -50
  308. package/.dockerignore +0 -14
  309. package/.mcp.json +0 -11
  310. package/.progmune_allowlist +0 -50
  311. package/.test_report/test_report.md +0 -87
  312. package/Dockerfile +0 -9
  313. package/FAQ.md +0 -167
  314. package/WHITEPAPER.md +0 -540
  315. package/demo-project/auth.ts +0 -55
  316. package/demo-project/tsconfig.json +0 -8
  317. package/dist/acl-breakdown.js +0 -13
  318. package/dist/all-sessions.js +0 -11
  319. package/dist/antibody-stats.js +0 -11
  320. package/dist/branch-tree-count.js +0 -14
  321. package/dist/common-fixpath.js +0 -12
  322. package/dist/constraint-types.js +0 -12
  323. package/dist/exec-metrics.js +0 -11
  324. package/dist/failure-report.js +0 -11
  325. package/dist/fast-path-hits.js +0 -13
  326. package/dist/fingerprint-list.js +0 -15
  327. package/dist/gen-history-log.js +0 -13
  328. package/dist/heatmap-data.js +0 -11
  329. package/dist/recent-session.js +0 -12
  330. package/dist/svl-distribution.js +0 -11
  331. package/dist/terminal-status.js +0 -11
  332. package/dist/token-savings.js +0 -11
  333. package/dist/total-repairs.js +0 -12
  334. package/dist/unresolved-count.js +0 -12
  335. package/dist/valid-fingerprints.js +0 -13
  336. package/dist/verify-ledgers.js +0 -11
  337. package/docs/whitepaper-style.css +0 -77
  338. package/docs/whitepaper-v2.1.md +0 -609
  339. package/docs/whitepaper-v2.2.md +0 -1064
  340. package/docs/whitepaper-v2.2.pdf +0 -0
  341. package/fly.toml +0 -31
  342. package/public/dashboard.html +0 -119
  343. package/server/hub.js +0 -116
  344. package/test/replay-golden/sess_1780063202050_mgeld.json +0 -9
  345. package/test/replay-golden/sess_1780064032560_gocld.json +0 -354
  346. package/test/replay-golden/sess_1780064413331_s2709.json +0 -606
  347. package/test/replay-golden/sess_1780064792710_y3avo.json +0 -614
  348. package/test/replay-golden.ts +0 -84
  349. package/test_benchmark.js +0 -165
  350. package/test_comprehensive.mjs +0 -638
  351. package/test_concurrency.js +0 -129
  352. package/test_ir_robustness.js +0 -85
  353. package/test_semantic_contracts.js +0 -269
  354. package/test_ssg_stress.js +0 -156
  355. package/test_svl3.js +0 -58
  356. package/tsconfig.json +0 -17
@@ -192,6 +192,150 @@ function deriveOutputs(returnType) {
192
192
  const t = returnType.replace(/\[\]$/, "").replace(/<[^>]*>/g, "").split("|")[0].trim();
193
193
  return (t === "void" || t === "any") ? [] : [t];
194
194
  }
195
+ /** Read tsconfig.json resolving the extends chain via TypeScript's config parser. */
196
+ function readOriginalTsConfig(tsconfigPath) {
197
+ try {
198
+ const raw = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
199
+ if (raw.error)
200
+ return null;
201
+ const parsed = ts.parseJsonConfigFileContent(raw.config, ts.sys, path.dirname(tsconfigPath));
202
+ if (parsed.errors?.length > 0) {
203
+ // Non-fatal — config may still be usable
204
+ }
205
+ const co = parsed.options;
206
+ // Convert numeric ModuleResolutionKind to string
207
+ let modRes;
208
+ if (co.moduleResolution !== undefined && typeof co.moduleResolution === 'number') {
209
+ modRes = ts.ModuleResolutionKind[co.moduleResolution];
210
+ }
211
+ return {
212
+ paths: (co.paths && Object.keys(co.paths).length > 0) ? co.paths : undefined,
213
+ baseUrl: co.baseUrl,
214
+ moduleResolution: modRes?.toLowerCase(),
215
+ };
216
+ }
217
+ catch {
218
+ return null;
219
+ }
220
+ }
221
+ /**
222
+ * Manual module resolution for bundler/NodeNext projects.
223
+ * Falls back after ts-morph's built-in resolution fails.
224
+ */
225
+ function manualResolveModule(moduleSpecifier, sourceFilePath, projectRoot, originalConfig) {
226
+ if (!moduleSpecifier || !moduleSpecifier.startsWith('.') && !moduleSpecifier.startsWith('@')) {
227
+ return null; // Not a relative or aliased import — skip
228
+ }
229
+ // ── 1. Path alias resolution (bundler) ──
230
+ if (originalConfig?.paths) {
231
+ const baseUrlPath = originalConfig.baseUrl
232
+ ? path.resolve(projectRoot, originalConfig.baseUrl)
233
+ : projectRoot;
234
+ for (const [aliasPattern, targets] of Object.entries(originalConfig.paths)) {
235
+ // Convert TypeScript glob pattern to regex: "@/*" → /^@\/(.*)$/
236
+ // Handle both glob ("@/*") and bare ("libnpmconfig") aliases
237
+ const hasWildcard = aliasPattern.includes('*');
238
+ let wildcard = '';
239
+ let matched = false;
240
+ if (hasWildcard) {
241
+ const aliasRegexSrc = '^' + aliasPattern.replace(/\*/g, '(.*)') + '$';
242
+ const aliasRegex = new RegExp(aliasRegexSrc);
243
+ const match = moduleSpecifier.match(aliasRegex);
244
+ if (!match)
245
+ continue;
246
+ wildcard = match[1] || '';
247
+ matched = true;
248
+ }
249
+ else {
250
+ // Bare alias: must be an exact match
251
+ if (moduleSpecifier !== aliasPattern && !moduleSpecifier.startsWith(aliasPattern + '/')) {
252
+ continue;
253
+ }
254
+ matched = true;
255
+ // For bare alias with subpath: "libnpmconfig/foo" → wildcard = "/foo"
256
+ if (moduleSpecifier.startsWith(aliasPattern + '/')) {
257
+ wildcard = moduleSpecifier.slice(aliasPattern.length); // "/foo"
258
+ }
259
+ }
260
+ if (!matched)
261
+ continue;
262
+ for (const target of targets) {
263
+ const resolvedRel = hasWildcard ? target.replace(/\*/g, wildcard) : (target + wildcard);
264
+ const candidateBase = path.resolve(baseUrlPath, resolvedRel);
265
+ // Try candidate as a file first
266
+ try {
267
+ const st = fs.statSync(candidateBase);
268
+ if (st.isFile())
269
+ return candidateBase;
270
+ }
271
+ catch { }
272
+ // Try adding .ts / .tsx / .d.ts extensions
273
+ for (const ext of ['.ts', '.tsx', '.d.ts']) {
274
+ try {
275
+ const withExt = candidateBase + ext;
276
+ const st = fs.statSync(withExt);
277
+ if (st.isFile())
278
+ return withExt;
279
+ }
280
+ catch { }
281
+ }
282
+ // Try as directory with index file
283
+ try {
284
+ const idxTs = path.join(candidateBase, 'index.ts');
285
+ if (fs.statSync(idxTs).isFile())
286
+ return idxTs;
287
+ }
288
+ catch { }
289
+ try {
290
+ const idxTsx = path.join(candidateBase, 'index.tsx');
291
+ if (fs.statSync(idxTsx).isFile())
292
+ return idxTsx;
293
+ }
294
+ catch { }
295
+ }
296
+ break; // First matching alias pattern wins
297
+ }
298
+ }
299
+ // ── 2. NodeNext .js → .ts mapping ──
300
+ if (moduleSpecifier.startsWith('.')) {
301
+ const sourceDir = path.dirname(sourceFilePath);
302
+ // Try the specifier as-is first (extensionless or explicit)
303
+ for (const suffix of ['', '.ts', '.tsx', '.d.ts']) {
304
+ try {
305
+ const candidate = path.resolve(sourceDir, moduleSpecifier + suffix);
306
+ if (fs.statSync(candidate).isFile())
307
+ return candidate;
308
+ }
309
+ catch { }
310
+ }
311
+ // NodeNext style: "./foo.js" → "./foo.ts"
312
+ if (moduleSpecifier.endsWith('.js') || moduleSpecifier.endsWith('.jsx')) {
313
+ const stripped = moduleSpecifier.replace(/\.jsx?$/, '');
314
+ for (const suffix of ['.ts', '.tsx', '.d.ts']) {
315
+ try {
316
+ const candidate = path.resolve(sourceDir, stripped + suffix);
317
+ if (fs.statSync(candidate).isFile())
318
+ return candidate;
319
+ }
320
+ catch { }
321
+ }
322
+ }
323
+ // Try as directory with index file
324
+ try {
325
+ const idxTs = path.resolve(sourceDir, moduleSpecifier, 'index.ts');
326
+ if (fs.existsSync(idxTs))
327
+ return idxTs;
328
+ }
329
+ catch { }
330
+ try {
331
+ const idxTsx = path.resolve(sourceDir, moduleSpecifier, 'index.tsx');
332
+ if (fs.existsSync(idxTsx))
333
+ return idxTsx;
334
+ }
335
+ catch { }
336
+ }
337
+ return null;
338
+ }
195
339
  function extractDirectCalls(func) {
196
340
  const body = func.getBody();
197
341
  if (!body)
@@ -222,13 +366,69 @@ function extractIR(projectRoot) {
222
366
  /** Extract both functions and type→file mapping. */
223
367
  /** @requires PROJECT_PATH @produces IR_WITH_TYPES */
224
368
  /** @requires PROJECT_PATH @produces IR_WITH_TYPES */
225
- function extractIRWithTypes(projectRoot) {
369
+ function extractIRWithTypes(projectRoot, _visited = new Set()) {
226
370
  const absRoot = path.resolve(projectRoot);
371
+ const tsconfigPath = path.join(absRoot, "tsconfig.json");
372
+ // Prevent infinite recursion for circular project references
373
+ if (_visited.has(absRoot)) {
374
+ return { functions: [], typeMap: {} };
375
+ }
376
+ _visited.add(absRoot);
377
+ // ── P0: Monorepo / project references detection ──
378
+ let references = [];
379
+ if (fs.existsSync(tsconfigPath)) {
380
+ try {
381
+ const tsconfigRaw = JSON.parse(fs.readFileSync(tsconfigPath, "utf-8"));
382
+ if (tsconfigRaw.references && Array.isArray(tsconfigRaw.references)) {
383
+ references = tsconfigRaw.references
384
+ .map((ref) => ref.path ? path.resolve(absRoot, ref.path) : null)
385
+ .filter((p) => p !== null && fs.existsSync(path.join(p, "tsconfig.json")));
386
+ }
387
+ }
388
+ catch { /* invalid tsconfig JSON */ }
389
+ }
390
+ if (references.length > 0) {
391
+ console.error(`🔧 检测到 monorepo: ${references.length} 个子项目`);
392
+ const allFunctions = [];
393
+ const allTypeMap = {};
394
+ // Only extract from referenced sub-projects — root tsconfig is just a container
395
+ for (const refDir of references) {
396
+ const childResult = extractIRWithTypes(refDir, _visited);
397
+ // Adjust file paths to be relative to the root project
398
+ for (const f of childResult.functions) {
399
+ const absolutePath = path.resolve(refDir, f.file);
400
+ f.file = path.relative(absRoot, absolutePath);
401
+ }
402
+ allFunctions.push(...childResult.functions);
403
+ Object.assign(allTypeMap, childResult.typeMap);
404
+ }
405
+ return { functions: allFunctions, typeMap: allTypeMap };
406
+ }
407
+ return _extractSingleProject(absRoot, tsconfigPath);
408
+ }
409
+ /** Extract IR from a single project (no references handling). */
410
+ function _extractSingleProject(absRoot, tsconfigPath) {
411
+ // ── P0: Read original tsconfig (with extends chain) for paths/baseUrl ──
412
+ const originalTsConfig = fs.existsSync(tsconfigPath)
413
+ ? readOriginalTsConfig(tsconfigPath)
414
+ : null;
415
+ if (originalTsConfig?.paths) {
416
+ console.error(`🔧 检测到路径别名: ${Object.keys(originalTsConfig.paths).join(', ')}`);
417
+ }
418
+ const modRes = (originalTsConfig?.moduleResolution || '').toLowerCase();
419
+ if (modRes === 'nodenext' || modRes === 'node16') {
420
+ console.error(`🔧 检测到 ${modRes} — 启用 .js→.ts 映射`);
421
+ }
227
422
  const project = new ts_morph_1.Project({
228
- tsConfigFilePath: path.join(absRoot, "tsconfig.json"),
423
+ tsConfigFilePath: tsconfigPath,
229
424
  skipAddingFilesFromTsConfig: false,
425
+ skipFileDependencyResolution: true, // compatible with NodeNext/ESM tsconfigs
426
+ compilerOptions: {
427
+ module: 1, // CommonJS — overrides project tsconfig for extraction
428
+ moduleResolution: 2, // Classic Node resolution
429
+ },
230
430
  });
231
- if (!fs.existsSync(path.join(absRoot, "tsconfig.json"))) {
431
+ if (!fs.existsSync(tsconfigPath)) {
232
432
  project.addSourceFilesAtPaths(path.join(absRoot, "**/*.ts"));
233
433
  }
234
434
  const funcs = [];
@@ -369,8 +569,23 @@ function extractIRWithTypes(projectRoot) {
369
569
  continue;
370
570
  }
371
571
  }
572
+ // ── P0 fallback: manual resolution for bundler aliases & NodeNext .js→.ts ──
573
+ const manualPath = manualResolveModule(mod, sf.getFilePath(), absRoot, originalTsConfig);
574
+ if (manualPath) {
575
+ try {
576
+ const manualFile = project.addSourceFileAtPathIfExists(manualPath);
577
+ if (manualFile) {
578
+ const sig = extractSignatureFromFile(name, manualFile);
579
+ if (sig) {
580
+ externalFuncs.set(name, sig);
581
+ continue;
582
+ }
583
+ }
584
+ }
585
+ catch { /* manual file may be a directory or invalid */ }
586
+ }
372
587
  }
373
- catch { }
588
+ catch { /* IR parse fallback */ }
374
589
  }
375
590
  // Namespace imports: import * as X from 'mod'
376
591
  const nsImport = imp.getNamespaceImport();
@@ -389,17 +604,29 @@ function extractIRWithTypes(projectRoot) {
389
604
  namespaceImports.set(nsImport.getText(), dtsFile);
390
605
  }
391
606
  else {
392
- // Node.js built-in: try @types/node
393
- const nodeTypesPath = path.join(absRoot, "node_modules/@types/node", mod + ".d.ts");
394
- if (fs.existsSync(nodeTypesPath)) {
395
- const nodeDts = project.addSourceFileAtPathIfExists(nodeTypesPath);
396
- if (nodeDts)
397
- namespaceImports.set(nsImport.getText(), nodeDts);
607
+ // ── P0 fallback: manual resolution for namespace imports ──
608
+ const manualPath = manualResolveModule(mod, sf.getFilePath(), absRoot, originalTsConfig);
609
+ if (manualPath) {
610
+ try {
611
+ const manualFile = project.addSourceFileAtPathIfExists(manualPath);
612
+ if (manualFile)
613
+ namespaceImports.set(nsImport.getText(), manualFile);
614
+ }
615
+ catch { /* manual file may be a directory */ }
616
+ }
617
+ else {
618
+ // Node.js built-in: try @types/node
619
+ const nodeTypesPath = path.join(absRoot, "node_modules/@types/node", mod + ".d.ts");
620
+ if (fs.existsSync(nodeTypesPath)) {
621
+ const nodeDts = project.addSourceFileAtPathIfExists(nodeTypesPath);
622
+ if (nodeDts)
623
+ namespaceImports.set(nsImport.getText(), nodeDts);
624
+ }
398
625
  }
399
626
  }
400
627
  }
401
628
  }
402
- catch { }
629
+ catch { /* IR parse fallback */ }
403
630
  }
404
631
  }
405
632
  }
@@ -418,7 +645,7 @@ function extractIRWithTypes(projectRoot) {
418
645
  // Collect undeclared calls (functions used but not declared and not resolved above)
419
646
  const allCalls = new Set();
420
647
  for (const f of funcs) {
421
- for (const c of f.calls) {
648
+ for (const c of (f.calls || [])) {
422
649
  allCalls.add(c);
423
650
  }
424
651
  }
@@ -601,6 +828,40 @@ function extractIRWithTypes(projectRoot) {
601
828
  break;
602
829
  }
603
830
  }
831
+ // ── P0 fallback: try manual resolution for named-import-style unknown calls ──
832
+ // Some imports may not have been resolved as named imports in ts-morph
833
+ // (e.g., when the import declaration itself wasn't parsed correctly)
834
+ if (!externalFuncs.has(callName) && !knownExternals[callName]) {
835
+ // Scan all source file imports again with manual resolution
836
+ for (const sf of project.getSourceFiles()) {
837
+ if (sf.getFilePath().includes('node_modules'))
838
+ continue;
839
+ for (const imp of sf.getImportDeclarations()) {
840
+ const mod = imp.getModuleSpecifierValue();
841
+ const manualPath = manualResolveModule(mod, sf.getFilePath(), absRoot, originalTsConfig);
842
+ if (!manualPath)
843
+ continue;
844
+ // Check if this module exports the callName
845
+ let manualFile;
846
+ try {
847
+ manualFile = project.addSourceFileAtPathIfExists(manualPath);
848
+ }
849
+ catch {
850
+ continue;
851
+ }
852
+ if (!manualFile)
853
+ continue;
854
+ const sig = extractSignatureFromFile(callName, manualFile);
855
+ if (sig) {
856
+ externalFuncs.set(callName, sig);
857
+ dynamicCount++;
858
+ break;
859
+ }
860
+ }
861
+ if (externalFuncs.has(callName))
862
+ break;
863
+ }
864
+ }
604
865
  // Priority: dynamic resolution > knownExternals fallback > any
605
866
  const dynamic = externalFuncs.get(callName);
606
867
  const fallback = knownExternals[callName];
@@ -670,6 +931,109 @@ function extractIRWithTypes(projectRoot) {
670
931
  _typeMap[_n] = _rp;
671
932
  }
672
933
  }
934
+ // ── Post-process: auto-derive missing capability metadata ──
935
+ // Name-based data-flow inference patterns
936
+ const PRODUCER_PREFIXES = [
937
+ [/^(load|get|fetch|read|find|list|query|select)/i, "DATA"],
938
+ [/^(create|build|generate|make|new)/i, "CREATED"],
939
+ [/^(validate|verify|check|assert)/i, "VALIDATION_RESULT"],
940
+ [/^(format|render|emit|stringify)/i, "FORMATTED"],
941
+ [/^(save|write|persist|store|put)/i, "SAVED"],
942
+ [/^(count|compute|calculate|measure)/i, "RESULT"],
943
+ [/^(extract|parse|scan)/i, "EXTRACTED"],
944
+ [/^(execute|run|invoke|apply)/i, "EXECUTED"],
945
+ [/^(delete|remove|clear|destroy)/i, "DELETED"],
946
+ ];
947
+ const CONSUMER_PREFIXES = [
948
+ [/^(save|write|persist|store)/i, "DATA"],
949
+ [/^(validate|verify|check|assert)/i, "DATA"],
950
+ [/^(format|render|emit|display)/i, "DATA"],
951
+ [/^(delete|remove|clear)/i, "DATA"],
952
+ [/^(execute|run|apply)/i, "CONFIG"],
953
+ [/^(search|query|filter|sort)/i, "DATA"],
954
+ [/^(merge|combine|concat)/i, "DATA"],
955
+ [/^(compare|diff|match)/i, "DATA"],
956
+ [/^(hash|encode|encrypt|sign)/i, "INPUT"],
957
+ ];
958
+ for (const f of funcs) {
959
+ // Strategy 1: @protocol pre_states → @requires, post_states → @produces
960
+ if (f.protocol) {
961
+ if ((!f.requires || f.requires.length === 0) && f.protocol.pre_states?.length > 0) {
962
+ f.requires = f.protocol.pre_states;
963
+ }
964
+ if ((!f.produces || f.produces.length === 0) && f.protocol.post_states?.length > 0) {
965
+ f.produces = f.protocol.post_states;
966
+ }
967
+ }
968
+ // Strategy 2: Derive purpose from function name if missing
969
+ if (!f.purpose && f.name) {
970
+ f.purpose = f.name
971
+ .replace(/([A-Z])/g, " $1")
972
+ .replace(/_/g, " ")
973
+ .replace(/\s+/g, " ")
974
+ .trim()
975
+ .toLowerCase();
976
+ }
977
+ // Strategy 3: Derive tags from file path if missing
978
+ if (!f.tags || f.tags.length === 0) {
979
+ const parts = (f.file || "").replace(/\.ts$/, "").replace(/^src\//, "").split("/");
980
+ f.tags = parts.filter(t => t.length > 2 && t !== "src");
981
+ }
982
+ // Strategy 4: Infer requires/produces from function name prefix
983
+ // Mark as derived so Strategy 5 can skip these (name-derived labels are
984
+ // too generic for cross-function data-flow inheritance).
985
+ if (!f.requires || f.requires.length === 0) {
986
+ for (const [re, label] of CONSUMER_PREFIXES) {
987
+ if (re.test(f.name)) {
988
+ f.requires = [label];
989
+ f._requiresDerived = true;
990
+ break;
991
+ }
992
+ }
993
+ }
994
+ if (!f.produces || f.produces.length === 0) {
995
+ for (const [re, label] of PRODUCER_PREFIXES) {
996
+ if (re.test(f.name)) {
997
+ f.produces = [label];
998
+ f._producesDerived = true;
999
+ break;
1000
+ }
1001
+ }
1002
+ }
1003
+ }
1004
+ // Strategy 5: Cross-function data-flow — only inherit from callees
1005
+ // with BOTH explicit requires AND produces (true pipeline functions).
1006
+ // Single-hop only. Prevents noise: generateAttemptId→CREATED won't propagate.
1007
+ const nameToFunc = new Map();
1008
+ for (const f of funcs)
1009
+ nameToFunc.set(f.name, f);
1010
+ for (const f of funcs) {
1011
+ if ((f.requires || []).length > 0 && (f.produces || []).length > 0)
1012
+ continue; // already annotated
1013
+ if (!f.calls || f.calls.length === 0)
1014
+ continue;
1015
+ let inherited = 0;
1016
+ const MAX_INHERIT = 2; // cap edges per function
1017
+ for (const calleeName of f.calls) {
1018
+ if (inherited >= MAX_INHERIT)
1019
+ break;
1020
+ const callee = nameToFunc.get(calleeName);
1021
+ if (!callee)
1022
+ continue;
1023
+ // Require BOTH explicit requires AND produces — true pipeline node
1024
+ const hasExplicitR = callee.requires && callee.requires.length > 0 && !callee._requiresDerived;
1025
+ const hasExplicitP = callee.produces && callee.produces.length > 0 && !callee._producesDerived;
1026
+ if (!hasExplicitR || !hasExplicitP)
1027
+ continue;
1028
+ if (!f.requires || f.requires.length === 0) {
1029
+ f.requires = [...new Set(callee.requires)];
1030
+ inherited++;
1031
+ }
1032
+ if (!f.produces || f.produces.length === 0) {
1033
+ f.produces = [...new Set(callee.produces)];
1034
+ }
1035
+ }
1036
+ }
673
1037
  return { functions: funcs, typeMap: _typeMap };
674
1038
  }
675
1039
  // ═══════════════════════════════════════════════════════════════
@@ -98,7 +98,7 @@ function recordFailure(record) {
98
98
  fs.mkdirSync(CORPUS_DIR, { recursive: true });
99
99
  fs.writeFileSync(`${CORPUS_DIR}/${id}.json`, JSON.stringify(entry, null, 2), "utf-8");
100
100
  }
101
- catch { }
101
+ catch { /* collect best-effort */ }
102
102
  return id;
103
103
  }
104
104
  /** Load all recorded failures. */
@@ -116,7 +116,7 @@ function loadFailures() {
116
116
  try {
117
117
  failures.push(JSON.parse(fs.readFileSync(`${CORPUS_DIR}/${f}`, "utf-8")));
118
118
  }
119
- catch { }
119
+ catch { /* collect best-effort */ }
120
120
  }
121
121
  return failures.sort((a, b) => b.timestamp - a.timestamp);
122
122
  }