@wowok/agent-mcp 3.0.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/dist/communication/evidence.d.ts +6 -0
  2. package/dist/communication/evidence.js +1 -0
  3. package/dist/evaluation/acceptance.d.ts +24 -0
  4. package/dist/evaluation/acceptance.js +1 -0
  5. package/dist/evaluation/builtins/demand-match.d.ts +3 -2
  6. package/dist/evaluation/builtins/demand-match.js +1 -1
  7. package/dist/evaluation/builtins/service-risk.d.ts +2 -1
  8. package/dist/evaluation/builtins/service-risk.js +1 -1
  9. package/dist/evaluation/index.d.ts +1 -0
  10. package/dist/evaluation/index.js +1 -1
  11. package/dist/evaluation/match-operation.d.ts +14 -0
  12. package/dist/evaluation/match-operation.js +1 -0
  13. package/dist/experience/realtime-feedback.js +1 -1
  14. package/dist/extensions/modes.js +1 -1
  15. package/dist/goal/GoalClassifier.js +1 -1
  16. package/dist/goal/GoalEngine.d.ts +8 -0
  17. package/dist/goal/GoalEngine.js +1 -1
  18. package/dist/goal/types.d.ts +1 -1
  19. package/dist/harness/auto-escalation.d.ts +0 -12
  20. package/dist/harness/auto-escalation.js +1 -1
  21. package/dist/harness/index.d.ts +1 -14
  22. package/dist/harness/index.js +1 -1
  23. package/dist/harness/types.d.ts +0 -38
  24. package/dist/intent/types.d.ts +1 -1
  25. package/dist/intent/types.js +1 -1
  26. package/dist/keeper/KeeperScan.d.ts +39 -0
  27. package/dist/keeper/KeeperScan.js +1 -0
  28. package/dist/keeper/KeeperStore.d.ts +43 -0
  29. package/dist/keeper/KeeperStore.js +1 -0
  30. package/dist/keeper/detectors.d.ts +23 -0
  31. package/dist/keeper/detectors.js +1 -0
  32. package/dist/keeper/keeper.spec.d.ts +1 -0
  33. package/dist/keeper/keeper.spec.js +1 -0
  34. package/dist/keeper/types.d.ts +65 -0
  35. package/dist/keeper/types.js +1 -0
  36. package/dist/knowledge/demand-risk.js +1 -1
  37. package/dist/knowledge/event-semantics.d.ts +3 -0
  38. package/dist/knowledge/event-semantics.js +1 -1
  39. package/dist/knowledge/event-semantics.spec.d.ts +1 -0
  40. package/dist/knowledge/event-semantics.spec.js +1 -0
  41. package/dist/knowledge/evidence-review.d.ts +23 -0
  42. package/dist/knowledge/evidence-review.js +1 -1
  43. package/dist/knowledge/examples-scanner-cli.js +1 -1
  44. package/dist/knowledge/examples-scanner.js +1 -1
  45. package/dist/knowledge/guard-bytecode-spec.d.ts +82 -0
  46. package/dist/knowledge/guard-bytecode-spec.js +1 -0
  47. package/dist/knowledge/guard-design-patterns.d.ts +1 -1
  48. package/dist/knowledge/guard-design-patterns.js +1 -1
  49. package/dist/knowledge/index.d.ts +10 -6
  50. package/dist/knowledge/index.js +1 -1
  51. package/dist/knowledge/industry-registry.js +1 -1
  52. package/dist/knowledge/mcp-schema-audit-cli.js +1 -1
  53. package/dist/knowledge/mcp-schema-audit.js +1 -1
  54. package/dist/knowledge/migration-preflight.d.ts +27 -0
  55. package/dist/knowledge/migration-preflight.js +1 -0
  56. package/dist/knowledge/scenario-modes.d.ts +1 -1
  57. package/dist/knowledge/scenario-modes.js +1 -1
  58. package/dist/knowledge/template-registry.js +1 -1
  59. package/dist/knowledge/tools-reference.js +1 -1
  60. package/dist/knowledge/workflow-guidance.d.ts +20 -0
  61. package/dist/knowledge/workflow-guidance.js +1 -1
  62. package/dist/monitor/MonitorLoop.d.ts +1 -0
  63. package/dist/monitor/MonitorLoop.js +1 -1
  64. package/dist/monitor/ScopeResolver.js +1 -1
  65. package/dist/monitor/SuggestionBridge.d.ts +1 -1
  66. package/dist/monitor/SuggestionBridge.js +1 -1
  67. package/dist/monitor/SuggestionBridge.spec.d.ts +1 -0
  68. package/dist/monitor/SuggestionBridge.spec.js +1 -0
  69. package/dist/monitor/normalize.js +1 -1
  70. package/dist/monitor/types.d.ts +0 -1
  71. package/dist/monitor/types.js +1 -1
  72. package/dist/participation/employee-kpi.d.ts +12 -0
  73. package/dist/participation/employee-kpi.js +1 -1
  74. package/dist/participation/employee-kpi.spec.d.ts +1 -0
  75. package/dist/participation/employee-kpi.spec.js +1 -0
  76. package/dist/playbooks/service-build/business-puzzle.js +1 -1
  77. package/dist/playbooks/service-build/mode-actions.d.ts +19 -6
  78. package/dist/playbooks/service-build/mode-actions.js +1 -1
  79. package/dist/playbooks/service-build/relationship-profile.js +1 -1
  80. package/dist/relationship/derivation.d.ts +6 -0
  81. package/dist/relationship/derivation.js +1 -1
  82. package/dist/relationship/derivation.spec.d.ts +1 -0
  83. package/dist/relationship/derivation.spec.js +1 -0
  84. package/dist/role/index.d.ts +2 -2
  85. package/dist/role/index.js +1 -1
  86. package/dist/role/model.d.ts +2 -1
  87. package/dist/role/model.js +1 -1
  88. package/dist/role/types.d.ts +5 -0
  89. package/dist/rules.d.ts +1 -1
  90. package/dist/safety/confirm-gate.js +1 -1
  91. package/dist/schema/call/semantic.js +1 -1
  92. package/dist/schema/common/index.js +1 -1
  93. package/dist/schema/employee/index.d.ts +61 -1
  94. package/dist/schema/employee/index.js +1 -1
  95. package/dist/schema/evaluation/index.d.ts +70 -5
  96. package/dist/schema/evaluation/index.js +1 -1
  97. package/dist/schema/index.d.ts +1 -0
  98. package/dist/schema/index.js +1 -1
  99. package/dist/schema/industry-pack/index.d.ts +43 -7
  100. package/dist/schema/industry-pack/modes.d.ts +42 -6
  101. package/dist/schema/industry-pack/modes.js +1 -1
  102. package/dist/schema/intent-radar/index.d.ts +3 -0
  103. package/dist/schema/intent-radar/index.js +1 -1
  104. package/dist/schema/keeper/index.d.ts +475 -0
  105. package/dist/schema/keeper/index.js +1 -0
  106. package/dist/schema/local/index.js +1 -1
  107. package/dist/schema/messenger/index.d.ts +2 -0
  108. package/dist/schema/messenger/index.js +1 -1
  109. package/dist/schema/operations.d.ts +34 -0
  110. package/dist/schema/query/bi.d.ts +188 -0
  111. package/dist/schema/query/bi.js +1 -1
  112. package/dist/schema/query/index.d.ts +48 -48
  113. package/dist/schema/query/index.js +1 -1
  114. package/dist/schema/schema-query/index.d.ts +2 -11
  115. package/dist/schema/schema-query/index.js +1 -1
  116. package/dist/schema/schema-version.js +1 -1
  117. package/dist/schema/utils/skills-recommendation.js +1 -1
  118. package/dist/schema/watch/index.d.ts +4 -0
  119. package/dist/schema/watch/index.js +1 -1
  120. package/dist/schema-query-impl/index.d.ts +33 -14
  121. package/dist/schema-query-impl/index.js +1 -1
  122. package/dist/schemas/employee_operation.output.json +100 -0
  123. package/dist/schemas/employee_operation.schema.json +148 -5
  124. package/dist/schemas/evaluation_operation.output.json +135 -9
  125. package/dist/schemas/evaluation_operation.schema.json +176 -7
  126. package/dist/schemas/index.json +7 -1
  127. package/dist/schemas/industry_pack_operation.output.json +158 -32
  128. package/dist/schemas/intent_radar.output.json +2 -0
  129. package/dist/schemas/intent_radar.schema.json +1 -0
  130. package/dist/schemas/keeper_operation.output.json +1274 -0
  131. package/dist/schemas/keeper_operation.schema.json +359 -0
  132. package/dist/schemas/messenger_operation.schema.json +8 -0
  133. package/dist/schemas/onchain_events.output.json +55 -11
  134. package/dist/schemas/onchain_events.schema.json +4 -0
  135. package/dist/schemas/onchain_table_data.output.json +59 -0
  136. package/dist/schemas/query_toolkit.output.json +428 -0
  137. package/dist/schemas/query_toolkit.schema.json +59 -0
  138. package/dist/schemas/schema_query.output.json +1 -64
  139. package/dist/schemas/schema_query.schema.json +18 -3
  140. package/dist/schemas/watch_operation.output.json +21 -1
  141. package/dist/task/playbook.js +1 -1
  142. package/dist/task/types.d.ts +1 -1
  143. package/dist/tools/handlers/bridge.js +1 -1
  144. package/dist/tools/handlers/config.js +1 -1
  145. package/dist/tools/handlers/employee.d.ts +6 -0
  146. package/dist/tools/handlers/employee.js +1 -1
  147. package/dist/tools/handlers/employee.spec.d.ts +1 -0
  148. package/dist/tools/handlers/employee.spec.js +1 -0
  149. package/dist/tools/handlers/evaluation.js +1 -1
  150. package/dist/tools/handlers/evaluation.spec.d.ts +1 -0
  151. package/dist/tools/handlers/evaluation.spec.js +1 -0
  152. package/dist/tools/handlers/intent-radar.js +1 -1
  153. package/dist/tools/handlers/keeper.d.ts +12 -0
  154. package/dist/tools/handlers/keeper.js +1 -0
  155. package/dist/tools/handlers/messenger.js +1 -1
  156. package/dist/tools/handlers/onchain.js +1 -1
  157. package/dist/tools/handlers/query.js +1 -1
  158. package/dist/tools/handlers/schema-query.js +1 -1
  159. package/dist/tools/handlers/watch.js +1 -1
  160. package/dist/tools/handlers/workflow.js +1 -1
  161. package/dist/tools/index.js +1 -1
  162. package/dist/tools/registry/agent.d.ts +2 -0
  163. package/dist/tools/registry/agent.js +1 -0
  164. package/dist/tools/registry/bridge.d.ts +2 -0
  165. package/dist/tools/registry/bridge.js +1 -0
  166. package/dist/tools/registry/business.d.ts +2 -0
  167. package/dist/tools/registry/business.js +1 -0
  168. package/dist/tools/registry/config.d.ts +2 -0
  169. package/dist/tools/registry/config.js +1 -0
  170. package/dist/tools/registry/files.d.ts +2 -0
  171. package/dist/tools/registry/files.js +1 -0
  172. package/dist/tools/registry/identity.d.ts +2 -0
  173. package/dist/tools/registry/identity.js +1 -0
  174. package/dist/tools/registry/local.d.ts +2 -0
  175. package/dist/tools/registry/local.js +1 -0
  176. package/dist/tools/registry/messenger.d.ts +2 -0
  177. package/dist/tools/registry/messenger.js +1 -0
  178. package/dist/tools/registry/monitor.d.ts +2 -0
  179. package/dist/tools/registry/monitor.js +1 -0
  180. package/dist/tools/registry/onchain.d.ts +2 -0
  181. package/dist/tools/registry/onchain.js +1 -0
  182. package/dist/tools/registry/query.d.ts +2 -0
  183. package/dist/tools/registry/query.js +1 -0
  184. package/dist/tools/registry/trust.d.ts +2 -0
  185. package/dist/tools/registry/trust.js +1 -0
  186. package/dist/tools/shared.js +1 -1
  187. package/dist/tools/wrap.js +1 -1
  188. package/package.json +2 -2
  189. package/dist/examples/arbitration-dispute-create.json +0 -41
  190. package/dist/examples/arbitration-vote-weighted.json +0 -35
  191. package/dist/examples/arbitration-voting-guard-add.json +0 -38
  192. package/dist/examples/demand-present-service.json +0 -33
  193. package/dist/examples/education-contact-create.json +0 -40
  194. package/dist/examples/freelance-contact-create.json +0 -40
  195. package/dist/examples/gen-passport-verify-guard.json +0 -48
  196. package/dist/examples/guard-template-balance-check.json +0 -59
  197. package/dist/examples/guard-template-time-lock.json +0 -60
  198. package/dist/examples/insurance-guard-claim-timelock.json +0 -75
  199. package/dist/examples/insurance-guard-withdraw-allocation.json +0 -96
  200. package/dist/examples/insurance-machine-create.json +0 -75
  201. package/dist/examples/insurance-service-allocators.json +0 -55
  202. package/dist/examples/machine-multisig-threshold.json +0 -87
  203. package/dist/examples/machine-publish.json +0 -30
  204. package/dist/examples/machine-template-7node-rental.json +0 -119
  205. package/dist/examples/payment-scenario-bound.json +0 -45
  206. package/dist/examples/rental-ziroom-machine-create.json +0 -148
  207. package/dist/examples/rental-ziroom-permission-create.json +0 -41
  208. package/dist/examples/rental-ziroom-service-create.json +0 -36
  209. package/dist/examples/retail-adv-guard-customer-win-create.json +0 -80
  210. package/dist/examples/retail-adv-guard-messenger-proof-create.json +0 -65
  211. package/dist/examples/retail-adv-guard-reward-timeout-create.json +0 -92
  212. package/dist/examples/retail-adv-reward-guard-add.json +0 -51
  213. package/dist/examples/retail-myshop-allocation-activate.json +0 -55
  214. package/dist/examples/retail-myshop-arbitration-create.json +0 -40
  215. package/dist/examples/retail-myshop-contact-create.json +0 -43
  216. package/dist/examples/retail-myshop-order-create.json +0 -56
  217. package/dist/examples/retail-myshop-progress-operate.json +0 -38
  218. package/dist/examples/retail-myshop-reward-create.json +0 -35
  219. package/dist/examples/retail-myshop-service-create.json +0 -38
  220. package/dist/examples/retail-myshop-service-customer-required.json +0 -31
  221. package/dist/examples/service-discount-issue.json +0 -46
  222. package/dist/examples/subscription-contact-create.json +0 -40
  223. package/dist/examples/threebody-guard-create.json +0 -56
  224. package/dist/examples/threebody-machine-create.json +0 -71
  225. package/dist/examples/threebody-permission-create.json +0 -38
  226. package/dist/examples/threebody-service-allocators.json +0 -48
  227. package/dist/examples/travel-guard-time-lock.json +0 -69
  228. package/dist/examples/travel-guard-weather-oracle.json +0 -70
  229. package/dist/examples/travel-machine-create.json +0 -135
  230. package/dist/examples/travel-repository-create.json +0 -47
  231. package/dist/examples/travel-service-create.json +0 -34
  232. package/dist/examples/travel-treasury-create.json +0 -34
  233. package/dist/examples/treasury-deposit.json +0 -37
  234. package/dist/examples/treasury-withdraw.json +0 -38
  235. package/dist/harness/plan.d.ts +0 -33
  236. package/dist/harness/plan.js +0 -1
  237. package/dist/knowledge/demand-matching.d.ts +0 -29
  238. package/dist/knowledge/demand-matching.js +0 -1
  239. package/dist/knowledge/guard-context.d.ts +0 -56
  240. package/dist/knowledge/guard-context.js +0 -1
  241. package/dist/knowledge/guard-migration.d.ts +0 -48
  242. package/dist/knowledge/guard-migration.js +0 -1
  243. package/dist/schemas/guard-node-schema.json +0 -1000
  244. package/dist/task/stage-gate.d.ts +0 -22
  245. package/dist/task/stage-gate.js +0 -1
