@wowok/agent-mcp 2.6.0 → 2.6.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.
Files changed (133) hide show
  1. package/README.md +5 -3
  2. package/dist/extensions/capability-manifest.d.ts +125 -0
  3. package/dist/extensions/capability-manifest.js +594 -0
  4. package/dist/extensions/constraint-registry.d.ts +24 -0
  5. package/dist/extensions/constraint-registry.js +196 -0
  6. package/dist/extensions/index.d.ts +12 -0
  7. package/dist/extensions/index.js +6 -0
  8. package/dist/extensions/metric-registry.d.ts +26 -0
  9. package/dist/extensions/metric-registry.js +257 -0
  10. package/dist/extensions/mode-evaluator.d.ts +15 -0
  11. package/dist/extensions/mode-evaluator.js +170 -0
  12. package/dist/extensions/modes.d.ts +2 -0
  13. package/dist/extensions/modes.js +407 -0
  14. package/dist/extensions/registry.d.ts +48 -0
  15. package/dist/extensions/registry.js +629 -0
  16. package/dist/extensions/types.d.ts +218 -0
  17. package/dist/extensions/types.js +1 -0
  18. package/dist/knowledge/deployment-scanner.d.ts +3 -0
  19. package/dist/knowledge/deployment-scanner.js +64 -3
  20. package/dist/knowledge/guard-risk.d.ts +13 -0
  21. package/dist/knowledge/guard-risk.js +57 -0
  22. package/dist/knowledge/guard-templates.js +278 -0
  23. package/dist/knowledge/machine-templates.js +20 -1
  24. package/dist/knowledge/service-confirm.d.ts +14 -5
  25. package/dist/knowledge/service-confirm.js +116 -8
  26. package/dist/knowledge/tool-constraints.js +6 -2
  27. package/dist/project/deployment-bridge.d.ts +1 -1
  28. package/dist/project/deployment-bridge.js +27 -4
  29. package/dist/project/deployment-doc.d.ts +3 -0
  30. package/dist/project/deployment-doc.js +72 -10
  31. package/dist/project/evaluation.d.ts +2 -0
  32. package/dist/project/evaluation.js +569 -84
  33. package/dist/project/graph-builder.d.ts +4 -1
  34. package/dist/project/graph-builder.js +126 -61
  35. package/dist/project/graph.d.ts +1 -0
  36. package/dist/project/handlers.d.ts +219 -5
  37. package/dist/project/handlers.js +819 -9
  38. package/dist/project/stage-gate.d.ts +4 -0
  39. package/dist/project/stage-gate.js +64 -5
  40. package/dist/project/task-tracker.d.ts +26 -0
  41. package/dist/project/task-tracker.js +78 -0
  42. package/dist/safety/preview.js +16 -0
  43. package/dist/schema/call/allocation.d.ts +16 -16
  44. package/dist/schema/call/base.d.ts +21 -13
  45. package/dist/schema/call/base.js +27 -6
  46. package/dist/schema/call/bridge.d.ts +5 -5
  47. package/dist/schema/call/bridge.js +3 -1
  48. package/dist/schema/call/demand.d.ts +23 -31
  49. package/dist/schema/call/guard.js +1 -1
  50. package/dist/schema/call/machine.d.ts +402 -376
  51. package/dist/schema/call/order.d.ts +149 -228
  52. package/dist/schema/call/order.js +7 -3
  53. package/dist/schema/call/payment.d.ts +183 -3
  54. package/dist/schema/call/payment.js +21 -3
  55. package/dist/schema/call/personal.d.ts +241 -52
  56. package/dist/schema/call/progress.d.ts +53 -61
  57. package/dist/schema/call/progress.js +18 -4
  58. package/dist/schema/call/repository.d.ts +23 -31
  59. package/dist/schema/call/semantic.d.ts +1 -1
  60. package/dist/schema/call/semantic.js +30 -1
  61. package/dist/schema/call/service.d.ts +95 -119
  62. package/dist/schema/call/service.js +22 -1
  63. package/dist/schema/common/index.d.ts +11 -2
  64. package/dist/schema/common/index.js +43 -14
  65. package/dist/schema/local/index.d.ts +32 -35
  66. package/dist/schema/local/index.js +23 -5
  67. package/dist/schema/messenger/index.d.ts +274 -46
  68. package/dist/schema/operations.d.ts +680 -539
  69. package/dist/schema/operations.js +22 -0
  70. package/dist/schema/project/index.d.ts +1796 -80
  71. package/dist/schema/project/index.js +304 -14
  72. package/dist/schema/query/index.d.ts +705 -349
  73. package/dist/schema/query/index.js +164 -31
  74. package/dist/schema/schema-query/index.d.ts +15 -3
  75. package/dist/schema/schema-query/index.js +23 -5
  76. package/dist/schema/utils/node-parser.js +7 -4
  77. package/dist/schema-query/index.d.ts +7 -1
  78. package/dist/schema-query/index.js +204 -4
  79. package/dist/schemas/account_operation.output.json +7 -1
  80. package/dist/schemas/account_operation.schema.json +2 -2
  81. package/dist/schemas/bridge_operation.output.json +6 -0
  82. package/dist/schemas/bridge_operation.schema.json +1 -1
  83. package/dist/schemas/guard-templates.json +379 -0
  84. package/dist/schemas/guard2file.schema.json +1 -1
  85. package/dist/schemas/index.json +1 -1
  86. package/dist/schemas/local_info_operation.output.json +6 -0
  87. package/dist/schemas/local_mark_operation.output.json +7 -1
  88. package/dist/schemas/local_mark_operation.schema.json +1 -1
  89. package/dist/schemas/machineNode2file.schema.json +1 -1
  90. package/dist/schemas/messenger_operation.schema.json +4 -4
  91. package/dist/schemas/onchain_events.output.json +1 -1
  92. package/dist/schemas/onchain_operations.schema.json +348 -296
  93. package/dist/schemas/onchain_operations_allocation.schema.json +34 -25
  94. package/dist/schemas/onchain_operations_arbitration.schema.json +8 -8
  95. package/dist/schemas/onchain_operations_contact.schema.json +8 -8
  96. package/dist/schemas/onchain_operations_demand.schema.json +8 -8
  97. package/dist/schemas/onchain_operations_gen_passport.schema.json +14 -14
  98. package/dist/schemas/onchain_operations_gen_proof.schema.json +2 -2
  99. package/dist/schemas/onchain_operations_guard.schema.json +1 -1
  100. package/dist/schemas/onchain_operations_machine.schema.json +41 -33
  101. package/dist/schemas/onchain_operations_order.schema.json +71 -77
  102. package/dist/schemas/onchain_operations_payment.schema.json +141 -111
  103. package/dist/schemas/onchain_operations_permission.schema.json +2 -2
  104. package/dist/schemas/onchain_operations_personal.schema.json +7 -7
  105. package/dist/schemas/onchain_operations_progress.schema.json +8 -8
  106. package/dist/schemas/onchain_operations_proof.schema.json +7 -7
  107. package/dist/schemas/onchain_operations_repository.schema.json +8 -8
  108. package/dist/schemas/onchain_operations_reward.schema.json +10 -10
  109. package/dist/schemas/onchain_operations_service.schema.json +46 -35
  110. package/dist/schemas/onchain_operations_treasury.schema.json +8 -8
  111. package/dist/schemas/onchain_table_data.output.json +33 -25
  112. package/dist/schemas/onchain_table_data.schema.json +12 -12
  113. package/dist/schemas/project_operation.output.json +1175 -23
  114. package/dist/schemas/project_operation.schema.json +40 -4
  115. package/dist/schemas/query_toolkit.output.json +104 -76
  116. package/dist/schemas/query_toolkit.schema.json +9 -9
  117. package/dist/schemas/schema_query.output.json +7 -3
  118. package/dist/schemas/schema_query.schema.json +17 -3
  119. package/dist/tools/handlers/local.js +20 -5
  120. package/dist/tools/handlers/onchain.js +23 -0
  121. package/dist/tools/handlers/project.js +52 -3
  122. package/dist/tools/handlers/query.js +27 -0
  123. package/dist/tools/handlers/schema-query.js +19 -0
  124. package/dist/tools/handlers/task-status.d.ts +170 -0
  125. package/dist/tools/handlers/task-status.js +55 -0
  126. package/dist/tools/handlers/wip.js +47 -1
  127. package/dist/tools/index.js +211 -7
  128. package/dist/tools/retry.d.ts +8 -0
  129. package/dist/tools/retry.js +85 -0
  130. package/dist/tools/wip-deploy-assist.d.ts +28 -0
  131. package/dist/tools/wip-deploy-assist.js +278 -0
  132. package/package.json +2 -2
  133. package/dist/schemas/guard-node-examples.md +0 -199
