@wowok/agent-mcp 2.6.1 → 2.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/customer/customer-advice.d.ts +31 -0
- package/dist/customer/customer-advice.js +129 -0
- package/dist/customer/index.d.ts +2 -0
- package/dist/customer/index.js +2 -0
- package/dist/customer/info-puzzle.d.ts +9 -2
- package/dist/customer/info-puzzle.js +34 -7
- package/dist/customer/order-monitor.d.ts +2 -0
- package/dist/customer/order-monitor.js +3 -2
- package/dist/customer/post-purchase.d.ts +2 -0
- package/dist/customer/post-purchase.js +6 -5
- package/dist/customer/preorder-compare.d.ts +24 -0
- package/dist/customer/preorder-compare.js +34 -0
- package/dist/customer/reminder-system.d.ts +2 -0
- package/dist/customer/reminder-system.js +2 -1
- package/dist/customer/risk-assessment.js +30 -7
- package/dist/customer/types.d.ts +7 -0
- package/dist/examples/arbitration-dispute-create.json +41 -0
- package/dist/examples/arbitration-vote-weighted.json +35 -0
- package/dist/examples/arbitration-voting-guard-add.json +38 -0
- package/dist/examples/demand-present-service.json +33 -0
- package/dist/examples/gen-passport-verify-guard.json +48 -0
- package/dist/examples/guard-template-balance-check.json +59 -0
- package/dist/examples/guard-template-time-lock.json +60 -0
- package/dist/examples/insurance-guard-claim-timelock.json +75 -0
- package/dist/examples/insurance-guard-withdraw-allocation.json +96 -0
- package/dist/examples/insurance-machine-create-publish.json +75 -0
- package/dist/examples/insurance-service-allocators-publish.json +56 -0
- package/dist/examples/machine-multisig-threshold.json +86 -0
- package/dist/examples/machine-template-7node-rental.json +119 -0
- package/dist/examples/payment-scenario-bound.json +45 -0
- package/dist/examples/rental-ziroom-machine-create.json +149 -0
- package/dist/examples/rental-ziroom-permission-create.json +42 -0
- package/dist/examples/rental-ziroom-service-create.json +89 -0
- package/dist/examples/retail-adv-guard-customer-win-create.json +80 -0
- package/dist/examples/retail-adv-guard-messenger-proof-create.json +65 -0
- package/dist/examples/retail-adv-guard-reward-timeout-create.json +92 -0
- package/dist/examples/retail-adv-reward-guard-add.json +51 -0
- package/dist/examples/retail-myshop-allocation-activate.json +55 -0
- package/dist/examples/retail-myshop-arbitration-create.json +40 -0
- package/dist/examples/retail-myshop-contact-create.json +43 -0
- package/dist/examples/retail-myshop-order-create.json +56 -0
- package/dist/examples/retail-myshop-progress-operate.json +38 -0
- package/dist/examples/retail-myshop-reward-create.json +35 -0
- package/dist/examples/retail-myshop-service-create.json +88 -0
- package/dist/examples/service-discount-issue.json +46 -0
- package/dist/examples/threebody-guard-create.json +56 -0
- package/dist/examples/threebody-machine-create.json +72 -0
- package/dist/examples/threebody-permission-create.json +38 -0
- package/dist/examples/threebody-service-allocators.json +49 -0
- package/dist/examples/travel-guard-time-lock.json +69 -0
- package/dist/examples/travel-guard-weather-oracle.json +70 -0
- package/dist/examples/travel-machine-create.json +136 -0
- package/dist/examples/travel-repository-create.json +47 -0
- package/dist/examples/travel-service-create.json +102 -0
- package/dist/examples/travel-treasury-create.json +34 -0
- package/dist/examples/treasury-deposit.json +37 -0
- package/dist/examples/treasury-withdraw.json +38 -0
- package/dist/extensions/business-modules.d.ts +49 -0
- package/dist/extensions/business-modules.js +287 -0
- package/dist/extensions/capability-manifest.js +216 -29
- package/dist/extensions/constraint-registry.js +21 -19
- package/dist/extensions/metric-registry.js +14 -14
- package/dist/extensions/mode-evaluator.js +16 -16
- package/dist/extensions/modes.js +141 -49
- package/dist/extensions/registry.d.ts +16 -9
- package/dist/extensions/registry.js +132 -44
- package/dist/extensions/types.d.ts +2 -0
- package/dist/index.js +50 -0
- package/dist/knowledge/deployment-scanner.js +1 -1
- package/dist/knowledge/fund-layer.d.ts +138 -0
- package/dist/knowledge/fund-layer.js +969 -0
- package/dist/knowledge/guard-render.d.ts +57 -0
- package/dist/knowledge/guard-render.js +700 -0
- package/dist/knowledge/guard-submission-prompt.d.ts +31 -0
- package/dist/knowledge/guard-submission-prompt.js +171 -0
- package/dist/knowledge/guard-templates.d.ts +10 -0
- package/dist/knowledge/guard-templates.js +50 -0
- package/dist/knowledge/index.d.ts +2 -2
- package/dist/knowledge/index.js +2 -2
- package/dist/knowledge/machine-ledger.js +1 -1
- package/dist/knowledge/machine-render.d.ts +41 -0
- package/dist/knowledge/machine-render.js +565 -0
- package/dist/knowledge/machine-risk.js +4 -1
- package/dist/knowledge/machine-templates.js +4 -4
- package/dist/knowledge/progress-context.js +1 -1
- package/dist/knowledge/progress-ledger.js +3 -3
- package/dist/knowledge/progress-templates.js +1 -1
- package/dist/knowledge/progress-translation.js +1 -1
- package/dist/knowledge/reward-confirm.js +2 -2
- package/dist/knowledge/reward-puzzle.js +1 -1
- package/dist/knowledge/reward-risk.js +9 -9
- package/dist/knowledge/reward-templates.js +2 -2
- package/dist/knowledge/safety-rules.d.ts +83 -1
- package/dist/knowledge/safety-rules.js +166 -2
- package/dist/knowledge/scenario-modes.d.ts +1 -1
- package/dist/knowledge/scenario-modes.js +13 -11
- package/dist/knowledge/service-confirm.d.ts +1 -1
- package/dist/knowledge/service-confirm.js +3 -3
- package/dist/knowledge/service-context.js +1 -1
- package/dist/knowledge/service-ledger.js +1 -1
- package/dist/knowledge/service-risk.d.ts +1 -1
- package/dist/knowledge/service-risk.js +3 -3
- package/dist/knowledge/service-templates.js +2 -2
- package/dist/knowledge/service-translation.d.ts +1 -1
- package/dist/knowledge/service-translation.js +7 -7
- package/dist/knowledge/template-registry.d.ts +48 -0
- package/dist/knowledge/template-registry.js +341 -0
- package/dist/knowledge/tool-constraints.js +6 -6
- package/dist/knowledge/tools-reference.js +11 -8
- package/dist/participation/merchant-interest.d.ts +32 -0
- package/dist/participation/merchant-interest.js +100 -0
- package/dist/participation/radar-core.d.ts +104 -0
- package/dist/participation/radar-core.js +269 -0
- package/dist/project/context-assembly.js +8 -0
- package/dist/project/deployment-bridge.js +6 -5
- package/dist/project/deployment-doc.js +5 -5
- package/dist/project/edit-planner.d.ts +123 -0
- package/dist/project/edit-planner.js +1342 -0
- package/dist/project/evaluation.d.ts +36 -0
- package/dist/project/evaluation.js +734 -68
- package/dist/project/game-theory.d.ts +43 -0
- package/dist/project/game-theory.js +177 -0
- package/dist/project/graph-builder.js +7 -1
- package/dist/project/handlers.d.ts +137 -2
- package/dist/project/handlers.js +423 -51
- package/dist/project/intent-analyzer.d.ts +71 -0
- package/dist/project/intent-analyzer.js +149 -0
- package/dist/project/machine-nodes.d.ts +2 -0
- package/dist/project/machine-nodes.js +36 -0
- package/dist/project/merchant-guide.d.ts +165 -0
- package/dist/project/merchant-guide.js +264 -0
- package/dist/project/mode-actions.d.ts +199 -0
- package/dist/project/mode-actions.js +309 -0
- package/dist/project/participation-radar.d.ts +18 -0
- package/dist/project/participation-radar.js +428 -0
- package/dist/project/pipeline-actions.d.ts +101 -0
- package/dist/project/pipeline-actions.js +109 -0
- package/dist/project/semantic-graph.d.ts +95 -0
- package/dist/project/semantic-graph.js +245 -0
- package/dist/project/stage-gate.js +4 -4
- package/dist/schema/call/allocation.d.ts +11 -11
- package/dist/schema/call/allocation.js +13 -3
- package/dist/schema/call/arbitration.d.ts +21 -21
- package/dist/schema/call/arbitration.js +30 -9
- package/dist/schema/call/base.d.ts +2 -2
- package/dist/schema/call/base.js +1 -1
- package/dist/schema/call/bridge.d.ts +127 -127
- package/dist/schema/call/bridge.js +12 -12
- package/dist/schema/call/contact.d.ts +3 -3
- package/dist/schema/call/contact.js +2 -2
- package/dist/schema/call/demand.d.ts +3 -3
- package/dist/schema/call/demand.js +2 -2
- package/dist/schema/call/guard.d.ts +11 -11
- package/dist/schema/call/guard.js +2 -2
- package/dist/schema/call/machine.d.ts +2072 -679
- package/dist/schema/call/machine.js +51 -5
- package/dist/schema/call/order.d.ts +7 -7
- package/dist/schema/call/order.js +3 -6
- package/dist/schema/call/payment.d.ts +3 -3
- package/dist/schema/call/permission.d.ts +3 -3
- package/dist/schema/call/permission.js +2 -2
- package/dist/schema/call/personal.d.ts +337 -3
- package/dist/schema/call/personal.js +10 -0
- package/dist/schema/call/progress.d.ts +177 -9
- package/dist/schema/call/progress.js +7 -3
- package/dist/schema/call/proof.d.ts +6 -6
- package/dist/schema/call/repository.d.ts +3 -3
- package/dist/schema/call/repository.js +2 -2
- package/dist/schema/call/reward.d.ts +57 -57
- package/dist/schema/call/reward.js +3 -3
- package/dist/schema/call/semantic.js +48 -2
- package/dist/schema/call/service.d.ts +285 -113
- package/dist/schema/call/service.js +92 -28
- package/dist/schema/call/treasury.d.ts +57 -57
- package/dist/schema/call/treasury.js +3 -3
- package/dist/schema/common/index.d.ts +2 -0
- package/dist/schema/common/index.js +46 -10
- package/dist/schema/local/index.js +5 -1
- package/dist/schema/messenger/index.js +4 -1
- package/dist/schema/operations.d.ts +1318 -317
- package/dist/schema/operations.js +76 -7
- package/dist/schema/project/index.d.ts +5662 -164
- package/dist/schema/project/index.js +1136 -5
- package/dist/schema/query/index.d.ts +580 -19
- package/dist/schema/query/index.js +88 -36
- package/dist/schema/schema-query/index.d.ts +59 -3
- package/dist/schema/schema-query/index.js +45 -6
- package/dist/schema/trust/index.d.ts +1012 -6
- package/dist/schema/trust/index.js +212 -11
- package/dist/schema/utils/node-parser.js +13 -0
- package/dist/schema/utils/object-type-utils.d.ts +12 -0
- package/dist/schema/utils/object-type-utils.js +35 -0
- package/dist/schema/utils/permission-machine-check.d.ts +49 -0
- package/dist/schema/utils/permission-machine-check.js +121 -0
- package/dist/schema/utils/skills-recommendation.d.ts +2 -0
- package/dist/schema/utils/skills-recommendation.js +77 -0
- package/dist/schema-query/index.d.ts +17 -1
- package/dist/schema-query/index.js +359 -3
- package/dist/schemas/account_operation.schema.json +1 -1
- package/dist/schemas/bridge_operation.schema.json +14 -7
- package/dist/schemas/guard2file.schema.json +2 -0
- package/dist/schemas/index.json +1 -1
- package/dist/schemas/machineNode2file.schema.json +2 -0
- package/dist/schemas/messenger_operation.schema.json +1 -1
- package/dist/schemas/onchain_events.output.json +1 -1
- package/dist/schemas/onchain_operations.output.json +2820 -0
- package/dist/schemas/onchain_operations.schema.json +255 -65
- package/dist/schemas/onchain_operations_allocation.schema.json +7 -6
- package/dist/schemas/onchain_operations_arbitration.schema.json +14 -10
- package/dist/schemas/onchain_operations_contact.schema.json +4 -3
- package/dist/schemas/onchain_operations_demand.schema.json +4 -3
- package/dist/schemas/onchain_operations_gen_passport.schema.json +4 -2
- package/dist/schemas/onchain_operations_gen_proof.schema.json +2 -0
- package/dist/schemas/onchain_operations_guard.schema.json +579 -1
- package/dist/schemas/onchain_operations_machine.schema.json +5 -4
- package/dist/schemas/onchain_operations_order.schema.json +7 -6
- package/dist/schemas/onchain_operations_payment.schema.json +2 -1
- package/dist/schemas/onchain_operations_permission.schema.json +3 -2
- package/dist/schemas/onchain_operations_personal.schema.json +37 -0
- package/dist/schemas/onchain_operations_progress.schema.json +91 -4
- package/dist/schemas/onchain_operations_proof.schema.json +2 -1
- package/dist/schemas/onchain_operations_repository.schema.json +4 -3
- package/dist/schemas/onchain_operations_reward.schema.json +7 -6
- package/dist/schemas/onchain_operations_service.schema.json +80 -19
- package/dist/schemas/onchain_operations_treasury.schema.json +5 -4
- package/dist/schemas/onchain_table_data.output.json +1 -1
- package/dist/schemas/onchain_table_data.schema.json +10 -9
- package/dist/schemas/project_operation.output.json +3318 -57
- package/dist/schemas/project_operation.schema.json +728 -4
- package/dist/schemas/query_toolkit.output.json +16 -16
- package/dist/schemas/query_toolkit.schema.json +40 -3
- package/dist/schemas/schema_query.output.json +65 -2
- package/dist/schemas/schema_query.schema.json +31 -5
- package/dist/schemas/trust_score.output.json +392 -1
- package/dist/schemas/trust_score.schema.json +275 -1
- package/dist/schemas/wowok_buildin_info.output.json +81 -8
- package/dist/schemas/wowok_buildin_info.schema.json +46 -2
- package/dist/tools/handlers/onchain.js +636 -6
- package/dist/tools/handlers/project.js +71 -2
- package/dist/tools/handlers/query.js +117 -2
- package/dist/tools/handlers/schema-query.js +65 -1
- package/dist/tools/handlers/trust.js +192 -6
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.js +229 -15
- package/dist/tools/wrap.js +194 -15
- package/package.json +2 -2
|
@@ -0,0 +1,565 @@
|
|
|
1
|
+
function sanitizeMermaidLabel(text) {
|
|
2
|
+
if (/[<>"\[\]{}()|&]/.test(text)) {
|
|
3
|
+
return `"${text.replace(/"/g, "'")}"`;
|
|
4
|
+
}
|
|
5
|
+
return text;
|
|
6
|
+
}
|
|
7
|
+
const MACHINE_NODE_COLORS = {
|
|
8
|
+
entry: { fill: "#10b981", stroke: "#065f46" },
|
|
9
|
+
terminal: { fill: "#ef4444", stroke: "#991b1b" },
|
|
10
|
+
revision: { fill: "#f59e0b", stroke: "#92400e" },
|
|
11
|
+
normal: { fill: "#3b82f6", stroke: "#1e40af" },
|
|
12
|
+
};
|
|
13
|
+
function classifyMachineNode(nodeName, edges, entryNodes) {
|
|
14
|
+
const outEdges = edges.filter(e => e.from === nodeName);
|
|
15
|
+
if (outEdges.length === 0)
|
|
16
|
+
return "terminal";
|
|
17
|
+
const hasOutgoingToNode = outEdges.some(e => e.to !== "");
|
|
18
|
+
if (!hasOutgoingToNode)
|
|
19
|
+
return "terminal";
|
|
20
|
+
const isRevisionTarget = edges.some(e => e.to === nodeName && e.from === nodeName);
|
|
21
|
+
if (isRevisionTarget)
|
|
22
|
+
return "revision";
|
|
23
|
+
if (entryNodes.has(nodeName))
|
|
24
|
+
return "entry";
|
|
25
|
+
return "normal";
|
|
26
|
+
}
|
|
27
|
+
export function sanitizeMermaidNodeId(name) {
|
|
28
|
+
if (/[^a-zA-Z0-9_]/.test(name)) {
|
|
29
|
+
return `"${name}"`;
|
|
30
|
+
}
|
|
31
|
+
return name;
|
|
32
|
+
}
|
|
33
|
+
export function renderMachineMermaid(nodes, edges, options) {
|
|
34
|
+
const colored = options?.colored !== false;
|
|
35
|
+
const lines = ["stateDiagram-v2"];
|
|
36
|
+
if (colored) {
|
|
37
|
+
lines.push(" %% Color Legend (BehaviorTree.CPP-inspired workflow roles):");
|
|
38
|
+
lines.push(" %% green #10b981 - entry (start state, targeted by [*])");
|
|
39
|
+
lines.push(" %% red #ef4444 - terminal (end state, no outgoing edges)");
|
|
40
|
+
lines.push(" %% amber #f59e0b - revision (self-loop / revision cycle)");
|
|
41
|
+
lines.push(" %% blue #3b82f6 - normal (regular intermediate state)");
|
|
42
|
+
lines.push(" %% Priority: terminal > revision > entry > normal");
|
|
43
|
+
}
|
|
44
|
+
const nodesWithIncoming = new Set(edges.filter(e => e.from !== "").map(e => e.to));
|
|
45
|
+
const entryNodes = new Set();
|
|
46
|
+
for (const node of nodes) {
|
|
47
|
+
if (!nodesWithIncoming.has(node.name)) {
|
|
48
|
+
entryNodes.add(node.name);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const entryNodesList = nodes.filter(n => entryNodes.has(n.name));
|
|
52
|
+
for (const entry of entryNodesList) {
|
|
53
|
+
const entryEdges = edges.filter(e => e.from === "" && e.to === entry.name);
|
|
54
|
+
if (entryEdges.length > 0) {
|
|
55
|
+
for (const edge of entryEdges) {
|
|
56
|
+
for (const fwd of edge.forwards) {
|
|
57
|
+
const label = buildForwardLabel(fwd, edge.threshold);
|
|
58
|
+
lines.push(` [*] --> ${sanitizeMermaidNodeId(entry.name)}: ${sanitizeMermaidLabel(label)}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
lines.push(` [*] --> ${sanitizeMermaidNodeId(entry.name)}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
for (const edge of edges) {
|
|
67
|
+
if (edge.from === "")
|
|
68
|
+
continue;
|
|
69
|
+
const fromId = sanitizeMermaidNodeId(edge.from);
|
|
70
|
+
const toId = edge.to === "" ? "[*]" : sanitizeMermaidNodeId(edge.to);
|
|
71
|
+
for (const fwd of edge.forwards) {
|
|
72
|
+
const label = buildForwardLabel(fwd, edge.threshold);
|
|
73
|
+
lines.push(` ${fromId} --> ${toId}: ${sanitizeMermaidLabel(label)}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
for (const node of nodes) {
|
|
77
|
+
if (node.description) {
|
|
78
|
+
lines.push(` ${sanitizeMermaidNodeId(node.name)}: ${sanitizeMermaidLabel(node.description)}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (colored) {
|
|
82
|
+
lines.push("");
|
|
83
|
+
lines.push(" %% Node colors (BehaviorTree.CPP-inspired workflow roles)");
|
|
84
|
+
for (const node of nodes) {
|
|
85
|
+
const category = classifyMachineNode(node.name, edges, entryNodes);
|
|
86
|
+
const color = MACHINE_NODE_COLORS[category];
|
|
87
|
+
lines.push(` style ${sanitizeMermaidNodeId(node.name)} fill:${color.fill},stroke:${color.stroke},color:#fff`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return lines.join("\n");
|
|
91
|
+
}
|
|
92
|
+
function buildForwardLabel(fwd, threshold) {
|
|
93
|
+
let label = fwd.name;
|
|
94
|
+
const annotations = [];
|
|
95
|
+
if (threshold > 1) {
|
|
96
|
+
annotations.push(`threshold=${threshold}`);
|
|
97
|
+
}
|
|
98
|
+
if (fwd.guard) {
|
|
99
|
+
const shortGuard = fwd.guard.length > 10
|
|
100
|
+
? `${fwd.guard.slice(0, 6)}…${fwd.guard.slice(-4)}`
|
|
101
|
+
: fwd.guard;
|
|
102
|
+
annotations.push(`guard=${shortGuard}`);
|
|
103
|
+
}
|
|
104
|
+
if (annotations.length > 0) {
|
|
105
|
+
label += ` (${annotations.join(", ")})`;
|
|
106
|
+
}
|
|
107
|
+
return label;
|
|
108
|
+
}
|
|
109
|
+
export function renderMachineTreeIndented(input) {
|
|
110
|
+
const { nodes, edges, machineName, machineAddress, published, paused } = input;
|
|
111
|
+
const lines = [];
|
|
112
|
+
lines.push("# Machine Workflow Definition");
|
|
113
|
+
lines.push("");
|
|
114
|
+
if (machineName) {
|
|
115
|
+
lines.push(`**Machine:** ${machineName}`);
|
|
116
|
+
}
|
|
117
|
+
if (machineAddress) {
|
|
118
|
+
lines.push(`**Address:** ${machineAddress}`);
|
|
119
|
+
}
|
|
120
|
+
lines.push(`**Total Nodes:** ${nodes.length}`);
|
|
121
|
+
lines.push(`**Total Edges:** ${edges.length}`);
|
|
122
|
+
if (published !== null && published !== undefined) {
|
|
123
|
+
lines.push(`**Published:** ${published}`);
|
|
124
|
+
}
|
|
125
|
+
if (paused !== null && paused !== undefined) {
|
|
126
|
+
lines.push(`**Paused:** ${paused}`);
|
|
127
|
+
}
|
|
128
|
+
lines.push("");
|
|
129
|
+
lines.push("## Topology (directed graph outline)");
|
|
130
|
+
lines.push("");
|
|
131
|
+
const entryEdges = edges.filter(e => e.from === "");
|
|
132
|
+
const regularEdges = edges.filter(e => e.from !== "");
|
|
133
|
+
for (const edge of entryEdges) {
|
|
134
|
+
const header = `- [*] --> ${edge.to} (threshold=${edge.threshold})`;
|
|
135
|
+
lines.push(header);
|
|
136
|
+
for (const fwd of edge.forwards) {
|
|
137
|
+
lines.push(` - forward: ${formatForwardInline(fwd)}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
for (const edge of regularEdges) {
|
|
141
|
+
const isSelfLoop = edge.from === edge.to;
|
|
142
|
+
const annotation = isSelfLoop ? " # self-loop (revision cycle)" : "";
|
|
143
|
+
const toLabel = edge.to === "" ? "[*]" : edge.to;
|
|
144
|
+
const header = `- ${edge.from} --> ${toLabel} (threshold=${edge.threshold})${annotation}`;
|
|
145
|
+
lines.push(header);
|
|
146
|
+
for (const fwd of edge.forwards) {
|
|
147
|
+
lines.push(` - forward: ${formatForwardInline(fwd)}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const nodesWithDesc = nodes.filter(n => n.description);
|
|
151
|
+
if (nodesWithDesc.length > 0) {
|
|
152
|
+
lines.push("");
|
|
153
|
+
lines.push("## Node Descriptions");
|
|
154
|
+
lines.push("");
|
|
155
|
+
for (const node of nodes) {
|
|
156
|
+
if (node.description) {
|
|
157
|
+
lines.push(`- ${node.name}: ${node.description}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const incomingMap = new Map();
|
|
162
|
+
for (const edge of edges) {
|
|
163
|
+
if (!incomingMap.has(edge.to))
|
|
164
|
+
incomingMap.set(edge.to, []);
|
|
165
|
+
incomingMap.get(edge.to).push({
|
|
166
|
+
from: edge.from === "" ? "[*]" : edge.from,
|
|
167
|
+
forwards: edge.forwards.map(f => f.name),
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
if (incomingMap.size > 0) {
|
|
171
|
+
lines.push("");
|
|
172
|
+
lines.push("## Backrefs (incoming edges per node)");
|
|
173
|
+
lines.push("");
|
|
174
|
+
for (const node of nodes) {
|
|
175
|
+
const incoming = incomingMap.get(node.name);
|
|
176
|
+
if (!incoming || incoming.length === 0)
|
|
177
|
+
continue;
|
|
178
|
+
const parts = incoming.map(inc => {
|
|
179
|
+
const fwdStr = inc.forwards.length > 0 ? ` (${inc.forwards.join(", ")})` : "";
|
|
180
|
+
const selfLoop = inc.from === node.name ? " # self-loop" : "";
|
|
181
|
+
return `<- ${inc.from}${fwdStr}${selfLoop}`;
|
|
182
|
+
});
|
|
183
|
+
lines.push(`- ${node.name}: ${parts.join(", ")}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
lines.push("");
|
|
187
|
+
lines.push("## JSON Definition");
|
|
188
|
+
lines.push("");
|
|
189
|
+
lines.push("```json");
|
|
190
|
+
lines.push(JSON.stringify({ nodes, edges }, null, 2));
|
|
191
|
+
lines.push("```");
|
|
192
|
+
return lines.join("\n");
|
|
193
|
+
}
|
|
194
|
+
function formatForwardInline(fwd) {
|
|
195
|
+
const parts = [`weight=${fwd.weight}`];
|
|
196
|
+
if (fwd.named_operator !== null && fwd.named_operator !== undefined) {
|
|
197
|
+
parts.push(`namedOperator='${fwd.named_operator}'`);
|
|
198
|
+
}
|
|
199
|
+
if (fwd.permission_index !== null && fwd.permission_index !== undefined) {
|
|
200
|
+
parts.push(`permissionIndex=${fwd.permission_index}`);
|
|
201
|
+
}
|
|
202
|
+
if (fwd.guard) {
|
|
203
|
+
parts.push(`guard=${fwd.guard}`);
|
|
204
|
+
}
|
|
205
|
+
if (fwd.retained_submission) {
|
|
206
|
+
const rsStr = Array.isArray(fwd.retained_submission)
|
|
207
|
+
? `[${fwd.retained_submission.join(",")}]`
|
|
208
|
+
: String(fwd.retained_submission);
|
|
209
|
+
parts.push(`retained_submission=${rsStr}`);
|
|
210
|
+
}
|
|
211
|
+
return `${fwd.name} (${parts.join(", ")})`;
|
|
212
|
+
}
|
|
213
|
+
export function parseMachineTreeIndented(text) {
|
|
214
|
+
const errors = [];
|
|
215
|
+
const jsonMatch = text.match(/```json\s*\n([\s\S]*?)```/);
|
|
216
|
+
if (jsonMatch) {
|
|
217
|
+
try {
|
|
218
|
+
const data = JSON.parse(jsonMatch[1].trim());
|
|
219
|
+
if (data && typeof data === "object" && Array.isArray(data.nodes) && Array.isArray(data.edges)) {
|
|
220
|
+
return { success: true, data, errors: [] };
|
|
221
|
+
}
|
|
222
|
+
if (Array.isArray(data)) {
|
|
223
|
+
const { nodes, edges } = convertNodeArrayToGraph(data);
|
|
224
|
+
return { success: true, data: { nodes, edges }, errors: [] };
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
catch (e) {
|
|
228
|
+
errors.push(`JSON code block parse error: ${e.message}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const topologyMatch = text.match(/##\s*Topology[^\n]*\n([\s\S]*?)(?=\n##\s|$)/i);
|
|
232
|
+
if (!topologyMatch) {
|
|
233
|
+
return {
|
|
234
|
+
success: false,
|
|
235
|
+
errors: [
|
|
236
|
+
"No '## Topology' section found. " +
|
|
237
|
+
"Use the format produced by renderMachineTreeIndented() or a JSON code block.",
|
|
238
|
+
],
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
const topologySection = topologyMatch[1];
|
|
242
|
+
const nodeNames = new Set();
|
|
243
|
+
const edges = [];
|
|
244
|
+
const edgeLines = topologySection.split("\n").filter(l => l.trim().startsWith("- "));
|
|
245
|
+
const pendingForwards = [];
|
|
246
|
+
let currentEdge = null;
|
|
247
|
+
for (const line of edgeLines) {
|
|
248
|
+
const trimmed = line.trim();
|
|
249
|
+
const isIndented = line.startsWith(" -");
|
|
250
|
+
if (isIndented) {
|
|
251
|
+
const fwdMatch = trimmed.match(/^-\s*forward:\s*(.+)$/);
|
|
252
|
+
if (fwdMatch && currentEdge) {
|
|
253
|
+
const fwd = parseForwardInline(fwdMatch[1]);
|
|
254
|
+
if (fwd) {
|
|
255
|
+
currentEdge.forwards.push(fwd);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
const edgeMatch = trimmed.match(/^-\s+(.+?)\s+-->\s+(\S+)(?:\s+\(threshold=(\d+)\))?(.*)$/);
|
|
261
|
+
if (edgeMatch) {
|
|
262
|
+
if (currentEdge) {
|
|
263
|
+
edges.push(currentEdge);
|
|
264
|
+
}
|
|
265
|
+
const fromRaw = edgeMatch[1].trim();
|
|
266
|
+
const to = edgeMatch[2].trim();
|
|
267
|
+
const threshold = edgeMatch[3] ? parseInt(edgeMatch[3], 10) : 1;
|
|
268
|
+
const from = fromRaw === "[*]" ? "" : fromRaw;
|
|
269
|
+
currentEdge = {
|
|
270
|
+
from,
|
|
271
|
+
to,
|
|
272
|
+
threshold,
|
|
273
|
+
forwards: [],
|
|
274
|
+
};
|
|
275
|
+
nodeNames.add(to);
|
|
276
|
+
if (from)
|
|
277
|
+
nodeNames.add(from);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
if (currentEdge) {
|
|
281
|
+
edges.push(currentEdge);
|
|
282
|
+
}
|
|
283
|
+
if (edges.length === 0) {
|
|
284
|
+
return {
|
|
285
|
+
success: false,
|
|
286
|
+
errors: ["No edges found in '## Topology' section. Expected lines like '- A --> B (threshold=1)'."],
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
const descMatch = text.match(/##\s*Node Descriptions[^\n]*\n([\s\S]*?)(?=\n##\s|$)/i);
|
|
290
|
+
const nodeDescMap = new Map();
|
|
291
|
+
if (descMatch) {
|
|
292
|
+
const descLines = descMatch[1].split("\n");
|
|
293
|
+
for (const line of descLines) {
|
|
294
|
+
const m = line.match(/^-\s+(\S+):\s*(.+)$/);
|
|
295
|
+
if (m) {
|
|
296
|
+
nodeDescMap.set(m[1], m[2]);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
const nodes = [];
|
|
301
|
+
for (const name of nodeNames) {
|
|
302
|
+
nodes.push({
|
|
303
|
+
name,
|
|
304
|
+
description: nodeDescMap.get(name) ?? null,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
return { success: true, data: { nodes, edges }, errors };
|
|
308
|
+
}
|
|
309
|
+
function parseForwardInline(text) {
|
|
310
|
+
const match = text.match(/^(\S+)\s*\(([^)]*)\)$/);
|
|
311
|
+
if (!match) {
|
|
312
|
+
return {
|
|
313
|
+
name: text.trim(),
|
|
314
|
+
weight: 1,
|
|
315
|
+
named_operator: null,
|
|
316
|
+
permission_index: null,
|
|
317
|
+
guard: null,
|
|
318
|
+
retained_submission: null,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
const name = match[1];
|
|
322
|
+
const annotationStr = match[2];
|
|
323
|
+
const fwd = {
|
|
324
|
+
name,
|
|
325
|
+
weight: 1,
|
|
326
|
+
named_operator: null,
|
|
327
|
+
permission_index: null,
|
|
328
|
+
guard: null,
|
|
329
|
+
retained_submission: null,
|
|
330
|
+
};
|
|
331
|
+
for (const part of annotationStr.split(",").map(s => s.trim())) {
|
|
332
|
+
if (!part)
|
|
333
|
+
continue;
|
|
334
|
+
const [key, ...valParts] = part.split("=");
|
|
335
|
+
const val = valParts.join("=").trim();
|
|
336
|
+
switch (key.trim()) {
|
|
337
|
+
case "weight":
|
|
338
|
+
fwd.weight = parseInt(val, 10) || 1;
|
|
339
|
+
break;
|
|
340
|
+
case "namedOperator":
|
|
341
|
+
fwd.named_operator = val.replace(/^'|'$/g, "");
|
|
342
|
+
break;
|
|
343
|
+
case "permissionIndex":
|
|
344
|
+
fwd.permission_index = parseInt(val, 10) || null;
|
|
345
|
+
break;
|
|
346
|
+
case "guard":
|
|
347
|
+
fwd.guard = val || null;
|
|
348
|
+
break;
|
|
349
|
+
case "retained_submission":
|
|
350
|
+
if (val.startsWith("[") && val.endsWith("]")) {
|
|
351
|
+
fwd.retained_submission = val
|
|
352
|
+
.slice(1, -1)
|
|
353
|
+
.split(",")
|
|
354
|
+
.map(s => parseInt(s.trim(), 10))
|
|
355
|
+
.filter(n => !isNaN(n));
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
fwd.retained_submission = val;
|
|
359
|
+
}
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return fwd;
|
|
364
|
+
}
|
|
365
|
+
function convertNodeArrayToGraph(data) {
|
|
366
|
+
const nodes = [];
|
|
367
|
+
const edges = [];
|
|
368
|
+
for (const item of data) {
|
|
369
|
+
if (!item || typeof item !== "object")
|
|
370
|
+
continue;
|
|
371
|
+
const node = item;
|
|
372
|
+
const name = typeof node.name === "string" ? node.name : "";
|
|
373
|
+
if (!name)
|
|
374
|
+
continue;
|
|
375
|
+
nodes.push({
|
|
376
|
+
name,
|
|
377
|
+
description: typeof node.description === "string" ? node.description : null,
|
|
378
|
+
});
|
|
379
|
+
const pairs = Array.isArray(node.pairs) ? node.pairs : [];
|
|
380
|
+
for (const pairRaw of pairs) {
|
|
381
|
+
if (!pairRaw || typeof pairRaw !== "object")
|
|
382
|
+
continue;
|
|
383
|
+
const pair = pairRaw;
|
|
384
|
+
const prevNode = typeof pair.prev_node === "string" ? pair.prev_node : "";
|
|
385
|
+
const threshold = typeof pair.threshold === "number" ? pair.threshold : 1;
|
|
386
|
+
const forwardsRaw = Array.isArray(pair.forwards) ? pair.forwards : [];
|
|
387
|
+
const forwards = forwardsRaw.map((f) => {
|
|
388
|
+
const fwd = f;
|
|
389
|
+
return {
|
|
390
|
+
name: typeof fwd.name === "string" ? fwd.name : "",
|
|
391
|
+
weight: typeof fwd.weight === "number" ? fwd.weight : 1,
|
|
392
|
+
named_operator: typeof fwd.namedOperator === "string" ? fwd.namedOperator : null,
|
|
393
|
+
permission_index: typeof fwd.permissionIndex === "number" ? fwd.permissionIndex : null,
|
|
394
|
+
guard: typeof fwd.guard === "string"
|
|
395
|
+
? fwd.guard
|
|
396
|
+
: (fwd.guard && typeof fwd.guard.guard === "string")
|
|
397
|
+
? fwd.guard.guard
|
|
398
|
+
: null,
|
|
399
|
+
retained_submission: null,
|
|
400
|
+
};
|
|
401
|
+
});
|
|
402
|
+
edges.push({
|
|
403
|
+
from: prevNode,
|
|
404
|
+
to: name,
|
|
405
|
+
threshold,
|
|
406
|
+
forwards,
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return { nodes, edges };
|
|
411
|
+
}
|
|
412
|
+
export function renderMachineAscii(input) {
|
|
413
|
+
const { nodes, edges, machineName, machineAddress, published, paused } = input;
|
|
414
|
+
const lines = [];
|
|
415
|
+
if (machineName) {
|
|
416
|
+
lines.push(`Machine: ${machineName}`);
|
|
417
|
+
}
|
|
418
|
+
if (machineAddress) {
|
|
419
|
+
lines.push(`Address: ${machineAddress}`);
|
|
420
|
+
}
|
|
421
|
+
if (published !== null && published !== undefined) {
|
|
422
|
+
lines.push(`Published: ${published}`);
|
|
423
|
+
}
|
|
424
|
+
if (paused !== null && paused !== undefined) {
|
|
425
|
+
lines.push(`Paused: ${paused}`);
|
|
426
|
+
}
|
|
427
|
+
if (machineName || machineAddress) {
|
|
428
|
+
lines.push("");
|
|
429
|
+
}
|
|
430
|
+
const outgoingMap = new Map();
|
|
431
|
+
for (const edge of edges) {
|
|
432
|
+
if (edge.from === "")
|
|
433
|
+
continue;
|
|
434
|
+
if (!outgoingMap.has(edge.from))
|
|
435
|
+
outgoingMap.set(edge.from, []);
|
|
436
|
+
outgoingMap.get(edge.from).push(edge);
|
|
437
|
+
}
|
|
438
|
+
const terminalNodes = new Set();
|
|
439
|
+
for (const node of nodes) {
|
|
440
|
+
const outEdges = outgoingMap.get(node.name) ?? [];
|
|
441
|
+
const hasOutgoingToNode = outEdges.some(e => e.to !== "");
|
|
442
|
+
if (!hasOutgoingToNode) {
|
|
443
|
+
const isTargeted = edges.some(e => e.to === node.name);
|
|
444
|
+
if (isTargeted) {
|
|
445
|
+
terminalNodes.add(node.name);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
const entryNodes = new Set();
|
|
450
|
+
for (const edge of edges) {
|
|
451
|
+
if (edge.from === "") {
|
|
452
|
+
entryNodes.add(edge.to);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
const revisionNodes = new Set();
|
|
456
|
+
for (const edge of edges) {
|
|
457
|
+
if (edge.from === edge.to && edge.from !== "") {
|
|
458
|
+
revisionNodes.add(edge.from);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
for (const edge of edges) {
|
|
462
|
+
const fromLabel = edge.from === "" ? "[*]" : edge.from;
|
|
463
|
+
const toLabel = edge.to === "" ? "[*]" : edge.to;
|
|
464
|
+
const isCycle = edge.from === edge.to && edge.from !== "";
|
|
465
|
+
for (const fwd of edge.forwards) {
|
|
466
|
+
const annotations = [];
|
|
467
|
+
if (isCycle)
|
|
468
|
+
annotations.push("cycle");
|
|
469
|
+
if (fwd.guard)
|
|
470
|
+
annotations.push(`guard=${fwd.guard}`);
|
|
471
|
+
if (fwd.named_operator !== null && fwd.named_operator !== undefined && fwd.named_operator !== "") {
|
|
472
|
+
annotations.push(`op=${fwd.named_operator}`);
|
|
473
|
+
}
|
|
474
|
+
if (fwd.permission_index !== null && fwd.permission_index !== undefined) {
|
|
475
|
+
annotations.push(`perm=${fwd.permission_index}`);
|
|
476
|
+
}
|
|
477
|
+
if (edge.threshold > 1)
|
|
478
|
+
annotations.push(`threshold=${edge.threshold}`);
|
|
479
|
+
const annotationStr = annotations.length > 0 ? ` [${annotations.join(", ")}]` : "";
|
|
480
|
+
const cycleStr = isCycle ? " ⟲" : "";
|
|
481
|
+
lines.push(`${fromLabel} ─${fwd.name}→ ${toLabel}${cycleStr}${annotationStr}`);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
const annotatedNodes = [];
|
|
485
|
+
for (const node of nodes) {
|
|
486
|
+
const annotations = [];
|
|
487
|
+
if (entryNodes.has(node.name))
|
|
488
|
+
annotations.push("entry");
|
|
489
|
+
if (terminalNodes.has(node.name))
|
|
490
|
+
annotations.push("terminal");
|
|
491
|
+
if (revisionNodes.has(node.name))
|
|
492
|
+
annotations.push("revision");
|
|
493
|
+
if (annotations.length > 0) {
|
|
494
|
+
annotatedNodes.push(` ${node.name}: ${annotations.join(", ")}`);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
if (annotatedNodes.length > 0) {
|
|
498
|
+
lines.push("");
|
|
499
|
+
lines.push("Node roles:");
|
|
500
|
+
lines.push(...annotatedNodes);
|
|
501
|
+
}
|
|
502
|
+
return lines.join("\n");
|
|
503
|
+
}
|
|
504
|
+
export function renderMachineMarkmap(input) {
|
|
505
|
+
const { nodes, edges, machineName, machineAddress, published, paused } = input;
|
|
506
|
+
const lines = [];
|
|
507
|
+
const titleParts = ["Machine"];
|
|
508
|
+
if (machineName)
|
|
509
|
+
titleParts.push(machineName);
|
|
510
|
+
lines.push(`# ${titleParts.join(": ")}`);
|
|
511
|
+
if (machineAddress || published !== null || paused !== null) {
|
|
512
|
+
lines.push("");
|
|
513
|
+
if (machineAddress)
|
|
514
|
+
lines.push(`**Address:** ${machineAddress}`);
|
|
515
|
+
if (published !== null && published !== undefined)
|
|
516
|
+
lines.push(`**Published:** ${published}`);
|
|
517
|
+
if (paused !== null && paused !== undefined)
|
|
518
|
+
lines.push(`**Paused:** ${paused}`);
|
|
519
|
+
}
|
|
520
|
+
lines.push("");
|
|
521
|
+
const outgoingMap = new Map();
|
|
522
|
+
for (const edge of edges) {
|
|
523
|
+
if (edge.from === "")
|
|
524
|
+
continue;
|
|
525
|
+
if (!outgoingMap.has(edge.from))
|
|
526
|
+
outgoingMap.set(edge.from, []);
|
|
527
|
+
outgoingMap.get(edge.from).push(edge);
|
|
528
|
+
}
|
|
529
|
+
const terminalNodes = new Set();
|
|
530
|
+
for (const node of nodes) {
|
|
531
|
+
const outEdges = outgoingMap.get(node.name) ?? [];
|
|
532
|
+
const hasOutgoingToNode = outEdges.some(e => e.to !== "");
|
|
533
|
+
if (!hasOutgoingToNode) {
|
|
534
|
+
const isTargeted = edges.some(e => e.to === node.name);
|
|
535
|
+
if (isTargeted)
|
|
536
|
+
terminalNodes.add(node.name);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
for (const edge of edges) {
|
|
540
|
+
const fromLabel = edge.from === "" ? "[*]" : edge.from;
|
|
541
|
+
const toLabel = edge.to === "" ? "[*]" : edge.to;
|
|
542
|
+
const isCycle = edge.from === edge.to && edge.from !== "";
|
|
543
|
+
const cycleStr = isCycle ? " (cycle)" : "";
|
|
544
|
+
const terminalStr = terminalNodes.has(edge.to) ? " (terminal)" : "";
|
|
545
|
+
lines.push(`## ${fromLabel} → ${toLabel}${cycleStr}${terminalStr}`);
|
|
546
|
+
for (const fwd of edge.forwards) {
|
|
547
|
+
const parts = [`weight=${fwd.weight}`];
|
|
548
|
+
if (fwd.named_operator !== null && fwd.named_operator !== undefined) {
|
|
549
|
+
parts.push(`namedOperator='${fwd.named_operator}'`);
|
|
550
|
+
}
|
|
551
|
+
if (fwd.permission_index !== null && fwd.permission_index !== undefined) {
|
|
552
|
+
parts.push(`permissionIndex=${fwd.permission_index}`);
|
|
553
|
+
}
|
|
554
|
+
if (fwd.guard) {
|
|
555
|
+
parts.push(`guard=${fwd.guard}`);
|
|
556
|
+
}
|
|
557
|
+
if (edge.threshold > 1) {
|
|
558
|
+
parts.push(`threshold=${edge.threshold}`);
|
|
559
|
+
}
|
|
560
|
+
lines.push(`### forward: ${fwd.name} (${parts.join(", ")})`);
|
|
561
|
+
}
|
|
562
|
+
lines.push("");
|
|
563
|
+
}
|
|
564
|
+
return lines.join("\n");
|
|
565
|
+
}
|
|
@@ -123,7 +123,10 @@ export const MACHINE_RISK_RULES = [
|
|
|
123
123
|
"dispute in the machine (e.g., 'disputed → refunded' forward guarded " +
|
|
124
124
|
"by Permission index 1500) create dead-end paths because no one has " +
|
|
125
125
|
"Permission 1500 — arbitrators are NOT Permission holders.",
|
|
126
|
-
detection: "Match node names against regex
|
|
126
|
+
detection: "Match node names against regex /(^|_)(disputed?|refund(?:ed)?|arbitration|arb)(_|$)/i " +
|
|
127
|
+
"(catches both exact names like 'refunded' and compound fund-flow terminals like " +
|
|
128
|
+
"'deposit_refunded'/'deposit_deducted'; business states like 'return_approved'/" +
|
|
129
|
+
"'damage_confirmed'/'cancelled'/'returned' do NOT match)",
|
|
127
130
|
recommendation: "Remove all dispute/refund nodes from the machine. Instead: (1) bind an " +
|
|
128
131
|
"Arbitration object to the Service via Service.arbitrations, (2) configure " +
|
|
129
132
|
"arbitrators via Arbitration.voting_guard_add, (3) deposit compensation_fund " +
|
|
@@ -1016,7 +1016,7 @@ export const MACHINE_TEMPLATES = [
|
|
|
1016
1016
|
type: "string",
|
|
1017
1017
|
required: true,
|
|
1018
1018
|
default: "wonder",
|
|
1019
|
-
description: "Node name for positive feedback (
|
|
1019
|
+
description: "Node name for positive feedback (praise) terminal",
|
|
1020
1020
|
constraint: "Must match /^(wonder|praise|thumbs_up)$/i OR be a custom name; must NOT match dispute anti-pattern regex",
|
|
1021
1021
|
},
|
|
1022
1022
|
{
|
|
@@ -1024,7 +1024,7 @@ export const MACHINE_TEMPLATES = [
|
|
|
1024
1024
|
type: "string",
|
|
1025
1025
|
required: true,
|
|
1026
1026
|
default: "no_wonder",
|
|
1027
|
-
description: "Node name for negative feedback (
|
|
1027
|
+
description: "Node name for negative feedback (complaint) terminal",
|
|
1028
1028
|
constraint: "Must match /^(no_wonder|complain|thumbs_down)$/i OR be a custom name; must NOT match dispute anti-pattern regex",
|
|
1029
1029
|
},
|
|
1030
1030
|
{
|
|
@@ -1047,8 +1047,8 @@ export const MACHINE_TEMPLATES = [
|
|
|
1047
1047
|
{ name: "Shipped", description: "Merchant dispatched goods/service" },
|
|
1048
1048
|
{ name: "Received", description: "Customer confirmed receipt" },
|
|
1049
1049
|
{ name: "Completed", description: "Terminal business state — triggers merchant Allocation. Funds settled." },
|
|
1050
|
-
{ name: "${wonder_node_name}", description: "Positive feedback terminal (
|
|
1051
|
-
{ name: "${no_wonder_node_name}", description: "Negative feedback terminal (
|
|
1050
|
+
{ name: "${wonder_node_name}", description: "Positive feedback terminal (praise). OrderHolder-only. Reward-eligible." },
|
|
1051
|
+
{ name: "${no_wonder_node_name}", description: "Negative feedback terminal (complaint). OrderHolder-only. Optional Repository write for analytics." },
|
|
1052
1052
|
],
|
|
1053
1053
|
example_pairs: [
|
|
1054
1054
|
{
|
|
@@ -336,7 +336,7 @@ export function buildPromptFromProgressContext(bundle) {
|
|
|
336
336
|
}
|
|
337
337
|
if (h.include_terminal_node_note) {
|
|
338
338
|
lines.push("─ Terminal Node Note ──────────────");
|
|
339
|
-
lines.push("At terminal nodes (completed/enforced/
|
|
339
|
+
lines.push("At terminal nodes (completed/enforced/return_approved/paid), use progress::owner_receive");
|
|
340
340
|
lines.push("to unwrap Receiving<K> / CoinWrapper<T> via Payment.unwrap_with_check.");
|
|
341
341
|
lines.push("Permission 225 (PROGRESS_OWNER_RECEIVE) required; recipient = Machine.permission owner.");
|
|
342
342
|
lines.push("");
|
|
@@ -177,7 +177,7 @@ export const PROGRESS_SCENES = [
|
|
|
177
177
|
industry: ["finance", "treasury", "rental", "freelance"],
|
|
178
178
|
scenario: "Owner receives Receiving<K> objects or CoinWrapper<T> coins sent to the Progress object. " +
|
|
179
179
|
"unwrap → permission::owner_receive_inner forwards to Permission owner. " +
|
|
180
|
-
"Used at terminal nodes (
|
|
180
|
+
"Used at terminal nodes (return_approved, completed, enforced) to disburse funds.",
|
|
181
181
|
phases: ["owner_receive"],
|
|
182
182
|
requires_published_machine: true,
|
|
183
183
|
requires_order_bound: true,
|
|
@@ -189,7 +189,7 @@ export const PROGRESS_SCENES = [
|
|
|
189
189
|
common_patterns: [
|
|
190
190
|
"owner_receive unwraps CoinWrapper<T> via Payment.unwrap_with_check (amount validation)",
|
|
191
191
|
"owner_receive_object receives a generic K:key+store object and forwards to Permission owner",
|
|
192
|
-
"Triggered at terminal nodes (e.g. '
|
|
192
|
+
"Triggered at terminal nodes (e.g. 'return_approved' in rental, 'enforced' in arbitration)",
|
|
193
193
|
"Permission owner ≠ Progress creator: receives flow to whoever owns the bound Machine's Permission",
|
|
194
194
|
],
|
|
195
195
|
recommended_templates: ["T-PR-06"],
|
|
@@ -326,5 +326,5 @@ export const PROGRESS_CROSS_OBJECT_REFS = [
|
|
|
326
326
|
{ object: "Passport", phase: "forward_advance", relationship: "Forward.guard (Some) requires Passport + passport::result_for_guard" },
|
|
327
327
|
{ object: "Passport", phase: "unhold_state", relationship: "unhold_with_passport: 224 check via passport (fallback when sender_has_permission_idcheck fails)" },
|
|
328
328
|
{ object: "Payment", phase: "owner_receive", relationship: "owner_receive unwraps CoinWrapper<T> via Payment.unwrap_with_check" },
|
|
329
|
-
{ object: "Allocation", phase: "completed", relationship: "Terminal node triggers Allocation alloc (e.g. 'completed', 'enforced', '
|
|
329
|
+
{ object: "Allocation", phase: "completed", relationship: "Terminal node triggers Allocation alloc (e.g. 'completed', 'enforced', 'return_approved')" },
|
|
330
330
|
];
|
|
@@ -184,7 +184,7 @@ export const PROGRESS_TEMPLATES = [
|
|
|
184
184
|
notes: [
|
|
185
185
|
"Permission 225 (PROGRESS_OWNER_RECEIVE) is required; SDK CallProgress_Data does NOT expose this op",
|
|
186
186
|
"Recipient is Permission owner (Machine.permission's owner), NOT Progress creator",
|
|
187
|
-
"Triggered at terminal nodes: '
|
|
187
|
+
"Triggered at terminal nodes: 'return_approved', 'completed', 'enforced', 'paid'",
|
|
188
188
|
"For coins: Payment.unwrap_with_check validates amount before forwarding to owner",
|
|
189
189
|
"For objects: generic K:key+store — forwarded directly via permission::owner_receive_inner",
|
|
190
190
|
],
|
|
@@ -128,7 +128,7 @@ export const PROGRESS_SEMANTIC_TO_SCHEMA_RULES = [
|
|
|
128
128
|
arguments: ["progress", "machine", "permission", "received", "payment"],
|
|
129
129
|
},
|
|
130
130
|
reverse_explanation: "Calls progress::owner_receive (225 permission). Unwraps CoinWrapper<T> via Payment.unwrap_with_check, " +
|
|
131
|
-
"forwards coin/object to Permission owner. Typically triggered at terminal nodes (
|
|
131
|
+
"forwards coin/object to Permission owner. Typically triggered at terminal nodes (return_approved, completed, enforced).",
|
|
132
132
|
},
|
|
133
133
|
];
|
|
134
134
|
export const PROGRESS_SCHEMA_TO_SEMANTIC_RULES = [
|
|
@@ -137,7 +137,7 @@ function runStaticChecklist(input) {
|
|
|
137
137
|
const cr11 = items.find(i => i.id === "C-R-11");
|
|
138
138
|
if (data.guard_expected_progress_state && input.user_intent_phrases && input.user_intent_phrases.length > 0) {
|
|
139
139
|
const intentLower = input.user_intent_phrases.join(" ").toLowerCase();
|
|
140
|
-
const praiseKeywords = ["
|
|
140
|
+
const praiseKeywords = ["praise", "wonder", "thumbs_up", "positive review", "satisfaction reward", "praise reward"];
|
|
141
141
|
const isPraiseIntent = praiseKeywords.some(kw => intentLower.includes(kw.toLowerCase()));
|
|
142
142
|
if (isPraiseIntent && input.machine_has_wonder_node !== false && data.guard_expected_progress_state !== "wonder") {
|
|
143
143
|
cr11.passed = false;
|
|
@@ -224,7 +224,7 @@ export const REWARD_CONFIRMATION_QUESTIONS = [
|
|
|
224
224
|
{
|
|
225
225
|
id: "QRW7",
|
|
226
226
|
question: "⚠️ For guard_add with progress.current check: does the Guard's expected progress node match the business intent? " +
|
|
227
|
-
"If intent is '
|
|
227
|
+
"If intent is 'praise/positive review', Guard must check 'wonder' (NOT 'completed'). " +
|
|
228
228
|
"Premature claim at wrong node drains reward pool — Guard is immutable after creation.",
|
|
229
229
|
requires_explicit_yes: true,
|
|
230
230
|
related_risk_ids: ["R-R-6-01", "R-R-6-02"],
|