@wowok/agent-mcp 3.0.6 → 3.1.2

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 (111) hide show
  1. package/dist/evaluation/arbitration-game.js +1 -1
  2. package/dist/evaluation/location-match.js +1 -1
  3. package/dist/goal/GoalClassifier.js +1 -1
  4. package/dist/graph/onchain/analyze.d.ts +3 -3
  5. package/dist/graph/onchain/analyze.js +1 -1
  6. package/dist/graph/onchain/analyze.spec.js +1 -1
  7. package/dist/graph/onchain/edge-schema.d.ts +1 -1
  8. package/dist/graph/onchain/edge-schema.js +1 -1
  9. package/dist/graph/onchain/interest.js +1 -1
  10. package/dist/graph/onchain/sdk-dataplane.js +1 -1
  11. package/dist/graph/onchain/types.d.ts +5 -5
  12. package/dist/harness/verify.js +1 -1
  13. package/dist/index.js +1 -1
  14. package/dist/knowledge/allocation-ledger.d.ts +2 -0
  15. package/dist/knowledge/allocation-ledger.js +1 -1
  16. package/dist/knowledge/allocation-puzzle.js +1 -1
  17. package/dist/knowledge/allocation-risk.d.ts +2 -1
  18. package/dist/knowledge/allocation-risk.js +1 -1
  19. package/dist/knowledge/guard-design-patterns.js +1 -1
  20. package/dist/knowledge/guard-field-cognition.d.ts +48 -0
  21. package/dist/knowledge/guard-field-cognition.js +1 -0
  22. package/dist/knowledge/index.d.ts +1 -0
  23. package/dist/knowledge/index.js +1 -1
  24. package/dist/knowledge/industry-registry.js +1 -1
  25. package/dist/knowledge/industry-strategy.js +1 -1
  26. package/dist/knowledge/jsonrpc-enum.js +1 -1
  27. package/dist/knowledge/recipient-constraint.d.ts +6 -1
  28. package/dist/knowledge/recipient-constraint.js +1 -1
  29. package/dist/knowledge/service-allocator-audit-node.d.ts +3 -0
  30. package/dist/knowledge/service-allocator-audit-node.js +1 -0
  31. package/dist/knowledge/service-risk-node.js +1 -1
  32. package/dist/knowledge/template-registry.js +1 -1
  33. package/dist/knowledge/workflow-guidance.d.ts +2 -0
  34. package/dist/knowledge/workflow-guidance.js +1 -1
  35. package/dist/monitor/MonitorLoop.js +1 -1
  36. package/dist/persona/strategy-intent.js +1 -1
  37. package/dist/playbooks/service-build/business-puzzle.js +1 -1
  38. package/dist/playbooks/service-build/intent-analyzer.js +1 -1
  39. package/dist/playbooks/service-build/object-panorama.js +1 -1
  40. package/dist/playbooks/service-build/risk-aggregator.js +1 -1
  41. package/dist/playbooks/service-build/topology-query.js +1 -1
  42. package/dist/safety/confirm-gate.js +1 -1
  43. package/dist/safety/preview.js +1 -1
  44. package/dist/schema/call/base.js +1 -1
  45. package/dist/schema/call/handler.js +1 -1
  46. package/dist/schema/call/semantic.js +1 -1
  47. package/dist/schema/call/service.d.ts +6 -6
  48. package/dist/schema/common/index.js +1 -1
  49. package/dist/schema/evaluation/index.js +1 -1
  50. package/dist/schema/local/index.js +1 -1
  51. package/dist/schema/operations.d.ts +4 -2
  52. package/dist/schema/operations.js +1 -1
  53. package/dist/schema/query/bi.d.ts +16 -14
  54. package/dist/schema/query/bi.js +1 -1
  55. package/dist/schema/query/index.d.ts +10 -10
  56. package/dist/schema/query/index.js +1 -1
  57. package/dist/schema/schema-version.js +1 -1
  58. package/dist/schema-query-impl/index.js +1 -1
  59. package/dist/schemas/account_operation.output.json +9 -9
  60. package/dist/schemas/account_operation.schema.json +3 -3
  61. package/dist/schemas/bridge_operation.output.json +9 -9
  62. package/dist/schemas/bridge_operation.schema.json +4 -4
  63. package/dist/schemas/evaluation_operation.output.json +6 -6
  64. package/dist/schemas/evaluation_operation.schema.json +5 -5
  65. package/dist/schemas/guard2file.schema.json +1 -1
  66. package/dist/schemas/index.json +1 -1
  67. package/dist/schemas/keeper_operation.output.json +9 -9
  68. package/dist/schemas/local_history_operation.output.json +9 -9
  69. package/dist/schemas/local_history_operation.schema.json +1 -1
  70. package/dist/schemas/local_info_operation.output.json +9 -9
  71. package/dist/schemas/local_mark_operation.output.json +9 -9
  72. package/dist/schemas/machineNode2file.schema.json +1 -1
  73. package/dist/schemas/messenger_operation.output.json +9 -9
  74. package/dist/schemas/monitor_events.output.json +9 -9
  75. package/dist/schemas/monitor_subscription.output.json +9 -9
  76. package/dist/schemas/onchain_events.output.json +10 -10
  77. package/dist/schemas/onchain_operations.output.json +9 -9
  78. package/dist/schemas/onchain_operations.schema.json +70 -72
  79. package/dist/schemas/onchain_operations_allocation.schema.json +6 -6
  80. package/dist/schemas/onchain_operations_arbitration.schema.json +4 -4
  81. package/dist/schemas/onchain_operations_contact.schema.json +3 -3
  82. package/dist/schemas/onchain_operations_demand.schema.json +3 -3
  83. package/dist/schemas/onchain_operations_gen_passport.schema.json +1 -1
  84. package/dist/schemas/onchain_operations_gen_proof.schema.json +1 -1
  85. package/dist/schemas/onchain_operations_guard.schema.json +2 -2
  86. package/dist/schemas/onchain_operations_machine.schema.json +5 -5
  87. package/dist/schemas/onchain_operations_order.schema.json +3 -3
  88. package/dist/schemas/onchain_operations_payment.schema.json +3 -3
  89. package/dist/schemas/onchain_operations_permission.schema.json +3 -3
  90. package/dist/schemas/onchain_operations_personal.schema.json +1 -1
  91. package/dist/schemas/onchain_operations_progress.schema.json +3 -3
  92. package/dist/schemas/onchain_operations_proof.schema.json +1 -1
  93. package/dist/schemas/onchain_operations_repository.schema.json +3 -3
  94. package/dist/schemas/onchain_operations_reward.schema.json +7 -7
  95. package/dist/schemas/onchain_operations_service.schema.json +12 -14
  96. package/dist/schemas/onchain_operations_treasury.schema.json +9 -9
  97. package/dist/schemas/onchain_table_data.output.json +17 -13
  98. package/dist/schemas/query_toolkit.output.json +50 -52
  99. package/dist/schemas/query_toolkit.schema.json +6 -2
  100. package/dist/strategy/collectors.js +1 -1
  101. package/dist/task/playbook.js +1 -1
  102. package/dist/tools/handlers/config.js +1 -1
  103. package/dist/tools/handlers/evaluation.spec.js +1 -1
  104. package/dist/tools/handlers/onchain.js +1 -1
  105. package/dist/tools/handlers/query.js +1 -1
  106. package/dist/tools/index.js +1 -1
  107. package/dist/tools/registry/monitor.js +1 -1
  108. package/dist/tools/registry/query.js +1 -1
  109. package/dist/tools/shared.js +1 -1
  110. package/dist/tools/wrap.js +1 -1
  111. package/package.json +2 -2