@@ -1,26 +1,3 @@
1
- import type { GraphNodeBase } from "../graph/base.js";
2
- export type ObjectType = "Permission" | "Service" | "Machine" | "Guard" | "Allocation" | "Progress" | "Repository" | "Treasury" | "Reward" | "Demand" | "Order" | "Arbitration" | "Contact" | "Personal" | "Payment";
3
- export type ObjectStatus = "not_created" | "created_unpublished" | "published" | "failed";
4
- export interface ODGNode extends GraphNodeBase {
5
- type: ObjectType;
6
- status: ObjectStatus;
7
- reversible: boolean;
8
- dependencies: string[];
9
- user_decisions?: string[];
10
- risk_flags?: string[];
11
- estimated_time?: string;
12
- }
13
- export interface ODGPhase {
14
- name: string;
15
- objects: string[];
16
- description?: string;
17
- }
18
- export interface ODG {
19
- task_id: string;
20
- scenario: string;
21
- objects: ODGNode[];
22
- phases: ODGPhase[];
23
- }
24
1
  export interface ExpectedObject {
25
2
  role: string;
26
3
  expect_fields?: Record<string, unknown>;
@@ -84,18 +61,3 @@ export interface RecoveryAction {
84
61
  current_attempt: number;
85
62
  detail: string;
86
63
  }
87
- export interface ScenarioTemplate {
88
- name: string;
89
- keywords: string[];
90
- objects: Array<Omit<ODGNode, "id" | "status" | "address">>;
91
- phases: Array<{
92
- name: string;
93
- object_types: ObjectType[];
94
- }>;
95
- default_permissions: {
96
- provider?: number;
97
- customer?: "namedOperator";
98
- arbiter?: number;
99
- };
100
- description: string;
101
- }
@@ -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" | "NewEntityEvent" | "ArbEvent" | "VoteEvent" | "FeedbackEvent" | "AllocationEvent" | "TreasuryEvent" | "RewardClaimEvent" | "RewardFundEvent" | "NewPaymentEvent";
3
+ export type IntentTargetType = "NewOrderEvent" | "ProgressEvent" | "DemandPresentEvent" | "DemandFeedbackEvent" | "DemandChangedEvent" | "ServiceEvent" | "ArbitrationEvent" | "NewEntityEvent" | "ArbEvent" | "VoteEvent" | "FeedbackEvent" | "AllocationEvent" | "TreasuryEvent" | "RewardClaimEvent" | "RewardFundEvent" | "NewPaymentEvent";
4
4
  export interface IntentRecord {
5
5
  id: string;
6
6
  intent: string;
@@ -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','NewEntityEvent','ArbEvent','VoteEvent','FeedbackEvent','AllocationEvent','TreasuryEvent','RewardClaimEvent','RewardFundEvent','NewPaymentEvent'];
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','NewPaymentEvent'];
@@ -0,0 +1,39 @@
1
+ import type { ScopeSnapshot } from "../monitor/types.js";
2
+ import { type PaymentDetectorDeps, type ProgressDetectorDeps } from "./detectors.js";
3
+ import { type KeeperStore } from "./KeeperStore.js";
4
+ import { type KeeperTask } from "./types.js";
5
+ export interface KeeperExecutionOutcome {
6
+ ok: boolean;
7
+ digest?: string;
8
+ error?: string;
9
+ }
10
+ export interface KeeperScanDeps {
11
+ store: KeeperStore;
12
+ payment: PaymentDetectorDeps;
13
+ progress: ProgressDetectorDeps;
14
+ execute(input: {
15
+ operation_type: string;
16
+ data: Record<string, unknown>;
17
+ account: string;
18
+ network: string;
19
+ via: string;
20
+ }): Promise<KeeperExecutionOutcome>;
21
+ now(): number;
22
+ logger(message: string): void;
23
+ }
24
+ export interface KeeperScanSummary {
25
+ scanned: boolean;
26
+ reason?: string;
27
+ opened: number;
28
+ refreshed: number;
29
+ revived: number;
30
+ superseded: number;
31
+ auto_executed: number;
32
+ auto_failed: number;
33
+ duration_ms: number;
34
+ }
35
+ export declare function realKeeperScanDeps(): KeeperScanDeps;
36
+ export declare function runKeeperScan(network: string, scope: ScopeSnapshot, deps: KeeperScanDeps, opts?: {
37
+ force?: boolean;
38
+ }): Promise<KeeperScanSummary>;
39
+ export declare function executeKeeperTask(network: string, task: KeeperTask, deps: KeeperScanDeps): Promise<KeeperExecutionOutcome>;
@@ -0,0 +1 @@
1
+ import{handleOnchainOperations}from'../tools/handlers/onchain.js';import{detectPaymentUnclaimed,detectProgressActionable,realPaymentDetectorDeps,realProgressDetectorDeps}from'./detectors.js';import{keeperStore}from'./KeeperStore.js';import{AUTO_EXECUTABLE_DETECTORS}from'./types.js';async function defaultExecute(a){try{const b=await handleOnchainOperations({'operation_type':a['operation_type'],'data':a['data'],'env':{'account':a['account'],'network':a['network'],'confirmed':!![],'user_intent_phrases':['keeper\x20auto-execute\x20via\x20'+a['via']]}}),c=b?.['structuredContent']?.['result'];if(c?.['type']==='transaction'&&typeof c?.['digest']==='string')return{'ok':!![],'digest':c['digest']};const d=c?.['type']==='error'&&typeof c?.['error']==='string'?c['error']:typeof b?.['structuredContent']?.['message']==='string'?b['structuredContent']['message']:'execution\x20did\x20not\x20produce\x20a\x20transaction';return{'ok':![],'error':String(d)['slice'](0x0,0x1f4)};}catch(f){return{'ok':![],'error':String(f?.['message']??f)['slice'](0x0,0x1f4)};}}export function realKeeperScanDeps(){return{'store':keeperStore,'payment':realPaymentDetectorDeps(),'progress':realProgressDetectorDeps(),'execute':defaultExecute,'now':()=>Date['now'](),'logger':a=>console['error']('[keeper]\x20'+a)};}export async function runKeeperScan(a,b,c,d){const f=c['now'](),g={'scanned':![],'opened':0x0,'refreshed':0x0,'revived':0x0,'superseded':0x0,'auto_executed':0x0,'auto_failed':0x0,'duration_ms':0x0};try{const h=await c['store']['getConfig'](a);if(!h['enabled'])return g['reason']='disabled',g;const i=await c['store']['getLastScanAt'](a);if(!d?.['force']&&c['now']()-i<h['scan_interval_ms'])return g['reason']='interval',g;await c['store']['setLastScanAt'](a,c['now']()),g['scanned']=!![];if(h['detectors']['payment_unclaimed'])try{const l=await detectPaymentUnclaimed((b['accounts']??[])['slice'](0x0,h['max_scan_objects']),a,c['payment']),m=await c['store']['upsertDesired'](a,'payment_unclaimed',l,c['now']());g['opened']+=m['opened'],g['refreshed']+=m['refreshed'],g['revived']+=m['revived'],g['superseded']+=m['superseded'];}catch(n){c['logger']('scan\x20'+a+':\x20payment_unclaimed\x20detector\x20failed:\x20'+String(n?.['message']??n));}if(h['detectors']['progress_actionable'])try{const o=await detectProgressActionable(b,a,c['progress'],h['max_scan_objects']),p=await c['store']['upsertDesired'](a,'progress_actionable',o,c['now']());g['opened']+=p['opened'],g['refreshed']+=p['refreshed'],g['revived']+=p['revived'],g['superseded']+=p['superseded'];}catch(q){c['logger']('scan\x20'+a+':\x20progress_actionable\x20detector\x20failed:\x20'+String(q?.['message']??q));}const j=await c['store']['listTasks'](a,{'status':'pending'});let k=h['max_auto_execute_per_scan'];for(const s of j){if(k<=0x0)break;if(!s['operation'])continue;if(!AUTO_EXECUTABLE_DETECTORS['includes'](s['detector']))continue;if(s['last_auto_attempt_at']&&c['now']()-s['last_auto_attempt_at']<h['auto_retry_cooldown_ms'])continue;const t=await c['store']['matchingAutoRules'](a,s['detector'],s['beneficiary']),u=t[0x0];if(!u)continue;k--,await c['store']['markAutoAttempt'](a,s['id'],c['now']());const v=await c['execute']({'operation_type':s['operation']['operation_type'],'data':s['operation']['data'],'account':s['beneficiary'],'network':a,'via':'rule\x20'+u['id']});v['ok']?(await c['store']['resolveTask'](a,s['id'],'auto_executed',c['now'](),v['digest']?'tx\x20'+v['digest']:'executed',u['id']),g['auto_executed']++,c['logger']('auto-executed\x20'+s['dedupe_key']+'\x20via\x20rule\x20'+u['id']+'\x20('+(v['digest']??'no\x20digest')+')')):(await c['store']['resolveTask'](a,s['id'],'execute_failed',c['now'](),v['error']??'unknown\x20execution\x20error',u['id']),g['auto_failed']++,c['logger']('auto-execute\x20failed\x20for\x20'+s['dedupe_key']+':\x20'+(v['error']??'unknown')));}return g;}catch(w){return c['logger']('scan\x20'+a+'\x20failed:\x20'+String(w?.['message']??w)),g['reason']='error',g;}finally{g['duration_ms']=c['now']()-f;}}export async function executeKeeperTask(a,b,c){if(!b['operation'])return{'ok':![],'error':'This\x20task\x20is\x20reminder-only\x20(no\x20keeper-executable\x20operation).\x20'+'Follow\x20its\x20detail\x20text\x20—\x20progress\x20forwards\x20are\x20advanced\x20via\x20workflow_operation.'};const d=await c['execute']({'operation_type':b['operation']['operation_type'],'data':b['operation']['data'],'account':b['beneficiary'],'network':a,'via':'manual'});return d['ok']?await c['store']['resolveTask'](a,b['id'],'manual_executed',c['now'](),d['digest']?'tx\x20'+d['digest']:'executed'):await c['store']['resolveTask'](a,b['id'],'execute_failed',c['now'](),d['error']),d;}
@@ -0,0 +1,43 @@
1
+ import { SQLiteStorage } from "@wowok/wowok/w/local";
2
+ import { type KeeperConfig, type KeeperConfigPatch, type KeeperRule, type KeeperTask } from "./types.js";
3
+ export interface KeeperDesiredItem {
4
+ dedupe_key: string;
5
+ detector: KeeperTask["detector"];
6
+ beneficiary: string;
7
+ object?: string;
8
+ operation?: KeeperTask["operation"];
9
+ title: string;
10
+ detail?: string;
11
+ benefit?: string;
12
+ state_fingerprint: string;
13
+ }
14
+ export interface KeeperReconcileResult {
15
+ opened: number;
16
+ refreshed: number;
17
+ revived: number;
18
+ superseded: number;
19
+ }
20
+ export declare class KeeperStore {
21
+ private storage;
22
+ constructor(storage?: SQLiteStorage);
23
+ getConfig(network: string): Promise<KeeperConfig>;
24
+ saveConfig(network: string, partial: KeeperConfigPatch): Promise<KeeperConfig>;
25
+ listRules(network: string): Promise<KeeperRule[]>;
26
+ private saveRules;
27
+ upsertRule(network: string, rule: KeeperRule): Promise<KeeperRule[]>;
28
+ removeRule(network: string, ruleId: string): Promise<KeeperRule[]>;
29
+ matchingAutoRules(network: string, detector: KeeperRule["detector"], beneficiary: string): Promise<KeeperRule[]>;
30
+ listTasks(network: string, filter?: {
31
+ status?: KeeperTask["status"];
32
+ detector?: KeeperTask["detector"];
33
+ beneficiary?: string;
34
+ }): Promise<KeeperTask[]>;
35
+ getTask(network: string, taskId: string): Promise<KeeperTask | undefined>;
36
+ private saveTasks;
37
+ upsertDesired(network: string, detector: KeeperTask["detector"], desired: KeeperDesiredItem[], now: number): Promise<KeeperReconcileResult>;
38
+ resolveTask(network: string, taskId: string, resolution: NonNullable<KeeperTask["resolution"]>, now: number, note?: string, ruleId?: string): Promise<KeeperTask | undefined>;
39
+ markAutoAttempt(network: string, taskId: string, now: number): Promise<void>;
40
+ getLastScanAt(network: string): Promise<number>;
41
+ setLastScanAt(network: string, at: number): Promise<void>;
42
+ }
43
+ export declare const keeperStore: KeeperStore;
@@ -0,0 +1 @@
1
+ import{SQLiteStorage}from'@wowok/wowok/w/local';import{clampKeeperConfig,defaultKeeperConfig,newKeeperTaskId}from'./types.js';const CFG_PREFIX='keeper_cfg:v1:',RULES_PREFIX='keeper_rules:v1:',TASKS_PREFIX='keeper_tasks:v1:',SCAN_PREFIX='keeper_scan:v1:',TASK_CAP=0x1f4;function netKey(a){return(a||'default')['replace'](/[^a-zA-Z0-9_-]/g,'_');}export class KeeperStore{['storage'];constructor(a){this['storage']=a??new SQLiteStorage();}async['getConfig'](a){let b;try{const e=await this['storage']['get'](''+CFG_PREFIX+netKey(a));b=e?JSON['parse'](e):undefined;}catch{b=undefined;}const c=defaultKeeperConfig(),d={...c,...b??{},'detectors':{...c['detectors'],...b?.['detectors']??{}}};return clampKeeperConfig(d);}async['saveConfig'](a,b){const c=await this['getConfig'](a),d=clampKeeperConfig({...c,...b??{},'detectors':{...c['detectors'],...b?.['detectors']??{}}});return await this['storage']['put'](''+CFG_PREFIX+netKey(a),JSON['stringify'](d)),d;}async['listRules'](a){try{const b=await this['storage']['get'](''+RULES_PREFIX+netKey(a)),c=b?JSON['parse'](b):[];return Array['isArray'](c)?c:[];}catch{return[];}}async['saveRules'](a,b){await this['storage']['put'](''+RULES_PREFIX+netKey(a),JSON['stringify'](b));}async['upsertRule'](a,b){const c=await this['listRules'](a),d=c['findIndex'](e=>e['id']===b['id']);if(d>=0x0)c[d]=b;else c['push'](b);return await this['saveRules'](a,c),c;}async['removeRule'](a,b){const c=(await this['listRules'](a))['filter'](d=>d['id']!==b);return await this['saveRules'](a,c),c;}async['matchingAutoRules'](a,c,d){const e=d['toLowerCase']();return(await this['listRules'](a))['filter'](f=>f['enabled']&&f['auto_execute']&&f['detector']===c&&(f['accounts']['length']===0x0||f['accounts']['map'](g=>g['toLowerCase']())['includes'](e)));}async['listTasks'](a,c){let d=[];try{const f=await this['storage']['get'](''+TASKS_PREFIX+netKey(a)),g=f?JSON['parse'](f):[];d=Array['isArray'](g)?g:[];}catch{d=[];}const e=c?.['beneficiary']?.['toLowerCase']();return d['filter'](h=>(!c?.['status']||h['status']===c['status'])&&(!c?.['detector']||h['detector']===c['detector'])&&(!e||h['beneficiary']===e));}async['getTask'](a,b){return(await this['listTasks'](a))['find'](c=>c['id']===b);}async['saveTasks'](a,b){const c=b['filter'](f=>f['status']==='pending'),d=b['filter'](f=>f['status']!=='pending')['sort']((f,g)=>(g['resolved_at']??g['updated_at'])-(f['resolved_at']??f['updated_at'])),e=[...c,...d['slice'](0x0,Math['max'](0x0,TASK_CAP-c['length']))];await this['storage']['put'](''+TASKS_PREFIX+netKey(a),JSON['stringify'](e));}async['upsertDesired'](a,b,c,d){const e=await this['listTasks'](a),f=new Map(e['map'](i=>[i['dedupe_key'],i])),g={'opened':0x0,'refreshed':0x0,'revived':0x0,'superseded':0x0};for(const i of c){const j=f['get'](i['dedupe_key']);if(!j){e['push']({'id':newKeeperTaskId(),'dedupe_key':i['dedupe_key'],'detector':i['detector'],'network':a,'beneficiary':i['beneficiary']['toLowerCase'](),...i['object']?{'object':i['object']}:{},...i['operation']?{'operation':i['operation']}:{},'title':i['title'],...i['detail']?{'detail':i['detail']}:{},...i['benefit']?{'benefit':i['benefit']}:{},'state_fingerprint':i['state_fingerprint'],'status':'pending','created_at':d,'updated_at':d}),g['opened']++;continue;}if(j['state_fingerprint']===i['state_fingerprint'])continue;if(j['status']==='executed')continue;j['title']=i['title'],j['detail']=i['detail'],j['benefit']=i['benefit'],j['operation']=i['operation'],j['object']=i['object'],j['state_fingerprint']=i['state_fingerprint'],j['updated_at']=d,j['status']!=='pending'?(j['status']='pending',j['resolution']=undefined,j['resolution_note']=undefined,j['resolved_at']=undefined,g['revived']++):g['refreshed']++;}const h=new Set(c['map'](k=>k['dedupe_key']));for(const k of e){if(k['detector']!==b||k['status']!=='pending')continue;if(h['has'](k['dedupe_key']))continue;k['status']='superseded',k['resolution']='superseded',k['resolution_note']='No\x20longer\x20applicable\x20(state\x20changed\x20on-chain).',k['resolved_at']=d,k['updated_at']=d,g['superseded']++;}return await this['saveTasks'](a,e),g;}async['resolveTask'](a,b,c,d,e,f){const g=await this['listTasks'](a),h=g['find'](i=>i['id']===b);if(!h)return undefined;if(c==='dismissed')h['status']='dismissed';else{if(c==='auto_executed'||c==='manual_executed')h['status']='executed';else{if(c==='execute_failed')return h['last_auto_attempt_at']=d,h['auto_attempts']=(h['auto_attempts']??0x0)+0x1,h['resolution_note']=e,h['updated_at']=d,await this['saveTasks'](a,g),h;else h['status']='superseded';}}return h['resolution']=c,h['resolution_note']=e,h['rule_id']=f,h['resolved_at']=d,h['updated_at']=d,await this['saveTasks'](a,g),h;}async['markAutoAttempt'](a,b,c){const d=await this['listTasks'](a),e=d['find'](f=>f['id']===b);if(!e)return;e['last_auto_attempt_at']=c,e['auto_attempts']=(e['auto_attempts']??0x0)+0x1,e['updated_at']=c,await this['saveTasks'](a,d);}async['getLastScanAt'](a){try{const b=await this['storage']['get'](''+SCAN_PREFIX+netKey(a)),c=b?JSON['parse'](b):undefined;return Number(c?.['last_scan_at'])||0x0;}catch{return 0x0;}}async['setLastScanAt'](a,b){await this['storage']['put'](''+SCAN_PREFIX+netKey(a),JSON['stringify']({'last_scan_at':b}));}}export const keeperStore=new KeeperStore();
@@ -0,0 +1,23 @@
1
+ import { type OrderContext, type ParsedMachineNode, type PermissionContext } from "../knowledge/index.js";
2
+ import type { ScopeSnapshot } from "../monitor/types.js";
3
+ import type { KeeperDesiredItem } from "./KeeperStore.js";
4
+ export interface UnclaimedPayment {
5
+ balance: bigint;
6
+ count: number;
7
+ token_type?: string;
8
+ }
9
+ export interface PaymentDetectorDeps {
10
+ queryUnclaimed(account: string, network: string): Promise<UnclaimedPayment | null>;
11
+ formatAmount?(balance: bigint, tokenType: string | undefined, network: string): Promise<string | undefined>;
12
+ }
13
+ export declare function detectPaymentUnclaimed(accounts: string[], network: string, deps: PaymentDetectorDeps): Promise<KeeperDesiredItem[]>;
14
+ export interface ProgressDetectorDeps {
15
+ fetchProgressFields(addrs: string[], network: string): Promise<Map<string, any>>;
16
+ fetchMachineNodes(machine: string, network: string): Promise<ParsedMachineNode[]>;
17
+ fetchMachinePermissionAddr(machine: string, network: string): Promise<string | undefined>;
18
+ fetchPermissionContext(perm: string, network: string): Promise<PermissionContext | undefined>;
19
+ fetchOrderContext(order: string, network: string): Promise<OrderContext | undefined>;
20
+ }
21
+ export declare function detectProgressActionable(scope: ScopeSnapshot, network: string, deps: ProgressDetectorDeps, maxObjects: number): Promise<KeeperDesiredItem[]>;
22
+ export declare function realPaymentDetectorDeps(): PaymentDetectorDeps;
23
+ export declare function realProgressDetectorDeps(): ProgressDetectorDeps;
@@ -0,0 +1 @@
1
+ import{query_received,query_objects}from'@wowok/wowok';import{batchQueryObjectsByIds,enumerateActionableForwards,fetchMachineNodes,fetchOrderContext,fetchPermissionContext}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';}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,![])};}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ import{describe,expect,it}from'vitest';import{KeeperStore}from'./KeeperStore.js';import{detectPaymentUnclaimed,detectProgressActionable}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::sui::SUI'};if(c===OTHER)return{'balance':0x0n,'count':0x0};throw new Error('rpc\x20down');},'formatAmount':async()=>'0.0000001\x20SUI'});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\x20SUI');}),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']([]);});});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},'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');});});
@@ -0,0 +1,65 @@
1
+ export type KeeperDetectorKind = "payment_unclaimed" | "progress_actionable";
2
+ export declare const KEEPER_DETECTORS: readonly KeeperDetectorKind[];
3
+ export declare const AUTO_EXECUTABLE_DETECTORS: readonly KeeperDetectorKind[];
4
+ export type KeeperTaskStatus = "pending" | "executed" | "dismissed" | "superseded";
5
+ export interface KeeperTask {
6
+ id: string;
7
+ dedupe_key: string;
8
+ detector: KeeperDetectorKind;
9
+ network: string;
10
+ beneficiary: string;
11
+ object?: string;
12
+ operation?: {
13
+ operation_type: string;
14
+ data: Record<string, unknown>;
15
+ };
16
+ title: string;
17
+ detail?: string;
18
+ benefit?: string;
19
+ state_fingerprint: string;
20
+ status: KeeperTaskStatus;
21
+ created_at: number;
22
+ updated_at: number;
23
+ resolved_at?: number;
24
+ resolution?: "auto_executed" | "manual_executed" | "dismissed" | "superseded" | "execute_failed";
25
+ resolution_note?: string;
26
+ rule_id?: string;
27
+ last_auto_attempt_at?: number;
28
+ auto_attempts?: number;
29
+ }
30
+ export interface KeeperRule {
31
+ id: string;
32
+ enabled: boolean;
33
+ detector: KeeperDetectorKind;
34
+ accounts: string[];
35
+ auto_execute: boolean;
36
+ created_at: number;
37
+ note?: string;
38
+ }
39
+ export interface KeeperConfig {
40
+ enabled: boolean;
41
+ detectors: Record<KeeperDetectorKind, boolean>;
42
+ scan_interval_ms: number;
43
+ max_scan_objects: number;
44
+ max_auto_execute_per_scan: number;
45
+ auto_retry_cooldown_ms: number;
46
+ }
47
+ export type KeeperConfigPatch = Omit<Partial<KeeperConfig>, "detectors"> & {
48
+ detectors?: Partial<Record<KeeperDetectorKind, boolean>>;
49
+ };
50
+ export declare const KEEPER_DEFAULTS: {
51
+ readonly scan_interval_ms: 120000;
52
+ readonly max_scan_objects: 20;
53
+ readonly max_auto_execute_per_scan: 5;
54
+ readonly auto_retry_cooldown_ms: 1800000;
55
+ };
56
+ export declare const KEEPER_MIN: {
57
+ readonly scan_interval_ms: 30000;
58
+ readonly max_scan_objects: 1;
59
+ readonly max_auto_execute_per_scan: 1;
60
+ readonly auto_retry_cooldown_ms: 60000;
61
+ };
62
+ export declare function defaultKeeperConfig(): KeeperConfig;
63
+ export declare function clampKeeperConfig(cfg: KeeperConfig): KeeperConfig;
64
+ export declare function newKeeperTaskId(): string;
65
+ export declare function newKeeperRuleId(): string;
@@ -0,0 +1 @@
1
+ export const KEEPER_DETECTORS=['payment_unclaimed','progress_actionable'];export const AUTO_EXECUTABLE_DETECTORS=['payment_unclaimed'];export const KEEPER_DEFAULTS={'scan_interval_ms':0x1d4c0,'max_scan_objects':0x14,'max_auto_execute_per_scan':0x5,'auto_retry_cooldown_ms':0x1b7740};export const KEEPER_MIN={'scan_interval_ms':0x7530,'max_scan_objects':0x1,'max_auto_execute_per_scan':0x1,'auto_retry_cooldown_ms':0xea60};export function defaultKeeperConfig(){return{'enabled':!![],'detectors':{'payment_unclaimed':!![],'progress_actionable':!![]},'scan_interval_ms':KEEPER_DEFAULTS['scan_interval_ms'],'max_scan_objects':KEEPER_DEFAULTS['max_scan_objects'],'max_auto_execute_per_scan':KEEPER_DEFAULTS['max_auto_execute_per_scan'],'auto_retry_cooldown_ms':KEEPER_DEFAULTS['auto_retry_cooldown_ms']};}export function clampKeeperConfig(a){const b=(c,d,e)=>{const f=Number(c);return Number['isFinite'](f)?Math['max'](e,Math['floor'](f)):d;};return{...a,'scan_interval_ms':b(a['scan_interval_ms'],KEEPER_DEFAULTS['scan_interval_ms'],KEEPER_MIN['scan_interval_ms']),'max_scan_objects':b(a['max_scan_objects'],KEEPER_DEFAULTS['max_scan_objects'],KEEPER_MIN['max_scan_objects']),'max_auto_execute_per_scan':b(a['max_auto_execute_per_scan'],KEEPER_DEFAULTS['max_auto_execute_per_scan'],KEEPER_MIN['max_auto_execute_per_scan']),'auto_retry_cooldown_ms':b(a['auto_retry_cooldown_ms'],KEEPER_DEFAULTS['auto_retry_cooldown_ms'],KEEPER_MIN['auto_retry_cooldown_ms'])};}export function newKeeperTaskId(){return'ktask_'+Date['now']()['toString'](0x24)+'_'+Math['random']()['toString'](0x24)['slice'](0x2,0x8);}export function newKeeperRuleId(){return'krule_'+Date['now']()['toString'](0x24)+'_'+Math['random']()['toString'](0x24)['slice'](0x2,0x8);}
@@ -1 +1 @@
1
- import{MAX_REWARD_COUNT,MAX_GUARD_COUNT_DEMAND}from'@wowok/wowok';const MAX_FEEDBACK_COUNT=0x14,R_DEM_1_01={'rule':{'id':'R-DEM-01','level':'HIGH','category':'structural','title':'rewards\x20count\x20exceeds\x20MAX_REWARD_COUNT\x20('+MAX_REWARD_COUNT+')','description':'The\x20\x27rewards\x27\x20vector\x20is\x20bounded\x20by\x20MAX_REWARD_COUNT='+MAX_REWARD_COUNT+'\x20(Move\x20source:\x20demand.move:21).\x20'+'Exceeding\x20this\x20limit\x20aborts\x20with\x20E_MAX_REWARD_COUNT_EXCEEDED\x20(1).\x20Each\x20reward\x20is\x20bound\x20via\x20object_linker::affiliation_core,\x20'+'so\x20adding\x20a\x20reward\x20also\x20triggers\x20object_linker::affiliation_core.\x20Use\x20reward_remove/reward_clear\x20to\x20free\x20slots\x20before\x20'+'adding\x20new\x20ones\x20if\x20the\x20limit\x20is\x20reached.','affected_stakeholders':['creator'],'scenario':'Caller\x20calls\x20reward_add\x20when\x2020\x20rewards\x20are\x20already\x20affiliated','mitigation':'Track\x20the\x20current\x20reward\x20count.\x20Before\x20adding\x20a\x20new\x20reward,\x20call\x20reward_remove\x20or\x20reward_clear\x20to\x20'+'free\x20a\x20slot.\x20Consider\x20consolidating\x20rewards\x20into\x20a\x20single\x20Reward\x20object\x20with\x20multiple\x20tiers\x20if\x20the\x20'+'\x20Demand\x20needs\x20to\x20offer\x20more\x20than\x2020\x20distinct\x20reward\x20paths.','related_move_error':'E_MAX_REWARD_COUNT_EXCEEDED\x20(1)','auto_fixable':![]},'check':a=>{if(a['reward_count']===undefined)return null;if(a['reward_count']<=MAX_REWARD_COUNT)return null;return{...R_DEM_1_01['rule'],'evidence':'reward_count='+a['reward_count']+',\x20limit='+MAX_REWARD_COUNT};}},R_DEM_1_02={'rule':{'id':'R-DEM-02','level':'HIGH','category':'structural','title':'guards\x20count\x20exceeds\x20MAX_GUARD_COUNT_DEMAND\x20('+MAX_GUARD_COUNT_DEMAND+')','description':'The\x20\x27guards\x27\x20vector\x20is\x20bounded\x20by\x20MAX_GUARD_COUNT_DEMAND='+MAX_GUARD_COUNT_DEMAND+'\x20(Move\x20source:\x20demand.move:22).\x20'+'Exceeding\x20this\x20limit\x20aborts\x20with\x20E_MAX_GUARD_COUNT_EXCEEDED\x20(2).\x20Each\x20guard\x20carries\x20an\x20optional\x20'+'service_identifier\x20(u8)\x20that\x20routes\x20present_with_passport\x20submissions\x20to\x20a\x20specific\x20Service\x20submission\x20'+'extracted\x20from\x20the\x20Passport.\x20Adding\x20a\x20duplicate\x20guard\x20updates\x20the\x20service_identifier\x20instead\x20of\x20pushing.','affected_stakeholders':['creator','presenter'],'scenario':'Caller\x20calls\x20guard_add\x20when\x2020\x20guards\x20are\x20already\x20affiliated\x20and\x20the\x20address\x20is\x20new','mitigation':'Track\x20the\x20current\x20guard\x20count.\x20Before\x20adding\x20a\x20new\x20guard,\x20call\x20guard_remove\x20or\x20guard_clear.\x20'+'If\x20updating\x20an\x20existing\x20guard\x27s\x20service_identifier,\x20call\x20guard_add\x20with\x20the\x20same\x20address\x20(it\x20updates\x20'+'in\x20place\x20rather\x20than\x20pushing).','related_move_error':'E_MAX_GUARD_COUNT_EXCEEDED\x20(2)','auto_fixable':![]},'check':a=>{if(a['guard_count']===undefined)return null;if(a['guard_count']<=MAX_GUARD_COUNT_DEMAND)return null;return{...R_DEM_1_02['rule'],'evidence':'guard_count='+a['guard_count']+',\x20limit='+MAX_GUARD_COUNT_DEMAND};}},R_DEM_1_03={'rule':{'id':'R-DEM-03','level':'MEDIUM','category':'structural','title':'feedback\x20batch\x20exceeds\x20MAX_FEEDBACK_COUNT\x20('+MAX_FEEDBACK_COUNT+')','description':'The\x20\x27feedback\x27\x20Move\x20function\x20(demand.move:352)\x20updates\x20ONE\x20presenter\x20per\x20call\x20(feedback_imp\x20iterates\x20'+('no\x20vector).\x20The\x20SDK\x20batches\x20multiple\x20feedback\x20calls\x20and\x20caps\x20the\x20batch\x20at\x20MAX_FEEDBACK_COUNT='+MAX_FEEDBACK_COUNT+'\x20')+'(SDK-only\x20limit,\x20NOT\x20in\x20onchain-constants.ts\x20—\x20Move\x20has\x20no\x20aggregate\x20feedback-count\x20check).\x20Exceeding\x20the\x20'+'SDK\x20batch\x20limit\x20causes\x20the\x20SDK\x20to\x20refuse\x20the\x20call\x20before\x20transaction\x20building.\x20Each\x20feedback\x20entry\x20writes\x20'+'a\x20String\x20(bounded\x20by\x20common::DESCRIPTION,\x204000\x20chars)\x20and\x20an\x20optional\x20u8\x20acceptance_score\x20to\x20a\x20presenter\x27s\x20'+'ServiceInfo\x20record.','affected_stakeholders':['creator'],'scenario':'Caller\x20attempts\x20to\x20submit\x2021\x20feedback\x20entries\x20in\x20a\x20single\x20SDK\x20call','mitigation':'Split\x20the\x20feedback\x20batch\x20into\x20chunks\x20of\x20≤\x2020\x20entries.\x20If\x20the\x20Demand\x20has\x20more\x20than\x2020\x20presenters\x20to\x20'+'give\x20feedback\x20on,\x20submit\x20multiple\x20transactions.\x20Consider\x20whether\x20bulk\x20feedback\x20is\x20appropriate\x20—\x20'+'individualized\x20feedback\x20per\x20presenter\x20is\x20often\x20more\x20meaningful.','auto_fixable':![]},'check':a=>{if(a['feedback_count']===undefined)return null;if(a['feedback_count']<=MAX_FEEDBACK_COUNT)return null;return{...R_DEM_1_03['rule'],'evidence':'feedback_count='+a['feedback_count']+',\x20limit='+MAX_FEEDBACK_COUNT};}},R_DEM_2_01={'rule':{'id':'R-DEM-04','level':'HIGH','category':'semantic','title':'present\x20called\x20without\x20passport\x20when\x20guards\x20vector\x20is\x20non-empty','description':'The\x20Move\x20present\x20function\x20(demand.move:100)\x20asserts\x20`vector::is_empty(&self.guards)`\x20and\x20aborts\x20with\x20'+'E_NEED_PASSPORT\x20(3)\x20if\x20the\x20guards\x20vector\x20is\x20non-empty.\x20When\x20guards\x20exist,\x20every\x20presenter\x20MUST\x20go\x20through\x20'+'present_with_passport\x20(or\x20present_service_with_passport),\x20which\x20routes\x20through\x20present_with_passport_imp.\x20'+'That\x20function\x20looks\x20up\x20the\x20specified\x20Guard\x20in\x20the\x20guards\x20vector,\x20calls\x20passport::result_for_guard\x20to\x20'+'verify\x20the\x20Passport,\x20and\x20(if\x20service_identifier\x20is\x20set)\x20extracts\x20the\x20submission\x20address\x20from\x20the\x20Passport.\x20'+'Calling\x20plain\x20`present`\x20on\x20a\x20guarded\x20Demand\x20always\x20aborts\x20—\x20there\x20is\x20no\x20fallback\x20path.','affected_stakeholders':['presenter','creator'],'scenario':'Demand\x20has\x202\x20guards;\x20a\x20presenter\x20calls\x20present()\x20instead\x20of\x20present_with_passport()','mitigation':'Before\x20presenting,\x20query\x20the\x20Demand\x27s\x20guards\x20vector.\x20If\x20non-empty,\x20use\x20present_with_passport\x20and\x20'+'supply\x20a\x20Guard\x20+\x20Passport.\x20The\x20Guard\x20address\x20must\x20already\x20be\x20in\x20the\x20guards\x20vector\x20(otherwise\x20'+'E_GUARD_NOT_FOUND\x20(4)\x20aborts).\x20If\x20service_identifier\x20is\x20set\x20on\x20the\x20matching\x20guard,\x20the\x20submission\x20'+'address\x20is\x20extracted\x20from\x20the\x20Passport\x20—\x20do\x20not\x20pass\x20a\x20separate\x20service\x20parameter.','related_move_error':'E_NEED_PASSPORT\x20(3)','auto_fixable':![]},'check':a=>{if(!a['using_present_without_passport'])return null;if(!a['guards_non_empty'])return null;return{...R_DEM_2_01['rule'],'evidence':'guards_non_empty=true,\x20using\x20present\x20(no\x20passport)'};}},R_DEM_3_01={'rule':{'id':'R-DEM-05','level':'INFO','category':'lifecycle','title':'um_set_imp\x20object-linker\x20dependency\x20leak\x20—\x20RESOLVED\x20(P-DEM-P1-1)','description':'PREVIOUS\x20RISK:\x20um_set_imp\x20(demand.move:139-147)\x20previously\x20set\x20self.um\x20to\x20the\x20new\x20Contact\x20address\x20'+'BEFORE\x20disaffiliating\x20the\x20old\x20um,\x20causing\x20the\x20old\x20Contact\x20to\x20retain\x20a\x20stale\x20object-linker\x20binding\x20record\x20in\x20the\x20'+'object_linker.\x20affiliation_change_core\x20was\x20not\x20called\x20for\x20the\x20old\x20um,\x20leading\x20to\x20an\x20object-linker\x20dependency\x20leak.\x0a\x0a'+'FIX\x20(P-DEM-P1-1):\x20um_set_imp\x20now\x20disaffiliates\x20the\x20old\x20um\x20via\x20object_linker::disaffiliation_core\x20BEFORE\x20setting\x20'+'the\x20new\x20one.\x20The\x20new\x20um\x20is\x20then\x20affiliated\x20via\x20object_linker::affiliation_core.\x20This\x20matches\x20the\x20pattern\x20used\x20'+'by\x20permission_set\x20(which\x20uses\x20affiliation_change_core).\x20um_none_imp\x20also\x20disaffiliates\x20before\x20clearing.\x0a\x0a'+'This\x20rule\x20is\x20retained\x20for\x20historical\x20audit\x20and\x20to\x20detect\x20regressions.','affected_stakeholders':['creator','system'],'scenario':'Future\x20regression:\x20someone\x20reorders\x20um_set_imp\x20to\x20set\x20new\x20before\x20disaffiliating\x20old','mitigation':'Keep\x20the\x20disaffiliate-then-set\x20ordering.\x20The\x20Move\x20invariant:\x20any\x20path\x20that\x20mutates\x20self.um\x20MUST\x20call\x20'+'object_linker::disaffiliation_core\x20on\x20the\x20old\x20value\x20before\x20assigning\x20a\x20new\x20one.','auto_fixable':![]},'check':a=>{if(a['constants_synced'])return null;return{...R_DEM_3_01['rule'],'evidence':'constants_synced=false\x20(regression\x20check)'};}},R_DEM_2_02={'rule':{'id':'R-DEM-06','level':'INFO','category':'semantic','title':'guard_add_imp\x20service_identifier\x20type\x20check\x20skipped\x20on\x20early\x20return\x20—\x20RESOLVED\x20(P-DEM-P1-2)','description':'PREVIOUS\x20RISK:\x20guard_add_imp\x20(demand.move:213-242)\x20previously\x20had\x20the\x20service_identifier\x20type\x20check\x20'+'AFTER\x20the\x20early-return\x20path\x20that\x20updates\x20an\x20existing\x20guard\x27s\x20service_identifier.\x20When\x20a\x20guard\x20with\x20'+'the\x20same\x20address\x20already\x20existed,\x20the\x20function\x20returned\x20before\x20validating\x20the\x20new\x20service_identifier\x20'+'against\x20guard::get_submission_object_type.\x20This\x20allowed\x20setting\x20an\x20invalid\x20service_identifier\x20that\x20'+'would\x20later\x20fail\x20at\x20present_with_passport\x20time\x20with\x20E_INVALID_SERVICE_OBJECT_TYPE\x20(common.move:13).\x0a\x0a'+'FIX\x20(P-DEM-P1-2):\x20The\x20service_identifier\x20type\x20check\x20now\x20runs\x20FIRST\x20(demand.move:218-222),\x20BEFORE\x20the\x20'+'duplicate-detection\x20loop.\x20common::assert_service_object_type\x20is\x20called\x20for\x20any\x20non-None\x20service_identifier,\x20'+'ensuring\x20both\x20the\x20insert\x20and\x20update\x20paths\x20validate\x20the\x20type.\x0a\x0a'+'This\x20rule\x20is\x20retained\x20for\x20historical\x20audit\x20and\x20to\x20detect\x20regressions.','affected_stakeholders':['creator','presenter'],'scenario':'Future\x20regression:\x20someone\x20moves\x20the\x20type\x20check\x20back\x20to\x20after\x20the\x20duplicate-detection\x20loop','mitigation':'Keep\x20the\x20type\x20check\x20at\x20the\x20top\x20of\x20guard_add_imp.\x20The\x20Move\x20invariant:\x20any\x20service_identifier\x20provided\x20'+'to\x20guard_add\x20MUST\x20be\x20validated\x20via\x20guard::get_submission_object_type\x20+\x20common::assert_service_object_type\x20'+'BEFORE\x20any\x20mutation\x20of\x20the\x20guards\x20vector.','auto_fixable':![]},'check':a=>{if(a['constants_synced'])return null;return{...R_DEM_2_02['rule'],'evidence':'constants_synced=false\x20(regression\x20check)'};}},R_DEM_4_01={'rule':{'id':'R-DEM-07','level':'INFO','category':'knowledge','title':'extractDemandInfo\x20expects\x20non-existent\x20Move\x20fields\x20—\x20RESOLVED\x20(P-DEM-P1-3)','description':'PREVIOUS\x20RISK:\x20extractDemandInfo\x20in\x20demand-matching.ts\x20previously\x20read\x20fields\x20(tags,\x20maxPrice,\x20'+'scenario,\x20minTrustScore,\x20keywords)\x20that\x20do\x20NOT\x20exist\x20on\x20the\x20Move\x20Demand\x20struct.\x20The\x20Move\x20struct\x20only\x20'+'has:\x20description,\x20location,\x20rewards,\x20guards,\x20presenters,\x20um,\x20permission.\x20This\x20caused\x20the\x20matching\x20'+'engine\x20to\x20silently\x20produce\x20undefined\x20values\x20when\x20fed\x20raw\x20on-chain\x20query\x20results.\x0a\x0a'+'FIX\x20(P-DEM-P1-3):\x20extractDemandInfo\x20now\x20documents\x20the\x20caller-enrichment\x20contract.\x20Only\x20`location`\x20maps\x20'+'directly\x20to\x20the\x20Move\x20Demand\x20struct;\x20all\x20other\x20fields\x20(tags,\x20maxPrice,\x20scenario,\x20minTrustScore,\x20keywords)\x20'+'MUST\x20be\x20injected\x20by\x20the\x20caller\x20before\x20calling\x20matchDemand.\x20The\x20caller\x20is\x20responsible\x20for\x20sourcing\x20'+'this\x20data\x20from\x20Service\x20tags,\x20Reward\x20objects,\x20user\x20input,\x20or\x20NLP\x20on\x20the\x20description.\x0a\x0a'+'This\x20rule\x20is\x20retained\x20for\x20historical\x20audit\x20and\x20to\x20detect\x20regressions.','affected_stakeholders':['system'],'scenario':'Future\x20regression:\x20someone\x20removes\x20the\x20caller-enrichment\x20contract\x20docs\x20from\x20extractDemandInfo','mitigation':'Keep\x20the\x20[caller-enriched]\x20/\x20[on-chain]\x20annotations\x20on\x20DemandInfo\x20fields.\x20The\x20matching\x20engine\x20must\x20'+'never\x20query\x20on-chain\x20data\x20directly\x20—\x20it\x20is\x20a\x20pure\x20scoring\x20function\x20over\x20caller-injected\x20data.','auto_fixable':![]},'check':a=>{if(a['constants_synced'])return null;return{...R_DEM_4_01['rule'],'evidence':'constants_synced=false\x20(regression\x20check)'};}},R_DEM_4_02={'rule':{'id':'R-DEM-08','level':'INFO','category':'knowledge','title':'permission_set\x20not\x20exposed\x20in\x20SDK\x20—\x20RESOLVED\x20(DE-D-2=A)','description':'PREVIOUS\x20GAP:\x20The\x20Move\x20permission_set\x20function\x20(demand.move:286)\x20was\x20not\x20exposed\x20as\x20a\x20standalone\x20'+'function\x20in\x20the\x20SDK\x27s\x20call/demand.ts.\x20Callers\x20could\x20not\x20change\x20the\x20Permission\x20object\x20bound\x20to\x20a\x20Demand\x20'+'after\x20creation.\x0a\x0a'+'RESOLUTION\x20(DE-D-2=A):\x20permission_set\x20is\x20now\x20exposed\x20via\x20the\x20CallPermission.apply\x20mechanism.\x20The\x20SDK\x20'+'wraps\x20permission_set\x20by\x20routing\x20it\x20through\x20CallPermission,\x20which\x20performs\x20the\x20assert_owner\x20check\x20on\x20the\x20'+'old\x20Permission\x20and\x20updates\x20the\x20Demand\x27s\x20bound\x20permission.\x20object_linker\x27s\x20affiliation_change_core\x20is\x20called\x20'+'to\x20migrate\x20the\x20binding\x20from\x20the\x20old\x20Permission\x20to\x20the\x20new\x20one.\x0a\x0a'+'Permission\x20indices\x20for\x20Demand\x20(demand.move:20):\x20400=DEMAND_NEW,\x20401=DEMAND_DESCRIPTION,\x20402=DEMAND_LOCATION,\x20'+'404=DEMAND_GUARD,\x20405=DEMAND_REWARD,\x20406=DEMAND_FEEDBACK,\x20407=DEMAND_OWNER_RECEIVE,\x20408=DEMAND_UM.\x0a\x0a'+'This\x20rule\x20is\x20retained\x20for\x20historical\x20audit\x20and\x20to\x20detect\x20regressions.','affected_stakeholders':['creator','system'],'scenario':'Future\x20regression:\x20someone\x20removes\x20the\x20CallPermission.apply\x20path\x20for\x20permission_set','mitigation':'Keep\x20permission_set\x20exposed\x20via\x20CallPermission.apply.\x20The\x20Move\x20invariant:\x20permission_set\x20requires\x20'+'permission::assert_owner(old)\x20and\x20MUST\x20call\x20object_linker::affiliation_change_core\x20to\x20migrate\x20the\x20binding.','auto_fixable':![]},'check':a=>{if(a['constants_synced'])return null;return{...R_DEM_4_02['rule'],'evidence':'constants_synced=false\x20(regression\x20check)'};}};export const DEMAND_RISK_RULES=[R_DEM_1_01,R_DEM_1_02,R_DEM_1_03,R_DEM_2_01,R_DEM_3_01,R_DEM_2_02,R_DEM_4_01,R_DEM_4_02];export function checkDemandRisks(a){const b=[];for(const c of DEMAND_RISK_RULES){const d=c['check'](a);if(d)b['push'](d);}return b;}export function getDemandRiskById(a){return DEMAND_RISK_RULES['find'](b=>b['rule']['id']===a)?.['rule'];}
1
+ import{MAX_REWARD_COUNT,MAX_GUARD_COUNT_DEMAND}from'@wowok/wowok';const MAX_FEEDBACK_COUNT=0x14,R_DEM_1_01={'rule':{'id':'R-DEM-01','level':'HIGH','category':'structural','title':'rewards\x20count\x20exceeds\x20MAX_REWARD_COUNT\x20('+MAX_REWARD_COUNT+')','description':'The\x20\x27rewards\x27\x20vector\x20is\x20bounded\x20by\x20MAX_REWARD_COUNT='+MAX_REWARD_COUNT+'\x20(Move\x20source:\x20demand.move:21).\x20'+'Exceeding\x20this\x20limit\x20aborts\x20with\x20E_MAX_REWARD_COUNT_EXCEEDED\x20(1).\x20Each\x20reward\x20is\x20bound\x20via\x20object_linker::affiliation_core,\x20'+'so\x20adding\x20a\x20reward\x20also\x20triggers\x20object_linker::affiliation_core.\x20Use\x20reward_remove/reward_clear\x20to\x20free\x20slots\x20before\x20'+'adding\x20new\x20ones\x20if\x20the\x20limit\x20is\x20reached.','affected_stakeholders':['creator'],'scenario':'Caller\x20calls\x20reward_add\x20when\x2020\x20rewards\x20are\x20already\x20affiliated','mitigation':'Track\x20the\x20current\x20reward\x20count.\x20Before\x20adding\x20a\x20new\x20reward,\x20call\x20reward_remove\x20or\x20reward_clear\x20to\x20'+'free\x20a\x20slot.\x20Consider\x20consolidating\x20rewards\x20into\x20a\x20single\x20Reward\x20object\x20with\x20multiple\x20tiers\x20if\x20the\x20'+'\x20Demand\x20needs\x20to\x20offer\x20more\x20than\x2020\x20distinct\x20reward\x20paths.','related_move_error':'E_MAX_REWARD_COUNT_EXCEEDED\x20(1)','auto_fixable':![]},'check':a=>{if(a['reward_count']===undefined)return null;if(a['reward_count']<=MAX_REWARD_COUNT)return null;return{...R_DEM_1_01['rule'],'evidence':'reward_count='+a['reward_count']+',\x20limit='+MAX_REWARD_COUNT};}},R_DEM_1_02={'rule':{'id':'R-DEM-02','level':'HIGH','category':'structural','title':'guards\x20count\x20exceeds\x20MAX_GUARD_COUNT_DEMAND\x20('+MAX_GUARD_COUNT_DEMAND+')','description':'The\x20\x27guards\x27\x20vector\x20is\x20bounded\x20by\x20MAX_GUARD_COUNT_DEMAND='+MAX_GUARD_COUNT_DEMAND+'\x20(Move\x20source:\x20demand.move:22).\x20'+'Exceeding\x20this\x20limit\x20aborts\x20with\x20E_MAX_GUARD_COUNT_EXCEEDED\x20(2).\x20Each\x20guard\x20carries\x20an\x20optional\x20'+'service_identifier\x20(u8)\x20that\x20routes\x20present_with_passport\x20submissions\x20to\x20a\x20specific\x20Service\x20submission\x20'+'extracted\x20from\x20the\x20Passport.\x20Adding\x20a\x20duplicate\x20guard\x20updates\x20the\x20service_identifier\x20instead\x20of\x20pushing.','affected_stakeholders':['creator','presenter'],'scenario':'Caller\x20calls\x20guard_add\x20when\x2020\x20guards\x20are\x20already\x20affiliated\x20and\x20the\x20address\x20is\x20new','mitigation':'Track\x20the\x20current\x20guard\x20count.\x20Before\x20adding\x20a\x20new\x20guard,\x20call\x20guard_remove\x20or\x20guard_clear.\x20'+'If\x20updating\x20an\x20existing\x20guard\x27s\x20service_identifier,\x20call\x20guard_add\x20with\x20the\x20same\x20address\x20(it\x20updates\x20'+'in\x20place\x20rather\x20than\x20pushing).','related_move_error':'E_MAX_GUARD_COUNT_EXCEEDED\x20(2)','auto_fixable':![]},'check':a=>{if(a['guard_count']===undefined)return null;if(a['guard_count']<=MAX_GUARD_COUNT_DEMAND)return null;return{...R_DEM_1_02['rule'],'evidence':'guard_count='+a['guard_count']+',\x20limit='+MAX_GUARD_COUNT_DEMAND};}},R_DEM_1_03={'rule':{'id':'R-DEM-03','level':'MEDIUM','category':'structural','title':'feedback\x20batch\x20exceeds\x20MAX_FEEDBACK_COUNT\x20('+MAX_FEEDBACK_COUNT+')','description':'The\x20\x27feedback\x27\x20Move\x20function\x20(demand.move:352)\x20updates\x20ONE\x20presenter\x20per\x20call\x20(feedback_imp\x20iterates\x20'+('no\x20vector).\x20The\x20SDK\x20batches\x20multiple\x20feedback\x20calls\x20and\x20caps\x20the\x20batch\x20at\x20MAX_FEEDBACK_COUNT='+MAX_FEEDBACK_COUNT+'\x20')+'(SDK-only\x20limit,\x20NOT\x20in\x20onchain-constants.ts\x20—\x20Move\x20has\x20no\x20aggregate\x20feedback-count\x20check).\x20Exceeding\x20the\x20'+'SDK\x20batch\x20limit\x20causes\x20the\x20SDK\x20to\x20refuse\x20the\x20call\x20before\x20transaction\x20building.\x20Each\x20feedback\x20entry\x20writes\x20'+'a\x20String\x20(bounded\x20by\x20common::DESCRIPTION,\x204000\x20chars)\x20and\x20an\x20optional\x20u8\x20acceptance_score\x20to\x20a\x20presenter\x27s\x20'+'ServiceInfo\x20record.','affected_stakeholders':['creator'],'scenario':'Caller\x20attempts\x20to\x20submit\x2021\x20feedback\x20entries\x20in\x20a\x20single\x20SDK\x20call','mitigation':'Split\x20the\x20feedback\x20batch\x20into\x20chunks\x20of\x20≤\x2020\x20entries.\x20If\x20the\x20Demand\x20has\x20more\x20than\x2020\x20presenters\x20to\x20'+'give\x20feedback\x20on,\x20submit\x20multiple\x20transactions.\x20Consider\x20whether\x20bulk\x20feedback\x20is\x20appropriate\x20—\x20'+'individualized\x20feedback\x20per\x20presenter\x20is\x20often\x20more\x20meaningful.','auto_fixable':![]},'check':a=>{if(a['feedback_count']===undefined)return null;if(a['feedback_count']<=MAX_FEEDBACK_COUNT)return null;return{...R_DEM_1_03['rule'],'evidence':'feedback_count='+a['feedback_count']+',\x20limit='+MAX_FEEDBACK_COUNT};}},R_DEM_2_01={'rule':{'id':'R-DEM-04','level':'HIGH','category':'semantic','title':'present\x20called\x20without\x20passport\x20when\x20guards\x20vector\x20is\x20non-empty','description':'The\x20Move\x20present\x20function\x20(demand.move:100)\x20asserts\x20`vector::is_empty(&self.guards)`\x20and\x20aborts\x20with\x20'+'E_NEED_PASSPORT\x20(3)\x20if\x20the\x20guards\x20vector\x20is\x20non-empty.\x20When\x20guards\x20exist,\x20every\x20presenter\x20MUST\x20go\x20through\x20'+'present_with_passport\x20(or\x20present_service_with_passport),\x20which\x20routes\x20through\x20present_with_passport_imp.\x20'+'That\x20function\x20looks\x20up\x20the\x20specified\x20Guard\x20in\x20the\x20guards\x20vector,\x20calls\x20passport::result_for_guard\x20to\x20'+'verify\x20the\x20Passport,\x20and\x20(if\x20service_identifier\x20is\x20set)\x20extracts\x20the\x20submission\x20address\x20from\x20the\x20Passport.\x20'+'Calling\x20plain\x20`present`\x20on\x20a\x20guarded\x20Demand\x20always\x20aborts\x20—\x20there\x20is\x20no\x20fallback\x20path.','affected_stakeholders':['presenter','creator'],'scenario':'Demand\x20has\x202\x20guards;\x20a\x20presenter\x20calls\x20present()\x20instead\x20of\x20present_with_passport()','mitigation':'Before\x20presenting,\x20query\x20the\x20Demand\x27s\x20guards\x20vector.\x20If\x20non-empty,\x20use\x20present_with_passport\x20and\x20'+'supply\x20a\x20Guard\x20+\x20Passport.\x20The\x20Guard\x20address\x20must\x20already\x20be\x20in\x20the\x20guards\x20vector\x20(otherwise\x20'+'E_GUARD_NOT_FOUND\x20(4)\x20aborts).\x20If\x20service_identifier\x20is\x20set\x20on\x20the\x20matching\x20guard,\x20the\x20submission\x20'+'address\x20is\x20extracted\x20from\x20the\x20Passport\x20—\x20do\x20not\x20pass\x20a\x20separate\x20service\x20parameter.','related_move_error':'E_NEED_PASSPORT\x20(3)','auto_fixable':![]},'check':a=>{if(!a['using_present_without_passport'])return null;if(!a['guards_non_empty'])return null;return{...R_DEM_2_01['rule'],'evidence':'guards_non_empty=true,\x20using\x20present\x20(no\x20passport)'};}},R_DEM_3_01={'rule':{'id':'R-DEM-05','level':'INFO','category':'lifecycle','title':'um_set_imp\x20object-linker\x20dependency\x20leak\x20—\x20RESOLVED\x20(P-DEM-P1-1)','description':'PREVIOUS\x20RISK:\x20um_set_imp\x20(demand.move:139-147)\x20previously\x20set\x20self.um\x20to\x20the\x20new\x20Contact\x20address\x20'+'BEFORE\x20disaffiliating\x20the\x20old\x20um,\x20causing\x20the\x20old\x20Contact\x20to\x20retain\x20a\x20stale\x20object-linker\x20binding\x20record\x20in\x20the\x20'+'object_linker.\x20affiliation_change_core\x20was\x20not\x20called\x20for\x20the\x20old\x20um,\x20leading\x20to\x20an\x20object-linker\x20dependency\x20leak.\x0a\x0a'+'FIX\x20(P-DEM-P1-1):\x20um_set_imp\x20now\x20disaffiliates\x20the\x20old\x20um\x20via\x20object_linker::disaffiliation_core\x20BEFORE\x20setting\x20'+'the\x20new\x20one.\x20The\x20new\x20um\x20is\x20then\x20affiliated\x20via\x20object_linker::affiliation_core.\x20This\x20matches\x20the\x20pattern\x20used\x20'+'by\x20permission_set\x20(which\x20uses\x20affiliation_change_core).\x20um_none_imp\x20also\x20disaffiliates\x20before\x20clearing.\x0a\x0a'+'This\x20rule\x20is\x20retained\x20for\x20historical\x20audit\x20and\x20to\x20detect\x20regressions.','affected_stakeholders':['creator','system'],'scenario':'Future\x20regression:\x20someone\x20reorders\x20um_set_imp\x20to\x20set\x20new\x20before\x20disaffiliating\x20old','mitigation':'Keep\x20the\x20disaffiliate-then-set\x20ordering.\x20The\x20Move\x20invariant:\x20any\x20path\x20that\x20mutates\x20self.um\x20MUST\x20call\x20'+'object_linker::disaffiliation_core\x20on\x20the\x20old\x20value\x20before\x20assigning\x20a\x20new\x20one.','auto_fixable':![]},'check':a=>{if(a['constants_synced'])return null;return{...R_DEM_3_01['rule'],'evidence':'constants_synced=false\x20(regression\x20check)'};}},R_DEM_2_02={'rule':{'id':'R-DEM-06','level':'INFO','category':'semantic','title':'guard_add_imp\x20service_identifier\x20type\x20check\x20skipped\x20on\x20early\x20return\x20—\x20RESOLVED\x20(P-DEM-P1-2)','description':'PREVIOUS\x20RISK:\x20guard_add_imp\x20(demand.move:213-242)\x20previously\x20had\x20the\x20service_identifier\x20type\x20check\x20'+'AFTER\x20the\x20early-return\x20path\x20that\x20updates\x20an\x20existing\x20guard\x27s\x20service_identifier.\x20When\x20a\x20guard\x20with\x20'+'the\x20same\x20address\x20already\x20existed,\x20the\x20function\x20returned\x20before\x20validating\x20the\x20new\x20service_identifier\x20'+'against\x20guard::get_submission_object_type.\x20This\x20allowed\x20setting\x20an\x20invalid\x20service_identifier\x20that\x20'+'would\x20later\x20fail\x20at\x20present_with_passport\x20time\x20with\x20E_INVALID_SERVICE_OBJECT_TYPE\x20(common.move:13).\x0a\x0a'+'FIX\x20(P-DEM-P1-2):\x20The\x20service_identifier\x20type\x20check\x20now\x20runs\x20FIRST\x20(demand.move:218-222),\x20BEFORE\x20the\x20'+'duplicate-detection\x20loop.\x20common::assert_service_object_type\x20is\x20called\x20for\x20any\x20non-None\x20service_identifier,\x20'+'ensuring\x20both\x20the\x20insert\x20and\x20update\x20paths\x20validate\x20the\x20type.\x0a\x0a'+'This\x20rule\x20is\x20retained\x20for\x20historical\x20audit\x20and\x20to\x20detect\x20regressions.','affected_stakeholders':['creator','presenter'],'scenario':'Future\x20regression:\x20someone\x20moves\x20the\x20type\x20check\x20back\x20to\x20after\x20the\x20duplicate-detection\x20loop','mitigation':'Keep\x20the\x20type\x20check\x20at\x20the\x20top\x20of\x20guard_add_imp.\x20The\x20Move\x20invariant:\x20any\x20service_identifier\x20provided\x20'+'to\x20guard_add\x20MUST\x20be\x20validated\x20via\x20guard::get_submission_object_type\x20+\x20common::assert_service_object_type\x20'+'BEFORE\x20any\x20mutation\x20of\x20the\x20guards\x20vector.','auto_fixable':![]},'check':a=>{if(a['constants_synced'])return null;return{...R_DEM_2_02['rule'],'evidence':'constants_synced=false\x20(regression\x20check)'};}},R_DEM_4_01={'rule':{'id':'R-DEM-07','level':'INFO','category':'knowledge','title':'Demand\x20matching\x20must\x20not\x20read\x20non-existent\x20Move\x20fields\x20—\x20RESOLVED\x20(P-DEM-P1-3)','description':'PREVIOUS\x20RISK:\x20the\x20retired\x20demand-matching.ts\x20engine\x20(matchDemand/extractDemandInfo)\x20read\x20fields\x20(tags,\x20'+'maxPrice,\x20scenario,\x20minTrustScore,\x20keywords)\x20that\x20do\x20NOT\x20exist\x20on\x20the\x20Move\x20Demand\x20struct.\x20The\x20Move\x20struct\x20'+'only\x20has:\x20description,\x20location,\x20rewards,\x20guards,\x20presenters,\x20um,\x20permission.\x20This\x20caused\x20the\x20matching\x20'+'engine\x20to\x20silently\x20produce\x20undefined\x20values\x20when\x20fed\x20raw\x20on-chain\x20query\x20results.\x0a\x0a'+'FIX\x20(P-DEM-P1-3):\x20the\x20capability-vector\x20engine\x20(evaluation/builtins/demand-match.ts)\x20enriches\x20via\x20'+'evaluation/extract.ts\x20(extractDemandCapability/extractServiceCapability).\x20Only\x20`location`\x20maps\x20directly\x20'+'to\x20the\x20Move\x20Demand\x20struct;\x20all\x20other\x20signals\x20(industry/tags/keywords/region/trust/price\x20budget)\x20are\x20'+'enriched\x20from\x20description\x20NLP,\x20the\x20industry\x20generalizer,\x20or\x20caller-injected\x20overrides/data\x20sources.\x0a\x0a'+'This\x20rule\x20is\x20retained\x20for\x20historical\x20audit\x20and\x20to\x20detect\x20regressions.','affected_stakeholders':['system'],'scenario':'Future\x20regression:\x20someone\x20removes\x20the\x20enrichment\x20contract\x20docs\x20from\x20evaluation/extract.ts','mitigation':'Keep\x20the\x20enrichment\x20contract\x20in\x20evaluation/extract.ts\x20(non-chain-derivable\x20fields\x20are\x20enriched\x20there,\x20'+'not\x20read\x20as\x20on-chain\x20fact).\x20The\x20matching\x20engine\x20must\x20never\x20query\x20on-chain\x20data\x20directly\x20—\x20it\x20scores\x20'+'over\x20already-enriched\x20capability\x20vectors.','auto_fixable':![]},'check':a=>{if(a['constants_synced'])return null;return{...R_DEM_4_01['rule'],'evidence':'constants_synced=false\x20(regression\x20check)'};}},R_DEM_4_02={'rule':{'id':'R-DEM-08','level':'INFO','category':'knowledge','title':'permission_set\x20not\x20exposed\x20in\x20SDK\x20—\x20RESOLVED\x20(DE-D-2=A)','description':'PREVIOUS\x20GAP:\x20The\x20Move\x20permission_set\x20function\x20(demand.move:286)\x20was\x20not\x20exposed\x20as\x20a\x20standalone\x20'+'function\x20in\x20the\x20SDK\x27s\x20call/demand.ts.\x20Callers\x20could\x20not\x20change\x20the\x20Permission\x20object\x20bound\x20to\x20a\x20Demand\x20'+'after\x20creation.\x0a\x0a'+'RESOLUTION\x20(DE-D-2=A):\x20permission_set\x20is\x20now\x20exposed\x20via\x20the\x20CallPermission.apply\x20mechanism.\x20The\x20SDK\x20'+'wraps\x20permission_set\x20by\x20routing\x20it\x20through\x20CallPermission,\x20which\x20performs\x20the\x20assert_owner\x20check\x20on\x20the\x20'+'old\x20Permission\x20and\x20updates\x20the\x20Demand\x27s\x20bound\x20permission.\x20object_linker\x27s\x20affiliation_change_core\x20is\x20called\x20'+'to\x20migrate\x20the\x20binding\x20from\x20the\x20old\x20Permission\x20to\x20the\x20new\x20one.\x0a\x0a'+'Permission\x20indices\x20for\x20Demand\x20(demand.move:20):\x20400=DEMAND_NEW,\x20401=DEMAND_DESCRIPTION,\x20402=DEMAND_LOCATION,\x20'+'404=DEMAND_GUARD,\x20405=DEMAND_REWARD,\x20406=DEMAND_FEEDBACK,\x20407=DEMAND_OWNER_RECEIVE,\x20408=DEMAND_UM.\x0a\x0a'+'This\x20rule\x20is\x20retained\x20for\x20historical\x20audit\x20and\x20to\x20detect\x20regressions.','affected_stakeholders':['creator','system'],'scenario':'Future\x20regression:\x20someone\x20removes\x20the\x20CallPermission.apply\x20path\x20for\x20permission_set','mitigation':'Keep\x20permission_set\x20exposed\x20via\x20CallPermission.apply.\x20The\x20Move\x20invariant:\x20permission_set\x20requires\x20'+'permission::assert_owner(old)\x20and\x20MUST\x20call\x20object_linker::affiliation_change_core\x20to\x20migrate\x20the\x20binding.','auto_fixable':![]},'check':a=>{if(a['constants_synced'])return null;return{...R_DEM_4_02['rule'],'evidence':'constants_synced=false\x20(regression\x20check)'};}};export const DEMAND_RISK_RULES=[R_DEM_1_01,R_DEM_1_02,R_DEM_1_03,R_DEM_2_01,R_DEM_3_01,R_DEM_2_02,R_DEM_4_01,R_DEM_4_02];export function checkDemandRisks(a){const b=[];for(const c of DEMAND_RISK_RULES){const d=c['check'](a);if(d)b['push'](d);}return b;}export function getDemandRiskById(a){return DEMAND_RISK_RULES['find'](b=>b['rule']['id']===a)?.['rule'];}
@@ -1,4 +1,5 @@
1
1
  export type EventCategory = "lifecycle" | "state_change" | "fund_flow" | "market_opportunity" | "reputation" | "other";
