progmune-runtime 2.1.6 → 3.2.1
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 +119 -461
- 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 +721 -0
- package/package.json +73 -6
- 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/planner.js
CHANGED
|
@@ -48,6 +48,7 @@ const protocol_registry_1 = require("./protocol-registry");
|
|
|
48
48
|
const semantic_snapshot_1 = require("./semantic-snapshot");
|
|
49
49
|
const strategy_planner_1 = require("./strategy-planner");
|
|
50
50
|
const semantic_topology_1 = require("./semantic-topology");
|
|
51
|
+
const planner_prompts_1 = require("./planner-prompts");
|
|
51
52
|
const fs = __importStar(require("fs"));
|
|
52
53
|
function enrichActions(actions, ir) {
|
|
53
54
|
return actions.map(a => {
|
|
@@ -93,98 +94,6 @@ function determineConstraintType(svl) {
|
|
|
93
94
|
case "SVL-4": return "protocol";
|
|
94
95
|
}
|
|
95
96
|
}
|
|
96
|
-
/** 构建紧凑函数列表 — 包含能力元数据帮助 LLM 理解函数语义 */
|
|
97
|
-
function buildCompactFuncList(funcs, allFuncs) {
|
|
98
|
-
// Known string enums with example values
|
|
99
|
-
const ENUM_DEFAULTS = {
|
|
100
|
-
"SVL": '"SVL-4"', "RootCause": '"F01"', "BranchReason": '"repair_attempt"',
|
|
101
|
-
"RepairStrategy": '"insert"', "ConstraintType": '"protocol"',
|
|
102
|
-
};
|
|
103
|
-
return funcs.map((f) => {
|
|
104
|
-
const params = (f.params || []).map((p) => {
|
|
105
|
-
const t = (p.type || "any").replace(/\[\]$/, "");
|
|
106
|
-
const def = ENUM_DEFAULTS[t];
|
|
107
|
-
return def ? `${p.name}: ${def}` : `${p.name}: ${p.type}`;
|
|
108
|
-
}).join(",");
|
|
109
|
-
let line = `${f.name}(${params})->${f.returnType || "any"}`;
|
|
110
|
-
// Add capability metadata + score
|
|
111
|
-
const meta = [];
|
|
112
|
-
if (f.score && f.score > 0)
|
|
113
|
-
meta.push(`★${f.score.toFixed(1)}`);
|
|
114
|
-
if (f.purpose)
|
|
115
|
-
meta.push(f.purpose.slice(0, 50));
|
|
116
|
-
if (f.produces && f.produces.length > 0)
|
|
117
|
-
meta.push(`→${f.produces.join(",")}`);
|
|
118
|
-
if (meta.length > 0)
|
|
119
|
-
line += ` // ${meta.join(" | ")}`;
|
|
120
|
-
return line;
|
|
121
|
-
}).join("\n");
|
|
122
|
-
}
|
|
123
|
-
/** Semantic matching: check if two capability labels are related.
|
|
124
|
-
* Uses SemanticTopology (structural graph) instead of string matching. */
|
|
125
|
-
function semanticMatch(a, b) {
|
|
126
|
-
try {
|
|
127
|
-
const topo = (0, semantic_topology_1.getTopology)();
|
|
128
|
-
if (topo.size > 0)
|
|
129
|
-
return topo.capabilityMatch(a, b);
|
|
130
|
-
}
|
|
131
|
-
catch { }
|
|
132
|
-
// Fallback: exact + substring
|
|
133
|
-
if (a === b)
|
|
134
|
-
return true;
|
|
135
|
-
if (a.includes(b) || b.includes(a))
|
|
136
|
-
return true;
|
|
137
|
-
return false;
|
|
138
|
-
}
|
|
139
|
-
/** Build capability chain hints from IR: producer→consumer relationships.
|
|
140
|
-
* Uses semantic matching for fuzzy capability linking. */
|
|
141
|
-
function buildChainHints(funcs) {
|
|
142
|
-
const chains = [];
|
|
143
|
-
const seen = new Set();
|
|
144
|
-
for (const f of funcs) {
|
|
145
|
-
if (!f.produces)
|
|
146
|
-
continue;
|
|
147
|
-
for (const p of f.produces) {
|
|
148
|
-
const consumers = funcs.filter((x) => x.name !== f.name &&
|
|
149
|
-
(x.requires || []).some((r) => semanticMatch(p, r)));
|
|
150
|
-
for (const c of consumers) {
|
|
151
|
-
const key = `${f.name}→${c.name}`;
|
|
152
|
-
if (seen.has(key))
|
|
153
|
-
continue;
|
|
154
|
-
seen.add(key);
|
|
155
|
-
const matchedReq = (c.requires || []).find((r) => semanticMatch(p, r));
|
|
156
|
-
chains.push(`${f.name}()→${c.name}() // ${p} ≈ ${matchedReq || "?"}`);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
if (chains.length === 0)
|
|
161
|
-
return "";
|
|
162
|
-
return "\n推荐调用链(先调生产者,用 $变量名 传给消费者):\n" + chains.map(c => ` ${c}`).join("\n");
|
|
163
|
-
}
|
|
164
|
-
const SYSTEM_PROMPT = `你是程序合成助手。只输出 JSON 数组,不输出解释。
|
|
165
|
-
|
|
166
|
-
格式:[{"f":"函数名","to":"变量名","a":[{"n":"参数名","t":"类型","v":值}]},{"r":"变量名"}]
|
|
167
|
-
|
|
168
|
-
规则:
|
|
169
|
-
- 函数名从可用列表中选择,优先选注释中 purpose 匹配需求的函数
|
|
170
|
-
- 0参数函数直接用 "a":[]:{"f":"getAllSessions","to":"s","a":[]}
|
|
171
|
-
- 参数值规则(重要!):
|
|
172
|
-
- 字符串: "v":""(空串)或 "v":"SVL-4"(已知枚举值)
|
|
173
|
-
- 数字: "v":0 或 "v":1
|
|
174
|
-
- 布尔: "v":false
|
|
175
|
-
- 对象/数组: "v":{} as Type
|
|
176
|
-
- 上一个函数返回值: "v":"$变量名"($前缀引用)
|
|
177
|
-
- 返回值: {"r":"变量名"} — 必须返回,不能只调用不返回
|
|
178
|
-
- 链式调用:看到推荐调用链时,用 $变量名 把生产者输出传给消费者
|
|
179
|
-
|
|
180
|
-
铁律:
|
|
181
|
-
- 函数签名中带引号的参数(如 "SVL-4")是字符串值,直接 v 中
|
|
182
|
-
- 字符串枚举(SVL等)用带引号的值,禁止 {} as Type
|
|
183
|
-
- 每个call的返回值用"to"命名变量,下一个call通过"$变量名"引用
|
|
184
|
-
- 最后一个action必须是{"r":"变量名"},不能以call结尾
|
|
185
|
-
- 如果你调了函数,必须return它的结果
|
|
186
|
-
- 只输出JSON`;
|
|
187
|
-
const RETRY_HINT = `输出格式:紧凑 JSON 数组 [{"f":"函数名","to":"变量名","a":[...]}]`;
|
|
188
97
|
/** 构建重试 prompt:精简但包含必要的 IR 语法提示 */
|
|
189
98
|
/** 解析 LLM 输出的紧凑 JSON 为 Action[]。
|
|
190
99
|
* 格式: [{"f":"fn","to":"var","a":[{"n":"p","t":"str","v":"x"}]}, {"r":"var"}, ...]
|
|
@@ -273,6 +182,15 @@ function correctFunctionNames(actions, ir) {
|
|
|
273
182
|
/** 参数签名预检:确保 call action 的参数数量与 IR 函数签名一致 */
|
|
274
183
|
function fixParameterCounts(actions, ir) {
|
|
275
184
|
const fixes = [];
|
|
185
|
+
// Find the most recent preceding call with assignTo for chain defaults
|
|
186
|
+
function findPrevVar(idx) {
|
|
187
|
+
for (let k = idx - 1; k >= 0; k--) {
|
|
188
|
+
const prev = actions[k];
|
|
189
|
+
if (prev.kind === "call" && prev.assignTo)
|
|
190
|
+
return prev.assignTo;
|
|
191
|
+
}
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
276
194
|
const corrected = actions.map((a, i) => {
|
|
277
195
|
if (a.kind !== "call" || !a.function)
|
|
278
196
|
return a;
|
|
@@ -284,16 +202,17 @@ function fixParameterCounts(actions, ir) {
|
|
|
284
202
|
if (actual === expected)
|
|
285
203
|
return a;
|
|
286
204
|
if (actual < expected) {
|
|
287
|
-
// 参数太少:填充缺失参数
|
|
288
205
|
const padded = [...(a.args || [])];
|
|
206
|
+
const prevVar = findPrevVar(i);
|
|
289
207
|
for (let j = actual; j < expected; j++) {
|
|
290
|
-
|
|
208
|
+
// Smart default: chain from previous call if available
|
|
209
|
+
const defaultValue = prevVar ? `$${prevVar}` : "";
|
|
210
|
+
padded.push({ name: def.params[j].name, type: def.params[j].type || "any", value: defaultValue });
|
|
291
211
|
}
|
|
292
|
-
fixes.push(`action[${i}] ${a.function}: 参数 ${actual}→${expected} (填充 ${expected - actual}
|
|
212
|
+
fixes.push(`action[${i}] ${a.function}: 参数 ${actual}→${expected} (填充 ${expected - actual} 个缺失参数${prevVar ? ", 链自 $" + prevVar : ""})`);
|
|
293
213
|
return { ...a, args: padded };
|
|
294
214
|
}
|
|
295
215
|
else {
|
|
296
|
-
// 参数太多:截断多余参数
|
|
297
216
|
fixes.push(`action[${i}] ${a.function}: 参数 ${actual}→${expected} (截断 ${actual - expected} 个多余参数)`);
|
|
298
217
|
return { ...a, args: a.args.slice(0, expected) };
|
|
299
218
|
}
|
|
@@ -301,30 +220,6 @@ function fixParameterCounts(actions, ir) {
|
|
|
301
220
|
return { actions: corrected, fixes };
|
|
302
221
|
}
|
|
303
222
|
/** 构建协议链提示:为 LLM 显示协议状态机的合法调用顺序 */
|
|
304
|
-
function buildProtocolChainHint(protocols) {
|
|
305
|
-
if (protocols.length === 0)
|
|
306
|
-
return "";
|
|
307
|
-
// 按命名空间分组
|
|
308
|
-
const byNs = new Map();
|
|
309
|
-
for (const p of protocols) {
|
|
310
|
-
const ns = p.protocol.namespace || "_global";
|
|
311
|
-
if (!byNs.has(ns))
|
|
312
|
-
byNs.set(ns, []);
|
|
313
|
-
byNs.get(ns).push(p);
|
|
314
|
-
}
|
|
315
|
-
const lines = ["\n⚠️ 协议约束(必须严格遵循调用顺序):"];
|
|
316
|
-
for (const [ns, fns] of byNs) {
|
|
317
|
-
if (ns === "_global" || fns.length <= 1)
|
|
318
|
-
continue;
|
|
319
|
-
lines.push(` [${ns}] 合法调用链: ${fns.map(p => p.function).join(" → ")}`);
|
|
320
|
-
for (const p of fns) {
|
|
321
|
-
const pre = p.protocol.pre_states?.join(",") || "(无)";
|
|
322
|
-
const post = p.protocol.post_states?.join(",") || "(无)";
|
|
323
|
-
lines.push(` ${p.function}: 前置状态=[${pre}] → 后置状态=[${post}]`);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
return lines.join("\n");
|
|
327
|
-
}
|
|
328
223
|
/** JSON schema pre-validation: structural checks before IR-aware validation.
|
|
329
224
|
* Catches malformed actions that parseActionJSON() accepted but are semantically invalid. */
|
|
330
225
|
function validateActionSchema(actions) {
|
|
@@ -451,7 +346,7 @@ function loadProtocols(ir) {
|
|
|
451
346
|
const protoDef = JSON.parse(fs.readFileSync("protocols.json", "utf-8"));
|
|
452
347
|
jsonProtocols = (0, ssg_validator_1.parseProtocolsFromJSON)(protoDef);
|
|
453
348
|
}
|
|
454
|
-
catch { }
|
|
349
|
+
catch { /* topology rebuild — optional */ }
|
|
455
350
|
// Merge: IR @protocol takes priority, but inherits JSON namespace
|
|
456
351
|
const merged = new Map();
|
|
457
352
|
for (const p of jsonProtocols)
|
|
@@ -551,7 +446,7 @@ function attemptSSGRepair(actions, rejection, ir, protocols, namespaceInitialSta
|
|
|
551
446
|
return null;
|
|
552
447
|
}
|
|
553
448
|
/** @requires INTENT @produces ACTION_PLAN */
|
|
554
|
-
async function plan(userIntent) {
|
|
449
|
+
async function plan(userIntent, llmSeeds) {
|
|
555
450
|
(0, llm_1.resetCallCount)();
|
|
556
451
|
const irRaw = JSON.parse(fs.readFileSync("ir.json", "utf-8"));
|
|
557
452
|
// Support both old (array) and new ({typeMap, functions}) formats
|
|
@@ -560,13 +455,14 @@ async function plan(userIntent) {
|
|
|
560
455
|
try {
|
|
561
456
|
(0, semantic_topology_1.rebuildTopology)(ir);
|
|
562
457
|
}
|
|
563
|
-
catch { }
|
|
458
|
+
catch { /* topology rebuild — optional */ }
|
|
564
459
|
// Helper: wrap actions into PlanResult
|
|
565
460
|
let repairMetrics = { applied: false, count: 0, branchIds: [] };
|
|
566
|
-
const wrapResult = (actions, repair) => ({
|
|
461
|
+
const wrapResult = (actions, repair, degraded = false) => ({
|
|
567
462
|
actions,
|
|
568
463
|
sessionId: session?.sessionId || "",
|
|
569
464
|
ruleHash: session?.ruleHash,
|
|
465
|
+
degraded,
|
|
570
466
|
repairApplied: repair?.applied ?? repairMetrics.applied,
|
|
571
467
|
repairCount: repair?.count ?? repairMetrics.count,
|
|
572
468
|
repairBranchIds: repair?.branchIds ?? repairMetrics.branchIds,
|
|
@@ -591,15 +487,45 @@ async function plan(userIntent) {
|
|
|
591
487
|
}
|
|
592
488
|
// 提前加载协议(后续多处使用)
|
|
593
489
|
const { protocols, namespaceInitialStates } = loadProtocols(ir);
|
|
594
|
-
//
|
|
595
|
-
const
|
|
490
|
+
// ── Auto Router: repo-specific tasks → Graph ON, generic tasks → OFF ──
|
|
491
|
+
const explicitMode = process.env.PROGMUNE_GRAPH_MODE;
|
|
492
|
+
let graphMode = explicitMode || "off"; // default OFF
|
|
493
|
+
if (!explicitMode) {
|
|
494
|
+
// Extract repo-specific terms from IR
|
|
495
|
+
const repoNames = new Set();
|
|
496
|
+
for (const f of ir) {
|
|
497
|
+
for (const word of f.name.replace(/([A-Z])/g, " $1").toLowerCase().split(/[\s_]+/))
|
|
498
|
+
if (word.length > 3)
|
|
499
|
+
repoNames.add(word);
|
|
500
|
+
for (const tag of (f.tags || []))
|
|
501
|
+
repoNames.add(tag.toLowerCase());
|
|
502
|
+
}
|
|
503
|
+
const stopWords = new Set(["this", "that", "with", "from", "have", "been", "their", "will", "would", "could", "should", "about", "which", "there"]);
|
|
504
|
+
for (const w of stopWords)
|
|
505
|
+
repoNames.delete(w);
|
|
506
|
+
// Split intent words the same way as function names: split on whitespace + camelCase
|
|
507
|
+
const intentWords = userIntent
|
|
508
|
+
.replace(/([A-Z])/g, " $1") // camelCase → "camel Case" (before toLowerCase!)
|
|
509
|
+
.toLowerCase()
|
|
510
|
+
.split(/[\s,,]+/)
|
|
511
|
+
.filter((w) => w.length > 2);
|
|
512
|
+
const repoHits = intentWords.filter((w) => repoNames.has(w)).length;
|
|
513
|
+
const density = intentWords.length > 0 ? repoHits / intentWords.length : 0;
|
|
514
|
+
// 0.20 threshold — lower bound for short intents (3-5 words) still triggers correctly
|
|
515
|
+
if (density > 0.20) {
|
|
516
|
+
graphMode = "on";
|
|
517
|
+
console.error("[AutoRouter] " + Math.round(density * 100) + "% repo terms → Graph ON");
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
// ── 抗体免疫系统:查询历史失败模式,注入知识回流 ──
|
|
521
|
+
const antibodies = graphMode !== "off" ? (0, failure_corpus_1.queryAntibodies)(userIntent, "ACL-3") : [];
|
|
596
522
|
let antibodyHint = "";
|
|
597
523
|
if (antibodies.length > 0) {
|
|
598
524
|
const top = antibodies[0];
|
|
599
525
|
const aclLabel = top.antibodyLevel;
|
|
600
526
|
console.error(`🛡️ 命中抗体: ${aclLabel} | 模式: ${top.signature} | 相似度: ${top._score.toFixed(2)}`);
|
|
601
527
|
console.error(` 修复路径: ${top.fixPath.join(" → ")}`);
|
|
602
|
-
// ACL-4
|
|
528
|
+
// L2: ACL-4 全局稳定抗体 → 快速通道,绕过 LLM
|
|
603
529
|
if (aclLabel === "ACL-4" && top.fixPath.length > 0) {
|
|
604
530
|
const antibodyActions = top.fixPath.map((fnName) => {
|
|
605
531
|
const def = ir.find((f) => f.name === fnName);
|
|
@@ -621,7 +547,7 @@ async function plan(userIntent) {
|
|
|
621
547
|
similarityScore: top._score,
|
|
622
548
|
action: "fast_path",
|
|
623
549
|
llmCallsSaved: 1,
|
|
624
|
-
estimatedTokensSaved: Math.ceil((0, llm_1.estimateTokens)(SYSTEM_PROMPT + userIntent) * 1.2),
|
|
550
|
+
estimatedTokensSaved: Math.ceil((0, llm_1.estimateTokens)(planner_prompts_1.SYSTEM_PROMPT + userIntent) * 1.2),
|
|
625
551
|
};
|
|
626
552
|
// 验证抗体序列
|
|
627
553
|
const antibodyRuleHash = (() => {
|
|
@@ -633,7 +559,7 @@ async function plan(userIntent) {
|
|
|
633
559
|
if (protocols.length > 0) {
|
|
634
560
|
const validation = validateProtocolWithTransitions(antibodyActions, protocols, namespaceInitialStates);
|
|
635
561
|
if (validation.valid) {
|
|
636
|
-
console.error(`⚡ ACL-4 抗体快速通道: 0 LLM 调用,节省 ~${Math.ceil((0, llm_1.estimateTokens)(SYSTEM_PROMPT + userIntent) * 1.2)} tokens (est.)`);
|
|
562
|
+
console.error(`⚡ ACL-4 抗体快速通道: 0 LLM 调用,节省 ~${Math.ceil((0, llm_1.estimateTokens)(planner_prompts_1.SYSTEM_PROMPT + userIntent) * 1.2)} tokens (est.)`);
|
|
637
563
|
const antibodyAttempt = {
|
|
638
564
|
id: (0, runtime_types_1.generateAttemptId)(),
|
|
639
565
|
sessionId: session.sessionId,
|
|
@@ -664,7 +590,7 @@ async function plan(userIntent) {
|
|
|
664
590
|
}
|
|
665
591
|
else {
|
|
666
592
|
// 无协议规则,直接信任抗体
|
|
667
|
-
console.error(`⚡ ACL-4 抗体快速通道: 0 LLM 调用(无协议约束),节省 ~${Math.ceil((0, llm_1.estimateTokens)(SYSTEM_PROMPT + userIntent) * 1.2)} tokens (est.)`);
|
|
593
|
+
console.error(`⚡ ACL-4 抗体快速通道: 0 LLM 调用(无协议约束),节省 ~${Math.ceil((0, llm_1.estimateTokens)(planner_prompts_1.SYSTEM_PROMPT + userIntent) * 1.2)} tokens (est.)`);
|
|
668
594
|
const antibodyAttempt = {
|
|
669
595
|
id: (0, runtime_types_1.generateAttemptId)(),
|
|
670
596
|
sessionId: session.sessionId,
|
|
@@ -693,9 +619,24 @@ async function plan(userIntent) {
|
|
|
693
619
|
return wrapResult(antibodyActions);
|
|
694
620
|
}
|
|
695
621
|
}
|
|
696
|
-
// ACL-3
|
|
697
|
-
|
|
698
|
-
|
|
622
|
+
// L1: ACL-3 抗体注入提示 — 知识回流到 Planner
|
|
623
|
+
const hints = [];
|
|
624
|
+
for (let i = 0; i < Math.min(antibodies.length, 3); i++) {
|
|
625
|
+
const ab = antibodies[i];
|
|
626
|
+
const level = ab.antibodyLevel;
|
|
627
|
+
const sig = ab.signature;
|
|
628
|
+
const count = ab.occurrenceCount;
|
|
629
|
+
const fix = ab.fixPath.join(" → ");
|
|
630
|
+
// 为每种违规类型生成具体的避错指南
|
|
631
|
+
const avoidance = sig.includes("F07") ? "确保在调用 .map/.filter 前检查对象是否为数组,使用 (obj || [])"
|
|
632
|
+
: sig.includes("SVL-1") ? "只使用可用函数列表中的函数名,禁止编造"
|
|
633
|
+
: sig.includes("SVL-2") ? `检查函数参数类型是否与 IR 签名一致`
|
|
634
|
+
: sig.includes("SVL-4") ? `严格遵循 SSG 协议状态顺序:${fix}`
|
|
635
|
+
: `避免此模式:${sig}`;
|
|
636
|
+
hints.push(`${i + 1}. [${level}] ${sig}(累计 ${count} 次)→ ${avoidance}`);
|
|
637
|
+
}
|
|
638
|
+
antibodyHint = `\n\n⚠️ 免疫系统警告(来自 ${antibodies.length} 条历史抗体记录):\n${hints.join("\n")}\n请避免上述已知错误模式。`;
|
|
639
|
+
console.error(`💉 L1 抗体注入: ${antibodies.length} 条抗体 → ${hints.length} 条注入提示`);
|
|
699
640
|
}
|
|
700
641
|
const keywords = (0, utils_1.extractKeywords)(userIntent);
|
|
701
642
|
const intentLower = userIntent.toLowerCase();
|
|
@@ -778,8 +719,9 @@ async function plan(userIntent) {
|
|
|
778
719
|
scored.sort((a, b) => b.score - a.score);
|
|
779
720
|
const topFuncs = scored.slice(0, 15);
|
|
780
721
|
// Strategy Layer: select capability chain (local, 0 LLM calls)
|
|
781
|
-
const
|
|
782
|
-
const
|
|
722
|
+
const chainResult = graphMode !== "off" ? (0, strategy_planner_1.selectCapabilityChains)(userIntent, ir, 3, llmSeeds) : { chains: [], needsLLM: false };
|
|
723
|
+
const chains = chainResult.chains;
|
|
724
|
+
const strategyHint = graphMode !== "off" ? (0, strategy_planner_1.formatChainHint)(chains) : "";
|
|
783
725
|
// Action Layer: filter functions to those in selected chains
|
|
784
726
|
let chainFuncs = topFuncs;
|
|
785
727
|
if (chains.length > 0) {
|
|
@@ -793,8 +735,10 @@ async function plan(userIntent) {
|
|
|
793
735
|
const outChain = topFuncs.filter((f) => !chainNames.has(f.name));
|
|
794
736
|
chainFuncs = [...inChain, ...outChain].slice(0, 15);
|
|
795
737
|
}
|
|
796
|
-
const compactFuncList = buildCompactFuncList(chainFuncs, ir);
|
|
797
|
-
|
|
738
|
+
const compactFuncList = (0, planner_prompts_1.buildCompactFuncList)(chainFuncs, ir);
|
|
739
|
+
// Graph recommendations: only inject when explicitly enabled (default: off)
|
|
740
|
+
// Graph validation (SVL, protocol, dataflow) always runs regardless
|
|
741
|
+
const chainHints = graphMode === "on" ? (0, planner_prompts_1.buildChainHints)(topFuncs) : "";
|
|
798
742
|
// Known string-enum types: tell LLM these are strings, not objects
|
|
799
743
|
const STRING_ENUMS = {
|
|
800
744
|
"SVL": '"SVL-1"|"SVL-2"|"SVL-3"|"SVL-4"',
|
|
@@ -813,15 +757,15 @@ async function plan(userIntent) {
|
|
|
813
757
|
forbiddenFuncs.push(targetName);
|
|
814
758
|
}
|
|
815
759
|
}
|
|
816
|
-
const protocolChainHint = buildProtocolChainHint(protocols);
|
|
760
|
+
const protocolChainHint = (0, planner_prompts_1.buildProtocolChainHint)(protocols);
|
|
817
761
|
const userPrompt = `可用函数:
|
|
818
762
|
${compactFuncList}${protocolChainHint}${chainHints}${typeHints}${strategyHint}
|
|
819
763
|
|
|
820
764
|
需求:${userIntent}${antibodyHint}
|
|
821
765
|
|
|
822
|
-
${RETRY_HINT}
|
|
766
|
+
${planner_prompts_1.RETRY_HINT}
|
|
823
767
|
只输出 JSON。`;
|
|
824
|
-
const estimatedTokens = (0, llm_1.estimateTokens)(SYSTEM_PROMPT + userPrompt);
|
|
768
|
+
const estimatedTokens = (0, llm_1.estimateTokens)(planner_prompts_1.SYSTEM_PROMPT + userPrompt);
|
|
825
769
|
console.error(`💰 估算 prompt token: ${estimatedTokens}`);
|
|
826
770
|
// ── 执行持久化:检查是否有未完成的 checkpoint ──
|
|
827
771
|
const cp = (0, failure_corpus_1.loadCheckpoint)(userIntent);
|
|
@@ -862,14 +806,14 @@ ${RETRY_HINT}
|
|
|
862
806
|
});
|
|
863
807
|
if (legalFuncs.length === topFuncs.length)
|
|
864
808
|
return compactFuncList;
|
|
865
|
-
return buildCompactFuncList(legalFuncs, ir);
|
|
809
|
+
return (0, planner_prompts_1.buildCompactFuncList)(legalFuncs, ir);
|
|
866
810
|
}
|
|
867
811
|
const maxRetries = 3;
|
|
868
812
|
for (let r = startRetry; r < maxRetries; r++) {
|
|
869
813
|
let text;
|
|
870
814
|
try {
|
|
871
815
|
text = useSystem
|
|
872
|
-
? await (0, llm_1.chat)(SYSTEM_PROMPT, currentPrompt)
|
|
816
|
+
? await (0, llm_1.chat)(planner_prompts_1.SYSTEM_PROMPT, currentPrompt)
|
|
873
817
|
: await (0, llm_1.generate)(`你是程序合成助手。\n\n${currentPrompt}`);
|
|
874
818
|
}
|
|
875
819
|
catch (e) {
|
|
@@ -878,7 +822,12 @@ ${RETRY_HINT}
|
|
|
878
822
|
if (!text)
|
|
879
823
|
continue;
|
|
880
824
|
text = text.replace(/```(?:json|javascript)?\s*/gi, '').replace(/```\s*/g, '').trim();
|
|
881
|
-
|
|
825
|
+
if ((0, llm_1.isVerbose)()) {
|
|
826
|
+
console.error(`\n📝 [VERBOSE] LLM raw output (attempt ${r + 1}/${maxRetries}):\n${text.slice(0, 3000)}${text.length > 3000 ? `\n... [${text.length - 3000} more chars]` : ""}\n`);
|
|
827
|
+
}
|
|
828
|
+
else {
|
|
829
|
+
console.error("📝 LLM 输出:\n", text);
|
|
830
|
+
}
|
|
882
831
|
// 优先尝试 JSON 解析,失败则回退到 DSL 执行
|
|
883
832
|
let rawActions = parseActionJSON(text);
|
|
884
833
|
if (!rawActions || !Array.isArray(rawActions)) {
|
|
@@ -887,7 +836,7 @@ ${RETRY_HINT}
|
|
|
887
836
|
}
|
|
888
837
|
if (!rawActions || !Array.isArray(rawActions) || rawActions.length === 0) {
|
|
889
838
|
console.error("⚠️ 解析失败,重试...");
|
|
890
|
-
currentPrompt = `可用函数:\n${compactFuncList}${protocolChainHint}\n\n需求:${userIntent}\n\n上一次输出无效。请严格输出 JSON 数组。\n${RETRY_HINT}\n只输出 JSON。`;
|
|
839
|
+
currentPrompt = `可用函数:\n${compactFuncList}${protocolChainHint}\n\n需求:${userIntent}${antibodyHint}\n\n上一次输出无效。请严格输出 JSON 数组。\n${planner_prompts_1.RETRY_HINT}\n只输出 JSON。`;
|
|
891
840
|
useSystem = false;
|
|
892
841
|
continue;
|
|
893
842
|
}
|
|
@@ -911,7 +860,7 @@ ${RETRY_HINT}
|
|
|
911
860
|
const schemaCheck = validateActionSchema(rawActions);
|
|
912
861
|
if (!schemaCheck.valid) {
|
|
913
862
|
console.error("⚠️ JSON schema 校验失败:", schemaCheck.errors.join("; "));
|
|
914
|
-
currentPrompt = `可用函数:\n${compactFuncList}${protocolChainHint}\n\n需求:${userIntent}\n\n输出格式错误:${schemaCheck.errors.join(";")}。请修正 JSON 结构。\n${RETRY_HINT}\n只输出 JSON。`;
|
|
863
|
+
currentPrompt = `可用函数:\n${compactFuncList}${protocolChainHint}\n\n需求:${userIntent}${antibodyHint}\n\n输出格式错误:${schemaCheck.errors.join(";")}。请修正 JSON 结构。\n${planner_prompts_1.RETRY_HINT}\n只输出 JSON。`;
|
|
915
864
|
useSystem = false;
|
|
916
865
|
const schemaViolation = {
|
|
917
866
|
svl: 1,
|
|
@@ -955,11 +904,25 @@ ${RETRY_HINT}
|
|
|
955
904
|
const enriched = enrichActions(rawActions, ir);
|
|
956
905
|
const filtered = enriched.filter(a => !forbiddenFuncs.includes(a.kind === "call" ? a.function : ''));
|
|
957
906
|
let ssgTransitions = [];
|
|
907
|
+
if ((0, llm_1.isVerbose)()) {
|
|
908
|
+
console.error(`🔬 [VERBOSE] Parsed ${rawActions.length} actions → ${enriched.length} enriched → ${filtered.length} after filtering`);
|
|
909
|
+
for (let ai = 0; ai < filtered.length; ai++) {
|
|
910
|
+
const a = filtered[ai];
|
|
911
|
+
if (a.kind === "call") {
|
|
912
|
+
console.error(` [${ai}] call ${a.function}(${(a.args || []).map((x) => `${x.name}=${JSON.stringify(x.value)}`).join(", ")})`);
|
|
913
|
+
}
|
|
914
|
+
else {
|
|
915
|
+
console.error(` [${ai}] ${a.kind}`);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
}
|
|
958
919
|
// 0) Hard Constraint Pre-check: local scan before full validation
|
|
959
920
|
// Saves LLM tokens by detecting obvious violations first
|
|
960
921
|
const preCheckRules = new Map();
|
|
961
922
|
for (const p of protocols)
|
|
962
923
|
preCheckRules.set(p.function, p.protocol);
|
|
924
|
+
// Protocol pre-check: state must accumulate across the sequence
|
|
925
|
+
const preCheckCtx = { ledger: [], currentState: (0, ssg_validator_1.rebuildState)([], namespaceInitialStates) };
|
|
963
926
|
const preCheckErrors = [];
|
|
964
927
|
for (let ai = 0; ai < filtered.length; ai++) {
|
|
965
928
|
const a = filtered[ai];
|
|
@@ -973,24 +936,30 @@ ${RETRY_HINT}
|
|
|
973
936
|
if (def.params && a.args && a.args.length !== def.params.length) {
|
|
974
937
|
preCheckErrors.push(`${a.function}: 参数数量错误 (期望${def.params.length}, 实际${a.args.length})`);
|
|
975
938
|
}
|
|
976
|
-
// Protocol pre-check: verify function is callable in
|
|
939
|
+
// Protocol pre-check: verify function is callable in ACCUMULATED namespace state
|
|
977
940
|
if (def.protocol && preCheckRules.size > 0) {
|
|
978
|
-
const
|
|
979
|
-
const { valid, rejection } = (0, ssg_validator_1.validateTransition)(ctx, a.function, ai, preCheckRules, namespaceInitialStates);
|
|
941
|
+
const { valid, transition, rejection } = (0, ssg_validator_1.validateTransition)(preCheckCtx, a.function, ai, preCheckRules, namespaceInitialStates);
|
|
980
942
|
if (!valid && rejection) {
|
|
981
943
|
preCheckErrors.push(`${a.function}: 协议违规 — 需要先调用 ${rejection.fixPath?.join(" → ") || "?"}`);
|
|
982
944
|
}
|
|
945
|
+
// Update accumulated state: validateTransition computes statesAfter but doesn't mutate ctx
|
|
946
|
+
if (transition.valid) {
|
|
947
|
+
preCheckCtx.currentState = transition.statesAfter;
|
|
948
|
+
}
|
|
983
949
|
}
|
|
984
950
|
}
|
|
985
|
-
//
|
|
951
|
+
// Strategy hint: warn if LLM missed all recommended nodes, record negative feedback
|
|
986
952
|
if (chains.length > 0 && chains[0].nodes.length >= 2) {
|
|
987
953
|
const topChain = chains[0];
|
|
988
|
-
const
|
|
954
|
+
const recommendedFuncs = topChain.nodes.map(n => n.name);
|
|
989
955
|
const chosenFuncs = filtered.filter(a => a.kind === "call").map(a => a.function);
|
|
990
|
-
const
|
|
991
|
-
if (
|
|
992
|
-
|
|
993
|
-
|
|
956
|
+
const hasAny = recommendedFuncs.some(fn => chosenFuncs.includes(fn));
|
|
957
|
+
if (!hasAny && recommendedFuncs.length >= 3) {
|
|
958
|
+
console.error(`⚠️ 策略提示: LLM 未使用推荐链中的任何函数 (推荐: ${topChain.explanation})`);
|
|
959
|
+
// Record negative feedback on recommended edges
|
|
960
|
+
for (let i = 0; i < topChain.nodes.length - 1; i++) {
|
|
961
|
+
(0, failure_corpus_1.recordEdgeRejection)(topChain.nodes[i].name, topChain.nodes[i + 1].name);
|
|
962
|
+
}
|
|
994
963
|
}
|
|
995
964
|
}
|
|
996
965
|
// 1) 基础序列校验
|
|
@@ -1038,7 +1007,7 @@ ${RETRY_HINT}
|
|
|
1038
1007
|
const specificErrors = preCheckErrors.length > 0
|
|
1039
1008
|
? `精确错误:\n${preCheckErrors.map(e => ` - ${e}`).join("\n")}`
|
|
1040
1009
|
: `错误:${errorsFlat.join(";")}`;
|
|
1041
|
-
currentPrompt = `可用函数:\n${compactFuncList}${protocolChainHint}\n\n需求:${userIntent}\n\n${specificErrors}\n请修正上述问题。\n${RETRY_HINT}\n只输出 JSON。`;
|
|
1010
|
+
currentPrompt = `可用函数:\n${compactFuncList}${protocolChainHint}\n\n需求:${userIntent}${antibodyHint}\n\n${specificErrors}\n请修正上述问题。\n${planner_prompts_1.RETRY_HINT}\n只输出 JSON。`;
|
|
1042
1011
|
useSystem = false;
|
|
1043
1012
|
(0, failure_corpus_1.saveCheckpoint)(userIntent, { attemptIndex: r + 1, sessionAttempts: session.attempts, currentPrompt, useSystem });
|
|
1044
1013
|
continue;
|
|
@@ -1130,21 +1099,33 @@ ${RETRY_HINT}
|
|
|
1130
1099
|
};
|
|
1131
1100
|
fs.writeFileSync(`${repairDir}/repair_${session.sessionId}.json`, JSON.stringify(repairRecord, null, 2), "utf-8");
|
|
1132
1101
|
}
|
|
1133
|
-
catch { }
|
|
1102
|
+
catch { /* topology rebuild — optional */ }
|
|
1134
1103
|
finalActions = repaired;
|
|
1135
1104
|
break;
|
|
1136
1105
|
}
|
|
1137
1106
|
const maskedFuncList = getMaskedFuncList();
|
|
1138
|
-
currentPrompt = `当前协议状态只允许以下函数:\n${maskedFuncList}${protocolChainHint}\n\n需求:${userIntent}\n\n协议违规:${explain.replace(/\n/g, ';')}。请修正。\n${RETRY_HINT}\n只输出 JSON。`;
|
|
1107
|
+
currentPrompt = `当前协议状态只允许以下函数:\n${maskedFuncList}${protocolChainHint}\n\n需求:${userIntent}${antibodyHint}\n\n协议违规:${explain.replace(/\n/g, ';')}。请修正。\n${planner_prompts_1.RETRY_HINT}\n只输出 JSON。`;
|
|
1139
1108
|
useSystem = false;
|
|
1140
1109
|
(0, failure_corpus_1.saveCheckpoint)(userIntent, { attemptIndex: r + 1, sessionAttempts: session.attempts, currentPrompt, useSystem });
|
|
1141
1110
|
continue;
|
|
1142
1111
|
}
|
|
1143
1112
|
// SSG passed — capture transitions
|
|
1144
1113
|
ssgTransitions = protoResult.transitions;
|
|
1114
|
+
if ((0, llm_1.isVerbose)()) {
|
|
1115
|
+
console.error(`✅ [VERBOSE] Protocol (SSG) validation passed — ${ssgTransitions.length} transitions recorded`);
|
|
1116
|
+
for (const t of ssgTransitions.slice(0, 5)) {
|
|
1117
|
+
const ns = t.namespace || "_global";
|
|
1118
|
+
const before = t.statesBefore?.[ns] || [];
|
|
1119
|
+
const after = t.statesAfter?.[ns] || [];
|
|
1120
|
+
console.error(` ${t.function}: [${before.join(",") || "·"}] → [${after.join(",") || "·"}] (ns=${ns})`);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1145
1123
|
}
|
|
1146
1124
|
// 3) 语义合约校验
|
|
1147
1125
|
const semResult = (0, semantic_validator_1.checkSemantic)(userIntent, filtered);
|
|
1126
|
+
if ((0, llm_1.isVerbose)() && semResult.valid) {
|
|
1127
|
+
console.error(`✅ [VERBOSE] Semantic contract validation passed`);
|
|
1128
|
+
}
|
|
1148
1129
|
if (!semResult.valid) {
|
|
1149
1130
|
console.error("⚠️ 语义校验失败:", semResult.errors.join(", "));
|
|
1150
1131
|
const violation = {
|
|
@@ -1181,7 +1162,7 @@ ${RETRY_HINT}
|
|
|
1181
1162
|
plannerRetryTotal: maxRetries,
|
|
1182
1163
|
});
|
|
1183
1164
|
(0, memory_layer_1.recordEpisode)({ intent: userIntent, actions: filtered, success: false, svlViolated: "SVL-4" });
|
|
1184
|
-
currentPrompt = `可用函数:\n${compactFuncList}${protocolChainHint}\n\n需求:${userIntent}\n\n语义错误:${semResult.errors.join(";")}。请修正。\n${RETRY_HINT}\n只输出 JSON。`;
|
|
1165
|
+
currentPrompt = `可用函数:\n${compactFuncList}${protocolChainHint}\n\n需求:${userIntent}${antibodyHint}\n\n语义错误:${semResult.errors.join(";")}。请修正。\n${planner_prompts_1.RETRY_HINT}\n只输出 JSON。`;
|
|
1185
1166
|
useSystem = false;
|
|
1186
1167
|
(0, failure_corpus_1.saveCheckpoint)(userIntent, { attemptIndex: r + 1, sessionAttempts: session.attempts, currentPrompt, useSystem });
|
|
1187
1168
|
continue;
|
|
@@ -1200,10 +1181,11 @@ ${RETRY_HINT}
|
|
|
1200
1181
|
}
|
|
1201
1182
|
}
|
|
1202
1183
|
}
|
|
1203
|
-
|
|
1184
|
+
// Only refine empty args if validation also failed — don't break good chains
|
|
1185
|
+
if (emptyArgs.length > 0 && r < maxRetries - 1 && (!seqResult.valid || preCheckErrors.length > 0)) {
|
|
1204
1186
|
const argDetails = emptyArgs.map(e => ` ${e.fn}() 参数 "${e.param}" (${e.type}) 是空值`).join("\n");
|
|
1205
1187
|
console.error(`🔍 检测到 ${emptyArgs.length} 个空参数,启动精炼...`);
|
|
1206
|
-
currentPrompt = `可用函数:\n${compactFuncList}${protocolChainHint}\n\n需求:${userIntent}\n\n上一次生成的 JSON 中以下参数为空值:\n${argDetails}\n\n请为这些参数填入有意义的示例值(字符串用描述性值,数字用合理数值,对象用 {} as Type)。\n${RETRY_HINT}\n只输出 JSON。`;
|
|
1188
|
+
currentPrompt = `可用函数:\n${compactFuncList}${protocolChainHint}\n\n需求:${userIntent}${antibodyHint}\n\n上一次生成的 JSON 中以下参数为空值:\n${argDetails}\n\n请为这些参数填入有意义的示例值(字符串用描述性值,数字用合理数值,对象用 {} as Type)。\n${planner_prompts_1.RETRY_HINT}\n只输出 JSON。`;
|
|
1207
1189
|
useSystem = false;
|
|
1208
1190
|
continue;
|
|
1209
1191
|
}
|
|
@@ -1299,7 +1281,8 @@ ${RETRY_HINT}
|
|
|
1299
1281
|
session.endedAt = Date.now();
|
|
1300
1282
|
(0, failure_corpus_1.recordSession)(session);
|
|
1301
1283
|
(0, failure_corpus_1.clearCheckpoint)(userIntent);
|
|
1302
|
-
|
|
1284
|
+
console.error("[降级] 返回回退结果 — 代码质量可能不高,建议人工审核。");
|
|
1285
|
+
return wrapResult(fallback, undefined, true);
|
|
1303
1286
|
}
|
|
1304
1287
|
(0, memory_layer_1.recordEpisode)({ intent: userIntent, actions: [], success: false });
|
|
1305
1288
|
session.resolved = false;
|
|
@@ -1310,7 +1293,8 @@ ${RETRY_HINT}
|
|
|
1310
1293
|
}
|
|
1311
1294
|
return wrapResult(finalActions);
|
|
1312
1295
|
}
|
|
1313
|
-
/** 本地规则回退:当 LLM
|
|
1296
|
+
/** 本地规则回退:当 LLM 不可用时,根据意图关键词生成简单动作序列。
|
|
1297
|
+
* 使用实际的默认值(而非占位符),确保生成的代码至少可以编译运行。 */
|
|
1314
1298
|
function generateFallbackPlan(intent, ir) {
|
|
1315
1299
|
const intentLower = intent.toLowerCase();
|
|
1316
1300
|
const actions = [];
|
|
@@ -1325,19 +1309,30 @@ function generateFallbackPlan(intent, ir) {
|
|
|
1325
1309
|
}
|
|
1326
1310
|
if (matchedFuncs.length === 0)
|
|
1327
1311
|
return [];
|
|
1312
|
+
// Sensible default values per type — no placeholder strings
|
|
1313
|
+
function defaultValue(typeName) {
|
|
1314
|
+
const t = (typeName || "string").toLowerCase();
|
|
1315
|
+
if (t === "number")
|
|
1316
|
+
return 0;
|
|
1317
|
+
if (t === "boolean")
|
|
1318
|
+
return false;
|
|
1319
|
+
if (t.includes("[]") || t.includes("array"))
|
|
1320
|
+
return [];
|
|
1321
|
+
return ""; // string default
|
|
1322
|
+
}
|
|
1328
1323
|
for (const fn of matchedFuncs) {
|
|
1329
1324
|
const args = (fn.params || []).map((p, i) => ({
|
|
1330
1325
|
name: p.name || `p${i}`,
|
|
1331
|
-
type: p.type ||
|
|
1332
|
-
value:
|
|
1326
|
+
type: p.type || "string",
|
|
1327
|
+
value: defaultValue(p.type || "string"),
|
|
1333
1328
|
}));
|
|
1334
|
-
const assignTo = fn.returnType && fn.returnType !==
|
|
1329
|
+
const assignTo = fn.returnType && fn.returnType !== "void" && fn.returnType !== "undefined"
|
|
1335
1330
|
? `${fn.name}_result` : undefined;
|
|
1336
1331
|
if (assignTo) {
|
|
1337
|
-
actions.push({ kind:
|
|
1332
|
+
actions.push({ kind: "call", function: fn.name, args, assignTo });
|
|
1338
1333
|
}
|
|
1339
1334
|
else {
|
|
1340
|
-
actions.push({ kind:
|
|
1335
|
+
actions.push({ kind: "call", function: fn.name, args });
|
|
1341
1336
|
}
|
|
1342
1337
|
}
|
|
1343
1338
|
return actions;
|