@wowok/agent-mcp 2.5.4 → 2.6.0

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 (76) hide show
  1. package/README.md +33 -26
  2. package/dist/config/runtime.js +3 -6
  3. package/dist/harness/checkpoint.js +2 -2
  4. package/dist/knowledge/flywheel-loop.js +2 -5
  5. package/dist/knowledge/overrides-loader.js +2 -4
  6. package/dist/knowledge/progress-ledger.js +3 -0
  7. package/dist/knowledge/progress-translation.js +5 -1
  8. package/dist/knowledge/reward-confirm.d.ts +3 -0
  9. package/dist/knowledge/reward-confirm.js +30 -0
  10. package/dist/knowledge/reward-puzzle.d.ts +1 -0
  11. package/dist/knowledge/reward-puzzle.js +12 -0
  12. package/dist/knowledge/reward-risk.d.ts +4 -1
  13. package/dist/knowledge/reward-risk.js +85 -3
  14. package/dist/knowledge/tools-reference.js +5 -4
  15. package/dist/loop-engineering/improve.js +2 -4
  16. package/dist/project/deployment-bridge.d.ts +5 -0
  17. package/dist/project/deployment-bridge.js +96 -0
  18. package/dist/project/evaluation.d.ts +53 -0
  19. package/dist/project/evaluation.js +860 -0
  20. package/dist/project/graph-builder.d.ts +43 -0
  21. package/dist/project/graph-builder.js +585 -0
  22. package/dist/project/handlers.d.ts +154 -0
  23. package/dist/project/handlers.js +567 -0
  24. package/dist/project/index.d.ts +1 -0
  25. package/dist/project/index.js +26 -7
  26. package/dist/project/project-store.js +2 -5
  27. package/dist/project/query.d.ts +1 -0
  28. package/dist/project/query.js +2 -0
  29. package/dist/project/semantic-assembler.d.ts +93 -0
  30. package/dist/project/semantic-assembler.js +345 -0
  31. package/dist/schema/call/base.js +1 -1
  32. package/dist/schema/config/index.d.ts +12 -12
  33. package/dist/schema/local/index.d.ts +108 -108
  34. package/dist/schema/local/index.js +21 -18
  35. package/dist/schema/messenger/index.d.ts +16 -16
  36. package/dist/schema/messenger/index.js +2 -2
  37. package/dist/schema/operations.d.ts +0 -6
  38. package/dist/schema/project/index.d.ts +1840 -3903
  39. package/dist/schema/project/index.js +403 -955
  40. package/dist/schema/query/index.d.ts +10 -5
  41. package/dist/schema/trust/index.d.ts +6 -6
  42. package/dist/schemas/account_operation.output.json +7 -21
  43. package/dist/schemas/account_operation.schema.json +9 -23
  44. package/dist/schemas/bridge_operation.schema.json +1 -1
  45. package/dist/schemas/guard2file.schema.json +1 -1
  46. package/dist/schemas/index.json +2 -2
  47. package/dist/schemas/machineNode2file.schema.json +1 -1
  48. package/dist/schemas/messenger_operation.schema.json +6 -6
  49. package/dist/schemas/onchain_operations.schema.json +5 -5
  50. package/dist/schemas/onchain_operations_allocation.schema.json +1 -1
  51. package/dist/schemas/onchain_operations_arbitration.schema.json +1 -1
  52. package/dist/schemas/onchain_operations_contact.schema.json +1 -1
  53. package/dist/schemas/onchain_operations_demand.schema.json +1 -1
  54. package/dist/schemas/onchain_operations_gen_passport.schema.json +2 -2
  55. package/dist/schemas/onchain_operations_gen_proof.schema.json +2 -2
  56. package/dist/schemas/onchain_operations_guard.schema.json +1 -1
  57. package/dist/schemas/onchain_operations_machine.schema.json +1 -1
  58. package/dist/schemas/onchain_operations_order.schema.json +1 -1
  59. package/dist/schemas/onchain_operations_payment.schema.json +1 -1
  60. package/dist/schemas/onchain_operations_permission.schema.json +1 -1
  61. package/dist/schemas/onchain_operations_personal.schema.json +1 -1
  62. package/dist/schemas/onchain_operations_progress.schema.json +1 -1
  63. package/dist/schemas/onchain_operations_proof.schema.json +1 -1
  64. package/dist/schemas/onchain_operations_repository.schema.json +1 -1
  65. package/dist/schemas/onchain_operations_reward.schema.json +1 -1
  66. package/dist/schemas/onchain_operations_service.schema.json +1 -1
  67. package/dist/schemas/onchain_operations_treasury.schema.json +1 -1
  68. package/dist/schemas/project_operation.output.json +1178 -2494
  69. package/dist/schemas/project_operation.schema.json +216 -530
  70. package/dist/schemas/query_toolkit.output.json +7 -6
  71. package/dist/schemas/query_toolkit.schema.json +0 -4
  72. package/dist/telemetry/storage.js +2 -2
  73. package/dist/tools/handlers/onchain.js +110 -19
  74. package/dist/tools/handlers/project.js +56 -1046
  75. package/dist/tools/index.js +85 -56
  76. package/package.json +2 -2
