@orangepro/orangepro-mcp 0.2.38 → 0.2.40
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/dist/local/cli.js
CHANGED
|
@@ -692,6 +692,8 @@ async function main() {
|
|
|
692
692
|
printJson(res);
|
|
693
693
|
else {
|
|
694
694
|
out(`Test gaps (${res.gaps.length} of ${res.total_behaviors} behaviors):`);
|
|
695
|
+
for (const w of res.warnings ?? [])
|
|
696
|
+
out(` warning: ${w}`);
|
|
695
697
|
if (res.guidance)
|
|
696
698
|
out(` ${res.guidance}`);
|
|
697
699
|
for (const g of res.gaps) {
|
package/dist/local/operations.js
CHANGED
|
@@ -656,7 +656,9 @@ export function opAnalyze(root, opts = {}, deps = defaultDeps()) {
|
|
|
656
656
|
const coverageSuccess = runtimeCoveragePrepare?.generated
|
|
657
657
|
.filter((g) => g.ok && g.artifact_path)
|
|
658
658
|
.map((g) => `coverage artifact generated for ${g.language} module ${g.module_dir}: ${g.artifact_path}`) ?? [];
|
|
659
|
-
|
|
659
|
+
// Risk-config problems must surface on EVERY entry point that ranks, not just `start`.
|
|
660
|
+
const riskConfigWarnings = loadRiskConfig(scanRoot).warnings;
|
|
661
|
+
const warnings = [...coverageSuccess, ...coverageWarnings, ...(runtimeCoveragePrepare?.warnings ?? []), ...analyzeFragment.warnings, ...enrichFragments.flatMap((f) => f.warnings), ...riskConfigWarnings];
|
|
660
662
|
return {
|
|
661
663
|
graph_path: paths.graphPath,
|
|
662
664
|
sources_count: graph.sources.length,
|
|
@@ -876,8 +878,11 @@ export function opGaps(root, opts = {}) {
|
|
|
876
878
|
is_new_code: gap.is_new_code,
|
|
877
879
|
integration_signal: gap.integration_signal
|
|
878
880
|
}));
|
|
881
|
+
// Same root the ranking itself uses (the analyzed source), not the workspace cwd.
|
|
882
|
+
const riskConfigWarnings = loadRiskConfig(graph.workspace.root).warnings;
|
|
879
883
|
return {
|
|
880
884
|
...gaps,
|
|
885
|
+
...(riskConfigWarnings.length ? { warnings: riskConfigWarnings } : {}),
|
|
881
886
|
top_risk_gaps: topRiskGaps,
|
|
882
887
|
risk_model: {
|
|
883
888
|
formula: "OrangePro Risk Score = Probability(1-10) × Impact(1-10) × DetectionDifficulty(1|5|10); P = normalize(git_churn*0.35 + fan_out*0.30 + new_code*15 + complexity*0.20); I = normalize(fan_in*0.30 + route_weight*0.30 + flow_position*0.20 + data_sensitivity*0.20); D = {proven:1, associated:5, none:10}",
|
|
@@ -1556,7 +1561,7 @@ export async function opStart(root, opts = {}, deps = defaultDeps()) {
|
|
|
1556
1561
|
reportProgress("start: deterministic graph is ready", { current: 4, total: 8 });
|
|
1557
1562
|
// A per-repo/user risk config that fails to parse must announce itself here, not
|
|
1558
1563
|
// silently revert to defaults (round-three review finding #1).
|
|
1559
|
-
for (const w of loadRiskConfig(
|
|
1564
|
+
for (const w of loadRiskConfig(scanRoot).warnings)
|
|
1560
1565
|
warnings.push(w);
|
|
1561
1566
|
const staticSnapshot = writeStartStaticSnapshot(root, opts.baseRef, warnings);
|
|
1562
1567
|
const aiProviderConfigured = deps.aiProvider !== undefined || resolveProviderConfig(providerEnv, providerOpts) !== null;
|
package/dist/local/score/risk.js
CHANGED
|
@@ -737,6 +737,10 @@ export function configDisclosureFor(graph, repoRoot) {
|
|
|
737
737
|
if (n.external_id === o.symbol || re.test(n.external_id))
|
|
738
738
|
suppressed.push({ symbol: n.title || n.external_id, reason: o.reason });
|
|
739
739
|
}
|
|
740
|
+
const ignoreRes = cfg.classification.sensitivity_ignore.map(globToRegExp);
|
|
741
|
+
const sensitivityIgnored = ignoreRes.length
|
|
742
|
+
? symbols.filter((n) => ignoreRes.some((re) => re.test(n.title || "") || re.test(n.external_id))).map((n) => n.title || n.external_id).slice(0, 50)
|
|
743
|
+
: [];
|
|
740
744
|
return {
|
|
741
745
|
hash: loaded.hash,
|
|
742
746
|
warnings: loaded.warnings,
|
|
@@ -744,6 +748,13 @@ export function configDisclosureFor(graph, repoRoot) {
|
|
|
744
748
|
suppressed,
|
|
745
749
|
rankExcludePaths: cfg.classification.rank_exclude_paths,
|
|
746
750
|
floor: cfg.tuning.irreversibility_floor,
|
|
747
|
-
silence: cfg.tuning.silence_multiplier
|
|
751
|
+
silence: cfg.tuning.silence_multiplier,
|
|
752
|
+
classification: {
|
|
753
|
+
test_support_paths: cfg.classification.test_support_paths,
|
|
754
|
+
scheduled_entry_paths: cfg.classification.scheduled_entry_paths,
|
|
755
|
+
destructive_sinks: cfg.classification.destructive_sinks,
|
|
756
|
+
sensitivity_ignore: cfg.classification.sensitivity_ignore
|
|
757
|
+
},
|
|
758
|
+
sensitivityIgnored
|
|
748
759
|
};
|
|
749
760
|
}
|
|
@@ -1034,12 +1034,16 @@ renderRisks();
|
|
|
1034
1034
|
const C=D.configDisclosure, host=$("#config-disclosure");
|
|
1035
1035
|
if(!C||!host)return;
|
|
1036
1036
|
const warn=(C.warnings||[]).length>0;
|
|
1037
|
-
const
|
|
1037
|
+
const K=C.classification||{};
|
|
1038
|
+
const clsSet=["test_support_paths","scheduled_entry_paths","destructive_sinks","sensitivity_ignore"].filter(k=>(K[k]||[]).length>0);
|
|
1039
|
+
const tuned=C.overridesActive>0||(C.rankExcludePaths||[]).length>0||!C.floor||!C.silence||clsSet.length>0;
|
|
1038
1040
|
const bits=["config <b>"+esc(C.hash)+"</b>","overrides active <b>"+C.overridesActive+"</b>","suppressed <b>"+(C.suppressed||[]).length+"</b>"];
|
|
1039
1041
|
if((C.rankExcludePaths||[]).length)bits.push("ranking excludes <b>"+esc(C.rankExcludePaths.join(", "))+"</b>");
|
|
1040
1042
|
if(!C.floor)bits.push("<b>irreversibility floor OFF</b>");
|
|
1041
1043
|
if(!C.silence)bits.push("<b>silence multiplier OFF</b>");
|
|
1042
1044
|
let html="<div>"+bits.join(" · ")+"</div>";
|
|
1045
|
+
clsSet.forEach(k=>{html+='<span class="cfg-row">'+esc(k)+': <b>'+esc(K[k].join(", "))+'</b></span>';});
|
|
1046
|
+
if((C.sensitivityIgnored||[]).length)html+='<span class="cfg-row">sensitivity ignored by config (score changed): <b>'+esc(C.sensitivityIgnored.join(", "))+'</b></span>';
|
|
1043
1047
|
(C.suppressed||[]).forEach(s=>{html+='<span class="cfg-row">suppressed by config: <b>'+esc(s.symbol)+'</b> — '+esc(s.reason)+'</span>';});
|
|
1044
1048
|
(C.warnings||[]).forEach(w=>{html+='<span class="cfg-row">⚠ '+esc(w)+'</span>';});
|
|
1045
1049
|
host.className="cfg"+(warn?" cfg-warn":tuned?" cfg-tuned":"");
|
package/dist/local/workspace.js
CHANGED
|
@@ -92,7 +92,16 @@ export function loadConfig(paths) {
|
|
|
92
92
|
privacy: defaultPrivacySettings()
|
|
93
93
|
};
|
|
94
94
|
}
|
|
95
|
-
|
|
95
|
+
const raw = readFileSync(paths.configPath, "utf8");
|
|
96
|
+
try {
|
|
97
|
+
return JSON.parse(raw);
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
// Fail loud AND clear: this file also carries the per-repo risk config, so a
|
|
101
|
+
// silent default here would be exactly the failure a verification layer must not have.
|
|
102
|
+
const hint = /\/\//.test(raw) ? " JSON does not allow // comments." : "";
|
|
103
|
+
throw new Error(`Unreadable ${paths.configPath}: ${err.message}.${hint} Fix the JSON, or delete the file to regenerate defaults.`);
|
|
104
|
+
}
|
|
96
105
|
}
|
|
97
106
|
export function saveConfig(paths, config) {
|
|
98
107
|
writeJson(paths.configPath, config);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orangepro/orangepro-mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.40",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "OrangePro (`opro`) — a local-first, BYOK CLI + MCP server that builds an evidence graph from a local checkout, ingests runtime coverage, and generates grounded tests. Metadata-only exports; no source upload; generated tests stay local.",
|
|
6
6
|
"license": "MIT",
|