2
+ export type EventConsumer = "suggestion_bridge" | "problem_bridge" | "intent_radar" | "keeper";
2
3
  export interface EventParamDoc {
3
4
  name: string;
4
5
  shape: string;
@@ -9,6 +10,8 @@ export interface EventSemanticEntry {
9
10
  move_type: string;
10
11
  module: string;
11
12
  category: EventCategory;
13
+ consumers: EventConsumer[];
14
+ channel_note?: string;
12
15
  business_meaning: string;
13
16
  trigger: string;
14
17
  side_effect?: string;
@@ -1 +1 @@
1
- export const EVENT_SEMANTIC_REGISTRY=[{'name':'NewOrderEvent','move_type':'::order::NewOrderEvent','module':'order','category':'lifecycle','business_meaning':'A\x20new\x20Order\x20was\x20placed\x20on\x20a\x20Service\x20(shared,\x20escrow-funded)','trigger':'order.move\x20`create`\x20—\x20the\x20ONLY\x20emission\x20point.\x20Fires\x20when\x20the\x20order\x20becomes\x20a\x20shared\x20object;\x20'+'validates:\x20machine\x20⇒\x20progress\x20bound;\x20amount\x20>\x200\x20⇒\x20allocation\x20bound.','side_effect':'Order\x20is\x20live:\x20buyer\x20funds\x20were\x20split\x20into\x20CoinWrappers\x20via\x20the\x20Service\x20Allocation;\x20'+'machine-governed\x20orders\x20can\x20now\x20be\x20advanced\x20by\x20operators.','params':[{'name':'object','shape':'address','meaning':'The\x20new\x20Order\x20object\x20id'},{'name':'service','shape':'address','meaning':'The\x20Service\x20the\x20order\x20was\x20placed\x20on'},{'name':'progress','shape':'Option<address>','meaning':'Bound\x20Progress\x20(machine\x20orders)\x20—\x20null\x20for\x20non-machine\x20orders'},{'name':'discount','shape':'Option<address>','meaning':'Discount\x20object\x20consumed\x20at\x20quote\x20time,\x20if\x20any'},{'name':'allocation','shape':'Option<address>','meaning':'Allocation\x20that\x20escrowed\x20the\x20payment\x20(required\x20when\x20amount\x20>\x200)'},{'name':'amount','shape':'u64','meaning':'Total\x20order\x20amount\x20in\x20the\x20Service\x27s\x20payment\x20token\x20(raw\x20on-chain\x20units)'}]},{'name':'ArbEvent','move_type':'::arb::ArbEvent','module':'arb','category':'state_change','business_meaning':'Arbitration\x20case\x20status\x20transition\x20(7\x20statuses,\x20incl.\x20creation)','trigger':'arb.move\x20—\x20emitted\x20on\x20EVERY\x20status\x20transition:\x20create\x20(Arbitrator_confirming),\x20'+'proposition_change\x20/\x20principal\x20confirm\x20(Voting),\x20votes\x20closed\x20(Arbitrated),\x20objection\x20'+'(Objectionable),\x20finish\x20with\x20indemnity\x20(Finished\x20+\x20compensation),\x20withdraw\x20(Withdrawn).\x20'+'Helper\x20`emit_arb_event`\x20reads\x20the\x20POST-transition\x20state.','side_effect':'Parties\x20should\x20re-read\x20the\x20Arb\x20object\x20on\x20every\x20event;\x20status\x20decides\x20who\x20acts\x20next.\x20'+'When\x20indemnity_amount\x20is\x20set,\x20the\x20compensation\x20recipient\x20can\x20claim\x20after\x20compensation_time.','params':[{'name':'object','shape':'address','meaning':'The\x20Arb\x20(dispute\x20case)\x20object\x20id'},{'name':'arbitration','shape':'address','meaning':'The\x20governing\x20Arbitration\x20object\x20(voting\x20rules,\x20arbitrator\x20set)'},{'name':'order','shape':'address','meaning':'The\x20disputed\x20Order'},{'name':'status','shape':'u8','meaning':'0\x20Principal_confirming\x20·\x201\x20Arbitrator_confirming\x20·\x202\x20Voting\x20·\x203\x20Arbitrated\x20·\x204\x20Objectionable\x20·\x205\x20Finished\x20·\x206\x20Withdrawn'},{'name':'indemnity_amount','shape':'Option<u64>','meaning':'Awarded\x20compensation\x20(set\x20on\x20Arbitrated/Finished);\x20null\x20otherwise'},{'name':'compensation_time','shape':'Option<u64>','meaning':'Timestamp-ms\x20after\x20which\x20the\x20compensation\x20can\x20be\x20withdrawn\x20(locks\x20expire)'}]},{'name':'VoteEvent','move_type':'::arb::VoteEvent','module':'arb','category':'state_change','business_meaning':'One\x20arbitration\x20vote\x20cast\x20(real-time\x20tally)','trigger':'arb.move\x20—\x20on\x20each\x20`vote`/`vote_with_passport`\x20call\x20(one\x20per\x20voter\x20per\x20round);\x20'+'lets\x20parties\x20track\x20the\x20tally\x20without\x20polling\x20the\x20Arb\x20object.','params':[{'name':'object','shape':'address','meaning':'The\x20Arb\x20object\x20being\x20voted\x20on'},{'name':'voter','shape':'address','meaning':'The\x20voting\x20arbitrator\x20(or\x20passport-proven\x20delegate)'},{'name':'agrees','shape':'vector<u8>','meaning':'Proposition\x20indexes\x20the\x20voter\x20agreed\x20to'},{'name':'weight','shape':'u32','meaning':'Vote\x20weight\x20applied\x20(guard-weighted\x20voting)'}]},{'name':'FeedbackEvent','move_type':'::arb::FeedbackEvent','module':'arb','category':'state_change','business_meaning':'New\x20feedback\x20message\x20on\x20an\x20arbitration\x20case','trigger':'arb.move\x20—\x20on\x20`feedback`\x20(any\x20party\x20posts\x20a\x20message\x20into\x20the\x20case).','params':[{'name':'object','shape':'address','meaning':'The\x20Arb\x20object'},{'name':'feedback','shape':'String','meaning':'The\x20feedback\x20text'}]},{'name':'DemandPresentEvent','move_type':'::demand::PresentEvent','module':'demand','category':'market_opportunity','business_meaning':'A\x20presenter\x20submitted/updated\x20a\x20solution\x20pitch\x20on\x20a\x20Demand','trigger':'demand.move\x20`present_imp`\x20—\x20first\x20present\x20inserts\x20a\x20presenter\x20row;\x20re-present\x20updates\x20it\x20'+'(recommend\x20text\x20+\x20optional\x20bound\x20Service).\x20Passport-gated\x20variants\x20resolve\x20the\x20Service\x20from\x20'+'the\x20passport\x20submission\x20when\x20the\x20demand\x27s\x20guard\x20sets\x20a\x20service_identifier.','side_effect':'Demand\x20owner\x20now\x20has\x20a\x20candidate;\x20track\x20update_time\x20to\x20rank\x20freshest\x20pitches.\x20'+'This\x20is\x20the\x20supply\x20side\x20of\x20the\x20demand\x20marketplace\x20(K3\x2013\x20§6.7).','params':[{'name':'object','shape':'address','meaning':'The\x20Demand\x20object'},{'name':'service','shape':'Option<address>','meaning':'The\x20presented\x20Service\x20(null\x20=\x20raw\x20recommendation\x20without\x20a\x20bound\x20service)'},{'name':'recommend','shape':'String','meaning':'The\x20presenter\x27s\x20pitch/recommendation\x20text'}]},{'name':'DemandFeedbackEvent','move_type':'::demand::DemandEvent','module':'demand','category':'reputation','business_meaning':'Demand\x20owner\x20scored/feedbacked\x20a\x20presenter\x20(acceptance\x20score)','trigger':'demand.move\x20`feedback_imp`\x20—\x20only\x20for\x20addresses\x20already\x20in\x20the\x20presenters\x20table;\x20'+'records\x20feedback\x20text\x20+\x20optional\x20acceptance\x20score\x20onto\x20the\x20presenter\x20row.','side_effect':'Acceptance\x20score\x20is\x20the\x20demand-side\x20quality\x20signal\x20for\x20the\x20presenter;\x20high\x20scores\x20build\x20'+'presenter\x20reputation\x20for\x20future\x20matching.','params':[{'name':'object','shape':'address','meaning':'The\x20Demand\x20object'},{'name':'service','shape':'Option<address>','meaning':'The\x20Service\x20that\x20was\x20presented\x20by\x20the\x20scored\x20presenter'},{'name':'feedback','shape':'String','meaning':'Feedback\x20text'},{'name':'acceptance_score','shape':'Option<u8>','meaning':'0-100\x20acceptance\x20score,\x20null\x20when\x20feedback\x20carries\x20no\x20score'}]},{'name':'DemandChangedEvent','move_type':'::demand::DemandChangedEvent','module':'demand','category':'market_opportunity','business_meaning':'Demand\x20became/updated\x20a\x20profitable\x20opportunity\x20for\x20merchants\x20(market-opportunity\x20event)','trigger':'demand.move\x20`demand_changed_event_emit`\x20—\x20fires\x20when\x20rewards\x20are\x20bound/changed,\x20or\x20'+'description/location\x20changes\x20while\x20reward-bearing.\x20A\x20reward-less\x20demand\x20NEVER\x20emits\x20'+'(not\x20a\x20profitable\x20opportunity\x20—\x20K3\x2013\x20§6.7\x20principle).','side_effect':'PRIMARY\x20merchant-side\x20discovery\x20signal:\x20Intent\x20Radar\x20/\x20match\x20engines\x20should\x20treat\x20every\x20'+'emission\x20as\x20a\x20fresh\x20matchmaking\x20opportunity.\x20Reward\x20amounts/claim\x20rules\x20are\x20NOT\x20carried\x20—\x20'+'read\x20the\x20Reward\x20objects\x20by\x20id\x20(authoritative,\x20never\x20stale).','params':[{'name':'object','shape':'address','meaning':'The\x20Demand\x20object'},{'name':'location','shape':'String','meaning':'Demand\x20location\x20(industry/geography\x20routing\x20signal)'},{'name':'description','shape':'String','meaning':'Bounded\x20description\x20preview\x20(truncated\x20on-chain;\x20full\x20text\x20on\x20the\x20object)'},{'name':'rewards','shape':'vector<address>','meaning':'Bound\x20Reward\x20object\x20ids\x20—\x20resolve\x20amounts/conditions\x20by\x20query_objects'}]},{'name':'ProgressEvent','move_type':'::progress::ProgressEvent','module':'progress','category':'state_change','business_meaning':'Order/task\x20workflow\x20advanced,\x20held,\x20or\x20initialized\x20on\x20a\x20Machine\x20graph','trigger':'progress.move\x20—\x204\x20emission\x20points:\x20`new_imp`\x20(progress\x20created\x20at\x20init\x20node,\x20no\x20forward),\x20'+'`session_accomplish`\x20(threshold\x20reached\x20→\x20node\x20migrated),\x20`hold_imp`/`hold_imp_with_passport`\x20'+'(hold\x20or\x20un-hold\x20of\x20a\x20forward,\x20hold\x20field\x20carries\x20the\x20new\x20state).','side_effect':'Operators\x20should\x20check\x20the\x20new\x20node\x20name\x20against\x20their\x20Machine\x20duties;\x20hold=true\x20pauses\x20that\x20'+'forward\x27s\x20contribution,\x20hold=false\x20resumes\x20it.','params':[{'name':'object','shape':'address','meaning':'The\x20Progress\x20object'},{'name':'machine','shape':'address','meaning':'The\x20Machine\x20(workflow\x20template)\x20governing\x20this\x20progress'},{'name':'task','shape':'Option<address>','meaning':'The\x20bound\x20task\x20(usually\x20the\x20Order)\x20—\x20null\x20for\x20standalone\x20progress'},{'name':'node','shape':'String','meaning':'Node\x20reached\x20(init\x20node\x20on\x20creation;\x20next_node\x20on\x20migration/hold)'},{'name':'forward','shape':'Option<String>','meaning':'The\x20forward\x20name\x20that\x20triggered\x20the\x20transition\x20(null\x20on\x20creation)'},{'name':'hold','shape':'Option<bool>','meaning':'Present\x20only\x20on\x20hold/un-hold:\x20true\x20=\x20forward\x20held,\x20false\x20=\x20released'}]},{'name':'NewEntityEvent','move_type':'::registrar::NewEntityEvent','module':'registrar','category':'lifecycle','business_meaning':'Entity\x20registered\x20or\x20re-announced\x20(new\x20counterparty\x20/\x20profile\x20update)','trigger':'registrar.move\x20—\x204\x20sites:\x20entity_register\x20/\x20entity_register_with_resource_forced\x20(new\x20Resource\x20'+'created),\x20entity_resource_use\x20(first\x20on-chain\x20use\x20of\x20a\x20resource),\x20entity_description_set,\x20'+'entity_info_add\x20(profile\x20updates\x20re-announce\x20the\x20entity).','side_effect':'A\x20new\x20potential\x20counterparty\x20entered\x20the\x20ecosystem,\x20or\x20an\x20existing\x20one\x20updated\x20its\x20public\x20'+'profile\x20—\x20refresh\x20cached\x20entity\x20profiles/records.','params':[{'name':'resource','shape':'address','meaning':'The\x20entity\x27s\x20Resource\x20object\x20(per-chain\x20identity\x20resource)'},{'name':'referrer','shape':'Option<address>','meaning':'Referring\x20entity\x20address,\x20when\x20registered\x20via\x20referral'}]},{'name':'ServiceEvent','move_type':'::service::ServiceEvent','module':'service','category':'market_opportunity','business_meaning':'Service\x20became/updated\x20a\x20purchasable\x20supply\x20(active-supply\x20event)','trigger':'service.move\x20`service_event_emit`\x20—\x20ONLY\x20when\x20bPublished\x20&&\x20!bPaused\x20at\x20the\x20mutation\x20point:\x20'+'publish,\x20unpause,\x20and\x20pre-publish\x20description\x20changes\x20re-notify.\x20Pausing\x20/\x20unpublishing\x20/\x20'+'draft-only\x20mutations\x20NEVER\x20emit\x20(not\x20a\x20participatable\x20opportunity\x20—\x20K3\x2013\x20§6.7).','side_effect':'PRIMARY\x20customer-side\x20discovery\x20signal:\x20every\x20emission\x20is\x20a\x20buyable\x20service\x20with\x20its\x20routing\x20'+'text.\x20The\x20authoritative\x20description/sales/stock\x20live\x20on\x20the\x20Service\x20object\x20by\x20id.','params':[{'name':'object','shape':'address','meaning':'The\x20Service\x20object'},{'name':'location','shape':'String','meaning':'Service\x20location\x20(industry/geography\x20routing\x20signal)'},{'name':'description','shape':'String','meaning':'Bounded\x20description\x20preview\x20(truncated\x20on-chain)'}]},{'name':'AllocationEvent','move_type':'::allocation::AllocationEvent','module':'allocation','category':'fund_flow','business_meaning':'Allocation\x20run\x20completed\x20—\x20funds\x20left\x20the\x20Allocation\x20pool\x20as\x20a\x20Payment','trigger':'allocation.move\x20alloc\x20loop\x20—\x20when\x20a\x20matching\x20Allocator\x27s\x20guard\x20passes:\x20splits\x20the\x20balance\x20per\x20'+'sharing\x20mode\x20(Amount\x20/\x20Rate\x20‰\x20/\x20Surplus),\x20creates\x20a\x20Payment\x20(from_object\x20=\x20Allocation),\x20'+'then\x20emits\x20with\x20the\x20actually-distributed\x20amount.','side_effect':'Recipients\x20receive\x20CoinWrappers\x20referencing\x20the\x20new\x20Payment\x20—\x20they\x20must\x20unwrap\x20to\x20obtain\x20coins.\x20'+'The\x20Payment\x20is\x20also\x20pushed\x20onto\x20the\x20Allocation\x27s\x20payment\x20list.','params':[{'name':'object','shape':'address','meaning':'The\x20Allocation\x20object\x20that\x20distributed\x20the\x20funds'},{'name':'payment','shape':'address','meaning':'The\x20Payment\x20object\x20created\x20by\x20this\x20run\x20(the\x20on-chain\x20receipt)'},{'name':'guard','shape':'address','meaning':'The\x20guard\x20of\x20the\x20Allocator\x20that\x20authorized\x20this\x20distribution'},{'name':'amount','shape':'u64','meaning':'Amount\x20actually\x20distributed\x20(balance\x20before\x20−\x20balance\x20after)'}]},{'name':'TreasuryEvent','move_type':'::treasury::TreasuryEvent','module':'treasury','category':'fund_flow','business_meaning':'Treasury\x20fund-flow\x20record\x20(withdraw\x20/\x20deposit\x20/\x20receive)\x20—\x20mirrors\x20on-chain\x20history','trigger':'treasury.move\x20—\x203\x20sites:\x20withdraw_imp\x20(balance\x20split\x20out\x20as\x20Payment,\x20from_object\x20=\x20Treasury),\x20'+'deposit_imp_\x20(coins\x20joined\x20in,\x20a\x20Payment\x20receipt\x20is\x20minted\x20for\x20the\x20depositor),\x20receive_imp\x20'+'(a\x20CoinWrapper\x20from\x20a\x20Payment\x20is\x20received\x20into\x20the\x20treasury).\x20Each\x20emission\x20appends\x20a\x20Record\x20'+'to\x20the\x20treasury\x27s\x20on-chain\x20history\x20parent\x20table.','params':[{'name':'object','shape':'address','meaning':'The\x20Treasury\x20object'},{'name':'op','shape':'u8','meaning':'0\x20Withdraw\x20·\x201\x20Deposit\x20·\x202\x20Receive'},{'name':'payment','shape':'address','meaning':'The\x20Payment\x20receipt\x20minted\x20for\x20this\x20flow'},{'name':'amount','shape':'u64','meaning':'Flow\x20amount\x20(raw\x20on-chain\x20units\x20of\x20the\x20Treasury\x27s\x20token)'},{'name':'external_guard','shape':'Option<address>','meaning':'External\x20withdraw\x20guard\x20that\x20authorized\x20a\x20withdraw,\x20if\x20any'},{'name':'store_from_id','shape':'Option<address>','meaning':'Passport-derived\x20store/branch\x20id\x20(multi-branch\x20treasury\x20bookkeeping)'}]},{'name':'RewardClaimEvent','move_type':'::reward::RewardClaimEvent','module':'reward','category':'fund_flow','business_meaning':'Reward\x20claimed\x20—\x20funds\x20paid\x20out\x20of\x20a\x20Reward\x20pool','trigger':'reward.move\x20claim\x20path\x20—\x20after\x20guard+passport\x20validation:\x20appends\x20a\x20Record\x20to\x20the\x20recipient\x27s\x20'+'on-chain\x20record,\x20splits\x20the\x20balance,\x20emits,\x20then\x20transfers\x20the\x20coin\x20to\x20the\x20recipient.\x20'+'The\x20ONLY\x20realtime\x20trace\x20of\x20the\x20claim\x20outflow.','params':[{'name':'object','shape':'address','meaning':'The\x20Reward\x20pool\x20object'},{'name':'guard','shape':'address','meaning':'The\x20reward\x20guard\x20that\x20authorized\x20this\x20claim'},{'name':'recipient','shape':'address','meaning':'Claim\x20recipient\x20(resolved\x20via\x20passport\x20when\x20required)'},{'name':'amount','shape':'u64','meaning':'This\x20claim\x27s\x20amount'},{'name':'total','shape':'u64','meaning':'Recipient\x27s\x20cumulative\x20claimed\x20total\x20on\x20this\x20pool'},{'name':'balance_left','shape':'u64','meaning':'Pool\x20balance\x20remaining\x20after\x20the\x20claim'},{'name':'store_from_id','shape':'Option<address>','meaning':'Passport-derived\x20store/branch\x20id,\x20when\x20the\x20guard\x20requires\x20it'}]},{'name':'RewardFundEvent','move_type':'::reward::RewardFundEvent','module':'reward','category':'fund_flow','business_meaning':'Reward\x20pool\x20inflow\x20—\x20funds\x20added\x20to\x20the\x20pool','trigger':'reward.move\x20—\x202\x20sites:\x20coin_add_imp\x20(direct\x20coin\x20deposit,\x20from_payment\x20=\x20null)\x20and\x20receive_imp\x20'+'(a\x20Payment\x27s\x20CoinWrapper\x20received\x20into\x20the\x20pool,\x20from_payment\x20=\x20that\x20Payment).','side_effect':'Claim\x20guards\x20whose\x20pool\x20ran\x20dry\x20become\x20satisfiable\x20again;\x20watchers\x20should\x20re-check\x20claim\x20'+'opportunities\x20against\x20the\x20new\x20balance.','params':[{'name':'object','shape':'address','meaning':'The\x20Reward\x20pool\x20object'},{'name':'amount','shape':'u64','meaning':'Inflow\x20amount'},{'name':'balance','shape':'u64','meaning':'Pool\x20balance\x20after\x20the\x20inflow'},{'name':'from_payment','shape':'Option<address>','meaning':'The\x20Payment\x20that\x20funded\x20this\x20inflow\x20(null\x20for\x20direct\x20coin\x20adds)'}]},{'name':'NewPaymentEvent','move_type':'::payment::NewPaymentEvent','module':'payment','category':'fund_flow','business_meaning':'A\x20Payment\x20was\x20created\x20—\x20the\x20universal\x20on-chain\x20receipt\x20of\x20WoWok\x20fund\x20flows','trigger':'payment.move\x20`create`\x20—\x20the\x20ONLY\x20emission\x20point,\x20reached\x20by\x20treasury\x20withdraw/deposit,\x20'+'allocation\x20runs,\x20service\x20compensation\x20payouts,\x20and\x20direct\x20user\x20payments\x20alike.\x20'+'Emission\x20is\x20the\x20last\x20step\x20before\x20the\x20Payment\x20object\x20is\x20frozen\x20(immutable\x20receipt).','side_effect':'Every\x20recipient\x20in\x20`record`\x20received\x20a\x20frozen\x20CoinWrapper\x20that\x20references\x20this\x20Payment\x20—\x20'+'unwrap\x20converts\x20it\x20to\x20a\x20transferable\x20Coin.\x20info.for_object\x20/\x20info.for_guard\x20/\x20from_object\x20'+'are\x20registered\x20as\x20object-linker\x20affiliations,\x20so\x20the\x20payment\x20is\x20discoverable\x20via\x20global\x20'+'affiliation\x20tables\x20(onchain_affiliations_of_object).','params':[{'name':'object','shape':'address','meaning':'The\x20Payment\x20object\x20id\x20(the\x20receipt)'},{'name':'info.for_object','shape':'Option<address>','meaning':'The\x20business\x20object\x20this\x20payment\x20is\x20FOR\x20(order/demand/reward/…)\x20—\x20user-settable\x20routing\x20hint'},{'name':'info.for_guard','shape':'Option<address>','meaning':'The\x20Guard\x20governing\x20this\x20payment\x20—\x20user-settable,\x20links\x20the\x20payment\x20to\x20a\x20trust\x20rule'},{'name':'info.remark','shape':'String','meaning':'Free-form\x20on-chain\x20remark\x20(e.g.\x20invoice\x20number,\x20purpose)'},{'name':'info.index','shape':'u64','meaning':'Creator-local\x20index\x20(installment\x20sequence,\x20table\x20row,\x20…)'},{'name':'record','shape':'vector<{recipient,\x20amount}>','meaning':'Revenue\x20legs:\x20one\x20{recipient,\x20amount}\x20per\x20CoinWrapper\x20transferred'},{'name':'amount','shape':'u64','meaning':'Total\x20paid\x20across\x20all\x20legs\x20(sum\x20of\x20record\x20amounts)'},{'name':'from_object','shape':'Option<address>','meaning':'FUNDING-SOURCE\x20object\x20the\x20funds\x20LEFT\x20from\x20—\x20INTERNAL-ONLY\x20field\x20(public(package)\x20'+'from_object_set;\x20user\x20code\x20can\x20never\x20set\x20it).\x20Treasury\x20withdraw\x20⇒\x20the\x20Treasury;\x20'+'Allocation\x20run\x20⇒\x20the\x20Allocation;\x20Service\x20compensation\x20withdraw\x20⇒\x20the\x20Service.\x20'+'create()\x20registers\x20an\x20object_linker\x20affiliation\x20(from_object\x20→\x20payment)\x20so\x20the\x20'+'outflow\x20is\x20traceable\x20back\x20to\x20its\x20pool.\x20Null\x20for\x20direct\x20user-initiated\x20payments\x20'+'(no\x20on-chain\x20source\x20object).'}]}];export const EVENT_BY_NAME=new Map(EVENT_SEMANTIC_REGISTRY['map'](a=>[a['name'],a]));export const EVENT_BY_MOVE_TYPE=new Map(EVENT_SEMANTIC_REGISTRY['map'](a=>[a['move_type'],a]));export function lookupEventMeaning(a){const b=String(a?.['type']??''),c=EVENT_BY_NAME['get'](b);if(c)return c['business_meaning'];const d=String(a?.['type_raw']??'');if(d)for(const f of EVENT_SEMANTIC_REGISTRY){if(d['includes'](f['move_type']))return f['business_meaning'];}return undefined;}
1
+ export const EVENT_SEMANTIC_REGISTRY=[{'name':'NewOrderEvent','move_type':'::order::NewOrderEvent','module':'order','category':'lifecycle','consumers':['suggestion_bridge','intent_radar'],'business_meaning':'A\x20new\x20Order\x20was\x20placed\x20on\x20a\x20Service\x20(shared,\x20escrow-funded)','trigger':'order.move\x20`create`\x20—\x20the\x20ONLY\x20emission\x20point.\x20Fires\x20when\x20the\x20order\x20becomes\x20a\x20shared\x20object;\x20'+'validates:\x20machine\x20⇒\x20progress\x20bound;\x20amount\x20>\x200\x20⇒\x20allocation\x20bound.','side_effect':'Order\x20is\x20live:\x20buyer\x20funds\x20were\x20split\x20into\x20CoinWrappers\x20via\x20the\x20Service\x20Allocation;\x20'+'machine-governed\x20orders\x20can\x20now\x20be\x20advanced\x20by\x20operators.','params':[{'name':'object','shape':'address','meaning':'The\x20new\x20Order\x20object\x20id'},{'name':'service','shape':'address','meaning':'The\x20Service\x20the\x20order\x20was\x20placed\x20on'},{'name':'progress','shape':'Option<address>','meaning':'Bound\x20Progress\x20(machine\x20orders)\x20—\x20null\x20for\x20non-machine\x20orders'},{'name':'discount','shape':'Option<address>','meaning':'Discount\x20object\x20consumed\x20at\x20quote\x20time,\x20if\x20any'},{'name':'allocation','shape':'Option<address>','meaning':'Allocation\x20that\x20escrowed\x20the\x20payment\x20(required\x20when\x20amount\x20>\x200)'},{'name':'amount','shape':'u64','meaning':'Total\x20order\x20amount\x20in\x20the\x20Service\x27s\x20payment\x20token\x20(raw\x20on-chain\x20units)'}]},{'name':'ArbEvent','move_type':'::arb::ArbEvent','module':'arb','category':'state_change','consumers':['suggestion_bridge','problem_bridge','intent_radar'],'business_meaning':'Arbitration\x20status\x20transition\x20on\x20a\x20dispute\x20case\x20(open\x20/\x20voting\x20/\x20verdict\x20/\x20objection\x20/\x20finish\x20/\x20withdraw)','trigger':'arb.move\x20—\x20emitted\x20on\x20EVERY\x20status\x20transition:\x20create\x20(Arbitrator_confirming),\x20'+'proposition_change\x20/\x20principal\x20confirm\x20(Voting),\x20votes\x20closed\x20(Arbitrated),\x20objection\x20'+'(Objectionable),\x20finish\x20with\x20indemnity\x20(Finished\x20+\x20compensation),\x20withdraw\x20(Withdrawn).\x20'+'Helper\x20`emit_arb_event`\x20reads\x20the\x20POST-transition\x20state.','side_effect':'Parties\x20should\x20re-read\x20the\x20Arb\x20object\x20on\x20every\x20event;\x20status\x20decides\x20who\x20acts\x20next.\x20'+'When\x20indemnity_amount\x20is\x20set,\x20the\x20compensation\x20recipient\x20can\x20claim\x20after\x20compensation_time.','params':[{'name':'object','shape':'address','meaning':'The\x20Arb\x20(dispute\x20case)\x20object\x20id'},{'name':'arbitration','shape':'address','meaning':'The\x20governing\x20Arbitration\x20object\x20(voting\x20rules,\x20arbitrator\x20set)'},{'name':'order','shape':'address','meaning':'The\x20disputed\x20Order'},{'name':'status','shape':'u8','meaning':'0\x20Principal_confirming\x20·\x201\x20Arbitrator_confirming\x20·\x202\x20Voting\x20·\x203\x20Arbitrated\x20·\x204\x20Objectionable\x20·\x205\x20Finished\x20·\x206\x20Withdrawn'},{'name':'indemnity_amount','shape':'Option<u64>','meaning':'Awarded\x20compensation\x20(set\x20on\x20Arbitrated/Finished);\x20null\x20otherwise'},{'name':'compensation_time','shape':'Option<u64>','meaning':'Timestamp-ms\x20after\x20which\x20the\x20compensation\x20can\x20be\x20withdrawn\x20(locks\x20expire)'}]},{'name':'VoteEvent','move_type':'::arb::VoteEvent','module':'arb','category':'state_change','consumers':['intent_radar'],'channel_note':'Deliberately\x20radar-only:\x20per-vote\x20granularity\x20is\x20too\x20noisy\x20for\x20push;\x20the\x20ArbEvent\x20'+'Voting/Arbitrated\x20transitions\x20already\x20carry\x20the\x20push\x20signals\x20(P2-1).','business_meaning':'One\x20arbitration\x20vote\x20cast\x20(real-time\x20tally)','trigger':'arb.move\x20—\x20on\x20each\x20`vote`/`vote_with_passport`\x20call\x20(one\x20per\x20voter\x20per\x20round);\x20'+'lets\x20parties\x20track\x20the\x20tally\x20without\x20polling\x20the\x20Arb\x20object.','params':[{'name':'object','shape':'address','meaning':'The\x20Arb\x20object\x20being\x20voted\x20on'},{'name':'voter','shape':'address','meaning':'The\x20voting\x20arbitrator\x20(or\x20passport-proven\x20delegate)'},{'name':'agrees','shape':'vector<u8>','meaning':'Proposition\x20indexes\x20the\x20voter\x20agreed\x20to'},{'name':'weight','shape':'u32','meaning':'Vote\x20weight\x20applied\x20(guard-weighted\x20voting)'}]},{'name':'FeedbackEvent','move_type':'::arb::FeedbackEvent','module':'arb','category':'state_change','consumers':['suggestion_bridge','intent_radar'],'business_meaning':'New\x20feedback\x20message\x20on\x20an\x20arbitration\x20case','trigger':'arb.move\x20—\x20on\x20`feedback`\x20(any\x20party\x20posts\x20a\x20message\x20into\x20the\x20case).','params':[{'name':'object','shape':'address','meaning':'The\x20Arb\x20object'},{'name':'feedback','shape':'String','meaning':'The\x20feedback\x20text'}]},{'name':'DemandPresentEvent','move_type':'::demand::PresentEvent','module':'demand','category':'market_opportunity','consumers':['suggestion_bridge','intent_radar'],'business_meaning':'A\x20presenter\x20submitted/updated\x20a\x20solution\x20pitch\x20on\x20a\x20Demand','trigger':'demand.move\x20`present_imp`\x20—\x20first\x20present\x20inserts\x20a\x20presenter\x20row;\x20re-present\x20updates\x20it\x20'+'(recommend\x20text\x20+\x20optional\x20bound\x20Service).\x20Passport-gated\x20variants\x20resolve\x20the\x20Service\x20from\x20'+'the\x20passport\x20submission\x20when\x20the\x20demand\x27s\x20guard\x20sets\x20a\x20service_identifier.','side_effect':'Demand\x20owner\x20now\x20has\x20a\x20candidate;\x20track\x20update_time\x20to\x20rank\x20freshest\x20pitches.\x20'+'This\x20is\x20the\x20supply\x20side\x20of\x20the\x20demand\x20marketplace\x20(K3\x2013\x20§6.7).','params':[{'name':'object','shape':'address','meaning':'The\x20Demand\x20object'},{'name':'service','shape':'Option<address>','meaning':'The\x20presented\x20Service\x20(null\x20=\x20raw\x20recommendation\x20without\x20a\x20bound\x20service)'},{'name':'recommend','shape':'String','meaning':'The\x20presenter\x27s\x20pitch/recommendation\x20text'}]},{'name':'DemandFeedbackEvent','move_type':'::demand::DemandEvent','module':'demand','category':'reputation','consumers':['suggestion_bridge','intent_radar'],'business_meaning':'Demand\x20owner\x20scored/feedbacked\x20a\x20presenter\x20(acceptance\x20score)','trigger':'demand.move\x20`feedback_imp`\x20—\x20only\x20for\x20addresses\x20already\x20in\x20the\x20presenters\x20table;\x20'+'records\x20feedback\x20text\x20+\x20optional\x20acceptance\x20score\x20onto\x20the\x20presenter\x20row.','side_effect':'Acceptance\x20score\x20is\x20the\x20demand-side\x20quality\x20signal\x20for\x20the\x20presenter;\x20high\x20scores\x20build\x20'+'presenter\x20reputation\x20for\x20future\x20matching.','params':[{'name':'object','shape':'address','meaning':'The\x20Demand\x20object'},{'name':'service','shape':'Option<address>','meaning':'The\x20Service\x20that\x20was\x20presented\x20by\x20the\x20scored\x20presenter'},{'name':'feedback','shape':'String','meaning':'Feedback\x20text'},{'name':'acceptance_score','shape':'Option<u8>','meaning':'0-100\x20acceptance\x20score,\x20null\x20when\x20feedback\x20carries\x20no\x20score'}]},{'name':'DemandChangedEvent','move_type':'::demand::DemandChangedEvent','module':'demand','category':'market_opportunity','consumers':['intent_radar'],'channel_note':'Deliberately\x20radar-only:\x20merchant-side\x20discovery\x20is\x20pull-based\x20matching\x20semantics\x20'+'(K3\x2013\x20§6.7\x20opportunity\x20broadcast);\x20there\x20is\x20no\x20goal-bound\x20push\x20target\x20to\x20bridge\x20to.','business_meaning':'Demand\x20became/updated\x20a\x20profitable\x20opportunity\x20for\x20merchants\x20(market-opportunity\x20event)','trigger':'demand.move\x20`demand_changed_event_emit`\x20—\x20fires\x20when\x20rewards\x20are\x20bound/changed,\x20or\x20'+'description/location\x20changes\x20while\x20reward-bearing.\x20A\x20reward-less\x20demand\x20NEVER\x20emits\x20'+'(not\x20a\x20profitable\x20opportunity\x20—\x20K3\x2013\x20§6.7\x20principle).','side_effect':'PRIMARY\x20merchant-side\x20discovery\x20signal:\x20Intent\x20Radar\x20/\x20match\x20engines\x20should\x20treat\x20every\x20'+'emission\x20as\x20a\x20fresh\x20matchmaking\x20opportunity.\x20Reward\x20amounts/claim\x20rules\x20are\x20NOT\x20carried\x20—\x20'+'read\x20the\x20Reward\x20objects\x20by\x20id\x20(authoritative,\x20never\x20stale).','params':[{'name':'object','shape':'address','meaning':'The\x20Demand\x20object'},{'name':'location','shape':'String','meaning':'Demand\x20location\x20(industry/geography\x20routing\x20signal)'},{'name':'description','shape':'String','meaning':'Bounded\x20description\x20preview\x20(truncated\x20on-chain;\x20full\x20text\x20on\x20the\x20object)'},{'name':'rewards','shape':'vector<address>','meaning':'Bound\x20Reward\x20object\x20ids\x20—\x20resolve\x20amounts/conditions\x20by\x20query_objects'}]},{'name':'ProgressEvent','move_type':'::progress::ProgressEvent','module':'progress','category':'state_change','consumers':['suggestion_bridge','intent_radar'],'business_meaning':'Order/task\x20workflow\x20advanced,\x20held,\x20or\x20initialized\x20on\x20a\x20Machine\x20graph','trigger':'progress.move\x20—\x204\x20emission\x20points:\x20`new_imp`\x20(progress\x20created\x20at\x20init\x20node,\x20no\x20forward),\x20'+'`session_accomplish`\x20(threshold\x20reached\x20→\x20node\x20migrated),\x20`hold_imp`/`hold_imp_with_passport`\x20'+'(hold\x20or\x20un-hold\x20of\x20a\x20forward,\x20hold\x20field\x20carries\x20the\x20new\x20state).','side_effect':'Operators\x20should\x20check\x20the\x20new\x20node\x20name\x20against\x20their\x20Machine\x20duties;\x20hold=true\x20pauses\x20that\x20'+'forward\x27s\x20contribution,\x20hold=false\x20resumes\x20it.','params':[{'name':'object','shape':'address','meaning':'The\x20Progress\x20object'},{'name':'machine','shape':'address','meaning':'The\x20Machine\x20(workflow\x20template)\x20governing\x20this\x20progress'},{'name':'task','shape':'Option<address>','meaning':'The\x20bound\x20task\x20(usually\x20the\x20Order)\x20—\x20null\x20for\x20standalone\x20progress'},{'name':'node','shape':'String','meaning':'Node\x20reached\x20(init\x20node\x20on\x20creation;\x20next_node\x20on\x20migration/hold)'},{'name':'forward','shape':'Option<String>','meaning':'The\x20forward\x20name\x20that\x20triggered\x20the\x20transition\x20(null\x20on\x20creation)'},{'name':'hold','shape':'Option<bool>','meaning':'Present\x20only\x20on\x20hold/un-hold:\x20true\x20=\x20forward\x20held,\x20false\x20=\x20released'}]},{'name':'NewEntityEvent','move_type':'::registrar::NewEntityEvent','module':'registrar','category':'lifecycle','consumers':['intent_radar'],'channel_note':'Deliberately\x20radar-only:\x20ecosystem-entry\x20/\x20profile-update\x20signal\x20with\x20no\x20goal-bound\x20'+'push\x20target;\x20the\x20Intent\x20Radar\x20consumes\x20it\x20as\x20matching\x20context,\x20not\x20as\x20an\x20actionable\x20push.','business_meaning':'Entity\x20registered\x20or\x20re-announced\x20(new\x20counterparty\x20/\x20profile\x20update)','trigger':'registrar.move\x20—\x204\x20sites:\x20entity_register\x20/\x20entity_register_with_resource_forced\x20(new\x20Resource\x20'+'created),\x20entity_resource_use\x20(first\x20on-chain\x20use\x20of\x20a\x20resource),\x20entity_description_set,\x20'+'entity_info_add\x20(profile\x20updates\x20re-announce\x20the\x20entity).','side_effect':'A\x20new\x20potential\x20counterparty\x20entered\x20the\x20ecosystem,\x20or\x20an\x20existing\x20one\x20updated\x20its\x20public\x20'+'profile\x20—\x20refresh\x20cached\x20entity\x20profiles/records.','params':[{'name':'resource','shape':'address','meaning':'The\x20entity\x27s\x20Resource\x20object\x20(per-chain\x20identity\x20resource)'},{'name':'referrer','shape':'Option<address>','meaning':'Referring\x20entity\x20address,\x20when\x20registered\x20via\x20referral'}]},{'name':'ServiceEvent','move_type':'::service::ServiceEvent','module':'service','category':'market_opportunity','consumers':['suggestion_bridge','intent_radar'],'business_meaning':'Service\x20became/updated\x20a\x20purchasable\x20supply\x20(active-supply\x20event)','trigger':'service.move\x20`service_event_emit`\x20—\x20ONLY\x20when\x20bPublished\x20&&\x20!bPaused\x20at\x20the\x20mutation\x20point:\x20'+'publish,\x20unpause,\x20and\x20pre-publish\x20description\x20changes\x20re-notify.\x20Pausing\x20/\x20unpublishing\x20/\x20'+'draft-only\x20mutations\x20NEVER\x20emit\x20(not\x20a\x20participatable\x20opportunity\x20—\x20K3\x2013\x20§6.7).','side_effect':'PRIMARY\x20customer-side\x20discovery\x20signal:\x20every\x20emission\x20is\x20a\x20buyable\x20service\x20with\x20its\x20routing\x20'+'text.\x20The\x20authoritative\x20description/sales/stock\x20live\x20on\x20the\x20Service\x20object\x20by\x20id.','params':[{'name':'object','shape':'address','meaning':'The\x20Service\x20object'},{'name':'location','shape':'String','meaning':'Service\x20location\x20(industry/geography\x20routing\x20signal)'},{'name':'description','shape':'String','meaning':'Bounded\x20description\x20preview\x20(truncated\x20on-chain)'}]},{'name':'ArbitrationEvent','move_type':'::arbitration::ArbitrationEvent','module':'arbitration','category':'market_opportunity','consumers':['intent_radar'],'channel_note':'Deliberately\x20radar-only:\x20arbitrator\x20discovery\x20is\x20pull-based\x20matching\x20semantics\x20'+'(merchants\x20query\x20ArbitrationEvent\x20to\x20shortlist\x20third-party\x20arbiters),\x20no\x20goal-bound\x20'+'push\x20target\x20(mirrors\x20DemandChangedEvent).','business_meaning':'Arbitration\x20became\x20selectable/updated\x20a\x20third-party\x20dispute-resolution\x20offer\x20(active-arbiter\x20supply\x20event)','trigger':'arbitration.move\x20`arbitration_event_emit`\x20—\x20ONLY\x20when\x20bPaused\x20==\x20false\x20at\x20the\x20mutation\x20point:\x20'+'pause(false)\x20(unpause/listing),\x20and\x20description_set\x20/\x20location_set\x20/\x20fee_set\x20while\x20active.\x20'+'Pausing\x20or\x20pre-publish\x20mutations\x20NEVER\x20emit\x20(not\x20a\x20selectable\x20opportunity\x20—\x20K3\x2013\x20§6.7).','side_effect':'Merchant-side\x20discovery\x20signal:\x20every\x20emission\x20is\x20a\x20selectable\x20third-party\x20arbiter\x20with\x20its\x20'+'routing\x20text,\x20fee,\x20and\x20voting-guard\x20count.\x20The\x20authoritative\x20description/voting-guards\x20live\x20on\x20the\x20Arbitration\x20object\x20by\x20id.','params':[{'name':'object','shape':'address','meaning':'The\x20Arbitration\x20object\x20id'},{'name':'location','shape':'String','meaning':'Arbitration\x20location\x20(industry/geography\x20routing\x20signal)'},{'name':'description','shape':'String','meaning':'Bounded\x20description\x20preview\x20(truncated\x20on-chain)'},{'name':'fee','shape':'u64','meaning':'Dispute\x20fee\x20charged\x20by\x20the\x20Arbitration\x20(raw\x20on-chain\x20units)'},{'name':'voting_guard_count','shape':'u64','meaning':'Number\x20of\x20voting\x20guards\x20(0\x20=\x20open\x20to\x20everybody;\x20>0\x20=\x20guarded/weighted)'}]},{'name':'AllocationEvent','move_type':'::allocation::AllocationEvent','module':'allocation','category':'fund_flow','consumers':['suggestion_bridge','intent_radar'],'business_meaning':'Allocation\x20run\x20completed\x20—\x20funds\x20left\x20the\x20Allocation\x20pool\x20as\x20a\x20Payment','trigger':'allocation.move\x20alloc\x20loop\x20—\x20when\x20a\x20matching\x20Allocator\x27s\x20guard\x20passes:\x20splits\x20the\x20balance\x20per\x20'+'sharing\x20mode\x20(Amount\x20/\x20Rate\x20‰\x20/\x20Surplus),\x20creates\x20a\x20Payment\x20(from_object\x20=\x20Allocation),\x20'+'then\x20emits\x20with\x20the\x20actually-distributed\x20amount.','side_effect':'Recipients\x20receive\x20CoinWrappers\x20referencing\x20the\x20new\x20Payment\x20—\x20they\x20must\x20unwrap\x20to\x20obtain\x20coins.\x20'+'The\x20Payment\x20is\x20also\x20pushed\x20onto\x20the\x20Allocation\x27s\x20payment\x20list.','params':[{'name':'object','shape':'address','meaning':'The\x20Allocation\x20object\x20that\x20distributed\x20the\x20funds'},{'name':'payment','shape':'address','meaning':'The\x20Payment\x20object\x20created\x20by\x20this\x20run\x20(the\x20on-chain\x20receipt)'},{'name':'guard','shape':'address','meaning':'The\x20guard\x20of\x20the\x20Allocator\x20that\x20authorized\x20this\x20distribution'},{'name':'amount','shape':'u64','meaning':'Amount\x20actually\x20distributed\x20(balance\x20before\x20−\x20balance\x20after)'}]},{'name':'TreasuryEvent','move_type':'::treasury::TreasuryEvent','module':'treasury','category':'fund_flow','consumers':['suggestion_bridge','intent_radar'],'business_meaning':'Treasury\x20fund-flow\x20record\x20(withdraw\x20/\x20deposit\x20/\x20receive)\x20—\x20mirrors\x20on-chain\x20history','trigger':'treasury.move\x20—\x203\x20sites:\x20withdraw_imp\x20(balance\x20split\x20out\x20as\x20Payment,\x20from_object\x20=\x20Treasury),\x20'+'deposit_imp_\x20(coins\x20joined\x20in,\x20a\x20Payment\x20receipt\x20is\x20minted\x20for\x20the\x20depositor),\x20receive_imp\x20'+'(a\x20CoinWrapper\x20from\x20a\x20Payment\x20is\x20received\x20into\x20the\x20treasury).\x20Each\x20emission\x20appends\x20a\x20Record\x20'+'to\x20the\x20treasury\x27s\x20on-chain\x20history\x20parent\x20table.','params':[{'name':'object','shape':'address','meaning':'The\x20Treasury\x20object'},{'name':'op','shape':'u8','meaning':'0\x20Withdraw\x20·\x201\x20Deposit\x20·\x202\x20Receive'},{'name':'payment','shape':'address','meaning':'The\x20Payment\x20receipt\x20minted\x20for\x20this\x20flow'},{'name':'amount','shape':'u64','meaning':'Flow\x20amount\x20(raw\x20on-chain\x20units\x20of\x20the\x20Treasury\x27s\x20token)'},{'name':'external_guard','shape':'Option<address>','meaning':'External\x20withdraw\x20guard\x20that\x20authorized\x20a\x20withdraw,\x20if\x20any'},{'name':'store_from_id','shape':'Option<address>','meaning':'Passport-derived\x20store/branch\x20id\x20(multi-branch\x20treasury\x20bookkeeping)'}]},{'name':'RewardClaimEvent','move_type':'::reward::RewardClaimEvent','module':'reward','category':'fund_flow','consumers':['suggestion_bridge','intent_radar'],'business_meaning':'Reward\x20claimed\x20—\x20funds\x20paid\x20out\x20of\x20a\x20Reward\x20pool','trigger':'reward.move\x20claim\x20path\x20—\x20after\x20guard+passport\x20validation:\x20appends\x20a\x20Record\x20to\x20the\x20recipient\x27s\x20'+'on-chain\x20record,\x20splits\x20the\x20balance,\x20emits,\x20then\x20transfers\x20the\x20coin\x20to\x20the\x20recipient.\x20'+'The\x20ONLY\x20realtime\x20trace\x20of\x20the\x20claim\x20outflow.','params':[{'name':'object','shape':'address','meaning':'The\x20Reward\x20pool\x20object'},{'name':'guard','shape':'address','meaning':'The\x20reward\x20guard\x20that\x20authorized\x20this\x20claim'},{'name':'recipient','shape':'address','meaning':'Claim\x20recipient\x20(resolved\x20via\x20passport\x20when\x20required)'},{'name':'amount','shape':'u64','meaning':'This\x20claim\x27s\x20amount'},{'name':'total','shape':'u64','meaning':'Recipient\x27s\x20cumulative\x20claimed\x20total\x20on\x20this\x20pool'},{'name':'balance_left','shape':'u64','meaning':'Pool\x20balance\x20remaining\x20after\x20the\x20claim'},{'name':'store_from_id','shape':'Option<address>','meaning':'Passport-derived\x20store/branch\x20id,\x20when\x20the\x20guard\x20requires\x20it'}]},{'name':'RewardFundEvent','move_type':'::reward::RewardFundEvent','module':'reward','category':'fund_flow','consumers':['suggestion_bridge','intent_radar'],'business_meaning':'Reward\x20pool\x20inflow\x20—\x20funds\x20added\x20to\x20the\x20pool','trigger':'reward.move\x20—\x202\x20sites:\x20coin_add_imp\x20(direct\x20coin\x20deposit,\x20from_payment\x20=\x20null)\x20and\x20receive_imp\x20'+'(a\x20Payment\x27s\x20CoinWrapper\x20received\x20into\x20the\x20pool,\x20from_payment\x20=\x20that\x20Payment).','side_effect':'Claim\x20guards\x20whose\x20pool\x20ran\x20dry\x20become\x20satisfiable\x20again;\x20watchers\x20should\x20re-check\x20claim\x20'+'opportunities\x20against\x20the\x20new\x20balance.','params':[{'name':'object','shape':'address','meaning':'The\x20Reward\x20pool\x20object'},{'name':'amount','shape':'u64','meaning':'Inflow\x20amount'},{'name':'balance','shape':'u64','meaning':'Pool\x20balance\x20after\x20the\x20inflow'},{'name':'from_payment','shape':'Option<address>','meaning':'The\x20Payment\x20that\x20funded\x20this\x20inflow\x20(null\x20for\x20direct\x20coin\x20adds)'}]},{'name':'NewPaymentEvent','move_type':'::payment::NewPaymentEvent','module':'payment','category':'fund_flow','consumers':['keeper','intent_radar'],'channel_note':'Deliberately\x20NOT\x20suggestion-bridged\x20(P2-4):\x20the\x20keeper\x20payment_unclaimed\x20state\x20scan\x20'+'owns\x20the\x20claimable-payment\x20reminder;\x20an\x20event\x20push\x20here\x20would\x20duplicate\x20it.','business_meaning':'A\x20Payment\x20was\x20created\x20—\x20the\x20universal\x20on-chain\x20receipt\x20of\x20WoWok\x20fund\x20flows','trigger':'payment.move\x20`create`\x20—\x20the\x20ONLY\x20emission\x20point,\x20reached\x20by\x20treasury\x20withdraw/deposit,\x20'+'allocation\x20runs,\x20service\x20compensation\x20payouts,\x20and\x20direct\x20user\x20payments\x20alike.\x20'+'Emission\x20is\x20the\x20last\x20step\x20before\x20the\x20Payment\x20object\x20is\x20frozen\x20(immutable\x20receipt).','side_effect':'Every\x20recipient\x20in\x20`record`\x20received\x20a\x20frozen\x20CoinWrapper\x20that\x20references\x20this\x20Payment\x20—\x20'+'unwrap\x20converts\x20it\x20to\x20a\x20transferable\x20Coin.\x20info.for_object\x20/\x20info.for_guard\x20/\x20from_object\x20'+'are\x20registered\x20as\x20object-linker\x20affiliations,\x20so\x20the\x20payment\x20is\x20discoverable\x20via\x20global\x20'+'affiliation\x20tables\x20(onchain_affiliations_of_object).','params':[{'name':'object','shape':'address','meaning':'The\x20Payment\x20object\x20id\x20(the\x20receipt)'},{'name':'info.for_object','shape':'Option<address>','meaning':'The\x20business\x20object\x20this\x20payment\x20is\x20FOR\x20(order/demand/reward/…)\x20—\x20user-settable\x20routing\x20hint'},{'name':'info.for_guard','shape':'Option<address>','meaning':'The\x20Guard\x20governing\x20this\x20payment\x20—\x20user-settable,\x20links\x20the\x20payment\x20to\x20a\x20trust\x20rule'},{'name':'info.remark','shape':'String','meaning':'Free-form\x20on-chain\x20remark\x20(e.g.\x20invoice\x20number,\x20purpose)'},{'name':'info.index','shape':'u64','meaning':'Creator-local\x20index\x20(installment\x20sequence,\x20table\x20row,\x20…)'},{'name':'record','shape':'vector<{recipient,\x20amount}>','meaning':'Revenue\x20legs:\x20one\x20{recipient,\x20amount}\x20per\x20CoinWrapper\x20transferred'},{'name':'amount','shape':'u64','meaning':'Total\x20paid\x20across\x20all\x20legs\x20(sum\x20of\x20record\x20amounts)'},{'name':'from_object','shape':'Option<address>','meaning':'FUNDING-SOURCE\x20object\x20the\x20funds\x20LEFT\x20from\x20—\x20INTERNAL-ONLY\x20field\x20(public(package)\x20'+'from_object_set;\x20user\x20code\x20can\x20never\x20set\x20it).\x20Treasury\x20withdraw\x20⇒\x20the\x20Treasury;\x20'+'Allocation\x20run\x20⇒\x20the\x20Allocation;\x20Service\x20compensation\x20withdraw\x20⇒\x20the\x20Service.\x20'+'create()\x20registers\x20an\x20object_linker\x20affiliation\x20(from_object\x20→\x20payment)\x20so\x20the\x20'+'outflow\x20is\x20traceable\x20back\x20to\x20its\x20pool.\x20Null\x20for\x20direct\x20user-initiated\x20payments\x20'+'(no\x20on-chain\x20source\x20object).'}]}];export const EVENT_BY_NAME=new Map(EVENT_SEMANTIC_REGISTRY['map'](a=>[a['name'],a]));export const EVENT_BY_MOVE_TYPE=new Map(EVENT_SEMANTIC_REGISTRY['map'](a=>[a['move_type'],a]));export function lookupEventMeaning(a){const b=String(a?.['type']??''),c=EVENT_BY_NAME['get'](b);if(c)return c['business_meaning'];const d=String(a?.['type_raw']??'');if(d)for(const f of EVENT_SEMANTIC_REGISTRY){if(d['includes'](f['move_type']))return f['business_meaning'];}return undefined;}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ import{describe,expect,it}from'vitest';import{EVENT_SEMANTIC_REGISTRY}from'./event-semantics.js';const EXPECTED_EVENTS=['NewOrderEvent','ArbEvent','ArbitrationEvent','VoteEvent','FeedbackEvent','DemandPresentEvent','DemandFeedbackEvent','DemandChangedEvent','ProgressEvent','NewEntityEvent','ServiceEvent','AllocationEvent','TreasuryEvent','RewardClaimEvent','RewardFundEvent','NewPaymentEvent'];describe('event\x20semantics\x20channel\x20ownership\x20(N-3)',()=>{it('registry\x20covers\x20all\x2016\x20framework\x20events',()=>{expect(EVENT_SEMANTIC_REGISTRY['map'](a=>a['name'])['sort']())['toEqual']([...EXPECTED_EVENTS]['sort']());}),it('every\x20entry\x20declares\x20at\x20least\x20one\x20consumer\x20channel',()=>{for(const a of EVENT_SEMANTIC_REGISTRY){expect(a['consumers']['length'],a['name']+'\x20has\x20no\x20consumer\x20channel')['toBeGreaterThan'](0x0);}}),it('an\x20entry\x20without\x20any\x20push\x20consumer\x20must\x20document\x20why\x20(channel_note)',()=>{const a=['suggestion_bridge','problem_bridge'];for(const b of EVENT_SEMANTIC_REGISTRY){const c=b['consumers']['some'](d=>a['includes'](d));!c&&expect(b['channel_note'],b['name']+'\x20lacks\x20push\x20consumers\x20but\x20has\x20no\x20channel_note')['toBeTruthy']();}}),it('the\x20deliberate\x20non-bridge\x20events\x20carry\x20their\x20documented\x20ownership',()=>{const a=new Map(EVENT_SEMANTIC_REGISTRY['map'](b=>[b['name'],b]));for(const b of['VoteEvent','DemandChangedEvent','NewEntityEvent','ArbitrationEvent']){expect(a['get'](b)?.['consumers'])['toEqual'](['intent_radar']);}expect(a['get']('NewPaymentEvent')?.['consumers'])['toEqual'](['keeper','intent_radar']);});});