package/README.md CHANGED
@@ -25,40 +25,47 @@ Docs: [https://github.com/wowok-ai/docs/](https://github.com/wowok-ai/docs/)
25
25
  }
26
26
  ```
27
27
 
28
- ### 2. Use WoWok Skills (Recommended)
28
+ ### 2. Install WoWok Skills (Recommended)
29
29
 
30
- **Skills significantly reduce the learning curve and usage difficulty of the MCP Server.**
30
+ **Skills significantly reduce the learning curve and usage difficulty of the MCP Server.** They provide structured guidance for AI assistants on complex system building, tool usage, and safety protocols.
31
31
 
32
32
  ```bash
33
+ # Personal (global) — available in all sessions:
33
34
  npm install -g @wowok/skills
35
+
36
+ # Project (team sharing) — commit to git for collaboration:
37
+ cd your-project
38
+ wowok-skills init # Claude Code (default)
39
+ wowok-skills init --target agents # Trae IDE
40
+ wowok-skills init --target all # All 6 supported clients
34
41
  ```
35
42
 
36
- Skills provide structured guidance for AI assistants:
43
+ **Supported clients:** Claude Code, OpenAI Codex, Trae IDE, CodeBuddy, Cursor, GitHub Copilot.
44
+
45
+ #### Available Skills
46
+
47
+ **Always loaded** (3 skills — foundational layer):
37
48
 
38
- - **Complex system building** — Dependency chains, build order, step-by-step patterns
39
- - **Tool usage failures** — Correct parameter formats, tool selection, error recovery
40
- - **Safety & authorization** — User confirmation for important operations
49
+ | Skill | Purpose |
50
+ |-------|---------|
51
+ | `wowok-tools` | MCP tool reference — 17 sub-tools, schema-gated execution, constraints |
52
+ | `wowok-safety` | Safety protocol — dry-run → confirm → execute, immutability rules |
53
+ | `wowok-output` | Output processing — address resolution, name mapping, data visualization |
41
54
 
42
- #### Available Skills (Organized by Role)
55
+ **On-demand** (11 skills — loaded by context):
43
56
 
44
57
  | Skill | Role | Purpose |
45
58
  |-------|------|---------|
46
- | `wowok-order` | 👤 Customer | Order lifecycle — place orders, track progress, submit disputes, claim compensation |
47
- | `wowok-provider` | 🏪 Provider | Service provider guide — create Service, design Machine, configure Allocators |
48
- | `wowok-machine` | 🏪 Provider | Workflow design — state machines, node definitions, progress tracking |
49
- | `wowok-arbitrator` | ⚖️ Arbitrator | Arbitration service — dispute resolution, voting organization, fee management |
50
- | `wowok-guard` | 🛠️ Shared | Guard design mastery — programmable trust rules, multi-signature authorization |
51
- | `wowok-messenger` | 🛠️ Shared | Encrypted messaging — E2E communication, WTS evidence, conversation management |
52
- | `wowok-output` | 🛠️ Shared | Output processing — post-process responses for human-readable presentation |
53
- | `wowok-tools` | 🛠️ Shared | MCP tool usage mastery — 13+ tools, parameter formats, schema references |
54
- | `wowok-safety` | 🛠️ Shared | Safety protocol — dry-run validation, user confirmation checkpoints |
55
-
56
- #### Role-Based Skill Selection
57
-
58
- - **Use `wowok-order`** when user acts as a customer/buyer placing orders
59
- - **Use `wowok-provider`** + `wowok-machine` when user is a merchant/service provider
60
- - **Use `wowok-arbitrator`** when user operates dispute resolution services
61
- - **Use `wowok-tools`** + `wowok-safety`** + `wowok-output` (always loaded) for all roles
62
- - **Use `wowok-guard`** when designing complex validation rules
63
-
64
- > **Note:** For detailed installation instructions for different AI clients (Claude Code, OpenAI Codex, Trae IDE, Cursor, etc.), see the [WoWok Skills](https://github.com/wowok-ai/skills) repository.
59
+ | `wowok-provider` | 🏪 Provider | Service provider guide — create Service, Machine, Allocators, order fulfillment |
60
+ | `wowok-machine` | 🏪 Provider | Workflow design — state machines, node/pair/forward graph, publish lifecycle |
61
+ | `wowok-order` | 👤 Customer | Order lifecycle — due diligence, consensus, order creation, progress, arbitration |
62
+ | `wowok-arbitrator` | ⚖️ Arbitrator | Arbitration service — dispute resolution, weighted voting, fee management |
63
+ | `wowok-guard` | 🛠️ Shared | Guard design — programmable trust rules, 4 data sources, 33 constraints |
64
+ | `wowok-messenger` | 🛠️ Shared | Encrypted messaging — E2E communication, WTS evidence, anti-spam |
65
+ | `wowok-onboard` | 🆕 New User | First-touch onboarding — 10-round dialogue from zero to first published Service |
66
+ | `wowok-scenario` | 🛠️ Shared | Industry mode templates — freelance, rental, education, travel presets |
67
+ | `wowok-planner` | 🛠️ Shared | Planning — converts natural language intent into Object Dependency Graph (ODG) |
68
+ | `wowok-auditor` | 🛠️ Shared | Pre-publish audit — Guard completeness, Machine soundness, 32 audit checks |
69
+ | `wowok-distill` | 🏪 Provider | Distillation review — review AI-generated improvement proposals |
70
+
71
+ > **Tip:** `wowok-tools` + `wowok-safety` + `wowok-output` are always loaded and serve all roles. Add role-specific skills (`wowok-provider`, `wowok-order`, `wowok-arbitrator`) as needed.
@@ -1,6 +1,6 @@
1
1
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
2
2
  import { dirname, join } from "path";
3
- import { homedir } from "os";
3
+ import { getWowMcpDir } from "@wowok/wowok";
4
4
  export const SERVICE_REGISTRY = [
5
5
  {
6
6
  name: "confirm_gate",
@@ -70,10 +70,7 @@ const SERVICE_MAP = new Map(SERVICE_REGISTRY.map((s) => [s.name, s]));
70
70
  const runtimeOverrides = new Map();
71
71
  let harnessTierOverride;
72
72
  function configFilePath() {
73
- const dir = process.env.WOWOK_CONFIG_DIR
74
- ? process.env.WOWOK_CONFIG_DIR
75
- : join(homedir(), ".wowok");
76
- return join(dir, "runtime-config.json");
73
+ return join(getWowMcpDir(), "runtime-config.json");
77
74
  }
78
75
  function isPersistEnabled() {
79
76
  const v = process.env.WOWOK_RUNTIME_CONFIG_PERSIST;
@@ -220,7 +217,7 @@ function buildReminder(service, enabled) {
220
217
  : "Harness is OFF. GLM5 recommends keeping it ON (lightweight tier) for safety. To enable, call config_operation toggle harness.";
221
218
  case "graph_persist":
222
219
  return enabled
223
- ? "Graph persistence is ON: the object dependency graph will be saved to ~/.wowok/project-graph.json."
220
+ ? "Graph persistence is ON: the object dependency graph will be saved to ~/.wow/mcp/project-graph.json."
224
221
  : "Graph persistence is OFF: the dependency graph exists only in memory and will be lost on process restart. To persist, call config_operation toggle graph_persist.";
225
222
  case "semantic_rich":
226
223
  return undefined;
@@ -1,7 +1,7 @@
1
1
  import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync, unlinkSync, openSync, closeSync } from "fs";
2
2
  import { join } from "path";
3
- import { homedir } from "os";
4
- const CHECKPOINT_ROOT = join(homedir(), ".wowok", "checkpoints");
3
+ import { getWowMcpDir } from "@wowok/wowok";
4
+ const CHECKPOINT_ROOT = join(getWowMcpDir(), "checkpoints");
5
5
  function getTaskDir(taskId) {
6
6
  return join(CHECKPOINT_ROOT, taskId);
7
7
  }
@@ -3,7 +3,7 @@ import { getIndustryProfile, resolveIndustryName } from "./industry-registry.js"
3
3
  import { evaluateIndustryHealthByIntent, suggestIndustryUpdateByIntent, getRoleAdvice, filterSuggestionsByRole, getIntentProfile, } from "./intent-metrics.js";
4
4
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
5
5
  import { dirname, join } from "path";
6
- import { homedir } from "os";
6
+ import { getWowMcpDir } from "@wowok/wowok";
7
7
  export const FLYWHEEL_LOOP_VERSION = 2;
8
8
  const MIN_SIGNALS_FOR_EVOLUTION = 10;
9
9
  const DEFAULT_SCHEDULE = {
@@ -287,10 +287,7 @@ export function getIndustryEvolutionStatus(industry) {
287
287
  }
288
288
  export const EVOLUTION_STATE_VERSION = 1;
289
289
  function evolutionStateFilePath() {
290
- const dir = process.env.WOWOK_CONFIG_DIR
291
- ? process.env.WOWOK_CONFIG_DIR
292
- : join(homedir(), ".wowok");
293
- return join(dir, "evolution-state.json");
290
+ return join(getWowMcpDir(), "evolution-state.json");
294
291
  }
295
292
  export function saveEvolutionState() {
296
293
  const path = evolutionStateFilePath();
@@ -1,10 +1,8 @@
1
1
  import { readFileSync, existsSync, readdirSync } from "fs";
2
2
  import { join } from "path";
3
- import { homedir } from "os";
3
+ import { getWowMcpDir } from "@wowok/wowok";
4
4
  function wowokRootDir() {
5
- return process.env.WOWOK_CONFIG_DIR
6
- ? process.env.WOWOK_CONFIG_DIR
7
- : join(homedir(), ".wowok");
5
+ return getWowMcpDir();
8
6
  }
9
7
  function overridesDir() {
10
8
  return join(wowokRootDir(), "overrides");
@@ -219,6 +219,9 @@ export const PROGRESS_SCENES = [
219
219
  "Progress.current = next_node only after session completes (atomic update)",
220
220
  "E_NOT_THE_HOLDER: if forward was held by another address, next() aborts",
221
221
  "E_FORWARD_ALREADY_ACCOMPLISHED: re-hold on completed forward is blocked",
222
+ "⚠ ROUTING RULE: Forward.namedOperator=\"\" (empty) → MUST call order.progress (order_next); " +
223
+ "non-empty namedOperator or permissionIndex-only → MUST call progress.operate (next). " +
224
+ "Wrong path → Permission denied (abort code 5). See file header CRITICAL ROUTING RULE.",
222
225
  ],
223
226
  recommended_templates: ["T-PR-04"],
224
227
  },
@@ -15,7 +15,11 @@ export const PROGRESS_SEMANTIC_TO_SCHEMA_RULES = [
15
15
  },
16
16
  },
17
17
  reverse_explanation: "operate.op='next' → calls progress::next or order_next (if task bound). " +
18
- "Move accumulates forward.weight; on reaching threshold, session → history and current = next_node_name.",
18
+ "Move accumulates forward.weight; on reaching threshold, session → history and current = next_node_name. " +
19
+ "⚠ ROUTING RULE: When Forward.namedOperator=\"\" (empty string = OrderHolder), the caller MUST use " +
20
+ "order.progress (not progress.operate) — order_next uses order.has_op_permission which recognizes " +
21
+ "the OrderHolder short-circuit. Direct progress::next will abort with 'Permission denied' (code 5). " +
22
+ "For non-empty namedOperator or permissionIndex-only forwards, use progress.operate directly.",
19
23
  },
20
24
  {
21
25
  id: "P-PR-02",
@@ -81,6 +81,7 @@ export interface RewardJsonForConfirm {
81
81
  guard_expiration_time?: number | null;
82
82
  owner_receive?: unknown;
83
83
  um?: string | null;
84
+ guard_expected_progress_state?: string;
84
85
  }
85
86
  export interface RewardConfirmGateInput {
86
87
  reward_json: RewardJsonForConfirm;
@@ -97,6 +98,8 @@ export interface RewardConfirmGateInput {
97
98
  passport_submission_value_types?: Record<number, string>;
98
99
  passport_identifier_is_address?: Record<number, boolean>;
99
100
  guard_store_from_id_compatible?: Record<string, boolean>;
101
+ user_intent_phrases?: string[];
102
+ machine_has_wonder_node?: boolean;
100
103
  skip_user_confirmation?: boolean;
101
104
  skip_environment_check?: boolean;
102
105
  }
@@ -11,6 +11,7 @@ export const REWARD_OPERATION_CHECKLIST = [
11
11
  { id: "C-R-08", description: "claim: Passport is provided (SDK W_ERROR if missing)", passed: false, message: "" },
12
12
  { id: "C-R-09", description: "owner_receive (156): user double-confirms blast radius", passed: false, message: "" },
13
13
  { id: "C-R-10", description: "guard_expiration_time_add (155): new time > current clock", passed: false, message: "" },
14
+ { id: "C-R-11", description: "guard_add: Guard's progress.current expected value matches business intent (praise→wonder, completion→completed)", passed: false, message: "" },
14
15
  ];
15
16
  function runStaticChecklist(input) {
16
17
  const items = REWARD_OPERATION_CHECKLIST.map(c => ({ ...c }));
@@ -133,6 +134,22 @@ function runStaticChecklist(input) {
133
134
  else {
134
135
  cr10.passed = true;
135
136
  }
137
+ const cr11 = items.find(i => i.id === "C-R-11");
138
+ if (data.guard_expected_progress_state && input.user_intent_phrases && input.user_intent_phrases.length > 0) {
139
+ const intentLower = input.user_intent_phrases.join(" ").toLowerCase();
140
+ const praiseKeywords = ["好评", "praise", "wonder", "thumbs_up", "positive review", "satisfaction reward", "好评奖励"];
141
+ const isPraiseIntent = praiseKeywords.some(kw => intentLower.includes(kw.toLowerCase()));
142
+ if (isPraiseIntent && input.machine_has_wonder_node !== false && data.guard_expected_progress_state !== "wonder") {
143
+ cr11.passed = false;
144
+ cr11.message = `intent=praise but Guard checks "${data.guard_expected_progress_state}" instead of "wonder" — R-R-6-01 violation`;
145
+ }
146
+ else {
147
+ cr11.passed = true;
148
+ }
149
+ }
150
+ else {
151
+ cr11.passed = true;
152
+ }
136
153
  return {
137
154
  all_passed: items.filter(i => i.id !== "C-R-09").every(i => i.passed),
138
155
  items,
@@ -162,6 +179,9 @@ function adaptRiskAssessment(input) {
162
179
  passport_submission_value_types: input.passport_submission_value_types,
163
180
  passport_identifier_is_address: input.passport_identifier_is_address,
164
181
  guard_store_from_id_compatible: input.guard_store_from_id_compatible,
182
+ user_intent_phrases: input.user_intent_phrases,
183
+ guard_expected_progress_state: input.reward_json.guard_expected_progress_state,
184
+ machine_has_wonder_node: input.machine_has_wonder_node,
165
185
  };
166
186
  return assessRewardRisks(ctx);
167
187
  }
@@ -201,6 +221,14 @@ export const REWARD_CONFIRMATION_QUESTIONS = [
201
221
  requires_explicit_yes: false,
202
222
  related_risk_ids: ["R-R-5-02"],
203
223
  },
224
+ {
225
+ id: "QRW7",
226
+ question: "⚠️ For guard_add with progress.current check: does the Guard's expected progress node match the business intent? " +
227
+ "If intent is '好评/praise', Guard must check 'wonder' (NOT 'completed'). " +
228
+ "Premature claim at wrong node drains reward pool — Guard is immutable after creation.",
229
+ requires_explicit_yes: true,
230
+ related_risk_ids: ["R-R-6-01", "R-R-6-02"],
231
+ },
204
232
  ];
205
233
  function processUserConfirmation(input, assessment) {
206
234
  const questions = [...REWARD_CONFIRMATION_QUESTIONS];
@@ -217,6 +245,8 @@ function processUserConfirmation(input, assessment) {
217
245
  continue;
218
246
  if (q.id === "QRW6" && !data.coin_add)
219
247
  continue;
248
+ if (q.id === "QRW7" && (!data.guard_add || !data.guard_expected_progress_state))
249
+ continue;
220
250
  filtered.push(q);
221
251
  }
222
252
  if (input.skip_user_confirmation) {
@@ -48,6 +48,7 @@ export interface RewardConstraintChecklist {
48
48
  F_R_06_recipient_amount_valid_pairing: boolean;
49
49
  F_R_07_coin_type_matches_reward_t: boolean;
50
50
  F_R_08_passport_required_for_claim: boolean;
51
+ F_R_09_progress_node_matches_intent: boolean;
51
52
  }
52
53
  export type RewardPuzzleDimension = "A" | "B" | "C" | "D" | "E" | "F";
53
54
  export interface RewardPuzzle {
@@ -29,6 +29,7 @@ export function initPuzzleFromIntent(intent) {
29
29
  F_R_06_recipient_amount_valid_pairing: false,
30
30
  F_R_07_coin_type_matches_reward_t: false,
31
31
  F_R_08_passport_required_for_claim: false,
32
+ F_R_09_progress_node_matches_intent: true,
32
33
  };
33
34
  return puzzle;
34
35
  }
@@ -177,6 +178,17 @@ export function validateConstraints(puzzle) {
177
178
  message: "claim requires Passport — SDK W_ERROR if missing",
178
179
  });
179
180
  }
181
+ if (puzzle.guard && puzzle.intent && puzzle.constraints) {
182
+ if (!puzzle.constraints.F_R_09_progress_node_matches_intent) {
183
+ violations.push({
184
+ constraint_id: "F-R-09",
185
+ severity: "HIGH",
186
+ message: "Guard's expected progress.current value does not match business intent — " +
187
+ "praise reward (好评/wonder) must check 'wonder' node, not 'completed'. " +
188
+ "Guard is immutable after creation; mismatch requires full rebuild.",
189
+ });
190
+ }
191
+ }
180
192
  return violations;
181
193
  }
182
194
  export function generateConfirmationText(puzzle) {
@@ -1,6 +1,6 @@
1
1
  import { type RewardScene, type RewardAmountType } from "./reward-ledger.js";
2
2
  export type RewardRiskLevel = "CRITICAL" | "HIGH" | "MEDIUM" | "LOW";
3
- export type RewardRiskCategory = "structural" | "semantic" | "permission" | "lifecycle" | "cross_object";
3
+ export type RewardRiskCategory = "structural" | "semantic" | "permission" | "lifecycle" | "cross_object" | "business_semantic";
4
4
  export interface RewardRisk {
5
5
  id: string;
6
6
  level: RewardRiskLevel;
@@ -65,6 +65,9 @@ export interface RewardRiskCheckContext {
65
65
  passport_submission_value_types?: Record<number, string>;
66
66
  passport_identifier_is_address?: Record<number, boolean>;
67
67
  guard_store_from_id_compatible?: Record<string, boolean>;
68
+ user_intent_phrases?: string[];
69
+ guard_expected_progress_state?: string;
70
+ machine_has_wonder_node?: boolean;
68
71
  }
69
72
  export declare const REWARD_RISK_VERSION = "1.0.0";
70
73
  export declare function getAllRewardRiskRules(): RewardRiskRule[];
@@ -469,12 +469,94 @@ const R_R_5_03 = {
469
469
  return null;
470
470
  },
471
471
  };
472
+ const R_R_6_01 = {
473
+ id: "R-R-6-01",
474
+ category: "business_semantic",
475
+ trigger: "intent mentions praise/好评 but Guard checks non-wonder progress node",
476
+ check: (ctx) => {
477
+ if (!ctx.user_intent_phrases || ctx.user_intent_phrases.length === 0)
478
+ return null;
479
+ if (!ctx.guard_expected_progress_state)
480
+ return null;
481
+ const intentLower = ctx.user_intent_phrases.join(" ").toLowerCase();
482
+ const praiseKeywords = [
483
+ "好评", "praise", "wonder", "thumbs_up",
484
+ "positive review", "satisfaction reward", "好评奖励",
485
+ ];
486
+ const isPraiseIntent = praiseKeywords.some(kw => intentLower.includes(kw.toLowerCase()));
487
+ if (!isPraiseIntent)
488
+ return null;
489
+ if (ctx.machine_has_wonder_node === false)
490
+ return null;
491
+ const expected = ctx.guard_expected_progress_state;
492
+ if (expected !== "wonder") {
493
+ return {
494
+ id: "R-R-6-01",
495
+ level: "HIGH",
496
+ category: "business_semantic",
497
+ title: `Guard checks progress=="${expected}" but intent indicates praise reward (wonder node)`,
498
+ description: `User intent mentions praise/好评/wonder, which maps to the 'wonder' progress node ` +
499
+ `(customer gives positive review AFTER service completion). But the Guard's table bakes ` +
500
+ `expected state="${expected}", allowing reward claim at the wrong lifecycle stage. ` +
501
+ `This violates the business semantics: "好评奖励" should only be claimable AFTER the ` +
502
+ `customer advances to the 'wonder' node, not before. ` +
503
+ `Guard is immutable — fixing this requires creating a new Guard + Reward pair.`,
504
+ affected_stakeholders: ["owner", "service_provider", "claimer"],
505
+ scenario: "Designer builds Guard checking 'completed' instead of 'wonder' for a praise reward",
506
+ mitigation: "Set the Guard table's expected progress state to 'wonder' (the positive-review node). " +
507
+ "The correct pattern: ordered → in_service → completed → wonder (praise) triggers reward claim. " +
508
+ "Reference: reward-templates.ts wonder_praise template.",
509
+ evidence: `intent="${intentLower}", expected_state="${expected}", expected_wonder=true`,
510
+ auto_fixable: false,
511
+ };
512
+ }
513
+ return null;
514
+ },
515
+ };
516
+ const R_R_6_02 = {
517
+ id: "R-R-6-02",
518
+ category: "business_semantic",
519
+ trigger: "Guard checks wonder node but intent does not mention praise",
520
+ check: (ctx) => {
521
+ if (!ctx.user_intent_phrases || ctx.user_intent_phrases.length === 0)
522
+ return null;
523
+ if (!ctx.guard_expected_progress_state)
524
+ return null;
525
+ if (ctx.guard_expected_progress_state !== "wonder")
526
+ return null;
527
+ const intentLower = ctx.user_intent_phrases.join(" ").toLowerCase();
528
+ const praiseKeywords = [
529
+ "好评", "praise", "wonder", "thumbs_up",
530
+ "positive review", "satisfaction reward", "好评奖励",
531
+ ];
532
+ const isPraiseIntent = praiseKeywords.some(kw => intentLower.includes(kw.toLowerCase()));
533
+ if (isPraiseIntent)
534
+ return null;
535
+ return {
536
+ id: "R-R-6-02",
537
+ level: "MEDIUM",
538
+ category: "business_semantic",
539
+ title: "Guard checks wonder node but intent does not mention praise",
540
+ description: `Guard's expected progress state is "wonder" (positive-review node), but the user intent ` +
541
+ `does not mention any praise/好评 keyword. This may be a copy-paste from a wonder_praise ` +
542
+ `template without adjusting the Guard for the actual business semantics. If this is a ` +
543
+ `general feedback reward (wonder_feedback), this is fine. Otherwise, verify the node choice.`,
544
+ affected_stakeholders: ["owner"],
545
+ scenario: "Designer copies wonder_praise template but actually wants a completion-based reward",
546
+ mitigation: "Verify: if intent is praise reward, add '好评/praise' to description. " +
547
+ "If intent is completion-based reward, change Guard to check 'completed' node.",
548
+ evidence: `expected_state="wonder", intent="${intentLower}" (no praise keyword)`,
549
+ auto_fixable: false,
550
+ };
551
+ },
552
+ };
472
553
  const ALL_RULES = [
473
554
  R_R_1_01, R_R_1_02, R_R_1_03,
474
555
  R_R_2_01, R_R_2_02, R_R_2_03, R_R_2_04,
475
556
  R_R_3_01, R_R_3_02, R_R_3_03,
476
557
  R_R_4_01, R_R_4_02, R_R_4_03, R_R_4_04,
477
558
  R_R_5_01, R_R_5_02, R_R_5_03,
559
+ R_R_6_01, R_R_6_02,
478
560
  ];
