@wowok/agent-mcp 3.3.6 → 3.3.7
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/eval-order.js +1 -1
- package/dist/chain-semantics/field-capability.js +1 -1
- package/dist/chain-semantics/fund-flow.js +1 -1
- package/dist/chain-semantics/guard-verbs.js +1 -1
- package/dist/chain-semantics/object-graph.js +1 -1
- package/dist/composition/audit.js +1 -1
- package/dist/composition/compile.d.ts +2 -1
- package/dist/composition/compile.js +1 -1
- package/dist/composition/materialize.js +1 -1
- package/dist/data/projection/facets.spec.js +1 -1
- package/dist/evaluation/match-policy.d.ts +30 -6
- package/dist/evaluation/match-policy.js +1 -1
- package/dist/evaluation/match-policy.spec.js +1 -1
- package/dist/extensions/business-modules.js +1 -1
- package/dist/harness/recover.js +1 -1
- package/dist/intent/types.d.ts +1 -1
- package/dist/intent/types.js +1 -1
- package/dist/keeper/detectors.d.ts +3 -0
- package/dist/keeper/detectors.js +1 -1
- package/dist/keeper/keeper.spec.js +1 -1
- package/dist/knowledge/allocator-rail-verifier.js +1 -1
- package/dist/knowledge/audit-rules.js +1 -1
- package/dist/knowledge/baselines/rules/plan.json +97 -2
- package/dist/knowledge/builtin-templates.d.ts +6 -1
- package/dist/knowledge/builtin-templates.js +1 -1
- package/dist/knowledge/event-semantics.js +1 -1
- package/dist/knowledge/guard-design-patterns.js +1 -1
- package/dist/knowledge/guard-templates.d.ts +1 -1
- package/dist/knowledge/guard-templates.js +1 -1
- package/dist/knowledge/industry-generalizer.d.ts +4 -0
- package/dist/knowledge/industry-generalizer.js +1 -1
- package/dist/knowledge/semantic-ir.d.ts +113 -0
- package/dist/knowledge/semantic-ir.js +1 -0
- package/dist/knowledge/strategy-manuals.js +1 -1
- package/dist/knowledge/template-loader.d.ts +34 -0
- package/dist/knowledge/template-loader.js +1 -1
- package/dist/knowledge/template-prose.d.ts +50 -0
- package/dist/knowledge/template-prose.js +1 -0
- package/dist/knowledge/template-registry.js +1 -1
- package/dist/knowledge/template-scanner.d.ts +1 -1
- package/dist/knowledge/template-scanner.js +1 -1
- package/dist/knowledge/tools-reference.js +1 -1
- package/dist/monitor/MonitorLoop.js +1 -1
- package/dist/monitor/normalize.d.ts +1 -1
- package/dist/monitor/normalize.js +1 -1
- package/dist/monitor/types.js +1 -1
- package/dist/playbooks/service-build/business-puzzle.js +1 -1
- package/dist/playbooks/service-build/machine-panorama.js +1 -1
- package/dist/playbooks/service-build/merchant-guide.d.ts +4 -0
- package/dist/playbooks/service-build/merchant-guide.js +1 -1
- package/dist/playbooks/service-build/migration-planner.d.ts +2 -1
- package/dist/playbooks/service-build/migration-planner.js +1 -1
- package/dist/playbooks/service-build/mode-actions.d.ts +7 -0
- package/dist/playbooks/service-build/mode-actions.js +1 -1
- package/dist/playbooks/service-build/object-panorama.d.ts +22 -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/relationship-profile.js +1 -1
- package/dist/playbooks/service-build/reverse-mapping-nk4.spec.js +1 -1
- package/dist/playbooks/service-build/reverse-mapping.d.ts +1 -0
- package/dist/playbooks/service-build/reverse-mapping.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/benchmark-migration/index.d.ts +64 -10
- package/dist/schema/benchmark-migration/index.js +1 -1
- package/dist/schema/call/arbitration.js +1 -1
- package/dist/schema/call/base.d.ts +8 -0
- package/dist/schema/call/bridge.d.ts +2 -0
- package/dist/schema/call/error-codes.d.ts +1 -1
- package/dist/schema/call/error-codes.js +1 -1
- package/dist/schema/call/reward.d.ts +10 -0
- package/dist/schema/call/reward.js +1 -1
- package/dist/schema/call/semantic.js +1 -1
- package/dist/schema/call/service.js +1 -1
- package/dist/schema/common/index.js +1 -1
- package/dist/schema/evaluation/index.d.ts +152 -0
- package/dist/schema/evaluation/index.js +1 -1
- package/dist/schema/goal/index.d.ts +2 -0
- package/dist/schema/goal/planning.d.ts +3 -0
- package/dist/schema/goal/planning.js +1 -1
- package/dist/schema/industry-pack/index.d.ts +62 -0
- package/dist/schema/industry-pack/modes.d.ts +62 -0
- package/dist/schema/industry-pack/modes.js +1 -1
- package/dist/schema/intent-radar/index.d.ts +3 -0
- package/dist/schema/intent-radar/index.js +1 -1
- package/dist/schema/local/index.d.ts +20 -0
- package/dist/schema/local/index.js +1 -1
- package/dist/schema/operations.d.ts +5 -0
- package/dist/schema/query/index.d.ts +145 -47
- package/dist/schema/query/index.js +1 -1
- package/dist/schema/schema-version.js +1 -1
- package/dist/schema-query-impl/index.js +1 -1
- package/dist/schemas/account_operation.output.json +2 -0
- package/dist/schemas/benchmark_migration_operation.output.json +42 -0
- package/dist/schemas/benchmark_migration_operation.schema.json +208 -5
- package/dist/schemas/bridge_operation.output.json +2 -0
- package/dist/schemas/evaluation_operation.output.json +240 -0
- package/dist/schemas/evaluation_operation.schema.json +397 -1
- package/dist/schemas/goal_operation.schema.json +18 -10
- package/dist/schemas/index.json +1 -1
- package/dist/schemas/industry_pack_operation.output.json +86 -2
- package/dist/schemas/industry_pack_operation.schema.json +199 -0
- package/dist/schemas/intent_radar.output.json +2 -0
- package/dist/schemas/intent_radar.schema.json +1 -0
- package/dist/schemas/local_cache_operation.output.json +2 -0
- package/dist/schemas/local_history_operation.output.json +2 -0
- package/dist/schemas/local_info_operation.output.json +2 -0
- package/dist/schemas/local_mark_operation.output.json +2 -0
- package/dist/schemas/onchain_events.output.json +281 -11
- package/dist/schemas/onchain_events.schema.json +5 -1
- package/dist/schemas/onchain_operations.output.json +2 -0
- package/dist/schemas/onchain_operations.schema.json +37 -3
- package/dist/schemas/onchain_operations_arbitration.schema.json +1 -1
- package/dist/schemas/onchain_operations_reward.schema.json +35 -1
- package/dist/schemas/onchain_operations_service.schema.json +1 -1
- package/dist/schemas/query_toolkit.output.json +34 -0
- package/dist/tools/handlers/benchmark-migration.d.ts +1 -0
- package/dist/tools/handlers/benchmark-migration.js +1 -1
- package/dist/tools/handlers/config.js +1 -1
- package/dist/tools/handlers/evaluation.js +1 -1
- package/dist/tools/handlers/evaluation.spec.js +1 -1
- package/dist/tools/handlers/intent-radar.js +1 -1
- package/dist/tools/handlers/messenger.d.ts +1 -0
- package/dist/tools/handlers/messenger.js +1 -1
- package/dist/tools/handlers/onchain.d.ts +1 -0
- package/dist/tools/handlers/onchain.js +1 -1
- package/dist/tools/handlers/query.js +1 -1
- package/dist/tools/handlers/wip.js +1 -1
- package/dist/tools/registry/agent.js +1 -1
- package/dist/tools/registry/query.js +1 -1
- package/dist/tools/wip-verify-ledger.d.ts +14 -0
- package/dist/tools/wip-verify-ledger.js +1 -0
- package/dist/tools/wrap.d.ts +4 -0
- package/dist/tools/wrap.js +1 -1
- package/package.json +2 -2
package/dist/harness/recover.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const RECOVERY_RULES={'insufficient_balance':{'error_code':'insufficient_balance','strategy':'claim_faucet','max_attempts':0x3,'automation':'semi','detail':'1.\x20Testnet:\x20claim\x20WOW\x20from\x20the\x20faucet\x202.\x20Mainnet:\x20transfer\x20ETH/USDT/USDC/WBTC\x20via\x20the\x20ETH\x20mainnet\x20cross-chain\x20bridge\x20(query\x20active\x20EVM\x20account\x20→\x20top\x20up\x20from\x20external\x20wallet\x20→\x20confirm\x20→\x20cross-chain)\x203.\x20Point\x20the\x20user\x20to\x20the\x20live\x20airdrop\x20page\x20(https://wowok.net/airdrop.html)\x20for\x20the\x20current\x20round\x204.\x20Retry\x20original\x20operation.\x20NOTE:\x20this\x20rule\x20is\x20for\x20the\x20SIGNING\x20ACCOUNT\x27s\x20wallet/gas\x20only\x20—\x20an\x20on-chain\x20POOL\x20shortage\x20(reward/allocation)\x20classifies\x20as\x20pool_shortage,\x20never\x20here','user_prompt':'Insufficient\x20balance\x20for\x20gas\x20or\x20operation.\x20How\x20to\x20obtain\x20WOW\x20tokens:\x20(1)\x20Testnet\x20—\x20claim\x20WOW\x20from\x20the\x20faucet\x20(https://faucet.testnet.wowok.net);\x20all\x20merchant\x20and\x20order\x20testing\x20can\x20use\x20WOW\x20as\x20the\x20payment\x20token.\x20(2)\x20Mainnet\x20—\x20transfer\x20ETH\x20/\x20USDT\x20/\x20USDC\x20/\x20WBTC\x20via\x20the\x20ETH\x20mainnet\x20cross-chain\x20bridge:\x20first\x20query\x20the\x20active\x20EVM\x20account\x20(bridge_operation\x20query_active_evm_account,\x20auto-generated\x20on\x20first\x20use),\x20then\x20transfer\x20from\x20an\x20external\x20wallet\x20(e.g.\x20MetaMask)\x20to\x20that\x20address,\x20confirm\x20the\x20balance\x20arrived,\x20and\x20cross-chain\x20to\x20WOW\x20mainnet\x20(bridge_operation\x20cross_chain_evm_to_wow).\x20(3)\x20WOW\x20airdrop:\x20current\x20round\x20status,\x20pool\x20and\x20eligibility\x20are\x20published\x20live\x20at\x20https://wowok.net/airdrop.html\x20(referral:\x20https://wowok.net/refer.html)\x20—\x20open\x20that\x20page\x20rather\x20than\x20assuming\x20a\x20round\x20is\x20live\x20or\x20closed.\x20Query\x20wowok_buildin_info\x20with\x20info=\x27funding\x20guidance\x27\x20for\x20the\x20canonical\x20funding\x20guidance.'},'pool_shortage':{'error_code':'pool_shortage','strategy':'adjust_params','max_attempts':0x1,'automation':'semi','detail':'An\x20on-chain\x20POOL\x20cannot\x20cover\x20the\x20operation\x20(reward.move:243\x20abort\x206\x20/\x20'+'allocation.move:509\x20abort\x207)\x20—\x20a\x20pool\x20funding\x20problem,\x20NOT\x20the\x20caller\x27s\x20wallet;\x20a\x20faucet\x20claim\x20will\x20NOT\x20help\x20and\x20re-sending\x20the\x20rail\x20unchanged\x20changes\x20nothing.\x201.\x20Reward\x20pool:\x20the\x20reward\x20ISSUER\x20tops\x20it\x20up\x20with\x20reward\x20coin_add\x20(permission\x20153)\x20—\x20the\x20claim\x20key\x20slot\x20is\x20written\x20BEFORE\x20the\x20balance\x20assert\x20and\x20the\x20abort\x20rolls\x20it\x20back,\x20so\x20NOTHING\x20was\x20consumed;\x20the\x20identical\x20claim\x20succeeds\x20after\x20the\x20top-up\x20(mainnet-proven,\x20T14).\x202.\x20Allocation\x20pool:\x20the\x20payer\x20side\x20funds\x20the\x20order/allocation\x20first\x20(order\x20renew,\x20payment\x20create\x20into\x20the\x20allocation),\x20then\x20re-runs\x20the\x20rail;\x20if\x20the\x20pool\x20is\x20drained\x20because\x20the\x20rail\x20ALREADY\x20paid\x20(balance\x200,\x20once-slot\x20consumed),\x20verify\x20via\x20the\x20Payment\x20record\x20instead\x20of\x20retrying.\x203.\x20As\x20the\x20BUYER:\x20report\x20the\x20shortage\x20to\x20the\x20merchant\x20—\x20never\x20fund\x20a\x20pool\x20you\x20do\x20not\x20own','user_prompt':'The\x20on-chain\x20pool\x20backing\x20this\x20operation\x20is\x20short\x20of\x20funds.\x20The\x20pool\x27s\x20owner\x20must\x20top\x20it\x20up\x20(reward\x20coin_add\x20/\x20allocation\x20funding)\x20—\x20a\x20faucet\x20claim\x20will\x20not\x20help.\x20As\x20the\x20buyer,\x20ask\x20the\x20merchant\x20to\x20fund\x20the\x20pool.'},'stock_exhausted':{'error_code':'stock_exhausted','strategy':'adjust_params','max_attempts':0x1,'automation':'semi','detail':'Merchant-side\x20inventory\x20shortfall\x20(Move\x20service:16\x20E_STOCK_NOT_ENOUGH)\x20—\x20NOT\x20a\x20buyer\x20balance\x20problem,\x20so\x20a\x20faucet\x20claim\x20will\x20NOT\x20help.\x201.\x20Reduce\x20the\x20purchase\x20quantity\x20to\x20the\x20item\x27s\x20remaining\x20stock\x202.\x20Pick\x20another\x20sale\x20item\x203.\x20Ask\x20the\x20merchant\x20to\x20restock,\x20then\x20retry','user_prompt':'The\x20sale\x20item\x27s\x20stock\x20is\x20exhausted\x20for\x20the\x20requested\x20quantity.\x20Reduce\x20the\x20quantity,\x20choose\x20another\x20item,\x20or\x20ask\x20the\x20merchant\x20to\x20restock.'},'sale_suspended':{'error_code':'sale_suspended','strategy':'adjust_params','max_attempts':0x1,'automation':'semi','detail':'The\x20merchant\x20suspended\x20this\x20sale\x20item\x20(Move\x20service:34\x20E_SALE_SUSPENDED).\x201.\x20Pick\x20another\x20(non-suspended)\x20item\x202.\x20Contact\x20the\x20merchant\x20to\x20resume\x20the\x20sale,\x20then\x20retry','user_prompt':'The\x20sale\x20item\x20is\x20suspended\x20by\x20the\x20merchant.\x20Please\x20choose\x20another\x20item\x20or\x20contact\x20the\x20merchant.'},'discount_invalid':{'error_code':'discount_invalid','strategy':'adjust_params','max_attempts':0x1,'automation':'semi','detail':'The\x20discount\x20is\x20outside\x20its\x20[time_start,\x20time_end]\x20validity\x20window\x20(Move\x20service:35\x20E_DISCOUNT_TIME_INVALID).\x201.\x20Retry\x20without\x20the\x20discount\x202.\x20Ask\x20the\x20merchant\x20for\x20a\x20fresh\x20discount,\x20then\x20retry','user_prompt':'The\x20discount\x20is\x20not\x20valid\x20at\x20the\x20current\x20time\x20(outside\x20its\x20validity\x20window).\x20Buy\x20without\x20the\x20discount\x20or\x20ask\x20the\x20merchant\x20for\x20a\x20new\x20one.'},'rate_limit':{'error_code':'rate_limit','strategy':'retry','max_attempts':0x5,'automation':'full','detail':'Rate\x20limit\x20hit\x20(HTTP\x20429).\x20Exponential\x20backoff\x20retry:\x202s\x20/\x204s\x20/\x208s\x20/\x2016s\x20/\x2032s.\x20Avoid\x20parallel\x20calls\x20while\x20the\x20limit\x20window\x20is\x20active.'},'gas_exceeded':{'error_code':'gas_exceeded','strategy':'adjust_params','max_attempts':0x3,'automation':'semi','detail':'Gas\x20budget\x20exceeded.\x201.\x20Increase\x20the\x20gas_budget\x20parameter\x202.\x20Reduce\x20the\x20operation\x20size\x20(fewer\x20objects\x20per\x20transaction)\x203.\x20Retry\x20the\x20original\x20operation','user_prompt':'Gas\x20budget\x20exceeded.\x20Increase\x20the\x20gas\x20budget\x20or\x20reduce\x20the\x20operation\x20size,\x20then\x20retry.'},'insufficient_gas':{'error_code':'insufficient_gas','strategy':'adjust_params','max_attempts':0x1,'automation':'semi','detail':'Gas\x20exhausted\x20—\x20the\x20transaction\x20failed\x20deterministically\x20and\x20did\x20NOT\x20commit\x20on-chain\x20(no\x20state\x20changed;\x20commit-state\x20verification\x20is\x20NOT\x20needed).\x201.\x20Raise\x20the\x20gas_budget\x20parameter\x20above\x20the\x20failed\x20transaction\x27s\x20gas_used\x202.\x20If\x20the\x20account\x20balance\x20cannot\x20cover\x20any\x20budget,\x20fund\x20the\x20signing\x20account\x20with\x20gas\x20tokens\x20first\x203.\x20Resubmit\x20as\x20a\x20FRESH\x20call\x20—\x20do\x20NOT\x20replay\x20the\x20same\x20transaction','user_prompt':'The\x20transaction\x20ran\x20out\x20of\x20gas\x20and\x20did\x20not\x20commit\x20on-chain.\x20Increase\x20the\x20gas\x20budget\x20(or\x20fund\x20the\x20account\x20with\x20gas)\x20and\x20submit\x20a\x20fresh\x20transaction\x20—\x20retrying\x20unchanged\x20will\x20fail\x20the\x20same\x20way.'},'bcs_error':{'error_code':'bcs_error','strategy':'adjust_params','max_attempts':0x2,'automation':'semi','detail':'BCS\x20serialization/deserialization\x20error\x20—\x20a\x20parameter\x20does\x20not\x20match\x20the\x20expected\x20type/structure.\x201.\x20Query\x20the\x20operation\x20schema\x20(schema_query)\x202.\x20Fix\x20the\x20offending\x20parameter\x20type\x20(e.g.\x20BigInt\x20vs\x20number,\x20vector\x20element\x20type)\x203.\x20Retry','user_prompt':'A\x20parameter\x20failed\x20serialization.\x20Check\x20the\x20parameter\x20types\x20against\x20the\x20schema\x20and\x20retry.'},'signature_error':{'error_code':'signature_error','strategy':'switch_account','max_attempts':0x2,'automation':'semi','detail':'Signature\x20verification\x20failed.\x201.\x20Verify\x20the\x20account\x20is\x20not\x20suspended\x202.\x20Check\x20the\x20network\x20matches\x20the\x20account\x27s\x203.\x20Switch\x20to\x20a\x20healthy\x20account\x20and\x20retry','user_prompt':'Signature\x20verification\x20failed.\x20The\x20account\x20may\x20be\x20suspended\x20or\x20misconfigured.\x20Switch\x20accounts\x20or\x20check\x20the\x20configuration\x20and\x20retry.'},'config_error':{'error_code':'config_error','strategy':'escalate_human','max_attempts':0x1,'automation':'manual','detail':'Local\x20configuration\x20error\x20(network\x20not\x20specified,\x20persistent\x20storage\x20not\x20set).\x201.\x20Show\x20the\x20user\x20which\x20configuration\x20is\x20missing\x202.\x20Guide\x20the\x20user\x20through\x20the\x20account_operation/config\x20setup\x203.\x20Retry\x20after\x20the\x20user\x20fixes\x20it','user_prompt':'Local\x20configuration\x20is\x20incomplete.\x20Please\x20finish\x20the\x20account/network\x20setup\x20and\x20retry.'},'wip_verification_failed':{'error_code':'wip_verification_failed','strategy':'adjust_params','max_attempts':0x2,'automation':'semi','detail':'WIP\x20file\x20not\x20publicly\x20reachable\x20/\x20hash\x20mismatch.\x201.\x20Upload\x20via\x20the\x20wip\x20storage\x20service\x20(wip_file\x20type=\x27upload\x27\x20—\x20official\x20free\x20store\x20or\x20storage=\x27custom\x27)\x202.\x20Or\x20deploy\x20to\x20a\x20public\x20URL\x20(GitHub\x20Pages\x20/\x20IPFS\x20/\x20own\x20site)\x203.\x20Update\x20the\x20sale\x27s\x20wip\x20URL\x204.\x20Re-run\x20the\x20operation','user_prompt':'The\x20WIP\x20file\x20could\x20not\x20be\x20verified\x20from\x20a\x20public\x20URL.\x20Upload\x20it\x20with\x20wip_file\x20type=\x27upload\x27\x20(official\x20free\x20store\x20or\x20your\x20own\x20service)\x20or\x20deploy\x20it\x20(GitHub\x20Pages\x20/\x20IPFS),\x20update\x20the\x20sale\x27s\x20WIP\x20URL,\x20and\x20retry.'},'wip_storage_unavailable':{'error_code':'wip_storage_unavailable','strategy':'retry','max_attempts':0x3,'automation':'full','detail':'Transient\x20wip\x20storage\x20transport\x20failure.\x201.\x20Retry\x20the\x20same\x20request\x20with\x20bounded\x20backoff\x202.\x20Large\x20WIP\x20files\x20are\x20network-sensitive:\x20compress\x20images\x20before\x20generate\x20(each\x20image\x20<=\x202MB,\x20total\x20<=\x2010MB)\x203.\x20Check\x20connectivity\x20to\x20the\x20storage\x20base\x20URL\x20if\x20retries\x20keep\x20failing','user_prompt':'The\x20wip\x20storage\x20request\x20failed\x20due\x20to\x20a\x20network\x20problem.\x20Retry\x20the\x20upload;\x20if\x20it\x20keeps\x20failing,\x20reduce\x20the\x20file\x20size\x20or\x20check\x20connectivity.'},'wip_storage_rejected':{'error_code':'wip_storage_rejected','strategy':'adjust_params','max_attempts':0x1,'automation':'semi','detail':'WIP\x20storage\x20service\x20rejected\x20the\x20request\x20(HTTP\x204xx\x20—\x20deterministic\x20client-side\x20fault,\x20retrying\x20unchanged\x20fails\x20identically).\x20400:\x20malformed\x20body\x20or\x20failed\x20WIP\x20validation\x20—\x20re-generate\x20via\x20wip_file\x20type=\x27generate\x27\x20401:\x20re-sign\x20with\x20a\x20fresh\x20nonce\x20inside\x20the\x20timestamp\x20window\x20403:\x20check\x20storage\x20service\x20configuration\x20404:\x20file\x20does\x20not\x20exist\x20—\x20re-upload\x20409:\x20quota\x20—\x20delete\x20old\x20files\x20via\x20wip_file\x20type=\x27list\x27\x20then\x20delete\x20413:\x20compress\x20images\x20(each\x20<=\x202MB,\x20total\x20<=\x2010MB)\x20and\x20regenerate','user_prompt':'The\x20WIP\x20storage\x20service\x20rejected\x20the\x20request\x20(HTTP\x204xx).\x20Fix\x20the\x20specific\x20fault\x20(re-generate/re-sign/re-upload\x20per\x20the\x20status\x20code)\x20and\x20retry\x20—\x20do\x20not\x20retry\x20unchanged.'},'network_error':{'error_code':'network_error','strategy':'retry','max_attempts':0x5,'automation':'full','detail':'Transport\x20failure\x20(timeout\x20/\x20connection\x20reset\x20/\x20RPC\x20unreachable\x20/\x20HTTP\x205xx\x20gateway\x20error).\x20Exponential\x20backoff\x20retry:\x201s\x20/\x202s\x20/\x204s\x20/\x208s\x20/\x2016s.\x20Switch\x20RPC\x20node\x20if\x20available.\x20READS:\x20a\x20plain\x20retry\x20is\x20safe.\x20FUND-MOVING\x20WRITES:\x20before\x20any\x20resubmission,\x20verify\x20whether\x20the\x20previous\x20attempt\x20landed\x20(query\x20the\x20reported\x20digest\x20directly,\x20or\x20the\x20expected\x20object\x20via\x20the\x20sender\x27s\x20recent\x20on-chain\x20objects\x20/\x20onchain_events)\x20—\x20if\x20it\x20landed,\x20ADOPT\x20it\x20and\x20stop;\x20a\x20blind\x20backoff\x20retry\x20of\x20a\x20landed\x20write\x20moves\x20the\x20funds\x20a\x20second\x20time.'},'submission_unknown':{'error_code':'submission_unknown','strategy':'query_and_retry','max_attempts':0x2,'automation':'semi','detail':'Transport-level\x20failure\x20after\x20the\x20request\x20left\x20the\x20client\x20—\x20the\x20submission\x20state\x20is\x20UNKNOWN\x20and\x20the\x20transaction\x20may\x20already\x20be\x20committed.\x20NEVER\x20auto-retry\x20a\x20write\x20here.\x201.\x20Verify\x20commit\x20state\x20on-chain:\x20query_toolkit\x20for\x20the\x20object\x20this\x20call\x20would\x20create/modify\x20(resolve\x20the\x20reference\x20from\x20the\x20call\x27s\x20own\x20arguments),\x20or\x20onchain_events\x20for\x20the\x20sender\x27s\x20recent\x20transactions.\x202.\x20If\x20the\x20expected\x20object\x20EXISTS,\x20adopt\x20it\x20and\x20continue\x20the\x20workflow\x20(the\x20operation\x20succeeded\x20despite\x20the\x20transport\x20error).\x203.\x20If\x20confirmed\x20ABSENT,\x20resubmit\x20the\x20SAME\x20call\x20once\x20—\x20for\x20a\x20FIRST-EVER\x20transaction\x20on\x20a\x20fresh\x20account\x20make\x20that\x20resubmission\x20with\x20env.no_auto_register=true\x20and\x20SAY\x20SO\x20(the\x20SDK\x20silently\x20appends\x20an\x20entity\x20registration\x20to\x20a\x20first\x20business\x20call;\x20if\x20that\x20appended\x20leg\x20was\x20the\x20failing\x20leg\x20the\x20skip\x20lets\x20the\x20call\x20through\x20—\x20ziroom-mn-261013\x20live\x20case;\x20if\x20the\x20resubmission\x20aborts,\x20the\x20envelope\x20now\x20names\x20the\x20abort\x20—\x20re-enable\x20auto\x20registration\x20and\x20retry).\x204.\x20If\x20the\x20reported\x20digest\x20does\x20not\x20resolve\x20or\x20the\x20failure\x20repeats,\x20STOP\x20looping\x20on\x20digest\x20checks\x20and\x20re-run\x20the\x20SAME\x20call\x20with\x20env.dry_run=true\x20—\x20the\x20simulation\x20surfaces\x20the\x20real\x20failure\x20(exact\x20Move\x20abort)\x20without\x20gas\x20or\x20duplicate\x20risk.\x205.\x20Reads\x20are\x20idempotent\x20—\x20retry\x20immediately.\x206.\x20M-K2\x20replay\x20discipline:\x20a\x20FAILED\x20receipt\x20is\x20final\x20—\x20its\x20digest\x20is\x20consumed\x20and\x20replaying\x20the\x20same\x20bytes\x20returns\x20the\x20same\x20failure\x20forever;\x20fix\x20the\x20cause\x20(usually\x20funding)\x20and\x20build\x20a\x20FRESH\x20transaction.\x20Live\x20mainnet\x20incident\x20behind\x20this\x20rule:\x20an\x20order_new\x20-32603\x20\x27did\x20not\x20complete\x27\x20had\x20committed;\x20the\x20blind\x20retry\x20created\x20a\x20second\x20order\x20with\x20a\x20second\x20full\x20escrow\x20and\x20a\x20second\x20stock\x20decrement','user_prompt':'The\x20request\x20failed\x20at\x20transport\x20level\x20but\x20may\x20have\x20already\x20been\x20committed\x20on-chain.\x20Verify\x20whether\x20the\x20expected\x20object\x20exists\x20(query\x20it)\x20before\x20any\x20retry\x20—\x20a\x20blind\x20retry\x20can\x20duplicate\x20the\x20operation\x20(double\x20escrow).\x20For\x20read\x20operations,\x20a\x20plain\x20retry\x20is\x20safe.'},'transaction_expired':{'error_code':'transaction_expired','strategy':'retry','max_attempts':0x3,'automation':'full','detail':'The\x20transaction\x20expired\x20before\x20execution\x20(epoch\x20boundary\x20or\x20validator/gateway\x20outage)\x20—\x20it\x20did\x20NOT\x20land\x20and\x20nothing\x20was\x20committed.\x20Bounded\x20backoff\x20retry:\x2010s\x20/\x2030s\x20/\x2060s,\x20resubmit\x20the\x20SAME\x20call\x20unchanged.\x20If\x20a\x20dry_run\x20passes\x20while\x20the\x20real\x20call\x20keeps\x20failing,\x20the\x20fault\x20is\x20chain-side\x20—\x20wait\x20it\x20out.\x20Verify\x20with\x20onchain_events\x20if\x20unsure.'},'guard_rejected':{'error_code':'guard_rejected','strategy':'fill_submission','max_attempts':0x2,'automation':'semi','detail':'1.\x20Parse\x20Guard\x20table\x20structure\x202.\x20If\x20the\x20Guard\x20defines\x20submission\x20items,\x20fill\x20them\x20and\x20resubmit\x20with\x20call_with_submission\x203.\x20If\x20it\x20defines\x20none,\x20the\x20rule\x20evaluated\x20false\x20—\x20typical\x20causes:\x20a\x20TIME\x20WINDOW\x20(Clock\x20deadline/opening\x20comparison\x20—\x20this\x20call\x20may\x20sit\x20outside\x20the\x20window,\x20and\x20a\x20mis-oriented\x20comparison\x20inverts\x20it:\x20everything\x20inside\x20rejected,\x20everything\x20after\x20admitted)\x20or\x20an\x20IDENTITY\x20condition\x20(signer/state\x20checks\x20—\x20the\x20caller\x20may\x20not\x20be\x20the\x20address\x20the\x20rule\x20expects);\x20adjust\x20the\x20call\x27s\x20parameters\x20or\x20change\x20the\x20Guard\x20(docs#40)\x204.\x20When\x20the\x20failure\x20is\x20passport\x20E_VERIFY_FAILED\x20and\x20a\x20submission\x20was\x20supplied,\x20the\x20response\x20appends\x20a\x20\x27Guard\x20diagnosis\x20(dry-run)\x27\x20line\x20naming\x20the\x20first\x20failing\x20impact\x20guard\x20—\x20fix\x20that\x20guard\x20first\x205.\x20A\x20TIME-window\x20rejection\x20may\x20simply\x20be\x20EARLY:\x20re-run\x20the\x20SAME\x20call\x20with\x20env.dry_run=true\x20to\x20probe\x20the\x20window\x20for\x20free\x20(guard\x20rejections\x20do\x20NOT\x20consume\x20the\x20total\x20retry\x20budget;\x20only\x20the\x20per-code\x20cap\x20of\x202\x20applies)','user_prompt':'Guard\x20verification\x20rejected.\x20If\x20the\x20Guard\x20defines\x20submission\x20items,\x20fill\x20in\x20the\x20required\x20submission\x20data\x20and\x20resubmit;\x20if\x20it\x20defines\x20none,\x20the\x20Guard\x20rule\x20evaluated\x20false\x20—\x20the\x20usual\x20causes\x20are\x20a\x20time\x20window\x20(this\x20call\x20may\x20be\x20outside\x20the\x20Clock\x20deadline/opening\x20window)\x20or\x20an\x20identity\x20condition\x20(the\x20caller\x20is\x20not\x20the\x20address\x20the\x20rule\x20expects);\x20adjust\x20this\x20call\x27s\x20parameters\x20or\x20change\x20the\x20Guard\x20rule.\x20When\x20the\x20response\x20includes\x20a\x20\x27Guard\x20diagnosis\x20(dry-run)\x27\x20line,\x20it\x20names\x20the\x20first\x20failing\x20impact\x20guard\x20—\x20address\x20that\x20guard\x20first.\x20A\x20time-window\x20rejection\x20may\x20simply\x20be\x20early:\x20probe\x20the\x20window\x20with\x20env.dry_run=true\x20(free\x20—\x20guard\x20rejections\x20do\x20not\x20consume\x20the\x20total\x20retry\x20budget).'},'time_lock_not_elapsed':{'error_code':'time_lock_not_elapsed','strategy':'wait_and_retry','max_attempts':0x1,'automation':'semi','detail':'1.\x20Verify\x20Service\x20is\x20paused\x20(bPaused=true).\x20If\x20not,\x20submit\x20pause=true\x20first.\x202.\x20Wait\x20until\x20paused_time\x20+\x20setting_lock_duration\x20<=\x20current\x20clock.\x203.\x20Retry\x20the\x20original\x20operation.\x20Do\x20NOT\x20recreate\x20the\x20object.','user_prompt':'Service\x20setting_lock_duration\x20has\x20not\x20elapsed\x20since\x20the\x20Service\x20was\x20paused.\x20Please\x20pause\x20the\x20Service\x20if\x20it\x20is\x20not\x20already\x20paused,\x20wait\x20for\x20the\x20lock\x20duration\x20to\x20elapse,\x20then\x20retry.'},'immutable_violation':{'error_code':'immutable_violation','strategy':'recreate','max_attempts':0x1,'automation':'semi','detail':'1.\x20Stop\x20modification\x20attempt\x202.\x20Evaluate\x20creating\x20a\x20new\x20object\x20as\x20replacement\x203.\x20Re-plan\x20affected\x20phases','user_prompt':'Cannot\x20modify\x20an\x20immutable\x20object.\x20A\x20new\x20object\x20must\x20be\x20created\x20as\x20a\x20replacement.\x20Confirm\x20to\x20proceed\x20with\x20recreation.'},'permission_denied':{'error_code':'permission_denied','strategy':'switch_account','max_attempts':0x2,'automation':'semi','detail':'1.\x20Query\x20object\x27s\x20permission_guard\x202.\x20List\x20accounts\x20with\x20permission\x203.\x20Switch\x20account\x20or\x20prompt\x20user\x20to\x20add\x20permission','user_prompt':'Current\x20account\x20lacks\x20permission\x20for\x20this\x20operation.\x20Switch\x20to\x20an\x20authorized\x20account\x20or\x20update\x20the\x20Permission\x20object.'},'object_not_found':{'error_code':'object_not_found','strategy':'query_and_retry','max_attempts':0x3,'automation':'semi','detail':'1.\x20Verify\x20the\x20referenced\x20name/ID\x20spelling\x20(local_mark_list)\x20and\x20that\x20the\x20object\x20exists\x20on\x20the\x20current\x20network\x202.\x20If\x20recently\x20created,\x20re-query\x20the\x20object\x20(may\x20be\x20sync\x20delay)\x203.\x20If\x20truly\x20absent,\x20search\x20for\x20similar\x20objects\x204.\x20Prompt\x20user\x20to\x20reselect','user_prompt':'Referenced\x20object\x20not\x20found.\x20First\x20verify\x20the\x20name/ID\x20spelling\x20and\x20that\x20the\x20object\x20exists\x20on\x20the\x20current\x20network;\x20if\x20it\x20was\x20created\x20recently,\x20this\x20may\x20be\x20a\x20synchronization\x20delay\x20—\x20retry.\x20If\x20the\x20issue\x20persists,\x20please\x20select\x20a\x20valid\x20object.'},'state_conflict':{'error_code':'state_conflict','strategy':'adjust_params','max_attempts':0x2,'automation':'full','detail':'1.\x20Query\x20object\x27s\x20current\x20true\x20state\x202.\x20Update\x20ODG\x20status\x20annotations\x203.\x20Adjust\x20subsequent\x20operations\x20(e.g.,\x20skip\x20completed\x20steps)'},'invalid_parameter':{'error_code':'invalid_parameter','strategy':'adjust_params','max_attempts':0x2,'automation':'semi','detail':'1.\x20Query\x20the\x20relevant\x20schema\x202.\x20Auto-fix\x20obvious\x20errors\x20(e.g.,\x20BigInt\x20vs\x20string)\x203.\x20If\x20unfixable,\x20prompt\x20user','user_prompt':'Parameter\x20validation\x20failed.\x20Please\x20check\x20the\x20parameter\x20types\x20and\x20values\x20against\x20the\x20schema\x20and\x20retry.'},'move_abort_unmapped':{'error_code':'move_abort_unmapped','strategy':'stop','max_attempts':0x1,'automation':'manual','detail':'The\x20chain\x27s\x20business\x20logic\x20aborted\x20and\x20the\x20(module,\x20abort\x20code)\x20pair\x20has\x20no\x20local\x20mapping.\x20Read\x20the\x20module\x20and\x20abort\x20code\x20from\x20move_abort_info\x20/\x20the\x20message\x20(rendered\x20as\x20\x27abort\x20(N)\x27),\x20resolve\x20their\x20meaning\x20from\x20the\x20module\x27s\x20documentation\x20or\x20the\x20wowok-tools\x20Skill,\x20fix\x20the\x20business\x20cause,\x20and\x20issue\x20a\x20NEW\x20call.\x20Do\x20NOT\x20restart\x20the\x20server\x20and\x20do\x20NOT\x20retry\x20the\x20identical\x20call\x20—\x20it\x20aborts\x20deterministically.','user_prompt':'The\x20operation\x20was\x20rejected\x20by\x20the\x20chain\x27s\x20business\x20logic\x20and\x20its\x20abort\x20code\x20is\x20not\x20mapped\x20locally.\x20The\x20module\x20name\x20and\x20abort\x20code\x20in\x20the\x20error\x20are\x20authoritative\x20—\x20review\x20them\x20(and\x20the\x20object\x20state\x20via\x20query_toolkit)\x20before\x20adjusting\x20anything.'},'missing_data':{'error_code':'missing_data','strategy':'adjust_params','max_attempts':0x2,'automation':'semi','detail':'A\x20guard\x20rule\x20read\x20a\x20keyed\x20table\x20row\x20that\x20does\x20NOT\x20exist\x20(repository.data\x20/\x20oracle\x20entry)\x20and\x20the\x20verifier\x20surfaced\x20it\x20as\x20a\x20location-only\x20fault\x20inside\x20the\x20passport\x20module\x20—\x20no\x20abort\x20code,\x20because\x20the\x20framework\x20cannot\x20express\x20\x27row\x20absent\x27\x20as\x20an\x20abort.\x20This\x20is\x20a\x20DATA\x20problem:\x201.\x20Identify\x20the\x20repository\x20and\x20key\x20the\x20guard\x20rule\x20reads\x20(guard2file\x20/\x20analyze_guard_semantics\x20on\x20the\x20guard\x20source)\x202.\x20Have\x20the\x20row\x27s\x20producer\x20write\x20it\x20(e.g.\x20an\x20oracle\x20timestamp\x20like\x20checkin_ts),\x20or\x20add\x20it\x20with\x20repository\x20data_add\x20(data_add.name\x20must\x20match\x20a\x20policy\x20rule\x20name)\x203.\x20Retry\x20the\x20SAME\x20call\x20unchanged\x20—\x20a\x20dry_run\x20that\x20turns\x20clean\x20after\x20the\x20row\x20exists\x20confirms\x20the\x20diagnosis','user_prompt':'A\x20guard\x20rule\x20references\x20a\x20data\x20row\x20that\x20has\x20not\x20been\x20written\x20yet\x20(location-only\x20fault\x20inside\x20the\x20passport\x20module\x20—\x20NOT\x20a\x20network\x20problem).\x20Identify\x20the\x20repository\x20row\x20the\x20guard\x20expects\x20(guard2file\x20/\x20analyze_guard_semantics),\x20write\x20it\x20with\x20repository\x20data_add\x20(or\x20let\x20its\x20producer\x20write\x20it),\x20then\x20retry.'},'state_not_visible':{'error_code':'state_not_visible','strategy':'wait_and_retry','max_attempts':0x3,'automation':'full','detail':'The\x20state\x20this\x20call\x20needs\x20was\x20JUST\x20written\x20and\x20is\x20not\x20yet\x20visible\x20to\x20reads\x20(write-to-visibility\x20window),\x20or\x20it\x20does\x20not\x20exist\x20at\x20all.\x201.\x20If\x20a\x20write\x20on\x20this\x20order/machine\x20committed\x20within\x20the\x20last\x20few\x20seconds,\x20wait\x20500ms\x20(doubling\x20each\x20attempt)\x20and\x20replay\x20the\x20SAME\x20call\x20UNCHANGED\x20—\x20NEVER\x20edit\x20parameters\x20to\x20\x27fix\x27\x20a\x20visibility\x20window;\x20an\x20aborted\x20call\x20never\x20landed,\x20so\x20the\x20replay\x20cannot\x20double-spend.\x202.\x20If\x20the\x20fault\x20persists\x20past\x20~3\x20attempts\x20(or\x20nothing\x20was\x20just\x20written),\x20the\x20state\x20is\x20deterministically\x20ABSENT\x20—\x20stop\x20retrying:\x20for\x20a\x20forward-info\x20miss\x20query\x20the\x20Machine\x27s\x20node\x20table\x20(onchain_table_data\x20onchain_table_item_machine_node)\x20and\x20use\x20an\x20existing\x20node/next_node/forward\x20triple;\x20for\x20a\x20guard-read\x20repository\x20row\x20follow\x20the\x20missing_data\x20path\x20(write\x20the\x20row).','user_prompt':'A\x20just-committed\x20write\x20is\x20not\x20visible\x20to\x20this\x20read\x20yet.\x20The\x20same\x20call\x20will\x20be\x20replayed\x20after\x20a\x20short\x20wait\x20—\x20no\x20parameter\x20change\x20is\x20needed.\x20If\x20it\x20keeps\x20failing,\x20the\x20required\x20state\x20is\x20genuinely\x20missing\x20and\x20must\x20be\x20created\x20first.'},'unknown':{'error_code':'unknown','strategy':'escalate_human','max_attempts':0x1,'automation':'manual','detail':'1.\x20Report\x20full\x20error\x20context\x20to\x20the\x20user\x202.\x20Escalate\x20to\x20human\x20intervention\x203.\x20Flag\x20for\x20error-classification\x20rule\x20addition','user_prompt':'An\x20unclassified\x20error\x20occurred.\x20Please\x20review\x20the\x20error\x20details\x20and\x20contact\x20support\x20if\x20needed.'}};const operationAttempts=new Map();function getAttemptCount(a,b){const c=operationAttempts['get'](a);if(!c)return 0x0;return c['get'](b)??0x0;}function incrementAttempt(a,b){!operationAttempts['has'](a)&&operationAttempts['set'](a,new Map());const c=operationAttempts['get'](a),d=(c['get'](b)??0x0)+0x1;return c['set'](b,d),d;}const BUDGET_EXEMPT_CODES=new Set(['guard_rejected']);function getBudgetAttempts(a){const b=operationAttempts['get'](a);if(!b)return 0x0;let c=0x0;for(const [d,e]of b){if(!BUDGET_EXEMPT_CODES['has'](d))c+=e;}return c;}export function resetAttempts(a){operationAttempts['delete'](a);}export function recover(a,b,c){const d=RECOVERY_RULES[a]??RECOVERY_RULES['unknown'],e=0x5,f=getBudgetAttempts(b),g=getAttemptCount(b,a);if(d['max_attempts']<=0x1||d['strategy']==='stop')return{'strategy':d['strategy'],'should_retry':![],'max_attempts':d['max_attempts'],'current_attempt':g,'adjusted_params':d['adjusted_params'],'user_prompt':d['user_prompt'],'detail':d['detail']};if(f>=e)return{'strategy':'stop','should_retry':![],'max_attempts':e,'current_attempt':f,'detail':'Total\x20retry\x20limit\x20('+e+')\x20reached\x20for\x20operation\x20'+b+'.\x20Escalating\x20to\x20human\x20intervention.\x20Attempts\x20recorded\x20for\x20this\x20operation\x20id:\x20'+([...(operationAttempts['get'](b)??new Map())['entries']()]['map'](([j,k])=>j+':'+k)['join'](',\x20')||'none')+'.','user_prompt':'Maximum\x20retry\x20attempts\x20reached.\x20Manual\x20intervention\x20required.'};if(g>=d['max_attempts'])return{'strategy':'escalate_human','should_retry':![],'max_attempts':d['max_attempts'],'current_attempt':g,'detail':'Per-error-code\x20retry\x20limit\x20('+d['max_attempts']+')\x20reached\x20for\x20'+a+'.\x20Escalating\x20to\x20human.','user_prompt':'Recovery\x20attempts\x20for\x20'+a+'\x20exhausted.\x20Manual\x20intervention\x20required.'};const h=incrementAttempt(b,a),i={'strategy':d['strategy'],'should_retry':d['automation']==='full'||h<d['max_attempts'],'max_attempts':d['max_attempts'],'current_attempt':h,'adjusted_params':d['adjusted_params'],'user_prompt':d['user_prompt'],'detail':d['detail']};return i['should_retry']&&c?.['retryable']===![]&&a!=='guard_rejected'&&d['strategy']!=='fill_submission'&&d['strategy']!=='query_and_retry'&&(i['should_retry']=![],i['detail']+='\x20NON-RETRYABLE\x20CLASSIFICATION:\x20retrying\x20the\x20IDENTICAL\x20call\x20fails\x20identically\x20—\x20apply\x20the\x20strategy\x20above\x20to\x20fix\x20the\x20cause,\x20then\x20submit\x20a\x20FRESH\x20call.'),i;}export function getBackoffDelay(a){return Math['pow'](0x2,a-0x1)*0x3e8;}
|
|
1
|
+
export const RECOVERY_RULES={'insufficient_balance':{'error_code':'insufficient_balance','strategy':'claim_faucet','max_attempts':0x3,'automation':'semi','detail':'1.\x20Testnet:\x20claim\x20WOW\x20from\x20the\x20faucet\x202.\x20Mainnet:\x20transfer\x20ETH/USDT/USDC/WBTC\x20via\x20the\x20ETH\x20mainnet\x20cross-chain\x20bridge\x20(query\x20active\x20EVM\x20account\x20→\x20top\x20up\x20from\x20external\x20wallet\x20→\x20confirm\x20→\x20cross-chain)\x203.\x20Point\x20the\x20user\x20to\x20the\x20live\x20airdrop\x20page\x20(https://wowok.net/airdrop.html)\x20for\x20the\x20current\x20round\x204.\x20Retry\x20original\x20operation.\x20NOTE:\x20this\x20rule\x20is\x20for\x20the\x20SIGNING\x20ACCOUNT\x27s\x20wallet/gas\x20only\x20—\x20an\x20on-chain\x20POOL\x20shortage\x20(reward/allocation)\x20classifies\x20as\x20pool_shortage,\x20never\x20here','user_prompt':'Insufficient\x20balance\x20for\x20gas\x20or\x20operation.\x20How\x20to\x20obtain\x20WOW\x20tokens:\x20(1)\x20Testnet\x20—\x20claim\x20WOW\x20from\x20the\x20faucet\x20(https://faucet.testnet.wowok.net);\x20all\x20merchant\x20and\x20order\x20testing\x20can\x20use\x20WOW\x20as\x20the\x20payment\x20token.\x20(2)\x20Mainnet\x20—\x20transfer\x20ETH\x20/\x20USDT\x20/\x20USDC\x20/\x20WBTC\x20via\x20the\x20ETH\x20mainnet\x20cross-chain\x20bridge:\x20first\x20query\x20the\x20active\x20EVM\x20account\x20(bridge_operation\x20query_active_evm_account,\x20auto-generated\x20on\x20first\x20use),\x20then\x20transfer\x20from\x20an\x20external\x20wallet\x20(e.g.\x20MetaMask)\x20to\x20that\x20address,\x20confirm\x20the\x20balance\x20arrived,\x20and\x20cross-chain\x20to\x20WOW\x20mainnet\x20(bridge_operation\x20cross_chain_evm_to_wow).\x20(3)\x20WOW\x20airdrop:\x20current\x20round\x20status,\x20pool\x20and\x20eligibility\x20are\x20published\x20live\x20at\x20https://wowok.net/airdrop.html\x20(referral:\x20https://wowok.net/refer.html)\x20—\x20open\x20that\x20page\x20rather\x20than\x20assuming\x20a\x20round\x20is\x20live\x20or\x20closed.\x20Query\x20wowok_buildin_info\x20with\x20info=\x27funding\x20guidance\x27\x20for\x20the\x20canonical\x20funding\x20guidance.'},'pool_shortage':{'error_code':'pool_shortage','strategy':'adjust_params','max_attempts':0x1,'automation':'semi','detail':'An\x20on-chain\x20POOL\x20cannot\x20cover\x20the\x20operation\x20(reward.move:243\x20abort\x206\x20/\x20'+'allocation.move:509\x20abort\x207)\x20—\x20a\x20pool\x20funding\x20problem,\x20NOT\x20the\x20caller\x27s\x20wallet;\x20a\x20faucet\x20claim\x20will\x20NOT\x20help\x20and\x20re-sending\x20the\x20rail\x20unchanged\x20changes\x20nothing.\x201.\x20Reward\x20pool:\x20the\x20reward\x20ISSUER\x20tops\x20it\x20up\x20with\x20reward\x20coin_add\x20(permission\x20153)\x20—\x20the\x20claim\x20key\x20slot\x20is\x20written\x20BEFORE\x20the\x20balance\x20assert\x20and\x20the\x20abort\x20rolls\x20it\x20back,\x20so\x20NOTHING\x20was\x20consumed;\x20the\x20identical\x20claim\x20succeeds\x20after\x20the\x20top-up\x20(mainnet-proven,\x20T14).\x202.\x20Allocation\x20pool:\x20the\x20payer\x20side\x20funds\x20the\x20order/allocation\x20first\x20(order\x20renew,\x20payment\x20create\x20into\x20the\x20allocation),\x20then\x20re-runs\x20the\x20rail;\x20if\x20the\x20pool\x20is\x20drained\x20because\x20the\x20rail\x20ALREADY\x20paid\x20(balance\x200,\x20once-slot\x20consumed),\x20verify\x20via\x20the\x20Payment\x20record\x20instead\x20of\x20retrying.\x203.\x20As\x20the\x20BUYER:\x20report\x20the\x20shortage\x20to\x20the\x20merchant\x20—\x20never\x20fund\x20a\x20pool\x20you\x20do\x20not\x20own','user_prompt':'The\x20on-chain\x20pool\x20backing\x20this\x20operation\x20is\x20short\x20of\x20funds.\x20The\x20pool\x27s\x20owner\x20must\x20top\x20it\x20up\x20(reward\x20coin_add\x20/\x20allocation\x20funding)\x20—\x20a\x20faucet\x20claim\x20will\x20not\x20help.\x20As\x20the\x20buyer,\x20ask\x20the\x20merchant\x20to\x20fund\x20the\x20pool.'},'stock_exhausted':{'error_code':'stock_exhausted','strategy':'adjust_params','max_attempts':0x1,'automation':'semi','detail':'Merchant-side\x20inventory\x20shortfall\x20(Move\x20service:16\x20E_STOCK_NOT_ENOUGH)\x20—\x20NOT\x20a\x20buyer\x20balance\x20problem,\x20so\x20a\x20faucet\x20claim\x20will\x20NOT\x20help.\x201.\x20Reduce\x20the\x20purchase\x20quantity\x20to\x20the\x20item\x27s\x20remaining\x20stock\x202.\x20Pick\x20another\x20sale\x20item\x203.\x20Ask\x20the\x20merchant\x20to\x20restock,\x20then\x20retry','user_prompt':'The\x20sale\x20item\x27s\x20stock\x20is\x20exhausted\x20for\x20the\x20requested\x20quantity.\x20Reduce\x20the\x20quantity,\x20choose\x20another\x20item,\x20or\x20ask\x20the\x20merchant\x20to\x20restock.'},'sale_suspended':{'error_code':'sale_suspended','strategy':'adjust_params','max_attempts':0x1,'automation':'semi','detail':'The\x20merchant\x20suspended\x20this\x20sale\x20item\x20(Move\x20service:34\x20E_SALE_SUSPENDED).\x201.\x20Pick\x20another\x20(non-suspended)\x20item\x202.\x20Contact\x20the\x20merchant\x20to\x20resume\x20the\x20sale,\x20then\x20retry','user_prompt':'The\x20sale\x20item\x20is\x20suspended\x20by\x20the\x20merchant.\x20Please\x20choose\x20another\x20item\x20or\x20contact\x20the\x20merchant.'},'discount_invalid':{'error_code':'discount_invalid','strategy':'adjust_params','max_attempts':0x1,'automation':'semi','detail':'The\x20discount\x20is\x20outside\x20its\x20[time_start,\x20time_end]\x20validity\x20window\x20(Move\x20service:35\x20E_DISCOUNT_TIME_INVALID).\x201.\x20Retry\x20without\x20the\x20discount\x202.\x20Ask\x20the\x20merchant\x20for\x20a\x20fresh\x20discount,\x20then\x20retry','user_prompt':'The\x20discount\x20is\x20not\x20valid\x20at\x20the\x20current\x20time\x20(outside\x20its\x20validity\x20window).\x20Buy\x20without\x20the\x20discount\x20or\x20ask\x20the\x20merchant\x20for\x20a\x20new\x20one.'},'rate_limit':{'error_code':'rate_limit','strategy':'retry','max_attempts':0x5,'automation':'full','detail':'Rate\x20limit\x20hit\x20(HTTP\x20429).\x20Exponential\x20backoff\x20retry:\x202s\x20/\x204s\x20/\x208s\x20/\x2016s\x20/\x2032s.\x20Avoid\x20parallel\x20calls\x20while\x20the\x20limit\x20window\x20is\x20active.'},'gas_exceeded':{'error_code':'gas_exceeded','strategy':'adjust_params','max_attempts':0x3,'automation':'semi','detail':'Gas\x20budget\x20exceeded.\x201.\x20Increase\x20the\x20gas_budget\x20parameter\x202.\x20Reduce\x20the\x20operation\x20size\x20(fewer\x20objects\x20per\x20transaction)\x203.\x20Retry\x20the\x20original\x20operation','user_prompt':'Gas\x20budget\x20exceeded.\x20Increase\x20the\x20gas\x20budget\x20or\x20reduce\x20the\x20operation\x20size,\x20then\x20retry.'},'insufficient_gas':{'error_code':'insufficient_gas','strategy':'adjust_params','max_attempts':0x1,'automation':'semi','detail':'Gas\x20exhausted\x20—\x20the\x20transaction\x20failed\x20deterministically\x20and\x20did\x20NOT\x20commit\x20on-chain\x20(no\x20state\x20changed;\x20commit-state\x20verification\x20is\x20NOT\x20needed).\x201.\x20Raise\x20the\x20gas_budget\x20parameter\x20above\x20the\x20failed\x20transaction\x27s\x20gas_used\x202.\x20If\x20the\x20account\x20balance\x20cannot\x20cover\x20any\x20budget,\x20fund\x20the\x20signing\x20account\x20with\x20gas\x20tokens\x20first\x203.\x20Resubmit\x20as\x20a\x20FRESH\x20call\x20—\x20do\x20NOT\x20replay\x20the\x20same\x20transaction','user_prompt':'The\x20transaction\x20ran\x20out\x20of\x20gas\x20and\x20did\x20not\x20commit\x20on-chain.\x20Increase\x20the\x20gas\x20budget\x20(or\x20fund\x20the\x20account\x20with\x20gas)\x20and\x20submit\x20a\x20fresh\x20transaction\x20—\x20retrying\x20unchanged\x20will\x20fail\x20the\x20same\x20way.'},'bcs_error':{'error_code':'bcs_error','strategy':'adjust_params','max_attempts':0x2,'automation':'semi','detail':'BCS\x20serialization/deserialization\x20error\x20—\x20a\x20parameter\x20does\x20not\x20match\x20the\x20expected\x20type/structure.\x201.\x20Query\x20the\x20operation\x20schema\x20(schema_query)\x202.\x20Fix\x20the\x20offending\x20parameter\x20type\x20(e.g.\x20BigInt\x20vs\x20number,\x20vector\x20element\x20type)\x203.\x20Retry','user_prompt':'A\x20parameter\x20failed\x20serialization.\x20Check\x20the\x20parameter\x20types\x20against\x20the\x20schema\x20and\x20retry.'},'signature_error':{'error_code':'signature_error','strategy':'switch_account','max_attempts':0x2,'automation':'semi','detail':'Signature\x20verification\x20failed.\x201.\x20Verify\x20the\x20account\x20is\x20not\x20suspended\x202.\x20Check\x20the\x20network\x20matches\x20the\x20account\x27s\x203.\x20Switch\x20to\x20a\x20healthy\x20account\x20and\x20retry','user_prompt':'Signature\x20verification\x20failed.\x20The\x20account\x20may\x20be\x20suspended\x20or\x20misconfigured.\x20Switch\x20accounts\x20or\x20check\x20the\x20configuration\x20and\x20retry.'},'config_error':{'error_code':'config_error','strategy':'escalate_human','max_attempts':0x1,'automation':'manual','detail':'Local\x20configuration\x20error\x20(network\x20not\x20specified,\x20persistent\x20storage\x20not\x20set).\x201.\x20Show\x20the\x20user\x20which\x20configuration\x20is\x20missing\x202.\x20Guide\x20the\x20user\x20through\x20the\x20account_operation/config\x20setup\x203.\x20Retry\x20after\x20the\x20user\x20fixes\x20it','user_prompt':'Local\x20configuration\x20is\x20incomplete.\x20Please\x20finish\x20the\x20account/network\x20setup\x20and\x20retry.'},'wip_verification_failed':{'error_code':'wip_verification_failed','strategy':'adjust_params','max_attempts':0x2,'automation':'semi','detail':'WIP\x20file\x20not\x20publicly\x20reachable\x20/\x20hash\x20mismatch.\x201.\x20Upload\x20via\x20the\x20wip\x20storage\x20service\x20(wip_file\x20type=\x27upload\x27\x20—\x20official\x20free\x20store\x20or\x20storage=\x27custom\x27)\x202.\x20Or\x20deploy\x20to\x20a\x20public\x20URL\x20(GitHub\x20Pages\x20/\x20IPFS\x20/\x20own\x20site)\x203.\x20Update\x20the\x20sale\x27s\x20wip\x20URL\x204.\x20Re-run\x20the\x20operation','user_prompt':'The\x20WIP\x20file\x20could\x20not\x20be\x20verified\x20from\x20a\x20public\x20URL.\x20Upload\x20it\x20with\x20wip_file\x20type=\x27upload\x27\x20(official\x20free\x20store\x20or\x20your\x20own\x20service)\x20or\x20deploy\x20it\x20(GitHub\x20Pages\x20/\x20IPFS),\x20update\x20the\x20sale\x27s\x20WIP\x20URL,\x20and\x20retry.'},'wip_storage_unavailable':{'error_code':'wip_storage_unavailable','strategy':'retry','max_attempts':0x3,'automation':'full','detail':'Transient\x20wip\x20storage\x20transport\x20failure.\x201.\x20Retry\x20the\x20same\x20request\x20with\x20bounded\x20backoff\x202.\x20Large\x20WIP\x20files\x20are\x20network-sensitive:\x20compress\x20images\x20before\x20generate\x20(each\x20image\x20<=\x202MB,\x20total\x20<=\x2010MB)\x203.\x20Check\x20connectivity\x20to\x20the\x20storage\x20base\x20URL\x20if\x20retries\x20keep\x20failing','user_prompt':'The\x20wip\x20storage\x20request\x20failed\x20due\x20to\x20a\x20network\x20problem.\x20Retry\x20the\x20upload;\x20if\x20it\x20keeps\x20failing,\x20reduce\x20the\x20file\x20size\x20or\x20check\x20connectivity.'},'wip_storage_rejected':{'error_code':'wip_storage_rejected','strategy':'adjust_params','max_attempts':0x1,'automation':'semi','detail':'WIP\x20storage\x20service\x20rejected\x20the\x20request\x20(HTTP\x204xx\x20—\x20deterministic\x20client-side\x20fault,\x20retrying\x20unchanged\x20fails\x20identically).\x20400:\x20malformed\x20body\x20or\x20failed\x20WIP\x20validation\x20—\x20re-generate\x20via\x20wip_file\x20type=\x27generate\x27\x20401:\x20re-sign\x20with\x20a\x20fresh\x20nonce\x20inside\x20the\x20timestamp\x20window\x20403:\x20check\x20storage\x20service\x20configuration\x20404:\x20file\x20does\x20not\x20exist\x20—\x20re-upload\x20409:\x20quota\x20—\x20delete\x20old\x20files\x20via\x20wip_file\x20type=\x27list\x27\x20then\x20delete\x20413:\x20compress\x20images\x20(each\x20<=\x202MB,\x20total\x20<=\x2010MB)\x20and\x20regenerate','user_prompt':'The\x20WIP\x20storage\x20service\x20rejected\x20the\x20request\x20(HTTP\x204xx).\x20Fix\x20the\x20specific\x20fault\x20(re-generate/re-sign/re-upload\x20per\x20the\x20status\x20code)\x20and\x20retry\x20—\x20do\x20not\x20retry\x20unchanged.'},'network_error':{'error_code':'network_error','strategy':'retry','max_attempts':0x5,'automation':'full','detail':'Transport\x20failure\x20(timeout\x20/\x20connection\x20reset\x20/\x20RPC\x20unreachable\x20/\x20HTTP\x205xx\x20gateway\x20error).\x20Exponential\x20backoff\x20retry:\x201s\x20/\x202s\x20/\x204s\x20/\x208s\x20/\x2016s.\x20Switch\x20RPC\x20node\x20if\x20available.\x20READS:\x20a\x20plain\x20retry\x20is\x20safe.\x20FUND-MOVING\x20WRITES:\x20before\x20any\x20resubmission,\x20verify\x20whether\x20the\x20previous\x20attempt\x20landed\x20(query\x20the\x20reported\x20digest\x20directly,\x20or\x20the\x20expected\x20object\x20via\x20the\x20sender\x27s\x20recent\x20on-chain\x20objects\x20/\x20onchain_events)\x20—\x20if\x20it\x20landed,\x20ADOPT\x20it\x20and\x20stop;\x20a\x20blind\x20backoff\x20retry\x20of\x20a\x20landed\x20write\x20moves\x20the\x20funds\x20a\x20second\x20time.'},'submission_unknown':{'error_code':'submission_unknown','strategy':'query_and_retry','max_attempts':0x2,'automation':'semi','detail':'Transport-level\x20failure\x20after\x20the\x20request\x20left\x20the\x20client\x20—\x20the\x20submission\x20state\x20is\x20UNKNOWN\x20and\x20the\x20transaction\x20may\x20already\x20be\x20committed.\x20NEVER\x20auto-retry\x20a\x20write\x20here.\x201.\x20Verify\x20commit\x20state\x20on-chain:\x20query_toolkit\x20for\x20the\x20object\x20this\x20call\x20would\x20create/modify\x20(resolve\x20the\x20reference\x20from\x20the\x20call\x27s\x20own\x20arguments),\x20or\x20onchain_events\x20for\x20the\x20sender\x27s\x20recent\x20transactions.\x202.\x20If\x20the\x20expected\x20object\x20EXISTS,\x20adopt\x20it\x20and\x20continue\x20the\x20workflow\x20(the\x20operation\x20succeeded\x20despite\x20the\x20transport\x20error).\x203.\x20If\x20confirmed\x20ABSENT,\x20resubmit\x20the\x20SAME\x20call\x20once\x20—\x20for\x20a\x20FIRST-EVER\x20transaction\x20on\x20a\x20fresh\x20account\x20make\x20that\x20resubmission\x20with\x20env.no_auto_register=true\x20and\x20SAY\x20SO\x20(the\x20SDK\x20silently\x20appends\x20an\x20entity\x20registration\x20to\x20a\x20first\x20business\x20call;\x20if\x20that\x20appended\x20leg\x20was\x20the\x20failing\x20leg\x20the\x20skip\x20lets\x20the\x20call\x20through\x20—\x20ziroom-mn-261013\x20live\x20case;\x20if\x20the\x20resubmission\x20aborts,\x20the\x20envelope\x20now\x20names\x20the\x20abort\x20—\x20re-enable\x20auto\x20registration\x20and\x20retry).\x204.\x20If\x20the\x20reported\x20digest\x20does\x20not\x20resolve\x20or\x20the\x20failure\x20repeats,\x20STOP\x20looping\x20on\x20digest\x20checks\x20and\x20re-run\x20the\x20SAME\x20call\x20with\x20env.dry_run=true\x20—\x20the\x20simulation\x20surfaces\x20the\x20real\x20failure\x20(exact\x20Move\x20abort)\x20without\x20gas\x20or\x20duplicate\x20risk.\x205.\x20Reads\x20are\x20idempotent\x20—\x20retry\x20immediately.\x206.\x20M-K2\x20replay\x20discipline:\x20a\x20FAILED\x20receipt\x20is\x20final\x20—\x20its\x20digest\x20is\x20consumed\x20and\x20replaying\x20the\x20same\x20bytes\x20returns\x20the\x20same\x20failure\x20forever;\x20fix\x20the\x20cause\x20(usually\x20funding)\x20and\x20build\x20a\x20FRESH\x20transaction.\x20Live\x20mainnet\x20incident\x20behind\x20this\x20rule:\x20an\x20order_new\x20-32603\x20\x27did\x20not\x20complete\x27\x20had\x20committed;\x20the\x20blind\x20retry\x20created\x20a\x20second\x20order\x20with\x20a\x20second\x20full\x20escrow\x20and\x20a\x20second\x20stock\x20decrement','user_prompt':'The\x20request\x20failed\x20at\x20transport\x20level\x20but\x20may\x20have\x20already\x20been\x20committed\x20on-chain.\x20Verify\x20whether\x20the\x20expected\x20object\x20exists\x20(query\x20it)\x20before\x20any\x20retry\x20—\x20a\x20blind\x20retry\x20can\x20duplicate\x20the\x20operation\x20(double\x20escrow).\x20For\x20read\x20operations,\x20a\x20plain\x20retry\x20is\x20safe.'},'transaction_expired':{'error_code':'transaction_expired','strategy':'retry','max_attempts':0x3,'automation':'full','detail':'The\x20transaction\x20expired\x20before\x20execution\x20(epoch\x20boundary\x20or\x20validator/gateway\x20outage)\x20—\x20it\x20did\x20NOT\x20land\x20and\x20nothing\x20was\x20committed.\x20Bounded\x20backoff\x20retry:\x2010s\x20/\x2030s\x20/\x2060s,\x20resubmit\x20the\x20SAME\x20call\x20unchanged.\x20If\x20a\x20dry_run\x20passes\x20while\x20the\x20real\x20call\x20keeps\x20failing,\x20the\x20fault\x20is\x20chain-side\x20—\x20wait\x20it\x20out.\x20Verify\x20with\x20onchain_events\x20if\x20unsure.'},'guard_rejected':{'error_code':'guard_rejected','strategy':'fill_submission','max_attempts':0x2,'automation':'semi','detail':'1.\x20Parse\x20Guard\x20table\x20structure\x202.\x20If\x20the\x20Guard\x20defines\x20submission\x20items,\x20fill\x20them\x20and\x20resubmit\x20with\x20call_with_submission\x203.\x20If\x20it\x20defines\x20none,\x20the\x20rule\x20evaluated\x20false\x20—\x20typical\x20causes:\x20a\x20TIME\x20WINDOW\x20(Clock\x20deadline/opening\x20comparison\x20—\x20this\x20call\x20may\x20sit\x20outside\x20the\x20window,\x20and\x20a\x20mis-oriented\x20comparison\x20inverts\x20it:\x20everything\x20inside\x20rejected,\x20everything\x20after\x20admitted),\x20an\x20IDENTITY\x20condition\x20(signer/state\x20checks\x20—\x20the\x20caller\x20may\x20not\x20be\x20the\x20address\x20the\x20rule\x20expects),\x20or\x20a\x20DATA-DEPENDENCY\x20ORDERING\x20(R-03,\x20nnd-tn-261025:\x20the\x20rule\x20reads\x20a\x20repository\x20row\x20/\x20workflow\x20state\x20that\x20does\x20not\x20hold\x20yet\x20—\x20e.g.\x20a\x20repository\x20data_add\x20whose\x20policy\x20write_guard\x20checks\x20progress.current\x20is\x20only\x20admitted\x20AFTER\x20the\x20machine\x20reaches\x20the\x20granting\x20node,\x20while\x20that\x20node\x27s\x20forward\x20may\x20read\x20this\x20very\x20row;\x20the\x20fix\x20is\x20ORDER,\x20not\x20parameters\x20—\x20find\x20the\x20reading\x20node\x20via\x20the\x20machine\x20node\x20table\x20(onchain_table_data)\x20or\x20analyze_guard_semantics,\x20advance\x20there\x20first,\x20then\x20re-run\x20the\x20SAME\x20write);\x20adjust\x20the\x20call\x27s\x20parameters\x20or\x20change\x20the\x20Guard\x20(docs#40)\x204.\x20When\x20the\x20failure\x20is\x20passport\x20E_VERIFY_FAILED\x20and\x20a\x20submission\x20was\x20supplied,\x20the\x20response\x20appends\x20a\x20\x27Guard\x20diagnosis\x20(dry-run)\x27\x20line\x20naming\x20the\x20first\x20failing\x20impact\x20guard\x20—\x20fix\x20that\x20guard\x20first\x205.\x20A\x20TIME-window\x20rejection\x20may\x20simply\x20be\x20EARLY:\x20re-run\x20the\x20SAME\x20call\x20with\x20env.dry_run=true\x20to\x20probe\x20the\x20window\x20for\x20free\x20(guard\x20rejections\x20do\x20NOT\x20consume\x20the\x20total\x20retry\x20budget;\x20only\x20the\x20per-code\x20cap\x20of\x202\x20applies)','user_prompt':'Guard\x20verification\x20rejected.\x20If\x20the\x20Guard\x20defines\x20submission\x20items,\x20fill\x20in\x20the\x20required\x20submission\x20data\x20and\x20resubmit;\x20if\x20it\x20defines\x20none,\x20the\x20Guard\x20rule\x20evaluated\x20false\x20—\x20the\x20usual\x20causes\x20are\x20a\x20time\x20window\x20(this\x20call\x20may\x20be\x20outside\x20the\x20Clock\x20deadline/opening\x20window),\x20an\x20identity\x20condition\x20(the\x20caller\x20is\x20not\x20the\x20address\x20the\x20rule\x20expects),\x20or\x20a\x20data-dependency\x20ordering\x20(the\x20rule\x20reads\x20a\x20row\x20/\x20workflow\x20state\x20that\x20does\x20not\x20hold\x20yet\x20—\x20advance\x20the\x20workflow\x20to\x20the\x20granting\x20node\x20first,\x20then\x20re-run\x20the\x20same\x20write);\x20adjust\x20this\x20call\x27s\x20parameters\x20or\x20change\x20the\x20Guard\x20rule.\x20When\x20the\x20response\x20includes\x20a\x20\x27Guard\x20diagnosis\x20(dry-run)\x27\x20line,\x20it\x20names\x20the\x20first\x20failing\x20impact\x20guard\x20—\x20address\x20that\x20guard\x20first.\x20A\x20time-window\x20rejection\x20may\x20simply\x20be\x20early:\x20probe\x20the\x20window\x20with\x20env.dry_run=true\x20(free\x20—\x20guard\x20rejections\x20do\x20not\x20consume\x20the\x20total\x20retry\x20budget).'},'time_lock_not_elapsed':{'error_code':'time_lock_not_elapsed','strategy':'wait_and_retry','max_attempts':0x1,'automation':'semi','detail':'1.\x20Verify\x20Service\x20is\x20paused\x20(bPaused=true).\x20If\x20not,\x20submit\x20pause=true\x20first.\x202.\x20Wait\x20until\x20paused_time\x20+\x20setting_lock_duration\x20<=\x20current\x20clock.\x203.\x20Retry\x20the\x20original\x20operation.\x20Do\x20NOT\x20recreate\x20the\x20object.','user_prompt':'Service\x20setting_lock_duration\x20has\x20not\x20elapsed\x20since\x20the\x20Service\x20was\x20paused.\x20Please\x20pause\x20the\x20Service\x20if\x20it\x20is\x20not\x20already\x20paused,\x20wait\x20for\x20the\x20lock\x20duration\x20to\x20elapse,\x20then\x20retry.'},'immutable_violation':{'error_code':'immutable_violation','strategy':'recreate','max_attempts':0x1,'automation':'semi','detail':'1.\x20Stop\x20modification\x20attempt\x202.\x20Evaluate\x20creating\x20a\x20new\x20object\x20as\x20replacement\x203.\x20Re-plan\x20affected\x20phases','user_prompt':'Cannot\x20modify\x20an\x20immutable\x20object.\x20A\x20new\x20object\x20must\x20be\x20created\x20as\x20a\x20replacement.\x20Confirm\x20to\x20proceed\x20with\x20recreation.'},'permission_denied':{'error_code':'permission_denied','strategy':'switch_account','max_attempts':0x2,'automation':'semi','detail':'1.\x20Query\x20object\x27s\x20permission_guard\x202.\x20List\x20accounts\x20with\x20permission\x203.\x20Switch\x20account\x20or\x20prompt\x20user\x20to\x20add\x20permission','user_prompt':'Current\x20account\x20lacks\x20permission\x20for\x20this\x20operation.\x20Switch\x20to\x20an\x20authorized\x20account\x20or\x20update\x20the\x20Permission\x20object.'},'object_not_found':{'error_code':'object_not_found','strategy':'query_and_retry','max_attempts':0x3,'automation':'semi','detail':'1.\x20Verify\x20the\x20referenced\x20name/ID\x20spelling\x20(local_mark_list)\x20and\x20that\x20the\x20object\x20exists\x20on\x20the\x20current\x20network\x202.\x20If\x20recently\x20created,\x20re-query\x20the\x20object\x20(may\x20be\x20sync\x20delay)\x203.\x20If\x20truly\x20absent,\x20search\x20for\x20similar\x20objects\x204.\x20Prompt\x20user\x20to\x20reselect','user_prompt':'Referenced\x20object\x20not\x20found.\x20First\x20verify\x20the\x20name/ID\x20spelling\x20and\x20that\x20the\x20object\x20exists\x20on\x20the\x20current\x20network;\x20if\x20it\x20was\x20created\x20recently,\x20this\x20may\x20be\x20a\x20synchronization\x20delay\x20—\x20retry.\x20If\x20the\x20issue\x20persists,\x20please\x20select\x20a\x20valid\x20object.'},'state_conflict':{'error_code':'state_conflict','strategy':'adjust_params','max_attempts':0x2,'automation':'full','detail':'1.\x20Query\x20object\x27s\x20current\x20true\x20state\x202.\x20Update\x20ODG\x20status\x20annotations\x203.\x20Adjust\x20subsequent\x20operations\x20(e.g.,\x20skip\x20completed\x20steps)'},'invalid_parameter':{'error_code':'invalid_parameter','strategy':'adjust_params','max_attempts':0x2,'automation':'semi','detail':'1.\x20Query\x20the\x20relevant\x20schema\x202.\x20Auto-fix\x20obvious\x20errors\x20(e.g.,\x20BigInt\x20vs\x20string)\x203.\x20If\x20unfixable,\x20prompt\x20user','user_prompt':'Parameter\x20validation\x20failed.\x20Please\x20check\x20the\x20parameter\x20types\x20and\x20values\x20against\x20the\x20schema\x20and\x20retry.'},'move_abort_unmapped':{'error_code':'move_abort_unmapped','strategy':'stop','max_attempts':0x1,'automation':'manual','detail':'The\x20chain\x27s\x20business\x20logic\x20aborted\x20and\x20the\x20(module,\x20abort\x20code)\x20pair\x20has\x20no\x20local\x20mapping.\x20Read\x20the\x20module\x20and\x20abort\x20code\x20from\x20move_abort_info\x20/\x20the\x20message\x20(rendered\x20as\x20\x27abort\x20(N)\x27),\x20resolve\x20their\x20meaning\x20from\x20the\x20module\x27s\x20documentation\x20or\x20the\x20wowok-tools\x20Skill,\x20fix\x20the\x20business\x20cause,\x20and\x20issue\x20a\x20NEW\x20call.\x20Do\x20NOT\x20restart\x20the\x20server\x20and\x20do\x20NOT\x20retry\x20the\x20identical\x20call\x20—\x20it\x20aborts\x20deterministically.','user_prompt':'The\x20operation\x20was\x20rejected\x20by\x20the\x20chain\x27s\x20business\x20logic\x20and\x20its\x20abort\x20code\x20is\x20not\x20mapped\x20locally.\x20The\x20module\x20name\x20and\x20abort\x20code\x20in\x20the\x20error\x20are\x20authoritative\x20—\x20review\x20them\x20(and\x20the\x20object\x20state\x20via\x20query_toolkit)\x20before\x20adjusting\x20anything.'},'missing_data':{'error_code':'missing_data','strategy':'adjust_params','max_attempts':0x2,'automation':'semi','detail':'A\x20guard\x20rule\x20read\x20a\x20keyed\x20table\x20row\x20that\x20does\x20NOT\x20exist\x20(repository.data\x20/\x20oracle\x20entry)\x20and\x20the\x20verifier\x20surfaced\x20it\x20as\x20a\x20location-only\x20fault\x20inside\x20the\x20passport\x20module\x20—\x20no\x20abort\x20code,\x20because\x20the\x20framework\x20cannot\x20express\x20\x27row\x20absent\x27\x20as\x20an\x20abort.\x20This\x20is\x20a\x20DATA\x20problem:\x201.\x20Identify\x20the\x20repository\x20and\x20key\x20the\x20guard\x20rule\x20reads\x20(guard2file\x20/\x20analyze_guard_semantics\x20on\x20the\x20guard\x20source)\x202.\x20Have\x20the\x20row\x27s\x20producer\x20write\x20it\x20(e.g.\x20an\x20oracle\x20timestamp\x20like\x20checkin_ts),\x20or\x20add\x20it\x20with\x20repository\x20data_add\x20(data_add.name\x20must\x20match\x20a\x20policy\x20rule\x20name)\x203.\x20Retry\x20the\x20SAME\x20call\x20unchanged\x20—\x20a\x20dry_run\x20that\x20turns\x20clean\x20after\x20the\x20row\x20exists\x20confirms\x20the\x20diagnosis.\x20OR-BRANCH\x20NOTE\x20(alg26\x20261026\x20F-A26-13):\x20a\x20guard\x27s\x20OR\x20does\x20NOT\x20short-circuit\x20—\x20every\x20branch\x20is\x20evaluated,\x20so\x20a\x20row\x20read\x20by\x20ANY\x20branch\x20must\x20exist\x20even\x20when\x20the\x20taken\x20path\x20would\x20not\x20read\x20it;\x20seed\x20initial\x20rows\x20(e.g.\x20a\x20counter\x20at\x200)\x20for\x20every\x20OR\x20branch\x20before\x20first\x20use','user_prompt':'A\x20guard\x20rule\x20references\x20a\x20data\x20row\x20that\x20has\x20not\x20been\x20written\x20yet\x20(location-only\x20fault\x20inside\x20the\x20passport\x20module\x20—\x20NOT\x20a\x20network\x20problem).\x20Identify\x20the\x20repository\x20row\x20the\x20guard\x20expects\x20(guard2file\x20/\x20analyze_guard_semantics),\x20write\x20it\x20with\x20repository\x20data_add\x20(or\x20let\x20its\x20producer\x20write\x20it),\x20then\x20retry.'},'state_not_visible':{'error_code':'state_not_visible','strategy':'wait_and_retry','max_attempts':0x3,'automation':'full','detail':'The\x20state\x20this\x20call\x20needs\x20was\x20JUST\x20written\x20and\x20is\x20not\x20yet\x20visible\x20to\x20reads\x20(write-to-visibility\x20window),\x20or\x20it\x20does\x20not\x20exist\x20at\x20all.\x201.\x20If\x20a\x20write\x20on\x20this\x20order/machine\x20committed\x20within\x20the\x20last\x20few\x20seconds,\x20wait\x20500ms\x20(doubling\x20each\x20attempt)\x20and\x20replay\x20the\x20SAME\x20call\x20UNCHANGED\x20—\x20NEVER\x20edit\x20parameters\x20to\x20\x27fix\x27\x20a\x20visibility\x20window;\x20an\x20aborted\x20call\x20never\x20landed,\x20so\x20the\x20replay\x20cannot\x20double-spend.\x202.\x20If\x20the\x20fault\x20persists\x20past\x20~3\x20attempts\x20(or\x20nothing\x20was\x20just\x20written),\x20the\x20state\x20is\x20deterministically\x20ABSENT\x20—\x20stop\x20retrying:\x20for\x20a\x20forward-info\x20miss\x20query\x20the\x20Machine\x27s\x20node\x20table\x20(onchain_table_data\x20onchain_table_item_machine_node)\x20and\x20use\x20an\x20existing\x20node/next_node/forward\x20triple\x20—\x20on\x20an\x20already-built\x20machine\x20check\x20TOPOLOGY\x20first\x20(alg26\x20261026\x20F-A26-14):\x20the\x20forward\x20may\x20simply\x20not\x20be\x20an\x20out-edge\x20of\x20the\x20order\x27s\x20CURRENT\x20node,\x20which\x20no\x20retry\x20can\x20fix;\x20for\x20a\x20guard-read\x20repository\x20row\x20follow\x20the\x20missing_data\x20path\x20(write\x20the\x20row).','user_prompt':'A\x20just-committed\x20write\x20is\x20not\x20visible\x20to\x20this\x20read\x20yet.\x20The\x20same\x20call\x20will\x20be\x20replayed\x20after\x20a\x20short\x20wait\x20—\x20no\x20parameter\x20change\x20is\x20needed.\x20If\x20it\x20keeps\x20failing,\x20the\x20required\x20state\x20is\x20genuinely\x20missing\x20and\x20must\x20be\x20created\x20first.'},'anchor_unavailable':{'error_code':'anchor_unavailable','strategy':'escalate_human','max_attempts':0x1,'automation':'manual','detail':'The\x20messenger\x20WTS\x20evidence\x20chain\x20is\x20unavailable:\x20the\x20server\x20key-book\x20anchor\x20could\x20not\x20be\x20confirmed\x20on\x20the\x20current\x20network\x20(signer\x20not\x20pinned\x20for\x20this\x20network,\x20anchor\x20repository\x20absent\x20on-chain\x20—\x20typical\x20after\x20a\x20chain\x20re-genesis\x20—\x20or\x20the\x20anchor\x20chain\x20read\x20failed).\x20This\x20is\x20an\x20INFRASTRUCTURE\x20configuration\x20gap,\x20NOT\x20a\x20guard\x20rejection,\x20a\x20network\x20fault,\x20or\x20a\x20parameter\x20problem\x20—\x20signing\x20and\x20anchoring\x20fail\x20closed\x20by\x20design\x20(an\x20unconfirmed\x20key\x20book\x20cannot\x20ground\x20evidence).\x20Remedy\x20(out\x20of\x20band,\x20no\x20retry\x20will\x20help):\x201.\x20Deploy\x20or\x20re-anchor\x20the\x20messenger\x20server\x20key\x20book\x20on\x20the\x20target\x20network\x202.\x20Pin\x20its\x20signer\x20for\x20that\x20network\x20in\x20the\x20SDK\x20keybook\x20table\x203.\x20Until\x20then,\x20treat\x20the\x20messenger\x20channel\x20as\x20private\x20communication\x20WITHOUT\x20third-party\x20provability\x20(verify_wts\x20still\x20returns\x20a\x20structured\x20valid:false\x20verdict\x20with\x20the\x20anchor\x20reason)','user_prompt':'The\x20WTS\x20evidence\x20chain\x20cannot\x20be\x20anchored\x20on\x20this\x20network:\x20the\x20messenger\x20server\x20key-book\x20anchor\x20is\x20missing\x20or\x20unconfirmed.\x20This\x20needs\x20an\x20out-of-band\x20keybook\x20deployment\x20plus\x20SDK\x20signer\x20pinning\x20for\x20the\x20network\x20—\x20retrying\x20the\x20call\x20will\x20fail\x20the\x20same\x20way.\x20Until\x20fixed,\x20messenger\x20communication\x20remains\x20private\x20but\x20cannot\x20be\x20turned\x20into\x20third-party-verifiable\x20evidence.'},'delivery_unknown':{'error_code':'delivery_unknown','strategy':'query_and_retry','max_attempts':0x1,'automation':'semi','detail':'The\x20messenger\x20send\x20failed\x20at\x20transport\x20level\x20AFTER\x20submission:\x20delivery\x20state\x20is\x20UNKNOWN\x20because\x20the\x20relay\x20may\x20have\x20already\x20committed\x20the\x20message\x20despite\x20the\x20client-side\x20failure.\x20A\x20blind\x20re-send\x20DOUBLE-DELIVERS\x20the\x20same\x20encrypted\x20payload,\x20so\x20the\x20retry\x20loop\x20is\x20verify-first:\x20read\x20the\x20conversation\x20(watch_conversations\x20/\x20message\x20list)\x20and\x20check\x20for\x20the\x20identical\x20payload;\x20re-send\x20only\x20after\x20confirming\x20it\x20never\x20arrived.\x20Note\x20the\x20message,\x20when\x20it\x20did\x20arrive,\x20is\x20fully\x20end-to-end\x20encrypted\x20—\x20only\x20delivery\x20is\x20uncertain','user_prompt':'The\x20send\x20failed\x20after\x20submission,\x20so\x20delivery\x20is\x20uncertain\x20(the\x20server\x20may\x20have\x20committed\x20it\x20anyway).\x20Do\x20NOT\x20resend\x20blindly:\x20first\x20check\x20the\x20conversation\x20for\x20the\x20same\x20message;\x20resend\x20only\x20if\x20it\x20never\x20arrived.'},'unknown':{'error_code':'unknown','strategy':'escalate_human','max_attempts':0x1,'automation':'manual','detail':'1.\x20Report\x20full\x20error\x20context\x20to\x20the\x20user\x202.\x20Escalate\x20to\x20human\x20intervention\x203.\x20Flag\x20for\x20error-classification\x20rule\x20addition','user_prompt':'An\x20unclassified\x20error\x20occurred.\x20Please\x20review\x20the\x20error\x20details\x20and\x20contact\x20support\x20if\x20needed.'}};const operationAttempts=new Map();function getAttemptCount(a,b){const c=operationAttempts['get'](a);if(!c)return 0x0;return c['get'](b)??0x0;}function incrementAttempt(a,b){!operationAttempts['has'](a)&&operationAttempts['set'](a,new Map());const c=operationAttempts['get'](a),d=(c['get'](b)??0x0)+0x1;return c['set'](b,d),d;}const BUDGET_EXEMPT_CODES=new Set(['guard_rejected']);function getBudgetAttempts(a){const b=operationAttempts['get'](a);if(!b)return 0x0;let c=0x0;for(const [d,e]of b){if(!BUDGET_EXEMPT_CODES['has'](d))c+=e;}return c;}export function resetAttempts(a){operationAttempts['delete'](a);}export function recover(a,b,c){const d=RECOVERY_RULES[a]??RECOVERY_RULES['unknown'],e=0x5,f=getBudgetAttempts(b),g=getAttemptCount(b,a);if(d['max_attempts']<=0x1||d['strategy']==='stop')return{'strategy':d['strategy'],'should_retry':![],'max_attempts':d['max_attempts'],'current_attempt':g,'adjusted_params':d['adjusted_params'],'user_prompt':d['user_prompt'],'detail':d['detail']};if(f>=e)return{'strategy':'stop','should_retry':![],'max_attempts':e,'current_attempt':f,'detail':'Total\x20retry\x20limit\x20('+e+')\x20reached\x20for\x20operation\x20'+b+'.\x20Escalating\x20to\x20human\x20intervention.\x20Attempts\x20recorded\x20for\x20this\x20operation\x20id:\x20'+([...(operationAttempts['get'](b)??new Map())['entries']()]['map'](([j,k])=>j+':'+k)['join'](',\x20')||'none')+'.','user_prompt':'Maximum\x20retry\x20attempts\x20reached.\x20Manual\x20intervention\x20required.'};if(g>=d['max_attempts'])return{'strategy':'escalate_human','should_retry':![],'max_attempts':d['max_attempts'],'current_attempt':g,'detail':'Per-error-code\x20retry\x20limit\x20('+d['max_attempts']+')\x20reached\x20for\x20'+a+'.\x20Escalating\x20to\x20human.','user_prompt':'Recovery\x20attempts\x20for\x20'+a+'\x20exhausted.\x20Manual\x20intervention\x20required.'};const h=incrementAttempt(b,a),i={'strategy':d['strategy'],'should_retry':d['automation']==='full'||h<d['max_attempts'],'max_attempts':d['max_attempts'],'current_attempt':h,'adjusted_params':d['adjusted_params'],'user_prompt':d['user_prompt'],'detail':d['detail']};return i['should_retry']&&c?.['retryable']===![]&&a!=='guard_rejected'&&d['strategy']!=='fill_submission'&&d['strategy']!=='query_and_retry'&&(i['should_retry']=![],i['detail']+='\x20NON-RETRYABLE\x20CLASSIFICATION:\x20retrying\x20the\x20IDENTICAL\x20call\x20fails\x20identically\x20—\x20apply\x20the\x20strategy\x20above\x20to\x20fix\x20the\x20cause,\x20then\x20submit\x20a\x20FRESH\x20call.'),i;}export function getBackoffDelay(a){return Math['pow'](0x2,a-0x1)*0x3e8;}
|
package/dist/intent/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { IndustryScenario } from "../evaluation/capability.js";
|
|
2
2
|
import type { PersonaRole } from "../persona/types.js";
|
|
3
|
-
export type IntentTargetType = "NewOrderEvent" | "ProgressEvent" | "DemandPresentEvent" | "DemandFeedbackEvent" | "DemandChangedEvent" | "ServiceEvent" | "ArbitrationEvent" | "NewEntityEvent" | "ArbEvent" | "VoteEvent" | "FeedbackEvent" | "AllocationEvent" | "TreasuryEvent" | "RewardClaimEvent" | "RewardFundEvent" | "RewardWithdrawEvent" | "NewPaymentEvent" | "PermissionChangedEvent" | "RepositoryDataOverwriteEvent";
|
|
3
|
+
export type IntentTargetType = "NewOrderEvent" | "ProgressEvent" | "ThresholdPendingEvent" | "DemandPresentEvent" | "DemandFeedbackEvent" | "DemandChangedEvent" | "ServiceEvent" | "ArbitrationEvent" | "NewEntityEvent" | "ArbEvent" | "VoteEvent" | "FeedbackEvent" | "AllocationEvent" | "TreasuryEvent" | "RewardClaimEvent" | "RewardFundEvent" | "RewardWithdrawEvent" | "NewPaymentEvent" | "PermissionChangedEvent" | "RepositoryDataOverwriteEvent";
|
|
4
4
|
export interface IntentRecord {
|
|
5
5
|
id: string;
|
|
6
6
|
intent: string;
|
package/dist/intent/types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const INTENT_VERSION=0x1;export const INTENT_MAX_PER_SCOPE=0x32;export const ALL_INTENT_TARGET_TYPES=['NewOrderEvent','ProgressEvent','DemandPresentEvent','DemandFeedbackEvent','DemandChangedEvent','ServiceEvent','ArbitrationEvent','NewEntityEvent','ArbEvent','VoteEvent','FeedbackEvent','AllocationEvent','TreasuryEvent','RewardClaimEvent','RewardFundEvent','RewardWithdrawEvent','NewPaymentEvent','PermissionChangedEvent','RepositoryDataOverwriteEvent'];
|
|
1
|
+
export const INTENT_VERSION=0x1;export const INTENT_MAX_PER_SCOPE=0x32;export const ALL_INTENT_TARGET_TYPES=['NewOrderEvent','ProgressEvent','ThresholdPendingEvent','DemandPresentEvent','DemandFeedbackEvent','DemandChangedEvent','ServiceEvent','ArbitrationEvent','NewEntityEvent','ArbEvent','VoteEvent','FeedbackEvent','AllocationEvent','TreasuryEvent','RewardClaimEvent','RewardFundEvent','RewardWithdrawEvent','NewPaymentEvent','PermissionChangedEvent','RepositoryDataOverwriteEvent'];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type OrderContext, type ParsedMachineNode, type PermissionContext } from "../graph/onchain/sdk-batch.js";
|
|
2
|
+
import type { GuardJsonInput } from "../knowledge/guard-lint.js";
|
|
2
3
|
import type { ScopeSnapshot } from "../monitor/types.js";
|
|
3
4
|
import type { KeeperDesiredItem } from "./KeeperStore.js";
|
|
4
5
|
export interface UnclaimedPayment {
|
|
@@ -17,7 +18,9 @@ export interface ProgressDetectorDeps {
|
|
|
17
18
|
fetchMachinePermissionAddr(machine: string, network: string): Promise<string | undefined>;
|
|
18
19
|
fetchPermissionContext(perm: string, network: string): Promise<PermissionContext | undefined>;
|
|
19
20
|
fetchOrderContext(order: string, network: string): Promise<OrderContext | undefined>;
|
|
21
|
+
fetchGuardJson?(guard: string, network: string): Promise<GuardJsonInput | undefined>;
|
|
20
22
|
}
|
|
23
|
+
export declare function extractGuardSignerPins(json: GuardJsonInput): string[];
|
|
21
24
|
export declare function detectProgressActionable(scope: ScopeSnapshot, network: string, deps: ProgressDetectorDeps, maxObjects: number): Promise<KeeperDesiredItem[]>;
|
|
22
25
|
export interface SettlementDetectorDeps {
|
|
23
26
|
fetchOrderFields(addrs: string[], network: string): Promise<Map<string, any>>;
|
package/dist/keeper/detectors.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{query_received,query_objects}from'@wowok/wowok';import{batchQueryObjectsByIds,fetchMachineNodes,fetchOrderContext,fetchPermissionContext}from'../graph/onchain/sdk-batch.js';import{extractCoinType}from'../graph/onchain/extract.js';import{enumerateActionableForwards}from'../knowledge/index.js';import{formatChainValue}from'../knowledge/fund-layer.js';import{formatShortAddress}from'../persona/address-format.js';export async function detectPaymentUnclaimed(a,b,c){const d=[];for(const e of a){const f=e['toLowerCase']();let g=null;try{g=await c['queryUnclaimed'](f,b);}catch{g=null;}if(!g||g['balance']<=0x0n||g['count']<=0x0)continue;let h;try{h=await c['formatAmount']?.(g['balance'],g['token_type'],b);}catch{h=undefined;}const i=h??g['balance']['toString']()+'\x20(smallest\x20unit)';d['push']({'dedupe_key':'payment_unclaimed:'+f,'detector':'payment_unclaimed','beneficiary':f,'operation':{'operation_type':'payment','data':{'receive':!![]}},'title':'Unclaimed\x20funds\x20—\x20'+i+'\x20waiting\x20to\x20be\x20received','detail':g['count']+'\x20CoinWrapper\x20object(s)\x20hold\x20'+i+'\x20for\x20this\x20account.\x20'+'They\x20are\x20owned\x20but\x20NOT\x20spendable\x20until\x20unwrapped.\x20Execute\x20payment\x20{receive:true}\x20'+'as\x20this\x20account\x20to\x20unwrap\x20all\x20of\x20them\x20into\x20the\x20wallet\x20in\x20one\x20transaction\x20(keeper\x20can\x20'+'auto-execute\x20this\x20when\x20a\x20payment_unclaimed\x20auto-exec\x20rule\x20covers\x20the\x20account).','benefit':'Receive\x20'+i+'\x20into\x20your\x20wallet','state_fingerprint':g['count']+':'+g['balance']['toString']()});}return d;}export async function detectProgressActionable(a,b,c,d){const e=(a['order_children']??[])['filter'](n=>n['type']==='progress'&&typeof n['object']==='string')['map'](n=>n['object'])['filter'](n=>n['startsWith']('0x')),f=(a['focus']??[])['map'](n=>n['object'])['filter'](n=>typeof n==='string'&&n['startsWith']('0x')),g=[...new Set([...e,...f])]['slice'](0x0,Math['max'](0x1,d));if(g['length']===0x0||(a['accounts']??[])['length']===0x0)return[];let h;try{h=await c['fetchProgressFields'](g,b);}catch{return[];}const i=new Map(),j=new Map(),k=new Map(),l=a['accounts'],m=[];for(const [n,o]of h){const p=typeof o?.['machine']==='string'?o['machine']:undefined;if(!p)continue;const q=p['toLowerCase']();let r=i['get'](q);if(!r){try{r=await c['fetchMachineNodes'](p,b);}catch{r=[];}i['set'](q,r);}if(r['length']===0x0)continue;let s;if(!j['has'](q)){let z;try{z=await c['fetchMachinePermissionAddr'](p,b);}catch{z=undefined;}let A;if(z)try{A=await c['fetchPermissionContext'](z,b);}catch{A=undefined;}j['set'](q,A);}s=j['get'](q);const t=typeof o?.['task']==='string'?o['task']:undefined;let u;if(t){const B=t['toLowerCase']();if(!k['has'](B))try{k['set'](B,await c['fetchOrderContext'](t,b));}catch{k['set'](B,undefined);}u=k['get'](B);}const v=(Array['isArray'](o?.['namedOperator'])?o['namedOperator']:[])['map'](C=>({'name':String(C?.['name']??''),'operators':(Array['isArray'](C?.['operators'])?C['operators']:[])['map'](D=>String(D))})),w=enumerateActionableForwards(o,r,l,v,u,s),x=typeof o?.['current']==='string'?o['current']:'',y=t?'order\x20'+formatShortAddress(t):'no\x20bound\x20order';for(const C of w){for(const D of C['executable_accounts']){const E=C['threshold']>0x1?'\x20—\x20cooperation\x20threshold\x20'+C['threshold']+'\x20(weight\x20'+C['weight']+');\x20other\x20distinct\x20forwards\x20may\x20still\x20be\x20needed':'',F=C['guard']?'\x20—\x20guard\x20'+formatShortAddress(C['guard'])+'\x20must\x20be\x20satisfied\x20(submissions\x20may\x20be\x20required)':'',G=u&&D===u['builder']['toLowerCase']()?'You\x20are\x20the\x20order\x20owner':C['operator_kind']==='named_operator'?'You\x20hold\x20the\x20named-operator\x20role\x20\x27'+C['named_operator']+'\x27':'You\x20hold\x20the\x20required\x20permission\x20index';m['push']({'dedupe_key':'progress_actionable:'+n+':'+D+':'+C['next_node']+'|'+C['forward'],'detector':'progress_actionable','beneficiary':D,'object':n,'title':'Workflow\x20action\x20available:\x20\x27'+C['forward']+'\x27\x20→\x20'+C['next_node'],'detail':'Progress\x20'+formatShortAddress(n)+'\x20('+y+')\x20sits\x20at\x20node\x20\x27'+x+'\x27.\x20'+(G+'\x20—\x20you\x20can\x20execute\x20forward\x20\x27'+C['forward']+'\x27\x20into\x20\x27'+C['next_node']+'\x27')+(''+E+F+'.\x20Advance\x20it\x20via\x20workflow_operation\x20')+'(action=\x27list\x27\x20to\x20review,\x20action=\x27operate\x27\x20to\x20execute).\x20'+'Who\x20benefits,\x20who\x20pushes:\x20waiting\x20does\x20not\x20move\x20the\x20order\x20—\x20the\x20party\x20that\x20'+'gains\x20from\x20the\x20next\x20step\x20sends\x20the\x20transaction.','benefit':benefitOfNode(C['next_node']),'state_fingerprint':C['weight']+':'+C['threshold']+':'+(C['guard']??'')+':'+C['operator_kind']});}}}return m;}function benefitOfNode(a){if(/(^|_)(completed?|done|finished|received|delivered|accepted|confirmed|finalized|success|approved)(_|$)/i['test'](a))return'Completing\x20this\x20step\x20settles\x20the\x20order\x20—\x20funds\x20are\x20released\x20to\x20the\x20provider';if(/(^|_)(cancel(led)?|refund(ed)?|return(ed|_approved)?)(_|$)/i['test'](a))return'This\x20step\x20routes\x20to\x20cancellation/refund\x20—\x20funds\x20return\x20to\x20the\x20buyer';if(/(^|_)(interrupt(ed)?|exception|dispute(d)?|fail(ed)?|abort(ed)?|reject(ed)?)(_|$)/i['test'](a))return'This\x20step\x20opens\x20the\x20exception\x20path\x20—\x20review\x20before\x20advancing';return'Advancing\x20keeps\x20the\x20order\x20moving\x20toward\x20settlement';}const REFUND_FLAVOR_RE=/(^|_)(cancel(led)?|refund(ed)?|return(ed|_approved)?|expired)(_|$)/i;export async function detectSettlementPending(a,b,c,e){const f=(a['accounts']??[])['map'](s=>s['toLowerCase']());if(f['length']===0x0)return[];const g=(a['orders']??[])['slice'](0x0,Math['max'](0x1,e));if(g['length']===0x0)return[];const h=g['map'](s=>s['order'])['filter'](s=>typeof s==='string'&&s['startsWith']('0x'));let i;try{i=await c['fetchOrderFields'](h,b);}catch{return[];}const j=[],k=[];for(const s of i['values']()){const t=s?.['data']??s;if(typeof t?.['allocation']==='string'&&t['allocation']['startsWith']('0x'))j['push'](t['allocation']);if(typeof t?.['progress']==='string'&&t['progress']['startsWith']('0x'))k['push'](t['progress']);}let l=new Map(),m=new Map();try{l=await c['fetchAllocationFields']([...new Set(j)],b);}catch{return[];}try{m=await c['fetchProgressFields']([...new Set(k)],b);}catch{m=new Map();}const o=new Set((a['services']??[])['map'](u=>u['toLowerCase']())),q=new Map(),r=[];for(const [u,v]of i){const w=v?.['data']??v,x=typeof w?.['allocation']==='string'?w['allocation']:undefined;if(!x)continue;const y=l['get'](x['toLowerCase']());if(!y)continue;const z=y?.['data']??y,A=typeof z['balance']==='bigint'?z['balance']:BigInt(z['balance']??0x0);if(A<=0x0n)continue;const B=Array['isArray'](z['payment'])?z['payment']:[];if(B['length']>0x0)continue;const C=typeof w?.['progress']==='string'?w['progress']:undefined,D=C?m['get'](C['toLowerCase']()):undefined,E=typeof D?.['current']==='string'?D['current']:'',F=typeof D?.['machine']==='string'?D['machine']:typeof w?.['machine']==='string'?w['machine']:undefined;if(!E||!F)continue;let G=q['get'](F['toLowerCase']());if(!G){try{G=await c['fetchMachineNodes'](F,b);}catch{G=[];}q['set'](F['toLowerCase'](),G);}if(G['length']===0x0)continue;const H=new Set();for(const P of G){for(const Q of P['pairs']){if((Q['forwards']??[])['length']>0x0)H['add'](P['name']);}}if(H['has'](E))continue;const I=REFUND_FLAVOR_RE['test'](E),J=[];if(I){const R=typeof w?.['builder']==='string'?w['builder']['toLowerCase']():'';if(R&&f['includes'](R))J['push'](R);}else{const S=typeof w?.['service']==='string'?w['service']['toLowerCase']():'';if(S&&o['has'](S))J['push'](...f);}if(J['length']===0x0)continue;const K=(Array['isArray'](z['allocators']?.['allocators'])?z['allocators']['allocators']:[])['map'](T=>String(T?.['guard']??''))['filter'](T=>T),L=K['length']>0x0?'Candidate\x20settle\x20guards\x20on\x20this\x20pool:\x20'+K['map'](T=>formatShortAddress(T))['join'](',\x20')+'.':'This\x20pool\x20exposes\x20no\x20readable\x20allocator\x20guards\x20—\x20inspect\x20it\x20before\x20acting.';let M;try{M=await c['formatAmount']?.(A,extractCoinType(y?.['type_raw']),b);}catch{M=undefined;}const N=M??A['toString']()+'\x20(smallest\x20unit)',O=I?'refund/cancel':'completion';for(const T of J){r['push']({'dedupe_key':'settlement_pending:'+u+':'+x,'detector':'settlement_pending','beneficiary':T,'object':x,'title':'Unsettled\x20escrow\x20—\x20'+N+'\x20on\x20a\x20'+O+'\x20terminal','detail':'Order\x20'+formatShortAddress(u)+'\x20sits\x20on\x20terminal\x20node\x20\x27'+E+'\x27\x20but\x20its\x20Allocation\x20'+(formatShortAddress(x)+'\x20still\x20holds\x20'+N+'\x20and\x20has\x20emitted\x20no\x20Payment.\x20The\x20chain\x20never\x20')+('auto-settles:\x20someone\x20must\x20trigger\x20the\x20matching\x20guard.\x20'+L+'\x20Execute\x20via\x20allocation_operation\x20')+'(operation_type=\x27allocation\x27,\x20alloc_by_guard=<guard>)\x20as\x20an\x20account\x20that\x20can\x20satisfy\x20the\x20guard,\x20then\x20'+'recipients\x20claim\x20their\x20CoinWrappers\x20(payment\x20receive).\x20Trigger\x20ONCE\x20and\x20verify\x20the\x20pool\x20drained\x20—\x20a\x20'+'fully-drained\x20pool\x20aborts\x20on\x20re-trigger,\x20but\x20a\x20max-capped\x20pool\x20re-splits\x20the\x20remainder.\x20'+'Who\x20benefits,\x20who\x20pushes:\x20waiting\x20keeps\x20the\x20funds\x20frozen\x20and\x20leaves\x20the\x20dispute\x20window\x20open.','benefit':'Release\x20'+N+'\x20from\x20escrow\x20to\x20its\x20rightful\x20recipients','state_fingerprint':A['toString']()+':'+B['length']+':'+E});}}return r;}export async function detectTimeoutIntermediate(a,b,c,d,e){const f=(a['order_children']??[])['filter'](m=>m['type']==='progress'&&typeof m['object']==='string')['map'](m=>m['object'])['filter'](m=>m['startsWith']('0x')),g=(a['focus']??[])['map'](m=>m['object'])['filter'](m=>typeof m==='string'&&m['startsWith']('0x')),h=[...new Set([...f,...g])]['slice'](0x0,Math['max'](0x1,d));if(h['length']===0x0||(a['accounts']??[])['length']===0x0)return[];let i;try{i=await c['fetchProgressFields'](h,b);}catch{return[];}const j=c['nowMs'](),k=new Map(),l=[];for(const [m,n]of i){const o=typeof n?.['current']==='string'?n['current']:'',p=typeof n?.['current_time']==='number'?n['current_time']:0x0;if(!o||p<=0x0)continue;const q=typeof n?.['machine']==='string'?n['machine']:undefined;if(!q)continue;const r=q['toLowerCase']();let s=k['get'](r);if(!s){try{s=await c['fetchMachineNodes'](q,b);}catch{s=[];}k['set'](r,s);}const t=s['find'](A=>A['name']===o);if(!t)continue;const u=t['pairs']['some'](A=>(A['forwards']??[])['length']>0x0);if(!u)continue;const v=j-p;if(v<e)continue;const w=typeof n?.['task']==='string'?n['task']:undefined,x=(a['accounts']??[])['map'](A=>A['toLowerCase']()),y=x[0x0];if(!y)continue;const z=Math['floor'](v/(0x3e8*0x3c*0x3c));l['push']({'dedupe_key':'timeout_intermediate:'+m+':'+o,'detector':'timeout_intermediate','beneficiary':y,'object':m,'title':'Possible\x20stuck\x20intermediate\x20state\x20—\x20\x27'+o+'\x27\x20for\x20'+z+'h','detail':'Progress\x20'+formatShortAddress(m)+'\x20has\x20been\x20on\x20node\x20\x27'+o+'\x27\x20for\x20'+z+'\x20hours\x20'+('(since\x20'+new Date(p)['toISOString']()+').\x20This\x20node\x20has\x20outgoing\x20forwards\x20but\x20none\x20have\x20fired.\x20')+'If\x20this\x20node\x20has\x20a\x20time-lock\x20guard\x20(confirm\x20timeout,\x20acceptance\x20timeout,\x20inspection\x20timeout,\x20etc.),\x20'+'the\x20keeper\x20may\x20need\x20to\x20advance\x20it.\x20Check\x20the\x20template\x27s\x20keeper_dependencies\x20and\x20the\x20guard\x27s\x20time\x20window\x20'+'before\x20acting.\x20Who\x20benefits,\x20who\x20pushes:\x20a\x20stuck\x20intermediate\x20state\x20blocks\x20the\x20order\x27s\x20funds\x20and\x20'+'business\x20flow\x20—\x20the\x20party\x20that\x20gains\x20from\x20unblocking\x20it\x20sends\x20the\x20transaction.','benefit':'Unblock\x20the\x20order\x20stuck\x20at\x20\x27'+o+'\x27','state_fingerprint':o+':'+p+':'+v});}return l;}export function realPaymentDetectorDeps(){return{'queryUnclaimed':async(a,b)=>{const c=await query_received({'name_or_address':{'name_or_address':a},'type':'CoinWrapper','network':b});if(!c||typeof c!=='object'||!Array['isArray'](c['received']))return null;const d=typeof c['balance']==='bigint'?c['balance']:BigInt(c['balance']??0x0);return{'balance':d,'count':c['received']['length'],'token_type':typeof c['token_type']==='string'&&c['token_type']?c['token_type']:undefined};},'formatAmount':async(a,b,c)=>{if(!b)return undefined;const e=await formatChainValue(a,b,c),f=e['symbol']?'\x20'+e['symbol']:'';return e['precision_known']?''+e['display']+f:''+e['raw']+f;}};}export function realProgressDetectorDeps(){return{'fetchProgressFields':async(a,b)=>{const c=await batchQueryObjectsByIds(a,b,![]),e=new Map();for(const f of c??[]){const g=f?.['data']??f;if(f?.['type']!=='Progress')continue;const h=String(f?.['query_name']??f?.['object']??'')['toLowerCase']();if(h)e['set'](h,g);}return e;},'fetchMachineNodes':(a,b)=>fetchMachineNodes(a,b,![]),'fetchMachinePermissionAddr':async(a,b)=>{const c=await query_objects({'objects':[a],'network':b}),d=c?.['objects']?.[0x0],e=(d?.['data']??d)?.['permission'];return typeof e==='string'&&e?e:undefined;},'fetchPermissionContext':(a,b)=>fetchPermissionContext(a,b,![]),'fetchOrderContext':(a,b)=>fetchOrderContext(a,b,![])};}async function fieldsByType(a,b,c){const d=await batchQueryObjectsByIds(a,b,![]),e=new Map();for(const f of d??[]){if(f?.['type']!==c)continue;const g=String(f?.['query_name']??f?.['object']??'')['toLowerCase']();if(g)e['set'](g,f);}return e;}export function realSettlementDetectorDeps(){return{'fetchOrderFields':(a,b)=>fieldsByType(a,b,'Order'),'fetchAllocationFields':(a,b)=>fieldsByType(a,b,'Allocation'),'fetchProgressFields':async(a,b)=>{const c=await fieldsByType(a,b,'Progress'),d=new Map();for(const [e,f]of c)d['set'](e,f?.['data']??f);return d;},'fetchMachineNodes':(a,b)=>fetchMachineNodes(a,b,![]),'formatAmount':async(a,b,c)=>{if(!b)return undefined;const e=await formatChainValue(a,b,c),f=e['symbol']?'\x20'+e['symbol']:'';return e['precision_known']?''+e['display']+f:''+e['raw']+f;}};}export function realTimeoutDetectorDeps(){return{'fetchProgressFields':async(a,b)=>{const c=await fieldsByType(a,b,'Progress'),d=new Map();for(const [e,f]of c)d['set'](e,f?.['data']??f);return d;},'fetchMachineNodes':(a,b)=>fetchMachineNodes(a,b,![]),'nowMs':()=>Date['now']()};}
|
|
1
|
+
import{query_received,query_objects}from'@wowok/wowok';import{batchQueryObjectsByIds,fetchMachineNodes,fetchOrderContext,fetchPermissionContext}from'../graph/onchain/sdk-batch.js';import{extractCoinType}from'../graph/onchain/extract.js';import{enumerateActionableForwards}from'../knowledge/index.js';import{formatChainValue}from'../knowledge/fund-layer.js';import{loadGuardJsonFromChain}from'../knowledge/guard-submission-brief.js';import{formatShortAddress}from'../persona/address-format.js';export async function detectPaymentUnclaimed(a,b,c){const d=[];for(const e of a){const f=e['toLowerCase']();let g=null;try{g=await c['queryUnclaimed'](f,b);}catch{g=null;}if(!g||g['balance']<=0x0n||g['count']<=0x0)continue;let h;try{h=await c['formatAmount']?.(g['balance'],g['token_type'],b);}catch{h=undefined;}const i=h??g['balance']['toString']()+'\x20(smallest\x20unit)';d['push']({'dedupe_key':'payment_unclaimed:'+f,'detector':'payment_unclaimed','beneficiary':f,'operation':{'operation_type':'payment','data':{'receive':!![]}},'title':'Unclaimed\x20funds\x20—\x20'+i+'\x20waiting\x20to\x20be\x20received','detail':g['count']+'\x20CoinWrapper\x20object(s)\x20hold\x20'+i+'\x20for\x20this\x20account.\x20'+'They\x20are\x20owned\x20but\x20NOT\x20spendable\x20until\x20unwrapped.\x20Execute\x20payment\x20{receive:true}\x20'+'as\x20this\x20account\x20to\x20unwrap\x20all\x20of\x20them\x20into\x20the\x20wallet\x20in\x20one\x20transaction\x20(keeper\x20can\x20'+'auto-execute\x20this\x20when\x20a\x20payment_unclaimed\x20auto-exec\x20rule\x20covers\x20the\x20account).','benefit':'Receive\x20'+i+'\x20into\x20your\x20wallet','state_fingerprint':g['count']+':'+g['balance']['toString']()});}return d;}export function extractGuardSignerPins(a){const b=Array['isArray'](a['table'])?a['table']:[],c=[],d=(e,f)=>{if(!e||typeof e!=='object')return;const g=f||e['type']==='logic_or'||e['type']==='logic_not';if(e['type']==='logic_equal'){const h=Array['isArray'](e['nodes'])?e['nodes']:e['left']&&e['right']?[e['left'],e['right']]:[],i=h['findIndex'](k=>k?.['type']==='context'&&k?.['context']==='Signer'),j=i>=0x0?h[0x1-i]:undefined;if(j?.['type']==='identifier'&&!g){const k=b['find'](l=>Number(l?.['identifier'])===Number(j['identifier']));k&&k['b_submission']!==!![]&&k['value_type']==='Address'&&typeof k['value']==='string'&&k['value']['startsWith']('0x')&&k['value']['length']>0x2&&c['push'](String(k['value']));}}for(const l of[e['nodes'],e['left'],e['right']]['flat']()){if(l&&typeof l==='object')d(l,g);}};return d(a['root'],![]),c;}export async function detectProgressActionable(a,b,c,d){const e=(a['order_children']??[])['filter'](p=>p['type']==='progress'&&typeof p['object']==='string')['map'](p=>p['object'])['filter'](p=>p['startsWith']('0x')),f=(a['focus']??[])['map'](p=>p['object'])['filter'](p=>typeof p==='string'&&p['startsWith']('0x')),g=[...new Set([...e,...f])]['slice'](0x0,Math['max'](0x1,d));if(g['length']===0x0||(a['accounts']??[])['length']===0x0)return[];let h;try{h=await c['fetchProgressFields'](g,b);}catch{return[];}const i=new Map(),j=new Map(),k=new Map(),l=new Map(),m=c['fetchGuardJson']??(async(p,q)=>(await loadGuardJsonFromChain(p,q))?.['json']),n=a['accounts'],o=[];for(const [p,q]of h){const r=typeof q?.['machine']==='string'?q['machine']:undefined;if(!r)continue;const s=r['toLowerCase']();let t=i['get'](s);if(!t){try{t=await c['fetchMachineNodes'](r,b);}catch{t=[];}i['set'](s,t);}if(t['length']===0x0)continue;let u;if(!j['has'](s)){let B;try{B=await c['fetchMachinePermissionAddr'](r,b);}catch{B=undefined;}let C;if(B)try{C=await c['fetchPermissionContext'](B,b);}catch{C=undefined;}j['set'](s,C);}u=j['get'](s);const v=typeof q?.['task']==='string'?q['task']:undefined;let w;if(v){const D=v['toLowerCase']();if(!k['has'](D))try{k['set'](D,await c['fetchOrderContext'](v,b));}catch{k['set'](D,undefined);}w=k['get'](D);}const x=(Array['isArray'](q?.['namedOperator'])?q['namedOperator']:[])['map'](E=>({'name':String(E?.['name']??''),'operators':(Array['isArray'](E?.['operators'])?E['operators']:[])['map'](F=>String(F))})),y=enumerateActionableForwards(q,t,n,x,w,u),z=typeof q?.['current']==='string'?q['current']:'',A=v?'order\x20'+formatShortAddress(v):'no\x20bound\x20order';for(const E of y){let F=[];const G=typeof E['guard']==='string'?E['guard']['toLowerCase']():'';if(G){const H=l['get'](G);if(H!==undefined)F=H;else{let I;try{I=await m(E['guard'],b);}catch{I=undefined;}F=I?extractGuardSignerPins(I):[],l['set'](G,F);}}for(const J of E['executable_accounts']){if(F['length']>0x0){const N=F[0x0]['toLowerCase'](),O=F['every'](P=>P['toLowerCase']()===N);if(O&&N!==J['toLowerCase']())continue;}const K=E['threshold']>0x1?'\x20—\x20cooperation\x20threshold\x20'+E['threshold']+'\x20(weight\x20'+E['weight']+');\x20other\x20distinct\x20forwards\x20may\x20still\x20be\x20needed':'',L=E['guard']?'\x20—\x20guard\x20'+formatShortAddress(E['guard'])+'\x20must\x20be\x20satisfied\x20(submissions\x20may\x20be\x20required)':'',M=w&&J===w['builder']['toLowerCase']()?'You\x20are\x20the\x20order\x20owner':E['operator_kind']==='named_operator'?'You\x20hold\x20the\x20named-operator\x20role\x20\x27'+E['named_operator']+'\x27':'You\x20hold\x20the\x20required\x20permission\x20index';o['push']({'dedupe_key':'progress_actionable:'+p+':'+J+':'+E['next_node']+'|'+E['forward'],'detector':'progress_actionable','beneficiary':J,'object':p,'title':'Workflow\x20action\x20available:\x20\x27'+E['forward']+'\x27\x20→\x20'+E['next_node'],'detail':'Progress\x20'+formatShortAddress(p)+'\x20('+A+')\x20sits\x20at\x20node\x20\x27'+z+'\x27.\x20'+(M+'\x20—\x20you\x20can\x20execute\x20forward\x20\x27'+E['forward']+'\x27\x20into\x20\x27'+E['next_node']+'\x27')+(''+K+L+'.\x20Advance\x20it\x20via\x20workflow_operation\x20')+'(action=\x27list\x27\x20to\x20review,\x20action=\x27operate\x27\x20to\x20execute).\x20'+'Who\x20benefits,\x20who\x20pushes:\x20waiting\x20does\x20not\x20move\x20the\x20order\x20—\x20the\x20party\x20that\x20'+'gains\x20from\x20the\x20next\x20step\x20sends\x20the\x20transaction.','benefit':benefitOfNode(E['next_node']),'state_fingerprint':E['weight']+':'+E['threshold']+':'+(E['guard']??'')+':'+E['operator_kind']});}}}return o;}function benefitOfNode(a){if(/(^|_)(completed?|done|finished|received|delivered|accepted|confirmed|finalized|success|approved)(_|$)/i['test'](a))return'Completing\x20this\x20step\x20settles\x20the\x20order\x20—\x20funds\x20are\x20released\x20to\x20the\x20provider';if(/(^|_)(cancel(led)?|refund(ed)?|return(ed|_approved)?)(_|$)/i['test'](a))return'This\x20step\x20routes\x20to\x20cancellation/refund\x20—\x20funds\x20return\x20to\x20the\x20buyer';if(/(^|_)(interrupt(ed)?|exception|dispute(d)?|fail(ed)?|abort(ed)?|reject(ed)?)(_|$)/i['test'](a))return'This\x20step\x20opens\x20the\x20exception\x20path\x20—\x20review\x20before\x20advancing';return'Advancing\x20keeps\x20the\x20order\x20moving\x20toward\x20settlement';}const REFUND_FLAVOR_RE=/(^|_)(cancel(led)?|refund(ed)?|return(ed|_approved)?|expired)(_|$)/i;export async function detectSettlementPending(a,b,c,e){const f=(a['accounts']??[])['map'](s=>s['toLowerCase']());if(f['length']===0x0)return[];const g=(a['orders']??[])['slice'](0x0,Math['max'](0x1,e));if(g['length']===0x0)return[];const h=g['map'](s=>s['order'])['filter'](s=>typeof s==='string'&&s['startsWith']('0x'));let i;try{i=await c['fetchOrderFields'](h,b);}catch{return[];}const j=[],k=[];for(const s of i['values']()){const t=s?.['data']??s;if(typeof t?.['allocation']==='string'&&t['allocation']['startsWith']('0x'))j['push'](t['allocation']);if(typeof t?.['progress']==='string'&&t['progress']['startsWith']('0x'))k['push'](t['progress']);}let l=new Map(),m=new Map();try{l=await c['fetchAllocationFields']([...new Set(j)],b);}catch{return[];}try{m=await c['fetchProgressFields']([...new Set(k)],b);}catch{m=new Map();}const o=new Set((a['services']??[])['map'](u=>u['toLowerCase']())),q=new Map(),r=[];for(const [u,v]of i){const w=v?.['data']??v,x=typeof w?.['allocation']==='string'?w['allocation']:undefined;if(!x)continue;const y=l['get'](x['toLowerCase']());if(!y)continue;const z=y?.['data']??y,A=typeof z['balance']==='bigint'?z['balance']:BigInt(z['balance']??0x0);if(A<=0x0n)continue;const B=Array['isArray'](z['payment'])?z['payment']:[];if(B['length']>0x0)continue;const C=typeof w?.['progress']==='string'?w['progress']:undefined,D=C?m['get'](C['toLowerCase']()):undefined,E=typeof D?.['current']==='string'?D['current']:'',F=typeof D?.['machine']==='string'?D['machine']:typeof w?.['machine']==='string'?w['machine']:undefined;if(!E||!F)continue;let G=q['get'](F['toLowerCase']());if(!G){try{G=await c['fetchMachineNodes'](F,b);}catch{G=[];}q['set'](F['toLowerCase'](),G);}if(G['length']===0x0)continue;const H=new Set();for(const P of G){for(const Q of P['pairs']){if((Q['forwards']??[])['length']>0x0)H['add'](P['name']);}}if(H['has'](E))continue;const I=REFUND_FLAVOR_RE['test'](E),J=[];if(I){const R=typeof w?.['builder']==='string'?w['builder']['toLowerCase']():'';if(R&&f['includes'](R))J['push'](R);}else{const S=typeof w?.['service']==='string'?w['service']['toLowerCase']():'';if(S&&o['has'](S))J['push'](...f);}if(J['length']===0x0)continue;const K=(Array['isArray'](z['allocators']?.['allocators'])?z['allocators']['allocators']:[])['map'](T=>String(T?.['guard']??''))['filter'](T=>T),L=K['length']>0x0?'Candidate\x20settle\x20guards\x20on\x20this\x20pool:\x20'+K['map'](T=>formatShortAddress(T))['join'](',\x20')+'.':'This\x20pool\x20exposes\x20no\x20readable\x20allocator\x20guards\x20—\x20inspect\x20it\x20before\x20acting.';let M;try{M=await c['formatAmount']?.(A,extractCoinType(y?.['type_raw']),b);}catch{M=undefined;}const N=M??A['toString']()+'\x20(smallest\x20unit)',O=I?'refund/cancel':'completion';for(const T of J){r['push']({'dedupe_key':'settlement_pending:'+u+':'+x,'detector':'settlement_pending','beneficiary':T,'object':x,'title':'Unsettled\x20escrow\x20—\x20'+N+'\x20on\x20a\x20'+O+'\x20terminal','detail':'Order\x20'+formatShortAddress(u)+'\x20sits\x20on\x20terminal\x20node\x20\x27'+E+'\x27\x20but\x20its\x20Allocation\x20'+(formatShortAddress(x)+'\x20still\x20holds\x20'+N+'\x20and\x20has\x20emitted\x20no\x20Payment.\x20The\x20chain\x20never\x20')+('auto-settles:\x20someone\x20must\x20trigger\x20the\x20matching\x20guard.\x20'+L+'\x20Execute\x20via\x20allocation_operation\x20')+'(operation_type=\x27allocation\x27,\x20alloc_by_guard=<guard>)\x20as\x20an\x20account\x20that\x20can\x20satisfy\x20the\x20guard,\x20then\x20'+'recipients\x20claim\x20their\x20CoinWrappers\x20(payment\x20receive).\x20Trigger\x20ONCE\x20and\x20verify\x20the\x20pool\x20drained\x20—\x20a\x20'+'fully-drained\x20pool\x20aborts\x20on\x20re-trigger,\x20but\x20a\x20max-capped\x20pool\x20re-splits\x20the\x20remainder.\x20'+'Who\x20benefits,\x20who\x20pushes:\x20waiting\x20keeps\x20the\x20funds\x20frozen\x20and\x20leaves\x20the\x20dispute\x20window\x20open.','benefit':'Release\x20'+N+'\x20from\x20escrow\x20to\x20its\x20rightful\x20recipients','state_fingerprint':A['toString']()+':'+B['length']+':'+E});}}return r;}export async function detectTimeoutIntermediate(a,b,c,d,e){const f=(a['order_children']??[])['filter'](m=>m['type']==='progress'&&typeof m['object']==='string')['map'](m=>m['object'])['filter'](m=>m['startsWith']('0x')),g=(a['focus']??[])['map'](m=>m['object'])['filter'](m=>typeof m==='string'&&m['startsWith']('0x')),h=[...new Set([...f,...g])]['slice'](0x0,Math['max'](0x1,d));if(h['length']===0x0||(a['accounts']??[])['length']===0x0)return[];let i;try{i=await c['fetchProgressFields'](h,b);}catch{return[];}const j=c['nowMs'](),k=new Map(),l=[];for(const [m,n]of i){const o=typeof n?.['current']==='string'?n['current']:'',p=typeof n?.['current_time']==='number'?n['current_time']:0x0;if(!o||p<=0x0)continue;const q=typeof n?.['machine']==='string'?n['machine']:undefined;if(!q)continue;const r=q['toLowerCase']();let s=k['get'](r);if(!s){try{s=await c['fetchMachineNodes'](q,b);}catch{s=[];}k['set'](r,s);}const t=s['find'](A=>A['name']===o);if(!t)continue;const u=t['pairs']['some'](A=>(A['forwards']??[])['length']>0x0);if(!u)continue;const v=j-p;if(v<e)continue;const w=typeof n?.['task']==='string'?n['task']:undefined,x=(a['accounts']??[])['map'](A=>A['toLowerCase']()),y=x[0x0];if(!y)continue;const z=Math['floor'](v/(0x3e8*0x3c*0x3c));l['push']({'dedupe_key':'timeout_intermediate:'+m+':'+o,'detector':'timeout_intermediate','beneficiary':y,'object':m,'title':'Possible\x20stuck\x20intermediate\x20state\x20—\x20\x27'+o+'\x27\x20for\x20'+z+'h','detail':'Progress\x20'+formatShortAddress(m)+'\x20has\x20been\x20on\x20node\x20\x27'+o+'\x27\x20for\x20'+z+'\x20hours\x20'+('(since\x20'+new Date(p)['toISOString']()+').\x20This\x20node\x20has\x20outgoing\x20forwards\x20but\x20none\x20have\x20fired.\x20')+'If\x20this\x20node\x20has\x20a\x20time-lock\x20guard\x20(confirm\x20timeout,\x20acceptance\x20timeout,\x20inspection\x20timeout,\x20etc.),\x20'+'the\x20keeper\x20may\x20need\x20to\x20advance\x20it.\x20Check\x20the\x20template\x27s\x20keeper_dependencies\x20and\x20the\x20guard\x27s\x20time\x20window\x20'+'before\x20acting.\x20Who\x20benefits,\x20who\x20pushes:\x20a\x20stuck\x20intermediate\x20state\x20blocks\x20the\x20order\x27s\x20funds\x20and\x20'+'business\x20flow\x20—\x20the\x20party\x20that\x20gains\x20from\x20unblocking\x20it\x20sends\x20the\x20transaction.','benefit':'Unblock\x20the\x20order\x20stuck\x20at\x20\x27'+o+'\x27','state_fingerprint':o+':'+p+':'+v});}return l;}export function realPaymentDetectorDeps(){return{'queryUnclaimed':async(a,b)=>{const c=await query_received({'name_or_address':{'name_or_address':a},'type':'CoinWrapper','network':b});if(!c||typeof c!=='object'||!Array['isArray'](c['received']))return null;const d=typeof c['balance']==='bigint'?c['balance']:BigInt(c['balance']??0x0);return{'balance':d,'count':c['received']['length'],'token_type':typeof c['token_type']==='string'&&c['token_type']?c['token_type']:undefined};},'formatAmount':async(a,b,c)=>{if(!b)return undefined;const e=await formatChainValue(a,b,c),f=e['symbol']?'\x20'+e['symbol']:'';return e['precision_known']?''+e['display']+f:''+e['raw']+f;}};}export function realProgressDetectorDeps(){return{'fetchProgressFields':async(a,b)=>{const c=await batchQueryObjectsByIds(a,b,![]),e=new Map();for(const f of c??[]){const g=f?.['data']??f;if(f?.['type']!=='Progress')continue;const h=String(f?.['query_name']??f?.['object']??'')['toLowerCase']();if(h)e['set'](h,g);}return e;},'fetchMachineNodes':(a,b)=>fetchMachineNodes(a,b,![]),'fetchMachinePermissionAddr':async(a,b)=>{const c=await query_objects({'objects':[a],'network':b}),d=c?.['objects']?.[0x0],e=(d?.['data']??d)?.['permission'];return typeof e==='string'&&e?e:undefined;},'fetchPermissionContext':(a,b)=>fetchPermissionContext(a,b,![]),'fetchOrderContext':(a,b)=>fetchOrderContext(a,b,![])};}async function fieldsByType(a,b,c){const d=await batchQueryObjectsByIds(a,b,![]),e=new Map();for(const f of d??[]){if(f?.['type']!==c)continue;const g=String(f?.['query_name']??f?.['object']??'')['toLowerCase']();if(g)e['set'](g,f);}return e;}export function realSettlementDetectorDeps(){return{'fetchOrderFields':(a,b)=>fieldsByType(a,b,'Order'),'fetchAllocationFields':(a,b)=>fieldsByType(a,b,'Allocation'),'fetchProgressFields':async(a,b)=>{const c=await fieldsByType(a,b,'Progress'),d=new Map();for(const [e,f]of c)d['set'](e,f?.['data']??f);return d;},'fetchMachineNodes':(a,b)=>fetchMachineNodes(a,b,![]),'formatAmount':async(a,b,c)=>{if(!b)return undefined;const e=await formatChainValue(a,b,c),f=e['symbol']?'\x20'+e['symbol']:'';return e['precision_known']?''+e['display']+f:''+e['raw']+f;}};}export function realTimeoutDetectorDeps(){return{'fetchProgressFields':async(a,b)=>{const c=await fieldsByType(a,b,'Progress'),d=new Map();for(const [e,f]of c)d['set'](e,f?.['data']??f);return d;},'fetchMachineNodes':(a,b)=>fetchMachineNodes(a,b,![]),'nowMs':()=>Date['now']()};}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{describe,expect,it}from'vitest';import{KeeperStore}from'./KeeperStore.js';import{detectPaymentUnclaimed,detectProgressActionable,detectSettlementPending}from'./detectors.js';import{executeKeeperTask,runKeeperScan}from'./KeeperScan.js';import{clampKeeperConfig,defaultKeeperConfig,KEEPER_MIN}from'./types.js';const NET='testnet',ACCT='0xaaa111',OTHER='0xbbb222';function memStorage(){const a=new Map();return{'get':async b=>a['get'](b),'put':async(b,c)=>void a['set'](b,c)};}function makeStore(){return new KeeperStore(memStorage());}function paymentItem(a,b,c=0x1){return{'dedupe_key':'payment_unclaimed:'+a,'detector':'payment_unclaimed','beneficiary':a,'operation':{'operation_type':'payment','data':{'receive':!![]}},'title':'Unclaimed\x20funds\x20—\x20'+b+'\x20waiting','state_fingerprint':c+':'+b['toString']()};}function makeScope(a){return{'version':0x1,'resolved_at':0x0,'accounts':[ACCT],'permissions':[],'managed_objects':[],'services':[],'orders':[],'order_children':[],'focus':[],'index':{},...a};}describe('keeper\x20config',()=>{it('returns\x20safe\x20defaults:\x20reminders\x20ON,\x20auto\x20rules\x20none',async()=>{const a=makeStore(),b=await a['getConfig'](NET);expect(b['enabled'])['toBe'](!![]),expect(b['detectors']['payment_unclaimed'])['toBe'](!![]),expect(b['detectors']['progress_actionable'])['toBe'](!![]),expect(await a['listRules'](NET))['toEqual']([]);}),it('config_set\x20patch\x20merges\x20detectors\x20individually',async()=>{const a=makeStore(),b=await a['saveConfig'](NET,{'detectors':{'payment_unclaimed':![]}});expect(b['detectors']['payment_unclaimed'])['toBe'](![]),expect(b['detectors']['progress_actionable'])['toBe'](!![]);const c=await a['getConfig'](NET);expect(c['detectors']['payment_unclaimed'])['toBe'](![]),expect(c['detectors']['progress_actionable'])['toBe'](!![]);}),it('clamps\x20numeric\x20bounds\x20(cost/gas\x20guards)',()=>{const a=clampKeeperConfig({...defaultKeeperConfig(),'scan_interval_ms':0x1,'max_scan_objects':0x0,'max_auto_execute_per_scan':0x0,'auto_retry_cooldown_ms':0x0});expect(a['scan_interval_ms'])['toBe'](KEEPER_MIN['scan_interval_ms']),expect(a['max_scan_objects'])['toBe'](KEEPER_MIN['max_scan_objects']),expect(a['max_auto_execute_per_scan'])['toBe'](KEEPER_MIN['max_auto_execute_per_scan']),expect(a['auto_retry_cooldown_ms'])['toBe'](KEEPER_MIN['auto_retry_cooldown_ms']);});}),describe('keeper\x20rules',()=>{const a=b=>({'id':'krule_1','enabled':!![],'detector':'payment_unclaimed','accounts':[],'auto_execute':!![],'created_at':0x0,...b});it('matchingAutoRules\x20honors\x20enabled\x20/\x20auto_execute\x20/\x20account\x20coverage',async()=>{const b=makeStore();await b['upsertRule'](NET,a()),expect(await b['matchingAutoRules'](NET,'payment_unclaimed',ACCT))['toHaveLength'](0x1),expect(await b['matchingAutoRules'](NET,'progress_actionable',ACCT))['toHaveLength'](0x0),await b['upsertRule'](NET,a({'id':'krule_2','accounts':[OTHER['toUpperCase']()]})),expect(await b['matchingAutoRules'](NET,'payment_unclaimed',ACCT))['toHaveLength'](0x1),expect(await b['matchingAutoRules'](NET,'payment_unclaimed',OTHER))['toHaveLength'](0x2),await b['upsertRule'](NET,a({'id':'krule_3','enabled':![]})),await b['upsertRule'](NET,a({'id':'krule_4','auto_execute':![]}));const c=await b['matchingAutoRules'](NET,'payment_unclaimed',OTHER);expect(c['map'](d=>d['id'])['sort']())['toEqual'](['krule_1','krule_2']);});}),describe('KeeperStore.upsertDesired',()=>{it('opens\x20new\x20tasks,\x20refreshes\x20on\x20fingerprint\x20change,\x20no\x20churn\x20when\x20identical',async()=>{const a=makeStore();let b=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);expect(b)['toEqual']({'opened':0x1,'refreshed':0x0,'revived':0x0,'superseded':0x0}),b=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x7d0),expect(b)['toEqual']({'opened':0x0,'refreshed':0x0,'revived':0x0,'superseded':0x0}),b=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0xfan)],0xbb8),expect(b)['toEqual']({'opened':0x0,'refreshed':0x1,'revived':0x0,'superseded':0x0});const c=(await a['listTasks'](NET))[0x0];expect(c['title'])['toContain']('250'),expect(c['updated_at'])['toBe'](0xbb8);}),it('dismissed\x20stays\x20dismissed\x20for\x20identical\x20state,\x20revives\x20on\x20material\x20change',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);const b=(await a['listTasks'](NET))[0x0];await a['resolveTask'](NET,b['id'],'dismissed',0x5dc,'not\x20now');let c=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x7d0);expect(c['revived'])['toBe'](0x0),expect((await a['getTask'](NET,b['id']))['status'])['toBe']('dismissed'),c=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x190n,0x2)],0xbb8),expect(c['revived'])['toBe'](0x1);const d=await a['getTask'](NET,b['id']);expect(d['status'])['toBe']('pending'),expect(d['resolution'])['toBeUndefined'](),expect(d['resolved_at'])['toBeUndefined']();}),it('executed\x20tasks\x20are\x20terminal\x20—\x20same\x20dedupe_key\x20never\x20re-opens\x20them',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);const b=(await a['listTasks'](NET))[0x0];await a['resolveTask'](NET,b['id'],'auto_executed',0x5dc,'tx\x20ABC','krule_1');const c=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x1f4n)],0x7d0);expect(c)['toEqual']({'opened':0x0,'refreshed':0x0,'revived':0x0,'superseded':0x0});const d=await a['getTask'](NET,b['id']);expect(d['status'])['toBe']('executed'),expect(d['rule_id'])['toBe']('krule_1');}),it('supersedes\x20pending\x20tasks\x20of\x20THIS\x20detector\x20only',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8),await a['upsertDesired'](NET,'progress_actionable',[{'dedupe_key':'progress_actionable:0xp1:0xaaa111:shipped|deliver','detector':'progress_actionable','beneficiary':ACCT,'title':'Workflow\x20action\x20available','state_fingerprint':'1:1::named_operator'}],0x3e8);const b=await a['upsertDesired'](NET,'payment_unclaimed',[],0x7d0);expect(b['superseded'])['toBe'](0x1);const c=await a['listTasks'](NET),d=c['find'](f=>f['detector']==='payment_unclaimed'),e=c['find'](f=>f['detector']==='progress_actionable');expect(d['status'])['toBe']('superseded'),expect(d['resolution'])['toBe']('superseded'),expect(e['status'])['toBe']('pending');}),it('execute_failed\x20keeps\x20the\x20task\x20pending\x20with\x20failure\x20bookkeeping',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);const b=(await a['listTasks'](NET))[0x0];await a['resolveTask'](NET,b['id'],'execute_failed',0x1388,'insufficient\x20gas','krule_1');const c=await a['getTask'](NET,b['id']);expect(c['status'])['toBe']('pending'),expect(c['last_auto_attempt_at'])['toBe'](0x1388),expect(c['auto_attempts'])['toBe'](0x1),expect(c['resolution_note'])['toBe']('insufficient\x20gas');});}),describe('detectPaymentUnclaimed',()=>{it('emits\x20a\x20claim-to-self\x20task\x20for\x20accounts\x20with\x20unclaimed\x20wrappers',async()=>{const a=await detectPaymentUnclaimed([ACCT['toUpperCase'](),OTHER,'0xccc333'],NET,{'queryUnclaimed':async c=>{if(c===ACCT)return{'balance':0x64n,'count':0x2,'token_type':'0x2::wow::WOW'};if(c===OTHER)return{'balance':0x0n,'count':0x0};throw new Error('rpc\x20down');},'formatAmount':async()=>'0.0000001\x20WOW'});expect(a)['toHaveLength'](0x1);const b=a[0x0];expect(b['dedupe_key'])['toBe']('payment_unclaimed:'+ACCT),expect(b['beneficiary'])['toBe'](ACCT),expect(b['operation'])['toEqual']({'operation_type':'payment','data':{'receive':!![]}}),expect(b['state_fingerprint'])['toBe']('2:100'),expect(b['title'])['toContain']('0.0000001\x20WOW');}),it('falls\x20back\x20to\x20raw\x20units\x20when\x20formatting\x20fails',async()=>{const a=await detectPaymentUnclaimed([ACCT],NET,{'queryUnclaimed':async()=>({'balance':0x2an,'count':0x1}),'formatAmount':async()=>{throw new Error('no\x20metadata');}});expect(a[0x0]['title'])['toContain']('42\x20(smallest\x20unit)');});}),describe('detectProgressActionable',()=>{const a='0xprog1',b='0xmachine1',c=[{'name':'shipped','pairs':[{'prev_node':'start','threshold':0x1,'forwards':[{'name':'deliver','weight':0x1,'namedOperator':'courier'}]}]}],d=(g=[])=>({'machine':b,'current':'start','session':g,'namedOperator':[{'name':'courier','operators':[ACCT]}]}),e=g=>({'fetchProgressFields':async()=>new Map([[a,g]]),'fetchMachineNodes':async()=>c,'fetchMachinePermissionAddr':async()=>undefined,'fetchPermissionContext':async()=>undefined,'fetchOrderContext':async()=>undefined}),f=makeScope({'order_children':[{'type':'progress','object':a}]});it('routes\x20an\x20actionable\x20forward\x20to\x20its\x20named\x20operator',async()=>{const g=await detectProgressActionable(f,NET,e(d()),0x14);expect(g)['toHaveLength'](0x1),expect(g[0x0]['dedupe_key'])['toBe']('progress_actionable:'+a+':'+ACCT+':shipped|deliver'),expect(g[0x0]['beneficiary'])['toBe'](ACCT),expect(g[0x0]['operation'])['toBeUndefined'](),expect(g[0x0]['detail'])['toContain']('workflow_operation');}),it('omits\x20accomplished\x20forwards\x20(single-operator\x20lock)',async()=>{const g=[{'next_node':'shipped','forwards':[{'forward':'deliver','who':ACCT,'accomplished':!![]}]}],h=await detectProgressActionable(f,NET,e(d(g)),0x14);expect(h)['toHaveLength'](0x0);}),it('restricts\x20a\x20held\x20forward\x20to\x20its\x20holder',async()=>{const g=[{'next_node':'shipped','forwards':[{'forward':'deliver','who':OTHER,'accomplished':![]}]}],h=await detectProgressActionable(f,NET,e(d(g)),0x14);expect(h)['toHaveLength'](0x0);}),it('returns\x20nothing\x20when\x20the\x20batch\x20read\x20fails\x20(fail-safe)',async()=>{const g=await detectProgressActionable(f,NET,{...e(d()),'fetchProgressFields':async()=>{throw new Error('rpc\x20down');}},0x14);expect(g)['toEqual']([]);});}),describe('detectSettlementPending',()=>{const a='0xorder1',b='0xpool1',c='0xprog1',d='0xmachine1',e='0xsvc1',f=i=>[{'name':'paid','pairs':[{'prev_node':'','threshold':0x1,'forwards':[{'name':'settle','weight':0x1}]}]},{'name':i,'pairs':[{'prev_node':'paid','threshold':0x1,'forwards':[]}]}];function g(i,j,k,l){return{'fetchOrderFields':async()=>new Map([[a,{'type':'Order','object':a,'data':i}]]),'fetchAllocationFields':async()=>new Map([[b,{'type':'Allocation','object':b,'type_raw':'0x2::allocation::Allocation<0x2::coin::COIN>','data':j}]]),'fetchProgressFields':async()=>new Map([[c,k]]),'fetchMachineNodes':async()=>l};}const h={'allocation':b,'progress':c,'machine':d,'service':e,'builder':ACCT};it('routes\x20a\x20completion\x20terminal\x20with\x20an\x20unsettled\x20pool\x20to\x20the\x20merchant\x20account',async()=>{const i=makeScope({'services':[e],'orders':[{'order':a,'role':'merchant'}]}),j=await detectSettlementPending(i,NET,g(h,{'balance':'5000','payment':[],'allocators':{'allocators':[{'guard':'0xgsettle'}]}},{'current':'completed','machine':d},f('completed')),0x14);expect(j)['toHaveLength'](0x1),expect(j[0x0]['beneficiary'])['toBe'](ACCT),expect(j[0x0]['detector'])['toBe']('settlement_pending'),expect(j[0x0]['title'])['toContain']('completion'),expect(j[0x0]['detail'])['toContain']('alloc_by_guard');}),it('routes\x20a\x20refund\x20terminal\x20to\x20the\x20buyer\x20(order\x20builder)\x20account',async()=>{const i=makeScope({'orders':[{'order':a,'role':'buyer'}]}),j=await detectSettlementPending(i,NET,g(h,{'balance':'5000','payment':[],'allocators':{'allocators':[{'guard':'0xgrefund'}]}},{'current':'refunded','machine':d},f('refunded')),0x14);expect(j)['toHaveLength'](0x1),expect(j[0x0]['beneficiary'])['toBe'](ACCT),expect(j[0x0]['title'])['toContain']('refund/cancel');}),it('skips\x20a\x20pool\x20already\x20drained\x20(balance\x200)',async()=>{const i=makeScope({'services':[e],'orders':[{'order':a,'role':'merchant'}]}),j=await detectSettlementPending(i,NET,g(h,{'balance':'0','payment':[],'allocators':{'allocators':[]}},{'current':'completed','machine':d},f('completed')),0x14);expect(j)['toHaveLength'](0x0);}),it('skips\x20a\x20pool\x20that\x20already\x20emitted\x20a\x20Payment',async()=>{const i=makeScope({'services':[e],'orders':[{'order':a,'role':'merchant'}]}),j=await detectSettlementPending(i,NET,g(h,{'balance':'5000','payment':['0xpay1'],'allocators':{'allocators':[]}},{'current':'completed','machine':d},f('completed')),0x14);expect(j)['toHaveLength'](0x0);}),it('skips\x20a\x20non-terminal\x20node\x20(still\x20has\x20outgoing\x20forwards)',async()=>{const i=makeScope({'services':[e],'orders':[{'order':a,'role':'merchant'}]}),j=await detectSettlementPending(i,NET,g(h,{'balance':'5000','payment':[],'allocators':{'allocators':[]}},{'current':'paid','machine':d},f('completed')),0x14);expect(j)['toHaveLength'](0x0);}),it('returns\x20nothing\x20when\x20the\x20order\x20batch\x20read\x20fails\x20(fail-safe)',async()=>{const i=makeScope({'services':[e],'orders':[{'order':a,'role':'merchant'}]}),j=await detectSettlementPending(i,NET,{...g(h,{'balance':'5000','payment':[]},{'current':'completed','machine':d},f('completed')),'fetchOrderFields':async()=>{throw new Error('rpc\x20down');}},0x14);expect(j)['toEqual']([]);});});function scanDepsFor(a,b){let c=0x2710;const d=[],e={'store':a,'payment':{'queryUnclaimed':async()=>({'balance':0x64n,'count':0x1})},'progress':{'fetchProgressFields':async()=>new Map(),'fetchMachineNodes':async()=>[],'fetchMachinePermissionAddr':async()=>undefined,'fetchPermissionContext':async()=>undefined,'fetchOrderContext':async()=>undefined},'settlement':{'fetchOrderFields':async()=>new Map(),'fetchAllocationFields':async()=>new Map(),'fetchProgressFields':async()=>new Map(),'fetchMachineNodes':async()=>[]},'timeout':{'fetchProgressFields':async()=>new Map(),'fetchMachineNodes':async()=>[],'nowMs':()=>0x2710},'execute':async f=>{return d['push']({'operation_type':f['operation_type'],'account':f['account'],'via':f['via']}),{'ok':!![],'digest':'DIGEST1'};},'now':()=>c,'logger':()=>{},...b};return{'deps':e,'executed':d,'advance':f=>{c+=f;},'setClock':f=>{c=f;}};}describe('runKeeperScan',()=>{it('skips\x20when\x20disabled\x20and\x20when\x20inside\x20the\x20cadence\x20interval',async()=>{const a=makeStore(),{deps:b}=scanDepsFor(a);await a['saveConfig'](NET,{'enabled':![]});let c=await runKeeperScan(NET,makeScope(),b);expect(c['scanned'])['toBe'](![]),expect(c['reason'])['toBe']('disabled'),await a['saveConfig'](NET,{'enabled':!![]}),await a['setLastScanAt'](NET,0x2710),c=await runKeeperScan(NET,makeScope(),b),expect(c['scanned'])['toBe'](![]),expect(c['reason'])['toBe']('interval');}),it('auto-executes\x20a\x20payment\x20task\x20ONLY\x20with\x20a\x20covering\x20enabled\x20rule',async()=>{const a=makeStore(),{deps:b,executed:c}=scanDepsFor(a);let d=await runKeeperScan(NET,makeScope(),b,{'force':!![]});expect(d['opened'])['toBe'](0x1),expect(d['auto_executed'])['toBe'](0x0),expect(c)['toHaveLength'](0x0),await a['upsertRule'](NET,{'id':'krule_1','enabled':!![],'detector':'payment_unclaimed','accounts':[],'auto_execute':!![],'created_at':0x0}),d=await runKeeperScan(NET,makeScope(),b,{'force':!![]}),expect(d['auto_executed'])['toBe'](0x1),expect(c[0x0])['toEqual']({'operation_type':'payment','account':ACCT,'via':'rule\x20krule_1'});const e=(await a['listTasks'](NET))[0x0];expect(e['status'])['toBe']('executed'),expect(e['resolution'])['toBe']('auto_executed'),expect(e['rule_id'])['toBe']('krule_1'),expect(e['resolution_note'])['toContain']('DIGEST1');}),it('never\x20auto-executes\x20progress\x20tasks\x20(reminder-only\x20boundary)',async()=>{const a=makeStore(),{deps:b,executed:c}=scanDepsFor(a,{'payment':{'queryUnclaimed':async()=>null},'progress':{'fetchProgressFields':async()=>new Map([['0xprog1',{'machine':'0xm1','current':'start','session':[],'namedOperator':[{'name':'courier','operators':[ACCT]}]}]]),'fetchMachineNodes':async()=>[{'name':'shipped','pairs':[{'prev_node':'start','threshold':0x1,'forwards':[{'name':'deliver','weight':0x1,'namedOperator':'courier'}]}]}],'fetchMachinePermissionAddr':async()=>undefined,'fetchPermissionContext':async()=>undefined,'fetchOrderContext':async()=>undefined}});await a['upsertRule'](NET,{'id':'krule_p','enabled':!![],'detector':'progress_actionable','accounts':[],'auto_execute':!![],'created_at':0x0});const d=await runKeeperScan(NET,makeScope({'order_children':[{'type':'progress','object':'0xprog1'}]}),b,{'force':!![]});expect(d['opened'])['toBe'](0x1),expect(d['auto_executed'])['toBe'](0x0),expect(c)['toHaveLength'](0x0),expect((await a['listTasks'](NET))[0x0]['status'])['toBe']('pending');}),it('backs\x20off\x20after\x20a\x20failed\x20auto-exec\x20until\x20the\x20cooldown\x20passes',async()=>{const a=makeStore(),b=scanDepsFor(a,{'execute':async()=>({'ok':![],'error':'insufficient\x20gas'})});await a['upsertRule'](NET,{'id':'krule_1','enabled':!![],'detector':'payment_unclaimed','accounts':[],'auto_execute':!![],'created_at':0x0});let c=await runKeeperScan(NET,makeScope(),b['deps'],{'force':!![]});expect(c['auto_failed'])['toBe'](0x1);const d=(await a['listTasks'](NET))[0x0];expect(d['status'])['toBe']('pending'),expect(d['resolution_note'])['toBe']('insufficient\x20gas'),c=await runKeeperScan(NET,makeScope(),b['deps'],{'force':!![]}),expect(c['auto_failed'])['toBe'](0x0),expect(c['auto_executed'])['toBe'](0x0),b['advance'](0x1f*0xea60),c=await runKeeperScan(NET,makeScope(),b['deps'],{'force':!![]}),expect(c['auto_failed'])['toBe'](0x1);}),it('caps\x20auto-executions\x20per\x20scan\x20(gas\x20guard)',async()=>{const a=makeStore(),{deps:b,executed:c}=scanDepsFor(a);await a['saveConfig'](NET,{'max_auto_execute_per_scan':0x1}),await a['upsertRule'](NET,{'id':'krule_1','enabled':!![],'detector':'payment_unclaimed','accounts':[],'auto_execute':!![],'created_at':0x0});const d=makeScope({'accounts':[ACCT,OTHER]}),e=await runKeeperScan(NET,d,b,{'force':!![]});expect(e['opened'])['toBe'](0x2),expect(e['auto_executed'])['toBe'](0x1),expect(c)['toHaveLength'](0x1),expect(await a['listTasks'](NET,{'status':'pending'}))['toHaveLength'](0x1);});}),describe('executeKeeperTask\x20(manual)',()=>{it('resolves\x20a\x20payment\x20task\x20as\x20manual_executed',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);const b=(await a['listTasks'](NET))[0x0],{deps:c}=scanDepsFor(a),d=await executeKeeperTask(NET,b,c);expect(d['ok'])['toBe'](!![]);const e=await a['getTask'](NET,b['id']);expect(e['status'])['toBe']('executed'),expect(e['resolution'])['toBe']('manual_executed');}),it('refuses\x20reminder-only\x20tasks\x20(progress)\x20with\x20guidance',async()=>{const a=makeStore(),{deps:b}=scanDepsFor(a),c={'id':'ktask_x','dedupe_key':'progress_actionable:0xp:0xaaa111:shipped|deliver','detector':'progress_actionable','network':NET,'beneficiary':ACCT,'title':'Workflow\x20action\x20available','state_fingerprint':'1:1::named_operator','status':'pending','created_at':0x0,'updated_at':0x0},d=await executeKeeperTask(NET,c,b);expect(d['ok'])['toBe'](![]),expect(d['error'])['toContain']('reminder-only');});}),describe('timeout_intermediate',()=>{const a=0xa*0x5265c00,b={'current':'awaiting_host_confirmation','current_time':a-0x1e*0x36ee80,'machine':'0xmach1','task':'0xorder1'};function c(e,f){return{'fetchProgressFields':async()=>new Map(e===undefined?[]:[['0xprog1',e]]),'fetchMachineNodes':async()=>f,'nowMs':()=>a};}function d(e,f){return{'name':e,'pairs':[{'prev_node':'paid','threshold':0x0,'forwards':Array['from']({'length':f},()=>({}))}]};}it('surfaces\x20a\x20progress\x20stuck\x20on\x20an\x20intermediate\x20node\x20past\x20the\x20threshold',async()=>{const {detectTimeoutIntermediate:e}=await import('./detectors.js'),f=await e(makeScope({'order_children':[{'type':'progress','object':'0xprog1'}]}),NET,c(b,[d('awaiting_host_confirmation',0x1)]),0x14,0x18*0x36ee80);expect(f)['toHaveLength'](0x1),expect(f[0x0]['detector'])['toBe']('timeout_intermediate'),expect(f[0x0]['beneficiary'])['toBe'](ACCT);}),it('stays\x20silent\x20below\x20the\x20threshold,\x20on\x20terminal\x20nodes,\x20and\x20on\x20missing\x20data',async()=>{const {detectTimeoutIntermediate:e}=await import('./detectors.js'),f=makeScope({'order_children':[{'type':'progress','object':'0xprog1'}]}),g={...b,'current_time':a-0x1*0x36ee80};expect(await e(f,NET,c(g,[d('awaiting_host_confirmation',0x1)]),0x14,0x18*0x36ee80))['toHaveLength'](0x0),expect(await e(f,NET,c(b,[d('awaiting_host_confirmation',0x0)]),0x14,0x18*0x36ee80))['toHaveLength'](0x0),expect(await e(f,NET,c(undefined,[d('awaiting_host_confirmation',0x1)]),0x14,0x18*0x36ee80))['toHaveLength'](0x0);}),it('the\x20scan\x20wires\x20the\x20detector:\x20a\x20stuck\x20progress\x20opens\x20a\x20reminder\x20task\x20(never\x20auto-exec)',async()=>{const e=makeStore(),f=scanDepsFor(e,{'payment':{'queryUnclaimed':async()=>null}}),{deps:g}=f;g['timeout']=c(b,[d('awaiting_host_confirmation',0x1)]),await e['upsertRule'](NET,{'id':'krule_t','enabled':!![],'detector':'timeout_intermediate','accounts':[],'auto_execute':!![],'created_at':0x0});const h=await runKeeperScan(NET,makeScope({'order_children':[{'type':'progress','object':'0xprog1'}]}),g,{'force':!![]});expect(h['opened'])['toBe'](0x1),expect(h['auto_executed'])['toBe'](0x0);const i=(await e['listTasks'](NET))[0x0];expect(i['detector'])['toBe']('timeout_intermediate'),expect(i['status'])['toBe']('pending');});});
|
|
1
|
+
import{describe,expect,it}from'vitest';import{KeeperStore}from'./KeeperStore.js';import{detectPaymentUnclaimed,detectProgressActionable,detectSettlementPending}from'./detectors.js';import{executeKeeperTask,runKeeperScan}from'./KeeperScan.js';import{clampKeeperConfig,defaultKeeperConfig,KEEPER_MIN}from'./types.js';const NET='testnet',ACCT='0xaaa111',OTHER='0xbbb222';function memStorage(){const a=new Map();return{'get':async b=>a['get'](b),'put':async(b,c)=>void a['set'](b,c)};}function makeStore(){return new KeeperStore(memStorage());}function paymentItem(a,b,c=0x1){return{'dedupe_key':'payment_unclaimed:'+a,'detector':'payment_unclaimed','beneficiary':a,'operation':{'operation_type':'payment','data':{'receive':!![]}},'title':'Unclaimed\x20funds\x20—\x20'+b+'\x20waiting','state_fingerprint':c+':'+b['toString']()};}function makeScope(a){return{'version':0x1,'resolved_at':0x0,'accounts':[ACCT],'permissions':[],'managed_objects':[],'services':[],'orders':[],'order_children':[],'focus':[],'index':{},...a};}describe('keeper\x20config',()=>{it('returns\x20safe\x20defaults:\x20reminders\x20ON,\x20auto\x20rules\x20none',async()=>{const a=makeStore(),b=await a['getConfig'](NET);expect(b['enabled'])['toBe'](!![]),expect(b['detectors']['payment_unclaimed'])['toBe'](!![]),expect(b['detectors']['progress_actionable'])['toBe'](!![]),expect(await a['listRules'](NET))['toEqual']([]);}),it('config_set\x20patch\x20merges\x20detectors\x20individually',async()=>{const a=makeStore(),b=await a['saveConfig'](NET,{'detectors':{'payment_unclaimed':![]}});expect(b['detectors']['payment_unclaimed'])['toBe'](![]),expect(b['detectors']['progress_actionable'])['toBe'](!![]);const c=await a['getConfig'](NET);expect(c['detectors']['payment_unclaimed'])['toBe'](![]),expect(c['detectors']['progress_actionable'])['toBe'](!![]);}),it('clamps\x20numeric\x20bounds\x20(cost/gas\x20guards)',()=>{const a=clampKeeperConfig({...defaultKeeperConfig(),'scan_interval_ms':0x1,'max_scan_objects':0x0,'max_auto_execute_per_scan':0x0,'auto_retry_cooldown_ms':0x0});expect(a['scan_interval_ms'])['toBe'](KEEPER_MIN['scan_interval_ms']),expect(a['max_scan_objects'])['toBe'](KEEPER_MIN['max_scan_objects']),expect(a['max_auto_execute_per_scan'])['toBe'](KEEPER_MIN['max_auto_execute_per_scan']),expect(a['auto_retry_cooldown_ms'])['toBe'](KEEPER_MIN['auto_retry_cooldown_ms']);});}),describe('keeper\x20rules',()=>{const a=b=>({'id':'krule_1','enabled':!![],'detector':'payment_unclaimed','accounts':[],'auto_execute':!![],'created_at':0x0,...b});it('matchingAutoRules\x20honors\x20enabled\x20/\x20auto_execute\x20/\x20account\x20coverage',async()=>{const b=makeStore();await b['upsertRule'](NET,a()),expect(await b['matchingAutoRules'](NET,'payment_unclaimed',ACCT))['toHaveLength'](0x1),expect(await b['matchingAutoRules'](NET,'progress_actionable',ACCT))['toHaveLength'](0x0),await b['upsertRule'](NET,a({'id':'krule_2','accounts':[OTHER['toUpperCase']()]})),expect(await b['matchingAutoRules'](NET,'payment_unclaimed',ACCT))['toHaveLength'](0x1),expect(await b['matchingAutoRules'](NET,'payment_unclaimed',OTHER))['toHaveLength'](0x2),await b['upsertRule'](NET,a({'id':'krule_3','enabled':![]})),await b['upsertRule'](NET,a({'id':'krule_4','auto_execute':![]}));const c=await b['matchingAutoRules'](NET,'payment_unclaimed',OTHER);expect(c['map'](d=>d['id'])['sort']())['toEqual'](['krule_1','krule_2']);});}),describe('KeeperStore.upsertDesired',()=>{it('opens\x20new\x20tasks,\x20refreshes\x20on\x20fingerprint\x20change,\x20no\x20churn\x20when\x20identical',async()=>{const a=makeStore();let b=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);expect(b)['toEqual']({'opened':0x1,'refreshed':0x0,'revived':0x0,'superseded':0x0}),b=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x7d0),expect(b)['toEqual']({'opened':0x0,'refreshed':0x0,'revived':0x0,'superseded':0x0}),b=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0xfan)],0xbb8),expect(b)['toEqual']({'opened':0x0,'refreshed':0x1,'revived':0x0,'superseded':0x0});const c=(await a['listTasks'](NET))[0x0];expect(c['title'])['toContain']('250'),expect(c['updated_at'])['toBe'](0xbb8);}),it('dismissed\x20stays\x20dismissed\x20for\x20identical\x20state,\x20revives\x20on\x20material\x20change',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);const b=(await a['listTasks'](NET))[0x0];await a['resolveTask'](NET,b['id'],'dismissed',0x5dc,'not\x20now');let c=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x7d0);expect(c['revived'])['toBe'](0x0),expect((await a['getTask'](NET,b['id']))['status'])['toBe']('dismissed'),c=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x190n,0x2)],0xbb8),expect(c['revived'])['toBe'](0x1);const d=await a['getTask'](NET,b['id']);expect(d['status'])['toBe']('pending'),expect(d['resolution'])['toBeUndefined'](),expect(d['resolved_at'])['toBeUndefined']();}),it('executed\x20tasks\x20are\x20terminal\x20—\x20same\x20dedupe_key\x20never\x20re-opens\x20them',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);const b=(await a['listTasks'](NET))[0x0];await a['resolveTask'](NET,b['id'],'auto_executed',0x5dc,'tx\x20ABC','krule_1');const c=await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x1f4n)],0x7d0);expect(c)['toEqual']({'opened':0x0,'refreshed':0x0,'revived':0x0,'superseded':0x0});const d=await a['getTask'](NET,b['id']);expect(d['status'])['toBe']('executed'),expect(d['rule_id'])['toBe']('krule_1');}),it('supersedes\x20pending\x20tasks\x20of\x20THIS\x20detector\x20only',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8),await a['upsertDesired'](NET,'progress_actionable',[{'dedupe_key':'progress_actionable:0xp1:0xaaa111:shipped|deliver','detector':'progress_actionable','beneficiary':ACCT,'title':'Workflow\x20action\x20available','state_fingerprint':'1:1::named_operator'}],0x3e8);const b=await a['upsertDesired'](NET,'payment_unclaimed',[],0x7d0);expect(b['superseded'])['toBe'](0x1);const c=await a['listTasks'](NET),d=c['find'](f=>f['detector']==='payment_unclaimed'),e=c['find'](f=>f['detector']==='progress_actionable');expect(d['status'])['toBe']('superseded'),expect(d['resolution'])['toBe']('superseded'),expect(e['status'])['toBe']('pending');}),it('execute_failed\x20keeps\x20the\x20task\x20pending\x20with\x20failure\x20bookkeeping',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);const b=(await a['listTasks'](NET))[0x0];await a['resolveTask'](NET,b['id'],'execute_failed',0x1388,'insufficient\x20gas','krule_1');const c=await a['getTask'](NET,b['id']);expect(c['status'])['toBe']('pending'),expect(c['last_auto_attempt_at'])['toBe'](0x1388),expect(c['auto_attempts'])['toBe'](0x1),expect(c['resolution_note'])['toBe']('insufficient\x20gas');});}),describe('detectPaymentUnclaimed',()=>{it('emits\x20a\x20claim-to-self\x20task\x20for\x20accounts\x20with\x20unclaimed\x20wrappers',async()=>{const a=await detectPaymentUnclaimed([ACCT['toUpperCase'](),OTHER,'0xccc333'],NET,{'queryUnclaimed':async c=>{if(c===ACCT)return{'balance':0x64n,'count':0x2,'token_type':'0x2::wow::WOW'};if(c===OTHER)return{'balance':0x0n,'count':0x0};throw new Error('rpc\x20down');},'formatAmount':async()=>'0.0000001\x20WOW'});expect(a)['toHaveLength'](0x1);const b=a[0x0];expect(b['dedupe_key'])['toBe']('payment_unclaimed:'+ACCT),expect(b['beneficiary'])['toBe'](ACCT),expect(b['operation'])['toEqual']({'operation_type':'payment','data':{'receive':!![]}}),expect(b['state_fingerprint'])['toBe']('2:100'),expect(b['title'])['toContain']('0.0000001\x20WOW');}),it('falls\x20back\x20to\x20raw\x20units\x20when\x20formatting\x20fails',async()=>{const a=await detectPaymentUnclaimed([ACCT],NET,{'queryUnclaimed':async()=>({'balance':0x2an,'count':0x1}),'formatAmount':async()=>{throw new Error('no\x20metadata');}});expect(a[0x0]['title'])['toContain']('42\x20(smallest\x20unit)');});}),describe('detectProgressActionable',()=>{const a='0xprog1',b='0xmachine1',c=[{'name':'shipped','pairs':[{'prev_node':'start','threshold':0x1,'forwards':[{'name':'deliver','weight':0x1,'namedOperator':'courier'}]}]}],d=(j=[])=>({'machine':b,'current':'start','session':j,'namedOperator':[{'name':'courier','operators':[ACCT]}]}),e=j=>({'fetchProgressFields':async()=>new Map([[a,j]]),'fetchMachineNodes':async()=>c,'fetchMachinePermissionAddr':async()=>undefined,'fetchPermissionContext':async()=>undefined,'fetchOrderContext':async()=>undefined}),f=makeScope({'order_children':[{'type':'progress','object':a}]});it('routes\x20an\x20actionable\x20forward\x20to\x20its\x20named\x20operator',async()=>{const j=await detectProgressActionable(f,NET,e(d()),0x14);expect(j)['toHaveLength'](0x1),expect(j[0x0]['dedupe_key'])['toBe']('progress_actionable:'+a+':'+ACCT+':shipped|deliver'),expect(j[0x0]['beneficiary'])['toBe'](ACCT),expect(j[0x0]['operation'])['toBeUndefined'](),expect(j[0x0]['detail'])['toContain']('workflow_operation');}),it('omits\x20accomplished\x20forwards\x20(single-operator\x20lock)',async()=>{const j=[{'next_node':'shipped','forwards':[{'forward':'deliver','who':ACCT,'accomplished':!![]}]}],k=await detectProgressActionable(f,NET,e(d(j)),0x14);expect(k)['toHaveLength'](0x0);}),it('restricts\x20a\x20held\x20forward\x20to\x20its\x20holder',async()=>{const j=[{'next_node':'shipped','forwards':[{'forward':'deliver','who':OTHER,'accomplished':![]}]}],k=await detectProgressActionable(f,NET,e(d(j)),0x14);expect(k)['toHaveLength'](0x0);}),it('returns\x20nothing\x20when\x20the\x20batch\x20read\x20fails\x20(fail-safe)',async()=>{const j=await detectProgressActionable(f,NET,{...e(d()),'fetchProgressFields':async()=>{throw new Error('rpc\x20down');}},0x14);expect(j)['toEqual']([]);});const g=[{'name':'shipped','pairs':[{'prev_node':'start','threshold':0x1,'forwards':[{'name':'deliver','weight':0x1,'namedOperator':'courier','guard':'0xguard1'}]}]}],h=(j,k=OTHER)=>({'table':[{'identifier':0x2,'b_submission':![],'value_type':'Address','value':k}],'root':j}),i=(j,k)=>({...e(j),'fetchMachineNodes':async()=>g,'fetchGuardJson':async()=>k});it('skips\x20the\x20task\x20when\x20the\x20guard\x20pins\x20the\x20Signer\x20to\x20another\x20account',async()=>{const j=h({'type':'logic_equal','nodes':[{'type':'context','context':'Signer'},{'type':'identifier','identifier':0x2}]}),k=await detectProgressActionable(f,NET,i(d(),j),0x14);expect(k)['toEqual']([]);}),it('keeps\x20the\x20task\x20when\x20the\x20guard\x20pins\x20the\x20Signer\x20to\x20the\x20beneficiary\x20itself',async()=>{const j=h({'type':'logic_equal','nodes':[{'type':'identifier','identifier':0x2},{'type':'context','context':'Signer'}]},ACCT),k=await detectProgressActionable(f,NET,i(d(),j),0x14);expect(k)['toHaveLength'](0x1);}),it('fail-open:\x20unreadable\x20guard\x20JSON\x20still\x20emits\x20the\x20task',async()=>{const j=await detectProgressActionable(f,NET,i(d(),undefined),0x14);expect(j)['toHaveLength'](0x1);}),it('fail-open:\x20a\x20Signer\x20pin\x20inside\x20a\x20logic_or\x20branch\x20is\x20only\x20an\x20alternative,\x20not\x20a\x20pin',async()=>{const j=h({'type':'logic_or','nodes':[{'type':'logic_equal','nodes':[{'type':'context','context':'Signer'},{'type':'identifier','identifier':0x2}]},{'type':'logic_equal','nodes':[{'type':'context','context':'Signer'},{'type':'identifier','identifier':0x2}]}]}),k=await detectProgressActionable(f,NET,i(d(),j),0x14);expect(k)['toHaveLength'](0x1);}),it('fail-open:\x20a\x20dynamic\x20query\x20operand\x20(order.owner\x20==\x20Signer)\x20is\x20not\x20a\x20pin',async()=>{const j={'table':[{'identifier':0x2,'b_submission':![],'value_type':'Address','value':OTHER}],'root':{'type':'logic_equal','nodes':[{'type':'context','context':'Signer'},{'type':'query','id':0x61a}]}},k=await detectProgressActionable(f,NET,i(d(),j),0x14);expect(k)['toHaveLength'](0x1);});}),describe('detectSettlementPending',()=>{const a='0xorder1',b='0xpool1',c='0xprog1',d='0xmachine1',e='0xsvc1',f=i=>[{'name':'paid','pairs':[{'prev_node':'','threshold':0x1,'forwards':[{'name':'settle','weight':0x1}]}]},{'name':i,'pairs':[{'prev_node':'paid','threshold':0x1,'forwards':[]}]}];function g(i,j,k,l){return{'fetchOrderFields':async()=>new Map([[a,{'type':'Order','object':a,'data':i}]]),'fetchAllocationFields':async()=>new Map([[b,{'type':'Allocation','object':b,'type_raw':'0x2::allocation::Allocation<0x2::coin::COIN>','data':j}]]),'fetchProgressFields':async()=>new Map([[c,k]]),'fetchMachineNodes':async()=>l};}const h={'allocation':b,'progress':c,'machine':d,'service':e,'builder':ACCT};it('routes\x20a\x20completion\x20terminal\x20with\x20an\x20unsettled\x20pool\x20to\x20the\x20merchant\x20account',async()=>{const i=makeScope({'services':[e],'orders':[{'order':a,'role':'merchant'}]}),j=await detectSettlementPending(i,NET,g(h,{'balance':'5000','payment':[],'allocators':{'allocators':[{'guard':'0xgsettle'}]}},{'current':'completed','machine':d},f('completed')),0x14);expect(j)['toHaveLength'](0x1),expect(j[0x0]['beneficiary'])['toBe'](ACCT),expect(j[0x0]['detector'])['toBe']('settlement_pending'),expect(j[0x0]['title'])['toContain']('completion'),expect(j[0x0]['detail'])['toContain']('alloc_by_guard');}),it('routes\x20a\x20refund\x20terminal\x20to\x20the\x20buyer\x20(order\x20builder)\x20account',async()=>{const i=makeScope({'orders':[{'order':a,'role':'buyer'}]}),j=await detectSettlementPending(i,NET,g(h,{'balance':'5000','payment':[],'allocators':{'allocators':[{'guard':'0xgrefund'}]}},{'current':'refunded','machine':d},f('refunded')),0x14);expect(j)['toHaveLength'](0x1),expect(j[0x0]['beneficiary'])['toBe'](ACCT),expect(j[0x0]['title'])['toContain']('refund/cancel');}),it('skips\x20a\x20pool\x20already\x20drained\x20(balance\x200)',async()=>{const i=makeScope({'services':[e],'orders':[{'order':a,'role':'merchant'}]}),j=await detectSettlementPending(i,NET,g(h,{'balance':'0','payment':[],'allocators':{'allocators':[]}},{'current':'completed','machine':d},f('completed')),0x14);expect(j)['toHaveLength'](0x0);}),it('skips\x20a\x20pool\x20that\x20already\x20emitted\x20a\x20Payment',async()=>{const i=makeScope({'services':[e],'orders':[{'order':a,'role':'merchant'}]}),j=await detectSettlementPending(i,NET,g(h,{'balance':'5000','payment':['0xpay1'],'allocators':{'allocators':[]}},{'current':'completed','machine':d},f('completed')),0x14);expect(j)['toHaveLength'](0x0);}),it('skips\x20a\x20non-terminal\x20node\x20(still\x20has\x20outgoing\x20forwards)',async()=>{const i=makeScope({'services':[e],'orders':[{'order':a,'role':'merchant'}]}),j=await detectSettlementPending(i,NET,g(h,{'balance':'5000','payment':[],'allocators':{'allocators':[]}},{'current':'paid','machine':d},f('completed')),0x14);expect(j)['toHaveLength'](0x0);}),it('returns\x20nothing\x20when\x20the\x20order\x20batch\x20read\x20fails\x20(fail-safe)',async()=>{const i=makeScope({'services':[e],'orders':[{'order':a,'role':'merchant'}]}),j=await detectSettlementPending(i,NET,{...g(h,{'balance':'5000','payment':[]},{'current':'completed','machine':d},f('completed')),'fetchOrderFields':async()=>{throw new Error('rpc\x20down');}},0x14);expect(j)['toEqual']([]);});});function scanDepsFor(a,b){let c=0x2710;const d=[],e={'store':a,'payment':{'queryUnclaimed':async()=>({'balance':0x64n,'count':0x1})},'progress':{'fetchProgressFields':async()=>new Map(),'fetchMachineNodes':async()=>[],'fetchMachinePermissionAddr':async()=>undefined,'fetchPermissionContext':async()=>undefined,'fetchOrderContext':async()=>undefined},'settlement':{'fetchOrderFields':async()=>new Map(),'fetchAllocationFields':async()=>new Map(),'fetchProgressFields':async()=>new Map(),'fetchMachineNodes':async()=>[]},'timeout':{'fetchProgressFields':async()=>new Map(),'fetchMachineNodes':async()=>[],'nowMs':()=>0x2710},'execute':async f=>{return d['push']({'operation_type':f['operation_type'],'account':f['account'],'via':f['via']}),{'ok':!![],'digest':'DIGEST1'};},'now':()=>c,'logger':()=>{},...b};return{'deps':e,'executed':d,'advance':f=>{c+=f;},'setClock':f=>{c=f;}};}describe('runKeeperScan',()=>{it('skips\x20when\x20disabled\x20and\x20when\x20inside\x20the\x20cadence\x20interval',async()=>{const a=makeStore(),{deps:b}=scanDepsFor(a);await a['saveConfig'](NET,{'enabled':![]});let c=await runKeeperScan(NET,makeScope(),b);expect(c['scanned'])['toBe'](![]),expect(c['reason'])['toBe']('disabled'),await a['saveConfig'](NET,{'enabled':!![]}),await a['setLastScanAt'](NET,0x2710),c=await runKeeperScan(NET,makeScope(),b),expect(c['scanned'])['toBe'](![]),expect(c['reason'])['toBe']('interval');}),it('auto-executes\x20a\x20payment\x20task\x20ONLY\x20with\x20a\x20covering\x20enabled\x20rule',async()=>{const a=makeStore(),{deps:b,executed:c}=scanDepsFor(a);let d=await runKeeperScan(NET,makeScope(),b,{'force':!![]});expect(d['opened'])['toBe'](0x1),expect(d['auto_executed'])['toBe'](0x0),expect(c)['toHaveLength'](0x0),await a['upsertRule'](NET,{'id':'krule_1','enabled':!![],'detector':'payment_unclaimed','accounts':[],'auto_execute':!![],'created_at':0x0}),d=await runKeeperScan(NET,makeScope(),b,{'force':!![]}),expect(d['auto_executed'])['toBe'](0x1),expect(c[0x0])['toEqual']({'operation_type':'payment','account':ACCT,'via':'rule\x20krule_1'});const e=(await a['listTasks'](NET))[0x0];expect(e['status'])['toBe']('executed'),expect(e['resolution'])['toBe']('auto_executed'),expect(e['rule_id'])['toBe']('krule_1'),expect(e['resolution_note'])['toContain']('DIGEST1');}),it('never\x20auto-executes\x20progress\x20tasks\x20(reminder-only\x20boundary)',async()=>{const a=makeStore(),{deps:b,executed:c}=scanDepsFor(a,{'payment':{'queryUnclaimed':async()=>null},'progress':{'fetchProgressFields':async()=>new Map([['0xprog1',{'machine':'0xm1','current':'start','session':[],'namedOperator':[{'name':'courier','operators':[ACCT]}]}]]),'fetchMachineNodes':async()=>[{'name':'shipped','pairs':[{'prev_node':'start','threshold':0x1,'forwards':[{'name':'deliver','weight':0x1,'namedOperator':'courier'}]}]}],'fetchMachinePermissionAddr':async()=>undefined,'fetchPermissionContext':async()=>undefined,'fetchOrderContext':async()=>undefined}});await a['upsertRule'](NET,{'id':'krule_p','enabled':!![],'detector':'progress_actionable','accounts':[],'auto_execute':!![],'created_at':0x0});const d=await runKeeperScan(NET,makeScope({'order_children':[{'type':'progress','object':'0xprog1'}]}),b,{'force':!![]});expect(d['opened'])['toBe'](0x1),expect(d['auto_executed'])['toBe'](0x0),expect(c)['toHaveLength'](0x0),expect((await a['listTasks'](NET))[0x0]['status'])['toBe']('pending');}),it('backs\x20off\x20after\x20a\x20failed\x20auto-exec\x20until\x20the\x20cooldown\x20passes',async()=>{const a=makeStore(),b=scanDepsFor(a,{'execute':async()=>({'ok':![],'error':'insufficient\x20gas'})});await a['upsertRule'](NET,{'id':'krule_1','enabled':!![],'detector':'payment_unclaimed','accounts':[],'auto_execute':!![],'created_at':0x0});let c=await runKeeperScan(NET,makeScope(),b['deps'],{'force':!![]});expect(c['auto_failed'])['toBe'](0x1);const d=(await a['listTasks'](NET))[0x0];expect(d['status'])['toBe']('pending'),expect(d['resolution_note'])['toBe']('insufficient\x20gas'),c=await runKeeperScan(NET,makeScope(),b['deps'],{'force':!![]}),expect(c['auto_failed'])['toBe'](0x0),expect(c['auto_executed'])['toBe'](0x0),b['advance'](0x1f*0xea60),c=await runKeeperScan(NET,makeScope(),b['deps'],{'force':!![]}),expect(c['auto_failed'])['toBe'](0x1);}),it('caps\x20auto-executions\x20per\x20scan\x20(gas\x20guard)',async()=>{const a=makeStore(),{deps:b,executed:c}=scanDepsFor(a);await a['saveConfig'](NET,{'max_auto_execute_per_scan':0x1}),await a['upsertRule'](NET,{'id':'krule_1','enabled':!![],'detector':'payment_unclaimed','accounts':[],'auto_execute':!![],'created_at':0x0});const d=makeScope({'accounts':[ACCT,OTHER]}),e=await runKeeperScan(NET,d,b,{'force':!![]});expect(e['opened'])['toBe'](0x2),expect(e['auto_executed'])['toBe'](0x1),expect(c)['toHaveLength'](0x1),expect(await a['listTasks'](NET,{'status':'pending'}))['toHaveLength'](0x1);});}),describe('executeKeeperTask\x20(manual)',()=>{it('resolves\x20a\x20payment\x20task\x20as\x20manual_executed',async()=>{const a=makeStore();await a['upsertDesired'](NET,'payment_unclaimed',[paymentItem(ACCT,0x64n)],0x3e8);const b=(await a['listTasks'](NET))[0x0],{deps:c}=scanDepsFor(a),d=await executeKeeperTask(NET,b,c);expect(d['ok'])['toBe'](!![]);const e=await a['getTask'](NET,b['id']);expect(e['status'])['toBe']('executed'),expect(e['resolution'])['toBe']('manual_executed');}),it('refuses\x20reminder-only\x20tasks\x20(progress)\x20with\x20guidance',async()=>{const a=makeStore(),{deps:b}=scanDepsFor(a),c={'id':'ktask_x','dedupe_key':'progress_actionable:0xp:0xaaa111:shipped|deliver','detector':'progress_actionable','network':NET,'beneficiary':ACCT,'title':'Workflow\x20action\x20available','state_fingerprint':'1:1::named_operator','status':'pending','created_at':0x0,'updated_at':0x0},d=await executeKeeperTask(NET,c,b);expect(d['ok'])['toBe'](![]),expect(d['error'])['toContain']('reminder-only');});}),describe('timeout_intermediate',()=>{const a=0xa*0x5265c00,b={'current':'awaiting_host_confirmation','current_time':a-0x1e*0x36ee80,'machine':'0xmach1','task':'0xorder1'};function c(e,f){return{'fetchProgressFields':async()=>new Map(e===undefined?[]:[['0xprog1',e]]),'fetchMachineNodes':async()=>f,'nowMs':()=>a};}function d(e,f){return{'name':e,'pairs':[{'prev_node':'paid','threshold':0x0,'forwards':Array['from']({'length':f},()=>({}))}]};}it('surfaces\x20a\x20progress\x20stuck\x20on\x20an\x20intermediate\x20node\x20past\x20the\x20threshold',async()=>{const {detectTimeoutIntermediate:e}=await import('./detectors.js'),f=await e(makeScope({'order_children':[{'type':'progress','object':'0xprog1'}]}),NET,c(b,[d('awaiting_host_confirmation',0x1)]),0x14,0x18*0x36ee80);expect(f)['toHaveLength'](0x1),expect(f[0x0]['detector'])['toBe']('timeout_intermediate'),expect(f[0x0]['beneficiary'])['toBe'](ACCT);}),it('stays\x20silent\x20below\x20the\x20threshold,\x20on\x20terminal\x20nodes,\x20and\x20on\x20missing\x20data',async()=>{const {detectTimeoutIntermediate:e}=await import('./detectors.js'),f=makeScope({'order_children':[{'type':'progress','object':'0xprog1'}]}),g={...b,'current_time':a-0x1*0x36ee80};expect(await e(f,NET,c(g,[d('awaiting_host_confirmation',0x1)]),0x14,0x18*0x36ee80))['toHaveLength'](0x0),expect(await e(f,NET,c(b,[d('awaiting_host_confirmation',0x0)]),0x14,0x18*0x36ee80))['toHaveLength'](0x0),expect(await e(f,NET,c(undefined,[d('awaiting_host_confirmation',0x1)]),0x14,0x18*0x36ee80))['toHaveLength'](0x0);}),it('the\x20scan\x20wires\x20the\x20detector:\x20a\x20stuck\x20progress\x20opens\x20a\x20reminder\x20task\x20(never\x20auto-exec)',async()=>{const e=makeStore(),f=scanDepsFor(e,{'payment':{'queryUnclaimed':async()=>null}}),{deps:g}=f;g['timeout']=c(b,[d('awaiting_host_confirmation',0x1)]),await e['upsertRule'](NET,{'id':'krule_t','enabled':!![],'detector':'timeout_intermediate','accounts':[],'auto_execute':!![],'created_at':0x0});const h=await runKeeperScan(NET,makeScope({'order_children':[{'type':'progress','object':'0xprog1'}]}),g,{'force':!![]});expect(h['opened'])['toBe'](0x1),expect(h['auto_executed'])['toBe'](0x0);const i=(await e['listTasks'](NET))[0x0];expect(i['detector'])['toBe']('timeout_intermediate'),expect(i['status'])['toBe']('pending');});});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const SYM_NODE='progress.current',SYM_CLAIMED='order.claimed_by\x20some';function slotValue(a,b){if(b===undefined)return{'value':undefined,'isSubmission':![]};const c=a['find'](d=>d['identifier']===b);if(!c)return{'value':undefined,'isSubmission':![]};return{'value':c['value'],'isSubmission':c['b_submission']===!![]};}function classifyQueryLhs(a){if(a===SYM_NODE)return{'kind':'node'};if(a===SYM_CLAIMED)return{'kind':'claimed'};return{'kind':'unknown'};}function resolveValue(a,b){if(!b||b['type']!=='identifier')return{'known':![]};const c=slotValue(a,b['identifier']);if(c['isSubmission'])return{'known':![]};if(c['value']===undefined)return{'known':![]};return{'known':!![],'value':c['value']};}function evaluate(a,b,d){if(!b||typeof b['type']!=='string')return undefined;switch(b['type']){case'logic_and':{const e=Array['isArray'](b['nodes'])?b['nodes']:[];let f=![];for(const g of e){const h=evaluate(a,g,d);if(h===![])return![];if(h===undefined)f=!![];}return f?undefined:!![];}case'logic_or':{const i=Array['isArray'](b['nodes'])?b['nodes']:[];let j=![];for(const k of i){const l=evaluate(a,k,d);if(l===!![])return!![];if(l===undefined)j=!![];}return j?undefined:![];}case'logic_not':{const m=evaluate(a,b['node'],d);if(m===undefined)return undefined;return!m;}case'logic_equal':{const n=Array['isArray'](b['nodes'])?b['nodes']:[];if(n['length']<0x2)return undefined;const o=classifyQueryLhs(n[0x0]?.['query']),p=resolveValue(a,n[0x1]),q=o['kind']==='unknown'?classifyQueryLhs(n[0x1]?.['query']):o,r=!p['known']&&n[0x1]?.['query']!==undefined?resolveValue(a,n[0x0]):p;if(q['kind']==='node'){if(!r['known']||typeof r['value']!=='string')return undefined;return d['node']===r['value'];}if(q['kind']==='claimed'){if(!r['known']||typeof r['value']!=='boolean')return undefined;return d['claimed']===r['value'];}return undefined;}default:return undefined;}}function satisfiable(a,b,c){return evaluate(a,b,c)!==![];}function findDeadLiterals(a,b,c,d){if(!a||typeof a['type']!=='string')return;if(a['type']==='logic_and'&&Array['isArray'](a['nodes'])){const e=new Map();for(const f of a['nodes']){const g=resolvableEquality(f,b);if(g)e['set'](g['symbol'],g['value']);}for(const h of a['nodes']){const i=resolvableEquality(h,b);if(i){const k=e['get'](i['symbol']);if(k!==undefined&&k!==i['value']){d['push']({'code':'RAIL_DEAD_LITERAL','detail':deadLiteralDetail(c,i['symbol'],k,i['value'])});return;}continue;}const j=findClash(h,b,e);if(j){d['push']({'code':'RAIL_DEAD_LITERAL','detail':deadLiteralDetail(c,j['symbol'],j['pinned'],j['value'])});return;}}for(const l of a['nodes'])findDeadLiterals(l,b,c,d);return;}if(Array['isArray'](a['nodes'])){for(const m of a['nodes'])findDeadLiterals(m,b,c,d);}if(a['node'])findDeadLiterals(a['node'],b,c,d);}function resolvableEquality(c,d){if(!c||c['type']!=='logic_equal'||!Array['isArray'](c['nodes']))return undefined;for(const [e,f]of[[c['nodes'][0x0],c['nodes'][0x1]],[c['nodes'][0x1],c['nodes'][0x0]]]){if(!e||typeof e['query']!=='string')continue;const g=classifyQueryLhs(e['query']);if(g['kind']==='unknown')continue;const h=resolveValue(d,f);if(!h['known'])continue;return{'symbol':g['kind']==='node'?SYM_NODE:SYM_CLAIMED,'value':h['value']};}return undefined;}function findClash(a,b,c){if(!a||typeof a['type']!=='string')return undefined;if(a['type']==='logic_not')return undefined;const d=resolvableEquality(a,b);if(d){const e=c['get'](d['symbol']);if(e!==undefined&&e!==d['value'])return{'symbol':d['symbol'],'pinned':e,'value':d['value']};return undefined;}if(Array['isArray'](a['nodes']))for(const f of a['nodes']){const g=findClash(f,b,c);if(g)return g;}if(a['node'])return findClash(a['node'],b,c);return undefined;}function deadLiteralDetail(a,b,c,d){return'allocator\x20guard\x20\x27'+a+'\x27:\x20one\x20conjunction\x20scope\x20carries\x20'+b+'\x20'+('==\x20'+JSON['stringify'](c)+'\x20and\x20ALSO\x20'+b+'\x20==\x20'+JSON['stringify'](d)+'\x20—\x20the\x20second\x20')+'literal\x20contradicts\x20the\x20first\x20and\x20is\x20a\x20DEAD\x20literal\x20(azx7-mn-261014\x20CR-azx7-01:\x20a\x20pinned\x20'+'node\x20equality\x20made\x20the\x20sibling\x20closed_cancel/item_lost\x20legs\x20unreachable,\x20stranding\x20the\x20'+'escrow\x20at\x20every\x20other\x20terminal).\x20Hoist\x20the\x20node\x20predicate\x20to\x20ONE\x20top-level\x20n-ary\x20logic_or\x20'+'instead\x20of\x20AND-prepending\x20a\x20single-node\x20gate.';}export function verifyAllocatorRails(a,b){const c=[];if(a['length']===0x0||b['length']===0x0)return c;const d=b['filter'](i=>i['semanticRole']==='cancelled'||i['semanticRole']==='final'),e=b['map'](i=>({'node':i['name'],'claimed':!![]}));for(const i of a){if(i['root']===undefined)continue;const j=i['table'];findDeadLiterals(i['root'],j,i['key'],c);}for(const k of d){const l={'node':k['name'],'claimed':![]},m=a['some'](n=>satisfiable(n['table'],n['root'],l));!m&&c['push']({'code':'RAIL_TERMINAL_UNCOVERED','detail':'terminal\x20node\x20\x27'+k['name']+'\x27\x20(role\x20'+k['semanticRole']+')\x20has\x20NO\x20allocator\x20rail\x20'+'satisfiable\x20at\x20claimed_by=none\x20—\x20a\x20normal\x20(unclaimed)\x20order\x20reaching\x20this\x20'+'terminal\x20strands\x20its\x20escrow\x20forever\x20(azx7-mn-261014\x20CR-azx7-01:\x20refund\x20'+'rejected\x20abort\x207\x20at\x20closed_cancel/item_lost;\x20crs-mn-261014\x20F-30:\x20double-'+'negated\x20claimed_by\x20leg\x20bricked\x20the\x20refund\x20at\x20returned).\x20Guards/allocators\x20'+'freeze\x20at\x20publish\x20—\x20fix\x20the\x20rail\x20polarity/node-set\x20BEFORE\x20publishing.'});}const f=a['some'](n=>e['some'](o=>satisfiable(n['table'],n['root'],o)));!f&&c['push']({'code':'RAIL_AWARD_EXIT_MISSING','detail':'no\x20allocator\x20rail\x20is\x20satisfiable\x20at\x20claimed_by=some\x20on\x20ANY\x20machine\x20node\x20—\x20an\x20'+'arbitration-paid\x20order\x20has\x20NO\x20escrow\x20exit\x20(escrow-exit\x20invariant,\x20az-mn-261007).\x20'+'Pair\x20the\x20refund\x20rail\x20with\x20a\x20merchant-recovery\x20allocator\x20asserting\x20order.claimed_by\x20'+'some\x20==\x20true\x20(query\x201570)\x20on\x20the\x20post-delivery\x20node\x20set.'});const h=a['filter'](n=>n['root']!==undefined);for(const n of e){const o=h['some'](q=>q['track']==='refund'&&satisfiable(q['table'],q['root'],n));if(!o)continue;const p=a['some'](q=>claimedTrueLegPasses(q,n));p&&c['push']({'code':'RAIL_POLARITY_COLLISION','detail':'at\x20node\x20\x27'+n['node']+'\x27\x20with\x20claimed_by=some,\x20BOTH\x20a\x20refund-track\x20rail\x20and\x20an\x20'+'award-polarity\x20rail\x20(claimed_by\x20some\x20==\x20true)\x20are\x20satisfiable\x20—\x20the\x20pairing\x20'+'can\x20double-pay\x20the\x20same\x20escrow\x20(crs-mn-261014\x20F-30:\x20the\x20double-negated\x20refund\x20'+'leg\x20passed\x20only\x20AFTER\x20the\x20award\x20paid;\x20dry-run\x20simulated\x20the\x20escrow\x20draining\x20'+'on\x20top\x20of\x20a\x20paid\x20ruling).\x20The\x20refund\x20leg\x20must\x20be\x20logic_equal[query\x20'+'\x27order.claimed_by\x20some\x27,\x20Bool\x20false]\x20—\x20never\x20logic_not(query)==false.'});}return c;}function claimedTrueLegPasses(a,b){const c=a['table'],d={'node':b['node'],'claimed':!![]};return satisfiable(c,a['root'],d)&&!satisfiable(c,a['root'],{'node':b['node'],'claimed':![]});}
|
|
1
|
+
const SYM_NODE='progress.current',SYM_CLAIMED='order.claimed_by\x20some';function slotValue(a,b){if(b===undefined)return{'value':undefined,'isSubmission':![]};const c=a['find'](d=>d['identifier']===b);if(!c)return{'value':undefined,'isSubmission':![]};return{'value':c['value'],'isSubmission':c['b_submission']===!![]};}function classifyQueryLhs(a){if(a===SYM_NODE)return{'kind':'node'};if(a===SYM_CLAIMED)return{'kind':'claimed'};return{'kind':'unknown'};}function resolveValue(a,b){if(!b||b['type']!=='identifier')return{'known':![]};const c=slotValue(a,b['identifier']);if(c['isSubmission'])return{'known':![]};if(c['value']===undefined)return{'known':![]};return{'known':!![],'value':c['value']};}function evaluate(a,b,d){if(!b||typeof b['type']!=='string')return undefined;switch(b['type']){case'logic_and':{const e=Array['isArray'](b['nodes'])?b['nodes']:[];let f=![];for(const g of e){const h=evaluate(a,g,d);if(h===![])return![];if(h===undefined)f=!![];}return f?undefined:!![];}case'logic_or':{const i=Array['isArray'](b['nodes'])?b['nodes']:[];let j=![];for(const k of i){const l=evaluate(a,k,d);if(l===!![])return!![];if(l===undefined)j=!![];}return j?undefined:![];}case'logic_not':{const m=evaluate(a,b['node'],d);if(m===undefined)return undefined;return!m;}case'logic_equal':{const n=Array['isArray'](b['nodes'])?b['nodes']:[];if(n['length']<0x2)return undefined;const o=classifyQueryLhs(n[0x0]?.['query']),p=resolveValue(a,n[0x1]),q=o['kind']==='unknown'?classifyQueryLhs(n[0x1]?.['query']):o,r=!p['known']&&n[0x1]?.['query']!==undefined?resolveValue(a,n[0x0]):p;if(q['kind']==='node'){if(!r['known']||typeof r['value']!=='string')return undefined;return d['node']===r['value'];}if(q['kind']==='claimed'){if(!r['known']||typeof r['value']!=='boolean')return undefined;return d['claimed']===r['value'];}return undefined;}default:return undefined;}}function satisfiable(a,b,c){return evaluate(a,b,c)!==![];}function findDeadLiterals(a,b,c,d){if(!a||typeof a['type']!=='string')return;if(a['type']==='logic_and'&&Array['isArray'](a['nodes'])){const e=new Map();for(const f of a['nodes']){const g=resolvableEquality(f,b);if(g)e['set'](g['symbol'],g['value']);}for(const h of a['nodes']){const i=resolvableEquality(h,b);if(i){const k=e['get'](i['symbol']);if(k!==undefined&&k!==i['value']){d['push']({'code':'RAIL_DEAD_LITERAL','detail':deadLiteralDetail(c,i['symbol'],k,i['value'])});return;}continue;}const j=findClash(h,b,e);if(j){d['push']({'code':'RAIL_DEAD_LITERAL','detail':deadLiteralDetail(c,j['symbol'],j['pinned'],j['value'])});return;}}for(const l of a['nodes'])findDeadLiterals(l,b,c,d);return;}if(Array['isArray'](a['nodes'])){for(const m of a['nodes'])findDeadLiterals(m,b,c,d);}if(a['node'])findDeadLiterals(a['node'],b,c,d);}function resolvableEquality(c,d){if(!c||c['type']!=='logic_equal'||!Array['isArray'](c['nodes']))return undefined;for(const [e,f]of[[c['nodes'][0x0],c['nodes'][0x1]],[c['nodes'][0x1],c['nodes'][0x0]]]){if(!e||typeof e['query']!=='string')continue;const g=classifyQueryLhs(e['query']);if(g['kind']==='unknown')continue;const h=resolveValue(d,f);if(!h['known'])continue;return{'symbol':g['kind']==='node'?SYM_NODE:SYM_CLAIMED,'value':h['value']};}return undefined;}function findClash(a,b,c){if(!a||typeof a['type']!=='string')return undefined;if(a['type']==='logic_not')return undefined;const d=resolvableEquality(a,b);if(d){const e=c['get'](d['symbol']);if(e!==undefined&&e!==d['value'])return{'symbol':d['symbol'],'pinned':e,'value':d['value']};return undefined;}if(Array['isArray'](a['nodes']))for(const f of a['nodes']){const g=findClash(f,b,c);if(g)return g;}if(a['node'])return findClash(a['node'],b,c);return undefined;}function deadLiteralDetail(a,b,c,d){return'allocator\x20guard\x20\x27'+a+'\x27:\x20one\x20conjunction\x20scope\x20carries\x20'+b+'\x20'+('==\x20'+JSON['stringify'](c)+'\x20and\x20ALSO\x20'+b+'\x20==\x20'+JSON['stringify'](d)+'\x20—\x20the\x20second\x20')+'literal\x20contradicts\x20the\x20first\x20and\x20is\x20a\x20DEAD\x20literal\x20(azx7-mn-261014\x20CR-azx7-01:\x20a\x20pinned\x20'+'node\x20equality\x20made\x20the\x20sibling\x20closed_cancel/item_lost\x20legs\x20unreachable,\x20stranding\x20the\x20'+'escrow\x20at\x20every\x20other\x20terminal).\x20Hoist\x20the\x20node\x20predicate\x20to\x20ONE\x20top-level\x20n-ary\x20logic_or\x20'+'instead\x20of\x20AND-prepending\x20a\x20single-node\x20gate.';}export function verifyAllocatorRails(a,b){const c=[];if(a['length']===0x0||b['length']===0x0)return c;const d=b['filter'](i=>i['semanticRole']==='cancelled'||i['semanticRole']==='final'),e=b['map'](i=>({'node':i['name'],'claimed':!![]}));for(const i of a){if(i['root']===undefined)continue;const j=i['table'];findDeadLiterals(i['root'],j,i['key'],c);}for(const k of d){const l={'node':k['name'],'claimed':![]},m=a['some'](n=>satisfiable(n['table'],n['root'],l));!m&&c['push']({'code':'RAIL_TERMINAL_UNCOVERED','detail':'terminal\x20node\x20\x27'+k['name']+'\x27\x20(role\x20'+k['semanticRole']+')\x20has\x20NO\x20allocator\x20rail\x20'+'satisfiable\x20at\x20claimed_by=none\x20—\x20a\x20normal\x20(unclaimed)\x20order\x20reaching\x20this\x20'+'terminal\x20strands\x20its\x20escrow\x20forever\x20(azx7-mn-261014\x20CR-azx7-01:\x20refund\x20'+'rejected\x20abort\x207\x20at\x20closed_cancel/item_lost;\x20crs-mn-261014\x20F-30:\x20double-'+'negated\x20claimed_by\x20leg\x20bricked\x20the\x20refund\x20at\x20returned).\x20Guards/allocators\x20'+'freeze\x20at\x20publish\x20—\x20fix\x20the\x20rail\x20polarity/node-set\x20BEFORE\x20publishing.'});}const f=a['some'](n=>e['some'](o=>satisfiable(n['table'],n['root'],o)));!f&&c['push']({'code':'RAIL_AWARD_EXIT_MISSING','detail':'no\x20allocator\x20rail\x20is\x20satisfiable\x20at\x20claimed_by=some\x20on\x20ANY\x20machine\x20node\x20—\x20an\x20'+'arbitration-paid\x20order\x20has\x20NO\x20escrow\x20exit\x20(escrow-exit\x20invariant,\x20az-mn-261007).\x20'+'Pair\x20the\x20refund\x20rail\x20with\x20a\x20merchant-recovery\x20allocator\x20asserting\x20order.claimed_by\x20'+'some\x20==\x20true\x20(query\x201570)\x20on\x20the\x20post-delivery\x20node\x20set.\x20R2-05\x20DISMISSAL-STAMP\x20CAUTION\x20'+'(alg26-tn-261026\x20O11):\x20a\x20concluded\x20DISMISSAL\x20(indemnity=0)\x20ALSO\x20stamps\x20order.claimed_by\x20'+'(service.move:1703-1711\x20—\x20permissionless\x20keeper\x20conclude;\x20on\x20protocol\x20>=\x20154\x20the\x20ruled-zero\x20'+'seal\x20closes\x20claimed_by-none\x20refund\x20rails\x20BY\x20DESIGN,\x20F-BS-54/56).\x20A\x20recover\x20rail\x20discriminated\x20'+'ONLY\x20on\x20the\x20bare\x20order\x20stamp\x20routes\x20to\x20its\x20STATIC\x20recipient\x20regardless\x20of\x20the\x20ruling\x20direction\x20—\x20'+'under\x20a\x20dismissal\x20that\x20static\x20recipient\x20can\x20be\x20the\x20LOSING\x20party\x20(O11:\x20assignee\x20took\x200.15\x20after\x20'+'losing).\x20Split\x20the\x20recover\x20rail\x20by\x20arb\x20outcome\x20or\x20bind\x20its\x20recipient\x20to\x20the\x20winning\x20side\x20—\x20'+'discriminate\x20on\x20the\x20arb-side\x20award\x20(indemnity\x20>\x200\x20/\x20award-claimed\x20polarity),\x20never\x20the\x20bare\x20'+'order\x20stamp:\x20\x27claimed_by\x20some\x20⇒\x20recover-safe\x27\x20holds\x20ONLY\x20when\x20indemnity\x20>\x200.'});const h=a['filter'](n=>n['root']!==undefined);for(const n of e){const o=h['some'](q=>q['track']==='refund'&&satisfiable(q['table'],q['root'],n));if(!o)continue;const p=a['some'](q=>claimedTrueLegPasses(q,n));p&&c['push']({'code':'RAIL_POLARITY_COLLISION','detail':'at\x20node\x20\x27'+n['node']+'\x27\x20with\x20claimed_by=some,\x20BOTH\x20a\x20refund-track\x20rail\x20and\x20an\x20'+'award-polarity\x20rail\x20(claimed_by\x20some\x20==\x20true)\x20are\x20satisfiable\x20—\x20the\x20pairing\x20'+'can\x20double-pay\x20the\x20same\x20escrow\x20(crs-mn-261014\x20F-30:\x20the\x20double-negated\x20refund\x20'+'leg\x20passed\x20only\x20AFTER\x20the\x20award\x20paid;\x20dry-run\x20simulated\x20the\x20escrow\x20draining\x20'+'on\x20top\x20of\x20a\x20paid\x20ruling).\x20The\x20refund\x20leg\x20must\x20be\x20logic_equal[query\x20'+'\x27order.claimed_by\x20some\x27,\x20Bool\x20false]\x20—\x20never\x20logic_not(query)==false.'});}return c;}function claimedTrueLegPasses(a,b){const c=a['table'],d={'node':b['node'],'claimed':!![]};return satisfiable(c,a['root'],d)&&!satisfiable(c,a['root'],{'node':b['node'],'claimed':![]});}
|