@@ -1 +1 @@
1
- import{appetiteMultiplier}from'./game-strategy.js';const ARB_ROLE_INTERESTS={'arbitrator':{'prefer':['case_advanced','fees_received','case_closed'],'avoid':['case_extended'],'sensitivity':0x1},'customer':{'prefer':['reversal_chance','case_closed'],'avoid':['adverse_ruling','case_extended'],'sensitivity':0x1},'merchant':{'prefer':['case_closed','fees_received'],'avoid':['adverse_ruling','reversal_chance','case_extended'],'sensitivity':0x1}},ARB_MOVE_SEMANTICS={'Principal_confirming':[{'action':'principal_confirm','perspective':'customer','gain':['case_advanced'],'risk':[],'payoff':'confirm\x20the\x20proposition\x20to\x20move\x20to\x20arbitrator\x20confirmation','base_risk':'low'},{'action':'proposition_change','perspective':'customer','gain':[],'risk':['case_extended'],'payoff':'modify\x20the\x20proposition\x20before\x20confirming\x20(extends\x20the\x20case)','base_risk':'medium'}],'Arbitrator_confirming':[{'action':'confirm','perspective':'arbitrator','gain':['case_advanced'],'risk':[],'payoff':'confirm\x20to\x20open\x20voting','base_risk':'low'},{'action':'reset','perspective':'arbitrator','gain':[],'risk':['case_extended'],'payoff':'reset\x20back\x20to\x20principal\x20confirmation\x20(extends\x20the\x20case)','base_risk':'high'}],'Voting':[{'action':'vote','perspective':'arbitrator','gain':['case_advanced'],'risk':[],'payoff':'vote\x20before\x20the\x20deadline','base_risk':'low'}],'Arbitrated':[{'action':'objection','perspective':'customer','gain':['reversal_chance'],'risk':[],'payoff':'object\x20the\x20ruling\x20(only\x20window\x20to\x20overturn)','base_risk':'medium'},{'action':'accept','perspective':'customer','gain':['case_closed'],'risk':['adverse_ruling'],'payoff':'accept\x20and\x20await\x20compensation','base_risk':'low'}],'Objectionable':[{'action':'reset','perspective':'arbitrator','gain':['case_advanced'],'risk':['case_extended'],'payoff':'reset\x20to\x20re-review\x20(extends\x20the\x20case)','base_risk':'medium'}],'Finished':[{'action':'arb_withdraw','perspective':'all','gain':['fees_received','case_closed'],'risk':[],'payoff':'withdraw\x20fees\x20/\x20compensation','base_risk':'low'}],'Withdrawn':[{'action':'done','perspective':'all','gain':['case_closed'],'risk':[],'payoff':'case\x20closed','base_risk':'low'}]};function dedupe(a){return Array['from'](new Set(a));}function resolveArbInterests(a,b){const c=ARB_ROLE_INTERESTS[a],d=c['sensitivity']*appetiteMultiplier(b?.['risk_appetite']),e=[...c['prefer']],f=[...c['avoid']];for(const g of b?.['requirements']??[]){const h=g['toLowerCase'](),i=/forbid|never|\bno\b/['test'](h);if(h['includes']('arbitration')&&i)f['push']('case_extended');if(h['includes']('refund')&&!i)e['push']('reversal_chance');if(h['includes']('prolong')||h['includes']('delay')||h['includes']('拖延'))f['push']('case_extended');}return{'prefer':dedupe(e),'avoid':dedupe(f),'sensitivity':d};}function scoreMove(a,b,c){const d=resolveArbInterests(b,c),e=a['gain']['filter'](j=>d['prefer']['includes'](j)),f=a['risk']['filter'](j=>d['avoid']['includes'](j)),g=e['length']*0x14,h=Math['round'](f['length']*0x19*d['sensitivity']),i=Math['max'](0x0,Math['min'](0x64,0x3c+g-h));return{'favorability':i,'gain_score':g,'risk_score':h};}export function evaluateArbGame(a,b,c){const d=ARB_MOVE_SEMANTICS[a]??[],e=d['filter'](g=>g['perspective']==='all'||g['perspective']===b),f=e['map'](g=>{const h=scoreMove(g,b,c);return{'action':g['action'],'favorability':h['favorability'],'gain_score':h['gain_score'],'risk_score':h['risk_score'],'is_optimal':![],'payoff_note':g['payoff'],'risk':g['base_risk']};})['sort']((g,h)=>h['favorability']-g['favorability']);return f['length']>0x0&&(f[0x0]['is_optimal']=!![]),{'status':a,'perspective':b,'actions':f,'summary':f['length']===0x0?'No\x20recommended\x20moves\x20for\x20'+b+'\x20in\x20status\x20\x27'+a+'\x27':'Optimal\x20for\x20'+b+'\x20in\x20\x27'+a+'\x27:\x20\x27'+f[0x0]['action']+'\x27\x20('+f[0x0]['payoff_note']+')'};}
1
+ import{appetiteMultiplier}from'./game-strategy.js';const ARB_ROLE_INTERESTS={'arbitrator':{'prefer':['case_advanced','fees_received','case_closed'],'avoid':['case_extended'],'sensitivity':0x1},'customer':{'prefer':['reversal_chance','case_closed'],'avoid':['adverse_ruling','case_extended'],'sensitivity':0x1},'merchant':{'prefer':['case_closed','fees_received'],'avoid':['adverse_ruling','reversal_chance','case_extended'],'sensitivity':0x1}},ARB_MOVE_SEMANTICS={'Principal_confirming':[{'action':'principal_confirm','perspective':'customer','gain':['case_advanced'],'risk':[],'payoff':'confirm\x20the\x20proposition\x20to\x20move\x20to\x20arbitrator\x20confirmation','base_risk':'low'},{'action':'proposition_change','perspective':'customer','gain':[],'risk':['case_extended'],'payoff':'modify\x20the\x20proposition\x20before\x20confirming\x20(extends\x20the\x20case)','base_risk':'medium'}],'Arbitrator_confirming':[{'action':'confirm','perspective':'arbitrator','gain':['case_advanced'],'risk':[],'payoff':'confirm\x20to\x20open\x20voting','base_risk':'low'},{'action':'reset','perspective':'arbitrator','gain':[],'risk':['case_extended'],'payoff':'reset\x20back\x20to\x20principal\x20confirmation\x20(extends\x20the\x20case)','base_risk':'high'}],'Voting':[{'action':'vote','perspective':'arbitrator','gain':['case_advanced'],'risk':[],'payoff':'vote\x20before\x20the\x20deadline','base_risk':'low'}],'Arbitrated':[{'action':'objection','perspective':'customer','gain':['reversal_chance'],'risk':[],'payoff':'object\x20the\x20ruling\x20(only\x20window\x20to\x20overturn)','base_risk':'medium'},{'action':'accept','perspective':'customer','gain':['case_closed'],'risk':['adverse_ruling'],'payoff':'accept\x20and\x20await\x20compensation','base_risk':'low'}],'Objectionable':[{'action':'reset','perspective':'arbitrator','gain':['case_advanced'],'risk':['case_extended'],'payoff':'reset\x20to\x20re-review\x20(extends\x20the\x20case)','base_risk':'medium'}],'Finished':[{'action':'arb_withdraw','perspective':'all','gain':['fees_received','case_closed'],'risk':[],'payoff':'withdraw\x20fees\x20/\x20compensation','base_risk':'low'}],'Withdrawn':[{'action':'done','perspective':'all','gain':['case_closed'],'risk':[],'payoff':'case\x20closed','base_risk':'low'}]};function dedupe(a){return Array['from'](new Set(a));}function resolveArbInterests(a,b){const c=ARB_ROLE_INTERESTS[a],d=c['sensitivity']*appetiteMultiplier(b?.['risk_appetite']),e=[...c['prefer']],f=[...c['avoid']];for(const g of b?.['requirements']??[]){const h=g['toLowerCase'](),i=/forbid|never|\bno\b/['test'](h);if(h['includes']('arbitration')&&i)f['push']('case_extended');if(h['includes']('refund')&&!i)e['push']('reversal_chance');if(h['includes']('prolong')||h['includes']('delay'))f['push']('case_extended');}return{'prefer':dedupe(e),'avoid':dedupe(f),'sensitivity':d};}function scoreMove(a,b,c){const d=resolveArbInterests(b,c),e=a['gain']['filter'](j=>d['prefer']['includes'](j)),f=a['risk']['filter'](j=>d['avoid']['includes'](j)),g=e['length']*0x14,h=Math['round'](f['length']*0x19*d['sensitivity']),i=Math['max'](0x0,Math['min'](0x64,0x3c+g-h));return{'favorability':i,'gain_score':g,'risk_score':h};}export function evaluateArbGame(a,b,c){const d=ARB_MOVE_SEMANTICS[a]??[],e=d['filter'](g=>g['perspective']==='all'||g['perspective']===b),f=e['map'](g=>{const h=scoreMove(g,b,c);return{'action':g['action'],'favorability':h['favorability'],'gain_score':h['gain_score'],'risk_score':h['risk_score'],'is_optimal':![],'payoff_note':g['payoff'],'risk':g['base_risk']};})['sort']((g,h)=>h['favorability']-g['favorability']);return f['length']>0x0&&(f[0x0]['is_optimal']=!![]),{'status':a,'perspective':b,'actions':f,'summary':f['length']===0x0?'No\x20recommended\x20moves\x20for\x20'+b+'\x20in\x20status\x20\x27'+a+'\x27':'Optimal\x20for\x20'+b+'\x20in\x20\x27'+a+'\x27:\x20\x27'+f[0x0]['action']+'\x27\x20('+f[0x0]['payoff_note']+')'};}
@@ -1 +1 @@
1
- import{parseRegion,relateRegion}from'./region.js';function toRegion(a){if(a===undefined)return parseRegion('');if(typeof a==='string')return parseRegion(a);const b=parseRegion(a['raw']);return{...b,'country':a['country']??b['country'],'province':a['province']??b['province'],'city':a['city']??b['city']};}export function gateLocation(a,b,c){const d=toRegion(b),e=toRegion(c);if(!d['raw']?.['trim']())return{'relation':'mismatch','satisfied':a!=='strict','score':0.5,'reason':'No\x20demand-side\x20location\x20stated\x20—\x20location\x20is\x20not\x20discriminating;\x20other\x20dimensions\x20decide.'};if(!e['raw']?.['trim']())return{'relation':'mismatch','satisfied':a!=='strict','score':a==='strict'?0x0:0.3,'reason':a==='strict'?'Service\x20has\x20NO\x20location\x20set\x20—\x20merchant\x20location\x20hygiene\x20issue;\x20excluded\x20under\x20strict\x20sensitivity.':'Service\x20has\x20no\x20location\x20set\x20—\x20kept\x20(soft\x20signal)\x20because\x20sensitivity\x20is\x20not\x20strict.'};const f=relateRegion(d,e),{satisfied:g,score:h,reason:i}=judge(a,f);return{'relation':f,'satisfied':g,'score':h,'reason':i};}function judge(a,b){switch(b){case'exact':return{'satisfied':!![],'score':0x1,'reason':'Location\x20exact\x20match.'};case'contains':return{'satisfied':!![],'score':0.9,'reason':'Location\x20containment\x20match\x20(one\x20region\x20covers\x20the\x20other).'};case'overlap':if(a==='strict')return{'satisfied':![],'score':0.4,'reason':'Same\x20province\x20but\x20different\x20city\x20—\x20fails\x20the\x20100%\x20location\x20gate\x20(strict).\x20Consider\x20\x27near\x27\x20sensitivity\x20to\x20accept\x20neighboring\x20cities.'};return{'satisfied':!![],'score':0.6,'reason':'Neighboring\x20city\x20within\x20the\x20same\x20province\x20—\x20accepted\x20(near/logistics).'};case'compatible':return{'satisfied':!![],'score':0.8,'reason':'Remote\x20service\x20serves\x20any\x20physical\x20region\x20(or\x20vice\x20versa).'};case'mismatch':default:return{'satisfied':a==='logistics','score':0x0,'reason':a==='logistics'?'Region\x20mismatch\x20—\x20soft\x20warning\x20only\x20(goods\x20can\x20ship\x20via\x20logistics).':'Region\x20mismatch\x20—\x20excluded\x20under\x20strict/near\x20sensitivity.'};}}export function rankByLocation(a,b,c){return c['map'](d=>{const e=gateLocation(a,b,d['location']);return{'id':d['id'],'name':d['name'],'location':typeof d['location']==='string'?d['location']:d['location']?.['raw'],'relation':e['relation'],'satisfied':e['satisfied'],'score':e['score'],'reason':e['reason']};})['sort']((d,e)=>{if(d['satisfied']!==e['satisfied'])return d['satisfied']?-0x1:0x1;if(e['score']!==d['score'])return e['score']-d['score'];return 0x0;});}export function expandSearchScope(a,b){const c=toRegion(b),d=c['city']?.['trim'](),e=c['province']?.['trim']();if(a==='strict')return{'sensitivity':a,'search_terms':d?[d]:[c['raw']]['filter'](Boolean),'ai_enrichment_note':'Strict:\x20do\x20NOT\x20widen\x20geographically.\x20If\x20nothing\x20matches,\x20report\x20honestly\x20and\x20suggest\x20switching\x20sensitivity\x20to\x20\x27near\x27\x20(user\x20decision)\x20instead\x20of\x20silently\x20expanding.'};if(a==='near'){const f=[c['raw'],d,e]['filter'](Boolean);return{'sensitivity':a,'search_terms':f,'ai_enrichment_note':'Near:\x20AI\x20enriches\x20neighboring\x20cities\x20of\x20the\x20demand\x20city\x20from\x20public\x20web\x20data\x20(authoritative\x20preferred),\x20confirms\x20the\x20list\x20with\x20the\x20user,\x20then\x20re-runs\x20discovery\x20with\x20the\x20expanded\x20terms.'};}return{'sensitivity':a,'search_terms':[c['raw'],e,'remote','online','nationwide','china','global']['filter'](Boolean),'ai_enrichment_note':'Logistics:\x20location\x20is\x20a\x20soft\x20signal.\x20Enumerate\x20broadly\x20(nationwide/remote\x20services),\x20rank\x20by\x20location\x20fit,\x20but\x20let\x20price/trust/tags\x20dominate\x20the\x20final\x20recommendation.'};}const ON_SITE_EN=/\b(hotel|accommodation|restaurant|dining|gym)\b/,ON_SITE_CJK=['民宿','酒店','餐厅','健身房'],LOGISTICS_EN=/\b(shipping|delivery|ship to home|mail)\b/,LOGISTICS_CJK=['快递','物流','邮寄','配送到家'],REMOTE_EN=/\b(online|remote)\b/,REMOTE_CJK=['在线','远程'],hits=(a,b,c)=>b['test'](a)||c['some'](d=>a['includes'](d));export function inferSensitivity(a){const b=(a??'')['toLowerCase'](),c=[];hits(b,ON_SITE_EN,ON_SITE_CJK)&&c['push']('on-site\x20consumption');hits(b,LOGISTICS_EN,LOGISTICS_CJK)&&c['push']('physical\x20logistics');hits(b,REMOTE_EN,REMOTE_CJK)&&c['push']('remote\x20service');if(c['includes']('on-site\x20consumption')&&!c['includes']('physical\x20logistics'))return{'sensitivity':'strict','signals':c};if(c['includes']('physical\x20logistics'))return{'sensitivity':'logistics','signals':c};if(c['includes']('remote\x20service'))return{'sensitivity':'near','signals':c};return{'sensitivity':'near','signals':c['length']?c:['no\x20explicit\x20signal\x20—\x20defaulted\x20to\x20near']};}
1
+ import{parseRegion,relateRegion}from'./region.js';function toRegion(a){if(a===undefined)return parseRegion('');if(typeof a==='string')return parseRegion(a);const b=parseRegion(a['raw']);return{...b,'country':a['country']??b['country'],'province':a['province']??b['province'],'city':a['city']??b['city']};}export function gateLocation(a,b,c){const d=toRegion(b),e=toRegion(c);if(!d['raw']?.['trim']())return{'relation':'mismatch','satisfied':a!=='strict','score':0.5,'reason':'No\x20demand-side\x20location\x20stated\x20—\x20location\x20is\x20not\x20discriminating;\x20other\x20dimensions\x20decide.'};if(!e['raw']?.['trim']())return{'relation':'mismatch','satisfied':a!=='strict','score':a==='strict'?0x0:0.3,'reason':a==='strict'?'Service\x20has\x20NO\x20location\x20set\x20—\x20merchant\x20location\x20hygiene\x20issue;\x20excluded\x20under\x20strict\x20sensitivity.':'Service\x20has\x20no\x20location\x20set\x20—\x20kept\x20(soft\x20signal)\x20because\x20sensitivity\x20is\x20not\x20strict.'};const f=relateRegion(d,e),{satisfied:g,score:h,reason:i}=judge(a,f);return{'relation':f,'satisfied':g,'score':h,'reason':i};}function judge(a,b){switch(b){case'exact':return{'satisfied':!![],'score':0x1,'reason':'Location\x20exact\x20match.'};case'contains':return{'satisfied':!![],'score':0.9,'reason':'Location\x20containment\x20match\x20(one\x20region\x20covers\x20the\x20other).'};case'overlap':if(a==='strict')return{'satisfied':![],'score':0.4,'reason':'Same\x20province\x20but\x20different\x20city\x20—\x20fails\x20the\x20100%\x20location\x20gate\x20(strict).\x20Consider\x20\x27near\x27\x20sensitivity\x20to\x20accept\x20neighboring\x20cities.'};return{'satisfied':!![],'score':0.6,'reason':'Neighboring\x20city\x20within\x20the\x20same\x20province\x20—\x20accepted\x20(near/logistics).'};case'compatible':return{'satisfied':!![],'score':0.8,'reason':'Remote\x20service\x20serves\x20any\x20physical\x20region\x20(or\x20vice\x20versa).'};case'mismatch':default:return{'satisfied':a==='logistics','score':0x0,'reason':a==='logistics'?'Region\x20mismatch\x20—\x20soft\x20warning\x20only\x20(goods\x20can\x20ship\x20via\x20logistics).':'Region\x20mismatch\x20—\x20excluded\x20under\x20strict/near\x20sensitivity.'};}}export function rankByLocation(a,b,c){return c['map'](d=>{const e=gateLocation(a,b,d['location']);return{'id':d['id'],'name':d['name'],'location':typeof d['location']==='string'?d['location']:d['location']?.['raw'],'relation':e['relation'],'satisfied':e['satisfied'],'score':e['score'],'reason':e['reason']};})['sort']((d,e)=>{if(d['satisfied']!==e['satisfied'])return d['satisfied']?-0x1:0x1;if(e['score']!==d['score'])return e['score']-d['score'];return 0x0;});}export function expandSearchScope(a,b){const c=toRegion(b),d=c['city']?.['trim'](),e=c['province']?.['trim']();if(a==='strict')return{'sensitivity':a,'search_terms':d?[d]:[c['raw']]['filter'](Boolean),'ai_enrichment_note':'Strict:\x20do\x20NOT\x20widen\x20geographically.\x20If\x20nothing\x20matches,\x20report\x20honestly\x20and\x20suggest\x20switching\x20sensitivity\x20to\x20\x27near\x27\x20(user\x20decision)\x20instead\x20of\x20silently\x20expanding.'};if(a==='near'){const f=[c['raw'],d,e]['filter'](Boolean);return{'sensitivity':a,'search_terms':f,'ai_enrichment_note':'Near:\x20AI\x20enriches\x20neighboring\x20cities\x20of\x20the\x20demand\x20city\x20from\x20public\x20web\x20data\x20(authoritative\x20preferred),\x20confirms\x20the\x20list\x20with\x20the\x20user,\x20then\x20re-runs\x20discovery\x20with\x20the\x20expanded\x20terms.'};}return{'sensitivity':a,'search_terms':[c['raw'],e,'remote','online','nationwide','china','global']['filter'](Boolean),'ai_enrichment_note':'Logistics:\x20location\x20is\x20a\x20soft\x20signal.\x20Enumerate\x20broadly\x20(nationwide/remote\x20services),\x20rank\x20by\x20location\x20fit,\x20but\x20let\x20price/trust/tags\x20dominate\x20the\x20final\x20recommendation.'};}const ON_SITE_EN=/\b(hotel|accommodation|homestay|restaurant|dining|gym)\b/,LOGISTICS_EN=/\b(shipping|delivery|ship to home|mail|courier)\b/,REMOTE_EN=/\b(online|remote)\b/,hits=(a,b)=>b['test'](a);export function inferSensitivity(a){const b=(a??'')['toLowerCase'](),c=[];hits(b,ON_SITE_EN)&&c['push']('on-site\x20consumption');hits(b,LOGISTICS_EN)&&c['push']('physical\x20logistics');hits(b,REMOTE_EN)&&c['push']('remote\x20service');if(c['includes']('on-site\x20consumption')&&!c['includes']('physical\x20logistics'))return{'sensitivity':'strict','signals':c};if(c['includes']('physical\x20logistics'))return{'sensitivity':'logistics','signals':c};if(c['includes']('remote\x20service'))return{'sensitivity':'near','signals':c};return{'sensitivity':'near','signals':c['length']?c:['no\x20explicit\x20signal\x20—\x20defaulted\x20to\x20near']};}
@@ -1 +1 @@
1
- import{GOAL_TYPES}from'./types.js';export const GOAL_KEYWORD_RULES=[{'goal_type':'publish_service','keywords':['发布服务','开店','上线服务','开个店','开个点','出售服务','上架','publish\x20service','launch\x20service','open\x20store','open\x20a\x20store','open\x20shop','sell\x20service']},{'goal_type':'fulfill_order','keywords':['履约','交付订单','新订单','推进订单','处理订单','订单交付','fulfill','fulfil','deliver\x20order','new\x20order','process\x20order']},{'goal_type':'capture_demand','keywords':['需求机会','接单','有什么需求','找需求','需求匹配','capture\x20demand','opportunities','opportunity','demands\x20available','what\x20demands']},{'goal_type':'purchase_service','keywords':['购买服务','帮我买','帮我找','定制','下单','买个','buy','purchase','order\x20a\x20service','customize','custom-made']},{'goal_type':'collaborate_flow','keywords':['待办','我的节点','协作','员工','工作任务','my\x20tasks','pending\x20nodes','collaborate','my\x20node','todo']},{'goal_type':'supply_suborder','keywords':['子订单','应征','供应商','供货','sub-order','suborder','supplier','present']},{'goal_type':'publish_demand','keywords':['发布需求','找人做','悬赏','求人','publish\x20demand','post\x20demand','bounty','looking\x20for\x20someone']},{'goal_type':'run_arbitration','keywords':['仲裁业务','仲裁服务','经营仲裁','仲裁经营','arbitration\x20business','arbitrator','arbitration\x20service']},{'goal_type':'dispute_resolution','keywords':['争议','纠纷','投诉','申诉','维权','dispute','complaint','appeal']},{'goal_type':'manage_assets','keywords':['资产','资金','数据管理','盘点','权限盘点','权限管理','财务','治理','金库','treasury','assets','manage\x20funds','asset','inventory','permission\x20management','governance','fund\x20audit','withdraw']}];const ASCII_RE=/^[\x20-\x7e]+$/;function keywordWeight(a){return a['length']>=0x4?0x2:0x1;}function escapeRe(a){return a['replace'](/[.*+?^${}()|[\]\\]/g,'\x5c$&');}const boundaryCache=new Map();function keywordMatches(a,b){if(ASCII_RE['test'](a)){let c=boundaryCache['get'](a);return!c&&(c=new RegExp('\x5cb'+escapeRe(a)+'\x5cb','i'),boundaryCache['set'](a,c)),c['test'](b);}return b['includes'](a);}export function classifyGoal(a){const b=(a??'')['trim']()['toLowerCase'](),c={'goal_type':null,'confidence':0x0,'matched':[],'alternatives':[]};if(!b)return c;const d=[];for(const k of GOAL_KEYWORD_RULES){const l=[];let m=0x0;for(const n of k['keywords']){keywordMatches(n,b)&&(l['push'](n),m+=keywordWeight(n));}if(m>0x0)d['push']({'goal_type':k['goal_type'],'score':m,'matched':l});}if(d['length']===0x0)return c;let e=d[0x0];for(const o of d){if(o['score']>e['score'])e=o;}const f=d['reduce']((p,q)=>p+q['score'],0x0),g=e['score']/f,h=Math['min'](0x1,e['score']/0x3),i=Math['round'](g*h*0x3e8)/0x3e8,j=d['filter'](p=>p['goal_type']!==e['goal_type'])['sort']((p,q)=>q['score']-p['score'])['map'](({goal_type:p,score:q})=>({'goal_type':p,'score':q}));return{'goal_type':e['goal_type'],'confidence':i,'matched':e['matched'],'alternatives':j};}export{GOAL_TYPES};
1
+ import{GOAL_TYPES}from'./types.js';export const GOAL_KEYWORD_RULES=[{'goal_type':'publish_service','keywords':['publish\x20service','launch\x20service','open\x20store','open\x20a\x20store','open\x20shop','sell\x20service','list\x20service','start\x20selling','set\x20up\x20shop']},{'goal_type':'fulfill_order','keywords':['fulfill','fulfil','deliver\x20order','new\x20order','process\x20order','advance\x20order','order\x20delivery','handle\x20order']},{'goal_type':'capture_demand','keywords':['capture\x20demand','opportunities','opportunity','demands\x20available','what\x20demands','find\x20demand','demand\x20matching','take\x20orders']},{'goal_type':'purchase_service','keywords':['buy','purchase','order\x20a\x20service','customize','custom-made','buy\x20for\x20me','help\x20me\x20find','place\x20an\x20order']},{'goal_type':'collaborate_flow','keywords':['my\x20tasks','pending\x20nodes','collaborate','my\x20node','todo','to-do','collaboration','staff','work\x20task']},{'goal_type':'supply_suborder','keywords':['sub-order','suborder','supplier','present','apply\x20for\x20sub-order','supply\x20goods']},{'goal_type':'publish_demand','keywords':['publish\x20demand','post\x20demand','bounty','looking\x20for\x20someone','find\x20someone\x20to','need\x20someone']},{'goal_type':'run_arbitration','keywords':['arbitration\x20business','arbitrator','arbitration\x20service','run\x20arbitration','operate\x20arbitration']},{'goal_type':'dispute_resolution','keywords':['dispute','complaint','appeal','raise\x20a\x20dispute']},{'goal_type':'manage_assets','keywords':['treasury','assets','manage\x20funds','asset','inventory','permission\x20management','governance','fund\x20audit','withdraw','finance','financial','data\x20management','permission\x20audit']}];const ASCII_RE=/^[\x20-\x7e]+$/;function keywordWeight(a){return a['length']>=0x4?0x2:0x1;}function escapeRe(a){return a['replace'](/[.*+?^${}()|[\]\\]/g,'\x5c$&');}const boundaryCache=new Map();function keywordMatches(a,b){if(ASCII_RE['test'](a)){let c=boundaryCache['get'](a);return!c&&(c=new RegExp('\x5cb'+escapeRe(a)+'\x5cb','i'),boundaryCache['set'](a,c)),c['test'](b);}return b['includes'](a);}export function classifyGoal(a){const b=(a??'')['trim']()['toLowerCase'](),c={'goal_type':null,'confidence':0x0,'matched':[],'alternatives':[]};if(!b)return c;const d=[];for(const k of GOAL_KEYWORD_RULES){const l=[];let m=0x0;for(const n of k['keywords']){keywordMatches(n,b)&&(l['push'](n),m+=keywordWeight(n));}if(m>0x0)d['push']({'goal_type':k['goal_type'],'score':m,'matched':l});}if(d['length']===0x0)return c;let e=d[0x0];for(const o of d){if(o['score']>e['score'])e=o;}const f=d['reduce']((p,q)=>p+q['score'],0x0),g=e['score']/f,h=Math['min'](0x1,e['score']/0x3),i=Math['round'](g*h*0x3e8)/0x3e8,j=d['filter'](p=>p['goal_type']!==e['goal_type'])['sort']((p,q)=>q['score']-p['score'])['map'](({goal_type:p,score:q})=>({'goal_type':p,'score':q}));return{'goal_type':e['goal_type'],'confidence':i,'matched':e['matched'],'alternatives':j};}export{GOAL_TYPES};
@@ -27,9 +27,9 @@ export declare function runAnalyzers(v: Viewport, opts?: {
27
27
  }): Finding[];
28
28
  export interface NodeRuleOutcome {
29
29
  severity?: FindingSeverity;
30
- titleZh: string;
31
- detailZh: string;
32
- suggestionZh: string;
30
+ title: string;
31
+ detail: string;
32
+ suggestion: string;
33
33
  roles?: ViewerRole[];
34
34
  confidence?: Confidence;
35
35
  }
