@wowok/agent-mcp 2.6.0 → 2.6.3
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 +5 -3
- package/dist/customer/info-puzzle.d.ts +1 -1
- package/dist/customer/info-puzzle.js +4 -2
- package/dist/customer/risk-assessment.js +26 -4
- package/dist/customer/types.d.ts +2 -0
- package/dist/examples/guard-template-balance-check.json +38 -0
- package/dist/examples/guard-template-time-lock.json +39 -0
- package/dist/examples/machine-template-7node-rental.json +114 -0
- package/dist/examples/rental-ziroom-machine-create.json +137 -0
- package/dist/examples/rental-ziroom-permission-create.json +35 -0
- package/dist/examples/rental-ziroom-service-create.json +80 -0
- package/dist/examples/retail-myshop-service-create.json +88 -0
- package/dist/extensions/capability-manifest.d.ts +125 -0
- package/dist/extensions/capability-manifest.js +594 -0
- package/dist/extensions/constraint-registry.d.ts +24 -0
- package/dist/extensions/constraint-registry.js +196 -0
- package/dist/extensions/index.d.ts +12 -0
- package/dist/extensions/index.js +6 -0
- package/dist/extensions/metric-registry.d.ts +26 -0
- package/dist/extensions/metric-registry.js +257 -0
- package/dist/extensions/mode-evaluator.d.ts +15 -0
- package/dist/extensions/mode-evaluator.js +170 -0
- package/dist/extensions/modes.d.ts +2 -0
- package/dist/extensions/modes.js +493 -0
- package/dist/extensions/registry.d.ts +50 -0
- package/dist/extensions/registry.js +662 -0
- package/dist/extensions/types.d.ts +219 -0
- package/dist/extensions/types.js +1 -0
- package/dist/index.js +50 -0
- package/dist/knowledge/deployment-scanner.d.ts +3 -0
- package/dist/knowledge/deployment-scanner.js +64 -3
- package/dist/knowledge/fund-layer.d.ts +72 -0
- package/dist/knowledge/fund-layer.js +420 -0
- package/dist/knowledge/guard-render.d.ts +57 -0
- package/dist/knowledge/guard-render.js +700 -0
- package/dist/knowledge/guard-risk.d.ts +13 -0
- package/dist/knowledge/guard-risk.js +57 -0
- package/dist/knowledge/guard-submission-prompt.d.ts +31 -0
- package/dist/knowledge/guard-submission-prompt.js +171 -0
- package/dist/knowledge/guard-templates.js +278 -0
- package/dist/knowledge/machine-ledger.js +1 -1
- package/dist/knowledge/machine-render.d.ts +41 -0
- package/dist/knowledge/machine-render.js +565 -0
- package/dist/knowledge/machine-templates.js +24 -5
- package/dist/knowledge/reward-confirm.js +2 -2
- package/dist/knowledge/reward-puzzle.js +1 -1
- package/dist/knowledge/reward-risk.js +9 -9
- package/dist/knowledge/reward-templates.js +2 -2
- package/dist/knowledge/service-confirm.d.ts +15 -6
- package/dist/knowledge/service-confirm.js +119 -11
- package/dist/knowledge/service-context.js +1 -1
- package/dist/knowledge/service-ledger.js +1 -1
- package/dist/knowledge/service-risk.d.ts +1 -1
- package/dist/knowledge/service-risk.js +3 -3
- package/dist/knowledge/service-templates.js +2 -2
- package/dist/knowledge/service-translation.d.ts +1 -1
- package/dist/knowledge/service-translation.js +7 -7
- package/dist/knowledge/tool-constraints.js +6 -2
- package/dist/project/deployment-bridge.d.ts +1 -1
- package/dist/project/deployment-bridge.js +31 -7
- package/dist/project/deployment-doc.d.ts +3 -0
- package/dist/project/deployment-doc.js +76 -14
- package/dist/project/edit-planner.d.ts +123 -0
- package/dist/project/edit-planner.js +1371 -0
- package/dist/project/evaluation.d.ts +2 -0
- package/dist/project/evaluation.js +873 -88
- package/dist/project/graph-builder.d.ts +4 -1
- package/dist/project/graph-builder.js +132 -62
- package/dist/project/graph.d.ts +1 -0
- package/dist/project/handlers.d.ts +317 -6
- package/dist/project/handlers.js +1171 -19
- package/dist/project/stage-gate.d.ts +4 -0
- package/dist/project/stage-gate.js +64 -5
- package/dist/project/task-tracker.d.ts +26 -0
- package/dist/project/task-tracker.js +78 -0
- package/dist/safety/preview.js +16 -0
- package/dist/schema/call/allocation.d.ts +16 -16
- package/dist/schema/call/allocation.js +2 -2
- package/dist/schema/call/arbitration.js +19 -6
- package/dist/schema/call/base.d.ts +21 -13
- package/dist/schema/call/base.js +27 -6
- package/dist/schema/call/bridge.d.ts +5 -5
- package/dist/schema/call/bridge.js +3 -1
- package/dist/schema/call/contact.js +2 -2
- package/dist/schema/call/demand.d.ts +23 -31
- package/dist/schema/call/demand.js +2 -2
- package/dist/schema/call/guard.js +2 -2
- package/dist/schema/call/machine.d.ts +1976 -752
- package/dist/schema/call/machine.js +50 -4
- package/dist/schema/call/order.d.ts +149 -228
- package/dist/schema/call/order.js +4 -3
- package/dist/schema/call/payment.d.ts +183 -3
- package/dist/schema/call/payment.js +21 -3
- package/dist/schema/call/permission.js +2 -2
- package/dist/schema/call/personal.d.ts +241 -52
- package/dist/schema/call/progress.d.ts +53 -61
- package/dist/schema/call/progress.js +18 -4
- package/dist/schema/call/repository.d.ts +23 -31
- package/dist/schema/call/repository.js +2 -2
- package/dist/schema/call/reward.js +3 -3
- package/dist/schema/call/semantic.d.ts +1 -1
- package/dist/schema/call/semantic.js +37 -2
- package/dist/schema/call/service.d.ts +275 -127
- package/dist/schema/call/service.js +89 -13
- package/dist/schema/call/treasury.js +3 -3
- package/dist/schema/common/index.d.ts +13 -2
- package/dist/schema/common/index.js +80 -15
- package/dist/schema/local/index.d.ts +32 -35
- package/dist/schema/local/index.js +28 -6
- package/dist/schema/messenger/index.d.ts +274 -46
- package/dist/schema/operations.d.ts +1264 -544
- package/dist/schema/operations.js +65 -7
- package/dist/schema/project/index.d.ts +2846 -167
- package/dist/schema/project/index.js +570 -16
- package/dist/schema/query/index.d.ts +922 -349
- package/dist/schema/query/index.js +205 -42
- package/dist/schema/schema-query/index.d.ts +65 -3
- package/dist/schema/schema-query/index.js +38 -5
- package/dist/schema/utils/node-parser.js +20 -4
- package/dist/schema/utils/object-type-utils.d.ts +12 -0
- package/dist/schema/utils/object-type-utils.js +35 -0
- package/dist/schema/utils/permission-machine-check.d.ts +49 -0
- package/dist/schema/utils/permission-machine-check.js +121 -0
- package/dist/schema/utils/skills-recommendation.d.ts +2 -0
- package/dist/schema/utils/skills-recommendation.js +76 -0
- package/dist/schema-query/index.d.ts +20 -1
- package/dist/schema-query/index.js +306 -4
- package/dist/schemas/account_operation.output.json +7 -1
- package/dist/schemas/account_operation.schema.json +3 -3
- package/dist/schemas/bridge_operation.output.json +6 -0
- package/dist/schemas/bridge_operation.schema.json +1 -1
- package/dist/schemas/guard-templates.json +379 -0
- package/dist/schemas/guard2file.schema.json +1 -1
- package/dist/schemas/index.json +1 -1
- package/dist/schemas/local_info_operation.output.json +6 -0
- package/dist/schemas/local_mark_operation.output.json +7 -1
- package/dist/schemas/local_mark_operation.schema.json +1 -1
- package/dist/schemas/machineNode2file.schema.json +1 -1
- package/dist/schemas/messenger_operation.schema.json +4 -4
- package/dist/schemas/onchain_events.output.json +1 -1
- package/dist/schemas/onchain_operations.output.json +2820 -0
- package/dist/schemas/onchain_operations.schema.json +444 -330
- package/dist/schemas/onchain_operations_allocation.schema.json +37 -28
- package/dist/schemas/onchain_operations_arbitration.schema.json +16 -14
- package/dist/schemas/onchain_operations_contact.schema.json +10 -10
- package/dist/schemas/onchain_operations_demand.schema.json +10 -10
- package/dist/schemas/onchain_operations_gen_passport.schema.json +16 -16
- package/dist/schemas/onchain_operations_gen_proof.schema.json +2 -2
- package/dist/schemas/onchain_operations_guard.schema.json +2 -2
- package/dist/schemas/onchain_operations_machine.schema.json +43 -35
- package/dist/schemas/onchain_operations_order.schema.json +72 -78
- package/dist/schemas/onchain_operations_payment.schema.json +141 -111
- package/dist/schemas/onchain_operations_permission.schema.json +3 -3
- package/dist/schemas/onchain_operations_personal.schema.json +7 -7
- package/dist/schemas/onchain_operations_progress.schema.json +9 -9
- package/dist/schemas/onchain_operations_proof.schema.json +8 -8
- package/dist/schemas/onchain_operations_repository.schema.json +10 -10
- package/dist/schemas/onchain_operations_reward.schema.json +14 -14
- package/dist/schemas/onchain_operations_service.schema.json +119 -48
- package/dist/schemas/onchain_operations_treasury.schema.json +11 -11
- package/dist/schemas/onchain_table_data.output.json +33 -25
- package/dist/schemas/onchain_table_data.schema.json +22 -21
- package/dist/schemas/project_operation.output.json +2194 -23
- package/dist/schemas/project_operation.schema.json +84 -6
- package/dist/schemas/query_toolkit.output.json +108 -80
- package/dist/schemas/query_toolkit.schema.json +12 -12
- package/dist/schemas/schema_query.output.json +70 -3
- package/dist/schemas/schema_query.schema.json +18 -3
- package/dist/schemas/wowok_buildin_info.output.json +81 -8
- package/dist/schemas/wowok_buildin_info.schema.json +46 -2
- package/dist/tools/handlers/local.js +20 -5
- package/dist/tools/handlers/onchain.js +594 -6
- package/dist/tools/handlers/project.js +76 -4
- package/dist/tools/handlers/query.js +27 -0
- package/dist/tools/handlers/schema-query.js +43 -1
- package/dist/tools/handlers/task-status.d.ts +170 -0
- package/dist/tools/handlers/task-status.js +55 -0
- package/dist/tools/handlers/wip.js +47 -1
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.js +387 -12
- package/dist/tools/retry.d.ts +8 -0
- package/dist/tools/retry.js +85 -0
- package/dist/tools/wip-deploy-assist.d.ts +28 -0
- package/dist/tools/wip-deploy-assist.js +278 -0
- package/package.json +2 -2
- package/dist/schemas/guard-node-examples.md +0 -199
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
const BUILTIN_CONSTRAINTS = [
|
|
2
|
+
{
|
|
3
|
+
constraint_id: "require_arbitration",
|
|
4
|
+
display_name: "Require Arbitration",
|
|
5
|
+
description: "Mode must include arbitration capability (arb.*) for dispute resolution",
|
|
6
|
+
rule: { type: "capability_required", capability_id: "arb.vote_weighted" },
|
|
7
|
+
severity: "hard",
|
|
8
|
+
on_violation: "block",
|
|
9
|
+
scope: "builtin",
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
constraint_id: "require_compensation_fund",
|
|
13
|
+
display_name: "Require Compensation Fund",
|
|
14
|
+
description: "Mode must include fund escrow capability (treasury.*) for compensation fund",
|
|
15
|
+
rule: { type: "capability_required", capability_id: "treasury.owner_receive" },
|
|
16
|
+
severity: "hard",
|
|
17
|
+
on_violation: "block",
|
|
18
|
+
scope: "builtin",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
constraint_id: "require_wip_evidence",
|
|
22
|
+
display_name: "Require WIP Evidence",
|
|
23
|
+
description: "Mode must include WIP evidence capability (guard.validate_wip_hash) for digital delivery validation",
|
|
24
|
+
rule: { type: "capability_required", capability_id: "guard.validate_wip_hash" },
|
|
25
|
+
severity: "soft",
|
|
26
|
+
on_violation: "warn",
|
|
27
|
+
scope: "builtin",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
constraint_id: "max_single_transaction_limit",
|
|
31
|
+
display_name: "Single Transaction Limit",
|
|
32
|
+
description: "Single transaction amount must not exceed 10000 WOW (default value, can be overridden by mode)",
|
|
33
|
+
rule: { type: "numeric_limit", field: "max_single_transaction", max: 10000 },
|
|
34
|
+
severity: "soft",
|
|
35
|
+
on_violation: "warn",
|
|
36
|
+
scope: "builtin",
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
export class ConstraintRegistry {
|
|
40
|
+
static instance;
|
|
41
|
+
constraints = new Map();
|
|
42
|
+
initialized = false;
|
|
43
|
+
static Instance() {
|
|
44
|
+
if (!ConstraintRegistry.instance) {
|
|
45
|
+
ConstraintRegistry.instance = new ConstraintRegistry();
|
|
46
|
+
}
|
|
47
|
+
return ConstraintRegistry.instance;
|
|
48
|
+
}
|
|
49
|
+
constructor() {
|
|
50
|
+
this.registerBuiltinConstraints();
|
|
51
|
+
this.initialized = true;
|
|
52
|
+
}
|
|
53
|
+
registerConstraint(constraint) {
|
|
54
|
+
if (!constraint.constraint_id || !constraint.rule)
|
|
55
|
+
return false;
|
|
56
|
+
if (this.constraints.has(constraint.constraint_id))
|
|
57
|
+
return false;
|
|
58
|
+
this.constraints.set(constraint.constraint_id, constraint);
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
registerCustomConstraint(constraint_id, display_name, description, rule, owner, severity = "soft", on_violation = "warn") {
|
|
62
|
+
return this.registerConstraint({
|
|
63
|
+
constraint_id,
|
|
64
|
+
display_name,
|
|
65
|
+
description,
|
|
66
|
+
rule,
|
|
67
|
+
severity,
|
|
68
|
+
on_violation,
|
|
69
|
+
scope: "custom",
|
|
70
|
+
owner,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
getConstraint(constraint_id) {
|
|
74
|
+
return this.constraints.get(constraint_id);
|
|
75
|
+
}
|
|
76
|
+
listConstraints(filter) {
|
|
77
|
+
let all = Array.from(this.constraints.values());
|
|
78
|
+
if (!filter)
|
|
79
|
+
return all;
|
|
80
|
+
if (filter.scope)
|
|
81
|
+
all = all.filter(c => c.scope === filter.scope);
|
|
82
|
+
if (filter.owner)
|
|
83
|
+
all = all.filter(c => c.owner === filter.owner);
|
|
84
|
+
if (filter.severity)
|
|
85
|
+
all = all.filter(c => c.severity === filter.severity);
|
|
86
|
+
return all;
|
|
87
|
+
}
|
|
88
|
+
unregisterConstraint(constraint_id, owner) {
|
|
89
|
+
const constraint = this.constraints.get(constraint_id);
|
|
90
|
+
if (!constraint || constraint.scope !== "custom" || constraint.owner !== owner)
|
|
91
|
+
return false;
|
|
92
|
+
return this.constraints.delete(constraint_id);
|
|
93
|
+
}
|
|
94
|
+
checkConstraints(mode, _capabilityRegistry, extraConstraints) {
|
|
95
|
+
const allConstraints = [...this.constraints.values()];
|
|
96
|
+
if (extraConstraints) {
|
|
97
|
+
for (const c of extraConstraints) {
|
|
98
|
+
if (!allConstraints.some(existing => existing.constraint_id === c.constraint_id)) {
|
|
99
|
+
allConstraints.push(c);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const violations = [];
|
|
104
|
+
for (const constraint of allConstraints) {
|
|
105
|
+
const violation = this.checkConstraint(mode, constraint);
|
|
106
|
+
if (violation) {
|
|
107
|
+
violations.push(violation);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return violations;
|
|
111
|
+
}
|
|
112
|
+
checkConstraint(mode, constraint) {
|
|
113
|
+
const rule = constraint.rule;
|
|
114
|
+
switch (rule.type) {
|
|
115
|
+
case "capability_required": {
|
|
116
|
+
if (!mode.capabilities_used.includes(rule.capability_id)) {
|
|
117
|
+
return {
|
|
118
|
+
constraint_id: constraint.constraint_id,
|
|
119
|
+
display_name: constraint.display_name,
|
|
120
|
+
violation: `Missing required capability: ${rule.capability_id}`,
|
|
121
|
+
severity: constraint.severity,
|
|
122
|
+
action: constraint.on_violation,
|
|
123
|
+
recommendation: `Add "${rule.capability_id}" to capabilities_used`,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
case "capability_forbidden": {
|
|
129
|
+
if (mode.capabilities_used.includes(rule.capability_id)) {
|
|
130
|
+
return {
|
|
131
|
+
constraint_id: constraint.constraint_id,
|
|
132
|
+
display_name: constraint.display_name,
|
|
133
|
+
violation: `Contains forbidden capability: ${rule.capability_id}`,
|
|
134
|
+
severity: constraint.severity,
|
|
135
|
+
action: constraint.on_violation,
|
|
136
|
+
recommendation: `Remove "${rule.capability_id}" from capabilities_used`,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
case "numeric_limit": {
|
|
142
|
+
const fieldValue = this.getNumericField(mode, rule.field);
|
|
143
|
+
if (fieldValue === undefined)
|
|
144
|
+
return null;
|
|
145
|
+
if (rule.max !== undefined && fieldValue > rule.max) {
|
|
146
|
+
return {
|
|
147
|
+
constraint_id: constraint.constraint_id,
|
|
148
|
+
display_name: constraint.display_name,
|
|
149
|
+
violation: `${rule.field}=${fieldValue} exceeds upper limit ${rule.max}`,
|
|
150
|
+
severity: constraint.severity,
|
|
151
|
+
action: constraint.on_violation,
|
|
152
|
+
recommendation: `Reduce ${rule.field} below ${rule.max}`,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
if (rule.min !== undefined && fieldValue < rule.min) {
|
|
156
|
+
return {
|
|
157
|
+
constraint_id: constraint.constraint_id,
|
|
158
|
+
display_name: constraint.display_name,
|
|
159
|
+
violation: `${rule.field}=${fieldValue} below lower limit ${rule.min}`,
|
|
160
|
+
severity: constraint.severity,
|
|
161
|
+
action: constraint.on_violation,
|
|
162
|
+
recommendation: `Increase ${rule.field} above ${rule.min}`,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
case "condition_required": {
|
|
168
|
+
return {
|
|
169
|
+
constraint_id: constraint.constraint_id,
|
|
170
|
+
display_name: constraint.display_name,
|
|
171
|
+
violation: `Natural language condition pending AI evaluation: "${rule.condition}"`,
|
|
172
|
+
severity: constraint.severity,
|
|
173
|
+
action: constraint.on_violation,
|
|
174
|
+
recommendation: `Please have AI evaluate whether this condition is satisfied, and update the mode configuration`,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
default:
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
getNumericField(mode, field) {
|
|
182
|
+
if (field === "max_single_transaction") {
|
|
183
|
+
return mode.risk_constraints.max_single_transaction;
|
|
184
|
+
}
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
registerBuiltinConstraints() {
|
|
188
|
+
for (const constraint of BUILTIN_CONSTRAINTS) {
|
|
189
|
+
this.registerConstraint(constraint);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
export function getConstraintRegistry() {
|
|
194
|
+
return ConstraintRegistry.Instance();
|
|
195
|
+
}
|
|
196
|
+
export const BUILTIN_CONSTRAINTS_COUNT = BUILTIN_CONSTRAINTS.length;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type { Blueprint, BlueprintObject, BlueprintEdge, BlueprintStep, BlueprintScenario, ProjectContext, } from "./types.js";
|
|
2
|
+
export type { IndustryMode, IndustryModeRegistration, UserDefinedMode, DeriveModeOptions, EvolveModeOptions, } from "./types.js";
|
|
3
|
+
export type { ExpectedBenefit, RiskAppetite, ModeRiskConstraints, ModeApplicableConditions, ConfigOverrideRule, ModeEvaluation, ModeMigrationEvaluation, } from "./types.js";
|
|
4
|
+
export type { BaseMetric, MetricType, MetricScale, MetricValue, CapabilityMetricValue, MetricEvaluation, } from "./types.js";
|
|
5
|
+
export type { ModeConstraint, ConstraintRule, ConstraintSeverity, ConstraintViolationAction, ConstraintViolation, } from "./types.js";
|
|
6
|
+
export { CapabilityRegistry, getCapabilityRegistry, recordCapabilitiesUsed, CAPABILITY_MANIFEST_VERSION, } from "./capability-manifest.js";
|
|
7
|
+
export type { CapabilityCard, CapabilityGraph, CapabilityGraphEdge, CapabilityModule, CapabilityCategory, IndustryAgnostic, MigrationEvaluation, CoverageReport, ExperienceUpdate, VerificationReport, CapabilityRiskProfile, CapabilityBenefitProfile, CapabilityConstraints, } from "./capability-manifest.js";
|
|
8
|
+
export { IndustryModeRegistry, getIndustryModeRegistry, INDUSTRY_MODE_REGISTRY_VERSION, } from "./registry.js";
|
|
9
|
+
export { MetricRegistry, getMetricRegistry, BUILTIN_METRICS_COUNT, } from "./metric-registry.js";
|
|
10
|
+
export { ConstraintRegistry, getConstraintRegistry, BUILTIN_CONSTRAINTS_COUNT, } from "./constraint-registry.js";
|
|
11
|
+
export { ModeEvaluator } from "./mode-evaluator.js";
|
|
12
|
+
export { BUILTIN_MODES } from "./modes.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { CapabilityRegistry, getCapabilityRegistry, recordCapabilitiesUsed, CAPABILITY_MANIFEST_VERSION, } from "./capability-manifest.js";
|
|
2
|
+
export { IndustryModeRegistry, getIndustryModeRegistry, INDUSTRY_MODE_REGISTRY_VERSION, } from "./registry.js";
|
|
3
|
+
export { MetricRegistry, getMetricRegistry, BUILTIN_METRICS_COUNT, } from "./metric-registry.js";
|
|
4
|
+
export { ConstraintRegistry, getConstraintRegistry, BUILTIN_CONSTRAINTS_COUNT, } from "./constraint-registry.js";
|
|
5
|
+
export { ModeEvaluator } from "./mode-evaluator.js";
|
|
6
|
+
export { BUILTIN_MODES } from "./modes.js";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { BaseMetric, MetricType, MetricScale, MetricEvaluation, IndustryMode } from "./types.js";
|
|
2
|
+
import type { CapabilityRegistry } from "./capability-manifest.js";
|
|
3
|
+
export declare class MetricRegistry {
|
|
4
|
+
private static instance;
|
|
5
|
+
private metrics;
|
|
6
|
+
private initialized;
|
|
7
|
+
static Instance(): MetricRegistry;
|
|
8
|
+
private constructor();
|
|
9
|
+
registerMetric(metric: BaseMetric): boolean;
|
|
10
|
+
registerCustomMetric(metric_id: string, display_name: string, description: string, type: MetricType, scale: MetricScale, owner: string, weight?: number): boolean;
|
|
11
|
+
getMetric(metric_id: string): BaseMetric | undefined;
|
|
12
|
+
listMetrics(filter?: {
|
|
13
|
+
type?: MetricType;
|
|
14
|
+
scope?: "builtin" | "custom";
|
|
15
|
+
owner?: string;
|
|
16
|
+
}): BaseMetric[];
|
|
17
|
+
unregisterMetric(metric_id: string, owner: string): boolean;
|
|
18
|
+
evaluateMode(mode: IndustryMode, capabilityRegistry: CapabilityRegistry, extraMetrics?: BaseMetric[]): MetricEvaluation;
|
|
19
|
+
private evaluateMetricGroup;
|
|
20
|
+
private computeAverageScore;
|
|
21
|
+
private aggregateValue;
|
|
22
|
+
private aggregateScore;
|
|
23
|
+
private registerBuiltinMetrics;
|
|
24
|
+
}
|
|
25
|
+
export declare function getMetricRegistry(): MetricRegistry;
|
|
26
|
+
export declare const BUILTIN_METRICS_COUNT: number;
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
const LEVEL_WEIGHT = {
|
|
2
|
+
high: 1.0,
|
|
3
|
+
medium: 0.6,
|
|
4
|
+
low: 0.3,
|
|
5
|
+
};
|
|
6
|
+
const BUILTIN_RISK_METRICS = [
|
|
7
|
+
{
|
|
8
|
+
metric_id: "funds_risk",
|
|
9
|
+
display_name: "Funds Risk",
|
|
10
|
+
description: "Directly operates funds / affects fund flow / no fund risk",
|
|
11
|
+
type: "risk",
|
|
12
|
+
scale: "level",
|
|
13
|
+
weight: 1.0,
|
|
14
|
+
scope: "builtin",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
metric_id: "trust_risk",
|
|
18
|
+
display_name: "Trust Risk",
|
|
19
|
+
description: "Degree of impact on trust mechanism",
|
|
20
|
+
type: "risk",
|
|
21
|
+
scale: "level",
|
|
22
|
+
weight: 1.0,
|
|
23
|
+
scope: "builtin",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
metric_id: "delivery_risk",
|
|
27
|
+
display_name: "Delivery Risk",
|
|
28
|
+
description: "Degree of impact on order fulfillment",
|
|
29
|
+
type: "risk",
|
|
30
|
+
scale: "level",
|
|
31
|
+
weight: 1.0,
|
|
32
|
+
scope: "builtin",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
metric_id: "compliance_risk",
|
|
36
|
+
display_name: "Compliance Risk",
|
|
37
|
+
description: "Degree of regulatory involvement",
|
|
38
|
+
type: "risk",
|
|
39
|
+
scale: "level",
|
|
40
|
+
weight: 1.0,
|
|
41
|
+
scope: "builtin",
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
const BUILTIN_BENEFIT_METRICS = [
|
|
45
|
+
{
|
|
46
|
+
metric_id: "automation_level",
|
|
47
|
+
display_name: "Automation Level",
|
|
48
|
+
description: "Fully automated / semi-automated / manual",
|
|
49
|
+
type: "benefit",
|
|
50
|
+
scale: "level",
|
|
51
|
+
weight: 1.0,
|
|
52
|
+
scope: "builtin",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
metric_id: "trust_boost",
|
|
56
|
+
display_name: "Trust Boost",
|
|
57
|
+
description: "Degree of enhancement to trust mechanism",
|
|
58
|
+
type: "benefit",
|
|
59
|
+
scale: "level",
|
|
60
|
+
weight: 1.0,
|
|
61
|
+
scope: "builtin",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
metric_id: "efficiency_gain",
|
|
65
|
+
display_name: "Efficiency Gain",
|
|
66
|
+
description: "Degree of efficiency improvement",
|
|
67
|
+
type: "benefit",
|
|
68
|
+
scale: "level",
|
|
69
|
+
weight: 1.0,
|
|
70
|
+
scope: "builtin",
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
export class MetricRegistry {
|
|
74
|
+
static instance;
|
|
75
|
+
metrics = new Map();
|
|
76
|
+
initialized = false;
|
|
77
|
+
static Instance() {
|
|
78
|
+
if (!MetricRegistry.instance) {
|
|
79
|
+
MetricRegistry.instance = new MetricRegistry();
|
|
80
|
+
}
|
|
81
|
+
return MetricRegistry.instance;
|
|
82
|
+
}
|
|
83
|
+
constructor() {
|
|
84
|
+
this.registerBuiltinMetrics();
|
|
85
|
+
this.initialized = true;
|
|
86
|
+
}
|
|
87
|
+
registerMetric(metric) {
|
|
88
|
+
if (!metric.metric_id || !metric.type || !metric.scale)
|
|
89
|
+
return false;
|
|
90
|
+
if (this.metrics.has(metric.metric_id))
|
|
91
|
+
return false;
|
|
92
|
+
this.metrics.set(metric.metric_id, metric);
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
registerCustomMetric(metric_id, display_name, description, type, scale, owner, weight) {
|
|
96
|
+
return this.registerMetric({
|
|
97
|
+
metric_id,
|
|
98
|
+
display_name,
|
|
99
|
+
description,
|
|
100
|
+
type,
|
|
101
|
+
scale,
|
|
102
|
+
weight: weight ?? 1.0,
|
|
103
|
+
scope: "custom",
|
|
104
|
+
owner,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
getMetric(metric_id) {
|
|
108
|
+
return this.metrics.get(metric_id);
|
|
109
|
+
}
|
|
110
|
+
listMetrics(filter) {
|
|
111
|
+
let all = Array.from(this.metrics.values());
|
|
112
|
+
if (!filter)
|
|
113
|
+
return all;
|
|
114
|
+
if (filter.type)
|
|
115
|
+
all = all.filter(m => m.type === filter.type);
|
|
116
|
+
if (filter.scope)
|
|
117
|
+
all = all.filter(m => m.scope === filter.scope);
|
|
118
|
+
if (filter.owner)
|
|
119
|
+
all = all.filter(m => m.owner === filter.owner);
|
|
120
|
+
return all;
|
|
121
|
+
}
|
|
122
|
+
unregisterMetric(metric_id, owner) {
|
|
123
|
+
const metric = this.metrics.get(metric_id);
|
|
124
|
+
if (!metric || metric.scope !== "custom" || metric.owner !== owner)
|
|
125
|
+
return false;
|
|
126
|
+
return this.metrics.delete(metric_id);
|
|
127
|
+
}
|
|
128
|
+
evaluateMode(mode, capabilityRegistry, extraMetrics) {
|
|
129
|
+
const allMetrics = [...this.metrics.values()];
|
|
130
|
+
if (extraMetrics) {
|
|
131
|
+
for (const m of extraMetrics) {
|
|
132
|
+
if (!allMetrics.some(existing => existing.metric_id === m.metric_id)) {
|
|
133
|
+
allMetrics.push(m);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const riskMetrics = allMetrics.filter(m => m.type === "risk");
|
|
138
|
+
const benefitMetrics = allMetrics.filter(m => m.type === "benefit");
|
|
139
|
+
const cards = [];
|
|
140
|
+
for (const capId of mode.capabilities_used) {
|
|
141
|
+
const card = capabilityRegistry.getCard(capId);
|
|
142
|
+
if (card)
|
|
143
|
+
cards.push(card);
|
|
144
|
+
}
|
|
145
|
+
const risk_details = this.evaluateMetricGroup(cards, riskMetrics, "risk");
|
|
146
|
+
const benefit_details = this.evaluateMetricGroup(cards, benefitMetrics, "benefit");
|
|
147
|
+
const risk_score = this.aggregateScore(risk_details);
|
|
148
|
+
const benefit_score = this.aggregateScore(benefit_details);
|
|
149
|
+
return {
|
|
150
|
+
risk_score,
|
|
151
|
+
benefit_score,
|
|
152
|
+
metric_details: [...risk_details, ...benefit_details],
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
evaluateMetricGroup(cards, metrics, type) {
|
|
156
|
+
const details = [];
|
|
157
|
+
for (const metric of metrics) {
|
|
158
|
+
const values = [];
|
|
159
|
+
for (const card of cards) {
|
|
160
|
+
const profile = type === "risk" ? card.risk_profile : card.benefit_profile;
|
|
161
|
+
if (!profile)
|
|
162
|
+
continue;
|
|
163
|
+
const fieldValue = profile[metric.metric_id];
|
|
164
|
+
if (fieldValue !== undefined) {
|
|
165
|
+
values.push({
|
|
166
|
+
value: fieldValue,
|
|
167
|
+
weight: 1.0,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (values.length === 0)
|
|
172
|
+
continue;
|
|
173
|
+
const avgScore = this.computeAverageScore(values, metric.scale);
|
|
174
|
+
details.push({
|
|
175
|
+
metric_id: metric.metric_id,
|
|
176
|
+
display_name: metric.display_name,
|
|
177
|
+
value: this.aggregateValue(values, metric.scale),
|
|
178
|
+
normalized_score: avgScore,
|
|
179
|
+
weight: metric.weight ?? 1.0,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
return details;
|
|
183
|
+
}
|
|
184
|
+
computeAverageScore(values, scale) {
|
|
185
|
+
if (values.length === 0)
|
|
186
|
+
return 0;
|
|
187
|
+
if (scale === "level") {
|
|
188
|
+
const levelToScore = { high: 100, medium: 60, low: 30 };
|
|
189
|
+
let total = 0;
|
|
190
|
+
let weightSum = 0;
|
|
191
|
+
for (const v of values) {
|
|
192
|
+
const score = levelToScore[String(v.value)] ?? 50;
|
|
193
|
+
total += score * v.weight;
|
|
194
|
+
weightSum += v.weight;
|
|
195
|
+
}
|
|
196
|
+
return Math.round(total / Math.max(weightSum, 1));
|
|
197
|
+
}
|
|
198
|
+
if (scale === "numeric") {
|
|
199
|
+
let total = 0;
|
|
200
|
+
let weightSum = 0;
|
|
201
|
+
for (const v of values) {
|
|
202
|
+
const numValue = typeof v.value === "number" ? v.value : 50;
|
|
203
|
+
total += numValue * v.weight;
|
|
204
|
+
weightSum += v.weight;
|
|
205
|
+
}
|
|
206
|
+
return Math.round(total / Math.max(weightSum, 1));
|
|
207
|
+
}
|
|
208
|
+
if (scale === "percentage") {
|
|
209
|
+
let total = 0;
|
|
210
|
+
let weightSum = 0;
|
|
211
|
+
for (const v of values) {
|
|
212
|
+
const pctValue = typeof v.value === "number" ? v.value : 50;
|
|
213
|
+
total += pctValue * v.weight;
|
|
214
|
+
weightSum += v.weight;
|
|
215
|
+
}
|
|
216
|
+
return Math.round(total / Math.max(weightSum, 1));
|
|
217
|
+
}
|
|
218
|
+
return 0;
|
|
219
|
+
}
|
|
220
|
+
aggregateValue(values, scale) {
|
|
221
|
+
if (scale === "level") {
|
|
222
|
+
const counts = { high: 0, medium: 0, low: 0 };
|
|
223
|
+
for (const v of values) {
|
|
224
|
+
const key = String(v.value);
|
|
225
|
+
if (counts[key] !== undefined)
|
|
226
|
+
counts[key]++;
|
|
227
|
+
}
|
|
228
|
+
const maxKey = Object.entries(counts).sort((a, b) => b[1] - a[1])[0]?.[0];
|
|
229
|
+
return maxKey ?? "medium";
|
|
230
|
+
}
|
|
231
|
+
const sum = values.reduce((acc, v) => acc + (typeof v.value === "number" ? v.value : 0), 0);
|
|
232
|
+
return Math.round(sum / values.length);
|
|
233
|
+
}
|
|
234
|
+
aggregateScore(details) {
|
|
235
|
+
if (details.length === 0)
|
|
236
|
+
return 0;
|
|
237
|
+
let total = 0;
|
|
238
|
+
let weightSum = 0;
|
|
239
|
+
for (const d of details) {
|
|
240
|
+
total += d.normalized_score * d.weight;
|
|
241
|
+
weightSum += d.weight;
|
|
242
|
+
}
|
|
243
|
+
return Math.round(total / Math.max(weightSum, 1));
|
|
244
|
+
}
|
|
245
|
+
registerBuiltinMetrics() {
|
|
246
|
+
for (const metric of BUILTIN_RISK_METRICS) {
|
|
247
|
+
this.registerMetric(metric);
|
|
248
|
+
}
|
|
249
|
+
for (const metric of BUILTIN_BENEFIT_METRICS) {
|
|
250
|
+
this.registerMetric(metric);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
export function getMetricRegistry() {
|
|
255
|
+
return MetricRegistry.Instance();
|
|
256
|
+
}
|
|
257
|
+
export const BUILTIN_METRICS_COUNT = BUILTIN_RISK_METRICS.length + BUILTIN_BENEFIT_METRICS.length;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { IndustryMode, ModeEvaluation, ModeMigrationEvaluation, ProjectContext } from "./types.js";
|
|
2
|
+
import type { CapabilityRegistry } from "./capability-manifest.js";
|
|
3
|
+
import { MetricRegistry } from "./metric-registry.js";
|
|
4
|
+
import { ConstraintRegistry } from "./constraint-registry.js";
|
|
5
|
+
export declare class ModeEvaluator {
|
|
6
|
+
private capabilityRegistry;
|
|
7
|
+
private metricRegistry;
|
|
8
|
+
private constraintRegistry;
|
|
9
|
+
constructor(capabilityRegistry: CapabilityRegistry, metricRegistry?: MetricRegistry, constraintRegistry?: ConstraintRegistry);
|
|
10
|
+
evaluateMode(mode: IndustryMode, intent: string, context: ProjectContext): ModeEvaluation;
|
|
11
|
+
evaluateMigration(source: IndustryMode, target: IndustryMode): ModeMigrationEvaluation;
|
|
12
|
+
private isCustomMode;
|
|
13
|
+
private checkCapabilityConflicts;
|
|
14
|
+
private generateRecommendations;
|
|
15
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { MetricRegistry } from "./metric-registry.js";
|
|
2
|
+
import { ConstraintRegistry } from "./constraint-registry.js";
|
|
3
|
+
export class ModeEvaluator {
|
|
4
|
+
capabilityRegistry;
|
|
5
|
+
metricRegistry;
|
|
6
|
+
constraintRegistry;
|
|
7
|
+
constructor(capabilityRegistry, metricRegistry, constraintRegistry) {
|
|
8
|
+
this.capabilityRegistry = capabilityRegistry;
|
|
9
|
+
this.metricRegistry = metricRegistry ?? MetricRegistry.Instance();
|
|
10
|
+
this.constraintRegistry = constraintRegistry ?? ConstraintRegistry.Instance();
|
|
11
|
+
}
|
|
12
|
+
evaluateMode(mode, intent, context) {
|
|
13
|
+
const capability_conflicts = this.checkCapabilityConflicts(mode);
|
|
14
|
+
const customConstraints = this.isCustomMode(mode) ? mode.custom_constraints : undefined;
|
|
15
|
+
const constraintViolations = this.constraintRegistry.checkConstraints(mode, this.capabilityRegistry, customConstraints);
|
|
16
|
+
const violated_constraints = constraintViolations
|
|
17
|
+
.filter(v => v.severity === "hard")
|
|
18
|
+
.map(v => `${v.display_name}: ${v.violation}`);
|
|
19
|
+
const unmet_conditions = constraintViolations
|
|
20
|
+
.filter(v => v.severity === "soft")
|
|
21
|
+
.map(v => `${v.display_name}: ${v.violation}`);
|
|
22
|
+
const customMetrics = this.isCustomMode(mode) ? mode.custom_metrics : undefined;
|
|
23
|
+
const metricEval = this.metricRegistry.evaluateMode(mode, this.capabilityRegistry, customMetrics);
|
|
24
|
+
const risk_score = metricEval.risk_score;
|
|
25
|
+
const benefit_score = metricEval.benefit_score;
|
|
26
|
+
const risk_benefit_ratio = benefit_score / Math.max(risk_score, 1);
|
|
27
|
+
const applicable = capability_conflicts.length === 0 &&
|
|
28
|
+
violated_constraints.length === 0;
|
|
29
|
+
const recommendations = this.generateRecommendations(mode, risk_score, benefit_score, capability_conflicts, violated_constraints, unmet_conditions);
|
|
30
|
+
return {
|
|
31
|
+
applicable,
|
|
32
|
+
risk_score,
|
|
33
|
+
benefit_score,
|
|
34
|
+
risk_benefit_ratio,
|
|
35
|
+
capability_conflicts,
|
|
36
|
+
violated_constraints,
|
|
37
|
+
unmet_conditions,
|
|
38
|
+
recommendations,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
evaluateMigration(source, target) {
|
|
42
|
+
const sourceCaps = new Set(source.capabilities_used);
|
|
43
|
+
const targetCaps = new Set(target.capabilities_used);
|
|
44
|
+
const added_capabilities = [];
|
|
45
|
+
const removed_capabilities = [];
|
|
46
|
+
const conflicting_capabilities = [];
|
|
47
|
+
for (const cap of targetCaps) {
|
|
48
|
+
if (!sourceCaps.has(cap))
|
|
49
|
+
added_capabilities.push(cap);
|
|
50
|
+
}
|
|
51
|
+
for (const cap of sourceCaps) {
|
|
52
|
+
if (!targetCaps.has(cap))
|
|
53
|
+
removed_capabilities.push(cap);
|
|
54
|
+
}
|
|
55
|
+
const targetConflicts = this.checkCapabilityConflicts(target);
|
|
56
|
+
conflicting_capabilities.push(...targetConflicts);
|
|
57
|
+
const sourceMetric = this.metricRegistry.evaluateMode(source, this.capabilityRegistry);
|
|
58
|
+
const targetMetric = this.metricRegistry.evaluateMode(target, this.capabilityRegistry);
|
|
59
|
+
const source_risk_score = sourceMetric.risk_score;
|
|
60
|
+
const target_risk_score = targetMetric.risk_score;
|
|
61
|
+
const source_benefit_score = sourceMetric.benefit_score;
|
|
62
|
+
const target_benefit_score = targetMetric.benefit_score;
|
|
63
|
+
const risk_delta = target_risk_score - source_risk_score;
|
|
64
|
+
const benefit_delta = target_benefit_score - source_benefit_score;
|
|
65
|
+
let feasibility_score = 50;
|
|
66
|
+
feasibility_score += benefit_delta * 0.5;
|
|
67
|
+
feasibility_score -= risk_delta * 0.3;
|
|
68
|
+
feasibility_score -= conflicting_capabilities.length * 10;
|
|
69
|
+
feasibility_score -= added_capabilities.length * 2;
|
|
70
|
+
feasibility_score = Math.max(0, Math.min(100, Math.round(feasibility_score)));
|
|
71
|
+
const recommendations = [];
|
|
72
|
+
if (benefit_delta > 0) {
|
|
73
|
+
recommendations.push(`Benefit increased by ${benefit_delta.toFixed(1)} points, migration has positive value`);
|
|
74
|
+
}
|
|
75
|
+
else if (benefit_delta < 0) {
|
|
76
|
+
recommendations.push(`Benefit decreased by ${Math.abs(benefit_delta).toFixed(1)} points, need to evaluate migration necessity`);
|
|
77
|
+
}
|
|
78
|
+
if (risk_delta > 10) {
|
|
79
|
+
recommendations.push(`Risk increased by ${risk_delta.toFixed(1)} points, recommend strengthening risk control measures`);
|
|
80
|
+
}
|
|
81
|
+
else if (risk_delta < -10) {
|
|
82
|
+
recommendations.push(`Risk decreased by ${Math.abs(risk_delta).toFixed(1)} points, migration helps risk management`);
|
|
83
|
+
}
|
|
84
|
+
if (added_capabilities.length > 0) {
|
|
85
|
+
recommendations.push(`Added ${added_capabilities.length} capabilities, need extra configuration: ${added_capabilities.slice(0, 3).join(", ")}`);
|
|
86
|
+
}
|
|
87
|
+
if (removed_capabilities.length > 0) {
|
|
88
|
+
recommendations.push(`Removed ${removed_capabilities.length} capabilities, related features will be unavailable`);
|
|
89
|
+
}
|
|
90
|
+
if (conflicting_capabilities.length > 0) {
|
|
91
|
+
recommendations.push(`Detected ${conflicting_capabilities.length} capability conflicts, must be resolved before migration`);
|
|
92
|
+
}
|
|
93
|
+
if (feasibility_score >= 70) {
|
|
94
|
+
recommendations.push("Migration feasibility is high, recommend executing");
|
|
95
|
+
}
|
|
96
|
+
else if (feasibility_score >= 40) {
|
|
97
|
+
recommendations.push("Migration feasibility is medium, need careful evaluation");
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
recommendations.push("Migration feasibility is low, recommend keeping the current mode or finding an alternative");
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
feasibility_score,
|
|
104
|
+
source_risk_score,
|
|
105
|
+
target_risk_score,
|
|
106
|
+
source_benefit_score,
|
|
107
|
+
target_benefit_score,
|
|
108
|
+
risk_delta,
|
|
109
|
+
benefit_delta,
|
|
110
|
+
added_capabilities,
|
|
111
|
+
removed_capabilities,
|
|
112
|
+
conflicting_capabilities,
|
|
113
|
+
recommendations,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
isCustomMode(mode) {
|
|
117
|
+
return mode.owner !== undefined &&
|
|
118
|
+
mode.source === "custom";
|
|
119
|
+
}
|
|
120
|
+
checkCapabilityConflicts(mode) {
|
|
121
|
+
const conflicts = [];
|
|
122
|
+
const caps = mode.capabilities_used;
|
|
123
|
+
for (const capId of caps) {
|
|
124
|
+
const card = this.capabilityRegistry.getCard(capId);
|
|
125
|
+
if (!card?.constraints?.conflicts_with)
|
|
126
|
+
continue;
|
|
127
|
+
for (const conflictId of card.constraints.conflicts_with) {
|
|
128
|
+
if (caps.includes(conflictId)) {
|
|
129
|
+
conflicts.push(`${capId} conflicts with ${conflictId}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (card.constraints.must_pair_with) {
|
|
133
|
+
for (const requiredId of card.constraints.must_pair_with) {
|
|
134
|
+
if (!caps.includes(requiredId)) {
|
|
135
|
+
conflicts.push(`${capId} requires ${requiredId} (must_pair_with not satisfied)`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return conflicts;
|
|
141
|
+
}
|
|
142
|
+
generateRecommendations(mode, risk_score, benefit_score, capability_conflicts, violated_constraints, unmet_conditions) {
|
|
143
|
+
const recs = [];
|
|
144
|
+
if (capability_conflicts.length > 0) {
|
|
145
|
+
recs.push(`Detected ${capability_conflicts.length} capability conflicts, must be resolved before applying the mode`);
|
|
146
|
+
}
|
|
147
|
+
if (violated_constraints.length > 0) {
|
|
148
|
+
recs.push(`Detected ${violated_constraints.length} hard constraint violations, need to supplement missing capabilities or adjust mode configuration`);
|
|
149
|
+
}
|
|
150
|
+
if (unmet_conditions.length > 0) {
|
|
151
|
+
recs.push(`Detected ${unmet_conditions.length} soft constraints not met, recommend adjusting to improve mode quality`);
|
|
152
|
+
}
|
|
153
|
+
const appetiteThresholds = {
|
|
154
|
+
conservative: { max_risk: 30, min_benefit: 50 },
|
|
155
|
+
balanced: { max_risk: 60, min_benefit: 60 },
|
|
156
|
+
aggressive: { max_risk: 100, min_benefit: 80 },
|
|
157
|
+
};
|
|
158
|
+
const threshold = appetiteThresholds[mode.risk_appetite];
|
|
159
|
+
if (risk_score > threshold.max_risk) {
|
|
160
|
+
recs.push(`Risk score ${risk_score} exceeds ${mode.risk_appetite} mode threshold ${threshold.max_risk}, recommend reducing risk or adjusting risk appetite`);
|
|
161
|
+
}
|
|
162
|
+
if (benefit_score < threshold.min_benefit) {
|
|
163
|
+
recs.push(`Benefit score ${benefit_score} below ${mode.risk_appetite} mode threshold ${threshold.min_benefit}, recommend adding benefit capabilities or adjusting risk appetite`);
|
|
164
|
+
}
|
|
165
|
+
if (recs.length === 0) {
|
|
166
|
+
recs.push(`Mode evaluation passed: risk ${risk_score} / benefit ${benefit_score} / risk-benefit ratio ${(benefit_score / Math.max(risk_score, 1)).toFixed(2)}`);
|
|
167
|
+
}
|
|
168
|
+
return recs;
|
|
169
|
+
}
|
|
170
|
+
}
|