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.
- package/README.md +108 -468
- package/dist/ablation-study.js +144 -0
- package/dist/ablation-study.test.js +18 -0
- package/dist/action-runtime.js +3 -1
- package/dist/active-learning.js +211 -0
- package/dist/analytics.js +139 -0
- package/dist/asset-factory.js +309 -0
- package/dist/asset-growth.js +244 -0
- package/dist/asset-promotion.js +382 -0
- package/dist/asset-quality.js +550 -0
- package/dist/audit/business-translator.js +285 -0
- package/dist/audit/cli.js +66 -0
- package/dist/audit/formatters/html.js +379 -0
- package/dist/audit/formatters/json.js +11 -0
- package/dist/audit/formatters/markdown.js +192 -0
- package/dist/audit/formatters/terminal.js +189 -0
- package/dist/audit/index.js +25 -0
- package/dist/audit/report-builder.js +318 -0
- package/dist/audit/types.js +8 -0
- package/dist/audit.js +3 -3
- package/dist/auto-benchmark-generator.js +137 -0
- package/dist/auto-benchmark-generator.test.js +45 -0
- package/dist/auto-protocol-synthesizer.js +362 -0
- package/dist/auto-protocol-synthesizer.test.js +82 -0
- package/dist/autonomous-patch.js +175 -0
- package/dist/autonomous-patch.test.js +128 -0
- package/dist/badge/badge-server.js +98 -0
- package/dist/behavior-miner.js +442 -0
- package/dist/belief-layer.js +475 -0
- package/dist/benchmark-count.js +5 -0
- package/dist/benchmark-generator.js +211 -0
- package/dist/benchmark-harness.js +201 -0
- package/dist/benchmark-pass-rate.js +7 -0
- package/dist/benchmark-report.js +8 -3
- package/dist/benchmark-save.js +14 -1
- package/dist/bootstrap-validation.js +197 -0
- package/dist/bootstrap-validation.test.js +51 -0
- package/dist/branch-ledger.js +1 -1
- package/dist/capability-gap.js +130 -0
- package/dist/certify-html.js +351 -0
- package/dist/certify.js +326 -0
- package/dist/check.js +4 -4
- package/dist/compliance-miner.js +447 -0
- package/dist/continuous-benchmark.js +194 -0
- package/dist/continuous-benchmark.test.js +116 -0
- package/dist/corpus-stats.js +173 -0
- package/dist/counterfactual-engine.js +288 -0
- package/dist/coverage-dashboard.js +109 -0
- package/dist/coverage-system.test.js +205 -0
- package/dist/cross-repo-precision.js +352 -0
- package/dist/cve-benchmark.js +180 -0
- package/dist/cve-benchmark.test.js +28 -0
- package/dist/cve-collector.js +73 -0
- package/dist/data-quality.js +141 -0
- package/dist/decision-engine.js +388 -0
- package/dist/derive-metadata.js +250 -0
- package/dist/difficulty-active.test.js +198 -0
- package/dist/difficulty-map.js +244 -0
- package/dist/discovery-analytics.js +125 -0
- package/dist/discovery-model.js +149 -0
- package/dist/discovery-optimize.test.js +199 -0
- package/dist/discovery-trace.js +276 -0
- package/dist/discovery-trace.test.js +97 -0
- package/dist/emitter.js +83 -1
- package/dist/enterprise-dashboard.js +405 -0
- package/dist/eval-hardening.js +297 -0
- package/dist/eval-hardening.test.js +85 -0
- package/dist/evaluation-campaign.js +359 -0
- package/dist/evaluation-campaign.test.js +181 -0
- package/dist/evidence-growth.js +143 -0
- package/dist/evidence-repository.js +209 -0
- package/dist/evidence-system.js +441 -0
- package/dist/execute.js +15 -7
- package/dist/experimental/software-physics.js +291 -0
- package/dist/experimental/state-inference.js +516 -0
- package/dist/experimental/unsupervised-physics.js +230 -0
- package/dist/extract-ir-python.js +54 -7
- package/dist/extract-ir.js +376 -12
- package/dist/failure-collector.js +2 -2
- package/dist/failure-corpus.js +322 -9
- package/dist/feedback.js +16 -5
- package/dist/feedback.test.js +49 -0
- package/dist/file-lock.js +1 -1
- package/dist/flywheel-batch.js +292 -0
- package/dist/frameworks/express-cli.js +237 -0
- package/dist/frameworks/express-detector.js +445 -0
- package/dist/frameworks/express-detector.test.js +206 -0
- package/dist/frameworks/index.js +30 -0
- package/dist/frameworks/nestjs-detector.js +302 -0
- package/dist/frameworks/trpc-detector.js +161 -0
- package/dist/frameworks/version-awareness.js +179 -0
- package/dist/function-synonyms.js +164 -0
- package/dist/function-synonyms.test.js +68 -0
- package/dist/generalization.test.js +352 -0
- package/dist/goal-annotator.js +113 -0
- package/dist/goal-planner.js +563 -0
- package/dist/gold-cve.js +164 -0
- package/dist/gold-cve.test.js +104 -0
- package/dist/gold-quality.js +206 -0
- package/dist/gold-tiers.js +241 -0
- package/dist/governance-dashboard.js +327 -0
- package/dist/graph-viz.js +240 -0
- package/dist/guided-frontier.js +195 -0
- package/dist/hierarchical-planner.js +148 -0
- package/dist/identifier-parser.js +260 -0
- package/dist/immune-metrics.js +93 -0
- package/dist/immune-receiver.js +158 -0
- package/dist/immune-reporter.js +1 -1
- package/dist/improvement-orchestrator.js +206 -0
- package/dist/inject-p0-vocabulary.js +300 -0
- package/dist/intent-parser.js +218 -0
- package/dist/invariant-algebra.js +476 -0
- package/dist/invariant-calculus.js +533 -0
- package/dist/ir-utils.js +70 -0
- package/dist/ir-utils.test.js +50 -0
- package/dist/knowledge-api.js +312 -0
- package/dist/knowledge-evolution.js +452 -0
- package/dist/knowledge-explorer.js +506 -0
- package/dist/knowledge-flywheel.js +274 -0
- package/dist/knowledge-governance.js +338 -0
- package/dist/knowledge-governance.test.js +150 -0
- package/dist/knowledge-graph.js +181 -0
- package/dist/knowledge-guided-synth.js +246 -0
- package/dist/knowledge-loop.test.js +77 -0
- package/dist/knowledge-object.js +316 -0
- package/dist/knowledge-package.js +98 -0
- package/dist/kpi-dashboard.js +561 -0
- package/dist/l3-cross-function.js +280 -0
- package/dist/learning-ranker.js +148 -0
- package/dist/learning-ranker.test.js +291 -0
- package/dist/ledger/accountability.js +322 -0
- package/dist/ledger/chain-builder.js +185 -0
- package/dist/ledger/cli.js +222 -0
- package/dist/ledger/index.js +13 -0
- package/dist/ledger/signatures.js +193 -0
- package/dist/ledger/types.js +9 -0
- package/dist/llm.js +74 -3
- package/dist/load-benchmarks.js +8 -3
- package/dist/logger.js +66 -0
- package/dist/logger.test.js +37 -0
- package/dist/logistic-reward.js +339 -0
- package/dist/logistic-reward.test.js +180 -0
- package/dist/macro-graph.js +193 -0
- package/dist/macro-repair.js +183 -0
- package/dist/mcp-server.mjs +1202 -483
- package/dist/memory-layer.js +42 -5
- package/dist/multi-repo-precision.js +422 -0
- package/dist/name-free-protocol.js +425 -0
- package/dist/name-free-protocol.test.js +170 -0
- package/dist/name-scrambling.js +138 -0
- package/dist/name-scrambling.test.js +16 -0
- package/dist/p3-observability.test.js +281 -0
- package/dist/p5-orchestrator.test.js +225 -0
- package/dist/pairwise-preference.js +294 -0
- package/dist/pairwise-preference.test.js +140 -0
- package/dist/planner-constraints.js +104 -0
- package/dist/planner-prompts.js +155 -0
- package/dist/planner-telemetry.js +415 -0
- package/dist/planner-trace.js +214 -0
- package/dist/planner.js +162 -167
- package/dist/plsb/artifact.js +116 -0
- package/dist/plsb/cli.js +71 -0
- package/dist/plsb/index.js +19 -0
- package/dist/plsb/leaderboard.js +249 -0
- package/dist/plsb/report-md.js +156 -0
- package/dist/plsb/schema.js +179 -0
- package/dist/plsb-benchmark.js +284 -0
- package/dist/plsb-benchmark.test.js +119 -0
- package/dist/policy/cli.js +134 -0
- package/dist/policy/engine.js +333 -0
- package/dist/policy/index.js +12 -0
- package/dist/policy/types.js +59 -0
- package/dist/policy-miner.js +505 -0
- package/dist/precision-analyze.js +229 -0
- package/dist/precision-benchmark.js +147 -0
- package/dist/precision-label-c.js +134 -0
- package/dist/precision-label.js +193 -0
- package/dist/precision-report-c.js +149 -0
- package/dist/precision-report.js +246 -0
- package/dist/progmune-status.js +108 -0
- package/dist/proof-engine.js +479 -0
- package/dist/proof-provenance.js +315 -0
- package/dist/protocol-coverage.js +294 -0
- package/dist/protocol-detector.js +1189 -0
- package/dist/protocol-embedding-expanded.js +297 -0
- package/dist/protocol-embedding-expanded.test.js +97 -0
- package/dist/protocol-embedding.js +195 -0
- package/dist/protocol-embedding.test.js +82 -0
- package/dist/protocol-extractor-v2.js +354 -0
- package/dist/protocol-extractor-v2.test.js +140 -0
- package/dist/protocol-extractor.js +310 -0
- package/dist/protocol-extractor.test.js +113 -0
- package/dist/protocol-foundation.js +322 -0
- package/dist/protocol-foundation.test.js +163 -0
- package/dist/protocol-frontier.js +243 -0
- package/dist/protocol-frontier.test.js +92 -0
- package/dist/protocol-gap-analyzer.js +228 -0
- package/dist/protocol-gap-analyzer.test.js +49 -0
- package/dist/protocol-invariants.js +276 -0
- package/dist/protocol-invariants.test.js +111 -0
- package/dist/protocol-knowledge.js +464 -0
- package/dist/protocol-miner.js +343 -0
- package/dist/protocol-mining.js +207 -0
- package/dist/protocol-mining.test.js +37 -0
- package/dist/protocol-registry.js +1 -1
- package/dist/protocol-security-benchmark.js +222 -0
- package/dist/protocol-vulnerability.js +257 -0
- package/dist/protocol-vulnerability.test.js +60 -0
- package/dist/python-benchmark.js +120 -0
- package/dist/python-emitter.js +163 -45
- package/dist/python-protocol-extractor.js +187 -0
- package/dist/python-protocol-extractor.test.js +116 -0
- package/dist/realworld-benchmark.js +646 -0
- package/dist/realworld-benchmark.test.js +36 -0
- package/dist/repair-arch.test.js +411 -0
- package/dist/repair-evolution.test.js +454 -0
- package/dist/repair-executor.js +719 -0
- package/dist/repair-proposal.js +4 -4
- package/dist/repair-ranker.js +141 -0
- package/dist/repair-strategies.js +419 -0
- package/dist/repair-taxonomy.js +234 -0
- package/dist/repair-types.js +12 -0
- package/dist/repo-evaluator.js +250 -0
- package/dist/repo-evaluator.test.js +128 -0
- package/dist/resource-abstraction.js +242 -0
- package/dist/resource-detector.js +211 -0
- package/dist/result.test.js +43 -0
- package/dist/reward-system.js +411 -0
- package/dist/reward-system.test.js +175 -0
- package/dist/risk-model.js +215 -0
- package/dist/rule-miner.js +234 -7
- package/dist/rule-specificity.js +254 -0
- package/dist/runtime-types.js +27 -0
- package/dist/scaffold.js +208 -0
- package/dist/scale-collector.test.js +101 -0
- package/dist/scale-trajectory-collector.js +128 -0
- package/dist/sdk.js +250 -0
- package/dist/search-planner.js +4 -41
- package/dist/semantic-snapshot.js +1 -1
- package/dist/semantic-topology.js +121 -0
- package/dist/semantic-trace.js +310 -317
- package/dist/sequence-extractor.js +343 -0
- package/dist/skill-library.js +245 -0
- package/dist/skill-planner.test.js +189 -0
- package/dist/software-physics.js +291 -0
- package/dist/software-physics.test.js +81 -0
- package/dist/ssg-precision.js +478 -0
- package/dist/ssg-validator.js +71 -21
- package/dist/state-inference-doubleblind.test.js +160 -0
- package/dist/state-inference.js +516 -0
- package/dist/state-inference.test.js +115 -0
- package/dist/state-machine-fingerprint.js +345 -0
- package/dist/state-machine-fingerprint.test.js +120 -0
- package/dist/state-miner.js +386 -0
- package/dist/state-name-inference.js +213 -0
- package/dist/state-name-inference.test.js +69 -0
- package/dist/strategy-planner.js +262 -96
- package/dist/strategy-planner.test.js +135 -0
- package/dist/telemetry-analytics.test.js +402 -0
- package/dist/terminal-format.js +68 -0
- package/dist/terminal-format.test.js +83 -0
- package/dist/topology-factory.js +196 -0
- package/dist/topology-representation.js +242 -0
- package/dist/topology-representation.test.js +27 -0
- package/dist/trajectory-augmentation.js +254 -0
- package/dist/trajectory-augmentation.test.js +63 -0
- package/dist/trajectory-corpus.js +440 -0
- package/dist/trajectory-corpus.test.js +32 -0
- package/dist/trajectory-feedback.test.js +116 -0
- package/dist/transition-synthesizer.js +286 -0
- package/dist/transition-synthesizer.test.js +123 -0
- package/dist/trust/api-semantic-mapper.js +809 -0
- package/dist/trust/call-graph-propagator.js +225 -0
- package/dist/trust/cli.js +122 -0
- package/dist/trust/compliance-scorer.js +283 -0
- package/dist/trust/confidence-calculator.js +261 -0
- package/dist/trust/engine.js +1145 -0
- package/dist/trust/explainability.js +85 -0
- package/dist/trust/formatters/ci.js +42 -0
- package/dist/trust/formatters/json.js +11 -0
- package/dist/trust/formatters/terminal.js +152 -0
- package/dist/trust/index.js +39 -0
- package/dist/trust/phase1-verify.js +171 -0
- package/dist/trust/protocol-domain-validator.js +697 -0
- package/dist/trust/score-calculator.js +282 -0
- package/dist/trust/ssg-bridge.js +641 -0
- package/dist/trust/ssg-bridge.test.js +269 -0
- package/dist/trust/types.js +67 -0
- package/dist/trust/violation-trace.js +335 -0
- package/dist/trust-api.js +179 -0
- package/dist/trust-calibration.js +279 -0
- package/dist/unknown-protocol-discovery.js +339 -0
- package/dist/unknown-protocol-discovery.test.js +102 -0
- package/dist/unsupervised-physics.js +230 -0
- package/dist/unsupervised-physics.test.js +95 -0
- package/dist/utils.test.js +37 -0
- package/dist/validator.js +187 -10
- package/dist/verification-intelligence.js +475 -0
- package/dist/verify-api.js +432 -0
- package/dist/vi-impact-report.js +293 -0
- package/dist/wl-fingerprint.js +162 -0
- package/dist/wl-fingerprint.test.js +130 -0
- package/dist/zeroshot-strategy.js +139 -0
- 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
- package/docs/Progmune_/351/241/271/347/233/256/345/205/250/350/247/243.html +710 -0
- package/package.json +74 -7
- package/protocols.json +1956 -50
- package/.dockerignore +0 -14
- package/.mcp.json +0 -11
- package/.progmune_allowlist +0 -50
- package/.test_report/test_report.md +0 -87
- package/Dockerfile +0 -9
- package/FAQ.md +0 -167
- package/WHITEPAPER.md +0 -540
- package/demo-project/auth.ts +0 -55
- package/demo-project/tsconfig.json +0 -8
- package/dist/acl-breakdown.js +0 -13
- package/dist/all-sessions.js +0 -11
- package/dist/antibody-stats.js +0 -11
- package/dist/branch-tree-count.js +0 -14
- package/dist/common-fixpath.js +0 -12
- package/dist/constraint-types.js +0 -12
- package/dist/exec-metrics.js +0 -11
- package/dist/failure-report.js +0 -11
- package/dist/fast-path-hits.js +0 -13
- package/dist/fingerprint-list.js +0 -15
- package/dist/gen-history-log.js +0 -13
- package/dist/heatmap-data.js +0 -11
- package/dist/recent-session.js +0 -12
- package/dist/svl-distribution.js +0 -11
- package/dist/terminal-status.js +0 -11
- package/dist/token-savings.js +0 -11
- package/dist/total-repairs.js +0 -12
- package/dist/unresolved-count.js +0 -12
- package/dist/valid-fingerprints.js +0 -13
- package/dist/verify-ledgers.js +0 -11
- package/docs/whitepaper-style.css +0 -77
- package/docs/whitepaper-v2.1.md +0 -609
- package/docs/whitepaper-v2.2.md +0 -1064
- package/docs/whitepaper-v2.2.pdf +0 -0
- package/fly.toml +0 -31
- package/public/dashboard.html +0 -119
- package/server/hub.js +0 -116
- package/test/replay-golden/sess_1780063202050_mgeld.json +0 -9
- package/test/replay-golden/sess_1780064032560_gocld.json +0 -354
- package/test/replay-golden/sess_1780064413331_s2709.json +0 -606
- package/test/replay-golden/sess_1780064792710_y3avo.json +0 -614
- package/test/replay-golden.ts +0 -84
- package/test_benchmark.js +0 -165
- package/test_comprehensive.mjs +0 -638
- package/test_concurrency.js +0 -129
- package/test_ir_robustness.js +0 -85
- package/test_semantic_contracts.js +0 -269
- package/test_ssg_stress.js +0 -156
- package/test_svl3.js +0 -58
- package/tsconfig.json +0 -17
package/dist/extract-ir.js
CHANGED
|
@@ -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:
|
|
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(
|
|
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
|
-
//
|
|
393
|
-
const
|
|
394
|
-
if (
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
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
|
}
|