@wowok/agent-mcp 3.2.1 → 3.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chain-semantics/field-capability.d.ts +11 -0
- package/dist/chain-semantics/field-capability.js +1 -0
- package/dist/chain-semantics/freeze-map.d.ts +11 -0
- package/dist/chain-semantics/freeze-map.js +1 -0
- package/dist/chain-semantics/fund-flow.d.ts +10 -0
- package/dist/chain-semantics/fund-flow.js +1 -0
- package/dist/chain-semantics/guard-verbs.d.ts +22 -0
- package/dist/chain-semantics/guard-verbs.js +1 -0
- package/dist/chain-semantics/index.d.ts +10 -0
- package/dist/chain-semantics/index.js +1 -0
- package/dist/chain-semantics/object-graph.d.ts +18 -0
- package/dist/chain-semantics/object-graph.js +1 -0
- package/dist/communication/wts-attestation.d.ts +34 -0
- package/dist/communication/wts-attestation.js +1 -0
- package/dist/composition/audit.d.ts +10 -0
- package/dist/composition/audit.js +1 -0
- package/dist/composition/compile.d.ts +38 -0
- package/dist/composition/compile.js +1 -0
- package/dist/composition/materialize.d.ts +64 -0
- package/dist/composition/materialize.js +1 -0
- package/dist/composition/plan.d.ts +92 -0
- package/dist/composition/plan.js +1 -0
- package/dist/composition/reflux.d.ts +28 -0
- package/dist/composition/reflux.js +1 -0
- package/dist/config/judgment.d.ts +25 -0
- package/dist/config/rule-engine.d.ts +10 -0
- package/dist/config/rule-engine.js +1 -1
- package/dist/evaluation/builtins/graph-service.spec.js +1 -1
- package/dist/evaluation/engine.js +1 -1
- package/dist/experience/realtime-feedback.js +1 -1
- package/dist/extensions/business-modules.js +1 -1
- package/dist/extensions/industry-pack.js +1 -1
- package/dist/extensions/modes.js +1 -1
- package/dist/graph/onchain/expand.js +1 -1
- package/dist/graph/onchain/exposure.js +1 -1
- package/dist/graph/onchain/facts.js +1 -1
- package/dist/keeper/detectors.d.ts +7 -0
- package/dist/keeper/detectors.js +1 -1
- package/dist/keeper/types.d.ts +1 -1
- package/dist/keeper/types.js +1 -1
- package/dist/knowledge/allocation-ledger.js +1 -1
- package/dist/knowledge/allocation-puzzle.js +1 -1
- package/dist/knowledge/allocation-risk.d.ts +2 -1
- package/dist/knowledge/allocation-risk.js +1 -1
- package/dist/knowledge/allocation-templates.js +1 -1
- package/dist/knowledge/arb-fund-facts.d.ts +31 -0
- package/dist/knowledge/arb-fund-facts.js +1 -0
- package/dist/knowledge/audit-rules.js +1 -1
- package/dist/knowledge/baselines/rules/allocation.json +75 -16
- package/dist/knowledge/baselines/rules/guard.json +27 -8
- package/dist/knowledge/baselines/rules/plan.json +161 -0
- package/dist/knowledge/baselines/semantic-facts.d.ts +12 -0
- package/dist/knowledge/baselines/semantic-facts.js +1 -0
- package/dist/knowledge/builtin-templates.d.ts +3 -1
- package/dist/knowledge/builtin-templates.js +1 -1
- package/dist/knowledge/entity-recipient-guard.d.ts +21 -0
- package/dist/knowledge/entity-recipient-guard.js +1 -0
- package/dist/knowledge/getting-started.js +1 -1
- package/dist/knowledge/guard-design-patterns.js +1 -1
- package/dist/knowledge/guard-ledger.js +1 -1
- package/dist/knowledge/guard-risk.js +1 -1
- package/dist/knowledge/guard-templates.js +1 -1
- package/dist/knowledge/index.js +1 -1
- package/dist/knowledge/industry-registry.js +1 -1
- package/dist/knowledge/jsonrpc-enum.js +1 -1
- package/dist/knowledge/machine-topology.d.ts +34 -0
- package/dist/knowledge/machine-topology.js +1 -1
- package/dist/knowledge/onchain-constants.d.ts +2 -2
- package/dist/knowledge/onchain-constants.js +1 -1
- package/dist/knowledge/scenario-modes.d.ts +13 -0
- package/dist/knowledge/scenario-modes.js +1 -1
- package/dist/knowledge/service-allocation-semantics.js +1 -1
- package/dist/knowledge/service-ledger.js +1 -1
- package/dist/knowledge/service-templates.js +1 -1
- package/dist/knowledge/strategy-manuals.js +1 -1
- package/dist/knowledge/template-loader.d.ts +37 -1
- package/dist/knowledge/template-loader.js +1 -1
- package/dist/knowledge/template-registry.js +1 -1
- package/dist/knowledge/template-scanner.js +1 -1
- package/dist/knowledge/tool-constraints.js +1 -1
- package/dist/knowledge/tools-reference.js +1 -1
- package/dist/knowledge/workflow-guidance.d.ts +4 -0
- package/dist/knowledge/workflow-guidance.js +1 -1
- package/dist/monitor/MonitorLoop.js +1 -1
- package/dist/participation/radar-core.d.ts +6 -0
- package/dist/participation/radar-core.js +1 -1
- package/dist/playbooks/service-build/business-puzzle.js +1 -1
- package/dist/playbooks/service-build/index.d.ts +1 -0
- package/dist/playbooks/service-build/intent-analyzer.d.ts +1 -0
- package/dist/playbooks/service-build/intent-analyzer.js +1 -1
- package/dist/playbooks/service-build/machine-nodes.d.ts +1 -1
- package/dist/playbooks/service-build/machine-nodes.js +1 -1
- package/dist/playbooks/service-build/machine-panorama.js +1 -1
- package/dist/playbooks/service-build/merchant-guide.js +1 -1
- package/dist/playbooks/service-build/migration-planner.js +1 -1
- package/dist/playbooks/service-build/object-panorama.d.ts +27 -1
- package/dist/playbooks/service-build/object-panorama.js +1 -1
- package/dist/playbooks/service-build/participation-radar.js +1 -1
- package/dist/playbooks/service-build/pipeline-actions.d.ts +4 -0
- package/dist/playbooks/service-build/pipeline-actions.js +1 -1
- package/dist/playbooks/service-build/relationship-profile.js +1 -1
- package/dist/playbooks/service-build/semantic-graph.d.ts +1 -0
- package/dist/playbooks/service-build/semantic-graph.js +1 -1
- package/dist/playbooks/service-build/service-panorama.js +1 -1
- package/dist/playbooks/service-build/service-quote.js +1 -1
- package/dist/review/index.js +1 -1
- package/dist/safety/confirm-gate.js +1 -1
- package/dist/schema/call/machine.d.ts +1 -0
- package/dist/schema/call/machine.js +1 -1
- package/dist/schema/call/order.d.ts +60 -0
- package/dist/schema/call/order.js +1 -1
- package/dist/schema/call/semantic.js +1 -1
- package/dist/schema/call/service.d.ts +56 -0
- package/dist/schema/call/service.js +1 -1
- package/dist/schema/common/index.js +1 -1
- package/dist/schema/goal/planning.d.ts +7 -0
- package/dist/schema/goal/planning.js +1 -1
- package/dist/schema/index.d.ts +1 -0
- package/dist/schema/index.js +1 -1
- package/dist/schema/industry-pack/index.d.ts +26 -0
- package/dist/schema/industry-pack/index.js +1 -1
- package/dist/schema/local/index.js +1 -1
- package/dist/schema/messenger/index.d.ts +20 -0
- package/dist/schema/messenger/index.js +1 -1
- package/dist/schema/operations.d.ts +50 -0
- package/dist/schema/persona/index.d.ts +110 -0
- package/dist/schema/query/bi.d.ts +2 -0
- package/dist/schema/query/bi.js +1 -1
- package/dist/schema/query/index.js +1 -1
- package/dist/schema/schema-version.js +1 -1
- package/dist/schema/service-clone/index.d.ts +46 -0
- package/dist/schema/service-clone/index.js +1 -0
- package/dist/schema/utils/node-parser.js +1 -1
- package/dist/schema-query-impl/index.js +1 -1
- package/dist/schemas/index.json +7 -1
- package/dist/schemas/industry_pack_operation.output.json +113 -0
- package/dist/schemas/industry_pack_operation.schema.json +7 -1
- package/dist/schemas/messenger_operation.output.json +42 -4
- package/dist/schemas/onchain_operations.output.json +1 -1
- package/dist/schemas/onchain_operations.schema.json +409 -98
- package/dist/schemas/onchain_operations_allocation.schema.json +5 -5
- package/dist/schemas/onchain_operations_arbitration.schema.json +2 -2
- package/dist/schemas/onchain_operations_contact.schema.json +1 -1
- package/dist/schemas/onchain_operations_demand.schema.json +3 -3
- package/dist/schemas/onchain_operations_gen_passport.schema.json +1 -1
- package/dist/schemas/onchain_operations_guard.schema.json +59 -59
- package/dist/schemas/onchain_operations_machine.schema.json +3 -3
- package/dist/schemas/onchain_operations_order.schema.json +133 -1
- package/dist/schemas/onchain_operations_progress.schema.json +1 -1
- package/dist/schemas/onchain_operations_proof.schema.json +1 -1
- package/dist/schemas/onchain_operations_repository.schema.json +1 -1
- package/dist/schemas/onchain_operations_reward.schema.json +4 -4
- package/dist/schemas/onchain_operations_service.schema.json +188 -9
- package/dist/schemas/onchain_operations_treasury.schema.json +7 -7
- package/dist/schemas/onchain_table_data.output.json +5 -1
- package/dist/schemas/persona_operation.output.json +266 -0
- package/dist/schemas/persona_operation.schema.json +42 -0
- package/dist/schemas/query_toolkit.output.json +46 -46
- package/dist/schemas/query_toolkit.schema.json +5 -1
- package/dist/schemas/service_clone_operation.output.json +168 -0
- package/dist/schemas/service_clone_operation.schema.json +49 -0
- package/dist/schemas/workflow_operation.schema.json +1 -1
- package/dist/tools/handlers/benchmark-migration.d.ts +17 -0
- package/dist/tools/handlers/benchmark-migration.js +1 -1
- package/dist/tools/handlers/config.js +1 -1
- package/dist/tools/handlers/industry-pack.js +1 -1
- package/dist/tools/handlers/messenger.js +1 -1
- package/dist/tools/handlers/onchain.js +1 -1
- package/dist/tools/handlers/query.js +1 -1
- package/dist/tools/handlers/service-clone.d.ts +2 -0
- package/dist/tools/handlers/service-clone.js +1 -0
- package/dist/tools/index.js +1 -1
- package/dist/tools/registry/business.js +1 -1
- package/dist/tools/wrap.d.ts +6 -1
- package/dist/tools/wrap.js +1 -1
- package/package.json +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync,mkdirSync,readdirSync,readFileSync,renameSync,rmdirSync,statSync,writeFileSync}from'node:fs';import{join}from'node:path';import{z}from'zod';import{getWowokDataDir,getWowokIndustryDir}from'@wowok/wowok';import{SUPPORTED_INDUSTRIES}from'../customer/user-preferences.js';import{isRegisteredIndustry}from'./industry-registry.js';import{BUILTIN_TEMPLATES,BUILTIN_TEMPLATES_VERSION}from'./builtin-templates.js';import{classifyRelease,releaseBodyHash,releaseSentinelLine,stripReleaseSentinel}from'./release-sentinel.js';export const TEMPLATES_SUBDIR='templates';export function resolveTemplatesDir(){return process['env']['WOWOK_TEMPLATES_DIR']||getWowokIndustryDir();}function resolveLegacyTemplatesDir(){return process['env']['WOWOK_LEGACY_TEMPLATES_DIR']||join(getWowokDataDir(),'templates');}const MachineNodeSchema=z['object']({'name':z['string']()['min'](0x1),'role':z['string']()['min'](0x1),'operator':z['enum'](['merchant','order_payer'])['optional'](),'semantic_role':z['enum'](['draft','active','delivered','final','cancelled'])['optional']()}),GuardRefSchema=z['object']({'template_id':z['string']()['regex'](/^(pattern\.[a-z0-9_]+|tpl_[a-z0-9_]+)$/,'guard\x20template_id\x20must\x20be\x20a\x20\x27pattern.*\x27\x20design\x20pattern\x20or\x20\x27tpl_*\x27\x20guard\x20template'),'host':z['enum'](['service','machine','reward','repository','arbitration']),'purpose':z['string']()['min'](0x1)}),AllocatorRowSchema=z['object']({'track':z['enum'](['settlement','refund']),'recipient':z['enum'](['entity','guard_identifier','signer']),'recipient_key':z['string']()['min'](0x1)['optional'](),'mode':z['enum'](['amount','rate','surplus']),'value':z['union']([z['string'](),z['number']()])['optional'](),'value_from':z['string']()['optional'](),'note':z['string']()['optional']()})['strict'](),AllocatorSchema=z['object']({'recipient':z['enum'](['signer','entity','fixed']),'refund_track':z['enum'](['order_anchored'])['optional'](),'count':z['number']()['int']()['positive'](),'mode':z['enum'](['amount','rate','surplus']),'once_per_order':z['boolean']()['optional'](),'rows':z['array'](AllocatorRowSchema)['optional'](),'description':z['string']()['min'](0x1)})['strict'](),IndustryNameSchema=z['string']()['regex'](/^[a-z][a-z0-9_]*$/,'industry\x20must\x20be\x20lowercase\x20snake_case\x20(a-z,\x200-9,\x20_)')['refine'](a=>isRegisteredIndustry(a),{'message':'unknown\x20industry\x20—\x20register\x20it\x20first\x20via\x20an\x20industry\x20pack\x20'+'(industry_pack_operation\x20action=\x27scaffold\x27)\x20or\x20the\x20industry\x20generalizer;\x20'+('builtin\x20industries:\x20'+SUPPORTED_INDUSTRIES['join'](',\x20'))});export const TemplateFrontmatterSchema=z['object']({'id':z['string']()['regex'](/^[a-z][a-z0-9_-]*\/[a-z][a-z0-9_-]*$/,'id\x20must\x20be\x20\x27<industry>/<variant>\x27'),'industry':IndustryNameSchema,'variant':z['string']()['regex'](/^[a-z][a-z0-9_-]*$/),'product_ref':z['string']()['regex'](/^[a-z][a-z0-9._-]*$/,'product_ref\x20must\x20be\x20a\x20lowercase\x20product\x20slug')['optional'](),'archetype':z['enum'](['leader','challenger']),'phase':z['number']()['int']()['min'](0x1)['max'](0x3),'machine_shape':z['array'](MachineNodeSchema)['min'](0x1),'guards':z['array'](GuardRefSchema),'allocator':AllocatorSchema,'fee_params':z['record'](z['string'](),z['union']([z['number'](),z['string']()])),'trust_mechanisms':z['array'](z['string']()),'keeper_dependencies':z['array'](z['string']()),'recommended_role':z['enum'](['merchant','supplier','both']),'role_rationale':z['string']()['min'](0x1),'differences':z['array'](z['string']()),'user_inputs':z['array'](z['string']()),'key_risk':z['string']()['min'](0x1),'build_notes':z['array'](z['string']()),'time_anchors':z['record'](z['string'](),z['string']())['optional']()})['strict']();export function parseTemplateFile(a){const b=a['replace'](/^\uFEFF/,'')['replace'](/^<!-- builtin:[a-z0-9-]+:v\d+:[0-9a-f]+ -->\r?\n/,''),c=b['split'](/\r?\n/);if(c[0x0]?.['trim']()!=='---')throw new Error('template\x20must\x20start\x20with\x20a\x20\x27---\x27\x20frontmatter\x20block');let d=-0x1;for(let f=0x1;f<c['length'];f++){if(c[f]['trim']()==='---'){d=f;break;}}if(d===-0x1)throw new Error('unterminated\x20frontmatter\x20block\x20(missing\x20closing\x20\x27---\x27)');const e={};for(let g=0x1;g<d;g++){const h=c[g];if(!h['trim']()||h['trim']()['startsWith']('#'))continue;const j=h['indexOf'](':');if(j===-0x1)throw new Error('invalid\x20frontmatter\x20line\x20'+(g+0x1)+':\x20\x27'+h['trim']()+'\x27\x20(expected\x20\x27key:\x20value\x27)');const k=h['slice'](0x0,j)['trim'](),l=h['slice'](j+0x1)['trim']();if(!k)throw new Error('invalid\x20frontmatter\x20line\x20'+(g+0x1)+':\x20empty\x20key');if(l['startsWith']('[')||l['startsWith']('{'))try{e[k]=JSON['parse'](l);}catch(m){throw new Error('frontmatter\x20key\x20\x27'+k+'\x27\x20is\x20not\x20valid\x20JSON:\x20'+m['message']);}else/^-?\d+(\.\d+)?$/['test'](l)?e[k]=Number(l):e[k]=l;}return{'frontmatter':e,'body':c['slice'](d+0x1)['join']('\x0a')['trim']()};}function frontmatterLine(a,b){if(typeof b==='number')return a+':\x20'+b;if(typeof b==='string')return a+':\x20'+b;return a+':\x20'+JSON['stringify'](b);}export const TEMPLATE_SENTINEL_KIND='industry-template';function canonicalTemplateContent(a){const b=[['id',a['id']],['industry',a['industry']],['variant',a['variant']],['product_ref',a['product_ref']],['archetype',a['archetype']],['phase',a['phase']],['recommended_role',a['recommended_role']],['role_rationale',a['role_rationale']],['key_risk',a['key_risk']],['machine_shape',a['machine_shape']],['guards',a['guards']],['allocator',a['allocator']],['fee_params',a['fee_params']],['trust_mechanisms',a['trust_mechanisms']],['keeper_dependencies',a['keeper_dependencies']],['differences',a['differences']],['user_inputs',a['user_inputs']],['build_notes',a['build_notes']],...a['time_anchors']?[['time_anchors',a['time_anchors']]]:[]],c=['---',...b['map'](([e,f])=>frontmatterLine(e,f)),'---'],d=['','#\x20'+a['industry']+'\x20/\x20'+a['variant']+'\x20('+a['archetype']+')','','>\x20Industry\x20archetype\x20template.\x20Editable\x20and\x20migratable:\x20the\x20frontmatter\x20is','>\x20zod-validated\x20on\x20every\x20load;\x20the\x20body\x20is\x20free-form\x20guidance\x20for\x20the\x20AI.','','##\x20Key\x20risk','',a['key_risk'],'','##\x20Differences\x20vs\x20the\x20sibling\x20variant','',...a['differences']['map'](e=>'-\x20'+e),'','##\x20User\x20inputs\x20(inject\x20at\x20build\x20time)','',...a['user_inputs']['map'](e=>'-\x20'+e),'','##\x20Risk-avoidance\x20checklist\x20(R1-R10)','',...a['trust_mechanisms']['map'](e=>'-\x20'+e),'','##\x20Build\x20notes','',...a['build_notes']['map'](e=>'-\x20'+e),''];return[...c,...d]['join']('\x0a');}export function renderTemplateFile(a){const b=canonicalTemplateContent(a);return releaseSentinelLine(TEMPLATE_SENTINEL_KIND,BUILTIN_TEMPLATES_VERSION,releaseBodyHash(b))+'\x0a'+b;}let seeded=![];function migrateLegacyTemplates(a){const b=resolveLegacyTemplatesDir();if(b===a)return;if(!existsSync(b))return;try{for(const c of readdirSync(b,{'withFileTypes':!![]})){if(!c['isDirectory']())continue;const d=join(b,c['name']),e=join(a,c['name'],TEMPLATES_SUBDIR);for(const g of readdirSync(d,{'withFileTypes':!![]})){if(!g['isFile']()||!g['name']['endsWith']('.md'))continue;const h=join(e,g['name']);if(existsSync(h))continue;mkdirSync(e,{'recursive':!![]}),renameSync(join(d,g['name']),h);}try{rmdirSync(d);}catch{}}try{rmdirSync(b);}catch{}}catch{}}export function seedBuiltinTemplates(){const a=[],b=resolveTemplatesDir();migrateLegacyTemplates(b);for(const c of BUILTIN_TEMPLATES){const d=join(b,c['industry'],TEMPLATES_SUBDIR),e=join(d,c['variant']+'.md'),f={'template':c['id'],'status':'written','path':e};try{if(!existsSync(e))mkdirSync(d,{'recursive':!![]}),writeFileSync(e,renderTemplateFile(c),'utf-8');else{const {sentinel:g,content:h}=stripReleaseSentinel(readFileSync(e,'utf-8'),TEMPLATE_SENTINEL_KIND);if(!g)f['status']='skipped_user_file',f['detail']='template\x20file\x20exists\x20without\x20builtin\x20sentinel;\x20leaving\x20user\x20file\x20untouched';else{const i=classifyRelease(g,h,BUILTIN_TEMPLATES_VERSION);if(i==='current')f['status']='current';else i==='user_modified'?(f['status']='skipped_user_modified',f['detail']='template\x20file\x20was\x20edited\x20locally;\x20keeping\x20user\x20content\x20and\x20not\x20upgrading'):(writeFileSync(e,renderTemplateFile(c),'utf-8'),f['status']='updated');}}}catch(j){f['status']='error',f['detail']=j['message'];}a['push'](f);}return a;}const cache=new Map();export function reloadTemplates(){cache['clear'](),seeded=![];}export function loadAndValidate(a){const b=readFileSync(a,'utf-8');let c;try{c=parseTemplateFile(b);}catch(e){throw new Error('template\x20\x27'+a+'\x27\x20failed\x20to\x20parse:\x20'+e['message']);}const d=TemplateFrontmatterSchema['safeParse'](c['frontmatter']);if(!d['success']){const f=d['error']['issues']['map'](g=>(g['path']['join']('.')||'<root>')+':\x20'+g['message'])['join'](';\x20');throw new Error('template\x20\x27'+a+'\x27\x20failed\x20validation:\x20'+f);}return{...d['data'],'body':c['body'],'source_path':a};}function templateFilesOnDisk(a){const b=[];if(!existsSync(a))return b;for(const c of readdirSync(a,{'withFileTypes':!![]})){if(!c['isDirectory']())continue;const d=join(a,c['name'],TEMPLATES_SUBDIR);if(!existsSync(d))continue;for(const e of readdirSync(d,{'withFileTypes':!![]})){if(e['isFile']()&&e['name']['endsWith']('.md'))b['push'](join(d,e['name']));}}return b['sort']();}export function listTemplates(){!seeded&&(seedBuiltinTemplates(),seeded=!![]);const a=resolveTemplatesDir(),b=[],c=[],d=new Set();for(const e of templateFilesOnDisk(a)){d['add'](e);try{const f=statSync(e)['mtimeMs'],g=cache['get'](e);if(g&&g['mtimeMs']===f){b['push'](g['template']);continue;}const h=loadAndValidate(e);cache['set'](e,{'mtimeMs':f,'template':h}),b['push'](h);}catch(i){cache['delete'](e),c['push'](i['message']);}}for(const j of[...cache['keys']()]){if(!d['has'](j))cache['delete'](j);}return b['sort']((k,l)=>k['id']['localeCompare'](l['id'])),{'templates':b,'errors':c};}export function getTemplate(a){return listTemplates()['templates']['find'](b=>b['id']===a);}export function getTemplatesByIndustry(a){return listTemplates()['templates']['filter'](b=>b['industry']===a);}
|
|
1
|
+
import{copyFileSync,existsSync,mkdirSync,readdirSync,readFileSync,renameSync,rmdirSync,statSync,writeFileSync}from'node:fs';import{join}from'node:path';import{z}from'zod';import{getWowokDataDir,getWowokIndustryDir}from'@wowok/wowok';import{SUPPORTED_INDUSTRIES}from'../customer/user-preferences.js';import{isRegisteredIndustry}from'./industry-registry.js';import{BUILTIN_TEMPLATES,BUILTIN_TEMPLATES_VERSION}from'./builtin-templates.js';import{classifyRelease,releaseBodyHash,releaseSentinelLine,stripReleaseSentinel}from'./release-sentinel.js';export const TEMPLATES_SUBDIR='templates';export function resolveTemplatesDir(){return process['env']['WOWOK_TEMPLATES_DIR']||getWowokIndustryDir();}function resolveLegacyTemplatesDir(){return process['env']['WOWOK_LEGACY_TEMPLATES_DIR']||join(getWowokDataDir(),'templates');}const MachineEdgeSchema=z['object']({'prev':z['string'](),'forward':z['string']()['min'](0x1)['optional'](),'operator':z['enum'](['merchant','order_payer'])['optional'](),'permission_index':z['number']()['int']()['min'](0x3e8)['optional'](),'guard_key':z['string']()['min'](0x1)['optional']()}),MachineNodeSchema=z['object']({'name':z['string']()['min'](0x1),'role':z['string']()['min'](0x1),'operator':z['enum'](['merchant','order_payer'])['optional'](),'semantic_role':z['enum'](['draft','active','delivered','final','cancelled'])['optional'](),'from':z['array'](z['union']([z['string'](),MachineEdgeSchema]))['optional']()}),GuardRefSchema=z['object']({'template_id':z['string']()['regex'](/^(pattern\.[a-z0-9_]+|tpl_[a-z0-9_]+)$/,'guard\x20template_id\x20must\x20be\x20a\x20\x27pattern.*\x27\x20design\x20pattern\x20or\x20\x27tpl_*\x27\x20guard\x20template'),'host':z['enum'](['service','machine','reward','repository','arbitration']),'purpose':z['string']()['min'](0x1),'key':z['string']()['min'](0x1)['optional']()}),AllocatorRowSchema=z['object']({'track':z['enum'](['settlement','refund']),'recipient':z['enum'](['entity','guard_identifier','signer']),'recipient_key':z['string']()['min'](0x1)['optional'](),'mode':z['enum'](['amount','rate','surplus']),'value':z['union']([z['string'](),z['number']()])['optional'](),'value_from':z['string']()['optional'](),'fix':z['union']([z['string'](),z['number']()])['optional'](),'fix_from':z['string']()['optional'](),'guard_key':z['string']()['min'](0x1)['optional'](),'note':z['string']()['optional']()})['strict'](),AllocatorSchema=z['object']({'recipient':z['enum'](['signer','entity','fixed']),'recipient_key':z['string']()['min'](0x1)['optional'](),'refund_track':z['enum'](['order_anchored'])['optional'](),'count':z['number']()['int']()['positive'](),'mode':z['enum'](['amount','rate','surplus']),'once_per_order':z['boolean']()['optional'](),'rows':z['array'](AllocatorRowSchema)['optional'](),'description':z['string']()['min'](0x1)})['strict'](),IndustryNameSchema=z['string']()['regex'](/^[a-z][a-z0-9_]*$/,'industry\x20must\x20be\x20lowercase\x20snake_case\x20(a-z,\x200-9,\x20_)')['refine'](a=>isRegisteredIndustry(a),{'message':'unknown\x20industry\x20—\x20register\x20it\x20first\x20via\x20an\x20industry\x20pack\x20'+'(industry_pack_operation\x20action=\x27scaffold\x27)\x20or\x20the\x20industry\x20generalizer;\x20'+('builtin\x20industries:\x20'+SUPPORTED_INDUSTRIES['join'](',\x20'))});export const TemplateFrontmatterSchema=z['object']({'id':z['string']()['regex'](/^[a-z][a-z0-9_-]*\/[a-z][a-z0-9_-]*$/,'id\x20must\x20be\x20\x27<industry>/<variant>\x27'),'industry':IndustryNameSchema,'variant':z['string']()['regex'](/^[a-z][a-z0-9_-]*$/),'product_ref':z['string']()['regex'](/^[a-z][a-z0-9._-]*$/,'product_ref\x20must\x20be\x20a\x20lowercase\x20product\x20slug')['optional'](),'archetype':z['enum'](['leader','challenger']),'phase':z['number']()['int']()['min'](0x1)['max'](0x3),'machine_shape':z['array'](MachineNodeSchema)['min'](0x1),'guards':z['array'](GuardRefSchema),'allocator':AllocatorSchema,'fee_params':z['record'](z['string'](),z['union']([z['number'](),z['string']()])),'trust_mechanisms':z['array'](z['string']()),'keeper_dependencies':z['array'](z['string']()),'recommended_role':z['enum'](['merchant','supplier','both']),'role_rationale':z['string']()['min'](0x1),'differences':z['array'](z['string']()),'user_inputs':z['array'](z['string']()),'key_risk':z['string']()['min'](0x1)['max'](0x12c,'key_risk\x20must\x20be\x20a\x20one-line\x20risk\x20statement\x20(<=\x20300\x20chars)\x20—\x20rules\x20and\x20doctrine\x20do\x20not\x20belong\x20in\x20this\x20field')['refine'](a=>!/STANDING RULE|TECHNOLOGY PROVIDER|NOT A PARTY TO THE DEAL|Full text:/i['test'](a),{'message':'key_risk\x20carries\x20an\x20instruction-block\x20fragment\x20(STANDING\x20RULE\x20/\x20provider\x20doctrine\x20/\x20\x27Full\x20text:\x27\x20reference)\x20—\x20keep\x20doctrine\x20in\x20body\x20prose\x20or\x20playbooks,\x20not\x20in\x20this\x20field'}),'build_notes':z['array'](z['string']()),'time_anchors':z['record'](z['string'](),z['string']())['optional'](),'payment_model':z['enum'](['milestone','subscription','escrow'])['optional'](),'arbitration_mode':z['enum'](['none','merchant_pick','mutual_pick','third_party'])['optional']()})['strict']();export function parseTemplateFile(a){const b=a['replace'](/^\uFEFF/,'')['replace'](/^<!-- builtin:[a-z0-9-]+:v\d+:[0-9a-f]+ -->\r?\n/,''),c=b['split'](/\r?\n/);if(c[0x0]?.['trim']()!=='---')throw new Error('template\x20must\x20start\x20with\x20a\x20\x27---\x27\x20frontmatter\x20block');let d=-0x1;for(let f=0x1;f<c['length'];f++){if(c[f]['trim']()==='---'){d=f;break;}}if(d===-0x1)throw new Error('unterminated\x20frontmatter\x20block\x20(missing\x20closing\x20\x27---\x27)');const e={};for(let g=0x1;g<d;g++){const h=c[g];if(!h['trim']()||h['trim']()['startsWith']('#'))continue;const j=h['indexOf'](':');if(j===-0x1)throw new Error('invalid\x20frontmatter\x20line\x20'+(g+0x1)+':\x20\x27'+h['trim']()+'\x27\x20(expected\x20\x27key:\x20value\x27)');const k=h['slice'](0x0,j)['trim'](),l=h['slice'](j+0x1)['trim']();if(!k)throw new Error('invalid\x20frontmatter\x20line\x20'+(g+0x1)+':\x20empty\x20key');if(l['startsWith']('[')||l['startsWith']('{'))try{e[k]=JSON['parse'](l);}catch(m){throw new Error('frontmatter\x20key\x20\x27'+k+'\x27\x20is\x20not\x20valid\x20JSON:\x20'+m['message']);}else/^-?\d+(\.\d+)?$/['test'](l)?e[k]=Number(l):e[k]=l;}return{'frontmatter':e,'body':c['slice'](d+0x1)['join']('\x0a')['trim']()};}function frontmatterLine(a,b){if(typeof b==='number')return a+':\x20'+b;if(typeof b==='string')return a+':\x20'+b;return a+':\x20'+JSON['stringify'](b);}export const TEMPLATE_SENTINEL_KIND='industry-template';function canonicalTemplateContent(a){const b=[['id',a['id']],['industry',a['industry']],['variant',a['variant']],['product_ref',a['product_ref']],['archetype',a['archetype']],['phase',a['phase']],['recommended_role',a['recommended_role']],['role_rationale',a['role_rationale']],['key_risk',a['key_risk']],['machine_shape',a['machine_shape']],['guards',a['guards']],['allocator',a['allocator']],['fee_params',a['fee_params']],['trust_mechanisms',a['trust_mechanisms']],['keeper_dependencies',a['keeper_dependencies']],['differences',a['differences']],['user_inputs',a['user_inputs']],['build_notes',a['build_notes']],...a['time_anchors']?[['time_anchors',a['time_anchors']]]:[],...a['payment_model']?[['payment_model',a['payment_model']]]:[],...a['arbitration_mode']?[['arbitration_mode',a['arbitration_mode']]]:[]],c=['---',...b['map'](([e,f])=>frontmatterLine(e,f)),'---'],d=['','#\x20'+a['industry']+'\x20/\x20'+a['variant']+'\x20('+a['archetype']+')','','>\x20Industry\x20archetype\x20template.\x20Editable\x20and\x20migratable:\x20the\x20frontmatter\x20is','>\x20zod-validated\x20on\x20every\x20load;\x20the\x20body\x20is\x20free-form\x20guidance\x20for\x20the\x20AI.','','##\x20Key\x20risk','',a['key_risk'],'','##\x20Differences\x20vs\x20the\x20sibling\x20variant','',...a['differences']['map'](e=>'-\x20'+e),'','##\x20User\x20inputs\x20(inject\x20at\x20build\x20time)','',...a['user_inputs']['map'](e=>'-\x20'+e),'','##\x20Risk-avoidance\x20checklist\x20(R1-R10)','',...a['trust_mechanisms']['map'](e=>'-\x20'+e),'','##\x20Build\x20notes','',...a['build_notes']['map'](e=>'-\x20'+e),''];return[...c,...d]['join']('\x0a');}export function renderTemplateFile(a){const b=canonicalTemplateContent(a);return releaseSentinelLine(TEMPLATE_SENTINEL_KIND,BUILTIN_TEMPLATES_VERSION,releaseBodyHash(b))+'\x0a'+b;}let seeded=![];function migrateLegacyTemplates(a){const b=resolveLegacyTemplatesDir();if(b===a)return;if(!existsSync(b))return;try{for(const c of readdirSync(b,{'withFileTypes':!![]})){if(!c['isDirectory']())continue;const d=join(b,c['name']),e=join(a,c['name'],TEMPLATES_SUBDIR);for(const g of readdirSync(d,{'withFileTypes':!![]})){if(!g['isFile']()||!g['name']['endsWith']('.md'))continue;const h=join(e,g['name']);if(existsSync(h))continue;mkdirSync(e,{'recursive':!![]}),renameSync(join(d,g['name']),h);}try{rmdirSync(d);}catch{}}try{rmdirSync(b);}catch{}}catch{}}export function seedBuiltinTemplates(){const a=[],b=resolveTemplatesDir();migrateLegacyTemplates(b);for(const c of BUILTIN_TEMPLATES){const d=join(b,c['industry'],TEMPLATES_SUBDIR),e=join(d,c['variant']+'.md'),f={'template':c['id'],'status':'written','path':e};try{if(!existsSync(e))mkdirSync(d,{'recursive':!![]}),writeFileSync(e,renderTemplateFile(c),'utf-8');else{const {sentinel:g,content:h}=stripReleaseSentinel(readFileSync(e,'utf-8'),TEMPLATE_SENTINEL_KIND);if(!g)f['status']='skipped_user_file',f['detail']='template\x20file\x20exists\x20without\x20builtin\x20sentinel;\x20leaving\x20user\x20file\x20untouched';else{const i=classifyRelease(g,h,BUILTIN_TEMPLATES_VERSION);if(i==='current')f['status']='current';else i==='user_modified'?(f['status']='skipped_user_modified',f['detail']='template\x20file\x20was\x20edited\x20locally;\x20keeping\x20user\x20content\x20and\x20not\x20upgrading'):(writeFileSync(e,renderTemplateFile(c),'utf-8'),f['status']='updated');}}}catch(j){f['status']='error',f['detail']=j['message'];}a['push'](f);}return a;}export function repairBuiltinTemplates(a){const b=[],c=resolveTemplatesDir(),d=a?.['backup']!==![],e=a?.['dryRun']===!![];for(const f of BUILTIN_TEMPLATES){const g=join(c,f['industry'],TEMPLATES_SUBDIR),h=join(g,f['variant']+'.md'),i={'template':f['id'],'status':'skipped_user_file','path':h};if(!existsSync(h))continue;let j=null;try{j=stripReleaseSentinel(readFileSync(h,'utf-8'),TEMPLATE_SENTINEL_KIND)['sentinel'];}catch(l){i['status']='error',i['detail']=l['message'],b['push'](i);continue;}if(j)continue;let k;try{k=String(parseTemplateFile(readFileSync(h,'utf-8'))['frontmatter']['id']??'');}catch{continue;}if(k!==f['id'])continue;if(e){i['status']='would_update',i['detail']='legacy\x20sentinel-less\x20builtin\x20file\x20would\x20be\x20reseeded\x20from\x20BUILTIN_TEMPLATES\x20('+f['id']+')'+(d?';\x20previous\x20content\x20would\x20be\x20saved\x20as\x20<file>.bak':'')+'\x20—\x20execute\x20with\x20authorize=true\x20after\x20the\x20user\x20explicitly\x20confirms',b['push'](i);continue;}try{if(d)copyFileSync(h,h+'.bak');writeFileSync(h,renderTemplateFile(f),'utf-8'),cache['delete'](h),i['status']='updated',i['detail']='legacy\x20sentinel-less\x20builtin\x20file\x20reseeded\x20from\x20BUILTIN_TEMPLATES\x20('+f['id']+')'+(d?';\x20previous\x20content\x20saved\x20as\x20<file>.bak':'');}catch(m){i['status']='error',i['detail']=m['message'];}b['push'](i);}return b;}export function builtinTemplateDrift(){const a=[],b=resolveTemplatesDir();for(const c of BUILTIN_TEMPLATES){const d=join(b,c['industry'],TEMPLATES_SUBDIR,c['variant']+'.md');if(!existsSync(d)){a['push']({'template':c['id'],'path':d,'state':'missing','detail':'no\x20file\x20on\x20disk;\x20seeding\x20will\x20create\x20it'});continue;}let e=null,f='';try{const h=stripReleaseSentinel(readFileSync(d,'utf-8'),TEMPLATE_SENTINEL_KIND);e=h['sentinel'],f=h['content'];}catch(i){a['push']({'template':c['id'],'path':d,'state':'missing','detail':'unreadable:\x20'+i['message']});continue;}if(!e){let j;try{j=String(parseTemplateFile(readFileSync(d,'utf-8'))['frontmatter']['id']??'');}catch{j=undefined;}a['push']({'template':c['id'],'path':d,'state':'no_sentinel_legacy','detail':j===c['id']?'builtin\x20id\x20but\x20NO\x20release\x20sentinel\x20—\x20seeding\x20classifies\x20this\x20as\x20a\x20user\x20file\x20and\x20will\x20NEVER\x20upgrade\x20it;\x20every\x20code-side\x20fix\x20to\x20this\x20template\x20is\x20invisible\x20at\x20runtime':'no\x20release\x20sentinel\x20and\x20id\x20\x27'+(j??'<unparseable>')+'\x27\x20does\x20not\x20match\x20a\x20builtin\x20id\x20—\x20treated\x20as\x20a\x20user\x20template,\x20never\x20touched'});continue;}const g=classifyRelease(e,f,BUILTIN_TEMPLATES_VERSION);if(g==='current')continue;a['push']({'template':c['id'],'path':d,'state':g==='user_modified'?'user_modified':'stale_release','detail':g==='user_modified'?'sentinel\x20present,\x20body\x20edited\x20locally\x20—\x20kept\x20by\x20design':'sentinel\x20present,\x20older\x20release\x20—\x20seeding\x20upgrades\x20it\x20on\x20next\x20access'});}return a;}const cache=new Map();export function reloadTemplates(){cache['clear'](),seeded=![];}export function loadAndValidate(a){const b=readFileSync(a,'utf-8');let c;try{c=parseTemplateFile(b);}catch(e){throw new Error('template\x20\x27'+a+'\x27\x20failed\x20to\x20parse:\x20'+e['message']);}const d=TemplateFrontmatterSchema['safeParse'](c['frontmatter']);if(!d['success']){const f=d['error']['issues']['map'](g=>(g['path']['join']('.')||'<root>')+':\x20'+g['message'])['join'](';\x20');throw new Error('template\x20\x27'+a+'\x27\x20failed\x20validation:\x20'+f);}return{...d['data'],'body':c['body'],'source_path':a};}function templateFilesOnDisk(a){const b=[];if(!existsSync(a))return b;for(const c of readdirSync(a,{'withFileTypes':!![]})){if(!c['isDirectory']())continue;const d=join(a,c['name'],TEMPLATES_SUBDIR);if(!existsSync(d))continue;for(const e of readdirSync(d,{'withFileTypes':!![]})){if(e['isFile']()&&e['name']['endsWith']('.md'))b['push'](join(d,e['name']));}}return b['sort']();}export function listTemplates(){!seeded&&(seedBuiltinTemplates(),seeded=!![]);const a=resolveTemplatesDir(),b=[],c=[],d=new Set();for(const e of templateFilesOnDisk(a)){d['add'](e);try{const f=statSync(e)['mtimeMs'],g=cache['get'](e);if(g&&g['mtimeMs']===f){b['push'](g['template']);continue;}const h=loadAndValidate(e);cache['set'](e,{'mtimeMs':f,'template':h}),b['push'](h);}catch(i){cache['delete'](e),c['push'](i['message']);}}for(const j of[...cache['keys']()]){if(!d['has'](j))cache['delete'](j);}return b['sort']((k,l)=>k['id']['localeCompare'](l['id'])),{'templates':b,'errors':c};}export function getTemplate(a){return listTemplates()['templates']['find'](b=>b['id']===a);}export function getTemplatesByIndustry(a){return listTemplates()['templates']['filter'](b=>b['industry']===a);}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{GUARD_TEMPLATES,fillGuardTemplate}from'./guard-templates.js';import{MACHINE_TEMPLATES,fillTemplate as
|
|
1
|
+
import{GUARD_TEMPLATES,fillGuardTemplate}from'./guard-templates.js';import{MACHINE_TEMPLATES,fillTemplate as a259a}from'./machine-templates.js';import{SERVICE_TEMPLATES,fillServiceTemplate}from'./service-templates.js';import{ORDER_TEMPLATES,fillTemplate as a259b}from'./order-templates.js';import{PROGRESS_TEMPLATES,fillProgressTemplate}from'./progress-templates.js';import{ARBITRATION_TEMPLATES,fillTemplate as a259c}from'./arbitration-templates.js';import{TREASURY_TEMPLATES,fillTemplate as a259d}from'./treasury-templates.js';import{PERMISSION_TEMPLATES,fillTemplate as a259e}from'./permission-templates.js';import{PASSPORT_TEMPLATES,fillTemplate as a259f}from'./passport-templates.js';import{ALLOCATION_TEMPLATES,fillTemplate as a259g}from'./allocation-templates.js';import{CONTACT_TEMPLATES,fillTemplate as a259h}from'./contact-templates.js';import{REWARD_TEMPLATES}from'./reward-templates.js';export const TEMPLATE_REGISTRY_VERSION=0x1;export const TEMPLATE_OBJECT_TYPES=['guard','machine','service','order','progress','arbitration','treasury','permission','passport','allocation','reward','contact'];function normalizeParam(a){return{'name':a['name'],'type':a['type'],'description':a['description']??'','required':a['required'],...a['default']!==undefined?{'default':a['default']}:{},...a['constraint']!==undefined?{'constraint':a['constraint']}:{}};}function guardMeta(a){return{'id':a['id'],'object_type':'guard','name':a['name'],'description':a['description'],'scenes':[a['scene_id']],'industries':a['applicable_industries'],'instantiable':!![],'parameters':a['parameters']['map'](b=>normalizeParam(b))};}function machineMeta(a){return{'id':a['id'],'object_type':'machine','name':a['name'],'description':a['description'],'scenes':[a['scene_id']],'industries':a['applicable_industries'],'instantiable':!![],'parameters':a['parameters']['map'](b=>normalizeParam(b))};}function bodyMeta(a,b,c,d){return{'id':a['id'],'object_type':b,'name':a['name'],'description':a['description'],'scenes':c,'industries':d,'instantiable':!![],'parameters':a['params']['map'](e=>normalizeParam(e))};}function rewardMeta(a){return{'id':a['type'],'object_type':'reward','name':a['name'],'description':a['description'],'scenes':[],'industries':[],'instantiable':![],'parameters':a['parameters']['map'](b=>normalizeParam(b))};}let REGISTRY=null,ID_COLLISIONS=[];function buildRegistry(){const a=new Map(),b=[],c=d=>{if(a['has'](d['meta']['id'])){b['push'](d['meta']['id']);return;}a['set'](d['meta']['id'],d);};for(const d of GUARD_TEMPLATES){c({'meta':guardMeta(d),'raw':d,'notes':d['creation_notes']});}for(const e of MACHINE_TEMPLATES){c({'meta':machineMeta(e),'raw':e,'notes':e['creation_notes']});}for(const f of SERVICE_TEMPLATES){c({'meta':bodyMeta(f,'service',f['applicable_scenes'],f['industry_tags']),'raw':f,'notes':f['notes']});}for(const g of ORDER_TEMPLATES){c({'meta':bodyMeta(g,'order',g['applicable_scenes'],g['industry_tags']),'raw':g,'notes':g['notes']});}for(const h of PROGRESS_TEMPLATES){c({'meta':bodyMeta(h,'progress',h['applicable_scenes'],h['industry_tags']),'raw':h,'notes':h['notes']});}for(const i of ARBITRATION_TEMPLATES){c({'meta':bodyMeta(i,'arbitration',i['applicable_scenes'],i['industry_tags']),'raw':i,'notes':i['notes']});}for(const j of TREASURY_TEMPLATES){c({'meta':bodyMeta(j,'treasury',j['applicable_scenes'],j['industry_tags']),'raw':j,'notes':j['notes']});}for(const k of PERMISSION_TEMPLATES){c({'meta':bodyMeta(k,'permission',k['applicable_scenes'],k['industry_tags']),'raw':k,'notes':k['notes']});}for(const l of PASSPORT_TEMPLATES){c({'meta':bodyMeta(l,'passport',l['applicable_scenarios'],l['industry_tags']),'raw':l,'notes':l['notes']});}for(const m of ALLOCATION_TEMPLATES){c({'meta':bodyMeta(m,'allocation',m['applicable_scenes'],m['industry_tags']),'raw':m,'notes':m['notes']});}for(const n of REWARD_TEMPLATES){c({'meta':rewardMeta(n),'raw':n,'guidance':{'guardCondition':n['guardCondition'],'amountRange':n['amountRange'],'allocationStrategy':n['allocationStrategy'],'example':n['example'],'relevantGuardOps':n['relevantGuardOps']}});}for(const o of CONTACT_TEMPLATES){c({'meta':bodyMeta(o,'contact',o['applicable_scenes'],o['industry_tags']),'raw':o,'notes':o['notes']});}return ID_COLLISIONS=b,a;}function registry(){return!REGISTRY&&(REGISTRY=buildRegistry()),REGISTRY;}export function getTemplateIdCollisions(){return registry(),ID_COLLISIONS;}export function getTemplateCounts(){const a=Object['fromEntries'](TEMPLATE_OBJECT_TYPES['map'](b=>[b,0x0]));for(const b of registry()['values']()){a[b['meta']['object_type']]+=0x1;}return a;}export function listTemplates(a){const b=[...registry()['values']()]['map'](c=>c['meta']);return a?b['filter'](c=>c['object_type']===a):b;}export function getTemplateDetail(a){const b=registry()['get'](a);if(!b)return null;return{...b['meta'],'raw':b['raw'],...b['notes']?{'notes':b['notes']}:{},...b['guidance']?{'guidance':b['guidance']}:{}};}export function findTemplateObjectType(a){return registry()['get'](a)?.['meta']['object_type']??null;}export function instantiateTemplate(a,b){const c=registry()['get'](a);if(!c)return{'ok':![],'object_type':null,'template_id':a,'error':'Template\x20not\x20found:\x20'+a+'.\x20Use\x20get_templates\x20without\x20\x27template\x27\x20to\x20list\x20all\x20template\x20ids.'};const d=c['meta']['object_type'];if(!c['meta']['instantiable'])return{'ok':![],'object_type':d,'template_id':a,'error':'Reward\x20templates\x20are\x20guidance-only\x20(prose\x20guard\x20conditions)\x20and\x20cannot\x20be\x20'+'instantiated\x20into\x20executable\x20JSON.\x20Use\x20the\x20guidance\x20payload\x20to\x20design\x20the\x20'+'Reward\x20+\x20Guard\x20manually.','guidance':c['guidance']};switch(d){case'guard':{const e=fillGuardTemplate(a,b);if(!e['ok'])return{'ok':![],'object_type':d,'template_id':a,'error':e['error'],...e['missing']?{'missing_params':e['missing']}:{}};return{'ok':!![],'object_type':d,'template_id':a,'body':{'table':e['table'],'root':e['root']},...c['notes']?{'notes':c['notes']}:{}};}case'machine':{const f=a259a(a,b);if(!f['success'])return{'ok':![],'object_type':d,'template_id':a,'error':f['validation_errors']?.['join'](';\x20')??'Machine\x20template\x20fill\x20failed',...f['missing_params']?{'missing_params':f['missing_params']}:{}};return{'ok':!![],'object_type':d,'template_id':a,'body':{'nodes':f['filled_nodes'],'pairs':f['filled_pairs']},...c['notes']?{'notes':c['notes']}:{}};}case'service':{const g=fillServiceTemplate(a,b);if(!g['ok'])return{'ok':![],'object_type':d,'template_id':a,'error':g['error']??'Service\x20template\x20fill\x20failed',...g['missing_required']?{'missing_params':g['missing_required']}:{}};return{'ok':!![],'object_type':d,'template_id':a,'body':g['body'],...c['notes']?{'notes':c['notes']}:{}};}case'order':case'arbitration':case'treasury':case'permission':case'passport':case'allocation':case'progress':case'contact':{const h=fillBodyTemplate(d,a,b);if(!h['ok'])return{'ok':![],'object_type':d,'template_id':a,'error':h['error']};return{'ok':!![],'object_type':d,'template_id':a,'body':h['body'],...c['notes']?{'notes':c['notes']}:{}};}default:return{'ok':![],'object_type':d,'template_id':a,'error':'Instantiation\x20not\x20supported\x20for\x20object_type\x20\x27'+d+'\x27'};}}function fillBodyTemplate(a,b,c){switch(a){case'order':return a259b(b,c);case'arbitration':return a259c(b,c);case'treasury':return a259d(b,c);case'permission':return a259e(b,c);case'passport':return a259f(b,c);case'allocation':return a259g(b,c);case'progress':return fillProgressTemplate(b,c);case'contact':return a259h(b,c);default:return{'ok':![],'error':'No\x20body-template\x20fill\x20for\x20\x27'+a+'\x27'};}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ENTRYPOINT}from'@wowok/wowok';import{buildViewport,runNodeAnalyzers}from'../graph/onchain/index.js';import{makeProposalNode}from'../graph/onchain/proposal-graph.js';import{machineRuleNodeAnalyzer,allocationRuleNodeAnalyzer}from'./rule-node-analyzers.js';import{GUARD_TEMPLATES}from'./guard-templates.js';import{GUARD_DESIGN_PATTERNS}from'./guard-design-patterns.js';import{unannotatedBuyerActionNodes}from'./scenario-modes.js';const PLATFORM_TAKE_KEY=/^(?:platform_(?:share|commission|take)_bps|platform_fee_rate_bps|commission_rate_bps|(?:base_)?commission_rate_bps|offsite_ads_rate_bps|service_fee_rate_bps|payment_fee_bps)$/,MERCHANT_OWN_PRICE_KEY=/^(?:merchant_service_fee_bps|contract_fee_(?:small|large)_usd|contract_fee_tier_boundary_usd|digital_product_fee_(?:bps|min_usd|max_usd)|arbitration_fee.*|escrow_.*|min_.*|max_.*)$/,MERCHANT_SHARE_KEY=/^(?:host|property|partner|institution|landlord|freelancer|creator|seller|instructor)_rate_bps$/;function directSalesEconomyChecks(a){const b=[],c=a['fee_params'],d=Object['keys'](c)['filter'](n=>PLATFORM_TAKE_KEY['test'](n)&&typeof c[n]==='number'&&c[n]!==0x0);d['length']>0x0&&b['push']({'rule_id':'R-ECON-01','severity':'critical','title':'Template\x20mandates\x20a\x20platform\x20commission\x20('+d['map'](n=>n+'='+c[n])['join'](',\x20')+')','detail':'WoWok\x20is\x20DIRECT\x20SALES:\x20the\x20protocol\x20never\x20extracts\x20and\x20a\x20merchant\x20pays\x20only\x20gas,\x20so\x20the\x20merchant-side\x20share\x20must\x20default\x20to\x20the\x20whole\x20sale.\x20A\x20non-zero\x20platform\x20take\x20is\x20(a)\x20an\x20extraction\x20the\x20platform\x20has\x20no\x20right\x20to,\x20and\x20(b)\x20an\x20UNALLOCATED\x20liability\x20—\x20no\x20template\x20declares\x20a\x20platform\x20address,\x20so\x20at\x20build\x20time\x20it\x20resolves\x20to\x20the\x20deploying\x20merchant\x20itself\x20(blank\x20→\x20Account.Instance(),\x20ts-sdk/w/local/index.ts:74-86),\x20to\x20the\x20keeper\x20(Recipient::Signer\x20→\x20tx_context::sender,\x20allocation.move:386-387),\x20or\x20back\x20to\x20the\x20buyer\x20(Recipient::GuardIdentifier,\x20allocation.move:378-382).\x20None\x20of\x20those\x20is\x20revenue.','suggestion':'Set\x20'+d['join'](',\x20')+'\x20to\x200\x20and\x20give\x20the\x20merchant\x20the\x20whole\x20sale\x20(single\x20Rate\x2010000\x20leg).\x20If\x20the\x20merchant\x20IS\x20the\x20aggregator\x20and\x20genuinely\x20charges\x20a\x20fee,\x20declare\x20it\x20via\x20merchant_service_fee_bps\x20with\x20an\x20EXPLICIT\x20non-empty\x20recipient\x20Entity.'});const e=a['allocator']['description'],f=/(?:commission|take|platform|remainder|share)\s*(?:=|:)\s*order\s*total\s*-\s*(?:segment|sum)/i['test'](e),g=/(?:platform|commission|fee|take)[^.;]{0,120}\bsurplus\b|\bsurplus\b[^.;]{0,120}(?:platform|commission|fee|take)/i['test'](e);f&&b['push']({'rule_id':'R-ECON-02','severity':'critical','title':'Take\x20is\x20an\x20implicit\x20remainder\x20(not\x20computable\x20before\x20ordering)','detail':'The\x20allocator\x20describes\x20the\x20platform\x20share\x20as\x20\x22order\x20total\x20-\x20segment\x20sums\x22,\x20so\x20the\x20amount\x20taken\x20depends\x20on\x20the\x20segment\x20configuration\x20rather\x20than\x20a\x20declared\x20rate.\x20A\x20buyer\x20(or\x20their\x20AI)\x20cannot\x20compute\x20the\x20take\x20BEFORE\x20ordering,\x20which\x20defeats\x20pre-order\x20evaluation\x20—\x20and\x20an\x20unbounded\x20remainder\x20off\x20a\x20transit\x20pool\x20is\x20unbounded\x20extraction.','suggestion':'Pin\x20every\x20share\x20to\x20an\x20EXPLICIT\x20Rate\x20(or\x20an\x20Amount\x20derived\x20from\x20a\x20declared\x20rate).\x20A\x20supplier\x20fee\x20belongs\x20in\x20its\x20own\x20explicitly-priced\x20segment\x20order,\x20never\x20as\x20a\x20residual\x20share.'});g&&b['push']({'rule_id':'R-ECON-02','severity':'high','title':'Fee\x20appears\x20to\x20be\x20taken\x20by\x20a\x20Surplus\x20leg','detail':'A\x20Surplus\x20sharing\x20entry\x20allocates\x20the\x20WHOLE\x20remaining\x20balance\x20(allocation.move:427\x20withdraw_all\x20semantics),\x20so\x20it\x20cannot\x20express\x20\x22take\x2015%\x22:\x20it\x20doubles\x20as\x20draining\x20the\x20pool.\x20Note\x20the\x20SAME\x20mechanism\x20is\x20why\x20rental/p2p-shortstay\x20disables\x20Surplus\x20outright\x20to\x20protect\x20the\x20claim-window\x20balance.','suggestion':'Use\x20Rate\x20(or\x20RateGross)\x20for\x20any\x20proportional\x20share.\x20Reserve\x20Surplus\x20for\x20an\x20explicitly-bounded\x20residual\x20whose\x20recipient\x20and\x20cap\x20are\x20stated.'});const h=/\{\s*(?:who|Entity|Signer|GuardIdentifier)\s*:/['test'](e)||/recipient\s*[:=]/i['test'](e),i=/^(?:merchant_service_fee_bps|digital_product_fee_bps|logistics_rate_bps|service_fee_rate_bps)$/,j=Object['keys'](c)['some'](n=>i['test'](n)&&typeof c[n]==='number'&&c[n]!==0x0);j&&!h&&d['length']===0x0&&b['push']({'rule_id':'R-ECON-03','severity':'high','title':'Fee-bearing\x20template\x20names\x20no\x20recipient\x20slot\x20for\x20the\x20non-merchant\x20share','detail':'fee_params\x20carry\x20fee-shaped\x20keys\x20but\x20the\x20allocator\x20names\x20no\x20recipient\x20for\x20them.\x20On-chain\x20each\x20Rate\x20lands\x20in\x20ITS\x20OWN\x20recipient\x20slot;\x20an\x20unnamed\x20one\x20resolves\x20to\x20the\x20deploying\x20account\x20(ts-sdk/w/local/index.ts:74-86),\x20to\x20the\x20keeper\x20(allocation.move:386-387),\x20or\x20back\x20to\x20the\x20buyer.\x20The\x20share\x20is\x20then\x20an\x20unallocated\x20liability\x20rather\x20than\x20revenue.','suggestion':'State\x20the\x20recipient\x20per\x20share\x20in\x20the\x20allocator\x20description\x20and\x20bind\x20it\x20to\x20an\x20explicit\x20NON-EMPTY\x20Entity\x20the\x20buyer\x20can\x20see\x20before\x20ordering.\x20Never\x20leave\x20it\x20blank.'});const k=/(?:layer-?1|service-?level|pool)[^.]*settles? the full amount|full amount to the (?:platform|organizer) pool/i['test'](e);k&&b['push']({'rule_id':'R-ECON-04','severity':'medium','title':'Escrow\x20transits\x20an\x20organizer\x20pool\x20before\x20reaching\x20the\x20merchant','detail':'The\x20full\x20order\x20amount\x20settles\x20into\x20a\x20platform/organizer\x20pool\x20first\x20and\x20is\x20then\x20redistributed.\x20That\x20contradicts\x20the\x20direct-sales\x20promise\x20(\x22money\x20moves\x20only\x20between\x20the\x20two\x20parties\x22)\x20and\x20makes\x20the\x20organizer\x20a\x20waypoint\x20on\x20every\x20payout,\x20including\x20every\x20refund.','suggestion':'Release\x20supplier\x20segments\x20directly\x20from\x20the\x20order\x27s\x20own\x20Allocation,\x20and\x20make\x20the\x20organizer\x20a\x20named\x20party\x20rather\x20than\x20a\x20transit\x20node.'});const l=Object['keys'](c)['find'](n=>/^attributed_.*_bps$/['test'](n)&&typeof c[n]==='number'),m=Object['keys'](c)['find'](n=>/^(?:base_)?commission_rate_bps$/['test'](n)&&typeof c[n]==='number');l&&m&&c[l]>c[m]&&b['push']({'rule_id':'R-ECON-05','severity':'medium','title':'Attribution-priced\x20take:\x20a\x20cheaper\x20acquisition\x20channel\x20is\x20charged\x20MORE','detail':l+'='+c[l]+'\x20exceeds\x20'+m+'='+c[m]+'.\x20Charging\x20more\x20for\x20attributed\x20orders\x20means\x20the\x20merchant\x27s\x20cheap\x20channels\x20(KOC,\x20social,\x20repeat\x20buyers)\x20are\x20penalised\x20—\x20the\x20opposite\x20of\x20what\x20direct\x20sales\x20should\x20reward.','suggestion':'Price\x20every\x20channel\x20identically.\x20Attribution\x20may\x20change\x20RANKING,\x20never\x20the\x20take.'});if(a['allocator']['mode']==='rate'){const n=Object['keys'](c)['filter'](q=>MERCHANT_SHARE_KEY['test'](q)&&typeof c[q]==='number'),o=Object['keys'](c)['filter'](q=>PLATFORM_TAKE_KEY['test'](q)&&typeof c[q]==='number'),p=[...n,...o];if(n['length']>0x0&&o['length']>0x0){const q=p['map'](u=>c[u])['filter'](u=>typeof u==='number'),r=q['reduce']((u,v)=>u+v,0x0),s=/surplus/i['test'](e);r!==0x2710&&!s&&b['push']({'rule_id':'R-ECON-06','severity':'critical','title':'Rate\x20shares\x20sum\x20to\x20'+r+',\x20not\x2010000','detail':'Declared\x20rate\x20shares\x20('+p['map']((u,v)=>u+'='+q[v])['join']('\x20+\x20')+')\x20total\x20'+r+'.\x20With\x20no\x20Surplus\x20recipient\x20the\x20remainder\x20is\x20not\x20protected:\x20the\x20chain\x20records\x20no\x20\x22already\x20triggered\x22\x20flag,\x20so\x20a\x20balance\x20left\x20behind\x20after\x20a\x20partial\x20split\x20can\x20be\x20claimed\x20REPEATEDLY\x20by\x20anyone\x20passing\x20the\x20same\x20Guard.\x20This\x20is\x20exactly\x20what\x20happens\x20when\x20a\x20platform\x20leg\x20is\x20zeroed\x20without\x20recomputing\x20the\x20merchant\x20leg.','suggestion':'Make\x20the\x20shares\x20sum\x20to\x20exactly\x2010000,\x20or\x20declare\x20an\x20explicit\x20Surplus\x20recipient\x20for\x20the\x20residual.'});}}return b;}const DISPUTE_NODE_REGEX=/(^|_)(disputed?|arbitration|arb)(_|$)|^(refund|refunded|deposit_refunded|deposit_deducted|cancel|cancelled)$/i,KNOWN_GUARD_REF_IDS=new Set([...GUARD_DESIGN_PATTERNS['map'](a=>a['id']),...GUARD_TEMPLATES['map'](a=>a['id'])]);function guardRefChecks(a){const b=[];for(const c of a['guards']){if(!/^(pattern\.[a-z0-9_]+|tpl_[a-z0-9_]+)$/['test'](c['template_id'])){b['push']({'rule_id':'R-REF-01','severity':'high','title':'Guard\x20reference\x20\x27'+c['template_id']+'\x27\x20is\x20not\x20a\x20resolvable\x20id','detail':'Guard\x20references\x20must\x20name\x20a\x20guard\x20design\x20pattern\x20(\x27pattern.*\x27,\x20'+GUARD_DESIGN_PATTERNS['length']+'\x20available)\x20or\x20a\x20guard\x20template\x20(\x27tpl_*\x27,\x20'+GUARD_TEMPLATES['length']+'\x20available).\x20Bare\x20prose\x20ids\x20dangle:\x20no\x20builder\x20can\x20resolve\x20them,\x20so\x20the\x20AI\x20invents\x20guard\x20logic\x20at\x20build\x20time.','suggestion':'Replace\x20with\x20the\x20semantically\x20nearest\x20pattern.*/tpl_*\x20id\x20(compose\x20multi-condition\x20logic\x20in\x20the\x20purpose\x20text).'});continue;}!KNOWN_GUARD_REF_IDS['has'](c['template_id'])&&b['push']({'rule_id':'R-REF-02','severity':'high','title':'Guard\x20reference\x20\x27'+c['template_id']+'\x27\x20does\x20not\x20exist\x20in\x20any\x20guard\x20catalog','detail':'The\x20id\x20is\x20namespaced\x20correctly\x20but\x20matches\x20no\x20guard\x20design\x20pattern\x20nor\x20guard\x20template\x20—\x20a\x20dangling\x20reference\x20the\x20AI\x20cannot\x20resolve.','suggestion':'Fix\x20the\x20id\x20(typo)\x20or\x20point\x20it\x20at\x20the\x20nearest\x20existing\x20pattern.*/tpl_*\x20entry.'});}return b;}function staticChecks(a){const b=[];for(const f of a['machine_shape']){DISPUTE_NODE_REGEX['test'](f['name'])&&b['push']({'rule_id':'R-M1-11','severity':'critical','title':'Machine\x20node\x20\x27'+f['name']+'\x27\x20models\x20dispute/refund\x20flow','detail':'Disputes\x20are\x20independent\x20of\x20the\x20Machine\x20workflow;\x20refunds\x20route\x20via\x20Allocators\x20triggered\x20by\x20business\x20states.','suggestion':'Remove\x20the\x20node;\x20route\x20refunds\x20via\x20Allocator\x20states\x20(closed_cancel/returned)\x20and\x20disputes\x20via\x20the\x20Arbitration\x20object.'});}for(const h of a['guards']){/time_lock|order_holder|progress_state/['test'](h['template_id'])&&!/order\.service|project bind|service binding/i['test'](h['purpose'])&&b['push']({'rule_id':'R-C3-05','severity':'medium','title':'Guard\x20\x27'+h['template_id']+'\x27\x20consumes\x20a\x20submitted\x20Order\x20without\x20project\x20binding','detail':'Passport\x20submissions\x20are\x20caller-built;\x20without\x20logic_equal[order.service,\x20<service>]\x20a\x20stale\x20order\x20from\x20another\x20project\x20can\x20satisfy\x20the\x20guard\x20for\x20a\x20fresh\x20order.','suggestion':'State\x20the\x20project\x20binding\x20in\x20the\x20guard\x20purpose\x20AND\x20include\x20it\x20in\x20the\x20guard\x20root\x20at\x20build\x20time.'});}a['machine_shape']['length']===0x0&&b['push']({'rule_id':'R-M1-01','severity':'critical','title':'machine_shape\x20is\x20empty','detail':'No\x20entry\x20node\x20—\x20the\x20Machine\x20cannot\x20start.','suggestion':'Add\x20at\x20least\x20one\x20entry\x20node\x20representing\x20the\x20escrowed\x20state.'});const c=a['guards']['some'](i=>/refund|cancel/i['test'](i['template_id'])||/refund|cancel/i['test'](i['purpose']))||/refund/i['test'](a['allocator']['description']);!c&&b['push']({'rule_id':'R1','severity':'high','title':'No\x20refund\x20path\x20detected','detail':'No\x20refund/cancel\x20guard\x20and\x20no\x20refund\x20route\x20in\x20the\x20allocator\x20description.','suggestion':'Add\x20a\x20refund/cancel\x20guard\x20or\x20an\x20allocator\x20refund\x20route\x20before\x20publishing.'});const d=a['guards']['some'](i=>i['host']==='arbitration')||a['trust_mechanisms']['some'](i=>i['startsWith']('R2'));!d&&b['push']({'rule_id':'R2','severity':'high','title':'No\x20independent\x20Arbitration\x20reference\x20detected','detail':'The\x20template\x20carries\x20no\x20arbitration-hosted\x20guard\x20and\x20no\x20R2\x20trust\x20mechanism.','suggestion':'Mount\x20an\x20independent\x20Arbitration\x20object\x20with\x20its\x20own\x20Permission.'});a['keeper_dependencies']['length']===0x0&&b['push']({'rule_id':'R9','severity':'medium','title':'No\x20keeper\x20dependencies\x20declared','detail':'Time-driven\x20transitions\x20only\x20ALLOW\x20advancement\x20—\x20someone\x20must\x20run\x20the\x20keepers.','suggestion':'Declare\x20the\x20keeper\x20operations\x20(timeouts,\x20window\x20expiries,\x20settlement\x20triggers).'});b['push'](...directSalesEconomyChecks(a));const e=unannotatedBuyerActionNodes(a['machine_shape']);return e['length']>0x0&&b['push']({'rule_id':'R-OPER-01','severity':'medium','title':'Buyer-side\x20node(s)\x20without\x20an\x20operator\x20annotation','detail':'Node(s)\x20'+e['map'](i=>'\x27'+i+'\x27')['join'](',\x20')+'\x20look\x20like\x20order-payer\x20actions\x20but\x20carry\x20no\x20operator\x20field.\x20At\x20build\x20time\x20they\x20default\x20to\x20a\x20merchant\x20permission\x20slot,\x20and\x20the\x20order\x20payer\x20cannot\x20advance\x20them\x20(E_PERMISSION_DENIED).','suggestion':'Annotate\x20true\x20buyer\x20actions\x20with\x20operator:\x20\x22order_payer\x22\x20(an\x20EMPTY\x20namedOperator\x20—\x20the\x20on-chain\x20check\x20resolves\x20it\x20to\x20the\x20order\x20payer);\x20rename\x20merchant-side\x20states\x20(e.g.\x20\x27cancelled\x27\x20->\x20\x27merchant_cancelled\x27)\x20when\x20the\x20actor\x20is\x20NOT\x20the\x20buyer.'}),b;}const PERIOD_COUNT_KEY_REGEX=/^(monthly_allocators|term_count|session_count|segment_count|periods|cycles|installments)$/;function poolPeriodCount(a){for(const [b,c]of Object['entries'](a['fee_params'])){if(PERIOD_COUNT_KEY_REGEX['test'](b)&&typeof c==='number'&&c>=0x2)return c;}return undefined;}function periodicReleaseChecks(a){const b=poolPeriodCount(a);if(b===undefined)return[];const c=[a['allocator']['description'],...a['build_notes'],...a['trust_mechanisms'],...a['guards']['map'](f=>f['purpose'])]['join']('\x20\x0a\x20'),d=[];/surplus/i['test'](c)&&!/no surplus|surplus[^.\n]*(disabled|forbidden|disallowed)|amount mode only|single surplus/i['test'](c)&&d['push']({'rule_id':'R-PER-01','severity':'high','title':'Multi-period\x20pool\x20('+b+'\x20periods)\x20declares\x20Surplus\x20without\x20a\x20terminal-only\x20qualifier','detail':'A\x20Surplus\x20allocator\x20entry\x20runs\x20balance::withdraw_all\x20(allocation.move:288-298).\x20In\x20a\x20pool\x20pre-funded\x20for\x20'+b+'\x20periods\x20it\x20drains\x20every\x20future\x20release,\x20not\x20just\x20the\x20remainder.','suggestion':'Release\x20each\x20period\x20with\x20Amount;\x20if\x20the\x20pool\x20remainder\x20settles\x20in\x20one\x20entry,\x20declare\x20it\x20explicitly\x20as\x20the\x20SINGLE\x20terminal\x20Surplus\x20at\x20the\x20settlement\x20node,\x20or\x20disable\x20Surplus\x20outright.'});const e=/per[- ](month|period|term|session|cycle|segment)|one per (rent )?period|release-sequence lock/i['test'](c);return!e&&d['push']({'rule_id':'R-PER-02','severity':'high','title':'Multi-period\x20pool\x20('+b+'\x20periods)\x20declares\x20no\x20per-period\x20release\x20Guard','detail':'alloc()\x20has\x20no\x20consumed/nonce\x20flag\x20(allocation.move:204-321):\x20two\x20releases\x20bound\x20to\x20the\x20SAME\x20Guard\x20can\x20both\x20fire\x20the\x20same\x20day\x20and\x20drain\x20the\x20pool.\x20The\x20cadence\x20gate\x20must\x20be\x20one\x20Guard\x20per\x20period.','suggestion':'Declare\x20one\x20release\x20Guard\x20per\x20period\x20(per-month/per-term\x20time-lock\x20Guards,\x20each\x20keyed\x20to\x20its\x20own\x20period\x20window)\x20in\x20the\x20guard\x20set.'}),!/threshold[^.\n]*(one|single|per[- ]|month|period|term|session|=\s*0\b|\b0\b|must be 0)/i['test'](c)&&d['push']({'rule_id':'R-PER-03','severity':'medium','title':'Multi-period\x20pool\x20('+b+'\x20periods)\x20does\x20not\x20pin\x20threshold\x20to\x20one\x20period','detail':'alloc()\x20asserts\x20balance\x20>=\x20threshold\x20before\x20EVERY\x20release\x20(allocation.move:206).\x20A\x20threshold\x20sized\x20to\x20the\x20total\x20pool\x20passes\x20the\x20first\x20release\x20and\x20then\x20locks\x20all\x20remaining\x20periods.','suggestion':'State\x20in\x20the\x20allocator\x20description\x20or\x20build\x20notes\x20that\x20threshold\x20=\x20one\x20period\x27s\x20release\x20amount\x20(never\x20the\x20pre-funded\x20total).'}),d;}const MIN_PRICE_KEY_REGEX=/^(?:min_[a-z0-9_]*?(?:price|amount|usd|value)|price_floor)$/,FLOOR_TEXT_REGEX=/fixed (?:fee|charge)[^.\n]*(?:<|less than|below) [^.\n]*(?:lowest|minimum|min)|minimum (?:sku|order|item|unit) (?:price|amount)|(?:below|under|<=)\s*the\s+smallest[^.\n]*(?:order|escrow|booking|price)/i,FIXED_FEE_TEXT_REGEX=/\bamount mode\b|fixed (?:fee|fulfillment|fulfilment|per[- ]order) (?:fee|charge)|\bAmount\b[^.\n]*(?:fee|charge)/i;function fundAnchorChecks(a){const b=[],c=[a['allocator']['description'],...a['build_notes'],...a['trust_mechanisms'],...a['guards']['map'](h=>h['template_id']+'\x20'+h['purpose'])]['join']('\x20\x0a\x20'),d=a['allocator']['refund_track']==='order_anchored'||/allocator_order_anchor/['test'](c)||/guardidentifier\(0\)|order[- ]anchored|for_object/i['test'](c);!d&&b['push']({'rule_id':'R-ANCHOR-01','severity':'critical','title':'Allocator\x20has\x20no\x20order\x20anchor\x20—\x20its\x20Guard\x20cannot\x20bind\x20the\x20paying\x20Order','detail':'Every\x20recipient\x20of\x20this\x20allocator\x20is\x20a\x20fixed\x20party\x20(recipient=\x27'+a['allocator']['recipient']+'\x27,\x20no\x20GuardIdentifier\x20row),\x20so\x20nothing\x20in\x20the\x20Guard\x27s\x20verification\x20context\x20names\x20the\x20Order\x20being\x20settled:\x20Recipient::Entity/Signer\x20are\x20resolved\x20without\x20any\x20submission\x20check\x20(allocation.move:383-388)\x20and\x20the\x20Allocation\x20itself\x20never\x20enters\x20the\x20Guard\x20context.\x20Testnet\x20proved\x20the\x20consequence:\x20a\x20passport\x20built\x20from\x20an\x20ALREADY-SETTLED\x20order\x20of\x20the\x20same\x20Service\x20drained\x20a\x20different\x20order\x27s\x20escrow\x20(CR-01).\x20The\x20identifier-255\x20once-slot\x20does\x20not\x20help\x20—\x20it\x20is\x20stored\x20per\x20Allocation,\x20so\x20a\x20fresh\x20pool\x20has\x20no\x20record.','suggestion':'Adopt\x20pattern.allocator_order_anchor:\x20add\x20one\x20{GuardIdentifier:\x200}\x20row\x20with\x20Rate\x200\x20(pays\x20nothing,\x20makes\x20the\x20submitted\x20Order\x20the\x20Guard\x27s\x20binding\x20target),\x20declare\x20refund_track:\x20\x22order_anchored\x22,\x20and\x20pin\x20the\x20Guard\x20expression\x20to\x20that\x20identifier\x20plus\x20logic_equal[order.service,\x20<this\x20service>].'});const e=a['allocator']['mode']==='amount',f=e||FIXED_FEE_TEXT_REGEX['test'](c),g=Object['keys'](a['fee_params'])['some'](h=>MIN_PRICE_KEY_REGEX['test'](h))||FLOOR_TEXT_REGEX['test'](c);return f&&!g&&b['push']({'rule_id':'R-FIXFEE-01','severity':e?'critical':'high','title':'Fixed\x20Amount\x20fee\x20with\x20no\x20minimum\x20order\x20value\x20—\x20sub-fee\x20orders\x20deadlock\x20permanently','detail':'alloc()\x20asserts\x20balance\x20>=\x20fix\x20before\x20distributing\x20(allocation.move:322):\x20an\x20order\x20escrowed\x20BELOW\x20the\x20fixed\x20fee\x20can\x20never\x20settle,\x20and\x20the\x20terminal\x20nodes\x20(completed/closed_cancel)\x20leave\x20no\x20refund\x20path\x20for\x20it,\x20so\x20buyer\x20funds\x20and\x20the\x20order\x20strand\x20forever\x20(testnet\x20CR-02,\x20reproduced\x20on\x20a\x200.001\x20WOW\x20SKU\x20against\x20a\x200.15\x20WOW\x20fee).','suggestion':'Declare\x20a\x20minimum\x20listing/order\x20value\x20above\x20every\x20fixed\x20leg\x20in\x20fee_params\x20(e.g.\x20min_sku_price)\x20and\x20state\x20it\x20in\x20the\x20allocator\x20description,\x20or\x20model\x20the\x20per-order\x20fee\x20as\x20Rate/RateGross\x20instead\x20of\x20a\x20fixed\x20Amount.'}),a['allocator']['once_per_order']===!![]&&!/per[- ]allocation|per[- ]pool|not cross[- ]order|within (a|the) (pool|allocation)/i['test'](c)&&b['push']({'rule_id':'R-ONCE-SCOPE-01','severity':'medium','title':'once_per_order\x20claim\x20does\x20not\x20state\x20its\x20per-Allocation\x20scope','detail':'The\x20identifier-255\x20once-slot\x20is\x20keyed\x20(guard,\x20allocator,\x20submission)\x20ON\x20ONE\x20Allocation,\x20so\x20replay\x20immunity\x20holds\x20within\x20a\x20single\x20pool\x20only;\x20a\x20second\x20Allocation\x20of\x20the\x20same\x20Service\x20starts\x20with\x20no\x20record.\x20Presenting\x20ONCE\x20as\x20general\x20idempotency\x20is\x20what\x20let\x20testnet\x20CR-01\x20read\x20as\x20\x27already\x20protected\x27.','suggestion':'Say\x20explicitly\x20that\x20255\x20protects\x20one\x20pool,\x20and\x20pair\x20it\x20with\x20the\x20order\x20anchor\x20(R-ANCHOR-01)\x20for\x20cross-order\x20safety.'}),b;}function templateText(a,b=[]){return[a['allocator']['description'],...a['build_notes'],...a['trust_mechanisms'],...a['guards']['map'](c=>c['template_id']+'\x20'+c['purpose']),...a['machine_shape']['map'](c=>c['name']+'\x20'+c['role']),...Object['entries'](a['time_anchors']??{})['map'](([c,d])=>c+'\x20'+d),...b]['join']('\x20\x0a\x20');}const STAY_DATE_REGEX=/check[\s-]?in|check[\s-]?out|departure\s+date|arrival\s+date|booking\s+date|checkin|checkout|stay\s+date|stay_nights|\bstay\s+nights?\b|\bper\s+night\b|入住|退房|离店|到店日/i,CHAIN_CLOCK_REGEX=/order\.time|progress\.current_time|\border\s+time\b|witness/i,REPOSITORY_DATE_SOURCE_REGEX=/(?:write|writes|written|storing|store|stores|persist|persisted|record|records|read|reads)\b[^.\n]{0,90}repositor|repositor\w*\b[^.\n]{0,90}(?:stay|check[\s-]?in|check[\s-]?out|departure|arrival|date)/i;function timeWindowAnchorChecks(a){const b=templateText(a);if(!STAY_DATE_REGEX['test'](b))return[];if(CHAIN_CLOCK_REGEX['test'](b)||REPOSITORY_DATE_SOURCE_REGEX['test'](b))return[];const c=b['match'](new RegExp(STAY_DATE_REGEX['source'],'gi'))??[],d=/\d+\s*[-–]\s*\d+\s*h(?:ours?|rs?)?\s*(?:adjustable|tunable|configurable)|\badjustable\b|\btunable\b/i['test'](b);return[{'rule_id':'R-WIN-ANCHOR-01','severity':'high','title':'Per-order\x20time\x20window(s)\x20anchored\x20to\x20a\x20stay\x20date\x20that\x20does\x20not\x20exist\x20on\x20chain\x20('+Array['from'](new Set(c))['slice'](0x0,0x5)['join'](',\x20')+')','detail':'The\x20template\x27s\x20windows\x20are\x20relative\x20to\x20a\x20check-in\x20/\x20check-out\x20/\x20departure\x20/\x20night\x20date.\x20No\x20such\x20field\x20exists\x20on\x20chain:\x20'+'`Order.items`\x20is\x20`vector<SaleItem>`\x20with\x20`SaleItem\x20{\x20item,\x20price,\x20quantity,\x20wip_hash\x20}`\x20(order.move:28-33)\x20and\x20the\x20purchasable\x20'+'`Sale\x20{\x20name,\x20price,\x20stock,\x20suspension,\x20wip,\x20wip_hash\x20}`\x20(service.move:100-107)\x20carries\x20no\x20schedule;\x20the\x20only\x20per-order\x20clock\x20is\x20'+'`Order.time`\x20(order.move:74),\x20the\x20CREATION\x20timestamp.\x20`Progress.current_time`\x20(progress.move:85)\x20is\x20overwritten\x20on\x20every\x20forward\x20'+'(progress.move:458)\x20and\x20`Progress.history`\x20records\x20node\x20visits,\x20so\x20neither\x20is\x20a\x20business\x20date.\x20A\x20window\x20declared\x20relative\x20to\x20the\x20'+'stay\x20calendar\x20is\x20therefore\x20UNREACHABLE\x20—\x20every\x20published\x20Guard\x20silently\x20measures\x20from\x20booking\x20time\x20instead,\x20and\x20for\x20a\x20lead\x20time\x20of\x20'+'days-to-weeks\x20that\x20is\x20a\x20material\x20semantic\x20loss,\x20not\x20a\x20rounding\x20error.'+(d?'\x20The\x20window\x20is\x20also\x20advertised\x20as\x20adjustable,\x20which\x20is\x20doubly\x20unreachable:\x20a\x20Guard\x20is\x20frozen\x20at\x20creation\x20'+'(transfer::freeze_object,\x20guard.move:262)\x20and\x20Machine\x20forwards\x20are\x20immutable\x20after\x20publish\x20(the\x20not-published\x20guard,\x20'+'machine.move:313),\x20so\x20an\x20\x27N-Mh\x20adjustable\x27\x20window\x20means\x20one\x20separately\x20published\x20Guard\x20per\x20window\x20value,\x20never\x20a\x20tunable\x20one.':''),'suggestion':'Express\x20every\x20window\x20relative\x20to\x20`order.time`\x20(or\x20`order.time\x20+\x20<window>`),\x20and\x20if\x20the\x20business\x20promise\x20is\x20genuinely\x20a\x20stay-date\x20'+'deadline,\x20write\x20the\x20stay\x20dates\x20into\x20a\x20Repository\x20at\x20buy\x20time,\x20pin\x20that\x20Repository\x20address\x20as\x20a\x20table\x20constant,\x20and\x20read\x20them\x20in\x20the\x20'+'Guard\x20(`query\x20repository.data`).\x20State\x20the\x20residual\x20semantic\x20loss\x20in\x20build_notes\x20rather\x20than\x20declaring\x20a\x20calendar-relative\x20window.'}];}function signerRefundChecks(a){const b=[],c=a['allocator']['rows']??[],d=c['find'](i=>i['recipient']==='signer'),e=a['allocator']['recipient']==='signer';if(!d&&!e)return b;const f=templateText(a),g=/refund|chargeback|repay|退款|(?:pay(?:ment|out)?|release|send|transfer|settle)\w*[^.\n]{0,40}to the (?:buyer|order|customer)/i['test'](f);if(!g)return b;const h=d?'allocator\x20row\x20'+d['track']+'/'+(d['recipient_key']??'?'):'allocator.recipient=\x27signer\x27';return b['push']({'rule_id':'R-SIGNER-02','severity':'high','title':'Refund\x20leg\x20pays\x20Recipient::Signer\x20—\x20the\x20keeper,\x20not\x20the\x20buyer\x20('+h+')','detail':'`Recipient::Signer`\x20resolves\x20to\x20`tx_context::sender(ctx)`\x20(allocation.move:386-388),\x20i.e.\x20whoever\x20signed\x20the\x20transaction\x20that\x20triggered\x20'+'`alloc`.\x20Time-driven\x20refunds\x20are\x20keeper-triggered\x20by\x20construction,\x20so\x20this\x20leg\x20pays\x20the\x20KEEPER,\x20and\x20because\x20`alloc()`\x20records\x20no\x20'+'consumed\x20flag\x20for\x20the\x20recipient,\x20first-come-first-served.\x20Only\x20`Recipient::GuardIdentifier`\x20(resolved\x20through\x20the\x20Guard\x20submission,\x20'+'allocation.move:376-381)\x20or\x20an\x20explicit\x20`Entity`\x20is\x20safe\x20for\x20a\x20refund.','suggestion':'Replace\x20the\x20Signer\x20refund\x20row\x20with\x20a\x20`{GuardIdentifier:\x200}`\x20row\x20(the\x20submission\x20for\x20a\x20Service-created\x20Allocation\x20is\x20pinned\x20to\x20the\x20paying\x20'+'Order,\x20so\x20only\x20`order.owner`\x20can\x20receive\x20it)\x20and\x20bind\x20the\x20Guard\x20to\x20`order.owner`\x20+\x20`progress.current\x20==\x20<refund\x20node>`.'}),b;}function orderAnchorDeclarationChecks(a){const b=templateText(a),c=a['allocator']['refund_track']==='order_anchored'||/order[\s-]anchored|order anchor|refund recipient is the order|anchor row|guardidentifier\s*\(\s*0\s*\)|for_object|退款接收方为订单/i['test'](b);if(!c)return[];const d=(a['allocator']['rows']??[])['some'](g=>g['recipient']==='guard_identifier'||g['recipient']==='guard_identifier_to_order'),e=a['guards']['some'](h=>h['template_id']==='pattern.allocator_order_anchor');if(d||e)return[];const f=a['allocator']['recipient']??'?';return[{'rule_id':'R-RECIPIENT-02','severity':'high','title':'Order-anchored\x20refund\x20recipient\x20is\x20asserted\x20in\x20prose\x20but\x20declared\x20nowhere\x20machine-checkable','detail':'The\x20template\x20claims\x20an\x20order-anchored\x20escrow\x20/\x20refund\x20recipient\x20while\x20its\x20machine-readable\x20allocator\x20says\x20recipient=\x27'+f+'\x27\x20'+'with\x20no\x20`guard_identifier`\x20row\x20and\x20no\x20`pattern.allocator_order_anchor`\x20Guard\x20reference.\x20Two\x20on-chain\x20facts\x20make\x20the\x20claim\x20as\x20written\x20'+'unbuildable:\x20(1)\x20`Recipient`\x20has\x20only\x20`GuardIdentifier(u8)`\x20/\x20`Entity(address)`\x20/\x20`Signer`\x20(allocation.move:100-104)\x20—\x20there\x20is\x20NO\x20'+'`Order`\x20variant,\x20so\x20\x27the\x20refund\x20recipient\x20is\x20the\x20order\x20object\x27\x20can\x20only\x20be\x20written\x20as\x20a\x20`GuardIdentifier`\x20row;\x20(2)\x20recipients\x20that\x20are\x20'+'all\x20fixed\x20`Entity`\x20rows\x20resolve\x20without\x20the\x20passport\x20submission\x20(allocation.move:383-388)\x20and\x20the\x20Allocation\x20never\x20enters\x20the\x20Guard\x20'+'context,\x20so\x20the\x20Guard\x20has\x20no\x20order\x20to\x20bind\x20at\x20all\x20—\x20the\x20CR-01\x20drain\x20shape.\x20A\x20build\x20agent\x20reading\x20the\x20prose\x20instead\x20of\x20the\x20schema\x20will\x20'+'emit\x20an\x20Entity\x20refund\x20leg\x20to\x20the\x20merchant,\x20or\x20a\x20Signer\x20leg\x20to\x20the\x20keeper.','suggestion':'Declare\x20the\x20anchor\x20machine-checkably:\x20one\x20`{\x20recipient:\x20\x27guard_identifier\x27,\x20recipient_key:\x20\x270\x27,\x20mode:\x20\x27rate\x27,\x20value:\x200\x20}`\x20row\x20(the\x20'+'pattern.allocator_order_anchor\x20convention)\x20plus\x20`refund_track:\x20\x27order_anchored\x27`,\x20and\x20reference\x20`pattern.allocator_order_anchor`\x20in\x20the\x20'+'guard\x20set\x20with\x20the\x20`logic_equal[order.service,\x20<this\x20service>]`\x20binding\x20stated\x20in\x20its\x20purpose.'}];}const EDGE_DEPENDENCY_REGEX=/\b(?:incoming|outgoing|arb_refund)\s+edge\b|\bstop[\s-]node\b|\bedges?\b|\bpairs?\b|\bforwards?\b|one pair|two pairs/i;function topologyChecks(a){const b=[],c=templateText(a);EDGE_DEPENDENCY_REGEX['test'](c)&&b['push']({'rule_id':'R-TOPO-01','severity':'high','title':'machine_shape\x20ships\x20nodes\x20only\x20—\x20no\x20Pair/forward\x20list,\x20so\x20stop-node\x20fund-exit\x20coverage\x20is\x20unauditable','detail':'This\x20template\x27s\x20correctness\x20depends\x20on\x20Machine\x20edges\x20(its\x20own\x20notes\x20reason\x20about\x20incoming/outgoing\x20edges,\x20pairs\x20and\x20stop-node\x20'+'fund-exit\x20coverage),\x20but\x20`machine_shape`\x20carries\x20NO\x20edges:\x20an\x20edge\x20on\x20chain\x20is\x20`Node[target].pairs\x20=\x20{\x20prev_node,\x20threshold,\x20'+'forwards[]\x20}`,\x20which\x20this\x20schema\x20cannot\x20express.\x20The\x20scanner\x20therefore\x20has\x20to\x20invent\x20a\x20linear\x20chain,\x20and\x20the\x20mandatory\x20'+'stop-node\x20walk\x20(R-M5-03\x20/\x20R-M5-09:\x20every\x20rest\x20state\x20needs\x20a\x20defined\x20withdrawal\x20AND\x20refund\x20rule,\x20satisfiable\x20in\x20both\x20directions)\x20'+'cannot\x20be\x20performed\x20—\x20an\x20uncovered\x20stop\x20node\x20strands\x20escrow\x20permanently\x20once\x20Machine\x20+\x20Allocator\x20are\x20frozen\x20at\x20publish.','suggestion':'Either\x20state\x20the\x20edges\x20explicitly\x20in\x20build_notes\x20as\x20`prev\x20─forward(op,w)→\x20next`\x20with\x20the\x20Pair\x20grouping,\x20or\x20declare\x20a\x20machine-readable\x20'+'edge\x20list\x20so\x20the\x20scanner\x20can\x20audit\x20stop-node\x20coverage\x20and\x20prev_node\x20uniqueness\x20instead\x20of\x20guessing.'});const d=a['machine_shape']['map'](i=>i['name']);if(d['length']===0x0)return b;const e=d['filter'](i=>BRANCH_STATE_REGEX['test'](i));if(e['length']===0x0)return b;const f=d[0x0],g=!BRANCH_STATE_REGEX['test'](d[0x1]),h=(g?0x1:0x0)+e['length'];if(h<=0x1)return b;return b['push']({'rule_id':'R-TOPO-02','severity':'high','title':'Node\x20\x27'+f+'\x27\x20needs\x20'+h+'\x20outgoing\x20rails\x20—\x20they\x20must\x20be\x20ONE\x20Pair\x20with\x20multiple\x20forwards','detail':'From\x20\x27'+f+'\x27\x20the\x20declared\x20node\x20set\x20requires\x20'+h+'\x20distinct\x20rails\x20'+('('+(g?'the\x20linear\x20rail\x20to\x20\x27'+d[0x1]+'\x27,\x20':''))+(e['map'](i=>'the\x20branch\x20to\x20\x27'+i+'\x27')['join'](',\x20')+').\x20On\x20chain\x20a\x20Machine\x20has\x20exactly\x20ONE\x20Pair\x20per\x20(node,\x20prev_node):\x20')+'`assert!(!vector::contains(&res,\x20&pair.prev_node),\x20E_DUPLICATE_NODE_PREV)`\x20(machine.move:168)\x20rejects\x20a\x20second\x20Pair\x20with\x20the\x20same\x20'+'prev_node.\x20Emitting\x20one\x20Pair\x20per\x20rail\x20ABORTS\x20at\x20publish\x20—\x20and\x20because\x20Machine\x20+\x20Guard\x20are\x20immutable\x20afterwards,\x20the\x20failure\x20surfaces\x20only\x20'+'after\x20the\x20whole\x20Service\x20is\x20configured.\x20Note\x20also\x20that\x20one\x20forward\x20cannot\x20satisfy\x20two\x20operators:\x20each\x20forward\x20contributes\x20its\x20weight\x20at\x20'+'most\x20once\x20(locked\x20by\x20its\x20first\x20operator),\x20so\x20a\x20dual-confirmation\x20step\x20needs\x20`threshold\x20=\x202`\x20with\x20two\x20DISTINCT\x20forwards.','suggestion':'Merge\x20all\x20'+h+'\x20rails\x20out\x20of\x20\x27'+f+'\x27\x20into\x20ONE\x20Pair\x20with\x20'+h+'\x20forwards;\x20raise\x20the\x20Pair\x20threshold\x20to\x20the\x20'+'number\x20of\x20DISTINCT\x20operators\x20that\x20must\x20act,\x20and\x20state\x20the\x20merged\x20Pair\x20explicitly\x20in\x20build_notes\x20so\x20a\x20builder\x20cannot\x20split\x20it.'}),b;}function compoundPayoutChecks(a){const b=templateText(a),c=a['allocator']['rows']??[],d=a['allocator']['refund_track']!==undefined||c['some'](f=>f['track']==='refund')||/refund|退款/i['test'](a['allocator']['description']);if(!d)return[];const e=a['guards']['some'](f=>f['host']==='arbitration')||a['trust_mechanisms']['some'](f=>/^R2\b/['test'](f))||/compensation[_ ]fund/i['test'](b);if(!e)return[];return[{'rule_id':'R-COMPOUND-01','severity':'high','title':'Dispute-reachable\x20refund-to-order\x20rail\x20AND\x20a\x20bound\x20Arbitration\x20—\x20the\x20same\x20order\x20can\x20be\x20paid\x20twice','detail':'This\x20template\x20funds\x20a\x20refund\x20to\x20the\x20buyer\x20from\x20the\x20order\x20escrow\x20AND\x20relies\x20on\x20the\x20compensation\x20fund\x20via\x20Arbitration.\x20Those\x20are\x20'+'INDEPENDENT\x20on-chain\x20channels:\x20the\x20compensation\x20payout\x20path\x20(service.move:471+)\x20pays\x20out\x20of\x20the\x20compensation\x20fund\x20while\x20the\x20refund\x20Allocator\x20'+'pays\x20out\x20of\x20the\x20escrow,\x20and\x20the\x20only\x20cross-channel\x20guard\x20is\x20`Order.claimed_by`\x20(order.move:94-97\x20the\x20already-claimed\x20guard),\x20which\x20'+'the\x20compensation\x20payout\x20path\x20sets\x20but\x20`alloc()`\x20never\x20reads.\x20So\x20an\x20arbitration\x20award\x20and\x20a\x20keeper-advanced\x20refund\x20rail\x20both\x20succeed\x20for\x20the\x20same\x20'+'order.\x20VERIFIED\x20LIVE\x20on\x20the\x20OTA\x20build:\x20a\x20guest\x20took\x20a\x20full\x20escrow\x20refund\x20AND\x20a\x203x-order\x20compensation\x20for\x20one\x20booking\x20—\x20the\x20merchant\x20'+'carried\x20both,\x20so\x20the\x20effective\x20payout\x20was\x20a\x20multiple\x20of\x20the\x20order\x20value.','suggestion':'Pick\x20ONE\x20buyer-remedy\x20channel\x20per\x20order\x20and\x20make\x20the\x20other\x20structurally\x20unreachable:\x20either\x20drop\x20the\x20order-anchored\x20refund\x20rail\x20in\x20'+'favour\x20of\x20the\x20compensation\x20payout,\x20or\x20state\x20that\x20arbitration\x20awards\x20are\x20recorded/capped\x20at\x20zero\x20when\x20the\x20refund\x20rail\x20has\x20already\x20paid\x20'+'(e.g.\x20the\x20ruling\x20target\x20is\x20a\x20non-monetary\x20remedy\x20such\x20as\x20a\x20Reputation\x20mark).\x20Do\x20not\x20leave\x20both\x20rails\x20funded\x20and\x20dispute-reachable.'}];}const BRANCH_STATE_REGEX=/(cancel|return|withdraw|exit|expired)/i;function syntheticMachine(a){const b=a['machine_shape']['map'](e=>({'name':e['name'],'description':e['role'],'operator':e['operator']})),c=[],d=(e,f)=>[{'name':e,'weight':0x1,'named_operator':f==='order_payer'?'':'order_holder'}];b['length']>0x0&&c['push']({'prev_node':'','next_node':b[0x0]['name'],'threshold':0x1,'forwards':d('enter_'+b[0x0]['name'],b[0x0]['operator'])});for(let e=0x0;e<b['length']-0x1;e++){const f=b[e]['name'],g=b[e+0x1];if(BRANCH_STATE_REGEX['test'](g['name']))continue;c['push']({'prev_node':f,'next_node':g['name'],'threshold':0x1,'forwards':d(f+'_to_'+g['name'],g['operator'])});}if(b['length']>0x0)for(const h of b){BRANCH_STATE_REGEX['test'](h['name'])&&c['push']({'prev_node':b[0x0]['name'],'next_node':h['name'],'threshold':0x1,'forwards':d('to_'+h['name'],h['operator'])});}return{'nodes':b,'pairs':c};}function singleNodeGraph(a){return{'network':ENTRYPOINT['Testnet'],'seed':a['id'],'builtAt':Date['now'](),'nodes':new Map([[a['id'],a]]),'edges':[],'out':new Map(),'inc':new Map(),'gaps':[],'truncations':[],'rpcReport':{'batches':0x0,'byChannel':{'objects':0x0,'keyedFields':0x0,'tables':0x0,'events':0x0},'dedupHits':0x0},'budgetExhausted':{}};}function analyzerFindings(a){const b=makeProposalNode('machine',syntheticMachine(a)),c=makeProposalNode('allocation',{}),d=[];for(const e of[b,c]){const g=singleNodeGraph(e),h=buildViewport(g,g['seed'],'neutral');for(const i of runNodeAnalyzers(h,[machineRuleNodeAnalyzer,allocationRuleNodeAnalyzer])){d['push'](i);}}return d;}const SEVERITY_ORDER={'low':0x0,'medium':0x1,'high':0x2,'critical':0x3};export function scanTemplate(a){const b=[...staticChecks(a),...guardRefChecks(a),...fundAnchorChecks(a),...periodicReleaseChecks(a),...timeWindowAnchorChecks(a),...signerRefundChecks(a),...orderAnchorDeclarationChecks(a),...topologyChecks(a),...compoundPayoutChecks(a)];for(const e of analyzerFindings(a)){const g=e['severity']==='info'?'low':e['severity'];b['push']({'rule_id':e['ruleId'],'severity':g,'title':e['title'],'detail':e['detail'],'suggestion':e['suggestion']});}b['sort']((h,i)=>SEVERITY_ORDER[i['severity']]-SEVERITY_ORDER[h['severity']]);const c=b['length']>0x0?b[0x0]['severity']:'low',d=b['filter'](h=>h['severity']==='critical')['map'](h=>''+(h['rule_id']?h['rule_id']+':\x20':'')+h['title']);return{'template_id':a['id'],'risk_level':c,'passed':d['length']===0x0,'findings':b,'red_flags':d};}
|
|
1
|
+
import{ENTRYPOINT}from'@wowok/wowok';import{buildViewport,runNodeAnalyzers}from'../graph/onchain/index.js';import{makeProposalNode}from'../graph/onchain/proposal-graph.js';import{machineRuleNodeAnalyzer,allocationRuleNodeAnalyzer}from'./rule-node-analyzers.js';import{GUARD_TEMPLATES}from'./guard-templates.js';import{GUARD_DESIGN_PATTERNS}from'./guard-design-patterns.js';import{unannotatedBuyerActionNodes}from'./scenario-modes.js';import{DIRECT_SALES_INVARIANT,ENTITY_RECIPIENT_RULE_ID}from'./entity-recipient-guard.js';const PLATFORM_TAKE_KEY=/^(?:platform_(?:share|commission|take)_bps|platform_fee_rate_bps|commission_rate_bps|(?:base_)?commission_rate_bps|offsite_ads_rate_bps|service_fee_rate_bps|payment_fee_bps)$/,MERCHANT_OWN_PRICE_KEY=/^(?:merchant_service_fee_bps|contract_fee_(?:small|large)_usd|contract_fee_tier_boundary_usd|digital_product_fee_(?:bps|min_usd|max_usd)|arbitration_fee.*|escrow_.*|min_.*|max_.*)$/,MERCHANT_SHARE_KEY=/^(?:host|property|partner|institution|landlord|freelancer|creator|seller|instructor)_rate_bps$/;function directSalesEconomyChecks(a){const b=[],c=a['fee_params'],d=Object['keys'](c)['filter'](x=>PLATFORM_TAKE_KEY['test'](x)&&typeof c[x]==='number'&&c[x]!==0x0);d['length']>0x0&&b['push']({'rule_id':'R-ECON-01','severity':'critical','title':'Template\x20mandates\x20a\x20platform\x20commission\x20('+d['map'](x=>x+'='+c[x])['join'](',\x20')+')','detail':'WoWok\x20is\x20DIRECT\x20SALES:\x20the\x20protocol\x20never\x20extracts\x20and\x20a\x20merchant\x20pays\x20only\x20gas,\x20so\x20the\x20merchant-side\x20share\x20must\x20default\x20to\x20the\x20whole\x20sale.\x20A\x20non-zero\x20platform\x20take\x20is\x20(a)\x20an\x20extraction\x20the\x20platform\x20has\x20no\x20right\x20to,\x20and\x20(b)\x20an\x20UNALLOCATED\x20liability\x20—\x20no\x20template\x20declares\x20a\x20platform\x20address,\x20so\x20at\x20build\x20time\x20it\x20resolves\x20to\x20the\x20deploying\x20merchant\x20itself\x20(blank\x20→\x20Account.Instance(),\x20ts-sdk/packages/wowok/src/w/local/index.ts:89-91),\x20to\x20the\x20keeper\x20(Recipient::Signer\x20→\x20tx_context::sender,\x20allocation.move:531-533),\x20or\x20back\x20to\x20the\x20buyer\x20(Recipient::GuardIdentifier,\x20allocation.move:501-527).\x20None\x20of\x20those\x20is\x20revenue.','suggestion':'Set\x20'+d['join'](',\x20')+'\x20to\x200\x20and\x20give\x20the\x20merchant\x20the\x20whole\x20sale\x20(single\x20Rate\x2010000\x20leg).\x20If\x20the\x20merchant\x20IS\x20the\x20aggregator\x20and\x20genuinely\x20charges\x20a\x20fee,\x20declare\x20it\x20via\x20merchant_service_fee_bps\x20with\x20an\x20EXPLICIT\x20non-empty\x20recipient\x20Entity.'});const e=a['allocator']['description'],f=/(?:commission|take|platform|remainder|share)\s*(?:=|:)\s*order\s*total\s*-\s*(?:segment|sum)/i['test'](e),g=(a['allocator']['rows']??[])['some'](x=>x['mode']==='surplus')||a['allocator']['mode']==='surplus',h=g&&/(?:platform|commission|fee|take)[^.;]{0,120}\bsurplus\b|\bsurplus\b[^.;]{0,120}(?:platform|commission|fee|take)/i['test'](e);f&&b['push']({'rule_id':'R-ECON-02','severity':'critical','title':'Take\x20is\x20an\x20implicit\x20remainder\x20(not\x20computable\x20before\x20ordering)','detail':'The\x20allocator\x20describes\x20the\x20platform\x20share\x20as\x20\x22order\x20total\x20-\x20segment\x20sums\x22,\x20so\x20the\x20amount\x20taken\x20depends\x20on\x20the\x20segment\x20configuration\x20rather\x20than\x20a\x20declared\x20rate.\x20A\x20buyer\x20(or\x20their\x20AI)\x20cannot\x20compute\x20the\x20take\x20BEFORE\x20ordering,\x20which\x20defeats\x20pre-order\x20evaluation\x20—\x20and\x20an\x20unbounded\x20remainder\x20off\x20a\x20transit\x20pool\x20is\x20unbounded\x20extraction.','suggestion':'Pin\x20every\x20share\x20to\x20an\x20EXPLICIT\x20Rate\x20(or\x20an\x20Amount\x20derived\x20from\x20a\x20declared\x20rate).\x20A\x20supplier\x20fee\x20belongs\x20in\x20its\x20own\x20explicitly-priced\x20segment\x20order,\x20never\x20as\x20a\x20residual\x20share.'});h&&b['push']({'rule_id':'R-ECON-02','severity':'high','title':'Fee\x20appears\x20to\x20be\x20taken\x20by\x20a\x20Surplus\x20leg','detail':'A\x20Surplus\x20sharing\x20entry\x20allocates\x20the\x20WHOLE\x20remaining\x20balance\x20(allocation.move:427\x20withdraw_all\x20semantics),\x20so\x20it\x20cannot\x20express\x20\x22take\x2015%\x22:\x20it\x20doubles\x20as\x20draining\x20the\x20pool.','suggestion':'Use\x20Rate\x20(or\x20RateGross)\x20for\x20any\x20proportional\x20share.\x20Reserve\x20Surplus\x20for\x20an\x20explicitly-bounded\x20residual\x20whose\x20recipient\x20and\x20cap\x20are\x20stated.'});const j=/\{\s*(?:who|Entity|Signer|GuardIdentifier)\s*:/['test'](e)||/recipient\s*[:=]/i['test'](e),k=/^(?:merchant_service_fee_bps|digital_product_fee_bps|logistics_rate_bps|service_fee_rate_bps)$/,l=Object['keys'](c)['some'](x=>k['test'](x)&&typeof c[x]==='number'&&c[x]!==0x0);l&&!j&&d['length']===0x0&&b['push']({'rule_id':'R-ECON-03','severity':'high','title':'Fee-bearing\x20template\x20names\x20no\x20recipient\x20slot\x20for\x20the\x20non-merchant\x20share','detail':'fee_params\x20carry\x20fee-shaped\x20keys\x20but\x20the\x20allocator\x20names\x20no\x20recipient\x20for\x20them.\x20On-chain\x20each\x20Rate\x20lands\x20in\x20ITS\x20OWN\x20recipient\x20slot;\x20an\x20unnamed\x20one\x20resolves\x20to\x20the\x20deploying\x20account\x20(ts-sdk/packages/wowok/src/w/local/index.ts:89-91),\x20to\x20the\x20keeper\x20(allocation.move:531-533),\x20or\x20back\x20to\x20the\x20buyer.\x20The\x20share\x20is\x20then\x20an\x20unallocated\x20liability\x20rather\x20than\x20revenue.','suggestion':'State\x20the\x20recipient\x20per\x20share\x20in\x20the\x20allocator\x20description\x20and\x20bind\x20it\x20to\x20an\x20explicit\x20NON-EMPTY\x20Entity\x20the\x20buyer\x20can\x20see\x20before\x20ordering.\x20Never\x20leave\x20it\x20blank.'});const m=/(?:layer-?1|service-?level|pool)[^.]*settles? the full amount|full amount to the (?:platform|organizer) pool/i['test'](e);m&&b['push']({'rule_id':'R-ECON-04','severity':'medium','title':'Escrow\x20transits\x20an\x20organizer\x20pool\x20before\x20reaching\x20the\x20merchant','detail':'The\x20full\x20order\x20amount\x20settles\x20into\x20a\x20platform/organizer\x20pool\x20first\x20and\x20is\x20then\x20redistributed.\x20That\x20contradicts\x20the\x20direct-sales\x20promise\x20(\x22money\x20moves\x20only\x20between\x20the\x20two\x20parties\x22)\x20and\x20makes\x20the\x20organizer\x20a\x20waypoint\x20on\x20every\x20payout,\x20including\x20every\x20refund.','suggestion':'Release\x20supplier\x20segments\x20directly\x20from\x20the\x20order\x27s\x20own\x20Allocation,\x20and\x20make\x20the\x20organizer\x20a\x20named\x20party\x20rather\x20than\x20a\x20transit\x20node.'});const n=Object['keys'](c)['find'](x=>/^attributed_.*_bps$/['test'](x)&&typeof c[x]==='number'),o=Object['keys'](c)['find'](x=>/^(?:base_)?commission_rate_bps$/['test'](x)&&typeof c[x]==='number');n&&o&&c[n]>c[o]&&b['push']({'rule_id':'R-ECON-05','severity':'medium','title':'Attribution-priced\x20take:\x20a\x20cheaper\x20acquisition\x20channel\x20is\x20charged\x20MORE','detail':n+'='+c[n]+'\x20exceeds\x20'+o+'='+c[o]+'.\x20Charging\x20more\x20for\x20attributed\x20orders\x20means\x20the\x20merchant\x27s\x20cheap\x20channels\x20(KOC,\x20social,\x20repeat\x20buyers)\x20are\x20penalised\x20—\x20the\x20opposite\x20of\x20what\x20direct\x20sales\x20should\x20reward.','suggestion':'Price\x20every\x20channel\x20identically.\x20Attribution\x20may\x20change\x20RANKING,\x20never\x20the\x20take.'});if(a['allocator']['mode']==='rate'){const x=Object['keys'](c)['filter'](A=>MERCHANT_SHARE_KEY['test'](A)&&typeof c[A]==='number'),y=Object['keys'](c)['filter'](A=>PLATFORM_TAKE_KEY['test'](A)&&typeof c[A]==='number'),z=[...x,...y];if(x['length']>0x0&&y['length']>0x0){const A=z['map'](D=>c[D])['filter'](D=>typeof D==='number'),B=A['reduce']((D,E)=>D+E,0x0),C=/surplus/i['test'](e);B!==0x2710&&!C&&b['push']({'rule_id':'R-ECON-06','severity':'critical','title':'Rate\x20shares\x20sum\x20to\x20'+B+',\x20not\x2010000','detail':'Declared\x20rate\x20shares\x20('+z['map']((D,E)=>D+'='+A[E])['join']('\x20+\x20')+')\x20total\x20'+B+'.\x20With\x20no\x20Surplus\x20recipient\x20the\x20remainder\x20is\x20not\x20protected:\x20the\x20chain\x20records\x20no\x20\x22already\x20triggered\x22\x20flag,\x20so\x20a\x20balance\x20left\x20behind\x20after\x20a\x20partial\x20split\x20can\x20be\x20claimed\x20REPEATEDLY\x20by\x20anyone\x20passing\x20the\x20same\x20Guard.\x20This\x20is\x20exactly\x20what\x20happens\x20when\x20a\x20platform\x20leg\x20is\x20zeroed\x20without\x20recomputing\x20the\x20merchant\x20leg.','suggestion':'Make\x20the\x20shares\x20sum\x20to\x20exactly\x2010000,\x20or\x20declare\x20an\x20explicit\x20Surplus\x20recipient\x20for\x20the\x20residual.'});}}const p=(a['allocator']['rows']??[])['map']((D,E)=>({'r':D,'i':E})),q=p['filter'](({r:D})=>D['recipient']==='entity'&&!(D['recipient_key']??'')['trim']());q['length']>0x0&&b['push']({'rule_id':ENTITY_RECIPIENT_RULE_ID,'severity':'critical','title':'Allocator\x20row(s)\x20'+q['map'](({i:D})=>'#'+D)['join'](',\x20')+'\x20name\x20no\x20Entity\x20recipient\x20—\x20the\x20share\x20silently\x20pays\x20the\x20deploying\x20merchant','detail':q['map'](({i:D})=>'rows['+D+']')['join'](',\x20')+'\x20declare\x20recipient=\x27entity\x27\x20with\x20no\x20recipient_key,\x20which\x20builds\x20as\x20'+'{\x20who:\x20{\x20Entity:\x20{\x20name_or_address:\x20\x22\x22\x20}\x20}\x20}.\x20That\x20is\x20NOT\x20a\x20no-op:\x20the\x20SDK\x20resolver\x20substitutes\x20the\x20DEFAULT\x20LOCAL\x20ACCOUNT\x20before\x20the\x20'+'address\x20reaches\x20Move,\x20so\x20the\x20order\x20escrow\x20pays\x20whoever\x20ran\x20the\x20deploy\x20—\x20the\x20\x27platform\x27\x20share\x20the\x20template\x20left\x20unnamed\x20becomes\x20the\x20merchant\x27s\x20'+('own\x20take.\x20'+DIRECT_SALES_INVARIANT),'suggestion':'Give\x20the\x20row\x20an\x20explicit\x20`recipient_key`\x20naming\x20the\x20party\x20(a\x20mark\x20name\x20or\x20a\x200x\x20address\x20the\x20buyer\x20can\x20see\x20BEFORE\x20ordering).\x20If\x20the\x20whole\x20sale\x20goes\x20'+'to\x20the\x20merchant,\x20do\x20not\x20declare\x20an\x20entity\x20row\x20at\x20all:\x20use\x20ONE\x20{\x20who:\x20{\x20GuardIdentifier:\x200\x20},\x20sharing:\x2010000,\x20mode:\x20\x22Rate\x22\x20}\x20leg.\x20The\x20scalar\x20'+'`allocator.recipient:\x20\x22entity\x22`\x20form\x20is\x20auditable\x20too:\x20it\x20must\x20carry\x20a\x20`recipient_key`\x20(or\x20a\x20`rows[]`\x20array)\x20when\x20no\x20rows\x20narrow\x20it.'});!a['allocator']['rows']&&a['allocator']['recipient']==='entity'&&!(a['allocator']['recipient_key']??'')['trim']()&&b['push']({'rule_id':ENTITY_RECIPIENT_RULE_ID,'severity':'critical','title':'Allocator\x20names\x20no\x20Entity\x20recipient\x20(scalar\x20form,\x20no\x20rows)\x20—\x20the\x20share\x20silently\x20pays\x20the\x20deploying\x20merchant','detail':'The\x20allocator\x20declares\x20scalar\x20recipient=\x27entity\x27\x20with\x20no\x20recipient_key\x20and\x20no\x20rows[],\x20which\x20builds\x20as\x20'+'{\x20who:\x20{\x20Entity:\x20{\x20name_or_address:\x20\x22\x22\x20}\x20}\x20}.\x20That\x20is\x20NOT\x20a\x20no-op:\x20the\x20SDK\x20resolver\x20substitutes\x20the\x20DEFAULT\x20LOCAL\x20ACCOUNT\x20before\x20the\x20'+'address\x20reaches\x20Move,\x20so\x20the\x20order\x20escrow\x20pays\x20whoever\x20ran\x20the\x20deploy\x20—\x20the\x20share\x20the\x20template\x20left\x20unnamed\x20becomes\x20the\x20merchant\x27s\x20'+('own\x20take.\x20'+DIRECT_SALES_INVARIANT),'suggestion':'Declare\x20the\x20destination\x20machine-checkably:\x20set\x20`recipient_key`\x20on\x20the\x20allocator\x20(a\x20mark\x20name\x20or\x20a\x200x\x20address\x20the\x20buyer\x20can\x20see\x20BEFORE\x20ordering),\x20'+'or\x20add\x20a\x20`rows[]`\x20array\x20carrying\x20the\x20on-chain\x20`who`\x20shape.\x20If\x20the\x20whole\x20sale\x20goes\x20to\x20the\x20merchant,\x20use\x20ONE\x20'+'{\x20recipient:\x20\x27guard_identifier\x27,\x20recipient_key:\x20\x270\x27\x20}\x20row\x20instead\x20of\x20an\x20entity\x20scalar.'});const s=p['filter'](({r:D})=>D['recipient']==='entity'&&/^0x0*$/i['test']((D['recipient_key']??'')['trim']()));s['length']>0x0&&b['push']({'rule_id':ENTITY_RECIPIENT_RULE_ID,'severity':'high','title':'Allocator\x20row(s)\x20'+s['map'](({i:D})=>'#'+D)['join'](',\x20')+'\x20name\x20the\x20zero\x20address\x20as\x20Entity\x20recipient','detail':s['map'](({i:D})=>'rows['+D+']')['join'](',\x20')+'\x20carry\x20recipient_key=\x270x0\x27\x20(or\x20an\x20all-zero\x20literal).\x20The\x20chain\x20does\x20NOT\x20reject\x20it:\x20'+'allocation.move:250-255\x20swallows\x20Recipient::Entity\x20in\x20a\x20(_)\x20catch-all\x20at\x20declaration\x20time,\x20and\x20allocation.move:451-453\x20/\x20:514\x20forward\x20the\x20raw\x20'+'address\x20straight\x20to\x20the\x20payout\x20constructor.\x20The\x20allocation\x20is\x20accepted\x20and\x20the\x20share\x20is\x20silently\x20transferred\x20to\x200x0\x20and\x20permanently\x20burned\x20—\x20'+'this\x20scan\x20is\x20the\x20only\x20defence.','suggestion':'Replace\x20the\x20zero\x20literal\x20with\x20the\x20real\x20recipient\x20address\x20(a\x20mark\x20name\x20or\x20a\x200x\x20address),\x20or\x20drop\x20the\x20row\x20if\x20the\x20share\x20is\x20not\x20owed.'});const u=D=>D['recipient']+':'+(D['recipient_key']??'')['trim']()['toLowerCase'](),v=new Set((a['allocator']['rows']??[])['filter'](D=>D['mode']==='rate')['map'](u)),w=p['filter'](({r:D})=>D['mode']==='surplus'&&v['has'](u(D)));return w['length']>0x0&&b['push']({'rule_id':'R-RECIPIENT-04','severity':'critical','title':'Surplus\x20row(s)\x20'+w['map'](({i:D})=>'#'+D)['join'](',\x20')+'\x20pay\x20a\x20recipient\x20a\x20Rate\x20leg\x20already\x20pays\x20—\x20the\x20remainder\x20swallows\x20an\x20undeclared\x20share','detail':w['map'](({i:D})=>'rows['+D+']')['join'](',\x20')+'\x20duplicate\x20a\x20Rate\x20leg\x27s\x20recipient.\x20The\x20chain\x20pays\x20every\x20Rate\x20leg\x20its\x20declared\x20basis\x20points\x20'+'and\x20then\x20pays\x20the\x20ENTIRE\x20remainder\x20to\x20the\x20Surplus\x20recipient,\x20so\x20this\x20party\x20quietly\x20receives\x20rate%\x20+\x20100%\x20of\x20the\x20residual\x20and\x20any\x20leg\x20the\x20'+'author\x20intended\x20but\x20omitted\x20(commission,\x20payment\x20fee,\x20platform\x20take)\x20is\x20never\x20created.\x20The\x20Rate-sum\x20rule\x20passes\x20because\x20the\x20sum\x20is\x20legal\x20—\x20'+'the\x20misroute\x20is\x20invisible\x20there,\x20and\x20order_allocators\x20freezes\x20permanently\x20at\x20publish.\x20Mainnet\x20precedent\x20(Booking\x20replica,\x202026-10-06):\x20the\x20'+'property\x20took\x20100%\x20(Rate\x208350\x20+\x20Surplus),\x20the\x2015%\x20commission\x20and\x201.5%\x20payment-fee\x20legs\x20never\x20existed,\x20and\x20the\x20published\x20Service\x20had\x20to\x20be\x20abandoned.','suggestion':'Point\x20the\x20Surplus\x20row\x20at\x20the\x20party\x20meant\x20to\x20absorb\x20the\x20remainder\x20(usually\x20the\x20merchant),\x20distinct\x20from\x20every\x20Rate\x20leg\x20—\x20or,\x20if\x20the\x20duplicated\x20'+'recipient\x20is\x20truly\x20intended\x20to\x20take\x20rate%\x20+\x20remainder,\x20collapse\x20the\x20two\x20rows\x20into\x20ONE\x20rate\x20row\x20so\x20the\x20declared\x20split\x20equals\x20the\x20actual\x20split.\x20'+'Every\x20intended\x20payee\x20must\x20be\x20its\x20own\x20explicit\x20row.'}),b;}const DISPUTE_NODE_REGEX=/(^|_)(disputed?|arbitration|arb)(_|$)|^(refund|refunded|deposit_refunded|deposit_deducted|cancel|cancelled)$/i,KNOWN_GUARD_REF_IDS=new Set([...GUARD_DESIGN_PATTERNS['map'](a=>a['id']),...GUARD_TEMPLATES['map'](a=>a['id'])]);function guardRefChecks(a){const b=[];for(const c of a['guards']){if(!/^(pattern\.[a-z0-9_]+|tpl_[a-z0-9_]+)$/['test'](c['template_id'])){b['push']({'rule_id':'R-REF-01','severity':'high','title':'Guard\x20reference\x20\x27'+c['template_id']+'\x27\x20is\x20not\x20a\x20resolvable\x20id','detail':'Guard\x20references\x20must\x20name\x20a\x20guard\x20design\x20pattern\x20(\x27pattern.*\x27,\x20'+GUARD_DESIGN_PATTERNS['length']+'\x20available)\x20or\x20a\x20guard\x20template\x20(\x27tpl_*\x27,\x20'+GUARD_TEMPLATES['length']+'\x20available).\x20Bare\x20prose\x20ids\x20dangle:\x20no\x20builder\x20can\x20resolve\x20them,\x20so\x20the\x20AI\x20invents\x20guard\x20logic\x20at\x20build\x20time.','suggestion':'Replace\x20with\x20the\x20semantically\x20nearest\x20pattern.*/tpl_*\x20id\x20(compose\x20multi-condition\x20logic\x20in\x20the\x20purpose\x20text).'});continue;}!KNOWN_GUARD_REF_IDS['has'](c['template_id'])&&b['push']({'rule_id':'R-REF-02','severity':'high','title':'Guard\x20reference\x20\x27'+c['template_id']+'\x27\x20does\x20not\x20exist\x20in\x20any\x20guard\x20catalog','detail':'The\x20id\x20is\x20namespaced\x20correctly\x20but\x20matches\x20no\x20guard\x20design\x20pattern\x20nor\x20guard\x20template\x20—\x20a\x20dangling\x20reference\x20the\x20AI\x20cannot\x20resolve.','suggestion':'Fix\x20the\x20id\x20(typo)\x20or\x20point\x20it\x20at\x20the\x20nearest\x20existing\x20pattern.*/tpl_*\x20entry.'});}return b;}function staticChecks(a){const b=[];for(const h of a['machine_shape']){DISPUTE_NODE_REGEX['test'](h['name'])&&b['push']({'rule_id':'R-M1-11','severity':'critical','title':'Machine\x20node\x20\x27'+h['name']+'\x27\x20models\x20dispute/refund\x20flow','detail':'Disputes\x20are\x20independent\x20of\x20the\x20Machine\x20workflow;\x20refunds\x20route\x20via\x20Allocators\x20triggered\x20by\x20business\x20states.','suggestion':'Remove\x20the\x20node;\x20route\x20refunds\x20via\x20Allocator\x20states\x20(closed_cancel/returned)\x20and\x20disputes\x20via\x20the\x20Arbitration\x20object.'});}const c=new Map();for(const j of a['guards']){if(/time_lock|order_holder|progress_state/['test'](j['template_id'])&&!/order\.service|project bind|service binding/i['test'](j['purpose'])){const k=c['get'](j['template_id'])??[];k['push'](j['key']??'(no\x20key)'),c['set'](j['template_id'],k);}}for(const [l,m]of c){b['push']({'rule_id':'R-C3-05','severity':'medium','title':'Guard\x20\x27'+l+'\x27\x20consumes\x20a\x20submitted\x20Order\x20without\x20project\x20binding\x20('+m['length']+'x:\x20'+m['join'](',\x20')+')','detail':'Passport\x20submissions\x20are\x20caller-built;\x20without\x20logic_equal[order.service,\x20<service>]\x20a\x20stale\x20order\x20from\x20another\x20project\x20can\x20satisfy\x20the\x20guard\x20for\x20a\x20fresh\x20order.','suggestion':'State\x20the\x20project\x20binding\x20in\x20the\x20guard\x20purpose\x20AND\x20include\x20it\x20in\x20the\x20guard\x20root\x20at\x20build\x20time.'});}a['machine_shape']['length']===0x0&&b['push']({'rule_id':'R-M1-01','severity':'critical','title':'machine_shape\x20is\x20empty','detail':'No\x20entry\x20node\x20—\x20the\x20Machine\x20cannot\x20start.','suggestion':'Add\x20at\x20least\x20one\x20entry\x20node\x20representing\x20the\x20escrowed\x20state.'});const d=a['guards']['some'](n=>/refund|cancel/i['test'](n['template_id'])||/refund|cancel/i['test'](n['purpose']))||/refund/i['test'](a['allocator']['description']);!d&&b['push']({'rule_id':'R1','severity':'high','title':'No\x20refund\x20path\x20detected','detail':'No\x20refund/cancel\x20guard\x20and\x20no\x20refund\x20route\x20in\x20the\x20allocator\x20description.','suggestion':'Add\x20a\x20refund/cancel\x20guard\x20or\x20an\x20allocator\x20refund\x20route\x20before\x20publishing.'});const e=a['guards']['some'](n=>n['host']==='arbitration')||a['trust_mechanisms']['some'](n=>n['startsWith']('R2'));!e&&b['push']({'rule_id':'R2','severity':'high','title':'No\x20independent\x20Arbitration\x20reference\x20detected','detail':'The\x20template\x20carries\x20no\x20arbitration-hosted\x20guard\x20and\x20no\x20R2\x20trust\x20mechanism.','suggestion':'Mount\x20an\x20independent\x20Arbitration\x20object\x20with\x20its\x20own\x20Permission.'});a['keeper_dependencies']['length']===0x0&&b['push']({'rule_id':'R9','severity':'medium','title':'No\x20keeper\x20dependencies\x20declared','detail':'Time-driven\x20transitions\x20only\x20ALLOW\x20advancement\x20—\x20someone\x20must\x20run\x20the\x20keepers.','suggestion':'Declare\x20the\x20keeper\x20operations\x20(timeouts,\x20window\x20expiries,\x20settlement\x20triggers).'});b['push'](...directSalesEconomyChecks(a));const f=unannotatedBuyerActionNodes(a['machine_shape']);return f['length']>0x0&&b['push']({'rule_id':'R-OPER-01','severity':'medium','title':'Buyer-side\x20node(s)\x20without\x20an\x20operator\x20annotation','detail':'Node(s)\x20'+f['map'](o=>'\x27'+o+'\x27')['join'](',\x20')+'\x20look\x20like\x20order-payer\x20actions\x20but\x20carry\x20no\x20operator\x20field.\x20At\x20build\x20time\x20they\x20default\x20to\x20a\x20merchant\x20permission\x20slot,\x20and\x20the\x20order\x20payer\x20cannot\x20advance\x20them\x20(E_PERMISSION_DENIED).','suggestion':'Annotate\x20true\x20buyer\x20actions\x20with\x20operator:\x20\x22order_payer\x22\x20(an\x20EMPTY\x20namedOperator\x20—\x20the\x20on-chain\x20check\x20resolves\x20it\x20to\x20the\x20order\x20payer);\x20rename\x20merchant-side\x20states\x20(e.g.\x20\x27cancelled\x27\x20->\x20\x27merchant_cancelled\x27)\x20when\x20the\x20actor\x20is\x20NOT\x20the\x20buyer.'}),b;}const PERIOD_COUNT_KEY_REGEX=/^(monthly_allocators|term_count|session_count|segment_count|periods|cycles|installments)$/;function poolPeriodCount(a){for(const [b,c]of Object['entries'](a['fee_params'])){if(PERIOD_COUNT_KEY_REGEX['test'](b)&&typeof c==='number'&&c>=0x2)return c;}return undefined;}function periodicReleaseChecks(a){const b=poolPeriodCount(a);if(b===undefined)return[];const c=[a['allocator']['description'],...a['build_notes'],...a['trust_mechanisms'],...a['guards']['map'](f=>f['purpose'])]['join']('\x20\x0a\x20'),d=[];/surplus/i['test'](c)&&!/no surplus|surplus[^.\n]*(disabled|forbidden|disallowed)|amount mode only|single surplus/i['test'](c)&&d['push']({'rule_id':'R-PER-01','severity':'high','title':'Multi-period\x20pool\x20('+b+'\x20periods)\x20declares\x20Surplus\x20without\x20a\x20terminal-only\x20qualifier','detail':'A\x20Surplus\x20allocator\x20entry\x20runs\x20balance::withdraw_all\x20(allocation.move:288-298).\x20In\x20a\x20pool\x20pre-funded\x20for\x20'+b+'\x20periods\x20it\x20drains\x20every\x20future\x20release,\x20not\x20just\x20the\x20remainder.','suggestion':'Release\x20each\x20period\x20with\x20Amount;\x20if\x20the\x20pool\x20remainder\x20settles\x20in\x20one\x20entry,\x20declare\x20it\x20explicitly\x20as\x20the\x20SINGLE\x20terminal\x20Surplus\x20at\x20the\x20settlement\x20node,\x20or\x20disable\x20Surplus\x20outright.'});const e=/per[- ](month|period|term|session|cycle|segment)|one per (rent )?period|release-sequence lock/i['test'](c);return!e&&d['push']({'rule_id':'R-PER-02','severity':'high','title':'Multi-period\x20pool\x20('+b+'\x20periods)\x20declares\x20no\x20per-period\x20release\x20Guard','detail':'alloc()\x20has\x20no\x20consumed/nonce\x20flag\x20(allocation.move:204-321):\x20two\x20releases\x20bound\x20to\x20the\x20SAME\x20Guard\x20can\x20both\x20fire\x20the\x20same\x20day\x20and\x20drain\x20the\x20pool.\x20The\x20cadence\x20gate\x20must\x20be\x20one\x20Guard\x20per\x20period.','suggestion':'Declare\x20one\x20release\x20Guard\x20per\x20period\x20(per-month/per-term\x20time-lock\x20Guards,\x20each\x20keyed\x20to\x20its\x20own\x20period\x20window)\x20in\x20the\x20guard\x20set.'}),!/threshold[^.\n]*(one|single|per[- ]|month|period|term|session|=\s*0\b|\b0\b|must be 0)/i['test'](c)&&d['push']({'rule_id':'R-PER-03','severity':'medium','title':'Multi-period\x20pool\x20('+b+'\x20periods)\x20does\x20not\x20pin\x20threshold\x20to\x20one\x20period','detail':'alloc()\x20asserts\x20balance\x20>=\x20threshold\x20before\x20EVERY\x20release\x20(allocation.move:206).\x20A\x20threshold\x20sized\x20to\x20the\x20total\x20pool\x20passes\x20the\x20first\x20release\x20and\x20then\x20locks\x20all\x20remaining\x20periods.','suggestion':'State\x20in\x20the\x20allocator\x20description\x20or\x20build\x20notes\x20that\x20threshold\x20=\x20one\x20period\x27s\x20release\x20amount\x20(never\x20the\x20pre-funded\x20total).'}),d;}const MIN_PRICE_KEY_REGEX=/^(?:min_[a-z0-9_]*?(?:price|amount|usd|value)|price_floor)$/,FLOOR_TEXT_REGEX=/fixed (?:fee|charge)[^.\n]*(?:<|less than|below) [^.\n]*(?:lowest|minimum|min)|minimum (?:sku|order|item|unit) (?:price|amount)|(?:below|under|<=)\s*the\s+smallest[^.\n]*(?:order|escrow|booking|price)/i,FIXED_FEE_TEXT_REGEX=/\bamount mode\b|fixed (?:fee|fulfillment|fulfilment|per[- ]order) (?:fee|charge)|\bAmount\b[^.\n]*(?:fee|charge)/i;function fundAnchorChecks(a){const b=[],c=[a['allocator']['description'],...a['build_notes'],...a['trust_mechanisms'],...a['guards']['map'](h=>h['template_id']+'\x20'+h['purpose'])]['join']('\x20\x0a\x20'),d=a['allocator']['refund_track']==='order_anchored'||/allocator_order_anchor/['test'](c)||/guardidentifier\(0\)|order[- ]anchored|for_object/i['test'](c);!d&&b['push']({'rule_id':'R-ANCHOR-01','severity':'critical','title':'Allocator\x20has\x20no\x20order\x20anchor\x20—\x20its\x20Guard\x20cannot\x20bind\x20the\x20paying\x20Order','detail':'Every\x20recipient\x20of\x20this\x20allocator\x20is\x20a\x20fixed\x20party\x20(recipient=\x27'+a['allocator']['recipient']+'\x27,\x20no\x20GuardIdentifier\x20row),\x20so\x20nothing\x20in\x20the\x20Guard\x27s\x20verification\x20context\x20names\x20the\x20Order\x20being\x20settled:\x20Recipient::Entity/Signer\x20are\x20resolved\x20without\x20any\x20submission\x20check\x20(allocation.move:451-456)\x20and\x20the\x20Allocation\x20itself\x20never\x20enters\x20the\x20Guard\x20context.\x20Testnet\x20proved\x20the\x20consequence:\x20a\x20passport\x20built\x20from\x20an\x20ALREADY-SETTLED\x20order\x20of\x20the\x20same\x20Service\x20drained\x20a\x20different\x20order\x27s\x20escrow\x20(CR-01).\x20The\x20identifier-255\x20once-slot\x20does\x20not\x20help\x20—\x20it\x20is\x20stored\x20per\x20Allocation,\x20so\x20a\x20fresh\x20pool\x20has\x20no\x20record.','suggestion':'Adopt\x20pattern.allocator_order_anchor:\x20add\x20one\x20{GuardIdentifier:\x200}\x20row\x20with\x20Rate\x200\x20(pays\x20nothing,\x20makes\x20the\x20submitted\x20Order\x20the\x20Guard\x27s\x20binding\x20target),\x20declare\x20refund_track:\x20\x22order_anchored\x22,\x20and\x20pin\x20the\x20Guard\x20expression\x20to\x20that\x20identifier\x20plus\x20logic_equal[order.service,\x20<this\x20service>].'});const e=a['allocator']['mode']==='amount',f=e||FIXED_FEE_TEXT_REGEX['test'](c),g=Object['keys'](a['fee_params'])['some'](h=>MIN_PRICE_KEY_REGEX['test'](h))||FLOOR_TEXT_REGEX['test'](c);return f&&!g&&b['push']({'rule_id':'R-FIXFEE-01','severity':e?'critical':'high','title':'Fixed\x20Amount\x20fee\x20with\x20no\x20minimum\x20order\x20value\x20—\x20sub-fee\x20orders\x20deadlock\x20permanently','detail':'alloc()\x20asserts\x20balance\x20>=\x20fix\x20before\x20distributing\x20(allocation.move:390):\x20an\x20order\x20escrowed\x20BELOW\x20the\x20fixed\x20fee\x20can\x20never\x20settle,\x20and\x20the\x20terminal\x20nodes\x20(completed/closed_cancel)\x20leave\x20no\x20refund\x20path\x20for\x20it,\x20so\x20buyer\x20funds\x20and\x20the\x20order\x20strand\x20forever\x20(testnet\x20CR-02,\x20reproduced\x20on\x20a\x200.001\x20WOW\x20SKU\x20against\x20a\x200.15\x20WOW\x20fee).','suggestion':'Declare\x20a\x20minimum\x20listing/order\x20value\x20above\x20every\x20fixed\x20leg\x20in\x20fee_params\x20(e.g.\x20min_sku_price)\x20and\x20state\x20it\x20in\x20the\x20allocator\x20description,\x20or\x20model\x20the\x20per-order\x20fee\x20as\x20Rate/RateGross\x20instead\x20of\x20a\x20fixed\x20Amount.'}),a['allocator']['once_per_order']===!![]&&!/per[- ]allocation|per[- ]pool|not cross[- ]order|within (a|the) (pool|allocation)/i['test'](c)&&b['push']({'rule_id':'R-ONCE-SCOPE-01','severity':'medium','title':'once_per_order\x20claim\x20does\x20not\x20state\x20its\x20per-Allocation\x20scope','detail':'The\x20identifier-255\x20once-slot\x20is\x20keyed\x20(guard,\x20allocator,\x20submission)\x20ON\x20ONE\x20Allocation,\x20so\x20replay\x20immunity\x20holds\x20within\x20a\x20single\x20pool\x20only;\x20a\x20second\x20Allocation\x20of\x20the\x20same\x20Service\x20starts\x20with\x20no\x20record.\x20Presenting\x20ONCE\x20as\x20general\x20idempotency\x20is\x20what\x20let\x20testnet\x20CR-01\x20read\x20as\x20\x27already\x20protected\x27.','suggestion':'Say\x20explicitly\x20that\x20255\x20protects\x20one\x20pool,\x20and\x20pair\x20it\x20with\x20the\x20order\x20anchor\x20(R-ANCHOR-01)\x20for\x20cross-order\x20safety.'}),b;}function templateText(a,b=[]){return[a['allocator']['description'],...a['build_notes'],...a['trust_mechanisms'],...a['guards']['map'](c=>c['template_id']+'\x20'+c['purpose']),...a['machine_shape']['map'](c=>c['name']+'\x20'+c['role']),...Object['entries'](a['time_anchors']??{})['map'](([c,d])=>c+'\x20'+d),...b]['join']('\x20\x0a\x20');}const STAY_DATE_REGEX=/check[\s-]?in|check[\s-]?out|departure\s+date|arrival\s+date|booking\s+date|checkin|checkout|stay\s+date|stay_nights|\bstay\s+nights?\b|\bper\s+night\b|入住|退房|离店|到店日/i,CHAIN_CLOCK_REGEX=/order\.time|progress\.current_time|\border\s+time\b|witness/i,REPOSITORY_DATE_SOURCE_REGEX=/(?:write|writes|written|storing|store|stores|persist|persisted|record|records|read|reads)\b[^.\n]{0,90}repositor|repositor\w*\b[^.\n]{0,90}(?:stay|check[\s-]?in|check[\s-]?out|departure|arrival|date)/i;function timeWindowAnchorChecks(a){const b=templateText(a);if(!STAY_DATE_REGEX['test'](b))return[];if(CHAIN_CLOCK_REGEX['test'](b)||REPOSITORY_DATE_SOURCE_REGEX['test'](b))return[];const c=b['match'](new RegExp(STAY_DATE_REGEX['source'],'gi'))??[],d=/\d+\s*[-–]\s*\d+\s*h(?:ours?|rs?)?\s*(?:adjustable|tunable|configurable)|\badjustable\b|\btunable\b/i['test'](b);return[{'rule_id':'R-WIN-ANCHOR-01','severity':'high','title':'Per-order\x20time\x20window(s)\x20anchored\x20to\x20a\x20stay\x20date\x20that\x20does\x20not\x20exist\x20on\x20chain\x20('+Array['from'](new Set(c))['slice'](0x0,0x5)['join'](',\x20')+')','detail':'The\x20template\x27s\x20windows\x20are\x20relative\x20to\x20a\x20check-in\x20/\x20check-out\x20/\x20departure\x20/\x20night\x20date.\x20No\x20such\x20field\x20exists\x20on\x20chain:\x20'+'`Order.items`\x20is\x20`vector<SaleItem>`\x20with\x20`SaleItem\x20{\x20item,\x20price,\x20quantity,\x20wip_hash\x20}`\x20(order.move:28-33)\x20and\x20the\x20purchasable\x20'+'`Sale\x20{\x20name,\x20price,\x20stock,\x20suspension,\x20wip,\x20wip_hash\x20}`\x20(service.move:100-107)\x20carries\x20no\x20schedule;\x20the\x20only\x20per-order\x20clock\x20is\x20'+'`Order.time`\x20(order.move:74),\x20the\x20CREATION\x20timestamp.\x20`Progress.current_time`\x20(progress.move:85)\x20is\x20overwritten\x20on\x20every\x20forward\x20'+'(progress.move:458)\x20and\x20`Progress.history`\x20records\x20node\x20visits,\x20so\x20neither\x20is\x20a\x20business\x20date.\x20A\x20window\x20declared\x20relative\x20to\x20the\x20'+'stay\x20calendar\x20is\x20therefore\x20UNREACHABLE\x20—\x20every\x20published\x20Guard\x20silently\x20measures\x20from\x20booking\x20time\x20instead,\x20and\x20for\x20a\x20lead\x20time\x20of\x20'+'days-to-weeks\x20that\x20is\x20a\x20material\x20semantic\x20loss,\x20not\x20a\x20rounding\x20error.'+(d?'\x20The\x20window\x20is\x20also\x20advertised\x20as\x20adjustable,\x20which\x20is\x20doubly\x20unreachable:\x20a\x20Guard\x20is\x20frozen\x20at\x20creation\x20'+'(transfer::freeze_object,\x20guard.move:262)\x20and\x20Machine\x20forwards\x20are\x20immutable\x20after\x20publish\x20(the\x20not-published\x20guard,\x20'+'machine.move:316),\x20so\x20an\x20\x27N-Mh\x20adjustable\x27\x20window\x20means\x20one\x20separately\x20published\x20Guard\x20per\x20window\x20value,\x20never\x20a\x20tunable\x20one.':''),'suggestion':'Express\x20every\x20window\x20relative\x20to\x20`order.time`\x20(or\x20`order.time\x20+\x20<window>`),\x20and\x20if\x20the\x20business\x20promise\x20is\x20genuinely\x20a\x20stay-date\x20'+'deadline,\x20write\x20the\x20stay\x20dates\x20into\x20a\x20Repository\x20at\x20buy\x20time,\x20pin\x20that\x20Repository\x20address\x20as\x20a\x20table\x20constant,\x20and\x20read\x20them\x20in\x20the\x20'+'Guard\x20(`query\x20repository.data`).\x20State\x20the\x20residual\x20semantic\x20loss\x20in\x20build_notes\x20rather\x20than\x20declaring\x20a\x20calendar-relative\x20window.'}];}function signerRefundChecks(a){const b=[],c=a['allocator']['rows']??[],d=c['find'](j=>j['recipient']==='signer'),e=a['allocator']['recipient']==='signer';if(!d&&!e)return b;const f=templateText(a),g=/refund|chargeback|repay|退款|(?:pay(?:ment|out)?|release|send|transfer|settle)\w*[^.\n]{0,40}to the (?:buyer|order|customer)/i['test'](f);if(!g)return b;const h=d?'allocator\x20row\x20'+d['track']+'/'+(d['recipient_key']??'?'):'allocator.recipient=\x27signer\x27';return b['push']({'rule_id':'R-SIGNER-02','severity':'high','title':'Refund\x20leg\x20pays\x20Recipient::Signer\x20—\x20the\x20keeper,\x20not\x20the\x20buyer\x20('+h+')','detail':'`Recipient::Signer`\x20resolves\x20to\x20`tx_context::sender(ctx)`\x20(allocation.move:531-533),\x20i.e.\x20whoever\x20signed\x20the\x20transaction\x20that\x20triggered\x20'+'`alloc`.\x20Time-driven\x20refunds\x20are\x20keeper-triggered\x20by\x20construction,\x20so\x20this\x20leg\x20pays\x20the\x20KEEPER,\x20and\x20because\x20`alloc()`\x20records\x20no\x20'+'consumed\x20flag\x20for\x20the\x20recipient,\x20first-come-first-served.\x20Only\x20`Recipient::GuardIdentifier`\x20(resolved\x20through\x20the\x20Guard\x20submission,\x20'+'allocation.move:501-527)\x20or\x20an\x20explicit\x20`Entity`\x20is\x20safe\x20for\x20a\x20refund.','suggestion':'Replace\x20the\x20Signer\x20refund\x20row\x20with\x20a\x20`{GuardIdentifier:\x200}`\x20row\x20(the\x20submission\x20for\x20a\x20Service-created\x20Allocation\x20is\x20pinned\x20to\x20the\x20paying\x20'+'Order,\x20so\x20only\x20`order.owner`\x20can\x20receive\x20it)\x20and\x20bind\x20the\x20Guard\x20to\x20`order.owner`\x20+\x20`progress.current\x20==\x20<refund\x20node>`.'}),b;}function orderAnchorDeclarationChecks(a){const b=templateText(a),c=a['allocator']['refund_track']==='order_anchored'||/order[\s-]anchored|order anchor|refund recipient is the order|anchor row|guardidentifier\s*\(\s*0\s*\)|for_object|退款接收方为订单/i['test'](b);if(!c)return[];const d=(a['allocator']['rows']??[])['some'](g=>g['recipient']==='guard_identifier'||g['recipient']==='guard_identifier_to_order'),e=a['guards']['some'](h=>h['template_id']==='pattern.allocator_order_anchor');if(d||e)return[];const f=a['allocator']['recipient']??'?';return[{'rule_id':'R-RECIPIENT-02','severity':'high','title':'Order-anchored\x20refund\x20recipient\x20is\x20asserted\x20in\x20prose\x20but\x20declared\x20nowhere\x20machine-checkable','detail':'The\x20template\x20claims\x20an\x20order-anchored\x20escrow\x20/\x20refund\x20recipient\x20while\x20its\x20machine-readable\x20allocator\x20says\x20recipient=\x27'+f+'\x27\x20'+'with\x20no\x20`guard_identifier`\x20row\x20and\x20no\x20`pattern.allocator_order_anchor`\x20Guard\x20reference.\x20Two\x20on-chain\x20facts\x20make\x20the\x20claim\x20as\x20written\x20'+'unbuildable:\x20(1)\x20`Recipient`\x20has\x20only\x20`GuardIdentifier(u8)`\x20/\x20`Entity(address)`\x20/\x20`Signer`\x20(allocation.move:148-152)\x20—\x20there\x20is\x20NO\x20'+'`Order`\x20variant,\x20so\x20\x27the\x20refund\x20recipient\x20is\x20the\x20order\x20object\x27\x20can\x20only\x20be\x20written\x20as\x20a\x20`GuardIdentifier`\x20row;\x20(2)\x20recipients\x20that\x20are\x20'+'all\x20fixed\x20`Entity`\x20rows\x20resolve\x20without\x20the\x20passport\x20submission\x20(allocation.move:528-530)\x20and\x20the\x20Allocation\x20never\x20enters\x20the\x20Guard\x20'+'context,\x20so\x20the\x20Guard\x20has\x20no\x20order\x20to\x20bind\x20at\x20all\x20—\x20the\x20CR-01\x20drain\x20shape.\x20A\x20build\x20agent\x20reading\x20the\x20prose\x20instead\x20of\x20the\x20schema\x20will\x20'+'emit\x20an\x20Entity\x20refund\x20leg\x20to\x20the\x20merchant,\x20or\x20a\x20Signer\x20leg\x20to\x20the\x20keeper.','suggestion':'Declare\x20the\x20anchor\x20machine-checkably:\x20one\x20`{\x20recipient:\x20\x27guard_identifier\x27,\x20recipient_key:\x20\x270\x27,\x20mode:\x20\x27rate\x27,\x20value:\x200\x20}`\x20row\x20(the\x20'+'pattern.allocator_order_anchor\x20convention)\x20plus\x20`refund_track:\x20\x27order_anchored\x27`,\x20and\x20reference\x20`pattern.allocator_order_anchor`\x20in\x20the\x20'+'guard\x20set\x20with\x20the\x20`logic_equal[order.service,\x20<this\x20service>]`\x20binding\x20stated\x20in\x20its\x20purpose.'}];}const EDGE_DEPENDENCY_REGEX=/\b(?:incoming|outgoing|arb_refund)\s+edge\b|\bstop[\s-]node\b|\bedges?\b|\bpairs?\b|\bforwards?\b|one pair|two pairs/i;function topologyChecks(a){const b=[],c=templateText(a);EDGE_DEPENDENCY_REGEX['test'](c)&&b['push']({'rule_id':'R-TOPO-01','severity':'high','title':'machine_shape\x20ships\x20nodes\x20only\x20—\x20no\x20Pair/forward\x20list,\x20so\x20stop-node\x20fund-exit\x20coverage\x20is\x20unauditable','detail':'This\x20template\x27s\x20correctness\x20depends\x20on\x20Machine\x20edges\x20(its\x20own\x20notes\x20reason\x20about\x20incoming/outgoing\x20edges,\x20pairs\x20and\x20stop-node\x20'+'fund-exit\x20coverage),\x20but\x20`machine_shape`\x20carries\x20NO\x20edges:\x20an\x20edge\x20on\x20chain\x20is\x20`Node[target].pairs\x20=\x20{\x20prev_node,\x20threshold,\x20'+'forwards[]\x20}`,\x20which\x20this\x20schema\x20cannot\x20express.\x20The\x20scanner\x20therefore\x20has\x20to\x20invent\x20a\x20linear\x20chain,\x20and\x20the\x20mandatory\x20'+'stop-node\x20walk\x20(R-M5-03\x20/\x20R-M5-09:\x20every\x20rest\x20state\x20needs\x20a\x20defined\x20withdrawal\x20AND\x20refund\x20rule,\x20satisfiable\x20in\x20both\x20directions)\x20'+'cannot\x20be\x20performed\x20—\x20an\x20uncovered\x20stop\x20node\x20strands\x20escrow\x20permanently\x20once\x20Machine\x20+\x20Allocator\x20are\x20frozen\x20at\x20publish.','suggestion':'Either\x20state\x20the\x20edges\x20explicitly\x20in\x20build_notes\x20as\x20`prev\x20─forward(op,w)→\x20next`\x20with\x20the\x20Pair\x20grouping,\x20or\x20declare\x20a\x20machine-readable\x20'+'edge\x20list\x20so\x20the\x20scanner\x20can\x20audit\x20stop-node\x20coverage\x20and\x20prev_node\x20uniqueness\x20instead\x20of\x20guessing.'});const d=a['machine_shape']['map'](j=>j['name']);if(d['length']===0x0)return b;const e=d['filter'](j=>BRANCH_STATE_REGEX['test'](j));if(e['length']===0x0)return b;const f=d[0x0],g=!BRANCH_STATE_REGEX['test'](d[0x1]),h=(g?0x1:0x0)+e['length'];if(h<=0x1)return b;return b['push']({'rule_id':'R-TOPO-02','severity':'medium','title':'Node\x20\x27'+f+'\x27\x20has\x20'+h+'\x20outgoing\x20rails\x20—\x20declare\x20the\x20Pair\x20grouping\x20(E_DUPLICATE_NODE_PREV\x20is\x20per\x20TARGET\x20node,\x20not\x20per\x20source)','detail':'From\x20\x27'+f+'\x27\x20the\x20declared\x20node\x20set\x20requires\x20'+h+'\x20distinct\x20rails\x20'+('('+(g?'the\x20linear\x20rail\x20to\x20\x27'+d[0x1]+'\x27,\x20':''))+(e['map'](j=>'the\x20branch\x20to\x20\x27'+j+'\x27')['join'](',\x20')+').\x20These\x20are\x20LEGAL\x20and\x20must\x20NOT\x20be\x20merged:\x20an\x20edge\x20A→B\x20is\x20')+'stored\x20in\x20`Node[B].pairs\x20=\x20{\x20prev_node:\x20A,\x20threshold,\x20forwards[]\x20}`,\x20and\x20the\x20chain\x20rejects\x20only\x20the\x20SAME\x20`prev_node`\x20appearing\x20'+'twice\x20inside\x20ONE\x20node\x27s\x20pairs\x20(`assert!(!vector::contains(&res,\x20&pair.prev_node),\x20E_DUPLICATE_NODE_PREV)`,\x20machine.move:171\x20and\x20'+'machine.move:440).\x20Rails\x20into\x20different\x20targets\x20occupy\x20different\x20nodes,\x20so\x20each\x20`prev_node`\x20still\x20appears\x20exactly\x20once\x20per\x20node.\x20'+'THE\x20HAZARD\x20IS\x20THE\x20MIRROR\x20IMAGE:\x20two\x20forwards\x20from\x20the\x20SAME\x20source\x20into\x20the\x20SAME\x20target\x20must\x20be\x20ONE\x20Pair\x20carrying\x20both\x20forwards\x20—\x20'+'a\x20builder\x20that\x20emits\x20one\x20Pair\x20per\x20forward\x20duplicates\x20`prev_node`\x20and\x20ABORTS\x20at\x20publish,\x20after\x20Machine\x20+\x20Guard\x20are\x20frozen.\x20Note\x20'+'also\x20that\x20one\x20forward\x20cannot\x20satisfy\x20two\x20operators:\x20each\x20forward\x20contributes\x20its\x20weight\x20at\x20most\x20once\x20(locked\x20by\x20its\x20first\x20operator,\x20'+'progress.move:425-431),\x20so\x20a\x20dual-confirmation\x20step\x20needs\x20`threshold\x20=\x202`\x20with\x20two\x20DISTINCT\x20forwards.\x20A\x20node\x20list\x20cannot\x20distinguish\x20'+'these\x20cases,\x20which\x20is\x20why\x20this\x20is\x20advisory\x20and\x20not\x20a\x20proven\x20defect.','suggestion':'Do\x20NOT\x20merge\x20the\x20rails.\x20Instead\x20declare\x20the\x20grouping\x20explicitly\x20in\x20build_notes\x20as\x20'+'`prev\x20─forward(op,w)→\x20next`,\x20marking\x20which\x20forwards\x20SHARE\x20one\x20target\x20and\x20therefore\x20belong\x20in\x20ONE\x20Pair,\x20and\x20state\x20each\x20Pair\x27s\x20'+'`threshold`\x20(2\x20with\x20two\x20distinct\x20forwards\x20when\x20two\x20different\x20operators\x20must\x20act).\x20This\x20also\x20lets\x20the\x20scanner\x20audit\x20prev_node\x20'+'uniqueness\x20instead\x20of\x20guessing.\x20Related:\x20R-TOPO-01\x20(high)\x20is\x20the\x20finding\x20that\x20records\x20that\x20edges\x20are\x20unauditable\x20at\x20all.'}),b;}function compoundPayoutChecks(a){const b=templateText(a),c=a['allocator']['rows']??[],d=a['allocator']['refund_track']!==undefined||c['some'](f=>f['track']==='refund')||/refund|退款/i['test'](a['allocator']['description']);if(!d)return[];const e=a['guards']['some'](f=>f['host']==='arbitration')||a['trust_mechanisms']['some'](f=>/^R2\b/['test'](f))||/compensation[_ ]fund/i['test'](b);if(!e)return[];return[{'rule_id':'R-COMPOUND-01','severity':'low','title':'Dual\x20buyer-remedy\x20rails\x20(escrow\x20refund\x20+\x20compensation\x20fund)\x20—\x20the\x20arbitrator\x20nets\x20the\x20award','detail':'This\x20template\x20carries\x20BOTH\x20buyer-remedy\x20channels\x20by\x20design:\x20a\x20refund\x20Allocator\x20paying\x20out\x20of\x20the\x20order\x20escrow\x20AND\x20a\x20bound\x20'+'Arbitration\x20paying\x20out\x20of\x20the\x20Service\x27s\x20compensation\x20fund.\x20The\x20two\x20channels\x20are\x20independent\x20on-chain\x20and\x20the\x20platform\x20does\x20not\x20'+'hard-block\x20a\x20double\x20payout\x20at\x20the\x20protocol\x20level\x20—\x20that\x20is\x20an\x20intentional\x20commercial\x20game,\x20not\x20a\x20defect:\x20the\x20merchant\x20chose\x20the\x20'+'arbitrator,\x20and\x20the\x20arbitrator\x20rules\x20on\x20the\x20full\x20fund\x20picture.\x20Every\x20query\x20of\x20an\x20Arb\x20case\x20auto-attaches\x20the\x20order-side\x20fund\x20facts\x20'+'(_order_fund_facts:\x20amount,\x20escrow\x20balance,\x20withdraw\x20history,\x20claimed_by,\x20workflow\x20node),\x20and\x20every\x20case\x20operation\x20result\x20carries\x20'+'order_fund_facts,\x20so\x20a\x20refund-then-claim\x20ordering\x20is\x20visible\x20at\x20ruling\x20time\x20and\x20the\x20award\x20is\x20expected\x20to\x20net\x20out\x20the\x20already-refunded\x20principal.','suggestion':'No\x20structural\x20change\x20required.\x20Keep\x20the\x20operational\x20rule:\x20arbitrators\x20read\x20order_fund_facts\x20before\x20finalizing\x20the\x20indemnity\x20and\x20net\x20'+'any\x20positive\x20escrow_deficit\x20/\x20withdraw_history\x20payouts\x20against\x20the\x20award.\x20If\x20a\x20template\x20intends\x20a\x20non-monetary\x20remedy\x20instead,\x20say\x20so\x20'+'explicitly\x20in\x20the\x20arbitration\x20proposition\x20wording.'}];}function surplusTrackChecks(a){const b=a['allocator']['rows']??[],c=[],d=b['filter'](h=>h['track']==='refund'&&h['mode']==='surplus'),e=b['filter'](h=>h['track']==='settlement'&&h['mode']==='amount');d['length']>0x0&&e['length']>0x0&&c['push']({'rule_id':'R-SURPLUS-01','severity':'critical','title':'Refund-track\x20Surplus\x20sweeps\x20UNPAID\x20settlement\x20Amounts\x20out\x20of\x20the\x20shared\x20pool','detail':'An\x20order\x20funds\x20ONE\x20pool\x20—\x20`track`\x20is\x20a\x20build-time\x20grouping\x20the\x20chain\x20never\x20sees.\x20The\x20refund\x20row\x20'+'runs\x20Surplus\x20mode,\x20which\x20pays\x20the\x20ENTIRE\x20remaining\x20balance\x20(allocation.move:494-505;\x20template\x20rows\x20cannot\x20set\x20'+'`Allocator.max`,\x20so\x20the\x20sweep\x20is\x20uncapped),\x20while\x20the\x20settlement\x20track\x20still\x20carries\x20fixed\x20Amount\x20obligations\x20'+('('+e['map'](h=>h['recipient_key']??h['recipient'])['join'](',\x20')+').\x20Track\x20guards\x20are\x20independent\x20—\x20a\x20')+'time-locked\x20deposit\x20release\x20does\x20not\x20wait\x20for\x20month-gated\x20rent\x20—\x20so\x20when\x20the\x20refund\x20fires\x20first,\x20the\x20sweep\x20hands\x20'+'the\x20unpaid\x20Amounts\x20to\x20the\x20refund\x20recipient.\x20VERIFIED\x20LIVE\x20on\x20ziroom\x20mainnet\x20T-05:\x20the\x20deposit_back\x20Surplus\x20paid\x20'+'the\x20tenant\x20the\x20deposit\x20PLUS\x20the\x20unreleased\x20rent\x20(585/525\x20in\x20full);\x20the\x20landlord\x20received\x200.','suggestion':'Size\x20the\x20refund\x20leg\x20explicitly:\x20an\x20Amount\x20row\x20pinned\x20to\x20the\x20deposit\x20value\x20(value/value_from),\x20so\x20the\x20payout\x20can\x20'+'never\x20exceed\x20its\x20own\x20scope\x20—\x20or\x20split\x20the\x20two\x20fund\x20scopes\x20into\x20separate\x20Allocation\x20objects\x20so\x20a\x20sweep\x20can\x20only\x20'+'reach\x20its\x20own\x20pool.\x20If\x20an\x20uncapped\x20sweep\x20is\x20truly\x20intended,\x20gate\x20it\x20on\x20a\x20node\x20that\x20provably\x20follows\x20the\x20FINAL\x20'+'settlement\x20release,\x20and\x20state\x20in\x20the\x20template\x20that\x20any\x20obligation\x20unpaid\x20by\x20then\x20is\x20forfeit.'});const f=b['filter'](h=>h['track']==='settlement'&&h['mode']==='surplus'),g=b['filter'](h=>h['track']==='refund'&&h['mode']==='amount');return f['length']>0x0&&g['length']>0x0&&c['push']({'rule_id':'R-SURPLUS-02','severity':'high','title':'Settlement-track\x20Surplus\x20can\x20drain\x20the\x20pool\x20ahead\x20of\x20a\x20fixed-Amount\x20refund','detail':'The\x20settlement\x20sweep\x20(Surplus,\x20uncapped\x20—\x20allocation.move:494-505)\x20pays\x20the\x20merchant\x20the\x20entire\x20remainder\x20while\x20'+('the\x20refund\x20track\x20still\x20owes\x20fixed\x20Amounts\x20('+g['map'](h=>h['recipient_key']??h['recipient'])['join'](',\x20')+').\x20')+'If\x20the\x20settlement\x20guard\x20fires\x20while\x20a\x20refund\x20obligation\x20is\x20still\x20open\x20(the\x20tracks\x20are\x20gated\x20independently),\x20the\x20'+'pool\x20is\x20empty\x20when\x20the\x20refund\x20fires\x20and\x20alloc()\x20aborts\x20on\x20insufficient\x20balance\x20(allocation.move:390)\x20—\x20the\x20buyer\x20'+'remedy\x20is\x20bricked\x20and\x20the\x20merchant\x20keeps\x20money\x20the\x20template\x20declared\x20refundable.','suggestion':'Make\x20the\x20two\x20tracks\x20mutually\x20exclusive\x20by\x20construction\x20(refund\x20fires\x20only\x20from\x20cancel\x20nodes\x20the\x20settlement\x20'+'guard\x20can\x20never\x20reach,\x20and\x20vice\x20versa),\x20or\x20size\x20the\x20refund\x20as\x20a\x20Rate\x20so\x20it\x20degrades\x20to\x20a\x20share\x20instead\x20of\x20'+'aborting.\x20NOTE:\x20there\x20is\x20no\x20on-chain\x20holdback\x20(FACT-ALLOC-03)\x20—\x20do\x20NOT\x20try\x20to\x20\x27reserve\x27\x20the\x20refund\x20Amount\x20'+'via\x20a\x20fix\x20value;\x20split\x20the\x20two\x20fund\x20scopes\x20into\x20separate\x20Allocation\x20objects\x20if\x20isolation\x20is\x20required.'}),c;}const BRANCH_STATE_REGEX=/(cancel|return|withdraw|exit|expired)/i;function amountDeadlockChecks(a){const b=a['allocator']['rows']??[],c=b['filter'](f=>f['track']==='settlement');if(c['length']===0x0||!c['every'](f=>f['mode']==='amount'))return[];const d=[a['allocator']['description'],...a['build_notes'],...a['trust_mechanisms'],...a['guards']['map'](f=>f['template_id']+'\x20'+f['purpose'])]['join']('\x20\x0a\x20'),e=Object['keys'](a['fee_params'])['some'](f=>MIN_PRICE_KEY_REGEX['test'](f))||FLOOR_TEXT_REGEX['test'](d);if(e)return[];return[{'rule_id':'R-DEADLOCK-01','severity':'medium','title':'Settlement\x20track\x20is\x20ALL\x20fixed\x20Amount\x20—\x20an\x20under-funded\x20pool\x20deadlocks\x20permanently','detail':'Every\x20settlement\x20row\x20is\x20mode\x20\x27amount\x27\x20('+c['length']+'\x20row(s));\x20each\x20asserts\x20balance\x20>=\x20fix\x20at\x20release\x20'+'(allocation.move:390).\x20When\x20the\x20pool\x20is\x20smaller\x20than\x20the\x20pinned\x20leg\x20—\x20a\x20discount\x20code,\x20a\x20low-price\x20SKU,\x20a\x20'+'partially-funded\x20order\x20—\x20the\x20call\x20aborts\x20and\x20NO\x20later\x20call\x20can\x20settle\x20a\x20smaller\x20amount:\x20the\x20merchant\x27s\x20payout\x20'+'path\x20is\x20bricked\x20for\x20that\x20order\x20(ziroom\x20CR-02:\x20fixed\x20Amount\x20legs\x20+\x20a\x20cheap\x20SKU\x20=\x20permanent\x20settlement\x20abort).\x20'+'Rate\x20and\x20Surplus\x20legs\x20degrade\x20to\x20whatever\x20the\x20pool\x20actually\x20holds;\x20Amount\x20legs\x20cannot.','suggestion':'Carry\x20at\x20least\x20one\x20Rate/Surplus\x20leg\x20as\x20the\x20degradation\x20path\x20(e.g.\x20the\x20merchant\x20remainder\x20as\x20Rate),\x20or\x20enforce\x20a\x20'+'build-time\x20price\x20floor\x20proving\x20order_total\x20>=\x20the\x20largest\x20fixed\x20leg\x20—\x20and\x20state\x20that\x20floor\x20in\x20fee_params\x20so\x20the\x20'+'builder\x20cannot\x20silently\x20undercut\x20it.'}];}function cancelCoverageChecks(a){const b=a['allocator']['rows']??[];if(b['some'](d=>d['track']==='refund'))return[];if(a['allocator']['refund_track']!==undefined)return[];const c=a['machine_shape']['find'](d=>BRANCH_STATE_REGEX['test'](d['name']));if(!c)return[];return[{'rule_id':'R-CANCEL-01','severity':'high','title':'Machine\x20models\x20\x27'+c['name']+'\x27\x20but\x20the\x20allocator\x20has\x20NO\x20refund-track\x20rows\x20—\x20money\x20locks\x20on\x20that\x20path','detail':'The\x20machine\x20shape\x20carries\x20a\x20cancel/return/exit\x20state,\x20yet\x20no\x20allocator\x20row\x20pays\x20on\x20the\x20refund\x20track.\x20Text-level\x20'+'claims\x20(guard\x20purposes,\x20allocator\x20description)\x20may\x20still\x20say\x20\x27refund\x27,\x20but\x20on\x20chain\x20only\x20rows\x20move\x20money:\x20an\x20'+'order\x20that\x20reaches\x20this\x20state\x20keeps\x20its\x20escrow\x20with\x20no\x20rail\x20out\x20(ofn\x20#P-02:\x20the\x20subscription\x20template\x27s\x20refund\x20'+'rails\x20missed\x20closed_cancel\x20and\x200.5\x20WOW\x20locked\x20permanently;\x20verified\x20live).','suggestion':'Add\x20refund-track\x20rows\x20covering\x20EVERY\x20cancel-ish\x20terminal\x20(order-anchored\x20GuardIdentifier(0)\x20recipient,\x20'+'Rate-sized\x20with\x20the\x20group\x20summing\x2010000),\x20or\x20remove\x20the\x20state\x20from\x20the\x20machine\x20so\x20orders\x20can\x20never\x20enter\x20it.'}];}function redundGuardObjectMismatchChecks(a){const b=a['allocator']['rows']??[],c=b['filter'](g=>g['track']==='refund'&&g['recipient']==='guard_identifier');if(c['length']===0x0)return[];const d=a['guards']['some'](h=>/arb|ruling|arbitration/i['test'](h['template_id'])||/arb|ruling|arbitration/i['test'](h['purpose']));if(!d)return[];const e=templateText(a),f=/two[- ]slot|slot\s*0.*order|slot\s*1.*arb|arb\.order.*==|for_object.*binding/i['test'](e);if(f)return[{'rule_id':'REDUND-GUARD-OBJECT-MISMATCH','severity':'low','title':'Arb-refund\x20guard\x20uses\x20two-slot\x20design\x20(Order\x20+\x20Arb)\x20—\x20self-certifying\x20pair','detail':'The\x20template\x20carries\x20a\x20refund\x20allocator\x20row\x20with\x20a\x20GuardIdentifier\x20recipient\x20AND\x20an\x20arbitration-ruling\x20guard.\x20'+'The\x20two-slot\x20design\x20(slot\x200\x20=\x20Order\x20for\x20the\x20allocator\x20recipient,\x20slot\x201\x20=\x20Arb\x20for\x20the\x20ruling\x20state)\x20is\x20the\x20'+'correct\x20resolution\x20of\x20the\x20F-02\x20slot\x20conflict:\x20the\x20allocator\x20reads\x20slot\x200\x20(payment_info.for_object\x20binding),\x20'+'the\x20forward\x20reads\x20slot\x201\x20(arb.indemnity\x20state),\x20and\x20the\x20binding\x20assertion\x20query(\x22arb.order\x22,\x20slot1)\x20==\x20slot0\x20'+'makes\x20the\x20pair\x20self-certifying\x20against\x20redirect\x20attacks.','suggestion':'Verify\x20the\x20guard\x20is\x20tpl_forward_arb_ruling_won\x20(two-slot\x20form)\x20or\x20an\x20equivalent\x20custom\x20guard\x20with\x20the\x20same\x20'+'slot\x20layout\x20and\x20binding\x20assertion.\x20Single-slot\x20arb-refund\x20guards\x20are\x20unreachable\x20(F-02).'}];return[{'rule_id':'REDUND-GUARD-OBJECT-MISMATCH','severity':'high','title':'Arb-refund\x20guard\x20may\x20use\x20a\x20SINGLE\x20slot\x20—\x20unreachable\x20rail\x20(F-02)','detail':'The\x20template\x20carries\x20a\x20refund\x20allocator\x20row\x20with\x20a\x20GuardIdentifier\x20recipient\x20AND\x20an\x20arbitration-ruling\x20guard,\x20'+'but\x20the\x20template\x20text\x20does\x20not\x20mention\x20the\x20two-slot\x20design.\x20A\x20single-slot\x20guard\x20cannot\x20satisfy\x20both\x20consumers:\x20'+'the\x20forward\x20needs\x20the\x20Arb\x20object\x20(to\x20read\x20arb.indemnity),\x20while\x20the\x20allocator\x20recipient\x20GuardIdentifier(0)\x20needs\x20'+'the\x20Order\x20object\x20(payment_info.for_object\x20binding).\x20F-02\x20verified\x20live:\x20Order\x20address\x20→\x20forward\x20aborts;\x20Arb\x20address\x20'+'→\x20allocation\x20aborts\x2015\x20(ERECIPIENT_NOT_FOR_OBJECT).\x20The\x20escrow\x20strands\x20permanently\x20with\x20no\x20on-chain\x20exit.','suggestion':'Use\x20tpl_forward_arb_ruling_won\x20(two-slot\x20form:\x20slot\x200\x20=\x20Order,\x20slot\x201\x20=\x20Arb,\x20with\x20arb.order\x20==\x20order\x20binding),\x20'+'or\x20document\x20the\x20two-slot\x20design\x20explicitly\x20in\x20the\x20template\x20build_notes.\x20A\x20single-slot\x20arb-refund\x20guard\x20is\x20'+'unreachable\x20by\x20construction\x20(F-02).'}];}function zeroAmountGuardChecks(a){const b=templateText(a),c=/zero[- ]amount|0[ -]?amount|free[^a-z]|price\s*=\s*0|amount\s*>\s*0|min_booking_amount/i['test'](b)||/no[- ]charge|gratis|complimentary/i['test'](b);if(c)return[];const d=a['guards']['some'](e=>e['host']==='machine'&&(/claimed_by|allocation|payment\s|alloc\b/i['test'](e['template_id'])||/claimed_by|allocation|payment\s|alloc\b/i['test'](e['purpose'])));if(!d)return[];return[{'rule_id':'D7-ZERO-AMOUNT-GUARD','severity':'medium','title':'Machine\x20progress\x20guards\x20may\x20depend\x20on\x20allocator\x20events\x20—\x20zero-amount\x20orders\x20deadlock','detail':'The\x20protocol\x20does\x20NOT\x20create\x20an\x20Allocation\x20for\x20a\x20zero-amount\x20order\x20(amount\x20>\x200\x20is\x20required).\x20'+'A\x20zero-amount\x20order\x20therefore\x20has\x20NO\x20claimed_by,\x20NO\x20payment\x20history,\x20and\x20NO\x20allocation\x20balance.\x20'+'This\x20template\x20carries\x20machine\x20guards\x20that\x20reference\x20allocator-dependent\x20state\x20(claimed_by\x20/\x20allocation\x20/\x20payment),\x20'+'but\x20the\x20template\x20does\x20NOT\x20explicitly\x20exclude\x20zero-amount\x20items.\x20A\x20zero-amount\x20order\x20can\x20never\x20satisfy\x20such\x20a\x20guard\x20'+'and\x20deadlocks\x20at\x20the\x20node\x20with\x20no\x20exit.','suggestion':'Either\x20(a)\x20exclude\x20zero-amount\x20items\x20explicitly\x20(e.g.\x20min_booking_amount,\x20amount\x20>\x200\x20in\x20build_notes),\x20or\x20'+'(b)\x20redesign\x20progress\x20guards\x20to\x20use\x20order-native\x20signals\x20(order.time,\x20signer,\x20progress.current,\x20Repository\x20data)\x20'+'instead\x20of\x20allocator-derived\x20state,\x20so\x20zero-amount\x20orders\x20can\x20still\x20advance.'}];}function serialClaimWindowChecks(a){const b=a['machine_shape']['some'](h=>/claim/i['test'](h['name']))||a['guards']['some'](h=>/claim/i['test'](h['purpose']));if(!b)return[];const c=a['allocator']['rows']??[],d=c['some'](h=>h['track']==='settlement'&&(h['mode']==='surplus'||h['mode']==='rate'&&h['value']===0x2710));if(!d)return[];const e=templateText(a),f=a['machine_shape']['some'](h=>/claim_window/i['test'](h['name'])),g=/serial claim[- ]window|claim_window.*serial|serial[- ]claim|claims? (is|are|always) adjudicated while the pool is intact|between checkout and payout|before (any )?release/i['test'](e);if(f&&g)return[{'rule_id':'D2-SERIAL-CLAIM-WINDOW','severity':'low','title':'Serial\x20claim\x20window\x20gates\x20the\x20full-drain\x20release\x20(ABNB2-validated\x20design)','detail':'The\x20template\x20carries\x20claim\x20machinery\x20AND\x20a\x20full-drain\x20settlement\x20group\x20(Rate\x2010000\x20/\x20Surplus),\x20'+'and\x20resolves\x20the\x20race\x20with\x20a\x20serial\x20claim_window\x20node\x20between\x20delivery\x20confirmation\x20and\x20payout:\x20'+'the\x20release\x20can\x20only\x20fire\x20after\x20the\x20window\x20closed\x20with\x20no\x20upheld\x20claim,\x20so\x20the\x20pool\x20is\x20intact\x20'+'whenever\x20money\x20moves.','suggestion':'Verify\x20the\x20release\x20guard\x20anchors\x20on\x20progress.current_time\x20of\x20the\x20claim_window\x20entry\x20'+'(witness-derived),\x20not\x20on\x20order.time\x20—\x20a\x20booking-time\x20delay\x20has\x20always\x20expired\x20before\x20'+'checkout\x20and\x20gives\x20no\x20post-delivery\x20protection.'}];return[{'rule_id':'D2-SERIAL-CLAIM-WINDOW','severity':'high','title':'Full-drain\x20release\x20can\x20fire\x20while\x20a\x20claim\x20is\x20still\x20openable\x20—\x20FCFS\x20race\x20on\x20one\x20pool\x20(FACT-ALLOC-03)','detail':'The\x20template\x20carries\x20claim\x20machinery\x20AND\x20a\x20full-drain\x20settlement\x20group\x20(Rate\x2010000\x20or\x20Surplus),\x20'+'but\x20no\x20serial\x20claim_window\x20node\x20orders\x20them:\x20the\x20payout\x20and\x20a\x20later\x20claim\x20race\x20first-come-first-served\x20'+'on\x20the\x20SAME\x20pool,\x20and\x20the\x20chain\x20has\x20no\x20holdback\x20primitive\x20(fix\x20is\x20the\x20PAID\x20sum\x20of\x20Amount\x20legs,\x20'+'allocation.move:399,540).\x20Once\x20the\x20release\x20fires,\x20a\x20claim\x20can\x20pay\x20nothing\x20from\x20the\x20pool.\x20'+'Airbnb\x20mainnet\x20audit\x202026-10-07:\x20the\x20parallel\x20payout/claim\x20design\x20paid\x20the\x20host\x20in\x20full\x20and\x20left\x20'+'the\x20claim\x20window\x20with\x20an\x20empty\x20pool.','suggestion':'Insert\x20a\x20SERIAL\x20claim_window\x20node\x20between\x20delivery\x20confirmation\x20and\x20payout\x20(ABNB2-validated):\x20'+'checkout\x20→\x20claim_window\x20→\x20payout,\x20with\x20exactly\x20two\x20exits\x20—\x20FileClaim\x20(inside\x20the\x20window,\x20'+'Clock\x20<=\x20current_time(claim_window)\x20+\x20claim_window_days)\x20and\x20ReleaseNoClaim\x20(window\x20elapsed).\x20'+'Gate\x20the\x20release\x20allocator\x20on\x20the\x20post-window\x20node,\x20and\x20give\x20a\x20denied\x20claim\x20its\x20own\x20release\x20'+'forward\x20so\x20no\x20stop\x20node\x20holds\x20funds.'}];}function syntheticMachine(a){const b=a['machine_shape']['map'](e=>({'name':e['name'],'description':e['role'],'operator':e['operator']})),c=[],d=(e,f)=>[{'name':e,'weight':0x1,'named_operator':f==='order_payer'?'':'order_holder'}];b['length']>0x0&&c['push']({'prev_node':'','next_node':b[0x0]['name'],'threshold':0x1,'forwards':d('enter_'+b[0x0]['name'],b[0x0]['operator'])});for(let e=0x0;e<b['length']-0x1;e++){const f=b[e]['name'],g=b[e+0x1];if(BRANCH_STATE_REGEX['test'](g['name']))continue;c['push']({'prev_node':f,'next_node':g['name'],'threshold':0x1,'forwards':d(f+'_to_'+g['name'],g['operator'])});}if(b['length']>0x0)for(const h of b){BRANCH_STATE_REGEX['test'](h['name'])&&c['push']({'prev_node':b[0x0]['name'],'next_node':h['name'],'threshold':0x1,'forwards':d('to_'+h['name'],h['operator'])});}return{'nodes':b,'pairs':c};}function singleNodeGraph(a){return{'network':ENTRYPOINT['Testnet'],'seed':a['id'],'builtAt':Date['now'](),'nodes':new Map([[a['id'],a]]),'edges':[],'out':new Map(),'inc':new Map(),'gaps':[],'truncations':[],'rpcReport':{'batches':0x0,'byChannel':{'objects':0x0,'keyedFields':0x0,'tables':0x0,'events':0x0},'dedupHits':0x0},'budgetExhausted':{}};}function analyzerFindings(a){const b=makeProposalNode('machine',syntheticMachine(a)),c=singleNodeGraph(b),d=buildViewport(c,c['seed'],'neutral');return runNodeAnalyzers(d,[machineRuleNodeAnalyzer,allocationRuleNodeAnalyzer]);}const SEVERITY_ORDER={'low':0x0,'medium':0x1,'high':0x2,'critical':0x3};export function scanTemplate(a){const b=[...staticChecks(a),...guardRefChecks(a),...fundAnchorChecks(a),...periodicReleaseChecks(a),...timeWindowAnchorChecks(a),...signerRefundChecks(a),...orderAnchorDeclarationChecks(a),...topologyChecks(a),...compoundPayoutChecks(a),...surplusTrackChecks(a),...amountDeadlockChecks(a),...cancelCoverageChecks(a),...redundGuardObjectMismatchChecks(a),...zeroAmountGuardChecks(a),...serialClaimWindowChecks(a)];for(const e of analyzerFindings(a)){const g=e['severity']==='info'?'low':e['severity'];b['push']({'rule_id':e['ruleId'],'severity':g,'title':e['title'],'detail':e['detail'],'suggestion':e['suggestion']});}b['sort']((h,j)=>SEVERITY_ORDER[j['severity']]-SEVERITY_ORDER[h['severity']]);const c=b['length']>0x0?b[0x0]['severity']:'low',d=b['filter'](h=>h['severity']==='critical')['map'](h=>''+(h['rule_id']?h['rule_id']+':\x20':'')+h['title']);return{'template_id':a['id'],'risk_level':c,'passed':d['length']===0x0,'findings':b,'red_flags':d};}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const TOOL_CONSTRAINTS=[{'operation_type':'service','constraints':[{'field':'namedNew.name','description':'Service\x20should\x20have\x20a\x20name\x20for\x20easy\x20reference','severity':'warning','check':a=>!!a?.['namedNew']?.['name']||typeof a?.['object']==='string','message':()=>'Service\x20without\x20a\x20name\x20is\x20hard\x20to\x20reference\x20later.\x20Consider\x20setting\x20namedNew.name.'},{'field':'price','description':'Service\x20price\x20should\x20be\x20set\x20before\x20publish','severity':'warning','check':a=>a?.['price']!==undefined||!a?.['publish'],'message':()=>'Publishing\x20a\x20service\x20without\x20a\x20price\x20—\x20customers\x20won\x27t\x20know\x20the\x20cost.'}],'requireOneOf':[{'fields':['object','namedNew'],'reason':'Must\x20specify\x20either\x20an\x20existing\x20object\x20(string)\x20or\x20create\x20new\x20(namedNew)'}]},{'operation_type':'machine','constraints':[{'field':'node.nodes','description':'Machine\x20must\x20have\x20at\x20least\x20one\x20node\x20when\x20published','severity':'error','check':a=>{if(typeof a?.['object']==='string')return!![];if(!a?.['publish'])return!![];if(Array['isArray'](a?.['node']?.['nodes'])&&a['node']['nodes']['length']>0x0)return!![];if(typeof a?.['node']?.['json_or_markdown_file']==='string'&&a['node']['json_or_markdown_file']['length']>0x0)return!![];return![];},'message':()=>'Publishing\x20a\x20Machine\x20without\x20nodes\x20—\x20a\x20workflow\x20template\x20requires\x20at\x20least\x20one\x20node.\x20Provide\x20nodes\x20via\x20inline\x20`node.nodes`\x20array\x20OR\x20`node.json_or_markdown_file`\x20path\x20(file\x20contains\x20JSON\x20or\x20Markdown\x20node\x20definitions).\x20Consider\x20adding\x20nodes\x20before\x20publish,\x20or\x20publish\x20later\x20after\x20adding\x20nodes.'}]},{'operation_type':'payment','constraints':[{'field':'revenue','description':'Payment\x20requires\x20at\x20least\x20one\x20revenue\x20entry\x20(CREATE\x20mode\x20only)','severity':'error','check':a=>a?.['receive']===!![]||Array['isArray'](a?.['revenue'])&&a['revenue']['length']>0x0,'message':()=>'Payment\x20requires\x20a\x20non-empty\x20\x27revenue\x27\x20array\x20(payment\x20recipients\x20and\x20amounts).\x20For\x20RECEIVE\x20mode\x20(unwrap\x20CoinWrapper),\x20use\x20{object:\x20\x27<coinwrapper_id>\x27,\x20receive:\x20true,\x20type_parameter:\x20\x270x2::wow::WOW\x27}.'},{'field':'revenue[0].amount','description':'Payment\x20revenue\x20amount\x20must\x20be\x20specified\x20(CREATE\x20mode\x20only)','severity':'error','check':a=>a?.['receive']===!![]||Array['isArray'](a?.['revenue'])&&a['revenue']['length']>0x0&&(!!a['revenue'][0x0]?.['amount']?.['balance']||!!a['revenue'][0x0]?.['amount']?.['coin']),'message':()=>'Payment\x20revenue[0].amount\x20must\x20specify\x20either\x20\x27balance\x27\x20value\x20or\x20\x27coin\x27\x20object\x20(see\x20CoinParamSchema).'}]},{'operation_type':'allocation','constraints':[{'field':'payment_info.for_object','description':'Unanchored\x20allocation\x20with\x20GuardIdentifier\x20recipients\x20is\x20blocked\x20by\x20default\x20(docs#11)','severity':'error','check':a=>{if(!a?.['allocators'])return!![];if(a?.['allow_unanchored']===!![])return!![];if(a?.['payment_info']?.['for_object'])return!![];const b=a?.['allocators']?.['allocators'];if(!Array['isArray'](b))return!![];return!b['some'](c=>Array['isArray'](c?.['sharing'])&&c['sharing']['some'](e=>e?.['who']&&'GuardIdentifier'in e['who']));},'message':()=>'Unanchored\x20allocation\x20(payment_info.for_object\x20not\x20set)\x20with\x20GuardIdentifier\x20recipients\x20lets\x20any\x20guard-passing\x20caller\x20redirect\x20the\x20submitted\x20payout\x20address\x20to\x20an\x20arbitrary\x20address\x20(docs#11).\x20Anchor\x20it\x20with\x20payment_info.for_object,\x20or\x20pass\x20allow_unanchored:true\x20to\x20proceed.'}]},{'operation_type':'order','constraints':[{'field':'object','description':'Order\x20requires\x20an\x20existing\x20Order\x20object\x20reference','severity':'error','check':a=>!!a?.['object'],'message':()=>'Order\x20requires\x20\x27object\x27\x20field\x20(Order\x20object\x20ID\x20or\x20name).'}]},{'operation_type':'reward','constraints':[{'field':'coin_add','description':'Reward\x20funding\x20requires\x20coin_add','severity':'warning','check':a=>{if(a?.['claim']||a?.['guard_add']||a?.['guard_remove_expired']||a?.['owner_receive']||a?.['receive'])return!![];return!!a?.['coin_add']?.['balance']||!!a?.['coin_add']?.['coin'];},'message':()=>'Reward\x20funding\x20requires\x20\x27coin_add\x27\x20with\x20either\x20\x27balance\x27\x20value\x20or\x20\x27coin\x27\x20object\x20(see\x20CoinParamSchema).\x20Other\x20operations\x20(claim,\x20guard_add,\x20etc.)\x20don\x27t\x20need\x20coin_add.'}]},{'operation_type':'guard','constraints':[{'field':'root','description':'Guard\x20must\x20specify\x20root\x20(node\x20tree\x20or\x20file)','severity':'error','check':a=>!!a?.['root'],'message':()=>'Guard\x20requires\x20a\x20\x27root\x27\x20field\x20(type=\x27node\x27\x20for\x20tree\x20or\x20type=\x27file\x27\x20to\x20load\x20from\x20file).'}]},{'operation_type':'permission','constraints':[{'field':'with_forbidden','description':'Permission\x20should\x20have\x20at\x20least\x20one\x20rule','severity':'warning','check':a=>Array['isArray'](a?.['with_forbidden'])&&a['with_forbidden']['length']>0x0||Array['isArray'](a?.['with_allowed'])&&a['with_allowed']['length']>0x0,'message':()=>'Permission\x20has\x20no\x20rules\x20(with_forbidden/with_allowed).\x20An\x20empty\x20permission\x20allows\x20nothing.'}]},{'operation_type':'demand','constraints':[{'field':'reward','description':'Demand\x20should\x20have\x20a\x20reward\x20to\x20attract\x20solutions','severity':'warning','check':a=>!!a?.['reward'],'message':()=>'Demand\x20without\x20a\x20reward\x20pool\x20may\x20not\x20attract\x20solution\x20providers.'}]},{'operation_type':'progress','constraints':[{'field':'object','description':'Progress\x20requires\x20an\x20existing\x20Progress\x20object\x20reference','severity':'error','check':a=>!!a?.['object'],'message':()=>'Progress\x20requires\x20\x27object\x27\x20field\x20(Progress\x20object\x20ID\x20or\x20name).'}]}];const CONSTRAINT_INDEX=new Map(TOOL_CONSTRAINTS['map'](a=>[a['operation_type'],a]));export function validateOperation(a,b){const d=CONSTRAINT_INDEX['get'](a);if(!d)return[];const e=[];for(const f of d['constraints']){try{!f['check'](b)&&e['push']({'field':f['field'],'severity':f['severity'],'message':f['message'](b)});}catch{}}if(d['requireOneOf'])for(const g of d['requireOneOf']){const h=g['fields']['some'](i=>b?.[i]!==undefined&&b?.[i]!==null);!h&&e['push']({'field':g['fields']['join']('|'),'severity':'error','message':g['reason']});}if(d['mutuallyExclusive'])for(const i of d['mutuallyExclusive']){const j=i['fields']['filter'](k=>b?.[k]!==undefined&&b?.[k]!==null);j['length']>0x1&&e['push']({'field':j['join']('|'),'severity':'error','message':'Fields\x20are\x20mutually\x20exclusive:\x20'+j['join'](',\x20')+'.\x20'+i['reason']});}return e;}export function hasBlockingViolations(a){return a['some'](b=>b['severity']==='error');}export function getWarningViolations(a){return a['filter'](b=>b['severity']==='warning');}export const TOOL_CONSTRAINTS_VERSION=0x1;
|
|
1
|
+
import{checkEntityRecipientsSync,describeEntityRecipients}from'./entity-recipient-guard.js';function entityRecipientsSatisfied(a){try{const b=a?.['allocators']??a?.['order_allocators'];if(!b)return!![];return checkEntityRecipientsSync(b)['length']===0x0;}catch{return!![];}}export const TOOL_CONSTRAINTS=[{'operation_type':'service','constraints':[{'field':'namedNew.name','description':'Service\x20should\x20have\x20a\x20name\x20for\x20easy\x20reference','severity':'warning','check':a=>!!a?.['namedNew']?.['name']||typeof a?.['object']==='string','message':()=>'Service\x20without\x20a\x20name\x20is\x20hard\x20to\x20reference\x20later.\x20Consider\x20setting\x20namedNew.name.'},{'field':'price','description':'Service\x20price\x20should\x20be\x20set\x20before\x20publish','severity':'warning','check':a=>a?.['price']!==undefined||!a?.['publish'],'message':()=>'Publishing\x20a\x20service\x20without\x20a\x20price\x20—\x20customers\x20won\x27t\x20know\x20the\x20cost.'},{'field':'allocators.allocators[].sharing[].who.Entity.name_or_address','description':'R-RECIPIENT-03\x20—\x20an\x20Entity\x20recipient\x20may\x20not\x20be\x20empty,\x20omitted,\x20unresolved,\x20or\x20the\x20deploying\x20account\x20(direct-sales\x20invariant)','severity':'error','check':entityRecipientsSatisfied,'message':a=>describeEntityRecipients(checkEntityRecipientsSync(a?.['allocators']??a?.['order_allocators']))}],'requireOneOf':[{'fields':['object','namedNew'],'reason':'Must\x20specify\x20either\x20an\x20existing\x20object\x20(string)\x20or\x20create\x20new\x20(namedNew)'}]},{'operation_type':'machine','constraints':[{'field':'node.nodes','description':'Machine\x20must\x20have\x20at\x20least\x20one\x20node\x20when\x20published','severity':'error','check':a=>{if(typeof a?.['object']==='string')return!![];if(!a?.['publish'])return!![];if(Array['isArray'](a?.['node']?.['nodes'])&&a['node']['nodes']['length']>0x0)return!![];if(typeof a?.['node']?.['json_or_markdown_file']==='string'&&a['node']['json_or_markdown_file']['length']>0x0)return!![];return![];},'message':()=>'Publishing\x20a\x20Machine\x20without\x20nodes\x20—\x20a\x20workflow\x20template\x20requires\x20at\x20least\x20one\x20node.\x20Provide\x20nodes\x20via\x20inline\x20`node.nodes`\x20array\x20OR\x20`node.json_or_markdown_file`\x20path\x20(file\x20contains\x20JSON\x20or\x20Markdown\x20node\x20definitions).\x20Consider\x20adding\x20nodes\x20before\x20publish,\x20or\x20publish\x20later\x20after\x20adding\x20nodes.'}]},{'operation_type':'payment','constraints':[{'field':'revenue','description':'Payment\x20requires\x20at\x20least\x20one\x20revenue\x20entry\x20(CREATE\x20mode\x20only)','severity':'error','check':a=>a?.['receive']===!![]||Array['isArray'](a?.['revenue'])&&a['revenue']['length']>0x0,'message':()=>'Payment\x20requires\x20a\x20non-empty\x20\x27revenue\x27\x20array\x20(payment\x20recipients\x20and\x20amounts).\x20For\x20RECEIVE\x20mode\x20(unwrap\x20CoinWrapper),\x20use\x20{object:\x20\x27<coinwrapper_id>\x27,\x20receive:\x20true,\x20type_parameter:\x20\x270x2::wow::WOW\x27}.'},{'field':'revenue[0].amount','description':'Payment\x20revenue\x20amount\x20must\x20be\x20specified\x20(CREATE\x20mode\x20only)','severity':'error','check':a=>a?.['receive']===!![]||Array['isArray'](a?.['revenue'])&&a['revenue']['length']>0x0&&(!!a['revenue'][0x0]?.['amount']?.['balance']||!!a['revenue'][0x0]?.['amount']?.['coin']),'message':()=>'Payment\x20revenue[0].amount\x20must\x20specify\x20either\x20\x27balance\x27\x20value\x20or\x20\x27coin\x27\x20object\x20(see\x20CoinParamSchema).'}]},{'operation_type':'allocation','constraints':[{'field':'payment_info.for_object','description':'Unanchored\x20allocation\x20with\x20GuardIdentifier\x20recipients\x20is\x20blocked\x20by\x20default\x20(docs#11)','severity':'error','check':a=>{if(!a?.['allocators'])return!![];if(a?.['allow_unanchored']===!![])return!![];if(a?.['payment_info']?.['for_object'])return!![];const b=a?.['allocators']?.['allocators'];if(!Array['isArray'](b))return!![];return!b['some'](c=>Array['isArray'](c?.['sharing'])&&c['sharing']['some'](e=>e?.['who']&&'GuardIdentifier'in e['who']));},'message':()=>'Unanchored\x20allocation\x20(payment_info.for_object\x20not\x20set)\x20with\x20GuardIdentifier\x20recipients\x20lets\x20any\x20guard-passing\x20caller\x20redirect\x20the\x20submitted\x20payout\x20address\x20to\x20an\x20arbitrary\x20address\x20(docs#11).\x20Anchor\x20it\x20with\x20payment_info.for_object,\x20or\x20pass\x20allow_unanchored:true\x20to\x20proceed.'},{'field':'allocators.allocators[].sharing[].who.Entity.name_or_address','description':'R-RECIPIENT-03\x20—\x20an\x20Entity\x20recipient\x20may\x20not\x20be\x20empty,\x20omitted,\x20unresolved,\x20or\x20the\x20deploying\x20account\x20(direct-sales\x20invariant)','severity':'error','check':entityRecipientsSatisfied,'message':a=>describeEntityRecipients(checkEntityRecipientsSync(a?.['allocators']??a?.['order_allocators']))}]},{'operation_type':'order','constraints':[{'field':'object','description':'Order\x20requires\x20an\x20existing\x20Order\x20object\x20reference','severity':'error','check':a=>!!a?.['object'],'message':()=>'Order\x20requires\x20\x27object\x27\x20field\x20(Order\x20object\x20ID\x20or\x20name).'}]},{'operation_type':'reward','constraints':[{'field':'coin_add','description':'Reward\x20funding\x20requires\x20coin_add','severity':'warning','check':a=>{if(a?.['claim']||a?.['guard_add']||a?.['guard_remove_expired']||a?.['owner_receive']||a?.['receive'])return!![];return!!a?.['coin_add']?.['balance']||!!a?.['coin_add']?.['coin'];},'message':()=>'Reward\x20funding\x20requires\x20\x27coin_add\x27\x20with\x20either\x20\x27balance\x27\x20value\x20or\x20\x27coin\x27\x20object\x20(see\x20CoinParamSchema).\x20Other\x20operations\x20(claim,\x20guard_add,\x20etc.)\x20don\x27t\x20need\x20coin_add.'}]},{'operation_type':'guard','constraints':[{'field':'root','description':'Guard\x20must\x20specify\x20root\x20(node\x20tree\x20or\x20file)','severity':'error','check':a=>!!a?.['root'],'message':()=>'Guard\x20requires\x20a\x20\x27root\x27\x20field\x20(type=\x27node\x27\x20for\x20tree\x20or\x20type=\x27file\x27\x20to\x20load\x20from\x20file).'}]},{'operation_type':'permission','constraints':[{'field':'with_forbidden','description':'Permission\x20should\x20have\x20at\x20least\x20one\x20rule','severity':'warning','check':a=>Array['isArray'](a?.['with_forbidden'])&&a['with_forbidden']['length']>0x0||Array['isArray'](a?.['with_allowed'])&&a['with_allowed']['length']>0x0,'message':()=>'Permission\x20has\x20no\x20rules\x20(with_forbidden/with_allowed).\x20An\x20empty\x20permission\x20allows\x20nothing.'}]},{'operation_type':'demand','constraints':[{'field':'reward','description':'Demand\x20should\x20have\x20a\x20reward\x20to\x20attract\x20solutions','severity':'warning','check':a=>!!a?.['reward'],'message':()=>'Demand\x20without\x20a\x20reward\x20pool\x20may\x20not\x20attract\x20solution\x20providers.'}]},{'operation_type':'progress','constraints':[{'field':'object','description':'Progress\x20requires\x20an\x20existing\x20Progress\x20object\x20reference','severity':'error','check':a=>!!a?.['object'],'message':()=>'Progress\x20requires\x20\x27object\x27\x20field\x20(Progress\x20object\x20ID\x20or\x20name).'}]}];const CONSTRAINT_INDEX=new Map(TOOL_CONSTRAINTS['map'](a=>[a['operation_type'],a]));export function validateOperation(a,b){const d=CONSTRAINT_INDEX['get'](a);if(!d)return[];const e=[];for(const f of d['constraints']){try{!f['check'](b)&&e['push']({'field':f['field'],'severity':f['severity'],'message':f['message'](b)});}catch{}}if(d['requireOneOf'])for(const g of d['requireOneOf']){const h=g['fields']['some'](i=>b?.[i]!==undefined&&b?.[i]!==null);!h&&e['push']({'field':g['fields']['join']('|'),'severity':'error','message':g['reason']});}if(d['mutuallyExclusive'])for(const i of d['mutuallyExclusive']){const j=i['fields']['filter'](k=>b?.[k]!==undefined&&b?.[k]!==null);j['length']>0x1&&e['push']({'field':j['join']('|'),'severity':'error','message':'Fields\x20are\x20mutually\x20exclusive:\x20'+j['join'](',\x20')+'.\x20'+i['reason']});}return e;}export function hasBlockingViolations(a){return a['some'](b=>b['severity']==='error');}export function getWarningViolations(a){return a['filter'](b=>b['severity']==='warning');}export const TOOL_CONSTRAINTS_VERSION=0x1;
|