479
561
  export const REWARD_RISK_VERSION = "1.0.0";
480
562
  export function getAllRewardRiskRules() {
@@ -529,13 +611,13 @@ export const REWARD_STAKEHOLDERS = [
529
611
  export function getRewardRiskRulesByStakeholder(stakeholder) {
530
612
  return ALL_RULES.filter(rule => {
531
613
  if (stakeholder === "owner") {
532
- return ["structural", "permission", "lifecycle"].includes(rule.category);
614
+ return ["structural", "permission", "lifecycle", "business_semantic"].includes(rule.category);
533
615
  }
534
616
  if (stakeholder === "claimer") {
535
- return rule.id.startsWith("R-R-4-0") || rule.id === "R-R-5-01" || rule.id === "R-R-1-02";
617
+ return rule.id.startsWith("R-R-4-0") || rule.id === "R-R-5-01" || rule.id === "R-R-1-02" || rule.id === "R-R-6-01";
536
618
  }
537
619
  if (stakeholder === "service_provider") {
538
- return rule.id === "R-R-4-02" || rule.id === "R-R-3-01" || rule.id === "R-R-3-02";
620
+ return rule.id === "R-R-4-02" || rule.id === "R-R-3-01" || rule.id === "R-R-3-02" || rule.id === "R-R-6-01";
539
621
  }
540
622
  if (stakeholder === "system") {
541
623
  return rule.category === "cross_object";
@@ -105,11 +105,12 @@ export const TOOLS_REFERENCE = [
105
105
  },
106
106
  {
107
107
  name: "project_operation",
108
- summary: "Project namespace + object dependency graph (DAG) + GLM5 C1-C4 composite actions.",
109
- actions: ["list_projects", "list_objects", "shareable", "dependencies", "referenced_by", "pre_publish_check", "cross_project_refs", "graph_stats", "save_graph", "load_graph", "analyze_intent", "aggregate_risks", "generate_deployment_doc", "trace_substeps"],
108
+ summary: "Project entity management (SQLite) + 3-pathway graph construction + dual rule-based/LLM-assisted evaluation engine.",
109
+ actions: ["list_projects", "create_project", "create_project_from_onchain", "update_project", "get_project_detail", "add_object", "remove_object", "create_version", "build_graph", "get_graph", "evaluate_project", "save_evaluation", "compare_projects", "refresh_objects", "get_object_diff", "assemble_context"],
110
110
  notes: [
111
- "GLM5: C1-C4 actions drive the 5-stage project-based deployment flow.",
112
- "Non-blocking: only CRITICAL risks block; HIGH/MEDIUM/LOW are advisory.",
111
+ "GLM6: Projects are first-class entities with SQLite persistence, rigid project-object relationships.",
112
+ "Evaluation: risk/trust/completeness are rule-based (computed locally). value/worth_buying require LLM assistance (returns a prompt).",
113
+ "Graph: 3 pathways — internal references (configurable depth), Registrar inbound (O(1)), potential relationships.",
113
114
  ],
114
115
  },
115
116
  {
@@ -1,7 +1,7 @@
1
1
  import { getPendingSuggestions } from "../knowledge/flywheel-loop.js";
2
2
  import { readFileSync, writeFileSync, existsSync, mkdirSync, appendFileSync, readdirSync } from "fs";
3
3
  import { join, dirname } from "path";
4
- import { homedir } from "os";
4
+ import { getWowMcpDir } from "@wowok/wowok";
5
5
  function proposeErrorRuleAddition(diagnosis) {
6
6
  const evidence = diagnosis.evidence;
7
7
  const topMessages = evidence.top_error_messages || [];
@@ -245,9 +245,7 @@ export function generateImprovements(report) {
245
245
  };
246
246
  }
247
247
  function wowokRootDir() {
248
- return process.env.WOWOK_CONFIG_DIR
249
- ? process.env.WOWOK_CONFIG_DIR
250
- : join(homedir(), ".wowok");
248
+ return getWowMcpDir();
251
249
  }
252
250
  function improvementQueuePath() {
253
251
  return join(wowokRootDir(), "improvement-queue.jsonl");
@@ -0,0 +1,5 @@
1
+ import type { DeploymentDocValidationResult } from "./deployment-doc.js";
2
+ export declare function generateDeploymentDocFromProject(projectId: string, network: "testnet" | "mainnet"): Promise<{
3
+ markdown: string;
4
+ validation: DeploymentDocValidationResult;
5
+ }>;
@@ -0,0 +1,96 @@
1
+ import { LocalProject } from "@wowok/wowok";
2
+ import { generateDeploymentDoc, validateDeploymentDoc } from "./deployment-doc.js";
3
+ export async function generateDeploymentDocFromProject(projectId, network) {
4
+ const project = await LocalProject.Instance().getProject(projectId);
5
+ if (!project) {
6
+ throw new Error(`Project not found: ${projectId}`);
7
+ }
8
+ const objects = await LocalProject.Instance().listObjects(projectId);
9
+ const graphEdges = await LocalProject.Instance().getGraph(projectId);
10
+ const evaluations = await LocalProject.Instance().listEvaluations(projectId, { evalType: "risk" });
11
+ const validObjects = objects.filter((o) => o.objectType !== null && o.objectType !== undefined);
12
+ const deployObjects = validObjects.map((o) => {
13
+ const objectType = o.objectType;
14
+ return {
15
+ entry_id: `${objectType}:${o.objectName || o.objectAddress || o.id}`,
16
+ object_type: normalizeObjectType(objectType),
17
+ name: o.objectName || o.objectAddress || o.id,
18
+ reused_from: o.objectAddress.startsWith("0x") ? o.objectAddress : undefined,
19
+ publish_required: objectType === "service" || objectType === "machine",
20
+ };
21
+ });
22
+ const addrToEntryId = new Map();
23
+ for (const o of validObjects) {
24
+ const objectType = o.objectType;
25
+ const entryId = `${objectType}:${o.objectName || o.objectAddress || o.id}`;
26
+ if (o.objectAddress) {
27
+ addrToEntryId.set(o.objectAddress, entryId);
28
+ }
29
+ if (o.objectName) {
30
+ addrToEntryId.set(o.objectName, entryId);
31
+ }
32
+ }
33
+ const deployEdges = graphEdges.map((e) => ({
34
+ from: addrToEntryId.get(e.sourceObject) ?? e.sourceObject,
35
+ to: addrToEntryId.get(e.targetObject) ?? e.targetObject,
36
+ edge_kind: e.relationshipType,
37
+ field_path: e.fieldName || "",
38
+ required_at_publish: e.edgeSource === "internal",
39
+ }));
40
+ const steps = buildTopoSteps(deployObjects, deployEdges, network);
41
+ const riskEval = evaluations[0];
42
+ const risk_status = riskEval
43
+ ? (riskEval.score !== null && riskEval.score < 50 ? "RISK_BLOCKED" : "RISK_PASSED")
44
+ : undefined;
45
+ const riskDetails = riskEval?.details;
46
+ const risk_critical_count = riskDetails?.critical_count;
47
+ const risk_high_count = riskDetails?.high_count;
48
+ const input = {
49
+ project_prefix: project.prefix,
50
+ business_intent: project.description || project.name,
51
+ industry: project.industry || "general",
52
+ version: project.currentVersion || "v1",
53
+ objects: deployObjects,
54
+ edges: deployEdges,
55
+ steps,
56
+ risk_status,
57
+ risk_critical_count,
58
+ risk_high_count,
59
+ };
60
+ const markdown = generateDeploymentDoc(input);
61
+ const validation = validateDeploymentDoc(input);
62
+ return { markdown, validation };
63
+ }
64
+ function normalizeObjectType(raw) {
65
+ const lower = raw.toLowerCase();
66
+ if (lower === "arbitration")
67
+ return "arb";
68
+ return lower;
69
+ }
70
+ function buildTopoSteps(objects, edges, network) {
71
+ const typeOrder = {
72
+ permission: 1, treasury: 2, allocation: 3, guard: 4,
73
+ service: 10, machine: 11, progress: 12,
74
+ order: 20, arb: 22,
75
+ reward: 30, proof: 32,
76
+ repository: 40, demand: 41, contact: 42,
77
+ personal: 51, payment: 52,
78
+ };
79
+ const sorted = [...objects].sort((a, b) => {
80
+ const oa = typeOrder[a.object_type] ?? 99;
81
+ const ob = typeOrder[b.object_type] ?? 99;
82
+ return oa - ob;
83
+ });
84
+ return sorted.map((obj, i) => ({
85
+ step: i + 1,
86
+ object_type: obj.object_type,
87
+ operation: obj.publish_required ? "publish" : "create",
88
+ substep_count: 1,
89
+ depends_on: edges
90
+ .filter((e) => e.to === obj.entry_id)
91
+ .map((e) => sorted.findIndex((o) => o.entry_id === e.from) + 1)
92
+ .filter((n) => n > 0),
93
+ entry_id: obj.entry_id,
94
+ network_phase: network,
95
+ }));
96
+ }
@@ -0,0 +1,53 @@
1
+ import type { Project, ProjectObject, GraphEdge, ObjectCacheEntry, EvaluationType } from "@wowok/wowok";
2
+ import type { ReputationData } from "./graph-builder.js";
3
+ export interface CriterionScore {
4
+ name: string;
5
+ score: number;
6
+ weight: number;
7
+ rationale: string;
8
+ }
9
+ export interface EvaluationFinding {
10
+ criterion: string;
11
+ severity: "critical" | "warning" | "info";
12
+ message: string;
13
+ deduction: number;
14
+ }
15
+ export interface EvaluationResult {
16
+ evaluationType: EvaluationType;
17
+ score: number;
18
+ summary: string;
19
+ criterionScores: CriterionScore[];
20
+ findings: EvaluationFinding[];
21
+ strengths: string[];
22
+ needsLlm: boolean;
23
+ llmPrompt?: string;
24
+ evaluatedAt: number;
25
+ }
26
+ export interface EvaluationInput {
27
+ project: Project;
28
+ objects: ProjectObject[];
29
+ edges: GraphEdge[];
30
+ objectCache: Map<string, ObjectCacheEntry>;
31
+ reputation?: Map<string, ReputationData>;
32
+ }
33
+ export declare function runEvaluation(input: EvaluationInput, evaluationType: EvaluationType, llmPrompt?: string): EvaluationResult;
34
+ export interface ProjectComparisonEntry {
35
+ projectId: string;
36
+ projectName: string;
37
+ score: number | null;
38
+ summary: string | null;
39
+ evaluatedAt: number | null;
40
+ }
41
+ export interface ProjectComparison {
42
+ evaluationType: EvaluationType;
43
+ entries: ProjectComparisonEntry[];
44
+ ranking: ProjectComparisonEntry[];
45
+ bestProjectId: string | null;
46
+ }
47
+ export declare function compareProjects(entries: Array<{
48
+ projectId: string;
49
+ projectName: string;
50
+ score: number | null;
51
+ summary: string | null;
52
+ evaluatedAt: number | null;
53
+ }>, evaluationType: EvaluationType): ProjectComparison;