@wowok/agent-mcp 2.6.1 → 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/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.js +24 -24
- package/dist/extensions/constraint-registry.js +18 -18
- package/dist/extensions/metric-registry.js +14 -14
- package/dist/extensions/mode-evaluator.js +16 -16
- package/dist/extensions/modes.js +131 -45
- package/dist/extensions/registry.d.ts +2 -0
- package/dist/extensions/registry.js +63 -30
- package/dist/extensions/types.d.ts +1 -0
- package/dist/index.js +50 -0
- package/dist/knowledge/deployment-scanner.js +1 -1
- 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-submission-prompt.d.ts +31 -0
- package/dist/knowledge/guard-submission-prompt.js +171 -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 +4 -4
- 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 +1 -1
- package/dist/knowledge/service-confirm.js +3 -3
- 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/project/deployment-bridge.js +6 -5
- package/dist/project/deployment-doc.js +5 -5
- package/dist/project/edit-planner.d.ts +123 -0
- package/dist/project/edit-planner.js +1371 -0
- package/dist/project/evaluation.js +314 -14
- package/dist/project/graph-builder.js +6 -1
- package/dist/project/handlers.d.ts +99 -2
- package/dist/project/handlers.js +358 -16
- package/dist/project/stage-gate.js +4 -4
- package/dist/schema/call/allocation.js +2 -2
- package/dist/schema/call/arbitration.js +19 -6
- package/dist/schema/call/contact.js +2 -2
- package/dist/schema/call/demand.js +2 -2
- package/dist/schema/call/guard.js +1 -1
- package/dist/schema/call/machine.d.ts +1975 -777
- package/dist/schema/call/machine.js +50 -4
- package/dist/schema/call/order.js +3 -6
- package/dist/schema/call/permission.js +2 -2
- package/dist/schema/call/repository.js +2 -2
- package/dist/schema/call/reward.js +3 -3
- package/dist/schema/call/semantic.js +7 -1
- package/dist/schema/call/service.d.ts +180 -8
- package/dist/schema/call/service.js +82 -27
- package/dist/schema/call/treasury.js +3 -3
- package/dist/schema/common/index.d.ts +2 -0
- package/dist/schema/common/index.js +46 -10
- package/dist/schema/local/index.js +5 -1
- package/dist/schema/operations.d.ts +755 -176
- package/dist/schema/operations.js +43 -7
- package/dist/schema/project/index.d.ts +969 -6
- package/dist/schema/project/index.js +268 -4
- package/dist/schema/query/index.d.ts +217 -0
- package/dist/schema/query/index.js +63 -33
- package/dist/schema/schema-query/index.d.ts +53 -3
- package/dist/schema/schema-query/index.js +17 -2
- package/dist/schema/utils/node-parser.js +13 -0
- 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 +14 -1
- package/dist/schema-query/index.js +104 -2
- package/dist/schemas/account_operation.schema.json +1 -1
- package/dist/schemas/index.json +1 -1
- 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 +115 -53
- package/dist/schemas/onchain_operations_allocation.schema.json +5 -5
- package/dist/schemas/onchain_operations_arbitration.schema.json +9 -7
- package/dist/schemas/onchain_operations_contact.schema.json +3 -3
- package/dist/schemas/onchain_operations_demand.schema.json +3 -3
- package/dist/schemas/onchain_operations_gen_passport.schema.json +2 -2
- package/dist/schemas/onchain_operations_guard.schema.json +1 -1
- package/dist/schemas/onchain_operations_machine.schema.json +4 -4
- package/dist/schemas/onchain_operations_order.schema.json +3 -3
- package/dist/schemas/onchain_operations_payment.schema.json +1 -1
- package/dist/schemas/onchain_operations_permission.schema.json +2 -2
- package/dist/schemas/onchain_operations_progress.schema.json +1 -1
- package/dist/schemas/onchain_operations_proof.schema.json +1 -1
- package/dist/schemas/onchain_operations_repository.schema.json +3 -3
- package/dist/schemas/onchain_operations_reward.schema.json +6 -6
- package/dist/schemas/onchain_operations_service.schema.json +77 -17
- package/dist/schemas/onchain_operations_treasury.schema.json +4 -4
- package/dist/schemas/onchain_table_data.output.json +1 -1
- package/dist/schemas/onchain_table_data.schema.json +10 -9
- package/dist/schemas/project_operation.output.json +1026 -7
- package/dist/schemas/project_operation.schema.json +46 -4
- package/dist/schemas/query_toolkit.output.json +15 -15
- package/dist/schemas/query_toolkit.schema.json +3 -3
- package/dist/schemas/schema_query.output.json +64 -1
- package/dist/schemas/schema_query.schema.json +3 -2
- package/dist/schemas/wowok_buildin_info.output.json +81 -8
- package/dist/schemas/wowok_buildin_info.schema.json +46 -2
- package/dist/tools/handlers/onchain.js +571 -6
- package/dist/tools/handlers/project.js +25 -2
- package/dist/tools/handlers/schema-query.js +24 -1
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.js +177 -6
- package/package.json +2 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IndustryModeRegistry } from "../extensions/registry.js";
|
|
2
|
+
import { collectPermissionIndexes, checkPermissionAuthorization, } from "../schema/utils/permission-machine-check.js";
|
|
2
3
|
const CRITICAL_BINDINGS = [
|
|
3
4
|
{ sourceType: "Service", targetType: "Machine", fieldName: "machine", critical: true },
|
|
4
5
|
{ sourceType: "Service", targetType: "Permission", fieldName: "permission", critical: true },
|
|
@@ -21,7 +22,7 @@ const MERCHANT_REQUIRED_ITEMS = [
|
|
|
21
22
|
{ id: "R11", objectType: "Repository", fieldName: "repositories", required: false, description: "Documentation — published data" },
|
|
22
23
|
{ id: "R12", objectType: "Demand", fieldName: "", required: false, description: "Market discovery — demand signals" },
|
|
23
24
|
];
|
|
24
|
-
function resolveRequiredItems(industry, compensationFundBalance = 0) {
|
|
25
|
+
function resolveRequiredItems(industry, compensationFundBalance = 0, hasAllocationEscrow = false) {
|
|
25
26
|
let result = MERCHANT_REQUIRED_ITEMS;
|
|
26
27
|
if (industry && industry !== "general") {
|
|
27
28
|
let mode;
|
|
@@ -42,6 +43,14 @@ function resolveRequiredItems(industry, compensationFundBalance = 0) {
|
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
}
|
|
46
|
+
if (hasAllocationEscrow && compensationFundBalance === 0) {
|
|
47
|
+
result = result.map(item => {
|
|
48
|
+
if (item.id === "R6") {
|
|
49
|
+
return { ...item, required: false };
|
|
50
|
+
}
|
|
51
|
+
return item;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
45
54
|
if (compensationFundBalance > 0) {
|
|
46
55
|
result = result.map(item => item.id === "R7" ? { ...item, required: true } : item);
|
|
47
56
|
}
|
|
@@ -130,6 +139,26 @@ export function getMachineNodeCount(data) {
|
|
|
130
139
|
}
|
|
131
140
|
return 0;
|
|
132
141
|
}
|
|
142
|
+
function extractMachineNodesFromCache(data) {
|
|
143
|
+
if (!data)
|
|
144
|
+
return [];
|
|
145
|
+
const nodesArr = data["nodes"];
|
|
146
|
+
if (Array.isArray(nodesArr)) {
|
|
147
|
+
return nodesArr;
|
|
148
|
+
}
|
|
149
|
+
const config = data["config"];
|
|
150
|
+
if (config && Array.isArray(config["nodes"])) {
|
|
151
|
+
return config["nodes"];
|
|
152
|
+
}
|
|
153
|
+
const nodesObj = data["nodes"];
|
|
154
|
+
if (nodesObj && typeof nodesObj === "object") {
|
|
155
|
+
const fieldsObj = nodesObj["fields"];
|
|
156
|
+
if (fieldsObj && Array.isArray(fieldsObj["contents"])) {
|
|
157
|
+
return fieldsObj["contents"];
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return [];
|
|
161
|
+
}
|
|
133
162
|
function getBalanceValue(data, field) {
|
|
134
163
|
if (!data)
|
|
135
164
|
return 0;
|
|
@@ -192,7 +221,7 @@ function getMaxSalePrice(data) {
|
|
|
192
221
|
}
|
|
193
222
|
return max;
|
|
194
223
|
}
|
|
195
|
-
function detectCircularRefs(edges) {
|
|
224
|
+
function detectCircularRefs(edges, objectTypeMap) {
|
|
196
225
|
const adj = new Map();
|
|
197
226
|
for (const e of edges) {
|
|
198
227
|
if (e.edgeSource === "potential")
|
|
@@ -239,12 +268,45 @@ function detectCircularRefs(edges) {
|
|
|
239
268
|
else if (recursionStack.has(neighbor)) {
|
|
240
269
|
const cycleStart = path.indexOf(neighbor);
|
|
241
270
|
const cycle = path.slice(cycleStart).concat(neighbor);
|
|
242
|
-
|
|
271
|
+
if (!isWoWokNormalFundCycle(cycle, objectTypeMap)) {
|
|
272
|
+
cycles.push(cycle.join("→"));
|
|
273
|
+
}
|
|
243
274
|
}
|
|
244
275
|
}
|
|
245
276
|
}
|
|
246
277
|
return cycles;
|
|
247
278
|
}
|
|
279
|
+
function isWoWokNormalFundCycle(cycle, objectTypeMap) {
|
|
280
|
+
if (!objectTypeMap || cycle.length < 3)
|
|
281
|
+
return false;
|
|
282
|
+
const typesInCycle = new Set();
|
|
283
|
+
for (const addr of cycle) {
|
|
284
|
+
const type = objectTypeMap.get(addr);
|
|
285
|
+
if (type) {
|
|
286
|
+
typesInCycle.add(type);
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (typesInCycle.size === 2 &&
|
|
293
|
+
typesInCycle.has("Order") &&
|
|
294
|
+
typesInCycle.has("Allocation")) {
|
|
295
|
+
return true;
|
|
296
|
+
}
|
|
297
|
+
if (typesInCycle.size === 3 &&
|
|
298
|
+
typesInCycle.has("Order") &&
|
|
299
|
+
typesInCycle.has("Allocation") &&
|
|
300
|
+
typesInCycle.has("Payment")) {
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
const workflowTypes = ["Service", "Machine", "Progress", "Order"];
|
|
304
|
+
const isWorkflowCycle = Array.from(typesInCycle).every(t => workflowTypes.includes(t));
|
|
305
|
+
if (isWorkflowCycle && typesInCycle.size >= 2) {
|
|
306
|
+
return true;
|
|
307
|
+
}
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
248
310
|
function adjustWeightsForPerspective(criterionScores, perspective) {
|
|
249
311
|
if (perspective === "consumer") {
|
|
250
312
|
return criterionScores.map(c => {
|
|
@@ -334,7 +396,7 @@ function evaluateIndustryPattern(project, objects, objectCache, edges) {
|
|
|
334
396
|
if (machines.length > 0) {
|
|
335
397
|
const machineObj = machines[0];
|
|
336
398
|
const cached = parseCacheData(objectCache.get(machineObj.objectAddress));
|
|
337
|
-
const nodeCount =
|
|
399
|
+
const nodeCount = getMachineNodeCount(cached);
|
|
338
400
|
if (nodeCount > 0 && nodeCount >= expectedNodes.length) {
|
|
339
401
|
matchCount++;
|
|
340
402
|
result.strengths.push(`Industry pattern match: Machine has ${nodeCount} nodes, covering "${industryName}" mode's ${expectedNodes.length} expected node(s)`);
|
|
@@ -444,6 +506,28 @@ function evaluateIndustryPattern(project, objects, objectCache, edges) {
|
|
|
444
506
|
deduction: 0,
|
|
445
507
|
});
|
|
446
508
|
}
|
|
509
|
+
if (industryName === "freelance") {
|
|
510
|
+
const machines = byType.get("Machine") ?? [];
|
|
511
|
+
for (const m of machines) {
|
|
512
|
+
const mData = parseCacheData(objectCache.get(m.objectAddress));
|
|
513
|
+
if (!mData)
|
|
514
|
+
continue;
|
|
515
|
+
const nodeCount = getMachineNodeCount(mData);
|
|
516
|
+
if (nodeCount > 0) {
|
|
517
|
+
result.findings.push({
|
|
518
|
+
criterion: "industry_pattern",
|
|
519
|
+
severity: "info",
|
|
520
|
+
message: `ISSUE-P1-4: freelance project has a Machine with ${nodeCount} node(s). ` +
|
|
521
|
+
`If the workflow includes a "delivered" state, 48h auto-accept requires ` +
|
|
522
|
+
`an off-chain keeper (WoWok Guard does not support time-based triggers). ` +
|
|
523
|
+
`Keeper should poll Progress objects in "delivered" state and call ` +
|
|
524
|
+
`adminUnhold (permission 224) after 48h timeout.`,
|
|
525
|
+
deduction: 0,
|
|
526
|
+
});
|
|
527
|
+
break;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
447
531
|
return result;
|
|
448
532
|
}
|
|
449
533
|
function evaluateRisk(input) {
|
|
@@ -499,8 +583,13 @@ function evaluateRisk(input) {
|
|
|
499
583
|
structuralScore = clampScore(structuralScore);
|
|
500
584
|
let fundScore = 100;
|
|
501
585
|
const treasuries = byType.get("Treasury") ?? [];
|
|
586
|
+
const allocations = byType.get("Allocation") ?? [];
|
|
502
587
|
const serviceData = serviceObj ? parseCacheData(objectCache.get(serviceObj.objectAddress)) : null;
|
|
503
588
|
const compensationBalance = serviceObj ? getBalanceValue(serviceData, "compensation_fund") : 0;
|
|
589
|
+
const orderAllocatorsBinding = serviceObj
|
|
590
|
+
? bindingIndex.get(`${serviceObj.objectAddress}#order_allocators`)?.size ?? 0
|
|
591
|
+
: 0;
|
|
592
|
+
const hasAllocationEscrow = allocations.length > 0 && orderAllocatorsBinding > 0;
|
|
504
593
|
let industryRequiresFund = true;
|
|
505
594
|
if (project.industry && project.industry !== "general") {
|
|
506
595
|
try {
|
|
@@ -512,7 +601,17 @@ function evaluateRisk(input) {
|
|
|
512
601
|
catch { }
|
|
513
602
|
}
|
|
514
603
|
if (treasuries.length === 0 && compensationBalance === 0) {
|
|
515
|
-
if (
|
|
604
|
+
if (hasAllocationEscrow) {
|
|
605
|
+
fundScore -= 5;
|
|
606
|
+
strengths.push("Allocation escrow mode active — funds locked in contract, released by Guard verification");
|
|
607
|
+
findings.push({
|
|
608
|
+
criterion: "fund_safety",
|
|
609
|
+
severity: "info",
|
|
610
|
+
message: `Using Allocation escrow (${allocations.length} Allocation object(s) + order_allocators bound) — fund safety via Guard verification, no Treasury/compensation_fund needed`,
|
|
611
|
+
deduction: -5,
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
else if (industryRequiresFund) {
|
|
516
615
|
fundScore -= 30;
|
|
517
616
|
findings.push({
|
|
518
617
|
criterion: "fund_safety",
|
|
@@ -539,13 +638,23 @@ function evaluateRisk(input) {
|
|
|
539
638
|
strengths.push(`Service.compensation_fund has ${compensationBalance} units — inline refund fund active`);
|
|
540
639
|
const maxSalePrice = getMaxSalePrice(serviceData);
|
|
541
640
|
if (maxSalePrice > 0) {
|
|
542
|
-
|
|
641
|
+
let coverageRatio = 5;
|
|
642
|
+
if (project.industry && project.industry !== "general") {
|
|
643
|
+
try {
|
|
644
|
+
const mode = IndustryModeRegistry.Instance().getMode(project.industry);
|
|
645
|
+
if (mode?.risk_constraints?.compensation_fund_coverage_ratio) {
|
|
646
|
+
coverageRatio = mode.risk_constraints.compensation_fund_coverage_ratio;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
catch { }
|
|
650
|
+
}
|
|
651
|
+
const requiredThreshold = coverageRatio * maxSalePrice;
|
|
543
652
|
if (compensationBalance < requiredThreshold) {
|
|
544
653
|
fundScore -= 10;
|
|
545
654
|
findings.push({
|
|
546
655
|
criterion: "fund_safety",
|
|
547
656
|
severity: "warning",
|
|
548
|
-
message: `Service.compensation_fund balance (${compensationBalance}) is less than
|
|
657
|
+
message: `Service.compensation_fund balance (${compensationBalance}) is less than ${coverageRatio}× the max order amount (${maxSalePrice} → threshold ${requiredThreshold}). Refund coverage may be insufficient — top up via service.compensation_fund_add to avoid arbitration rulings exceeding the fund. (industry: ${project.industry ?? "general"}, ratio: ${coverageRatio}×)`,
|
|
549
658
|
deduction: -10,
|
|
550
659
|
});
|
|
551
660
|
}
|
|
@@ -553,7 +662,7 @@ function evaluateRisk(input) {
|
|
|
553
662
|
findings.push({
|
|
554
663
|
criterion: "fund_safety",
|
|
555
664
|
severity: "info",
|
|
556
|
-
message: `Service.compensation_fund balance (${compensationBalance}) covers
|
|
665
|
+
message: `Service.compensation_fund balance (${compensationBalance}) covers ${coverageRatio}× the max order amount (${maxSalePrice}). Fund is sufficient for refund protection. (industry: ${project.industry ?? "general"}, ratio: ${coverageRatio}×)`,
|
|
557
666
|
deduction: 0,
|
|
558
667
|
});
|
|
559
668
|
}
|
|
@@ -632,6 +741,160 @@ function evaluateRisk(input) {
|
|
|
632
741
|
});
|
|
633
742
|
}
|
|
634
743
|
}
|
|
744
|
+
const machines = byType.get("Machine") ?? [];
|
|
745
|
+
for (const machineObj of machines) {
|
|
746
|
+
const meta = machineObj.metadata;
|
|
747
|
+
const config = meta?.config;
|
|
748
|
+
if (config?.entry_node_forward_hint) {
|
|
749
|
+
const hint = config.entry_node_forward_hint;
|
|
750
|
+
const exampleFwd = hint.example_forward;
|
|
751
|
+
if (exampleFwd?.namedOperator === "") {
|
|
752
|
+
strengths.push("Machine entry forward uses namedOperator='' (OrderHolder) — " +
|
|
753
|
+
"correct for customer-operable nodes. namedOperator='' represents " +
|
|
754
|
+
"the order holder, distinct from merchant's permission index.");
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
const guardObjects = config?.guard_objects;
|
|
758
|
+
if (guardObjects && guardObjects.length > 0) {
|
|
759
|
+
strengths.push(`Machine has ${guardObjects.length} guard object reference(s) — ` +
|
|
760
|
+
`forward-level permission validation configured`);
|
|
761
|
+
}
|
|
762
|
+
const cached = parseCacheData(objectCache.get(machineObj.objectAddress));
|
|
763
|
+
const nodeCount = getMachineNodeCount(cached);
|
|
764
|
+
if (nodeCount > 0 && !config) {
|
|
765
|
+
findings.push({
|
|
766
|
+
criterion: "governance_risk",
|
|
767
|
+
severity: "info",
|
|
768
|
+
message: `Machine has ${nodeCount} node(s). Verify each forward has at least one of ` +
|
|
769
|
+
`namedOperator or permissionIndex. Key: namedOperator='' means OrderHolder ` +
|
|
770
|
+
`(customer), NOT 'anyone'. Use non-empty namedOperator for specific roles, ` +
|
|
771
|
+
`or permissionIndex for permission-based access. Both set = OR semantic ` +
|
|
772
|
+
`(either can execute).`,
|
|
773
|
+
deduction: 0,
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
const machinesForPermCheck = byType.get("Machine") ?? [];
|
|
778
|
+
const permissionsForCheck = byType.get("Permission") ?? [];
|
|
779
|
+
const permDataMap = new Map();
|
|
780
|
+
for (const permObj of permissionsForCheck) {
|
|
781
|
+
const cached = parseCacheData(objectCache.get(permObj.objectAddress));
|
|
782
|
+
if (cached) {
|
|
783
|
+
permDataMap.set(permObj.objectAddress, {
|
|
784
|
+
address: permObj.objectAddress,
|
|
785
|
+
entity_count: typeof cached.entity_count === "number" ? cached.entity_count : undefined,
|
|
786
|
+
perm_remark: Array.isArray(cached.perm_remark) ? cached.perm_remark : undefined,
|
|
787
|
+
owner: typeof cached.owner === "string" ? cached.owner : (typeof cached.builder === "string" ? cached.builder : undefined),
|
|
788
|
+
admin: Array.isArray(cached.admin) ? cached.admin : undefined,
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
for (const machineObj of machinesForPermCheck) {
|
|
793
|
+
const machinePermKey = `${machineObj.objectAddress}#permission`;
|
|
794
|
+
const machinePermBindings = bindingIndex.get(machinePermKey);
|
|
795
|
+
if (!machinePermBindings || machinePermBindings.size === 0)
|
|
796
|
+
continue;
|
|
797
|
+
let permAddress = null;
|
|
798
|
+
for (const addr of machinePermBindings) {
|
|
799
|
+
permAddress = addr;
|
|
800
|
+
break;
|
|
801
|
+
}
|
|
802
|
+
if (!permAddress)
|
|
803
|
+
continue;
|
|
804
|
+
const permData = permDataMap.get(permAddress);
|
|
805
|
+
if (!permData)
|
|
806
|
+
continue;
|
|
807
|
+
const machineCached = parseCacheData(objectCache.get(machineObj.objectAddress));
|
|
808
|
+
if (!machineCached)
|
|
809
|
+
continue;
|
|
810
|
+
const machineNodes = extractMachineNodesFromCache(machineCached);
|
|
811
|
+
if (machineNodes.length === 0)
|
|
812
|
+
continue;
|
|
813
|
+
const collection = collectPermissionIndexes(machineNodes);
|
|
814
|
+
if (collection.requiredIndexes.length === 0)
|
|
815
|
+
continue;
|
|
816
|
+
const report = checkPermissionAuthorization(collection.requiredIndexes, permData);
|
|
817
|
+
if (!report.allAuthorized) {
|
|
818
|
+
governanceScore -= 25;
|
|
819
|
+
findings.push({
|
|
820
|
+
criterion: "governance_risk",
|
|
821
|
+
severity: "critical",
|
|
822
|
+
message: `Machine ${machineObj.objectAddress.slice(0, 8)} has forwards referencing ` +
|
|
823
|
+
`un-authorized permission indexes: [${report.missingIndexes.join(", ")}]. ` +
|
|
824
|
+
`These forwards can NEVER be executed — Progress will be permanently stuck. ` +
|
|
825
|
+
`Grant entities for these indexes via permission.op="add perm by index" ` +
|
|
826
|
+
`before publishing the Machine.`,
|
|
827
|
+
deduction: -25,
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
else {
|
|
831
|
+
strengths.push(`Machine ${machineObj.objectAddress.slice(0, 8)}: all ${collection.requiredIndexes.length} ` +
|
|
832
|
+
`permission index(es) are authorized`);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
if (serviceObj && arbitrations.length > 0) {
|
|
836
|
+
const svcPermKey = `${serviceObj.objectAddress}#permission`;
|
|
837
|
+
const svcPermBindings = bindingIndex.get(svcPermKey);
|
|
838
|
+
const svcPermAddress = svcPermBindings && svcPermBindings.size > 0
|
|
839
|
+
? Array.from(svcPermBindings)[0]
|
|
840
|
+
: null;
|
|
841
|
+
const svcPermData = svcPermAddress ? permDataMap.get(svcPermAddress) : null;
|
|
842
|
+
for (const arbObj of arbitrations) {
|
|
843
|
+
const arbPermKey = `${arbObj.objectAddress}#permission`;
|
|
844
|
+
const arbPermBindings = bindingIndex.get(arbPermKey);
|
|
845
|
+
const arbPermAddress = arbPermBindings && arbPermBindings.size > 0
|
|
846
|
+
? Array.from(arbPermBindings)[0]
|
|
847
|
+
: null;
|
|
848
|
+
if (!svcPermAddress || !arbPermAddress)
|
|
849
|
+
continue;
|
|
850
|
+
if (svcPermAddress === arbPermAddress) {
|
|
851
|
+
governanceScore -= 30;
|
|
852
|
+
findings.push({
|
|
853
|
+
criterion: "governance_risk",
|
|
854
|
+
severity: "critical",
|
|
855
|
+
message: `Arbitration ${arbObj.objectAddress.slice(0, 8)} and Service share the SAME ` +
|
|
856
|
+
`Permission object (${svcPermAddress.slice(0, 8)}). This breaks dispute ` +
|
|
857
|
+
`fairness — the merchant fully controls arbitration operations. ` +
|
|
858
|
+
`Use a separate Permission object for Arbitration to ensure independent ` +
|
|
859
|
+
`dispute resolution. (per arbitration.move: the permission field controls ` +
|
|
860
|
+
`who can vote, confirm, and execute arbitration rulings)`,
|
|
861
|
+
deduction: -30,
|
|
862
|
+
});
|
|
863
|
+
continue;
|
|
864
|
+
}
|
|
865
|
+
const arbPermData = permDataMap.get(arbPermAddress);
|
|
866
|
+
if (svcPermData && arbPermData) {
|
|
867
|
+
const svcOwner = svcPermData.owner?.toLowerCase();
|
|
868
|
+
const arbOwner = arbPermData.owner?.toLowerCase();
|
|
869
|
+
const svcAdmins = new Set((svcPermData.admin ?? []).map(a => a.toLowerCase()));
|
|
870
|
+
const arbAdmins = new Set((arbPermData.admin ?? []).map(a => a.toLowerCase()));
|
|
871
|
+
const ownerOverlap = svcOwner && arbOwner && svcOwner === arbOwner;
|
|
872
|
+
const adminOverlap = [...svcAdmins].some(a => arbAdmins.has(a));
|
|
873
|
+
if (ownerOverlap || adminOverlap) {
|
|
874
|
+
const overlapType = ownerOverlap && adminOverlap
|
|
875
|
+
? "owner AND admin overlap"
|
|
876
|
+
: ownerOverlap ? "same owner" : "admin overlap";
|
|
877
|
+
governanceScore -= 20;
|
|
878
|
+
findings.push({
|
|
879
|
+
criterion: "governance_risk",
|
|
880
|
+
severity: "warning",
|
|
881
|
+
message: `Arbitration ${arbObj.objectAddress.slice(0, 8)} and Service have ` +
|
|
882
|
+
`overlapping Permission control (${overlapType}). Even with separate ` +
|
|
883
|
+
`Permission objects, shared control undermines dispute independence. ` +
|
|
884
|
+
`For mainnet deployment, use a completely independent third-party ` +
|
|
885
|
+
`Permission (different owner and admin list) for Arbitration. ` +
|
|
886
|
+
`(testnet may tolerate this, but mainnet users should treat this as ` +
|
|
887
|
+
`a critical trust factor)`,
|
|
888
|
+
deduction: -20,
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
else {
|
|
892
|
+
strengths.push(`Arbitration ${arbObj.objectAddress.slice(0, 8)} has independent ` +
|
|
893
|
+
`Permission (separate owner/admin) — trustworthy dispute resolution`);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
}
|
|
635
898
|
governanceScore = clampScore(governanceScore);
|
|
636
899
|
let coherenceScore = 100;
|
|
637
900
|
const objectAddresses = new Set();
|
|
@@ -661,7 +924,13 @@ function evaluateRisk(input) {
|
|
|
661
924
|
deduction,
|
|
662
925
|
});
|
|
663
926
|
}
|
|
664
|
-
const
|
|
927
|
+
const objectTypeMap = new Map();
|
|
928
|
+
for (const o of objects) {
|
|
929
|
+
if (o.objectAddress) {
|
|
930
|
+
objectTypeMap.set(o.objectAddress, shortTypeName(o.objectType));
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
const cycles = detectCircularRefs(edges, objectTypeMap);
|
|
665
934
|
if (cycles.length > 0) {
|
|
666
935
|
coherenceScore -= 15;
|
|
667
936
|
findings.push({
|
|
@@ -964,7 +1233,12 @@ function evaluateCompleteness(input) {
|
|
|
964
1233
|
? parseCacheData(objectCache.get(svcObjForRequiredItems.objectAddress))
|
|
965
1234
|
: null;
|
|
966
1235
|
const compensationBalanceForItems = getBalanceValue(svcDataForRequiredItems, "compensation_fund");
|
|
967
|
-
const
|
|
1236
|
+
const allocationsForItems = byType.get("Allocation") ?? [];
|
|
1237
|
+
const orderAllocatorsBindingForItems = svcObjForRequiredItems
|
|
1238
|
+
? bindingIndex.get(`${svcObjForRequiredItems.objectAddress}#order_allocators`)?.size ?? 0
|
|
1239
|
+
: 0;
|
|
1240
|
+
const hasAllocationEscrowForItems = allocationsForItems.length > 0 && orderAllocatorsBindingForItems > 0;
|
|
1241
|
+
const requiredItems = resolveRequiredItems(project.industry ?? undefined, compensationBalanceForItems, hasAllocationEscrowForItems);
|
|
968
1242
|
const requiredCount = requiredItems.filter(r => r.required).length;
|
|
969
1243
|
const optionalItems = requiredItems.filter(r => !r.required);
|
|
970
1244
|
let requiredMet = 0;
|
|
@@ -1077,7 +1351,7 @@ function evaluateCompleteness(input) {
|
|
|
1077
1351
|
for (const m of machines) {
|
|
1078
1352
|
const data = parseCacheData(objectCache.get(m.objectAddress));
|
|
1079
1353
|
if (data) {
|
|
1080
|
-
const nodeCount =
|
|
1354
|
+
const nodeCount = getMachineNodeCount(data);
|
|
1081
1355
|
if (nodeCount > 0) {
|
|
1082
1356
|
strengths.push(`Machine has ${nodeCount} node(s)`);
|
|
1083
1357
|
}
|
|
@@ -1227,16 +1501,42 @@ function evaluateCompleteness(input) {
|
|
|
1227
1501
|
evaluatedAt: Date.now(),
|
|
1228
1502
|
};
|
|
1229
1503
|
}
|
|
1230
|
-
function evaluateWorthBuyingStub(
|
|
1504
|
+
function evaluateWorthBuyingStub(input, llmPrompt) {
|
|
1505
|
+
const riskResult = evaluateRisk(input);
|
|
1506
|
+
const trustResult = evaluateTrust(input);
|
|
1507
|
+
const completenessResult = evaluateCompleteness(input);
|
|
1508
|
+
const summaryLines = [
|
|
1509
|
+
"=== RULE-BASED EVALUATION SUMMARY (F-08 enriched context) ===",
|
|
1510
|
+
"",
|
|
1511
|
+
`Risk: ${riskResult.score}/100 — ${riskResult.summary}`,
|
|
1512
|
+
...riskResult.findings.slice(0, 3).map(f => ` - [${f.severity}] ${f.message}`),
|
|
1513
|
+
"",
|
|
1514
|
+
`Trust: ${trustResult.score}/100 — ${trustResult.summary}`,
|
|
1515
|
+
...trustResult.findings.slice(0, 3).map(f => ` - [${f.severity}] ${f.message}`),
|
|
1516
|
+
"",
|
|
1517
|
+
`Completeness: ${completenessResult.score}/100 — ${completenessResult.summary}`,
|
|
1518
|
+
...completenessResult.findings.slice(0, 3).map(f => ` - [${f.severity}] ${f.message}`),
|
|
1519
|
+
"",
|
|
1520
|
+
"=== END RULE-BASED SUMMARY ===",
|
|
1521
|
+
"",
|
|
1522
|
+
];
|
|
1523
|
+
const enrichment = summaryLines.join("\n");
|
|
1524
|
+
const enrichedPrompt = llmPrompt
|
|
1525
|
+
? `${llmPrompt}\n\n${enrichment}`
|
|
1526
|
+
: `${enrichment}\nInstruction: Based on the rule-based summary above, ` +
|
|
1527
|
+
"evaluate whether this project is worth buying. Return a 0-100 score " +
|
|
1528
|
+
"and a brief rationale. Focus on buyer risk vs. value proposition.";
|
|
1231
1529
|
return {
|
|
1232
1530
|
evaluationType: "worth_buying",
|
|
1233
1531
|
score: 0,
|
|
1234
|
-
summary: "Requires LLM evaluation — semantic prompt assembled
|
|
1532
|
+
summary: "Requires LLM evaluation — semantic prompt assembled with rule-based " +
|
|
1533
|
+
"context (risk/trust/completeness summary). Call save_evaluation with " +
|
|
1534
|
+
"the LLM result.",
|
|
1235
1535
|
criterionScores: [],
|
|
1236
1536
|
findings: [],
|
|
1237
1537
|
strengths: [],
|
|
1238
1538
|
needsLlm: true,
|
|
1239
|
-
llmPrompt,
|
|
1539
|
+
llmPrompt: enrichedPrompt,
|
|
1240
1540
|
evaluatedAt: Date.now(),
|
|
1241
1541
|
};
|
|
1242
1542
|
}
|
|
@@ -9,7 +9,12 @@ function shortTypeName(objectType) {
|
|
|
9
9
|
}
|
|
10
10
|
function extractAddressFields(obj) {
|
|
11
11
|
const refs = [];
|
|
12
|
-
const
|
|
12
|
+
const rawType = obj.type;
|
|
13
|
+
let objType = rawType;
|
|
14
|
+
if (rawType && rawType.includes("::")) {
|
|
15
|
+
const parts = rawType.split("::");
|
|
16
|
+
objType = parts[parts.length - 1];
|
|
17
|
+
}
|
|
13
18
|
const isAddress = (v) => typeof v === "string" && v.startsWith("0x") && v.length >= 10;
|
|
14
19
|
const addRef = (addr, field, refType) => {
|
|
15
20
|
if (isAddress(addr) && addr !== "0x0" && addr !== obj.object) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { z } from "zod";
|
|
2
|
-
import { type ProjectObject, type EvaluationType } from "@wowok/wowok";
|
|
2
|
+
import { type ProjectObject, type ObjectRole, type EvaluationType } from "@wowok/wowok";
|
|
3
3
|
import type { ProjectOperationInputSchema } from "../schema/project/index.js";
|
|
4
4
|
type ProjectInput = z.infer<typeof ProjectOperationInputSchema>;
|
|
5
5
|
export declare function handleListProjects(v: ProjectInput): Promise<{
|
|
@@ -100,14 +100,31 @@ export declare function handleUpdateProject(v: ProjectInput): Promise<{
|
|
|
100
100
|
export declare function handleGetProjectDetail(v: ProjectInput): Promise<{
|
|
101
101
|
action: "get_project_detail";
|
|
102
102
|
project: import("@wowok/wowok").Project;
|
|
103
|
-
objects:
|
|
103
|
+
objects: {
|
|
104
|
+
isDraft: boolean;
|
|
105
|
+
id: string;
|
|
106
|
+
projectId: string;
|
|
107
|
+
objectAddress: string;
|
|
108
|
+
objectType: string | null;
|
|
109
|
+
objectName: string | null;
|
|
110
|
+
role: ObjectRole;
|
|
111
|
+
tags: string[] | null;
|
|
112
|
+
addedAt: number;
|
|
113
|
+
metadata: Record<string, unknown> | null;
|
|
114
|
+
}[];
|
|
115
|
+
objectCount: number;
|
|
116
|
+
onchainCount: number;
|
|
117
|
+
draftCount: number;
|
|
104
118
|
objectGroups: {
|
|
105
119
|
core: ProjectObject[];
|
|
106
120
|
dependency: ProjectObject[];
|
|
107
121
|
reference: ProjectObject[];
|
|
108
122
|
other: ProjectObject[];
|
|
123
|
+
draft: ProjectObject[];
|
|
109
124
|
stats: {
|
|
110
125
|
total: number;
|
|
126
|
+
onchain_count: number;
|
|
127
|
+
draft_count: number;
|
|
111
128
|
core_count: number;
|
|
112
129
|
dependency_count: number;
|
|
113
130
|
reference_count: number;
|
|
@@ -212,6 +229,8 @@ export declare function handleEvaluateProject(v: ProjectInput): Promise<{
|
|
|
212
229
|
needsLlm: boolean;
|
|
213
230
|
llmPrompt: string | undefined;
|
|
214
231
|
evaluationId: string;
|
|
232
|
+
refreshWarning: string | undefined;
|
|
233
|
+
graphFallbackWarning: string | undefined;
|
|
215
234
|
}>;
|
|
216
235
|
export declare function handleSaveEvaluation(v: ProjectInput): Promise<{
|
|
217
236
|
action: "save_evaluation";
|
|
@@ -248,6 +267,67 @@ export declare function handleCloneProjectToNetwork(v: ProjectInput): Promise<{
|
|
|
248
267
|
message: string;
|
|
249
268
|
next_steps: string;
|
|
250
269
|
}>;
|
|
270
|
+
export declare function handleMigrateToMainnet(v: ProjectInput): Promise<{
|
|
271
|
+
action: "migrate_to_mainnet";
|
|
272
|
+
migration_status: string;
|
|
273
|
+
source_project: {
|
|
274
|
+
prefix: string;
|
|
275
|
+
network: string;
|
|
276
|
+
preserved: boolean;
|
|
277
|
+
};
|
|
278
|
+
target_project: {
|
|
279
|
+
prefix: string;
|
|
280
|
+
project_id: string;
|
|
281
|
+
network: string;
|
|
282
|
+
cloned_objects_count: number;
|
|
283
|
+
};
|
|
284
|
+
key_principle: string;
|
|
285
|
+
migration_plan: ({
|
|
286
|
+
step: number;
|
|
287
|
+
status: string;
|
|
288
|
+
action: string;
|
|
289
|
+
description: string;
|
|
290
|
+
result: string;
|
|
291
|
+
deployment_plan?: undefined;
|
|
292
|
+
critical_note?: undefined;
|
|
293
|
+
names_to_register?: undefined;
|
|
294
|
+
} | {
|
|
295
|
+
step: number;
|
|
296
|
+
status: string;
|
|
297
|
+
action: string;
|
|
298
|
+
description: string;
|
|
299
|
+
deployment_plan: {
|
|
300
|
+
order: number;
|
|
301
|
+
object_type: string;
|
|
302
|
+
object_name: string;
|
|
303
|
+
operation_type: string;
|
|
304
|
+
localmark_name: string;
|
|
305
|
+
note: string;
|
|
306
|
+
}[];
|
|
307
|
+
critical_note: string;
|
|
308
|
+
result?: undefined;
|
|
309
|
+
names_to_register?: undefined;
|
|
310
|
+
} | {
|
|
311
|
+
step: number;
|
|
312
|
+
status: string;
|
|
313
|
+
action: string;
|
|
314
|
+
description: string;
|
|
315
|
+
names_to_register: string[];
|
|
316
|
+
result?: undefined;
|
|
317
|
+
deployment_plan?: undefined;
|
|
318
|
+
critical_note?: undefined;
|
|
319
|
+
} | {
|
|
320
|
+
step: number;
|
|
321
|
+
status: string;
|
|
322
|
+
action: string;
|
|
323
|
+
description: string;
|
|
324
|
+
result?: undefined;
|
|
325
|
+
deployment_plan?: undefined;
|
|
326
|
+
critical_note?: undefined;
|
|
327
|
+
names_to_register?: undefined;
|
|
328
|
+
})[];
|
|
329
|
+
summary: string;
|
|
330
|
+
}>;
|
|
251
331
|
export declare function handleGetObjectDiff(v: ProjectInput): Promise<{
|
|
252
332
|
action: "get_object_diff";
|
|
253
333
|
address: string;
|
|
@@ -284,6 +364,23 @@ export declare function handleGetMachineGraph(v: ProjectInput): Promise<{
|
|
|
284
364
|
}[];
|
|
285
365
|
published: boolean | null;
|
|
286
366
|
paused: boolean | null;
|
|
367
|
+
mermaid: string;
|
|
368
|
+
tree_outline: string;
|
|
369
|
+
ascii_art: string;
|
|
370
|
+
markmap: string;
|
|
371
|
+
}>;
|
|
372
|
+
export declare function handleGetGuardGraph(v: ProjectInput): Promise<{
|
|
373
|
+
action: "get_guard_graph";
|
|
374
|
+
guardAddress: string;
|
|
375
|
+
guardName: string | null;
|
|
376
|
+
root: any;
|
|
377
|
+
table: any[];
|
|
378
|
+
rely: any;
|
|
379
|
+
immutable: any;
|
|
380
|
+
mermaid: string;
|
|
381
|
+
tree_outline: string;
|
|
382
|
+
ascii_art: string;
|
|
383
|
+
markmap: string;
|
|
287
384
|
}>;
|
|
288
385
|
export declare function handlePreEvaluateCheck(v: ProjectInput): Promise<{
|
|
289
386
|
action: "pre_evaluate_check";
|