@@ -1,9 +1,9 @@
1
+ import { IndustryModeRegistry } from "../extensions/registry.js";
1
2
  const CRITICAL_BINDINGS = [
2
3
  { sourceType: "Service", targetType: "Machine", fieldName: "machine", critical: true },
3
4
  { sourceType: "Service", targetType: "Permission", fieldName: "permission", critical: true },
4
5
  { sourceType: "Service", targetType: "Guard", fieldName: "buy_guard", critical: false },
5
- { sourceType: "Service", targetType: "Treasury", fieldName: "compensation_fund", critical: false },
6
- { sourceType: "Service", targetType: "Allocation", fieldName: "order_allocators", critical: false },
6
+ { sourceType: "Service", targetType: "Allocation", fieldName: "order_allocators", critical: true },
7
7
  { sourceType: "Service", targetType: "Arbitration", fieldName: "arbitrations", critical: false },
8
8
  { sourceType: "Machine", targetType: "Permission", fieldName: "permission", critical: true },
9
9
  ];
@@ -11,21 +11,47 @@ const MERCHANT_REQUIRED_ITEMS = [
11
11
  { id: "R1", objectType: "Permission", fieldName: "", required: true, description: "Governance — who can manage the service" },
12
12
  { id: "R2", objectType: "Service", fieldName: "", required: true, description: "Core offering — the service itself" },
13
13
  { id: "R3", objectType: "Machine", fieldName: "machine", required: true, description: "Workflow — order processing pipeline" },
14
- { id: "R4", objectType: "Guard", fieldName: "buy_guard", required: true, description: "Purchase validation — guard on Service.buy()" },
15
- { id: "R5", objectType: "Allocation", fieldName: "order_allocators", required: true, description: "Order allocators — fund distribution rules" },
16
- { id: "R6", objectType: "Treasury", fieldName: "compensation_fund", required: true, description: "Compensation fund — buyer refund protection" },
17
- { id: "R7", objectType: "Arbitration", fieldName: "arbitrations", required: true, description: "Dispute resolution — arbitration configured" },
14
+ { id: "R4", objectType: "Guard", fieldName: "", required: true, description: "Purchase validation — Guard objects configured (binding to Service.buy_guard is optional)" },
15
+ { id: "R5", objectType: "Allocation", fieldName: "order_allocators", required: true, description: "Order allocators template — inline Allocators on Service (independent Allocation objects are created per-order)" },
16
+ { id: "R6", objectType: "Treasury", fieldName: "", required: true, description: "Compensation fund — independent Treasury object for buyer refund protection (industry-aware: optional for freelance)" },
17
+ { id: "R7", objectType: "Arbitration", fieldName: "arbitrations", required: true, description: "Dispute resolution — arbitration configured (required when compensation_fund > 0 per service.move:494)" },
18
18
  { id: "R8", objectType: "Contact", fieldName: "", required: true, description: "Customer communication — contact info" },
19
19
  { id: "R9", objectType: "Progress", fieldName: "", required: false, description: "Order tracking — progress nodes" },
20
20
  { id: "R10", objectType: "Reward", fieldName: "rewards", required: false, description: "Customer incentives — reward claims" },
21
21
  { id: "R11", objectType: "Repository", fieldName: "repositories", required: false, description: "Documentation — published data" },
22
22
  { id: "R12", objectType: "Demand", fieldName: "", required: false, description: "Market discovery — demand signals" },
23
23
  ];