@@ -1 +1 @@
1
- import{detectFakeOrders,detectShellMerchant}from'./anti-cheat.js';import{orderCompletionInGraph}from'./expand.js';function root(a){const b=a?.['raw'],c=b?.['data']??b;return c&&typeof c==='object'?c:undefined;}function str(a){return typeof a==='string'&&a!=='0x0'?a:undefined;}function big(a){if(a==null)return 0x0n;try{return BigInt(typeof a==='number'?Math['trunc'](a):String(a));}catch{return 0x0n;}}function bool(a){return a===!![]||a===0x1||a==='1';}function asList(a){return Array['isArray'](a)?a:[];}function wfNodeName(a){const b=a['indexOf']('::node::');return b>=0x0?a['slice'](b+'::node::'['length']):a;}function wfMachineOf(a){const b=a['indexOf']('::node::');return b>=0x0?a['slice'](0x0,b):'';}function typedNodes(a,b){const c=[];for(const d of a['visibleNodes']){const e=a['graph']['nodes']['get'](d);if(e?.['kind']==='object'&&e['objectType']===b&&e['raw'])c['push'](e);}return c;}function edgeList(a,b){return a['visibleEdges']['filter'](c=>c['schema']===b);}function out(a,b,c){return a['visibleEdges']['filter'](d=>d['from']===b['toLowerCase']()&&d['schema']===c);}function inc(a,b,c){return a['visibleEdges']['filter'](d=>d['to']===b['toLowerCase']()&&d['schema']===c);}const RETENTION_RANK={'complete':0x0,'bounded_exact':0x1,'membership':0x1,'derived':0x2,'bounded_window':0x3},WINDOW_LIMIT=0x1450;export function pathConfidence(a,b){let c=0x0,d=![];for(const g of b){c=Math['max'](c,RETENTION_RANK[g['retention']]??0x0);if(g['retention']==='bounded_window'||g['truncated'])d=!![];}if(d){let h=0x0;for(const i of b){if(i['retention']!=='bounded_window'&&!i['truncated'])continue;const j=a['visibleEdges']['filter'](l=>l['schema']===i['schema']&&l['from']===i['from'])['length'];h=Math['max'](h,j);const k=a['graph']['truncations']['find'](l=>l['nodeId']===i['from']&&l['schema']===i['schema']);if(k)h=Math['max'](h,k['observed']);}return{'confidence':'windowed','window':{'observed':h||b['length'],'limit':WINDOW_LIMIT}};}const f=c===0x0?'exact':c===0x2?'derived':'bounded';return{'confidence':f};}function makeFinding(a,b,c,d,e){const {confidence:f,window:g}=pathConfidence(a,e['pathEdges']??[]);return{'id':b,'kind':c,'severity':e['severity']??'info','titleZh':d,'path':e['path'],'confidence':f,...g?{'window':g}:{},'roles':e['roles']??['neutral'],'detailZh':e['detailZh'],'suggestionZh':e['suggestionZh']};}const MAX_FINDINGS_PER_RULE=0x14,ROLE_OWNER_OR_ADMIN=0x1|0x2;export function buildControlIndex(a){const b=new Map(),c=new Map(),d=new Map(),f=(h,i,j)=>{const l=h['get'](i)??new Set();l['add'](j),h['set'](i,l);},g=new Map();for(const h of edgeList(a,'eoa.permission')){const i=typeof h['payload']?.['roleBits']==='number'?h['payload']['roleBits']:ROLE_OWNER_OR_ADMIN;if((i&ROLE_OWNER_OR_ADMIN)===0x0)continue;f(g,h['from'],h['to']);}for(const j of edgeList(a,'permission.core_binding')){const k=a['graph']['nodes']['get'](j['to']);if(!k||k['kind']!=='object')continue;f(d,j['to'],j['from']);for(const [l,m]of g){if(!m['has'](j['from']))continue;f(b,j['to'],l),f(c,l,j['to']);}}return{'controllers':b,'objectsByEoa':c,'permsOfObject':d};}function machineViews(a){const b=new Map();for(const d of edgeList(a,'wf.transition')){const f=wfMachineOf(d['from']);if(!f)continue;const g=b['get'](f)??[];g['push'](d),b['set'](f,g);}const c=[];for(const [h,i]of b){const j=a['graph']['nodes']['get'](h);if(!j||!a['visibleNodes']['has'](h))continue;const k=new Set([...(function*(){const l=new Set(i['map'](p=>String(p['payload']?.['node']??''))['filter'](Boolean)),o=new Set(i['map'](p=>String(p['payload']?.['prevNode']??''))['filter'](Boolean));for(const p of l)if(!o['has'](p))yield p;}())]);c['push']({'machine':j,'transitions':i,'terminals':k});}return c;}const ROLES_RISK_NEUTRAL_MERCHANT=['neutral','system','merchant'],R1={'id':'R1','kind':'risk','run'(b){const c=buildControlIndex(b),d=[],e=typedNodes(b,'Service'),f=typedNodes(b,'Arbitration');o:for(const g of e){const h=c['controllers']['get'](g['id']);if(!h)continue;for(const i of f){const j=c['controllers']['get'](i['id']);if(!j)continue;const k=c['permsOfObject']['get'](g['id']),l=c['permsOfObject']['get'](i['id']),m=[...k??[]]['some'](n=>l?.['has'](n));if(m)continue;for(const n of h){if(!j['has'](n))continue;d['push'](makeFinding(b,'R1:'+g['id']+':'+i['id']+':'+n,'risk','同裁风险:店铺与仲裁服务受同一实控\x20EOA\x20支配',{'severity':'high','path':[n,'eoa.permission','permission.core_binding',g['id'],i['id']],'pathEdges':edgeList(b,'permission.core_binding'),'roles':['neutral','system','merchant','arbitrator'],'detailZh':'EOA\x20'+n+'\x20同时以\x20owner/admin\x20身份控制\x20Service\x20'+g['id']+'\x20与\x20Arbitration\x20'+i['id']+','+'且二者挂接在不同\x20Permission\x20下(E33\x20只禁止同一\x20Permission,未禁跨组同裁)。'+'该\x20EOA\x20在结构上可以同时影响被裁店铺与裁决结果。','suggestionZh':'核查该\x20EOA\x20的实控关系;要求店铺与仲裁服务的\x20owner/admin\x20集合互不相交,或将该仲裁服务移出可选列表。'}));if(d['length']>=MAX_FINDINGS_PER_RULE)break o;}}}return d;}},R2={'id':'R2','kind':'risk','run'(a){const b=[];for(const c of typedNodes(a,'Service')){const f=root(c),g=out(a,c['id'],'service.order');if(g['length']===0x0)continue;let h=0x0n,i=0x0;for(const l of g){const m=root(a['graph']['nodes']['get'](l['to']));if(!m)continue;h+=big(m['amount']),i++;}if(i===0x0)continue;const j=big(f['compensation_fund']),k=h*0x3n;if(j>=k)continue;b['push'](makeFinding(a,'R2:'+c['id'],'risk','赔付敞口:补偿基金低于窗口订单额的\x203\x20倍上限',{'severity':j<h?'high':'medium','path':[c['id'],'service.order','Order.amount','Service.compensation_fund'],'pathEdges':g,'roles':['neutral','system','merchant','buyer'],'detailZh':'补偿基金\x20'+j+'\x20基准单位,窗口内\x20'+i+'\x20笔订单金额合计\x20'+h+','+('法定赔付封顶为单笔\x203×amount\x20的结构总敞口\x20'+k+'(arb.move:302-321)。'),'suggestionZh':'补足\x20compensation_fund\x20至窗口金额\x203\x20倍以上,或在窗口内降低未结订单规模。'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break;}return b;}},CONTROL_TYPES=new Set(['Service','Machine','Treasury']),CONTROL_FANOUT_ALERT=0x3,R3={'id':'R3','kind':'risk','run'(a){const b=buildControlIndex(a),c=[];for(const [d,e]of b['objectsByEoa']){const f=[...e]['filter'](i=>CONTROL_TYPES['has'](a['graph']['nodes']['get'](i)?.['objectType']??''));if(f['length']<CONTROL_FANOUT_ALERT)continue;const g=f['filter'](i=>a['graph']['nodes']['get'](i)?.['objectType']==='Service'),h=g['reduce']((i,j)=>i+out(a,j,'service.order')['length'],0x0);c['push'](makeFinding(a,'R3:'+d,'risk','权限集中:单个\x20EOA\x20控制多个经营核心对象',{'severity':f['length']>=0x5?'medium':'low','path':[d,'eoa.permission','permission.core_binding'],'pathEdges':edgeList(a,'eoa.permission')['concat'](edgeList(a,'permission.core_binding')),'roles':ROLES_RISK_NEUTRAL_MERCHANT,'detailZh':'EOA\x20'+d+'\x20通过\x20owner/admin\x20权限控制\x20'+f['length']+'\x20个\x20Service/Machine/Treasury\x20对象'+('(其中\x20Service\x20'+g['length']+'\x20个,窗口内可见订单\x20'+h+'\x20笔),经营规模与权限分散度不匹配。'),'suggestionZh':'将日常运营权限下放给独立\x20admin/entity\x20角色,owner\x20仅保留紧急处置;核心对象避免同组挂接。'}));if(c['length']>=MAX_FINDINGS_PER_RULE)break;}return c;}},R4={'id':'R4','kind':'risk','run'(a){const b=[];p:for(const c of machineViews(a)){const d=new Map();for(const g of c['transitions']){if(!c['terminals']['has'](String(g['payload']?.['node']??'')))continue;const h=g['from']+'→'+g['to'],i=d['get'](h)??[];i['push'](g),d['set'](h,i);}for(const [j,k]of d){const l=new Set();let m=![];for(const n of k){if(str(n['payload']?.['namedOperator']))l['add']('name:'+n['payload']['namedOperator']);if(typeof n['payload']?.['permissionIndex']==='number')l['add']('perm:'+n['payload']['permissionIndex']);if(str(n['payload']?.['guard']))m=!![];}if(l['size']===0x1&&!m){const o=[...l][0x0];b['push'](makeFinding(a,'R4:'+c['machine']['id']+':'+j,'risk','流程单点:终态前\x20Forward\x20仅唯一操作方且无替补\x20Guard',{'severity':'medium','path':[c['machine']['id'],'machine.node','wf.transition',j],'pathEdges':k,'roles':['neutral','system','merchant','collaborator'],'detailZh':'Machine\x20'+c['machine']['id']+'\x20进入终态\x20'+wfNodeName(k[0x0]['to'])+'\x20的路径\x20'+j+'\x20上,'+('唯一可执行操作方为\x20'+o+',且所有\x20Forward\x20均无\x20guard\x20兜底;该操作方离线即流程卡死。'),'suggestionZh':'为该\x20Forward\x20增加\x20permissionIndex\x20备选或挂接\x20guard\x20自动推进条件,避免单人阻断终态。'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break p;}}}return b;}},R5={'id':'R5','kind':'risk','run'(a){const b=[],c=new Set();for(const d of a['graph']['truncations']){if(!a['visibleNodes']['has'](d['nodeId']))continue;const e=d['nodeId']+'|'+d['schema'];if(c['has'](e))continue;c['add'](e),b['push']({'id':'R5:'+e,'kind':'risk','severity':'info','titleZh':'窗口截断:相关结论仅为\x20≤5200\x20FIFO/环形窗口内下界','path':[d['nodeId'],d['schema']],'confidence':'windowed','window':{'observed':d['observed'],'limit':d['limit']??WINDOW_LIMIT},'roles':['neutral','system','merchant','buyer','supplier','arbitrator','collaborator'],'detailZh':'节点\x20'+d['nodeId']+'\x20的\x20'+d['schema']+'\x20扇出被截断(已观测\x20'+d['observed']+',窗口上限\x20'+(d['limit']??WINDOW_LIMIT)+');'+'依赖该路径的任何结论都必须表述为\x22窗口内/至少\x22,不得当作全量真值。','suggestionZh':'需要全量结论时改走事件通道(channel\x20D)或在预算内放大\x20perKindCaps。'});if(b['length']>=MAX_FINDINGS_PER_RULE)break;}return b;}},R6={'id':'R6','kind':'risk','run'(a){const b=[];for(const c of typedNodes(a,'Service')){const e=root(c);if(!bool(e['bPublished']))continue;if(big(e['setting_lock_duration'])!==0x0n)continue;b['push'](makeFinding(a,'R6:'+c['id'],'risk','设置锁缺失:已发布\x20Service\x20的\x20setting_lock_duration=0',{'severity':'medium','path':[c['id'],'Service.setting_lock_duration'],'roles':ROLES_RISK_NEUTRAL_MERCHANT['concat']('buyer'),'detailZh':'Service\x20'+c['id']+'\x20已发布但\x20setting_lock_duration=0:order_allocators\x20/\x20rewards\x20/\x20arbitrations\x20/\x20machine\x20'+'与\x20compensation_fund\x20提现可被即时修改(默认锁为\x2030\x20天,service.move:38),买家面对的是可瞬变条款。','suggestionZh':'发布后设置\x20setting_lock_duration(30\x20天=2592000000\x20毫秒起),条款变更必须经过等待期。'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break;}return b;}},RATE_BASIS=0x2710n;function allocationStructuralIssues(a){const b=[];let c=0x0,d=![];for(const e of asList(a)){const f=e??{};let g=0x0n,h=![];for(const i of asList(f['sharing'])){const j=i??{},k=Number(j['mode']);if(k===0x2||j['mode']==='Surplus'){c++,d=!![];continue;}k===0x1||j['mode']==='Rate'?g+=big(j['sharing']):h=!![];}g!==0x0n&&g!==RATE_BASIS&&!d&&b['push']('存在\x20Rate\x20分账合计\x20'+g+'\x20≠\x2010000\x20基点且无\x20Surplus\x20兜底,支付时将中止'),h&&(f['max']==null||big(f['max'])===0x0n)&&b['push']('定额(Amount)分账\x20Allocator\x20缺少\x20max\x20上限,guard\x20触发时存在超额划出空间');}if(c>0x1)b['push']('Surplus\x20条目\x20'+c+'\x20个(合法至多\x201\x20个),多余收益归属不确定');return[...new Set(b)];}const A1={'id':'A1','kind':'arbitrage','run'(a){const b=[],c=(e,f,g,h)=>{const i=allocationStructuralIssues(f);if(i['length']===0x0||h['has'](e))return;h['add'](e),b['push'](makeFinding(a,'A1:'+e,'arbitrage','分账结构错配:Rate/Surplus/max\x20配置存在可被触发的结构性问题',{'severity':'medium','path':[e,'allocators[].sharing'],'pathEdges':g,'roles':['neutral','system','merchant','buyer'],'detailZh':e+':'+i['join'](';')+'(allocation.move:173-200)。','suggestionZh':'Rate\x20组补齐至\x2010000\x20或配置唯一\x20Surplus;定额\x20Allocator\x20必须设置\x20max;上线前用分账预检工具回归。'}));},d=new Set();for(const e of typedNodes(a,'Allocation')){c(e['id'],root(e)['allocators'],inc(a,e['id'],'order.allocation'),d);}for(const f of typedNodes(a,'Service')){const g=root(f)['order_allocators'];if(g?.['allocators'])c(f['id'],g['allocators'],edgeList(a,'service.order_allocator_guard'),d);}return b['slice'](0x0,MAX_FINDINGS_PER_RULE);}},DISCOUNT_FIXED=0x1,THIRTY_DAYS_MS=0x1en*0x18n*0x3cn*0x3cn*0x3e8n,A2={'id':'A2','kind':'arbitrage','run'(a){const b=[];for(const c of typedNodes(a,'Discount')){const e=root(c),f=big(e['time_end'])-big(e['time_start'])>=THIRTY_DAYS_MS;if(!bool(e['transferable'])||!f)continue;if(Number(e['discount_type'])!==DISCOUNT_FIXED)continue;if(e['benchmark']!=null&&e['benchmark']!=='0')continue;b['push'](makeFinding(a,'A2:'+c['id'],'arbitrage','折扣组合:可转让\x20+\x20宽时间窗\x20+\x20无\x20benchmark\x20固定额折扣',{'severity':'low','path':[c['id'],'Discount.transferable/time_window/benchmark'],'roles':['neutral','system','merchant'],'detailZh':'Discount\x20'+c['id']+'\x20可转让、有效期\x20≥30\x20天、为固定额折扣且无\x20benchmark\x20价格校验(service.move:109-121),'+'存在囤券与转手套利空间。','suggestionZh':'缩短有效期、改为\x20RATES\x20比例折扣或增加\x20benchmark\x20\x20Guards;必要时关闭\x20transferable。'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break;}return b;}},A3={'id':'A3','kind':'arbitrage','run'(a){const b=[];for(const e of typedNodes(a,'Arbitration')){const f=root(e),g=big(f['fee'])===0x0n&&!str(f['usage_guard']);g&&b['push'](makeFinding(a,'A3:'+e['id'],'arbitrage','救济成本结构:零费用\x20+\x20无使用门槛,恶意纠纷具备正期望结构条件',{'severity':'medium','path':[e['id'],'Arbitration.fee','Arbitration.usage_guard'],'roles':['neutral','system','arbitrator','merchant','buyer'],'detailZh':'Arbitration\x20'+e['id']+'\x20的\x20fee=0\x20且\x20usage_guard\x20为空;叠加赔付封顶\x203×amount、单次\x20claim、'+'30\x20天提现锁等规则(arb.move:302-358,\x20order.move:86-96),恶意发起纠纷在结构上无需前置成本。','suggestionZh':'设置非零\x20fee\x20覆盖裁决成本,或用\x20usage_guard\x20要求纠纷方持有链上参与凭证。'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break;}const c=new Map();for(const h of a['visibleNodes']){const i=a['graph']['nodes']['get'](h),j=i?.['raw']?.['type_raw'];if(typeof j!=='string'||!j['includes']('::payment::CoinWrapper<'))continue;const k=j['slice'](j['indexOf']('<')+0x1,j['lastIndexOf']('>'))['trim'](),l=c['get'](k)??[];l['push'](h),c['set'](k,l);}if(c['size']>0x0){const m=[...c['keys']()]['sort']();b['push']({'id':'A3:coinwrapper','kind':'arbitrage','severity':'info','titleZh':'跨币托管审查点:图中存在\x20CoinWrapper<K>\x20托管对象','path':['payment::CoinWrapper'],'confidence':'exact','roles':['neutral','system','arbitrator','merchant'],'detailZh':'可见\x20CoinWrapper\x20托管覆盖币种:'+m['join'](',\x20')+'(对象数\x20'+[...c['values']()]['reduce']((o,p)=>o+p['length'],0x0)+')。'+'v1\x20不做行情估值;涉及救济/分账时须人工审查币种错配与脱锚风险。','suggestionZh':'核对托管币种与服务币种\x20T\x20是否一致;跨币场景补充独立汇率/预言机证据后再下结论。'});}return b['slice'](0x0,MAX_FINDINGS_PER_RULE);}},SCARCE_PRESENTERS=0x2;function demandGuardIds(a,b){const c=new Set();for(const d of out(a,b,'demand.guard'))c['add'](d['to']);return c;}function serviceGuardIds(a,b){const c=new Set();for(const f of out(a,b['id'],'service.buy_guard'))c['add'](f['to']);const d=out(a,b['id'],'service.machine')[0x0]?.['to'];if(d)for(const g of a['visibleEdges']){if(g['schema']==='wf.forward_guard'&&g['from']['startsWith'](d+'::node::'))c['add'](g['to']);}return c;}const O1={'id':'O1','kind':'opportunity','run'(a){const b=[],c=typedNodes(a,'Service');for(const d of typedNodes(a,'Demand')){const e=out(a,d['id'],'demand.presenter');if(e['length']>=SCARCE_PRESENTERS)continue;const f=demandGuardIds(a,d['id']),g=[];for(const i of c){const j=serviceGuardIds(a,i);if(f['size']===0x0||[...f]['every'](k=>j['has'](k)))g['push'](i['id']);}const h=e;b['push'](makeFinding(a,'O1:'+d['id'],'opportunity','开放需求:提案稀缺,存在结构能力匹配的供应方',{'severity':'info','path':[d['id'],'demand.presenter','demand.guard','Service'],'pathEdges':h['concat'](out(a,d['id'],'demand.guard')),'roles':['neutral','system','supplier'],'detailZh':'Demand\x20'+d['id']+'\x20当前仅\x20'+e['length']+'\x20个提案;按\x20Guard\x20结构(不解析\x20Guard\x20字节码)匹配到\x20'+(g['length']+'\x20个候选\x20Service:'+(g['slice'](0x0,0x5)['join'](',\x20')||'(图内无匹配)')+'。'),'suggestionZh':'候选供方可准备\x20present\x20证据(需求\x20Guards\x20的可通过性证明);机会结论为结构性,不构成履约能力背书。'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break;}return b;}},O2={'id':'O2','kind':'opportunity','run'(a){const b=typedNodes(a,'Service'),c=typedNodes(a,'Demand');if(b['length']===0x0&&c['length']===0x0)return[];const d=b['filter'](f=>bool(root(f)['bPublished'])&&!bool(root(f)['bPaused']))['length'],e=c['filter'](f=>out(a,f['id'],'demand.presenter')['length']===0x0)['length'];return[makeFinding(a,'O2:graph','opportunity','供需密度:图内供应/开放需求统计',{'path':['Service','Demand','demand.presenter'],'pathEdges':edgeList(a,'demand.presenter'),'roles':['neutral','system','supplier','merchant'],'detailZh':'当前视角内\x20Service\x20'+b['length']+'\x20个(已发布未暂停\x20'+d+'),Demand\x20'+c['length']+'\x20个'+('(无提案的开放需求\x20'+e+')。开放需求/活跃供应比\x20=\x20')+((d>0x0?(e/d)['toFixed'](0x3):'n/a')+'。'),'suggestionZh':'比值偏高说明供给稀缺;结合类目精确匹配数(collectors\x20category_enumerated_count)判断切入品类。'})];}},O3={'id':'O3','kind':'opportunity','run'(a){const b=[];for(const c of machineViews(a)){const d=new Map();for(const g of c['transitions']){if(str(g['payload']?.['namedOperator'])||g['payload']?.['permissionIndex']!=null)continue;const h=String(g['payload']?.['forward']??g['payload']?.['prevNode']+'→'+g['payload']?.['node']);d['set'](wfNodeName(g['from'])+':'+h,g);}if(d['size']===0x0)continue;const f=[...d['values']()];b['push'](makeFinding(a,'O3:'+c['machine']['id'],'opportunity','流程空位:关键\x20Forward\x20无操作方绑定(仅\x20guard/付款方直通)',{'path':[c['machine']['id'],'machine.node','wf.transition'],'pathEdges':f,'roles':['neutral','system','supplier','collaborator','merchant'],'detailZh':'Machine\x20'+c['machine']['id']+'\x20有\x20'+d['size']+'\x20个\x20Forward\x20无\x20namedOperator/permissionIndex\x20绑定:'+([...d['keys']()]['slice'](0x0,0x8)['join'](',\x20')+'。这些位点只能由\x20guard\x20自动满足或付款交易直接推进。'),'suggestionZh':'供应方/协作者可承接这些位点的操作职责,或推动商家把隐式直通改为显式角色绑定。'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break;}return b;}};function arbitrationCases(a,b){return inc(a,b,'arb.arbitration_service')['map'](c=>a['graph']['nodes']['get'](c['from']))['filter'](c=>!!c&&c['objectType']==='Arb'&&!!c['raw']);}const G1={'id':'G1','kind':'game','run'(a){const b=[];for(const e of typedNodes(a,'Arbitration')){const f=root(e),g=asList(f['voting_guard']),h=new Set(g['map'](l=>l['vote_weight']&&typeof l['vote_weight']==='object'?Object['keys'](l['vote_weight'])[0x0]:'unknown')),i=arbitrationCases(a,e['id']),j=new Map();let k=0x0;for(const l of i){for(const m of asList(root(l)['voted'])){const n=Number(m['weight']??0x0);j['set'](n,(j['get'](n)??0x0)+0x1),k++;}}b['push'](makeFinding(a,'G1:'+e['id'],'game','投票权结构:仲裁投票\x20Guard\x20配置与实际投票权重分布',{'severity':'info','path':[e['id'],'arbitration.voting_guard','arb.arbitration_service','arb.voter'],'pathEdges':out(a,e['id'],'arbitration.voting_guard')['concat'](edgeList(a,'arb.voter')),'roles':['neutral','system','arbitrator','merchant','buyer'],'detailZh':'Arbitration\x20'+e['id']+':voting_guard\x20'+(g['length']===0x0?'为空=全员可投(arbitration.move:48-59)':'权重制('+[...h]['join']('/')+')')+';'+('窗口内案件\x20'+i['length']+'\x20个、实际投票\x20'+k+'\x20人次')+(j['size']?',权重分布\x20'+[...j['entries']()]['map'](([o,p])=>'w'+o+'×'+p)['join'](',\x20'):'')+'。','suggestionZh':'全员可投适合低标的高频场景;高标的应使用权重\x20Guard;该结论只描述客观局面,打分由博弈模块完成。'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break;}return b;}},G2={'id':'G2','kind':'game','run'(a){const b=[];n:for(const c of machineViews(a)){const d=out(a,c['machine']['id'],'machine.permission')[0x0]?.['to'],f=d?inc(a,d,'permission.entity')['map'](h=>({'eoa':h['to'],'bits':h['payload']?.['permIndices']??[]})):[],g=new Set();for(const h of c['transitions']){const i=String(h['payload']?.['forward']??h['payload']?.['prevNode']+'→'+h['payload']?.['node']),j=wfNodeName(h['from'])+':'+i;if(g['has'](j))continue;let k,l='';if(str(h['payload']?.['namedOperator']))k=0x1,l='namedOperator='+h['payload']['namedOperator'];else{if(h['payload']?.['permissionIndex']!=null){if(!d)continue;const m=Number(h['payload']['permissionIndex']);k=f['filter'](n=>n['bits']['includes'](m))['length'],l='permissionIndex='+m;if(k===0x0)continue;}else continue;}if(k!==0x1)continue;g['add'](j),b['push'](makeFinding(a,'G2:'+c['machine']['id']+':'+j,'game','操作权可替代池=1:敲竹杠位点',{'severity':'low','path':[c['machine']['id'],'machine.node','wf.transition',j],'pathEdges':[h],'roles':['neutral','system','collaborator','merchant','supplier'],'detailZh':'Machine\x20'+c['machine']['id']+'\x20的\x20Forward\x20'+j+'('+l+')可执行方池大小为\x201:'+'该方在流程节点上拥有不可替代的议价地位(machine.move\x20操作预检)。','suggestionZh':'增加同\x20permissionIndex\x20的备选实体或设置\x20namedOperator\x20候补;签订覆盖该位点的\x20SLA/惩罚条款。'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break n;}}return b;}},G3={'id':'G3','kind':'game','run'(a){const b=[];for(const c of typedNodes(a,'Arbitration')){const e=root(c),f=asList(e['voting_guard']);b['push'](makeFinding(a,'G3:'+c['id'],'game','救济策略参数:收益/等待矩阵的结构化输入',{'severity':'info','path':[c['id'],'Arbitration.fee/usage_guard/voting_guard'],'roles':['neutral','system','arbitrator','merchant','buyer'],'detailZh':'Arbitration\x20'+c['id']+':fee='+big(e['fee'])+',usage_guard='+(str(e['usage_guard'])??'无')+',voting_guard='+f['length']+'\x20个。'+'全局结构常量:赔付封顶\x203×amount、补偿提现\x2030\x20天锁、赔付单次\x20claim、撤回/异议窗\x2030\x20天'+'(arb.move:302-358,\x20order.move:86-96)。','suggestionZh':'将上述参数作为\x20node-game/arbitration-game\x20的收益与等待矩阵输入;本分析器不打分、不排序。'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break;}return b;}},ANTI_CHEAT_ROLES=['neutral','system','merchant','buyer'];function projectOrderEvidence(a,b){const c=[];for(const d of typedNodes(a,'Service')){const f=[...b['controllers']['get'](d['id'])??[]];if(f['length']===0x0)continue;for(const g of out(a,d['id'],'service.order')){const h=a['graph']['nodes']['get'](g['to']);if(!h||h['kind']!=='object'||h['objectType']!=='Order'||!h['raw'])continue;const i=out(a,h['id'],'order.builder')[0x0]?.['to'];if(!i)continue;const j=orderCompletionInGraph(a['graph'],h['id'])['status'],k=String(root(h)?.['amount']??0x0),l=out(a,h['id'],'order.allocation')[0x0]?.['to']??null;for(const m of f){c['push']({'service':d['id'],'id':h['id'],'buyer':i,'seller':m,'amount':k,'status':j,'allocation':l});}}}return c;}function orderCheatEdges(a){return edgeList(a,'service.order')['concat'](edgeList(a,'eoa.permission'))['concat'](edgeList(a,'permission.core_binding'));}function shortRefs(a){const b=a['slice'](0x0,0x5)['join']('、');return a['length']>0x5?b+'\x20等\x20'+a['length']+'\x20个对象':b;}const AC1={'id':'AC1','kind':'risk','run'(a){const b=projectOrderEvidence(a,buildControlIndex(a)),c=detectFakeOrders(b)['find'](e=>e['code']==='self_buy');if(!c)return[];const d=c['refs']??[];return[makeFinding(a,'AC1:'+d['join'](','),'risk','刷单嫌疑:窗口内订单买家即店铺实控\x20EOA(自买自卖)',{'severity':'high','path':['EOA','eoa.permission','permission.core_binding','Service','service.order','Order','order.builder'],'pathEdges':orderCheatEdges(a),'roles':ANTI_CHEAT_ROLES,'detailZh':'窗口内可见\x20'+d['length']+'\x20笔订单的买家\x20EOA\x20同时以\x20owner/admin\x20身份控制售出该订单的\x20Service'+('('+shortRefs(d)+'):买卖双方处于同一实控集合,资金体内循环,不构成真实竞争成交。'),'suggestionZh':'将该批订单剔除出销量/声誉统计,结合支付分账腿与时间窗复核;对该\x20Service\x20降低市场曝光与推荐权重。'})];}},AC2={'id':'AC2','kind':'risk','run'(a){const b=projectOrderEvidence(a,buildControlIndex(a)),c=detectFakeOrders(b)['find'](e=>e['code']==='reciprocal_loop');if(!c)return[];const d=c['refs']??[];return[makeFinding(a,'AC2:'+d['join'](','),'risk','对倒嫌疑:窗口内存在买卖角色互换的资金循环',{'severity':c['severity'],'path':['EOA-A','order.builder','Order@Service-B','service.order','EOA-B','order.builder','Order@Service-A'],'pathEdges':orderCheatEdges(a),'roles':ANTI_CHEAT_ROLES,'detailZh':'窗口内\x20'+d['length']+'\x20笔订单构成买卖互换:A\x20实控集合购买\x20B\x20的\x20Service,同时\x20B\x20实控集合购买\x20A\x20的\x20Service'+('('+shortRefs(d)+')。双向成交可能是互为捧场的资金对倒。'),'suggestionZh':'核查两个实控集合的关联关系(设备/权限/资金往来);对互购订单不计入有效竞争成交。'})];}},AC3={'id':'AC3','kind':'risk','run'(a){const b=projectOrderEvidence(a,buildControlIndex(a)),c=detectFakeOrders(b)['find'](e=>e['code']==='no_allocation');if(!c)return[];const d=c['refs']??[];return[makeFinding(a,'AC3:'+d['join'](','),'risk','无资金闭环:已完成的正额订单缺少\x20Allocation\x20分账对象',{'severity':c['severity'],'path':['Service','service.order','Order','order.allocation'],'pathEdges':orderCheatEdges(a),'roles':ANTI_CHEAT_ROLES,'detailZh':'窗口内\x20'+d['length']+'\x20笔已完成(完成态由\x20order-status\x20结构终结点集权威判定)且\x20amount>0\x20的订单没有\x20Allocation'+('('+shortRefs(d)+')。order.move\x20L130\x20规定正额订单必有分账路径,缺失意味着该“成交”无资金闭环证据。')+'零额订单不在此列(无资金流)。','suggestionZh':'复核订单原始支付记录;无支付凭证的完成订单不得计入声誉;排查无\x20Allocation\x20完成路径的合约入口。'})];}},SHELL_COPY={'shell_no_arbitration':{'titleZh':'空壳商家:已发布\x20Service\x20无仲裁绑定,争议无救济路径','detailZh':'Service\x20处于已发布状态但\x20arbitrations\x20为空:买家下单后没有可选仲裁服务,争议无法进入裁决流程。','suggestionZh':'发布前至少绑定一个与店铺\x20Permission\x20不同组的\x20Arbitration;无救济路径的店铺不应进入推荐。'},'shell_funded_no_arbitration':{'titleZh':'赔付资金悬空:补偿基金已充值但无\x20Arbitration,赔付无法裁决/发放','detailZh':'compensation_fund>0\x20却没有任何\x20Arbitration:触发赔付时无人可裁、无路径可发,充值只构成宣传假象。','suggestionZh':'先绑定仲裁服务再对外宣传赔付保障;市场侧应将“有基金无仲裁”标记为高危并限制曝光。'},'shell_no_machine':{'titleZh':'空壳商家:已发布\x20Service\x20未绑定\x20Machine,无结构化履约流程','detailZh':'Service\x20已发布但\x20machine\x20为空:没有冻结的工作流模板,交付与完成节点均无链上结构约束。','suggestionZh':'绑定并发布\x20Machine\x20后再开张;无工作流的已发布店铺仅适合现货即时交割类目。'}},AC4={'id':'AC4','kind':'risk','run'(a){const b=[];for(const c of typedNodes(a,'Service')){const e=root(c);if(!bool(e['bPublished']))continue;const f=e['arbitrations']!=null?asList(e['arbitrations'])['length']:out(a,c['id'],'service.arbitration')['length'],g=str(e['machine'])??out(a,c['id'],'service.machine')[0x0]?.['to']??null,h=detectShellMerchant({'object':c['id'],'arbitrations':Array(f)['fill']('x'),'compensation_fund':String(big(e['compensation_fund'])),'machine':g,'bPublished':!![]}),i=out(a,c['id'],'service.arbitration')['concat'](out(a,c['id'],'service.machine'));for(const j of h){const k=SHELL_COPY[j['code']];if(!k)continue;b['push'](makeFinding(a,'AC4:'+c['id']+':'+j['code'],'risk',k['titleZh'],{'severity':j['severity'],'path':[c['id'],'Service.bPublished','Service.arbitrations','Service.machine','Service.compensation_fund'],'pathEdges':i,'roles':ANTI_CHEAT_ROLES,'detailZh':k['detailZh']+'(对象:'+c['id']+')','suggestionZh':k['suggestionZh']}));if(b['length']>=MAX_FINDINGS_PER_RULE)return b;}}return b;}};export const DEFAULT_ANALYZERS=[R1,R2,R3,R4,R5,R6,A1,A2,A3,O1,O2,O3,G1,G2,G3,AC1,AC2,AC3,AC4];const registry=new Map(DEFAULT_ANALYZERS['map'](b=>[b['id'],b]));export function registerAnalyzer(a){registry['set'](a['id'],a);}export function getAnalyzer(a){return registry['get'](a);}export function listAnalyzers(){return[...registry['keys']()];}export function runAnalyzers(a,b){const c=b?.['only']?new Set(b['only']):undefined,d=[];for(const e of registry['values']()){if(c&&!c['has'](e['id']))continue;if(b?.['kinds']&&!b['kinds']['includes'](e['kind']))continue;try{d['push'](...e['run'](a));}catch{}}return d;}export function adaptNodeAnalyzer(a){return{'id':a['id'],'kind':a['kind'],'objectType':a['objectType'],'run'(b,c){const d=a['inspect'](b,c);return d['map']((e,f)=>({'id':a['id']+':'+b['id']+'#'+f,'kind':a['kind'],'severity':e['severity']??'info','titleZh':e['titleZh'],'path':[b['id']],'confidence':e['confidence']??'exact','roles':e['roles']??['neutral'],'detailZh':e['detailZh'],'suggestionZh':e['suggestionZh']}));}};}export function runNodeAnalyzers(a,b){const c=[];for(const d of b){for(const e of typedNodes(a,d['objectType'])){try{c['push'](...d['run'](e,a));}catch{}}}return c;}
1
+ import{detectFakeOrders,detectShellMerchant}from'./anti-cheat.js';import{orderCompletionInGraph}from'./expand.js';function root(a){const b=a?.['raw'],c=b?.['data']??b;return c&&typeof c==='object'?c:undefined;}function str(a){return typeof a==='string'&&a!=='0x0'?a:undefined;}function big(a){if(a==null)return 0x0n;try{return BigInt(typeof a==='number'?Math['trunc'](a):String(a));}catch{return 0x0n;}}function bool(a){return a===!![]||a===0x1||a==='1';}function asList(a){return Array['isArray'](a)?a:[];}function wfNodeName(a){const b=a['indexOf']('::node::');return b>=0x0?a['slice'](b+'::node::'['length']):a;}function wfMachineOf(a){const b=a['indexOf']('::node::');return b>=0x0?a['slice'](0x0,b):'';}function typedNodes(a,b){const c=[];for(const d of a['visibleNodes']){const e=a['graph']['nodes']['get'](d);if(e?.['kind']==='object'&&e['objectType']===b&&e['raw'])c['push'](e);}return c;}function edgeList(a,b){return a['visibleEdges']['filter'](c=>c['schema']===b);}function out(a,b,c){return a['visibleEdges']['filter'](d=>d['from']===b['toLowerCase']()&&d['schema']===c);}function inc(a,b,c){return a['visibleEdges']['filter'](d=>d['to']===b['toLowerCase']()&&d['schema']===c);}const RETENTION_RANK={'complete':0x0,'bounded_exact':0x1,'membership':0x1,'derived':0x2,'bounded_window':0x3},WINDOW_LIMIT=0x1450;export function pathConfidence(a,b){let c=0x0,d=![];for(const g of b){c=Math['max'](c,RETENTION_RANK[g['retention']]??0x0);if(g['retention']==='bounded_window'||g['truncated'])d=!![];}if(d){let h=0x0;for(const i of b){if(i['retention']!=='bounded_window'&&!i['truncated'])continue;const j=a['visibleEdges']['filter'](l=>l['schema']===i['schema']&&l['from']===i['from'])['length'];h=Math['max'](h,j);const k=a['graph']['truncations']['find'](l=>l['nodeId']===i['from']&&l['schema']===i['schema']);if(k)h=Math['max'](h,k['observed']);}return{'confidence':'windowed','window':{'observed':h||b['length'],'limit':WINDOW_LIMIT}};}const f=c===0x0?'exact':c===0x2?'derived':'bounded';return{'confidence':f};}function makeFinding(a,b,c,d,e){const {confidence:f,window:g}=pathConfidence(a,e['pathEdges']??[]);return{'id':b,'kind':c,'severity':e['severity']??'info','title':d,'path':e['path'],'confidence':f,...g?{'window':g}:{},'roles':e['roles']??['neutral'],'detail':e['detail'],'suggestion':e['suggestion']};}const MAX_FINDINGS_PER_RULE=0x14,ROLE_OWNER_OR_ADMIN=0x1|0x2;export function buildControlIndex(a){const b=new Map(),c=new Map(),d=new Map(),f=(h,i,j)=>{const l=h['get'](i)??new Set();l['add'](j),h['set'](i,l);},g=new Map();for(const h of edgeList(a,'eoa.permission')){const i=typeof h['payload']?.['roleBits']==='number'?h['payload']['roleBits']:ROLE_OWNER_OR_ADMIN;if((i&ROLE_OWNER_OR_ADMIN)===0x0)continue;f(g,h['from'],h['to']);}for(const j of edgeList(a,'permission.core_binding')){const k=a['graph']['nodes']['get'](j['to']);if(!k||k['kind']!=='object')continue;f(d,j['to'],j['from']);for(const [l,m]of g){if(!m['has'](j['from']))continue;f(b,j['to'],l),f(c,l,j['to']);}}return{'controllers':b,'objectsByEoa':c,'permsOfObject':d};}function machineViews(a){const b=new Map();for(const d of edgeList(a,'wf.transition')){const f=wfMachineOf(d['from']);if(!f)continue;const g=b['get'](f)??[];g['push'](d),b['set'](f,g);}const c=[];for(const [h,i]of b){const j=a['graph']['nodes']['get'](h);if(!j||!a['visibleNodes']['has'](h))continue;const k=new Set([...(function*(){const l=new Set(i['map'](p=>String(p['payload']?.['node']??''))['filter'](Boolean)),o=new Set(i['map'](p=>String(p['payload']?.['prevNode']??''))['filter'](Boolean));for(const p of l)if(!o['has'](p))yield p;}())]);c['push']({'machine':j,'transitions':i,'terminals':k});}return c;}const ROLES_RISK_NEUTRAL_MERCHANT=['neutral','system','merchant'],R1={'id':'R1','kind':'risk','run'(b){const c=buildControlIndex(b),d=[],e=typedNodes(b,'Service'),f=typedNodes(b,'Arbitration');o:for(const g of e){const h=c['controllers']['get'](g['id']);if(!h)continue;for(const i of f){const j=c['controllers']['get'](i['id']);if(!j)continue;const k=c['permsOfObject']['get'](g['id']),l=c['permsOfObject']['get'](i['id']),m=[...k??[]]['some'](n=>l?.['has'](n));if(m)continue;for(const n of h){if(!j['has'](n))continue;d['push'](makeFinding(b,'R1:'+g['id']+':'+i['id']+':'+n,'risk','Same-controller\x20arbitration\x20risk:\x20the\x20service\x20and\x20the\x20arbitration\x20service\x20are\x20controlled\x20by\x20the\x20same\x20EOA',{'severity':'high','path':[n,'eoa.permission','permission.core_binding',g['id'],i['id']],'pathEdges':edgeList(b,'permission.core_binding'),'roles':['neutral','system','merchant','arbitrator'],'detail':'EOA\x20'+n+'\x20controls\x20both\x20Service\x20'+g['id']+'\x20and\x20Arbitration\x20'+i['id']+'\x20as\x20owner/admin,\x20'+'and\x20the\x20two\x20are\x20attached\x20to\x20DIFFERENT\x20Permissions\x20(E33\x20only\x20forbids\x20the\x20same\x20Permission,\x20not\x20cross-group\x20arbitration).\x20'+'structurally\x20this\x20EOA\x20can\x20influence\x20both\x20the\x20arbitrated\x20service\x20and\x20the\x20ruling\x20outcome.','suggestion':'Verify\x20the\x20EOA\x27s\x20control\x20relationships;\x20require\x20disjoint\x20owner/admin\x20sets\x20between\x20the\x20service\x20and\x20the\x20arbitration\x20service,\x20or\x20remove\x20that\x20arbitration\x20service\x20from\x20the\x20selectable\x20list.'}));if(d['length']>=MAX_FINDINGS_PER_RULE)break o;}}}return d;}},R2={'id':'R2','kind':'risk','run'(a){const b=[];for(const c of typedNodes(a,'Service')){const f=root(c),g=out(a,c['id'],'service.order');if(g['length']===0x0)continue;let h=0x0n,i=0x0;for(const l of g){const m=root(a['graph']['nodes']['get'](l['to']));if(!m)continue;h+=big(m['amount']),i++;}if(i===0x0)continue;const j=big(f['compensation_fund']),k=h*0x3n;if(j>=k)continue;b['push'](makeFinding(a,'R2:'+c['id'],'risk','Payout\x20exposure:\x20compensation\x20fund\x20is\x20below\x20the\x203x\x20ceiling\x20of\x20windowed\x20order\x20amounts',{'severity':j<h?'high':'medium','path':[c['id'],'service.order','Order.amount','Service.compensation_fund'],'pathEdges':g,'roles':['neutral','system','merchant','buyer'],'detail':'Compensation\x20fund\x20'+j+'\x20base\x20units;\x20'+i+'\x20windowed\x20orders\x20total\x20'+h+';\x20'+('the\x20per-order\x20statutory\x20payout\x20cap\x20of\x203x\x20amount\x20gives\x20a\x20structural\x20total\x20exposure\x20of\x20'+k+'\x20(arb.move:302-321).'),'suggestion':'Top\x20up\x20compensation_fund\x20to\x20more\x20than\x203x\x20the\x20windowed\x20amount,\x20or\x20reduce\x20open\x20order\x20volume\x20within\x20the\x20window.'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break;}return b;}},CONTROL_TYPES=new Set(['Service','Machine','Treasury']),CONTROL_FANOUT_ALERT=0x3,R3={'id':'R3','kind':'risk','run'(a){const b=buildControlIndex(a),c=[];for(const [d,e]of b['objectsByEoa']){const f=[...e]['filter'](i=>CONTROL_TYPES['has'](a['graph']['nodes']['get'](i)?.['objectType']??''));if(f['length']<CONTROL_FANOUT_ALERT)continue;const g=f['filter'](i=>a['graph']['nodes']['get'](i)?.['objectType']==='Service'),h=g['reduce']((i,j)=>i+out(a,j,'service.order')['length'],0x0);c['push'](makeFinding(a,'R3:'+d,'risk','Permission\x20concentration:\x20a\x20single\x20EOA\x20controls\x20multiple\x20business-critical\x20objects',{'severity':f['length']>=0x5?'medium':'low','path':[d,'eoa.permission','permission.core_binding'],'pathEdges':edgeList(a,'eoa.permission')['concat'](edgeList(a,'permission.core_binding')),'roles':ROLES_RISK_NEUTRAL_MERCHANT,'detail':'EOA\x20'+d+'\x20controls\x20'+f['length']+'\x20Service/Machine/Treasury\x20objects\x20via\x20owner/admin\x20permissions\x20'+('('+g['length']+'\x20of\x20them\x20Services,\x20'+h+'\x20orders\x20visible\x20in\x20the\x20window);\x20business\x20scale\x20does\x20not\x20match\x20permission\x20dispersion.'),'suggestion':'Delegate\x20day-to-day\x20operations\x20to\x20dedicated\x20admin/entity\x20roles\x20and\x20keep\x20owner\x20for\x20emergencies\x20only;\x20avoid\x20attaching\x20core\x20objects\x20to\x20the\x20same\x20permission\x20group.'}));if(c['length']>=MAX_FINDINGS_PER_RULE)break;}return c;}},R4={'id':'R4','kind':'risk','run'(a){const b=[];p:for(const c of machineViews(a)){const d=new Map();for(const g of c['transitions']){if(!c['terminals']['has'](String(g['payload']?.['node']??'')))continue;const h=g['from']+'→'+g['to'],i=d['get'](h)??[];i['push'](g),d['set'](h,i);}for(const [j,k]of d){const l=new Set();let m=![];for(const n of k){if(str(n['payload']?.['namedOperator']))l['add']('name:'+n['payload']['namedOperator']);if(typeof n['payload']?.['permissionIndex']==='number')l['add']('perm:'+n['payload']['permissionIndex']);if(str(n['payload']?.['guard']))m=!![];}if(l['size']===0x1&&!m){const o=[...l][0x0];b['push'](makeFinding(a,'R4:'+c['machine']['id']+':'+j,'risk','Workflow\x20single\x20point:\x20the\x20only\x20Forward\x20before\x20a\x20terminal\x20state\x20has\x20a\x20single\x20operator\x20and\x20no\x20fallback\x20Guard',{'severity':'medium','path':[c['machine']['id'],'machine.node','wf.transition',j],'pathEdges':k,'roles':['neutral','system','merchant','collaborator'],'detail':'On\x20Machine\x20'+c['machine']['id']+',\x20path\x20'+j+'\x20toward\x20terminal\x20state\x20'+wfNodeName(k[0x0]['to'])+':\x20'+('the\x20only\x20operable\x20party\x20is\x20'+o+'\x20and\x20no\x20Forward\x20has\x20a\x20guard\x20fallback;\x20if\x20that\x20party\x20goes\x20offline\x20the\x20workflow\x20stalls.'),'suggestion':'Add\x20a\x20permissionIndex\x20alternative\x20or\x20attach\x20a\x20guard\x20auto-advance\x20condition\x20to\x20this\x20Forward\x20so\x20one\x20party\x20cannot\x20block\x20the\x20terminal\x20state.'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break p;}}}return b;}},R5={'id':'R5','kind':'risk','run'(a){const b=[],c=new Set();for(const d of a['graph']['truncations']){if(!a['visibleNodes']['has'](d['nodeId']))continue;const e=d['nodeId']+'|'+d['schema'];if(c['has'](e))continue;c['add'](e),b['push']({'id':'R5:'+e,'kind':'risk','severity':'info','title':'Window\x20truncation:\x20affected\x20conclusions\x20are\x20lower\x20bounds\x20within\x20the\x20<=5200\x20FIFO/ring\x20window\x20only','path':[d['nodeId'],d['schema']],'confidence':'windowed','window':{'observed':d['observed'],'limit':d['limit']??WINDOW_LIMIT},'roles':['neutral','system','merchant','buyer','supplier','arbitrator','collaborator'],'detail':'Fanout\x20of\x20'+d['schema']+'\x20at\x20node\x20'+d['nodeId']+'\x20is\x20truncated\x20(observed\x20'+d['observed']+',\x20window\x20limit\x20'+(d['limit']??WINDOW_LIMIT)+');\x20'+'any\x20conclusion\x20relying\x20on\x20this\x20path\x20must\x20be\x20worded\x20as\x20\x22within\x20the\x20window\x20/\x20at\x20least\x22,\x20never\x20as\x20exhaustive\x20truth.','suggestion':'For\x20exhaustive\x20conclusions\x20switch\x20to\x20the\x20event\x20channel\x20(channel\x20D)\x20or\x20raise\x20perKindCaps\x20within\x20budget.'});if(b['length']>=MAX_FINDINGS_PER_RULE)break;}return b;}},R6={'id':'R6','kind':'risk','run'(a){const b=[];for(const c of typedNodes(a,'Service')){const e=root(c);if(!bool(e['bPublished']))continue;if(big(e['setting_lock_duration'])!==0x0n)continue;b['push'](makeFinding(a,'R6:'+c['id'],'risk','Missing\x20setting\x20lock:\x20published\x20Service\x20has\x20setting_lock_duration=0',{'severity':'medium','path':[c['id'],'Service.setting_lock_duration'],'roles':ROLES_RISK_NEUTRAL_MERCHANT['concat']('buyer'),'detail':'Service\x20'+c['id']+'\x20is\x20published\x20but\x20setting_lock_duration=0:\x20order_allocators\x20/\x20rewards\x20/\x20arbitrations\x20/\x20machine\x20'+'and\x20compensation_fund\x20withdrawals\x20can\x20be\x20changed\x20instantly\x20(default\x20lock\x20is\x2030\x20days,\x20service.move:38);\x20buyers\x20face\x20instantly\x20mutable\x20terms.','suggestion':'Set\x20setting_lock_duration\x20after\x20publishing\x20(30\x20days\x20=\x202592000000\x20ms\x20at\x20minimum);\x20term\x20changes\x20must\x20go\x20through\x20a\x20waiting\x20period.'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break;}return b;}},RATE_BASIS=0x2710n;function allocationStructuralIssues(a){const b=[];let c=0x0,d=![];for(const e of asList(a)){const f=e??{};let g=0x0n,h=![];for(const i of asList(f['sharing'])){const j=i??{},k=Number(j['mode']);if(k===0x2||j['mode']==='Surplus'){c++,d=!![];continue;}k===0x1||j['mode']==='Rate'?g+=big(j['sharing']):h=!![];}g!==0x0n&&g!==RATE_BASIS&&!d&&b['push']('Rate\x20allocation\x20totals\x20'+g+'\x20!=\x2010000\x20basis\x20points\x20with\x20no\x20Surplus\x20fallback;\x20payment\x20will\x20abort'),h&&(f['max']==null||big(f['max'])===0x0n)&&b['push']('Fixed-amount\x20(Amount)\x20allocation\x20Allocator\x20lacks\x20a\x20max\x20cap;\x20excess\x20transfer\x20is\x20possible\x20when\x20the\x20guard\x20triggers');}if(c>0x1)b['push'](c+'\x20Surplus\x20entries\x20(at\x20most\x201\x20is\x20legal);\x20surplus\x20ownership\x20is\x20ambiguous');return[...new Set(b)];}const A1={'id':'A1','kind':'arbitrage','run'(a){const b=[],c=(e,f,g,h)=>{const i=allocationStructuralIssues(f);if(i['length']===0x0||h['has'](e))return;h['add'](e),b['push'](makeFinding(a,'A1:'+e,'arbitrage','Allocation\x20structure\x20mismatch:\x20Rate/Surplus/max\x20configuration\x20has\x20triggerable\x20structural\x20defects',{'severity':'medium','path':[e,'allocators[].sharing'],'pathEdges':g,'roles':['neutral','system','merchant','buyer'],'detail':e+':\x20'+i['join'](';\x20')+'\x20(allocation.move:173-200).','suggestion':'Complete\x20Rate\x20groups\x20to\x2010000\x20or\x20configure\x20a\x20single\x20Surplus;\x20fixed-amount\x20Allocators\x20must\x20set\x20max;\x20run\x20the\x20allocation\x20precheck\x20before\x20going\x20live.'}));},d=new Set();for(const e of typedNodes(a,'Allocation')){c(e['id'],root(e)['allocators'],inc(a,e['id'],'order.allocation'),d);}for(const f of typedNodes(a,'Service')){const g=root(f)['order_allocators'];if(g?.['allocators'])c(f['id'],g['allocators'],edgeList(a,'service.order_allocator_guard'),d);}return b['slice'](0x0,MAX_FINDINGS_PER_RULE);}},DISCOUNT_FIXED=0x1,THIRTY_DAYS_MS=0x1en*0x18n*0x3cn*0x3cn*0x3e8n,A2={'id':'A2','kind':'arbitrage','run'(a){const b=[];for(const c of typedNodes(a,'Discount')){const e=root(c),f=big(e['time_end'])-big(e['time_start'])>=THIRTY_DAYS_MS;if(!bool(e['transferable'])||!f)continue;if(Number(e['discount_type'])!==DISCOUNT_FIXED)continue;if(e['benchmark']!=null&&e['benchmark']!=='0')continue;b['push'](makeFinding(a,'A2:'+c['id'],'arbitrage','Discount\x20combination:\x20transferable\x20+\x20long\x20validity\x20window\x20+\x20fixed-amount\x20discount\x20without\x20benchmark',{'severity':'low','path':[c['id'],'Discount.transferable/time_window/benchmark'],'roles':['neutral','system','merchant'],'detail':'Discount\x20'+c['id']+'\x20is\x20transferable,\x20valid\x20>=30\x20days,\x20is\x20a\x20fixed-amount\x20discount,\x20and\x20has\x20no\x20benchmark\x20price\x20check\x20(service.move:109-121);\x20'+'this\x20leaves\x20room\x20for\x20coupon\x20hoarding\x20and\x20resale\x20arbitrage.','suggestion':'Shorten\x20the\x20validity\x20window,\x20switch\x20to\x20RATES\x20proportional\x20discounts,\x20or\x20add\x20benchmark\x20Guards;\x20disable\x20transferable\x20if\x20needed.'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break;}return b;}},A3={'id':'A3','kind':'arbitrage','run'(a){const b=[];for(const e of typedNodes(a,'Arbitration')){const f=root(e),g=big(f['fee'])===0x0n&&!str(f['usage_guard']);g&&b['push'](makeFinding(a,'A3:'+e['id'],'arbitrage','Remedy\x20cost\x20structure:\x20zero\x20fee\x20+\x20no\x20usage\x20gate\x20gives\x20malicious\x20disputes\x20a\x20positive-expected-value\x20setup',{'severity':'medium','path':[e['id'],'Arbitration.fee','Arbitration.usage_guard'],'roles':['neutral','system','arbitrator','merchant','buyer'],'detail':'Arbitration\x20'+e['id']+'\x20has\x20fee=0\x20and\x20an\x20empty\x20usage_guard;\x20combined\x20with\x20the\x203x\x20amount\x20payout\x20cap,\x20single\x20claim,\x20'+'and\x2030-day\x20withdrawal\x20lock\x20rules\x20(arb.move:302-358,\x20order.move:86-96),\x20filing\x20a\x20malicious\x20dispute\x20carries\x20no\x20structural\x20upfront\x20cost.','suggestion':'Set\x20a\x20non-zero\x20fee\x20to\x20cover\x20adjudication\x20cost,\x20or\x20use\x20usage_guard\x20to\x20require\x20disputing\x20parties\x20to\x20hold\x20on-chain\x20participation\x20credentials.'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break;}const c=new Map();for(const h of a['visibleNodes']){const i=a['graph']['nodes']['get'](h),j=i?.['raw']?.['type_raw'];if(typeof j!=='string'||!j['includes']('::payment::CoinWrapper<'))continue;const k=j['slice'](j['indexOf']('<')+0x1,j['lastIndexOf']('>'))['trim'](),l=c['get'](k)??[];l['push'](h),c['set'](k,l);}if(c['size']>0x0){const m=[...c['keys']()]['sort']();b['push']({'id':'A3:coinwrapper','kind':'arbitrage','severity':'info','title':'Cross-coin\x20escrow\x20review\x20point:\x20CoinWrapper<K>\x20escrow\x20objects\x20exist\x20in\x20the\x20graph','path':['payment::CoinWrapper'],'confidence':'exact','roles':['neutral','system','arbitrator','merchant'],'detail':'Visible\x20CoinWrapper\x20escrow\x20covers\x20coin\x20types:\x20'+m['join'](',\x20')+'\x20('+[...c['values']()]['reduce']((o,p)=>o+p['length'],0x0)+'\x20objects).\x20'+'v1\x20performs\x20no\x20market\x20valuation;\x20remedy/allocation\x20conclusions\x20across\x20coins\x20require\x20manual\x20review\x20of\x20coin\x20mismatch\x20and\x20depeg\x20risk.','suggestion':'Verify\x20the\x20escrow\x20coin\x20type\x20matches\x20the\x20service\x20coin\x20type\x20T;\x20add\x20independent\x20exchange-rate/oracle\x20evidence\x20before\x20concluding\x20cross-coin\x20cases.'});}return b['slice'](0x0,MAX_FINDINGS_PER_RULE);}},SCARCE_PRESENTERS=0x2;function demandGuardIds(a,b){const c=new Set();for(const d of out(a,b,'demand.guard'))c['add'](d['to']);return c;}function serviceGuardIds(a,b){const c=new Set();for(const f of out(a,b['id'],'service.buy_guard'))c['add'](f['to']);const d=out(a,b['id'],'service.machine')[0x0]?.['to'];if(d)for(const g of a['visibleEdges']){if(g['schema']==='wf.forward_guard'&&g['from']['startsWith'](d+'::node::'))c['add'](g['to']);}return c;}const O1={'id':'O1','kind':'opportunity','run'(a){const b=[],c=typedNodes(a,'Service');for(const d of typedNodes(a,'Demand')){const e=out(a,d['id'],'demand.presenter');if(e['length']>=SCARCE_PRESENTERS)continue;const f=demandGuardIds(a,d['id']),g=[];for(const i of c){const j=serviceGuardIds(a,i);if(f['size']===0x0||[...f]['every'](k=>j['has'](k)))g['push'](i['id']);}const h=e;b['push'](makeFinding(a,'O1:'+d['id'],'opportunity','Open\x20demand:\x20few\x20proposals,\x20with\x20structurally\x20capable\x20suppliers\x20present',{'severity':'info','path':[d['id'],'demand.presenter','demand.guard','Service'],'pathEdges':h['concat'](out(a,d['id'],'demand.guard')),'roles':['neutral','system','supplier'],'detail':'Demand\x20'+d['id']+'\x20currently\x20has\x20only\x20'+e['length']+'\x20proposal(s);\x20matched\x20by\x20Guard\x20structure\x20(no\x20Guard\x20bytecode\x20parsing)\x20to\x20'+(g['length']+'\x20candidate\x20Service(s):\x20'+(g['slice'](0x0,0x5)['join'](',\x20')||'(no\x20match\x20in\x20graph)')+'.'),'suggestion':'Candidate\x20suppliers\x20can\x20prepare\x20present\x20evidence\x20(proof\x20of\x20satisfying\x20the\x20demand\x20Guards);\x20the\x20opportunity\x20conclusion\x20is\x20structural\x20only\x20and\x20does\x20not\x20endorse\x20fulfillment\x20capability.'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break;}return b;}},O2={'id':'O2','kind':'opportunity','run'(a){const b=typedNodes(a,'Service'),c=typedNodes(a,'Demand');if(b['length']===0x0&&c['length']===0x0)return[];const d=b['filter'](f=>bool(root(f)['bPublished'])&&!bool(root(f)['bPaused']))['length'],e=c['filter'](f=>out(a,f['id'],'demand.presenter')['length']===0x0)['length'];return[makeFinding(a,'O2:graph','opportunity','Supply/demand\x20density:\x20in-graph\x20supply\x20and\x20open-demand\x20statistics',{'path':['Service','Demand','demand.presenter'],'pathEdges':edgeList(a,'demand.presenter'),'roles':['neutral','system','supplier','merchant'],'detail':'In\x20the\x20current\x20viewport:\x20'+b['length']+'\x20Service(s)\x20('+d+'\x20published\x20and\x20unpaused),\x20'+c['length']+'\x20Demand(s)\x20'+('('+e+'\x20open\x20demand(s)\x20without\x20proposals).\x20Open-demand/active-supply\x20ratio\x20=\x20')+((d>0x0?(e/d)['toFixed'](0x3):'n/a')+'.'),'suggestion':'A\x20high\x20ratio\x20indicates\x20scarce\x20supply;\x20use\x20category\x20exact-match\x20counts\x20(collectors\x20category_enumerated_count)\x20to\x20pick\x20an\x20entry\x20category.'})];}},O3={'id':'O3','kind':'opportunity','run'(a){const b=[];for(const c of machineViews(a)){const d=new Map();for(const g of c['transitions']){if(str(g['payload']?.['namedOperator'])||g['payload']?.['permissionIndex']!=null)continue;const h=String(g['payload']?.['forward']??g['payload']?.['prevNode']+'→'+g['payload']?.['node']);d['set'](wfNodeName(g['from'])+':'+h,g);}if(d['size']===0x0)continue;const f=[...d['values']()];b['push'](makeFinding(a,'O3:'+c['machine']['id'],'opportunity','Workflow\x20gaps:\x20key\x20Forwards\x20have\x20no\x20operator\x20binding\x20(guard/payment\x20passthrough\x20only)',{'path':[c['machine']['id'],'machine.node','wf.transition'],'pathEdges':f,'roles':['neutral','system','supplier','collaborator','merchant'],'detail':'Machine\x20'+c['machine']['id']+'\x20has\x20'+d['size']+'\x20Forward(s)\x20without\x20namedOperator/permissionIndex\x20binding:\x20'+([...d['keys']()]['slice'](0x0,0x8)['join'](',\x20')+'.\x20These\x20slots\x20can\x20only\x20be\x20satisfied\x20automatically\x20by\x20guards\x20or\x20advanced\x20directly\x20by\x20payment\x20transactions.'),'suggestion':'Suppliers/collaborators\x20can\x20take\x20over\x20these\x20operator\x20slots,\x20or\x20push\x20the\x20merchant\x20to\x20convert\x20implicit\x20passthrough\x20into\x20explicit\x20role\x20bindings.'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break;}return b;}};function arbitrationCases(a,b){return inc(a,b,'arb.arbitration_service')['map'](c=>a['graph']['nodes']['get'](c['from']))['filter'](c=>!!c&&c['objectType']==='Arb'&&!!c['raw']);}const G1={'id':'G1','kind':'game','run'(a){const b=[];for(const e of typedNodes(a,'Arbitration')){const f=root(e),g=asList(f['voting_guard']),h=new Set(g['map'](l=>l['vote_weight']&&typeof l['vote_weight']==='object'?Object['keys'](l['vote_weight'])[0x0]:'unknown')),i=arbitrationCases(a,e['id']),j=new Map();let k=0x0;for(const l of i){for(const m of asList(root(l)['voted'])){const n=Number(m['weight']??0x0);j['set'](n,(j['get'](n)??0x0)+0x1),k++;}}b['push'](makeFinding(a,'G1:'+e['id'],'game','Voting\x20power\x20structure:\x20arbitration\x20voting\x20Guard\x20configuration\x20vs\x20actual\x20voting\x20weight\x20distribution',{'severity':'info','path':[e['id'],'arbitration.voting_guard','arb.arbitration_service','arb.voter'],'pathEdges':out(a,e['id'],'arbitration.voting_guard')['concat'](edgeList(a,'arb.voter')),'roles':['neutral','system','arbitrator','merchant','buyer'],'detail':'Arbitration\x20'+e['id']+':\x20voting_guard\x20'+(g['length']===0x0?'empty\x20=\x20open\x20to\x20all\x20members\x20(arbitration.move:48-59)':'weighted\x20('+[...h]['join']('/')+')')+';\x20'+(i['length']+'\x20case(s)\x20in\x20window,\x20'+k+'\x20actual\x20vote(s)')+(j['size']?',\x20weight\x20distribution\x20'+[...j['entries']()]['map'](([o,p])=>'w'+o+'x'+p)['join'](',\x20'):'')+'.','suggestion':'Open\x20voting\x20suits\x20high-frequency\x20low-stakes\x20cases;\x20high-stakes\x20cases\x20should\x20use\x20weighted\x20Guards;\x20this\x20describes\x20the\x20objective\x20situation\x20only\x20—\x20scoring\x20belongs\x20to\x20the\x20game\x20modules.'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break;}return b;}},G2={'id':'G2','kind':'game','run'(a){const b=[];n:for(const c of machineViews(a)){const d=out(a,c['machine']['id'],'machine.permission')[0x0]?.['to'],f=d?inc(a,d,'permission.entity')['map'](h=>({'eoa':h['to'],'bits':h['payload']?.['permIndices']??[]})):[],g=new Set();for(const h of c['transitions']){const i=String(h['payload']?.['forward']??h['payload']?.['prevNode']+'→'+h['payload']?.['node']),j=wfNodeName(h['from'])+':'+i;if(g['has'](j))continue;let k,l='';if(str(h['payload']?.['namedOperator']))k=0x1,l='namedOperator='+h['payload']['namedOperator'];else{if(h['payload']?.['permissionIndex']!=null){if(!d)continue;const m=Number(h['payload']['permissionIndex']);k=f['filter'](n=>n['bits']['includes'](m))['length'],l='permissionIndex='+m;if(k===0x0)continue;}else continue;}if(k!==0x1)continue;g['add'](j),b['push'](makeFinding(a,'G2:'+c['machine']['id']+':'+j,'game','Operator\x20replaceable\x20pool\x20=\x201:\x20hold-up\x20slot',{'severity':'low','path':[c['machine']['id'],'machine.node','wf.transition',j],'pathEdges':[h],'roles':['neutral','system','collaborator','merchant','supplier'],'detail':'Forward\x20'+j+'\x20('+l+')\x20on\x20Machine\x20'+c['machine']['id']+'\x20has\x20an\x20operable-party\x20pool\x20of\x20size\x201:\x20'+'that\x20party\x20holds\x20an\x20irreplaceable\x20bargaining\x20position\x20at\x20this\x20workflow\x20node\x20(machine.move\x20operation\x20precheck).','suggestion':'Add\x20an\x20alternative\x20entity\x20under\x20the\x20same\x20permissionIndex\x20or\x20a\x20namedOperator\x20backup;\x20sign\x20SLA/penalty\x20terms\x20covering\x20this\x20slot.'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break n;}}return b;}},G3={'id':'G3','kind':'game','run'(a){const b=[];for(const c of typedNodes(a,'Arbitration')){const e=root(c),f=asList(e['voting_guard']);b['push'](makeFinding(a,'G3:'+c['id'],'game','Remedy\x20strategy\x20parameters:\x20structured\x20inputs\x20for\x20the\x20payoff/waiting\x20matrices',{'severity':'info','path':[c['id'],'Arbitration.fee/usage_guard/voting_guard'],'roles':['neutral','system','arbitrator','merchant','buyer'],'detail':'Arbitration\x20'+c['id']+':\x20fee='+big(e['fee'])+',\x20usage_guard='+(str(e['usage_guard'])??'none')+',\x20voting_guard='+f['length']+'.\x20'+'Global\x20structural\x20constants:\x20payout\x20cap\x203x\x20amount,\x2030-day\x20compensation\x20withdrawal\x20lock,\x20single\x20claim\x20per\x20payout,\x2030-day\x20withdraw/objection\x20window\x20'+'(arb.move:302-358,\x20order.move:86-96).','suggestion':'Feed\x20these\x20parameters\x20into\x20node-game/arbitration-game\x20payoff\x20and\x20waiting\x20matrices;\x20this\x20analyzer\x20does\x20not\x20score\x20or\x20rank.'}));if(b['length']>=MAX_FINDINGS_PER_RULE)break;}return b;}},ANTI_CHEAT_ROLES=['neutral','system','merchant','buyer'];function projectOrderEvidence(a,b){const c=[];for(const d of typedNodes(a,'Service')){const f=[...b['controllers']['get'](d['id'])??[]];if(f['length']===0x0)continue;for(const g of out(a,d['id'],'service.order')){const h=a['graph']['nodes']['get'](g['to']);if(!h||h['kind']!=='object'||h['objectType']!=='Order'||!h['raw'])continue;const i=out(a,h['id'],'order.builder')[0x0]?.['to'];if(!i)continue;const j=orderCompletionInGraph(a['graph'],h['id'])['status'],k=String(root(h)?.['amount']??0x0),l=out(a,h['id'],'order.allocation')[0x0]?.['to']??null;for(const m of f){c['push']({'service':d['id'],'id':h['id'],'buyer':i,'seller':m,'amount':k,'status':j,'allocation':l});}}}return c;}function orderCheatEdges(a){return edgeList(a,'service.order')['concat'](edgeList(a,'eoa.permission'))['concat'](edgeList(a,'permission.core_binding'));}function shortRefs(a){const b=a['slice'](0x0,0x5)['join'](',\x20');return a['length']>0x5?b+'\x20and\x20'+a['length']+'\x20object(s)\x20in\x20total':b;}const AC1={'id':'AC1','kind':'risk','run'(a){const b=projectOrderEvidence(a,buildControlIndex(a)),c=detectFakeOrders(b)['find'](e=>e['code']==='self_buy');if(!c)return[];const d=c['refs']??[];return[makeFinding(a,'AC1:'+d['join'](','),'risk','Fake-order\x20suspicion:\x20windowed\x20order\x20buyers\x20are\x20the\x20selling\x20service\x27s\x20controlling\x20EOA\x20(self-trading)',{'severity':'high','path':['EOA','eoa.permission','permission.core_binding','Service','service.order','Order','order.builder'],'pathEdges':orderCheatEdges(a),'roles':ANTI_CHEAT_ROLES,'detail':d['length']+'\x20order(s)\x20visible\x20in\x20the\x20window\x20have\x20buyer\x20EOAs\x20that\x20also\x20control\x20the\x20selling\x20Service\x20as\x20owner/admin\x20'+('('+shortRefs(d)+'):\x20buyer\x20and\x20seller\x20sit\x20in\x20the\x20same\x20control\x20set,\x20funds\x20circulate\x20internally,\x20and\x20this\x20is\x20not\x20genuine\x20competitive\x20volume.'),'suggestion':'Exclude\x20these\x20orders\x20from\x20sales/reputation\x20statistics\x20and\x20re-verify\x20via\x20payment\x20allocation\x20legs\x20and\x20time\x20windows;\x20reduce\x20market\x20exposure\x20and\x20recommendation\x20weight\x20for\x20this\x20Service.'})];}},AC2={'id':'AC2','kind':'risk','run'(a){const b=projectOrderEvidence(a,buildControlIndex(a)),c=detectFakeOrders(b)['find'](e=>e['code']==='reciprocal_loop');if(!c)return[];const d=c['refs']??[];return[makeFinding(a,'AC2:'+d['join'](','),'risk','Wash-trading\x20suspicion:\x20reciprocal\x20buy/sell\x20role-swapping\x20fund\x20loops\x20in\x20the\x20window',{'severity':c['severity'],'path':['EOA-A','order.builder','Order@Service-B','service.order','EOA-B','order.builder','Order@Service-A'],'pathEdges':orderCheatEdges(a),'roles':ANTI_CHEAT_ROLES,'detail':d['length']+'\x20order(s)\x20in\x20the\x20window\x20form\x20a\x20buy/sell\x20swap:\x20control\x20set\x20A\x20buys\x20B\x27s\x20Service\x20while\x20control\x20set\x20B\x20buys\x20A\x27s\x20Service\x20'+('('+shortRefs(d)+').\x20The\x20two-way\x20volume\x20may\x20be\x20mutually\x20staged\x20wash\x20trading.'),'suggestion':'Investigate\x20links\x20between\x20the\x20two\x20control\x20sets\x20(devices/permissions/fund\x20flows);\x20exclude\x20mutually-purchased\x20orders\x20from\x20genuine\x20competitive\x20volume.'})];}},AC3={'id':'AC3','kind':'risk','run'(a){const b=projectOrderEvidence(a,buildControlIndex(a)),c=detectFakeOrders(b)['find'](e=>e['code']==='no_allocation');if(!c)return[];const d=c['refs']??[];return[makeFinding(a,'AC3:'+d['join'](','),'risk','Missing\x20fund\x20closure:\x20completed\x20positive-amount\x20orders\x20lack\x20an\x20Allocation\x20object',{'severity':c['severity'],'path':['Service','service.order','Order','order.allocation'],'pathEdges':orderCheatEdges(a),'roles':ANTI_CHEAT_ROLES,'detail':d['length']+'\x20completed\x20order(s)\x20in\x20the\x20window\x20(completion\x20authoritatively\x20judged\x20by\x20the\x20order-status\x20terminal\x20node\x20set)\x20with\x20amount>0\x20have\x20no\x20Allocation\x20'+('('+shortRefs(d)+').\x20order.move\x20L130\x20requires\x20positive-amount\x20orders\x20to\x20have\x20an\x20allocation\x20path;\x20its\x20absence\x20means\x20the\x20\x22transaction\x22\x20lacks\x20fund-closure\x20evidence.\x20')+'Zero-amount\x20orders\x20are\x20excluded\x20(no\x20fund\x20flow).','suggestion':'Review\x20original\x20payment\x20records;\x20completed\x20orders\x20without\x20payment\x20evidence\x20must\x20not\x20count\x20toward\x20reputation;\x20audit\x20contract\x20entry\x20points\x20that\x20complete\x20without\x20an\x20Allocation\x20path.'})];}},SHELL_COPY={'shell_no_arbitration':{'title':'Shell\x20merchant:\x20published\x20Service\x20has\x20no\x20arbitration\x20binding,\x20disputes\x20have\x20no\x20remedy\x20path','detail':'The\x20Service\x20is\x20published\x20but\x20arbitrations\x20is\x20empty:\x20buyers\x20have\x20no\x20selectable\x20arbitration\x20service\x20after\x20ordering\x20and\x20disputes\x20cannot\x20enter\x20adjudication.','suggestion':'Bind\x20at\x20least\x20one\x20Arbitration\x20in\x20a\x20different\x20group\x20than\x20the\x20shop\x20Permission\x20before\x20publishing;\x20shops\x20without\x20a\x20remedy\x20path\x20should\x20not\x20be\x20recommended.'},'shell_funded_no_arbitration':{'title':'Floating\x20payout\x20funds:\x20compensation\x20fund\x20is\x20funded\x20but\x20no\x20Arbitration\x20exists,\x20payouts\x20cannot\x20be\x20adjudicated\x20or\x20released','detail':'compensation_fund>0\x20with\x20no\x20Arbitration\x20at\x20all:\x20when\x20a\x20payout\x20triggers\x20there\x20is\x20no\x20one\x20to\x20adjudicate\x20and\x20no\x20path\x20to\x20release;\x20the\x20funding\x20is\x20marketing\x20theater.','suggestion':'Bind\x20an\x20arbitration\x20service\x20before\x20advertising\x20payout\x20guarantees;\x20marketplaces\x20should\x20flag\x20\x27fund\x20without\x20arbitration\x27\x20as\x20high\x20risk\x20and\x20limit\x20exposure.'},'shell_no_machine':{'title':'Shell\x20merchant:\x20published\x20Service\x20has\x20no\x20Machine\x20binding,\x20no\x20structured\x20fulfillment\x20workflow','detail':'The\x20Service\x20is\x20published\x20but\x20machine\x20is\x20empty:\x20no\x20frozen\x20workflow\x20template\x20exists,\x20and\x20delivery/completion\x20nodes\x20carry\x20no\x20on-chain\x20structural\x20constraints.','suggestion':'Bind\x20and\x20publish\x20a\x20Machine\x20before\x20opening;\x20published\x20shops\x20without\x20workflows\x20suit\x20only\x20instant\x20spot-delivery\x20categories.'}},AC4={'id':'AC4','kind':'risk','run'(a){const b=[];for(const c of typedNodes(a,'Service')){const e=root(c);if(!bool(e['bPublished']))continue;const f=e['arbitrations']!=null?asList(e['arbitrations'])['length']:out(a,c['id'],'service.arbitration')['length'],g=str(e['machine'])??out(a,c['id'],'service.machine')[0x0]?.['to']??null,h=detectShellMerchant({'object':c['id'],'arbitrations':Array(f)['fill']('x'),'compensation_fund':String(big(e['compensation_fund'])),'machine':g,'bPublished':!![]}),i=out(a,c['id'],'service.arbitration')['concat'](out(a,c['id'],'service.machine'));for(const j of h){const k=SHELL_COPY[j['code']];if(!k)continue;b['push'](makeFinding(a,'AC4:'+c['id']+':'+j['code'],'risk',k['title'],{'severity':j['severity'],'path':[c['id'],'Service.bPublished','Service.arbitrations','Service.machine','Service.compensation_fund'],'pathEdges':i,'roles':ANTI_CHEAT_ROLES,'detail':k['detail']+'\x20(object:\x20'+c['id']+')','suggestion':k['suggestion']}));if(b['length']>=MAX_FINDINGS_PER_RULE)return b;}}return b;}};export const DEFAULT_ANALYZERS=[R1,R2,R3,R4,R5,R6,A1,A2,A3,O1,O2,O3,G1,G2,G3,AC1,AC2,AC3,AC4];const registry=new Map(DEFAULT_ANALYZERS['map'](b=>[b['id'],b]));export function registerAnalyzer(a){registry['set'](a['id'],a);}export function getAnalyzer(a){return registry['get'](a);}export function listAnalyzers(){return[...registry['keys']()];}export function runAnalyzers(a,b){const c=b?.['only']?new Set(b['only']):undefined,d=[];for(const e of registry['values']()){if(c&&!c['has'](e['id']))continue;if(b?.['kinds']&&!b['kinds']['includes'](e['kind']))continue;try{d['push'](...e['run'](a));}catch{}}return d;}export function adaptNodeAnalyzer(a){return{'id':a['id'],'kind':a['kind'],'objectType':a['objectType'],'run'(b,c){const d=a['inspect'](b,c);return d['map']((e,f)=>({'id':a['id']+':'+b['id']+'#'+f,'kind':a['kind'],'severity':e['severity']??'info','title':e['title'],'path':[b['id']],'confidence':e['confidence']??'exact','roles':e['roles']??['neutral'],'detail':e['detail'],'suggestion':e['suggestion']}));}};}export function runNodeAnalyzers(a,b){const c=[];for(const d of b){for(const e of typedNodes(a,d['objectType'])){try{c['push'](...d['run'](e,a));}catch{}}}return c;}
@@ -1 +1 @@
1
- import{describe,it,expect}from'vitest';import{ENTRYPOINT}from'@wowok/wowok';import{buildViewport,runAnalyzers,runNodeAnalyzers,adaptNodeAnalyzer,listAnalyzers,registerAnalyzer}from'./index.js';const FAMILY={'eoa.permission':'R','permission.core_binding':'R','permission.entity':'W','service.order':'R','service.machine':'F','service.buy_guard':'F','machine.permission':'F','machine.node':'W','wf.transition':'W','wf.forward_guard':'W','order.allocation':'F','demand.guard':'R','demand.presenter':'R','arbitration.voting_guard':'F','arb.arbitration_service':'F','arb.voter':'S'};class GB{['nodes']=new Map();['edges']=[];['out']=new Map();['inc']=new Map();['truncations']=[];['eoa'](a){return this['nodes']['set'](a,{'id':a,'kind':'eoa','state':'fetched','origins':[],'depth':0x0}),this;}['obj'](a,b,c,d){return this['nodes']['set'](a,{'id':a,'kind':'object','objectType':b,'state':'fetched','origins':[],'depth':0x1,'raw':{'object':a,'type':b,...d?{'type_raw':d}:{},'data':c}}),this;}['edge'](a,b,c,d,f,g=![]){const h={'id':a+'|'+b+'→'+c+(d?.['forward']?'|'+d['forward']:''),'schema':a,'family':FAMILY[a]??'F','from':b,'to':c,'retention':f??(FAMILY[a]==='R'?'bounded_exact':'complete'),'evidence':'test','observedAt':0x1,...d?{'payload':d}:{},...g?{'truncated':!![]}:{}};return this['edges']['push'](h),(this['out']['get'](b)??this['out']['set'](b,[])['get'](b))['push'](h),(this['inc']['get'](c)??this['inc']['set'](c,[])['get'](c))['push'](h),h;}['trunc'](a,b,c){return this['truncations']['push']({'nodeId':a,'schema':b,'observed':c,'limit':0x1450}),this;}['build'](a='0xseed'){return{'network':ENTRYPOINT['Mainnet'],'seed':a,'builtAt':0x1,'nodes':this['nodes'],'edges':this['edges'],'out':this['out'],'inc':this['inc'],'gaps':[],'truncations':this['truncations'],'rpcReport':{'batches':0x0,'byChannel':{'objects':0x0,'keyedFields':0x0,'tables':0x0,'events':0x0},'dedupHits':0x0},'budgetExhausted':{}};}['vp'](a='0xseed',b='neutral'){return buildViewport(this['build'](a),a,b);}}const ids=a=>a['map'](b=>b['id']);describe('analyze\x20—\x20registry',()=>{it('ships\x20the\x2019\x20rules\x20(R1-6/A1-3/O1-3/G1-3\x20+\x20anti-cheat\x20AC1-4)',()=>{expect(listAnalyzers()['sort']())['toEqual'](['R1','R2','R3','R4','R5','R6','A1','A2','A3','O1','O2','O3','G1','G2','G3','AC1','AC2','AC3','AC4']['sort']());}),it('is\x20fail-soft:\x20a\x20throwing\x20analyzer\x20never\x20aborts\x20the\x20suite',()=>{registerAnalyzer({'id':'__boom','kind':'risk','run':()=>{throw new Error('boom');}});const a=new GB()['obj']('0xs1','Service',{'bPublished':!![],'setting_lock_duration':'0'})['vp'](),b=runAnalyzers(a,{'only':['__boom','R6']});expect(ids(b))['toContain']('R6:0xs1'),expect(b['find'](c=>c['id']['startsWith']('__boom')))['toBeUndefined']();}),it('adapts\x20single-object\x20legacy\x20rules\x20through\x20the\x20NodeAnalyzer\x20bridge',()=>{const a=adaptNodeAnalyzer({'id':'legacy-lock','kind':'risk','objectType':'Service','inspect':e=>{const f=e['raw']['data']??{};return f['setting_lock_duration']==='0'?[{'titleZh':'锁','detailZh':'d','suggestionZh':'s','roles':['merchant']}]:[];}}),b=new GB()['obj']('0xs1','Service',{'bPublished':!![],'setting_lock_duration':'0'})['vp'](),c=runNodeAnalyzers(b,[a]);expect(c)['toHaveLength'](0x1),expect(c[0x0]['id'])['toBe']('legacy-lock:0xs1#0'),expect(c[0x0]['kind'])['toBe']('risk');});}),describe('analyze\x20—\x20risk\x20rules',()=>{it('R6\x20flags\x20published\x20services\x20without\x20a\x20setting\x20lock',()=>{const a=new GB()['obj']('0xs1','Service',{'bPublished':!![],'setting_lock_duration':'0'})['obj']('0xs2','Service',{'bPublished':!![],'setting_lock_duration':'2592000000'})['obj']('0xs3','Service',{'bPublished':![],'setting_lock_duration':'0'})['vp'](),b=runAnalyzers(a,{'only':['R6']});expect(ids(b))['toEqual'](['R6:0xs1']);}),it('R2\x20measures\x20the\x20compensation\x20fund\x20against\x203x\x20windowed\x20order\x20volume',()=>{const a=new GB();a['obj']('0xs1','Service',{'bPublished':!![],'compensation_fund':'100'}),a['obj']('0xo1','Order',{'amount':'100'}),a['obj']('0xo2','Order',{'amount':'100'}),a['edge']('service.order','0xs1','0xo1',undefined,'bounded_window'),a['edge']('service.order','0xs1','0xo2',undefined,'bounded_window',!![]);const b=runAnalyzers(a['vp'](),{'only':['R2']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['severity'])['toBe']('high'),expect(b[0x0]['confidence'])['toBe']('windowed'),expect(b[0x0]['window']?.['limit'])['toBe'](0x1450);}),it('R1\x20flags\x20one\x20EOA\x20controlling\x20a\x20shop\x20and\x20an\x20arbitration\x20service\x20across\x20distinct\x20permissions',()=>{const a=new GB();a['eoa']('0xe1'),a['obj']('0xp1','Permission',{'owner':'0xe1'}),a['obj']('0xp2','Permission',{'owner':'0xe1'}),a['obj']('0xs1','Service',{}),a['obj']('0xa1','Arbitration',{'fee':'0'}),a['edge']('eoa.permission','0xe1','0xp1',{'roleBits':0x3}),a['edge']('eoa.permission','0xe1','0xp2',{'roleBits':0x3}),a['edge']('permission.core_binding','0xp1','0xs1'),a['edge']('permission.core_binding','0xp2','0xa1');const b=runAnalyzers(a['vp'](),{'only':['R1']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['severity'])['toBe']('high');const c=new GB();c['eoa']('0xe1')['obj']('0xp1','Permission',{})['obj']('0xs1','Service',{})['obj']('0xa1','Arbitration',{'fee':'0'}),c['edge']('eoa.permission','0xe1','0xp1',{'roleBits':0x3}),c['edge']('permission.core_binding','0xp1','0xs1'),c['edge']('permission.core_binding','0xp1','0xa1'),expect(runAnalyzers(c['vp'](),{'only':['R1']}))['toHaveLength'](0x0);}),it('R3\x20flags\x20concentrated\x20control\x20of\x20core\x20objects',()=>{const a=new GB();a['eoa']('0xe1')['obj']('0xp1','Permission',{}),a['obj']('0xs1','Service',{})['obj']('0xs2','Service',{})['obj']('0xm1','Machine',{}),a['edge']('eoa.permission','0xe1','0xp1',{'roleBits':0x1});for(const c of['0xs1','0xs2','0xm1'])a['edge']('permission.core_binding','0xp1',c);const b=runAnalyzers(a['vp'](),{'only':['R3']});expect(ids(b))['toEqual'](['R3:0xe1']);}),it('R4\x20flags\x20a\x20unique\x20operator\x20with\x20no\x20backup\x20guard\x20on\x20a\x20terminal-entering\x20forward',()=>{const a=new GB();a['obj']('0xm1','Machine',{'bPublished':!![]}),a['edge']('wf.transition','0xm1::node::paid','0xm1::node::delivered',{'node':'delivered','prevNode':'paid','forward':'go','namedOperator':'alice'});const b=runAnalyzers(a['vp'](),{'only':['R4']});expect(b)['toHaveLength'](0x1);const c=new GB();c['obj']('0xm1','Machine',{'bPublished':!![]}),c['edge']('wf.transition','0xm1::node::paid','0xm1::node::delivered',{'node':'delivered','prevNode':'paid','forward':'go','namedOperator':'alice','guard':'0xg1'}),expect(runAnalyzers(c['vp'](),{'only':['R4']}))['toHaveLength'](0x0);}),it('R5\x20reports\x20window\x20truncations\x20as\x20downgraded\x20meta\x20findings',()=>{const a=new GB()['obj']('0xs1','Service',{})['trunc']('0xs1','service.order',0x1450),b=runAnalyzers(a['vp'](),{'only':['R5']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['confidence'])['toBe']('windowed'),expect(b[0x0]['window'])['toEqual']({'observed':0x1450,'limit':0x1450});});}),describe('analyze\x20—\x20arbitrage\x20rules',()=>{it('A1\x20detects\x20rate-basis\x20mismatch,\x20surplus\x20duplication\x20and\x20missing\x20max',()=>{const a=new GB();a['obj']('0xal1','Allocation',{'allocators':[{'guard':'0xg1','max':null,'sharing':[{'who':'0xa','mode':0x0,'sharing':'100'}]},{'guard':'0xg2','sharing':[{'who':'0xb','mode':0x1,'sharing':'9000'}]},{'guard':'0xg3','sharing':[{'who':'0xc','mode':0x2}]},{'guard':'0xg4','sharing':[{'who':'0xd','mode':0x2}]}]});const b=runAnalyzers(a['vp'](),{'only':['A1']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['detailZh'])['toContain']('9000'),expect(b[0x0]['detailZh'])['toContain']('max'),expect(b[0x0]['detailZh'])['toContain']('Surplus');}),it('A2\x20flags\x20transferable\x20fixed\x20long-window\x20discounts\x20without\x20a\x20benchmark',()=>{const a=new GB();a['obj']('0xd1','Discount',{'discount_type':0x1,'benchmark':null,'transferable':!![],'time_start':'0','time_end':String(0x1fn*0x18n*0x3cn*0x3cn*0x3e8n)});const b=runAnalyzers(a['vp'](),{'only':['A2']});expect(b)['toHaveLength'](0x1);const c=new GB();c['obj']('0xd2','Discount',{'discount_type':0x1,'benchmark':null,'transferable':![],'time_start':'0','time_end':String(0x1fn*0x18n*0x3cn*0x3cn*0x3e8n)}),expect(runAnalyzers(c['vp'](),{'only':['A2']}))['toHaveLength'](0x0);}),it('A3\x20flags\x20zero-fee/no-usage-guard\x20arbitration\x20and\x20reports\x20CoinWrapper\x20custody',()=>{const a=new GB();a['obj']('0xa1','Arbitration',{'fee':'0','usage_guard':null,'voting_guard':[]}),a['obj']('0xcw1','Payment',{},'0x2::payment::CoinWrapper<0x2::wow::WOW>');const b=runAnalyzers(a['vp'](),{'only':['A3']});expect(ids(b)['sort']())['toEqual'](['A3:0xa1','A3:coinwrapper']),expect(b['find'](c=>c['id']==='A3:coinwrapper')['detailZh'])['toContain']('0x2::wow::WOW');});}),describe('analyze\x20—\x20opportunity\x20rules',()=>{it('O1\x20surfaces\x20scarce-presenter\x20demands\x20with\x20structurally\x20matching\x20services',()=>{const a=new GB();a['obj']('0xdm1','Demand',{'guards':[{'guard':'0xg1'}]}),a['edge']('demand.guard','0xdm1','0xg1'),a['obj']('0xs1','Service',{'bPublished':!![]}),a['obj']('0xm1','Machine',{}),a['edge']('service.machine','0xs1','0xm1'),a['edge']('wf.forward_guard','0xm1::node::paid','0xg1');const b=runAnalyzers(a['vp'](),{'only':['O1']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['detailZh'])['toContain']('0xs1'),a['eoa']('0u1')['eoa']('0u2'),a['edge']('demand.presenter','0xdm1','0u1',{'service':'0xs1'}),a['edge']('demand.presenter','0xdm1','0u2',{'service':'0xs1'}),expect(runAnalyzers(a['vp'](),{'only':['O1']}))['toHaveLength'](0x0);}),it('O2\x20reports\x20graph\x20supply/demand\x20density',()=>{const a=new GB();a['obj']('0xs1','Service',{'bPublished':!![],'bPaused':![]}),a['obj']('0xs2','Service',{'bPublished':![]}),a['obj']('0xd1','Demand',{});const b=runAnalyzers(a['vp'](),{'only':['O2']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['detailZh'])['toContain']('Service\x202'),expect(b[0x0]['detailZh'])['toContain']('开放需求\x201');}),it('O3\x20lists\x20operator-less\x20forwards\x20as\x20workflow\x20slots',()=>{const a=new GB();a['obj']('0xm1','Machine',{}),a['edge']('wf.transition','0xm1::node::paid','0xm1::node::done',{'node':'done','prevNode':'paid','forward':'auto','namedOperator':null,'permissionIndex':null,'guard':'0xg1'});const b=runAnalyzers(a['vp'](),{'only':['O3']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['detailZh'])['toContain']('paid:auto');});}),describe('analyze\x20—\x20game\x20rules',()=>{it('G1\x20reports\x20all-vote\x20vs\x20weighted\x20structures\x20plus\x20observed\x20case\x20weights',()=>{const a=new GB();a['obj']('0xa1','Arbitration',{'fee':'0','voting_guard':[]}),a['obj']('0xcase1','Arb',{'voted':[{'voter':'0u1','weight':0x1},{'voter':'0u2','weight':0x2}]}),a['edge']('arb.arbitration_service','0xcase1','0xa1');const b=runAnalyzers(a['vp'](),{'only':['G1']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['detailZh'])['toContain']('全员可投'),expect(b[0x0]['detailZh'])['toContain']('w1×1'),expect(b[0x0]['detailZh'])['toContain']('w2×1');}),it('G2\x20marks\x20a\x20named-operator\x20forward\x20as\x20a\x20pool-of-one\x20hold-up\x20point',()=>{const a=new GB();a['obj']('0xm1','Machine',{}),a['edge']('wf.transition','0xm1::node::paid','0xm1::node::done',{'node':'done','prevNode':'paid','forward':'sign','namedOperator':'bob'});const b=runAnalyzers(a['vp'](),{'only':['G2']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['id'])['toContain']('paid:sign');}),it('G3\x20emits\x20the\x20relief\x20parameter\x20matrix\x20for\x20every\x20arbitration\x20service',()=>{const a=new GB();a['obj']('0xa1','Arbitration',{'fee':'5','usage_guard':'0xg1','voting_guard':[{'guard':'0xg2'}]});const b=runAnalyzers(a['vp'](),{'only':['G3']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['detailZh'])['toContain']('fee=5'),expect(b[0x0]['detailZh'])['toContain']('30\x20天');});}),describe('analyze\x20—\x20anti-cheat\x20rules\x20(AC1-AC4)',()=>{function a(c,d,e,f){c['eoa'](d),c['edge']('eoa.permission',d,e,{'roleBits':0x1|0x2}),c['edge']('permission.core_binding',e,f);}function b(c,d,e,f){c['obj'](e,'Order',f),c['edge']('service.order',d,e,undefined,'bounded_window'),c['edge']('order.builder',e,String(f['builder']));}it('AC1\x20flags\x20window\x20orders\x20whose\x20buyer\x20controls\x20the\x20selling\x20Service',()=>{const c=new GB();c['obj']('0xs1','Service',{'bPublished':!![],'machine':'0xm1'}),a(c,'0u1','0p1','0xs1'),b(c,'0xs1','0o1',{'builder':'0u1','service':'0xs1','amount':'100'});const d=runAnalyzers(c['vp'](),{'only':['AC1']});expect(d)['toHaveLength'](0x1),expect(d[0x0]['severity'])['toBe']('high'),expect(d[0x0]['confidence'])['toBe']('windowed'),expect(d[0x0]['id'])['toContain']('0o1');const e=new GB();e['obj']('0xs1','Service',{'bPublished':!![],'machine':'0xm1'}),a(e,'0u1','0p1','0xs1'),b(e,'0xs1','0o1',{'builder':'0u2','service':'0xs1','amount':'100'}),expect(runAnalyzers(e['vp'](),{'only':['AC1']}))['toEqual']([]);}),it('AC2\x20flags\x20reciprocal\x20buying\x20between\x20two\x20controlled\x20Services',()=>{const c=new GB();c['obj']('0xs1','Service',{'bPublished':!![],'machine':'0xm1'}),c['obj']('0xs2','Service',{'bPublished':!![],'machine':'0xm2'}),a(c,'0u1','0p1','0xs1'),a(c,'0u2','0p2','0xs2'),b(c,'0xs1','0o1',{'builder':'0u2','service':'0xs1','amount':'100'}),b(c,'0xs2','0o2',{'builder':'0u1','service':'0xs2','amount':'100'});const d=runAnalyzers(c['vp'](),{'only':['AC2']});expect(d)['toHaveLength'](0x1),expect(d[0x0]['severity'])['toBe']('medium'),expect(d[0x0]['id'])['toContain']('0o1'),expect(d[0x0]['id'])['toContain']('0o2');}),it('AC3\x20flags\x20completed\x20positive-amount\x20orders\x20without\x20Allocation,\x20but\x20not\x20zero-amount\x20orders',()=>{const c=new GB();c['obj']('0xs1','Service',{'bPublished':!![],'machine':'0xm1'}),a(c,'0u1','0p1','0xs1'),b(c,'0xs1','0opaid',{'builder':'0u9','service':'0xs1','amount':'100'}),b(c,'0xs1','0ofree',{'builder':'0u8','service':'0xs1','amount':'0'});const d=runAnalyzers(c['vp'](),{'only':['AC3']});expect(d)['toHaveLength'](0x1),expect(d[0x0]['id'])['toContain']('0opaid'),expect(d[0x0]['id'])['not']['toContain']('0ofree'),c['edge']('order.allocation','0opaid','0al1'),expect(runAnalyzers(c['vp'](),{'only':['AC3']}))['toEqual']([]);}),it('AC4\x20surfaces\x20shell-merchant\x20shapes\x20only\x20for\x20published\x20Services',()=>{const c=new GB();c['obj']('0xs1','Service',{'bPublished':!![],'arbitrations':[],'compensation_fund':'0'});const d=runAnalyzers(c['vp'](),{'only':['AC4']});expect(ids(d)['sort']())['toEqual'](['AC4:0xs1:shell_no_arbitration','AC4:0xs1:shell_no_machine']['sort']());const e=new GB();e['obj']('0xs2','Service',{'bPublished':!![],'arbitrations':[],'compensation_fund':'500'});const f=runAnalyzers(e['vp'](),{'only':['AC4']});expect(f['map'](h=>h['severity'])['sort']())['toEqual'](['high','low','medium']['sort']());const g=new GB();g['obj']('0xs3','Service',{'bPublished':![],'arbitrations':[],'compensation_fund':'500'}),expect(runAnalyzers(g['vp'](),{'only':['AC4']}))['toEqual']([]);});});
1
+ import{describe,it,expect}from'vitest';import{ENTRYPOINT}from'@wowok/wowok';import{buildViewport,runAnalyzers,runNodeAnalyzers,adaptNodeAnalyzer,listAnalyzers,registerAnalyzer}from'./index.js';const FAMILY={'eoa.permission':'R','permission.core_binding':'R','permission.entity':'W','service.order':'R','service.machine':'F','service.buy_guard':'F','machine.permission':'F','machine.node':'W','wf.transition':'W','wf.forward_guard':'W','order.allocation':'F','demand.guard':'R','demand.presenter':'R','arbitration.voting_guard':'F','arb.arbitration_service':'F','arb.voter':'S'};class GB{['nodes']=new Map();['edges']=[];['out']=new Map();['inc']=new Map();['truncations']=[];['eoa'](a){return this['nodes']['set'](a,{'id':a,'kind':'eoa','state':'fetched','origins':[],'depth':0x0}),this;}['obj'](a,b,c,d){return this['nodes']['set'](a,{'id':a,'kind':'object','objectType':b,'state':'fetched','origins':[],'depth':0x1,'raw':{'object':a,'type':b,...d?{'type_raw':d}:{},'data':c}}),this;}['edge'](a,b,c,d,f,g=![]){const h={'id':a+'|'+b+'→'+c+(d?.['forward']?'|'+d['forward']:''),'schema':a,'family':FAMILY[a]??'F','from':b,'to':c,'retention':f??(FAMILY[a]==='R'?'bounded_exact':'complete'),'evidence':'test','observedAt':0x1,...d?{'payload':d}:{},...g?{'truncated':!![]}:{}};return this['edges']['push'](h),(this['out']['get'](b)??this['out']['set'](b,[])['get'](b))['push'](h),(this['inc']['get'](c)??this['inc']['set'](c,[])['get'](c))['push'](h),h;}['trunc'](a,b,c){return this['truncations']['push']({'nodeId':a,'schema':b,'observed':c,'limit':0x1450}),this;}['build'](a='0xseed'){return{'network':ENTRYPOINT['Mainnet'],'seed':a,'builtAt':0x1,'nodes':this['nodes'],'edges':this['edges'],'out':this['out'],'inc':this['inc'],'gaps':[],'truncations':this['truncations'],'rpcReport':{'batches':0x0,'byChannel':{'objects':0x0,'keyedFields':0x0,'tables':0x0,'events':0x0},'dedupHits':0x0},'budgetExhausted':{}};}['vp'](a='0xseed',b='neutral'){return buildViewport(this['build'](a),a,b);}}const ids=a=>a['map'](b=>b['id']);describe('analyze\x20—\x20registry',()=>{it('ships\x20the\x2019\x20rules\x20(R1-6/A1-3/O1-3/G1-3\x20+\x20anti-cheat\x20AC1-4)',()=>{expect(listAnalyzers()['sort']())['toEqual'](['R1','R2','R3','R4','R5','R6','A1','A2','A3','O1','O2','O3','G1','G2','G3','AC1','AC2','AC3','AC4']['sort']());}),it('is\x20fail-soft:\x20a\x20throwing\x20analyzer\x20never\x20aborts\x20the\x20suite',()=>{registerAnalyzer({'id':'__boom','kind':'risk','run':()=>{throw new Error('boom');}});const a=new GB()['obj']('0xs1','Service',{'bPublished':!![],'setting_lock_duration':'0'})['vp'](),b=runAnalyzers(a,{'only':['__boom','R6']});expect(ids(b))['toContain']('R6:0xs1'),expect(b['find'](c=>c['id']['startsWith']('__boom')))['toBeUndefined']();}),it('adapts\x20single-object\x20legacy\x20rules\x20through\x20the\x20NodeAnalyzer\x20bridge',()=>{const a=adaptNodeAnalyzer({'id':'legacy-lock','kind':'risk','objectType':'Service','inspect':e=>{const f=e['raw']['data']??{};return f['setting_lock_duration']==='0'?[{'title':'Lock','detail':'d','suggestion':'s','roles':['merchant']}]:[];}}),b=new GB()['obj']('0xs1','Service',{'bPublished':!![],'setting_lock_duration':'0'})['vp'](),c=runNodeAnalyzers(b,[a]);expect(c)['toHaveLength'](0x1),expect(c[0x0]['id'])['toBe']('legacy-lock:0xs1#0'),expect(c[0x0]['kind'])['toBe']('risk');});}),describe('analyze\x20—\x20risk\x20rules',()=>{it('R6\x20flags\x20published\x20services\x20without\x20a\x20setting\x20lock',()=>{const a=new GB()['obj']('0xs1','Service',{'bPublished':!![],'setting_lock_duration':'0'})['obj']('0xs2','Service',{'bPublished':!![],'setting_lock_duration':'2592000000'})['obj']('0xs3','Service',{'bPublished':![],'setting_lock_duration':'0'})['vp'](),b=runAnalyzers(a,{'only':['R6']});expect(ids(b))['toEqual'](['R6:0xs1']);}),it('R2\x20measures\x20the\x20compensation\x20fund\x20against\x203x\x20windowed\x20order\x20volume',()=>{const a=new GB();a['obj']('0xs1','Service',{'bPublished':!![],'compensation_fund':'100'}),a['obj']('0xo1','Order',{'amount':'100'}),a['obj']('0xo2','Order',{'amount':'100'}),a['edge']('service.order','0xs1','0xo1',undefined,'bounded_window'),a['edge']('service.order','0xs1','0xo2',undefined,'bounded_window',!![]);const b=runAnalyzers(a['vp'](),{'only':['R2']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['severity'])['toBe']('high'),expect(b[0x0]['confidence'])['toBe']('windowed'),expect(b[0x0]['window']?.['limit'])['toBe'](0x1450);}),it('R1\x20flags\x20one\x20EOA\x20controlling\x20a\x20shop\x20and\x20an\x20arbitration\x20service\x20across\x20distinct\x20permissions',()=>{const a=new GB();a['eoa']('0xe1'),a['obj']('0xp1','Permission',{'owner':'0xe1'}),a['obj']('0xp2','Permission',{'owner':'0xe1'}),a['obj']('0xs1','Service',{}),a['obj']('0xa1','Arbitration',{'fee':'0'}),a['edge']('eoa.permission','0xe1','0xp1',{'roleBits':0x3}),a['edge']('eoa.permission','0xe1','0xp2',{'roleBits':0x3}),a['edge']('permission.core_binding','0xp1','0xs1'),a['edge']('permission.core_binding','0xp2','0xa1');const b=runAnalyzers(a['vp'](),{'only':['R1']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['severity'])['toBe']('high');const c=new GB();c['eoa']('0xe1')['obj']('0xp1','Permission',{})['obj']('0xs1','Service',{})['obj']('0xa1','Arbitration',{'fee':'0'}),c['edge']('eoa.permission','0xe1','0xp1',{'roleBits':0x3}),c['edge']('permission.core_binding','0xp1','0xs1'),c['edge']('permission.core_binding','0xp1','0xa1'),expect(runAnalyzers(c['vp'](),{'only':['R1']}))['toHaveLength'](0x0);}),it('R3\x20flags\x20concentrated\x20control\x20of\x20core\x20objects',()=>{const a=new GB();a['eoa']('0xe1')['obj']('0xp1','Permission',{}),a['obj']('0xs1','Service',{})['obj']('0xs2','Service',{})['obj']('0xm1','Machine',{}),a['edge']('eoa.permission','0xe1','0xp1',{'roleBits':0x1});for(const c of['0xs1','0xs2','0xm1'])a['edge']('permission.core_binding','0xp1',c);const b=runAnalyzers(a['vp'](),{'only':['R3']});expect(ids(b))['toEqual'](['R3:0xe1']);}),it('R4\x20flags\x20a\x20unique\x20operator\x20with\x20no\x20backup\x20guard\x20on\x20a\x20terminal-entering\x20forward',()=>{const a=new GB();a['obj']('0xm1','Machine',{'bPublished':!![]}),a['edge']('wf.transition','0xm1::node::paid','0xm1::node::delivered',{'node':'delivered','prevNode':'paid','forward':'go','namedOperator':'alice'});const b=runAnalyzers(a['vp'](),{'only':['R4']});expect(b)['toHaveLength'](0x1);const c=new GB();c['obj']('0xm1','Machine',{'bPublished':!![]}),c['edge']('wf.transition','0xm1::node::paid','0xm1::node::delivered',{'node':'delivered','prevNode':'paid','forward':'go','namedOperator':'alice','guard':'0xg1'}),expect(runAnalyzers(c['vp'](),{'only':['R4']}))['toHaveLength'](0x0);}),it('R5\x20reports\x20window\x20truncations\x20as\x20downgraded\x20meta\x20findings',()=>{const a=new GB()['obj']('0xs1','Service',{})['trunc']('0xs1','service.order',0x1450),b=runAnalyzers(a['vp'](),{'only':['R5']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['confidence'])['toBe']('windowed'),expect(b[0x0]['window'])['toEqual']({'observed':0x1450,'limit':0x1450});});}),describe('analyze\x20—\x20arbitrage\x20rules',()=>{it('A1\x20detects\x20rate-basis\x20mismatch,\x20surplus\x20duplication\x20and\x20missing\x20max',()=>{const a=new GB();a['obj']('0xal1','Allocation',{'allocators':[{'guard':'0xg1','max':null,'sharing':[{'who':'0xa','mode':0x0,'sharing':'100'}]},{'guard':'0xg2','sharing':[{'who':'0xb','mode':0x1,'sharing':'9000'}]},{'guard':'0xg3','sharing':[{'who':'0xc','mode':0x2}]},{'guard':'0xg4','sharing':[{'who':'0xd','mode':0x2}]}]});const b=runAnalyzers(a['vp'](),{'only':['A1']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['detail'])['toContain']('9000'),expect(b[0x0]['detail'])['toContain']('max'),expect(b[0x0]['detail'])['toContain']('Surplus');}),it('A2\x20flags\x20transferable\x20fixed\x20long-window\x20discounts\x20without\x20a\x20benchmark',()=>{const a=new GB();a['obj']('0xd1','Discount',{'discount_type':0x1,'benchmark':null,'transferable':!![],'time_start':'0','time_end':String(0x1fn*0x18n*0x3cn*0x3cn*0x3e8n)});const b=runAnalyzers(a['vp'](),{'only':['A2']});expect(b)['toHaveLength'](0x1);const c=new GB();c['obj']('0xd2','Discount',{'discount_type':0x1,'benchmark':null,'transferable':![],'time_start':'0','time_end':String(0x1fn*0x18n*0x3cn*0x3cn*0x3e8n)}),expect(runAnalyzers(c['vp'](),{'only':['A2']}))['toHaveLength'](0x0);}),it('A3\x20flags\x20zero-fee/no-usage-guard\x20arbitration\x20and\x20reports\x20CoinWrapper\x20custody',()=>{const a=new GB();a['obj']('0xa1','Arbitration',{'fee':'0','usage_guard':null,'voting_guard':[]}),a['obj']('0xcw1','Payment',{},'0x2::payment::CoinWrapper<0x2::wow::WOW>');const b=runAnalyzers(a['vp'](),{'only':['A3']});expect(ids(b)['sort']())['toEqual'](['A3:0xa1','A3:coinwrapper']),expect(b['find'](c=>c['id']==='A3:coinwrapper')['detail'])['toContain']('0x2::wow::WOW');});}),describe('analyze\x20—\x20opportunity\x20rules',()=>{it('O1\x20surfaces\x20scarce-presenter\x20demands\x20with\x20structurally\x20matching\x20services',()=>{const a=new GB();a['obj']('0xdm1','Demand',{'guards':[{'guard':'0xg1'}]}),a['edge']('demand.guard','0xdm1','0xg1'),a['obj']('0xs1','Service',{'bPublished':!![]}),a['obj']('0xm1','Machine',{}),a['edge']('service.machine','0xs1','0xm1'),a['edge']('wf.forward_guard','0xm1::node::paid','0xg1');const b=runAnalyzers(a['vp'](),{'only':['O1']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['detail'])['toContain']('0xs1'),a['eoa']('0u1')['eoa']('0u2'),a['edge']('demand.presenter','0xdm1','0u1',{'service':'0xs1'}),a['edge']('demand.presenter','0xdm1','0u2',{'service':'0xs1'}),expect(runAnalyzers(a['vp'](),{'only':['O1']}))['toHaveLength'](0x0);}),it('O2\x20reports\x20graph\x20supply/demand\x20density',()=>{const a=new GB();a['obj']('0xs1','Service',{'bPublished':!![],'bPaused':![]}),a['obj']('0xs2','Service',{'bPublished':![]}),a['obj']('0xd1','Demand',{});const b=runAnalyzers(a['vp'](),{'only':['O2']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['detail'])['toContain']('2\x20Service(s)'),expect(b[0x0]['detail'])['toContain']('1\x20open\x20demand(s)');}),it('O3\x20lists\x20operator-less\x20forwards\x20as\x20workflow\x20slots',()=>{const a=new GB();a['obj']('0xm1','Machine',{}),a['edge']('wf.transition','0xm1::node::paid','0xm1::node::done',{'node':'done','prevNode':'paid','forward':'auto','namedOperator':null,'permissionIndex':null,'guard':'0xg1'});const b=runAnalyzers(a['vp'](),{'only':['O3']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['detail'])['toContain']('paid:auto');});}),describe('analyze\x20—\x20game\x20rules',()=>{it('G1\x20reports\x20all-vote\x20vs\x20weighted\x20structures\x20plus\x20observed\x20case\x20weights',()=>{const a=new GB();a['obj']('0xa1','Arbitration',{'fee':'0','voting_guard':[]}),a['obj']('0xcase1','Arb',{'voted':[{'voter':'0u1','weight':0x1},{'voter':'0u2','weight':0x2}]}),a['edge']('arb.arbitration_service','0xcase1','0xa1');const b=runAnalyzers(a['vp'](),{'only':['G1']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['detail'])['toContain']('open\x20to\x20all\x20members'),expect(b[0x0]['detail'])['toContain']('w1x1'),expect(b[0x0]['detail'])['toContain']('w2x1');}),it('G2\x20marks\x20a\x20named-operator\x20forward\x20as\x20a\x20pool-of-one\x20hold-up\x20point',()=>{const a=new GB();a['obj']('0xm1','Machine',{}),a['edge']('wf.transition','0xm1::node::paid','0xm1::node::done',{'node':'done','prevNode':'paid','forward':'sign','namedOperator':'bob'});const b=runAnalyzers(a['vp'](),{'only':['G2']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['id'])['toContain']('paid:sign');}),it('G3\x20emits\x20the\x20relief\x20parameter\x20matrix\x20for\x20every\x20arbitration\x20service',()=>{const a=new GB();a['obj']('0xa1','Arbitration',{'fee':'5','usage_guard':'0xg1','voting_guard':[{'guard':'0xg2'}]});const b=runAnalyzers(a['vp'](),{'only':['G3']});expect(b)['toHaveLength'](0x1),expect(b[0x0]['detail'])['toContain']('fee=5'),expect(b[0x0]['detail'])['toContain']('30-day');});}),describe('analyze\x20—\x20anti-cheat\x20rules\x20(AC1-AC4)',()=>{function a(c,d,e,f){c['eoa'](d),c['edge']('eoa.permission',d,e,{'roleBits':0x1|0x2}),c['edge']('permission.core_binding',e,f);}function b(c,d,e,f){c['obj'](e,'Order',f),c['edge']('service.order',d,e,undefined,'bounded_window'),c['edge']('order.builder',e,String(f['builder']));}it('AC1\x20flags\x20window\x20orders\x20whose\x20buyer\x20controls\x20the\x20selling\x20Service',()=>{const c=new GB();c['obj']('0xs1','Service',{'bPublished':!![],'machine':'0xm1'}),a(c,'0u1','0p1','0xs1'),b(c,'0xs1','0o1',{'builder':'0u1','service':'0xs1','amount':'100'});const d=runAnalyzers(c['vp'](),{'only':['AC1']});expect(d)['toHaveLength'](0x1),expect(d[0x0]['severity'])['toBe']('high'),expect(d[0x0]['confidence'])['toBe']('windowed'),expect(d[0x0]['id'])['toContain']('0o1');const e=new GB();e['obj']('0xs1','Service',{'bPublished':!![],'machine':'0xm1'}),a(e,'0u1','0p1','0xs1'),b(e,'0xs1','0o1',{'builder':'0u2','service':'0xs1','amount':'100'}),expect(runAnalyzers(e['vp'](),{'only':['AC1']}))['toEqual']([]);}),it('AC2\x20flags\x20reciprocal\x20buying\x20between\x20two\x20controlled\x20Services',()=>{const c=new GB();c['obj']('0xs1','Service',{'bPublished':!![],'machine':'0xm1'}),c['obj']('0xs2','Service',{'bPublished':!![],'machine':'0xm2'}),a(c,'0u1','0p1','0xs1'),a(c,'0u2','0p2','0xs2'),b(c,'0xs1','0o1',{'builder':'0u2','service':'0xs1','amount':'100'}),b(c,'0xs2','0o2',{'builder':'0u1','service':'0xs2','amount':'100'});const d=runAnalyzers(c['vp'](),{'only':['AC2']});expect(d)['toHaveLength'](0x1),expect(d[0x0]['severity'])['toBe']('medium'),expect(d[0x0]['id'])['toContain']('0o1'),expect(d[0x0]['id'])['toContain']('0o2');}),it('AC3\x20flags\x20completed\x20positive-amount\x20orders\x20without\x20Allocation,\x20but\x20not\x20zero-amount\x20orders',()=>{const c=new GB();c['obj']('0xs1','Service',{'bPublished':!![],'machine':'0xm1'}),a(c,'0u1','0p1','0xs1'),b(c,'0xs1','0opaid',{'builder':'0u9','service':'0xs1','amount':'100'}),b(c,'0xs1','0ofree',{'builder':'0u8','service':'0xs1','amount':'0'});const d=runAnalyzers(c['vp'](),{'only':['AC3']});expect(d)['toHaveLength'](0x1),expect(d[0x0]['id'])['toContain']('0opaid'),expect(d[0x0]['id'])['not']['toContain']('0ofree'),c['edge']('order.allocation','0opaid','0al1'),expect(runAnalyzers(c['vp'](),{'only':['AC3']}))['toEqual']([]);}),it('AC4\x20surfaces\x20shell-merchant\x20shapes\x20only\x20for\x20published\x20Services',()=>{const c=new GB();c['obj']('0xs1','Service',{'bPublished':!![],'arbitrations':[],'compensation_fund':'0'});const d=runAnalyzers(c['vp'](),{'only':['AC4']});expect(ids(d)['sort']())['toEqual'](['AC4:0xs1:shell_no_arbitration','AC4:0xs1:shell_no_machine']['sort']());const e=new GB();e['obj']('0xs2','Service',{'bPublished':!![],'arbitrations':[],'compensation_fund':'500'});const f=runAnalyzers(e['vp'](),{'only':['AC4']});expect(f['map'](h=>h['severity'])['sort']())['toEqual'](['high','low','medium']['sort']());const g=new GB();g['obj']('0xs3','Service',{'bPublished':![],'arbitrations':[],'compensation_fund':'500'}),expect(runAnalyzers(g['vp'](),{'only':['AC4']}))['toEqual']([]);});});
@@ -52,7 +52,7 @@ export interface EdgeSchema {
52
52
  evidence: string;
53
53
  contract?: EdgeContractMeta;
54
54
  bridgeIds?: string[];
55
- zh: string;
55
+ label: string;
56
56
  }
57
57
  export declare const EDGE_SCHEMAS: EdgeSchema[];
58
58
  export declare const EDGE_SCHEMA_BY_ID: Map<string, EdgeSchema>;