24
+ function resolveRequiredItems(industry, compensationFundBalance = 0) {
25
+ let result = MERCHANT_REQUIRED_ITEMS;
26
+ if (industry && industry !== "general") {
27
+ let mode;
28
+ try {
29
+ mode = IndustryModeRegistry.Instance().getMode(industry);
30
+ }
31
+ catch {
32
+ }
33
+ if (mode) {
34
+ const requireFund = mode.risk_constraints?.require_compensation_fund ?? true;
35
+ if (!requireFund) {
36
+ result = MERCHANT_REQUIRED_ITEMS.map(item => {
37
+ if (item.id === "R6" || item.id === "R7") {
38
+ return { ...item, required: false };
39
+ }
40
+ return item;
41
+ });
42
+ }
43
+ }
44
+ }
45
+ if (compensationFundBalance > 0) {
46
+ result = result.map(item => item.id === "R7" ? { ...item, required: true } : item);
47
+ }
48
+ return result;
49
+ }
24
50
  const CONSUMER_DUE_DILIGENCE = [
25
51
  { id: "E1", check: "Service is published (bPublished=true)", severity: "critical", deduction: -30 },
26
52
  { id: "E2", check: "Service is not paused (bPaused=false)", severity: "warning", deduction: -20 },
27
53
  { id: "E3", check: "Machine has workflow nodes", severity: "warning", deduction: -15 },
28
- { id: "E4", check: "Service has buy_guard (purchase validation)", severity: "warning", deduction: -15 },
54
+ { id: "E4", check: "Service has buy_guard (purchase validation)", severity: "info", deduction: 0 },
29
55
  { id: "E5", check: "Service has compensation_fund (refund protection)", severity: "warning", deduction: -15 },
30
56
  { id: "E6", check: "Arbitration is configured (dispute resolution)", severity: "critical", deduction: -25 },
31
57
  { id: "E7", check: "Permission is present (governance)", severity: "warning", deduction: -10 },
@@ -34,7 +60,6 @@ const CONSUMER_DUE_DILIGENCE = [
34
60
  { id: "E10", check: "Reward is configured (customer incentives)", severity: "info", deduction: -3 },
35
61
  { id: "E11", check: "Service has description (offering clarity)", severity: "info", deduction: -5 },
36
62
  { id: "E12", check: "Registrar reputation is positive", severity: "warning", deduction: -10 },
37
- { id: "E13", check: "No critical findings in risk evaluation", severity: "critical", deduction: -20 },
38
63
  ];
39
64
  function clampScore(n) {
40
65
  return Math.max(0, Math.min(100, Math.round(n)));
@@ -44,7 +69,11 @@ function shortTypeName(objectType) {
44
69
  return "unknown";
45
70
  const base = objectType.replace(/<.*>/, "").trim();
46
71
  const segments = base.split("::");
47
- return segments[segments.length - 1] || "unknown";
72
+ const shortName = segments[segments.length - 1] || "unknown";
73
+ if (shortName.length > 0 && shortName === shortName.toLowerCase()) {
74
+ return shortName.charAt(0).toUpperCase() + shortName.slice(1);
75
+ }
76
+ return shortName;
48
77
  }
49
78
  function parseCacheData(cached) {
50
79
  if (!cached)
@@ -65,6 +94,104 @@ function countArrayField(data, field) {
65
94
  return v.length;
66
95
  return 0;
67
96
  }
97
+ export function getNumberField(data, field) {
98
+ if (!data)
99
+ return 0;
100
+ const v = data[field];
101
+ if (typeof v === "number" && Number.isFinite(v))
102
+ return v;
103
+ if (typeof v === "string") {
104
+ const n = Number(v);
105
+ if (Number.isFinite(n))
106
+ return n;
107
+ }
108
+ return 0;
109
+ }
110
+ export function getMachineNodeCount(data) {
111
+ if (!data)
112
+ return 0;
113
+ const nc = getNumberField(data, "node_count");
114
+ if (nc > 0)
115
+ return nc;
116
+ const arrLen = countArrayField(data, "nodes");
117
+ if (arrLen > 0)
118
+ return arrLen;
119
+ const nodesObj = data["nodes"];
120
+ if (nodesObj && typeof nodesObj === "object") {
121
+ const fieldsObj = nodesObj["fields"];
122
+ if (fieldsObj && typeof fieldsObj === "object") {
123
+ const sizeVal = getNumberField(fieldsObj, "size");
124
+ if (sizeVal > 0)
125
+ return sizeVal;
126
+ }
127
+ const directSize = getNumberField(nodesObj, "size");
128
+ if (directSize > 0)
129
+ return directSize;
130
+ }
131
+ return 0;
132
+ }
133
+ function getBalanceValue(data, field) {
134
+ if (!data)
135
+ return 0;
136
+ const v = data[field];
137
+ if (v == null)
138
+ return 0;
139
+ if (typeof v === "number" && Number.isFinite(v))
140
+ return v;
141
+ if (typeof v === "string") {
142
+ const n = Number(v);
143
+ if (Number.isFinite(n))
144
+ return n;
145
+ }
146
+ if (typeof v === "object") {
147
+ const obj = v;
148
+ const inner = obj.value ?? obj.fields;
149
+ if (typeof inner === "number" && Number.isFinite(inner))
150
+ return inner;
151
+ if (typeof inner === "string") {
152
+ const n = Number(inner);
153
+ if (Number.isFinite(n))
154
+ return n;
155
+ }
156
+ if (typeof inner === "object" && inner !== null) {
157
+ const innerObj = inner;
158
+ const val = innerObj.value;
159
+ if (typeof val === "number" && Number.isFinite(val))
160
+ return val;
161
+ if (typeof val === "string") {
162
+ const n = Number(val);
163
+ if (Number.isFinite(n))
164
+ return n;
165
+ }
166
+ }
167
+ }
168
+ return 0;
169
+ }
170
+ function getMaxSalePrice(data) {
171
+ if (!data)
172
+ return 0;
173
+ const sales = data.sales;
174
+ if (!Array.isArray(sales) || sales.length === 0)
175
+ return 0;
176
+ let max = 0;
177
+ for (const sale of sales) {
178
+ if (typeof sale !== "object" || sale === null)
179
+ continue;
180
+ const price = sale.price;
181
+ let n = 0;
182
+ if (typeof price === "number" && Number.isFinite(price)) {
183
+ n = price;
184
+ }
185
+ else if (typeof price === "string") {
186
+ const parsed = Number(price);
187
+ if (Number.isFinite(parsed))
188
+ n = parsed;
189
+ }
190
+ if (n > max)
191
+ max = n;
192
+ }
193
+ return max;
194
+ }
68
195
  function detectCircularRefs(edges) {
69
196
  const adj = new Map();
70
197
  for (const e of edges) {
@@ -78,14 +205,36 @@ function detectCircularRefs(edges) {
78
205
  const visited = new Set();
79
206
  const recursionStack = new Set();
80
207
  const path = [];
81
- const dfs = (node) => {
82
- visited.add(node);
83
- recursionStack.add(node);
84
- path.push(node);
85
- const neighbors = adj.get(node) ?? [];
86
- for (const neighbor of neighbors) {
208
+ for (const startNode of adj.keys()) {
209
+ if (visited.has(startNode))
210
+ continue;
211
+ const stack = [{
212
+ node: startNode,
213
+ nextNeighborIdx: 0,
214
+ neighbors: adj.get(startNode) ?? [],
215
+ }];
216
+ visited.add(startNode);
217
+ recursionStack.add(startNode);
218
+ path.push(startNode);
219
+ while (stack.length > 0) {
220
+ const frame = stack[stack.length - 1];
221
+ if (frame.nextNeighborIdx >= frame.neighbors.length) {
222
+ stack.pop();
223
+ path.pop();
224
+ recursionStack.delete(frame.node);
225
+ continue;
226
+ }
227
+ const neighbor = frame.neighbors[frame.nextNeighborIdx];
228
+ frame.nextNeighborIdx++;
87
229
  if (!visited.has(neighbor)) {
88
- dfs(neighbor);
230
+ visited.add(neighbor);
231
+ recursionStack.add(neighbor);
232
+ path.push(neighbor);
233
+ stack.push({
234
+ node: neighbor,
235
+ nextNeighborIdx: 0,
236
+ neighbors: adj.get(neighbor) ?? [],
237
+ });
89
238
  }
90
239
  else if (recursionStack.has(neighbor)) {
91
240
  const cycleStart = path.indexOf(neighbor);
@@ -93,12 +242,6 @@ function detectCircularRefs(edges) {
93
242
  cycles.push(cycle.join("→"));
94
243
  }
95
244
  }
96
- path.pop();
97
- recursionStack.delete(node);
98
- };
99
- for (const node of adj.keys()) {
100
- if (!visited.has(node))
101
- dfs(node);
102
245
  }
103
246
  return cycles;
104
247
  }
@@ -145,8 +288,164 @@ function buildBindingIndex(edges) {
145
288
  idx.set(key, new Set());
146
289
  idx.get(key).add(e.targetObject);
147
290
  }
291
+ for (const e of edges) {
292
+ if (e.edgeSource !== "potential")
293
+ continue;
294
+ if (!e.fieldName)
295
+ continue;
296
+ const key = `${e.sourceObject}#${e.fieldName}`;
297
+ if (!idx.has(key) || idx.get(key).size === 0) {
298
+ if (!idx.has(key))
299
+ idx.set(key, new Set());
300
+ idx.get(key).add(e.targetObject);
301
+ }
302
+ }
148
303
  return idx;
149
304
  }
305
+ function evaluateIndustryPattern(project, objects, objectCache, edges) {
306
+ const result = { strengths: [], findings: [], matched: false };
307
+ const industryName = project.industry;
308
+ if (!industryName || industryName === "general") {
309
+ return result;
310
+ }
311
+ let mode;
312
+ try {
313
+ mode = IndustryModeRegistry.Instance().getMode(industryName);
314
+ }
315
+ catch {
316
+ return result;
317
+ }
318
+ if (!mode)
319
+ return result;
320
+ const byType = new Map();
321
+ for (const obj of objects) {
322
+ const t = shortTypeName(obj.objectType);
323
+ if (!byType.has(t))
324
+ byType.set(t, []);
325
+ byType.get(t).push(obj);
326
+ }
327
+ const bindingIndex = buildBindingIndex(edges);
328
+ let matchCount = 0;
329
+ let totalChecks = 0;
330
+ const expectedNodes = mode.machine_shape;
331
+ if (expectedNodes.length > 0) {
332
+ totalChecks++;
333
+ const machines = byType.get("Machine") ?? [];
334
+ if (machines.length > 0) {
335
+ const machineObj = machines[0];
336
+ const cached = parseCacheData(objectCache.get(machineObj.objectAddress));
337
+ const nodeCount = getNumberField(cached, "node_count") || countArrayField(cached ?? {}, "nodes");
338
+ if (nodeCount > 0 && nodeCount >= expectedNodes.length) {
339
+ matchCount++;
340
+ result.strengths.push(`Industry pattern match: Machine has ${nodeCount} nodes, covering "${industryName}" mode's ${expectedNodes.length} expected node(s)`);
341
+ }
342
+ else if (nodeCount > 0) {
343
+ result.findings.push({
344
+ criterion: "industry_pattern",
345
+ severity: "info",
346
+ message: `Industry pattern: Machine has ${nodeCount} nodes, but "${industryName}" mode expects at least ${expectedNodes.length}`,
347
+ deduction: 0,
348
+ });
349
+ }
350
+ }
351
+ }
352
+ const expectedGuards = mode.guards;
353
+ if (expectedGuards.length > 0) {
354
+ totalChecks++;
355
+ const guards = byType.get("Guard") ?? [];
356
+ const minGuards = expectedGuards.length;
357
+ const maxGuards = expectedGuards.length * 2;
358
+ if (guards.length >= minGuards && guards.length <= maxGuards) {
359
+ matchCount++;
360
+ result.strengths.push(`Industry pattern match: ${guards.length} Guard(s) present, within "${industryName}" mode's expected range [${minGuards}-${maxGuards}]`);
361
+ }
362
+ else if (guards.length > 0 && guards.length < minGuards) {
363
+ result.findings.push({
364
+ criterion: "industry_pattern",
365
+ severity: "info",
366
+ message: `Industry pattern: ${guards.length} Guard(s) present, but "${industryName}" mode expects at least ${minGuards} (recommended range [${minGuards}-${maxGuards}])`,
367
+ deduction: 0,
368
+ });
369
+ }
370
+ else if (guards.length > maxGuards) {
371
+ matchCount++;
372
+ result.strengths.push(`Industry pattern match: ${guards.length} Guard(s) present, covering "${industryName}" mode's ${minGuards} expected guard(s)`);
373
+ result.findings.push({
374
+ criterion: "industry_pattern",
375
+ severity: "info",
376
+ message: `Industry pattern: ${guards.length} Guard(s) present, exceeds recommended max ${maxGuards}. Consider consolidating guards if some are redundant.`,
377
+ deduction: 0,
378
+ });
379
+ }
380
+ }
381
+ const expectedAllocStrategy = mode.allocator;
382
+ if (expectedAllocStrategy) {
383
+ totalChecks++;
384
+ const allocations = byType.get("Allocation") ?? [];
385
+ const services4Alloc = byType.get("Service") ?? [];
386
+ const serviceForAlloc = services4Alloc[0];
387
+ const hasOrderAllocators = serviceForAlloc
388
+ ? !!bindingIndex.get(`${serviceForAlloc.objectAddress}#order_allocators`)?.size
389
+ : false;
390
+ const expectsMultiple = mode.traits.multi_tier_allocation;
391
+ if (hasOrderAllocators) {
392
+ matchCount++;
393
+ if (allocations.length > 0) {
394
+ result.strengths.push(`Industry pattern match: Service.order_allocators bound + ${allocations.length} Allocation object(s) present (post-order) — matching "${industryName}" allocation pattern`);
395
+ }
396
+ else {
397
+ result.strengths.push(`Industry pattern match: Service.order_allocators template bound — matching "${industryName}" allocation pattern (Allocation objects created per-order)`);
398
+ }
399
+ }
400
+ else if (allocations.length > 0) {
401
+ matchCount++;
402
+ result.strengths.push(`Industry pattern match: ${allocations.length} Allocation object(s) present — matching "${industryName}" allocation pattern`);
403
+ }
404
+ else {
405
+ result.findings.push({
406
+ criterion: "industry_pattern",
407
+ severity: "info",
408
+ message: `Industry pattern: Service.order_allocators not bound and no Allocation objects — "${industryName}" mode expects ${expectsMultiple ? "multi-tier" : "single-tier"} allocation (Allocation objects are created per-order, so this is only a template-level gap)`,
409
+ deduction: 0,
410
+ });
411
+ }
412
+ }
413
+ const requireCompensationFund = mode.risk_constraints?.require_compensation_fund ?? false;
414
+ if (requireCompensationFund || mode.traits.deposit_required || mode.traits.trust_sensitivity !== "low") {
415
+ totalChecks++;
416
+ const treasuries = byType.get("Treasury") ?? [];
417
+ const services4Treas = byType.get("Service") ?? [];
418
+ const serviceForTreas = services4Treas[0];
419
+ const serviceDataForTreas = serviceForTreas
420
+ ? parseCacheData(objectCache.get(serviceForTreas.objectAddress))
421
+ : null;
422
+ const compensationBalance = serviceForTreas
423
+ ? getBalanceValue(serviceDataForTreas, "compensation_fund")
424
+ : 0;
425
+ if (treasuries.length > 0 || compensationBalance > 0) {
426
+ matchCount++;
427
+ const parts = [];
428
+ if (treasuries.length > 0)
429
+ parts.push(`${treasuries.length} Treasury object(s)`);
430
+ if (compensationBalance > 0)
431
+ parts.push(`compensation_fund balance ${compensationBalance}`);
432
+ result.strengths.push(`Industry pattern match: ${parts.join(" + ")} — matching "${industryName}" trust/deposit pattern`);
433
+ }
434
+ }
435
+ result.matched = totalChecks > 0 && matchCount / totalChecks >= 0.6;
436
+ if (result.matched) {
437
+ result.strengths.push(`Industry pattern: project structure matches "${industryName}" mode (${matchCount}/${totalChecks} checks passed)`);
438
+ }
439
+ else if (totalChecks > 0) {
440
+ result.findings.push({
441
+ criterion: "industry_pattern",
442
+ severity: "info",
443
+ message: `Industry pattern: project partially matches "${industryName}" mode (${matchCount}/${totalChecks} checks passed)`,
444
+ deduction: 0,
445
+ });
446
+ }
447
+ return result;
448
+ }
150
449
  function evaluateRisk(input) {
151
450
  const findings = [];
152
451
  const strengths = [];
@@ -162,19 +461,24 @@ function evaluateRisk(input) {
162
461
  const bindingIndex = buildBindingIndex(edges);
163
462
  let structuralScore = 100;
164
463
  const serviceObj = services[0];
464
+ const svcDataForStruct = serviceObj ? parseCacheData(objectCache.get(serviceObj.objectAddress)) : null;
465
+ const compensationBalanceForStruct = serviceObj ? getBalanceValue(svcDataForStruct, "compensation_fund") : 0;
165
466
  if (serviceObj) {
166
467
  for (const expected of CRITICAL_BINDINGS) {
167
468
  if (expected.sourceType !== "Service")
168
469
  continue;
470
+ const effectiveCritical = expected.fieldName === "arbitrations"
471
+ ? (compensationBalanceForStruct > 0 ? true : expected.critical)
472
+ : expected.critical;
169
473
  const key = `${serviceObj.objectAddress}#${expected.fieldName}`;
170
474
  const bindings = bindingIndex.get(key);
171
475
  if (!bindings || bindings.size === 0) {
172
- const deduction = expected.critical ? -25 : -10;
476
+ const deduction = effectiveCritical ? -25 : -10;
173
477
  structuralScore += deduction;
174
478
  findings.push({
175
479
  criterion: "structural_risk",
176
- severity: expected.critical ? "critical" : "warning",
177
- message: `Service missing ${expected.fieldName} binding (expected ${expected.targetType})`,
480
+ severity: effectiveCritical ? "critical" : "warning",
481
+ message: `Service missing ${expected.fieldName} binding (expected ${expected.targetType})${expected.fieldName === "arbitrations" ? (compensationBalanceForStruct > 0 ? " — required by contract when compensation_fund > 0 (service.move:494)" : " — optional when compensation_fund is 0") : ""}`,
178
482
  deduction,
179
483
  });
180
484
  }
@@ -195,27 +499,72 @@ function evaluateRisk(input) {
195
499
  structuralScore = clampScore(structuralScore);
196
500
  let fundScore = 100;
197
501
  const treasuries = byType.get("Treasury") ?? [];
198
- if (treasuries.length === 0) {
199
- fundScore -= 30;
200
- findings.push({
201
- criterion: "fund_safety",
202
- severity: "warning",
203
- message: "No Treasury object — no compensation fund for refunds",
204
- deduction: -30,
205
- });
206
- }
207
- else {
208
- strengths.push(`${treasuries.length} Treasury object(s) present`);
502
+ const serviceData = serviceObj ? parseCacheData(objectCache.get(serviceObj.objectAddress)) : null;
503
+ const compensationBalance = serviceObj ? getBalanceValue(serviceData, "compensation_fund") : 0;
504
+ let industryRequiresFund = true;
505
+ if (project.industry && project.industry !== "general") {
506
+ try {
507
+ const mode = IndustryModeRegistry.Instance().getMode(project.industry);
508
+ if (mode) {
509
+ industryRequiresFund = mode.risk_constraints?.require_compensation_fund ?? true;
510
+ }
511
+ }
512
+ catch { }
209
513
  }
210
- if (serviceObj) {
211
- const cfKey = `${serviceObj.objectAddress}#compensation_fund`;
212
- if (!bindingIndex.get(cfKey)?.size) {
213
- fundScore -= 20;
514
+ if (treasuries.length === 0 && compensationBalance === 0) {
515
+ if (industryRequiresFund) {
516
+ fundScore -= 30;
214
517
  findings.push({
215
518
  criterion: "fund_safety",
216
519
  severity: "warning",
217
- message: "Service compensation_fund not bound — buyer refunds unprotected",
218
- deduction: -20,
520
+ message: "No Treasury object and Service.compensation_fund is empty — no refund fund for buyers",
521
+ deduction: -30,
522
+ });
523
+ }
524
+ else {
525
+ fundScore -= 10;
526
+ findings.push({
527
+ criterion: "fund_safety",
528
+ severity: "info",
529
+ message: `No Treasury/compensation_fund — industry "${project.industry}" does not require refund fund (optional)`,
530
+ deduction: -10,
531
+ });
532
+ }
533
+ }
534
+ else {
535
+ if (treasuries.length > 0) {
536
+ strengths.push(`${treasuries.length} Treasury object(s) present — independent fund holder`);
537
+ }
538
+ if (compensationBalance > 0) {
539
+ strengths.push(`Service.compensation_fund has ${compensationBalance} units — inline refund fund active`);
540
+ const maxSalePrice = getMaxSalePrice(serviceData);
541
+ if (maxSalePrice > 0) {
542
+ const requiredThreshold = 5 * maxSalePrice;
543
+ if (compensationBalance < requiredThreshold) {
544
+ fundScore -= 10;
545
+ findings.push({
546
+ criterion: "fund_safety",
547
+ severity: "warning",
548
+ message: `Service.compensation_fund balance (${compensationBalance}) is less than 5× 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.`,
549
+ deduction: -10,
550
+ });
551
+ }
552
+ else {
553
+ findings.push({
554
+ criterion: "fund_safety",
555
+ severity: "info",
556
+ message: `Service.compensation_fund balance (${compensationBalance}) covers 5× the max order amount (${maxSalePrice}). Fund is sufficient for refund protection.`,
557
+ deduction: 0,
558
+ });
559
+ }
560
+ }
561
+ }
562
+ else {
563
+ findings.push({
564
+ criterion: "fund_safety",
565
+ severity: "info",
566
+ message: "Treasury present but Service.compensation_fund balance is 0 — consider depositing refund fund",
567
+ deduction: -5,
219
568
  });
220
569
  }
221
570
  }
@@ -274,18 +623,27 @@ function evaluateRisk(input) {
274
623
  if (serviceObj) {
275
624
  const data = parseCacheData(objectCache.get(serviceObj.objectAddress));
276
625
  if (data && !isAddress(data.um)) {
277
- governanceScore -= 15;
626
+ governanceScore -= 5;
278
627
  findings.push({
279
628
  criterion: "governance_risk",
280
- severity: "warning",
281
- message: "Service has no UM (manager) — cannot be managed on-chain",
282
- deduction: -15,
629
+ severity: "info",
630
+ message: "Service has no UM (manager) — UM is optional; set via um_set if management delegation needed",
631
+ deduction: -5,
283
632
  });
284
633
  }
285
634
  }
286
635
  governanceScore = clampScore(governanceScore);
287
636
  let coherenceScore = 100;
288
- const objectAddresses = new Set(objects.map(o => o.objectAddress));
637
+ const objectAddresses = new Set();
638
+ for (const o of objects) {
639
+ if (o.objectAddress)
640
+ objectAddresses.add(o.objectAddress);
641
+ if (o.objectName) {
642
+ objectAddresses.add(o.objectName);
643
+ const shortType = shortTypeName(o.objectType).toLowerCase();
644
+ objectAddresses.add(`${shortType}:${o.objectName}`);
645
+ }
646
+ }
289
647
  let danglingCount = 0;
290
648
  for (const e of edges) {
291
649
  if (e.edgeSource === "potential")
@@ -423,15 +781,10 @@ function evaluateTrust(input) {
423
781
  const bgKey = `${services[0].objectAddress}#buy_guard`;
424
782
  if (bindingIndex.get(bgKey)?.size) {
425
783
  guardScore = clampScore(guardScore + 15);
426
- strengths.push("Service has buy_guard — purchase validation active");
784
+ strengths.push("Service has buy_guard bound — purchase validation active");
427
785
  }
428
- else {
429
- findings.push({
430
- criterion: "guard_quality",
431
- severity: "warning",
432
- message: "Service buy_guard not bound — unvalidated purchases",
433
- deduction: -15,
434
- });
786
+ else if (guards.length > 0) {
787
+ strengths.push("Guard objects present (buy_guard binding optional)");
435
788
  }
436
789
  }
437
790
  guardScore = clampScore(guardScore);
@@ -491,14 +844,16 @@ function evaluateTrust(input) {
491
844
  case "E3":
492
845
  passed = (byType.get("Machine") ?? []).some(m => {
493
846
  const d = parseCacheData(objectCache.get(m.objectAddress));
494
- return d && (countArrayField(d, "nodes") > 0);
847
+ return d && (getNumberField(d, "node_count") > 0 || countArrayField(d, "nodes") > 0);
495
848
  });
496
849
  break;
497
850
  case "E4":
498
- passed = !!bindingIndex2.get(`${serviceObj2.objectAddress}#buy_guard`)?.size;
851
+ passed = !!bindingIndex2.get(`${serviceObj2.objectAddress}#buy_guard`)?.size
852
+ || (byType.get("Guard") ?? []).length > 0;
499
853
  break;
500
854
  case "E5":
501
- passed = !!bindingIndex2.get(`${serviceObj2.objectAddress}#compensation_fund`)?.size;
855
+ passed = getBalanceValue(svcData, "compensation_fund") > 0
856
+ || (byType.get("Treasury") ?? []).length > 0;
502
857
  break;
503
858
  case "E6":
504
859
  passed = (byType.get("Arbitration") ?? []).length > 0;
@@ -524,20 +879,32 @@ function evaluateTrust(input) {
524
879
  passed = !!rep && rep.likes >= rep.dislikes;
525
880
  }
526
881
  break;
527
- case "E13":
528
- passed = true;
529
- break;
530
882
  }
531
883
  if (passed) {
532
884
  diligencePassed.push(check.id);
533
885
  }
534
886
  else {
535
- diligenceScore += check.deduction;
887
+ let effectiveDeduction = check.deduction;
888
+ let effectiveSeverity = check.severity;
889
+ if (check.id === "E5" && project.industry && project.industry !== "general") {
890
+ try {
891
+ const mode = IndustryModeRegistry.Instance().getMode(project.industry);
892
+ if (mode && mode.risk_constraints?.require_compensation_fund === false) {
893
+ effectiveDeduction = -3;
894
+ effectiveSeverity = "info";
895
+ }
896
+ }
897
+ catch { }
898
+ }
899
+ diligenceScore += effectiveDeduction;
900
+ const detailSuffix = check.id === "E5" && effectiveDeduction !== check.deduction
901
+ ? " (industry does not require compensation_fund — reduced deduction)"
902
+ : "";
536
903
  findings.push({
537
904
  criterion: "consumer_diligence",
538
- severity: check.severity,
539
- message: `${check.id}: ${check.check} — FAILED`,
540
- deduction: check.deduction,
905
+ severity: effectiveSeverity,
906
+ message: `${check.id}: ${check.check} — FAIL: condition not met${detailSuffix} [severity: ${effectiveSeverity}]`,
907
+ deduction: effectiveDeduction,
541
908
  });
542
909
  }
543
910
  }
@@ -592,7 +959,12 @@ function evaluateCompleteness(input) {
592
959
  }
593
960
  const services = byType.get("Service") ?? [];
594
961
  const bindingIndex = buildBindingIndex(edges);
595
- const requiredItems = MERCHANT_REQUIRED_ITEMS;
962
+ const svcObjForRequiredItems = services[0];
963
+ const svcDataForRequiredItems = svcObjForRequiredItems
964
+ ? parseCacheData(objectCache.get(svcObjForRequiredItems.objectAddress))
965
+ : null;
966
+ const compensationBalanceForItems = getBalanceValue(svcDataForRequiredItems, "compensation_fund");
967
+ const requiredItems = resolveRequiredItems(project.industry ?? undefined, compensationBalanceForItems);
596
968
  const requiredCount = requiredItems.filter(r => r.required).length;
597
969
  const optionalItems = requiredItems.filter(r => !r.required);
598
970
  let requiredMet = 0;
@@ -650,23 +1022,28 @@ function evaluateCompleteness(input) {
650
1022
  let bindingScore = 100;
651
1023
  if (services[0]) {
652
1024
  const serviceAddr = services[0].objectAddress;
1025
+ const svcDataForBind = parseCacheData(objectCache.get(serviceAddr));
1026
+ const compensationBalanceForBind = getBalanceValue(svcDataForBind, "compensation_fund");
653
1027
  let boundCount = 0;
654
1028
  let totalCount = 0;
655
1029
  for (const expected of CRITICAL_BINDINGS) {
656
1030
  if (expected.sourceType !== "Service")
657
1031
  continue;
658
1032
  totalCount++;
1033
+ const effectiveCritical = expected.fieldName === "arbitrations"
1034
+ ? (compensationBalanceForBind > 0 ? true : expected.critical)
1035
+ : expected.critical;
659
1036
  const key = `${serviceAddr}#${expected.fieldName}`;
660
1037
  if (bindingIndex.get(key)?.size) {
661
1038
  boundCount++;
662
1039
  }
663
1040
  else {
664
- const deduction = expected.critical ? -20 : -8;
1041
+ const deduction = effectiveCritical ? -20 : -8;
665
1042
  bindingScore += deduction;
666
1043
  findings.push({
667
1044
  criterion: "binding_completeness",
668
- severity: expected.critical ? "critical" : "warning",
669
- message: `Service.${expected.fieldName} not bound (expected ${expected.targetType})`,
1045
+ severity: effectiveCritical ? "critical" : "warning",
1046
+ message: `Service.${expected.fieldName} not bound (expected ${expected.targetType})${expected.fieldName === "arbitrations" ? (compensationBalanceForBind > 0 ? " — required by contract when compensation_fund > 0" : " — optional when compensation_fund is 0") : ""}`,
670
1047
  deduction,
671
1048
  });
672
1049
  }
@@ -688,19 +1065,19 @@ function evaluateCompleteness(input) {
688
1065
  let workflowScore = 80;
689
1066
  const machines = byType.get("Machine") ?? [];
690
1067
  if (machines.length === 0) {
691
- workflowScore -= 30;
1068
+ workflowScore -= 20;
692
1069
  findings.push({
693
1070
  criterion: "workflow_rationality",
694
- severity: "warning",
695
- message: "No Machine object — no workflow defined",
696
- deduction: -30,
1071
+ severity: "info",
1072
+ message: "No Machine object — bind one before publishing (deploy-time requirement)",
1073
+ deduction: -20,
697
1074
  });
698
1075
  }
699
1076
  else {
700
1077
  for (const m of machines) {
701
1078
  const data = parseCacheData(objectCache.get(m.objectAddress));
702
1079
  if (data) {
703
- const nodeCount = countArrayField(data, "nodes") || countArrayField(data, "node_count");
1080
+ const nodeCount = getNumberField(data, "node_count") || countArrayField(data, "nodes");
704
1081
  if (nodeCount > 0) {
705
1082
  strengths.push(`Machine has ${nodeCount} node(s)`);
706
1083
  }
@@ -716,7 +1093,16 @@ function evaluateCompleteness(input) {
716
1093
  }
717
1094
  }
718
1095
  }
719
- const objectAddresses = new Set(objects.map(o => o.objectAddress));
1096
+ const objectAddresses = new Set();
1097
+ for (const o of objects) {
1098
+ if (o.objectAddress)
1099
+ objectAddresses.add(o.objectAddress);
1100
+ if (o.objectName) {
1101
+ objectAddresses.add(o.objectName);
1102
+ const shortType = shortTypeName(o.objectType).toLowerCase();
1103
+ objectAddresses.add(`${shortType}:${o.objectName}`);
1104
+ }
1105
+ }
720
1106
  let danglingCount = 0;
721
1107
  for (const e of edges) {
722
1108
  if (e.edgeSource === "potential")
@@ -742,10 +1128,26 @@ function evaluateCompleteness(input) {
742
1128
  if (published) {
743
1129
  strengths.push("Service already published — deployment complete");
744
1130
  readinessScore = 100;
1131
+ const machineAddr = data.machine;
1132
+ if (typeof machineAddr === "string" && machineAddr.startsWith("0x")) {
1133
+ const machineData = parseCacheData(objectCache.get(machineAddr));
1134
+ if (machineData && machineData.bPublished === false) {
1135
+ readinessScore -= 10;
1136
+ findings.push({
1137
+ criterion: "deployment_readiness",
1138
+ severity: "info",
1139
+ message: `Bound Machine ${machineAddr.slice(0, 8)} is not published — order_progress will fail (machine.move E_NOT_PUBLISHED)`,
1140
+ deduction: -10,
1141
+ });
1142
+ }
1143
+ }
745
1144
  }
746
1145
  else {
747
1146
  const hasMachine = bindingIndex.get(`${services[0].objectAddress}#machine`)?.size;
748
1147
  const hasPermission = bindingIndex.get(`${services[0].objectAddress}#permission`)?.size;
1148
+ const hasOrderAllocators = bindingIndex.get(`${services[0].objectAddress}#order_allocators`)?.size;
1149
+ const compensationBalanceForReady = getBalanceValue(data, "compensation_fund");
1150
+ const hasArbitrations = bindingIndex.get(`${services[0].objectAddress}#arbitrations`)?.size;
749
1151
  if (!hasMachine) {
750
1152
  readinessScore -= 30;
751
1153
  findings.push({
@@ -764,8 +1166,31 @@ function evaluateCompleteness(input) {
764
1166
  deduction: -30,
765
1167
  });
766
1168
  }
767
- if (hasMachine && hasPermission) {
768
- strengths.push("Service ready to publish (Machine + Permission bound)");
1169
+ if (!hasOrderAllocators) {
1170
+ readinessScore -= 30;
1171
+ findings.push({
1172
+ criterion: "deployment_readiness",
1173
+ severity: "critical",
1174
+ message: "Service has no order_allocators — cannot publish (service.move:493 E_NO_ALLOCATOR)",
1175
+ deduction: -30,
1176
+ });
1177
+ }
1178
+ if (compensationBalanceForReady > 0 && !hasArbitrations) {
1179
+ readinessScore -= 25;
1180
+ findings.push({
1181
+ criterion: "deployment_readiness",
1182
+ severity: "critical",
1183
+ message: `Service has compensation_fund (${compensationBalanceForReady}) but no arbitrations — cannot publish (service.move:495 E_ARBITRATION_NOT_SET_WITH_COMPENSATION_FUND)`,
1184
+ deduction: -25,
1185
+ });
1186
+ }
1187
+ if (hasMachine && hasPermission && hasOrderAllocators) {
1188
+ if (compensationBalanceForReady > 0 && hasArbitrations) {
1189
+ strengths.push("Service ready to publish (Machine + Permission + order_allocators + arbitrations bound)");
1190
+ }
1191
+ else if (compensationBalanceForReady === 0) {
1192
+ strengths.push("Service ready to publish (Machine + Permission + order_allocators bound; arbitrations optional when compensation_fund is 0)");
1193
+ }
769
1194
  }
770
1195
  }
771
1196
  }
@@ -788,6 +1213,9 @@ function evaluateCompleteness(input) {
788
1213
  : overall >= 80
789
1214
  ? `Complete project (score ${overall}/100). Ready for deployment.`
790
1215
  : `Partially complete (score ${overall}/100). ${findings.length} gap(s) to address.`;
1216
+ const industryPattern = evaluateIndustryPattern(project, objects, objectCache, edges);
1217
+ strengths.push(...industryPattern.strengths);
1218
+ findings.push(...industryPattern.findings);
791
1219
  return {
792
1220
  evaluationType: "completeness",
793
1221
  score: overall,
@@ -799,7 +1227,7 @@ function evaluateCompleteness(input) {
799
1227
  evaluatedAt: Date.now(),
800
1228
  };
801
1229
  }
802
- function evaluateWorthBuyingStub(input, llmPrompt) {
1230
+ function evaluateWorthBuyingStub(_input, llmPrompt) {
803
1231
  return {
804
1232
  evaluationType: "worth_buying",
805
1233
  score: 0,
@@ -812,7 +1240,7 @@ function evaluateWorthBuyingStub(input, llmPrompt) {
812
1240
  evaluatedAt: Date.now(),
813
1241
  };
814
1242
  }
815
- function evaluateValueStub(input, llmPrompt) {
1243
+ function evaluateValueStub(_input, llmPrompt) {
816
1244
  return {
817
1245
  evaluationType: "value",
818
1246
  score: 0,
@@ -826,21 +1254,78 @@ function evaluateValueStub(input, llmPrompt) {
826
1254
  };
827
1255
  }
828
1256
  export function runEvaluation(input, evaluationType, llmPrompt) {
1257
+ const filtered = filterTemplateObjects(input);
829
1258
  switch (evaluationType) {
830
1259
  case "risk":
831
- return evaluateRisk(input);
1260
+ return evaluateRisk(filtered);
832
1261
  case "trust":
833
- return evaluateTrust(input);
1262
+ return evaluateTrust(filtered);
834
1263
  case "completeness":
835
- return evaluateCompleteness(input);
1264
+ return evaluateCompleteness(filtered);
836
1265
  case "worth_buying":
837
- return evaluateWorthBuyingStub(input, llmPrompt);
1266
+ return evaluateWorthBuyingStub(filtered, llmPrompt);
838
1267
  case "value":
839
- return evaluateValueStub(input, llmPrompt);
1268
+ return evaluateValueStub(filtered, llmPrompt);
840
1269
  default:
841
1270
  throw new Error(`Unknown evaluation type: ${evaluationType}`);
842
1271
  }
843
1272
  }
1273
+ function filterTemplateObjects(input) {
1274
+ const isDraftAddr = (addr) => {
1275
+ if (!addr)
1276
+ return true;
1277
+ return addr.startsWith("draft:");
1278
+ };
1279
+ const isDraftObject = (o) => {
1280
+ if (isDraftAddr(o.objectAddress))
1281
+ return true;
1282
+ const meta = o.metadata;
1283
+ return !!(meta && meta.status === "draft");
1284
+ };
1285
+ const draftObjects = [];
1286
+ const realObjects = [];
1287
+ for (const o of input.objects) {
1288
+ if (isDraftObject(o)) {
1289
+ draftObjects.push(o);
1290
+ }
1291
+ else {
1292
+ realObjects.push(o);
1293
+ }
1294
+ }
1295
+ const realIds = new Set();
1296
+ for (const o of realObjects) {
1297
+ if (o.objectAddress)
1298
+ realIds.add(o.objectAddress);
1299
+ if (o.objectName) {
1300
+ realIds.add(o.objectName);
1301
+ const shortType = shortTypeName(o.objectType).toLowerCase();
1302
+ realIds.add(`${shortType}:${o.objectName}`);
1303
+ }
1304
+ }
1305
+ const draftIds = new Set();
1306
+ for (const o of draftObjects) {
1307
+ if (o.objectAddress)
1308
+ draftIds.add(o.objectAddress);
1309
+ if (o.objectName) {
1310
+ draftIds.add(o.objectName);
1311
+ const shortType = shortTypeName(o.objectType).toLowerCase();
1312
+ draftIds.add(`${shortType}:${o.objectName}`);
1313
+ }
1314
+ }
1315
+ const realEdges = input.edges.filter((e) => {
1316
+ const meta = e.metadata;
1317
+ if (meta && meta.blueprint === true)
1318
+ return false;
1319
+ const sourceIsDraft = isDraftAddr(e.sourceObject) || draftIds.has(e.sourceObject);
1320
+ const targetIsDraft = isDraftAddr(e.targetObject) || draftIds.has(e.targetObject);
1321
+ return !sourceIsDraft && !targetIsDraft;
1322
+ });
1323
+ return {
1324
+ ...input,
1325
+ objects: realObjects,
1326
+ edges: realEdges,
1327
+ };
1328
+ }
844
1329
  export function compareProjects(entries, evaluationType) {
845
1330
  const ranking = [...entries].sort((a, b) => {
846
1331
  if (a.score === null && b.score === null)