@wowok/agent-mcp 2.5.2 → 2.5.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.
Files changed (110) hide show
  1. package/dist/customer/index.d.ts +2 -2
  2. package/dist/customer/index.js +1 -1
  3. package/dist/customer/info-puzzle.d.ts +39 -2
  4. package/dist/customer/info-puzzle.js +370 -29
  5. package/dist/customer/risk-assessment.js +51 -14
  6. package/dist/customer/types.d.ts +85 -0
  7. package/dist/index.js +46 -6
  8. package/dist/knowledge/guard-design-patterns.js +104 -1
  9. package/dist/knowledge/guard-ledger.js +3 -3
  10. package/dist/knowledge/guard-lint.js +3 -3
  11. package/dist/knowledge/guard-risk.js +23 -15
  12. package/dist/knowledge/guard-templates.js +174 -2
  13. package/dist/knowledge/guard-translation.js +3 -3
  14. package/dist/knowledge/index.d.ts +3 -0
  15. package/dist/knowledge/index.js +9 -0
  16. package/dist/knowledge/machine-context.d.ts +1 -1
  17. package/dist/knowledge/machine-context.js +21 -0
  18. package/dist/knowledge/machine-ledger.d.ts +1 -0
  19. package/dist/knowledge/machine-ledger.js +60 -37
  20. package/dist/knowledge/machine-risk.js +23 -0
  21. package/dist/knowledge/machine-templates.js +150 -164
  22. package/dist/knowledge/overrides-loader.d.ts +13 -0
  23. package/dist/knowledge/overrides-loader.js +67 -0
  24. package/dist/knowledge/payment-risk.d.ts +4 -0
  25. package/dist/knowledge/payment-risk.js +67 -0
  26. package/dist/knowledge/repository-confirm.d.ts +4 -0
  27. package/dist/knowledge/repository-confirm.js +44 -0
  28. package/dist/knowledge/repository-risk.d.ts +8 -2
  29. package/dist/knowledge/repository-risk.js +61 -0
  30. package/dist/knowledge/repository-translation.js +23 -0
  31. package/dist/knowledge/reward-templates.d.ts +1 -1
  32. package/dist/knowledge/reward-templates.js +77 -5
  33. package/dist/knowledge/scenario-modes.js +22 -5
  34. package/dist/knowledge/service-templates.js +38 -0
  35. package/dist/knowledge/treasury-templates.js +42 -0
  36. package/dist/knowledge/trust-metrics.d.ts +4 -0
  37. package/dist/knowledge/trust-metrics.js +67 -7
  38. package/dist/loop-engineering/context-collect.d.ts +7 -0
  39. package/dist/loop-engineering/context-collect.js +83 -0
  40. package/dist/loop-engineering/improve.d.ts +29 -0
  41. package/dist/loop-engineering/improve.js +178 -0
  42. package/dist/project/context-assembly.d.ts +16 -0
  43. package/dist/project/context-assembly.js +130 -0
  44. package/dist/project/deployment-doc.d.ts +115 -0
  45. package/dist/project/deployment-doc.js +595 -0
  46. package/dist/project/index.js +37 -1
  47. package/dist/project/migration.d.ts +22 -0
  48. package/dist/project/migration.js +125 -0
  49. package/dist/project/project-store.d.ts +110 -0
  50. package/dist/project/project-store.js +425 -0
  51. package/dist/project/rollback-policy.d.ts +45 -0
  52. package/dist/project/rollback-policy.js +290 -0
  53. package/dist/project/stage-gate.d.ts +49 -0
  54. package/dist/project/stage-gate.js +310 -0
  55. package/dist/schema/call/allocation.d.ts +5 -0
  56. package/dist/schema/call/arbitration.d.ts +59 -54
  57. package/dist/schema/call/base.d.ts +3 -0
  58. package/dist/schema/call/base.js +1 -0
  59. package/dist/schema/call/bridge.d.ts +24 -0
  60. package/dist/schema/call/contact.d.ts +5 -0
  61. package/dist/schema/call/demand.d.ts +53 -48
  62. package/dist/schema/call/guard.d.ts +15 -0
  63. package/dist/schema/call/machine.d.ts +10 -0
  64. package/dist/schema/call/order.d.ts +5 -0
  65. package/dist/schema/call/payment.d.ts +5 -0
  66. package/dist/schema/call/permission.d.ts +5 -0
  67. package/dist/schema/call/personal.d.ts +5 -0
  68. package/dist/schema/call/progress.d.ts +5 -0
  69. package/dist/schema/call/proof.d.ts +10 -0
  70. package/dist/schema/call/repository.d.ts +5 -0
  71. package/dist/schema/call/reward.d.ts +5 -0
  72. package/dist/schema/call/service.d.ts +5 -0
  73. package/dist/schema/call/treasury.d.ts +5 -0
  74. package/dist/schema/operations.d.ts +286 -76
  75. package/dist/schema/operations.js +24 -0
  76. package/dist/schema/project/index.d.ts +2633 -120
  77. package/dist/schema/project/index.js +622 -2
  78. package/dist/schema/query/index.d.ts +601 -0
  79. package/dist/schema/query/index.js +61 -0
  80. package/dist/schema/trust/index.d.ts +10 -10
  81. package/dist/schemas/bridge_operation.schema.json +4 -0
  82. package/dist/schemas/guard2file.schema.json +4 -0
  83. package/dist/schemas/index.json +1 -1
  84. package/dist/schemas/machineNode2file.schema.json +4 -0
  85. package/dist/schemas/onchain_operations.schema.json +20 -0
  86. package/dist/schemas/onchain_operations_allocation.schema.json +4 -0
  87. package/dist/schemas/onchain_operations_arbitration.schema.json +4 -0
  88. package/dist/schemas/onchain_operations_contact.schema.json +4 -0
  89. package/dist/schemas/onchain_operations_demand.schema.json +4 -0
  90. package/dist/schemas/onchain_operations_gen_passport.schema.json +8 -0
  91. package/dist/schemas/onchain_operations_gen_proof.schema.json +8 -0
  92. package/dist/schemas/onchain_operations_guard.schema.json +4 -0
  93. package/dist/schemas/onchain_operations_machine.schema.json +4 -0
  94. package/dist/schemas/onchain_operations_order.schema.json +4 -0
  95. package/dist/schemas/onchain_operations_payment.schema.json +4 -0
  96. package/dist/schemas/onchain_operations_permission.schema.json +4 -0
  97. package/dist/schemas/onchain_operations_personal.schema.json +4 -0
  98. package/dist/schemas/onchain_operations_progress.schema.json +4 -0
  99. package/dist/schemas/onchain_operations_proof.schema.json +4 -0
  100. package/dist/schemas/onchain_operations_repository.schema.json +4 -0
  101. package/dist/schemas/onchain_operations_reward.schema.json +4 -0
  102. package/dist/schemas/onchain_operations_service.schema.json +4 -0
  103. package/dist/schemas/onchain_operations_treasury.schema.json +4 -0
  104. package/dist/schemas/project_operation.output.json +1798 -0
  105. package/dist/schemas/project_operation.schema.json +132 -2
  106. package/dist/schemas/query_toolkit.output.json +407 -1
  107. package/dist/schemas/query_toolkit.schema.json +132 -0
  108. package/dist/tools/handlers/project.js +742 -1
  109. package/dist/tools/handlers/query.js +38 -2
  110. package/package.json +2 -2
@@ -0,0 +1,45 @@
1
+ import { type ProjectStage, type StageState } from "./project-store.js";
2
+ export type ObjectLifecycleState = "created" | "referenced" | "published" | "bound";
3
+ export type StructReversibility = "reversible" | "limited" | "immutable";
4
+ export type GasImpact = "low" | "medium" | "high" | "none";
5
+ export interface ReversibilityEntry {
6
+ object_type: string;
7
+ lifecycle_state: ObjectLifecycleState;
8
+ struct_reversible: StructReversibility;
9
+ behavior_reversible: boolean;
10
+ gas_impact: GasImpact;
11
+ explanation: string;
12
+ }
13
+ export declare const REVERSIBILITY_MATRIX: ReversibilityEntry[];
14
+ export declare function queryReversibility(objectType: string, lifecycleState: ObjectLifecycleState): ReversibilityEntry | undefined;
15
+ export declare function getReversibilityForType(objectType: string): ReversibilityEntry[];
16
+ export type IterationStrategy = "in_place" | "fork";
17
+ export interface IterationRecommendation {
18
+ strategy: IterationStrategy;
19
+ reason: string;
20
+ fork_to_version?: string;
21
+ published_objects?: string[];
22
+ }
23
+ export declare function recommendIterationStrategy(prefix: string, version: string, currentStage?: ProjectStage): IterationRecommendation;
24
+ export interface RollbackPolicyResult {
25
+ allowed: boolean;
26
+ target_stage: ProjectStage;
27
+ current_stage: ProjectStage;
28
+ block_reason?: string;
29
+ files_to_clean: string[];
30
+ warnings: string[];
31
+ iteration_strategy: IterationRecommendation;
32
+ }
33
+ export declare function evaluateRollbackPolicy(prefix: string, version: string, targetStage: ProjectStage): RollbackPolicyResult;
34
+ export interface RollbackResult {
35
+ success: boolean;
36
+ target_stage: ProjectStage;
37
+ previous_stage: ProjectStage;
38
+ files_to_clean: string[];
39
+ files_cleaned: string[];
40
+ stage_state: StageState;
41
+ warnings: string[];
42
+ iteration_strategy: IterationRecommendation;
43
+ message: string;
44
+ }
45
+ export declare function rollbackStageWithPolicy(prefix: string, version: string, targetStage: ProjectStage, reason?: string): RollbackResult;
@@ -0,0 +1,290 @@
1
+ import { existsSync, rmSync } from "fs";
2
+ import { join } from "path";
3
+ import { loadStageState, projectDir, rollbackStage as rollbackStageState, } from "./project-store.js";
4
+ export const REVERSIBILITY_MATRIX = [
5
+ {
6
+ object_type: "permission",
7
+ lifecycle_state: "created",
8
+ struct_reversible: "reversible",
9
+ behavior_reversible: true,
10
+ gas_impact: "low",
11
+ explanation: "Permission (unpublished): can add tables/admins freely",
12
+ },
13
+ {
14
+ object_type: "permission",
15
+ lifecycle_state: "referenced",
16
+ struct_reversible: "limited",
17
+ behavior_reversible: true,
18
+ gas_impact: "medium",
19
+ explanation: "Permission (referenced by published service): modifications limited — affects dependents",
20
+ },
21
+ {
22
+ object_type: "machine",
23
+ lifecycle_state: "created",
24
+ struct_reversible: "reversible",
25
+ behavior_reversible: true,
26
+ gas_impact: "low",
27
+ explanation: "Machine (unpublished): can modify nodes/edges/forwards freely",
28
+ },
29
+ {
30
+ object_type: "machine",
31
+ lifecycle_state: "published",
32
+ struct_reversible: "immutable",
33
+ behavior_reversible: true,
34
+ gas_impact: "none",
35
+ explanation: "Machine (published): structure is immutable — can only advance progress",
36
+ },
37
+ {
38
+ object_type: "service",
39
+ lifecycle_state: "created",
40
+ struct_reversible: "reversible",
41
+ behavior_reversible: true,
42
+ gas_impact: "low",
43
+ explanation: "Service (unpublished): can modify fields freely",
44
+ },
45
+ {
46
+ object_type: "service",
47
+ lifecycle_state: "published",
48
+ struct_reversible: "immutable",
49
+ behavior_reversible: true,
50
+ gas_impact: "none",
51
+ explanation: "Service (published): machine/order_allocators frozen — can still transact normally",
52
+ },
53
+ {
54
+ object_type: "guard",
55
+ lifecycle_state: "created",
56
+ struct_reversible: "immutable",
57
+ behavior_reversible: false,
58
+ gas_impact: "none",
59
+ explanation: "Guard: create-only semantics — immutable from creation",
60
+ },
61
+ {
62
+ object_type: "allocation",
63
+ lifecycle_state: "created",
64
+ struct_reversible: "reversible",
65
+ behavior_reversible: true,
66
+ gas_impact: "low",
67
+ explanation: "Allocator (unbound): can modify strategy freely",
68
+ },
69
+ {
70
+ object_type: "allocation",
71
+ lifecycle_state: "bound",
72
+ struct_reversible: "limited",
73
+ behavior_reversible: true,
74
+ gas_impact: "medium",
75
+ explanation: "Allocator (bound to published service): strategy modifications limited",
76
+ },
77
+ {
78
+ object_type: "treasury",
79
+ lifecycle_state: "created",
80
+ struct_reversible: "reversible",
81
+ behavior_reversible: true,
82
+ gas_impact: "low",
83
+ explanation: "Treasury: can modify rules freely",
84
+ },
85
+ {
86
+ object_type: "arb",
87
+ lifecycle_state: "created",
88
+ struct_reversible: "reversible",
89
+ behavior_reversible: true,
90
+ gas_impact: "low",
91
+ explanation: "Arbitration: can modify rules freely",
92
+ },
93
+ {
94
+ object_type: "reward",
95
+ lifecycle_state: "created",
96
+ struct_reversible: "reversible",
97
+ behavior_reversible: true,
98
+ gas_impact: "low",
99
+ explanation: "Reward: can modify rules freely",
100
+ },
101
+ {
102
+ object_type: "progress",
103
+ lifecycle_state: "bound",
104
+ struct_reversible: "immutable",
105
+ behavior_reversible: true,
106
+ gas_impact: "none",
107
+ explanation: "Progress (bound to machine): cannot swap machine — can only forward",
108
+ },
109
+ {
110
+ object_type: "order",
111
+ lifecycle_state: "created",
112
+ struct_reversible: "immutable",
113
+ behavior_reversible: true,
114
+ gas_impact: "none",
115
+ explanation: "Order: structure immutable after creation — can only advance state",
116
+ },
117
+ ];
118
+ export function queryReversibility(objectType, lifecycleState) {
119
+ return REVERSIBILITY_MATRIX.find((e) => e.object_type === objectType && e.lifecycle_state === lifecycleState);
120
+ }
121
+ export function getReversibilityForType(objectType) {
122
+ return REVERSIBILITY_MATRIX.filter((e) => e.object_type === objectType);
123
+ }
124
+ export function recommendIterationStrategy(prefix, version, currentStage) {
125
+ const state = loadStageState(prefix, version);
126
+ if (!state) {
127
+ return {
128
+ strategy: "in_place",
129
+ reason: "Project not initialized — no stage state found. Use in-place for new projects.",
130
+ };
131
+ }
132
+ if (state.has_published_object) {
133
+ const versionMatch = version.match(/^v(\d+)$/);
134
+ const nextVersionNum = versionMatch ? parseInt(versionMatch[1]) + 1 : 2;
135
+ const forkTo = `v${nextVersionNum}`;
136
+ return {
137
+ strategy: "fork",
138
+ reason: `Project has published on-chain objects — in-place modification would break running business. ` +
139
+ `Fork to ${forkTo} to preserve the original version as a read-only historical snapshot.`,
140
+ fork_to_version: forkTo,
141
+ published_objects: state.stage_meta[5]?.committed
142
+ ? ["see deployment/05-substeps/ for published object list"]
143
+ : [],
144
+ };
145
+ }
146
+ const stage = currentStage ?? state.stage;
147
+ return {
148
+ strategy: "in_place",
149
+ reason: `Project has no published objects (current stage: ${stage}). ` +
150
+ `Safe to modify the current version directly — all changes are local and reversible.`,
151
+ };
152
+ }
153
+ const STAGE_DIR_SUFFIXES = {
154
+ 1: "01-namespace",
155
+ 2: "02-puzzle",
156
+ 3: "03-risk",
157
+ 4: "04-steps",
158
+ 5: "05-substeps",
159
+ };
160
+ export function evaluateRollbackPolicy(prefix, version, targetStage) {
161
+ const state = loadStageState(prefix, version);
162
+ if (!state) {
163
+ return {
164
+ allowed: false,
165
+ target_stage: targetStage,
166
+ current_stage: 1,
167
+ block_reason: `Project not initialized: ${prefix}_${version}`,
168
+ files_to_clean: [],
169
+ warnings: [],
170
+ iteration_strategy: {
171
+ strategy: "in_place",
172
+ reason: "Project not initialized.",
173
+ },
174
+ };
175
+ }
176
+ const currentStage = state.stage;
177
+ const iterationStrategy = recommendIterationStrategy(prefix, version, currentStage);
178
+ if (state.has_published_object) {
179
+ return {
180
+ allowed: false,
181
+ target_stage: targetStage,
182
+ current_stage: currentStage,
183
+ block_reason: `Project has published on-chain objects — rollback is forbidden (§3.3). ` +
184
+ `Use fork_project to create a new version for modifications.`,
185
+ files_to_clean: [],
186
+ warnings: [],
187
+ iteration_strategy: iterationStrategy,
188
+ };
189
+ }
190
+ if (targetStage >= currentStage) {
191
+ return {
192
+ allowed: false,
193
+ target_stage: targetStage,
194
+ current_stage: currentStage,
195
+ block_reason: `Target stage ${targetStage} must be less than current stage ${currentStage}.`,
196
+ files_to_clean: [],
197
+ warnings: [],
198
+ iteration_strategy: iterationStrategy,
199
+ };
200
+ }
201
+ if (targetStage < 1) {
202
+ return {
203
+ allowed: false,
204
+ target_stage: targetStage,
205
+ current_stage: currentStage,
206
+ block_reason: "Cannot rollback below stage 1.",
207
+ files_to_clean: [],
208
+ warnings: [],
209
+ iteration_strategy: iterationStrategy,
210
+ };
211
+ }
212
+ const filesToClean = [];
213
+ const warnings = [];
214
+ const depDir = join(projectDir(prefix, version), "deployment");
215
+ for (let s = targetStage + 1; s <= 5; s++) {
216
+ const stageDir = join(depDir, STAGE_DIR_SUFFIXES[s]);
217
+ if (existsSync(stageDir)) {
218
+ filesToClean.push(`deployment/${STAGE_DIR_SUFFIXES[s]}/`);
219
+ }
220
+ }
221
+ if (targetStage <= 2 && existsSync(depDir)) {
222
+ filesToClean.length = 0;
223
+ filesToClean.push("deployment/");
224
+ }
225
+ if (filesToClean.length > 0) {
226
+ warnings.push(`Rollback will delete ${filesToClean.length} file(s)/directory(ies): ${filesToClean.join(", ")}. ` +
227
+ `This data will be lost — regenerate by re-running the stage action.`);
228
+ }
229
+ return {
230
+ allowed: true,
231
+ target_stage: targetStage,
232
+ current_stage: currentStage,
233
+ files_to_clean: filesToClean,
234
+ warnings,
235
+ iteration_strategy: iterationStrategy,
236
+ };
237
+ }
238
+ export function rollbackStageWithPolicy(prefix, version, targetStage, reason) {
239
+ const policy = evaluateRollbackPolicy(prefix, version, targetStage);
240
+ if (!policy.allowed) {
241
+ return {
242
+ success: false,
243
+ target_stage: targetStage,
244
+ previous_stage: policy.current_stage,
245
+ files_to_clean: [],
246
+ files_cleaned: [],
247
+ stage_state: loadStageState(prefix, version),
248
+ warnings: [],
249
+ iteration_strategy: policy.iteration_strategy,
250
+ message: `Rollback blocked: ${policy.block_reason}`,
251
+ };
252
+ }
253
+ const filesCleaned = [];
254
+ const depDir = join(projectDir(prefix, version), "deployment");
255
+ if (policy.files_to_clean.includes("deployment/")) {
256
+ if (existsSync(depDir)) {
257
+ rmSync(depDir, { recursive: true, force: true });
258
+ filesCleaned.push("deployment/");
259
+ }
260
+ }
261
+ else {
262
+ for (const relPath of policy.files_to_clean) {
263
+ const absPath = join(projectDir(prefix, version), relPath);
264
+ if (existsSync(absPath)) {
265
+ rmSync(absPath, { recursive: true, force: true });
266
+ filesCleaned.push(relPath);
267
+ }
268
+ }
269
+ }
270
+ const newState = rollbackStageState(prefix, version, targetStage, {
271
+ reason: reason ?? `rollback to stage ${targetStage} (policy-evaluated)`,
272
+ affectedFiles: filesCleaned.length > 0 ? filesCleaned : ["stage.json"],
273
+ });
274
+ return {
275
+ success: true,
276
+ target_stage: targetStage,
277
+ previous_stage: policy.current_stage,
278
+ files_to_clean: policy.files_to_clean,
279
+ files_cleaned: filesCleaned,
280
+ stage_state: newState,
281
+ warnings: policy.warnings,
282
+ iteration_strategy: policy.iteration_strategy,
283
+ message: `Rolled back from stage ${policy.current_stage} to ${targetStage}. ` +
284
+ `${filesCleaned.length} file(s)/directory(ies) cleaned. ` +
285
+ `Stage state updated. ` +
286
+ (policy.iteration_strategy.strategy === "fork"
287
+ ? `Note: this project has published objects — future modifications require fork.`
288
+ : `Project has no published objects — in-place modification is safe.`),
289
+ };
290
+ }
@@ -0,0 +1,49 @@
1
+ import type { ProjectStage } from "./project-store.js";
2
+ export type GateDimension = "semantic" | "tools" | "reversibility" | "risk" | "isolation" | "gas_budget";
3
+ export interface GasBudgetCheck {
4
+ network: "testnet" | "mainnet";
5
+ already_spent_gas: number;
6
+ estimated_rerun_gas: number;
7
+ warning?: string;
8
+ }
9
+ export interface StageGateCheck {
10
+ dimension: GateDimension;
11
+ status: "PASS" | "FAIL" | "WARN";
12
+ message: string;
13
+ }
14
+ export interface StageGateInput {
15
+ stage: ProjectStage;
16
+ prefix: string;
17
+ version: string;
18
+ naming?: {
19
+ prefix_valid: boolean;
20
+ version_valid: boolean;
21
+ };
22
+ puzzles?: Record<string, unknown>;
23
+ puzzles_completeness?: "complete" | "partial" | "empty";
24
+ risk_status?: string;
25
+ risk_can_proceed?: boolean;
26
+ doc_error_count?: number;
27
+ objects?: Array<{
28
+ entry_id: string;
29
+ object_type?: string;
30
+ reused_from?: string;
31
+ }>;
32
+ edges?: Array<{
33
+ from: string;
34
+ to: string;
35
+ }>;
36
+ trace_coherent?: boolean;
37
+ has_published_object?: boolean;
38
+ gas_budget?: GasBudgetCheck;
39
+ }
40
+ export interface StageGateResult {
41
+ stage: ProjectStage;
42
+ passed: boolean;
43
+ checks: StageGateCheck[];
44
+ blocking_issues: string[];
45
+ warnings: string[];
46
+ can_proceed: boolean;
47
+ }
48
+ export declare function validateStageGate(input: StageGateInput): StageGateResult;
49
+ export declare function validateStageGateFromDisk(prefix: string, version: string, stage?: ProjectStage, extra?: Partial<StageGateInput>): StageGateResult;
@@ -0,0 +1,310 @@
1
+ import { loadStageState, projectExists } from "./project-store.js";
2
+ function buildGasBudgetCheck(input) {
3
+ const gb = input.gas_budget;
4
+ if (!gb) {
5
+ return {
6
+ dimension: "gas_budget",
7
+ status: "PASS",
8
+ message: "Gas budget not provided (N/A for this stage or caller omitted)",
9
+ };
10
+ }
11
+ if (gb.network === "testnet") {
12
+ return {
13
+ dimension: "gas_budget",
14
+ status: "PASS",
15
+ message: "testnet: no gas limit (faucet is free); rollback is costless",
16
+ };
17
+ }
18
+ const total = gb.already_spent_gas + gb.estimated_rerun_gas;
19
+ const warning = gb.warning ??
20
+ `mainnet: estimated total gas ${total} MIST (already_spent=${gb.already_spent_gas} + rerun=${gb.estimated_rerun_gas}). Rollback will incur real cost.`;
21
+ return {
22
+ dimension: "gas_budget",
23
+ status: "WARN",
24
+ message: warning,
25
+ };
26
+ }
27
+ function validateStage1Gate(input) {
28
+ const checks = [];
29
+ const namingValid = input.naming?.prefix_valid && input.naming?.version_valid;
30
+ checks.push({
31
+ dimension: "semantic",
32
+ status: namingValid ? "PASS" : "FAIL",
33
+ message: namingValid
34
+ ? "Project namespace is valid (prefix + version)"
35
+ : "Project naming is invalid — prefix must match ^[a-z][a-z0-9_]{2,63}$ and version must match ^v\\d+$",
36
+ });
37
+ checks.push({
38
+ dimension: "tools",
39
+ status: "PASS",
40
+ message: "Stage 1 requires no on-chain tools (namespace is local-only)",
41
+ });
42
+ checks.push({
43
+ dimension: "reversibility",
44
+ status: "PASS",
45
+ message: "Stage 1 is fully reversible (no on-chain state changes)",
46
+ });
47
+ checks.push({
48
+ dimension: "risk",
49
+ status: "PASS",
50
+ message: "No risks at namespace stage",
51
+ });
52
+ checks.push({
53
+ dimension: "isolation",
54
+ status: "PASS",
55
+ message: "Stage 1 has no objects (isolation N/A)",
56
+ });
57
+ checks.push(buildGasBudgetCheck(input));
58
+ return checks;
59
+ }
60
+ function validateStage2Gate(input) {
61
+ const checks = [];
62
+ const hasPuzzles = input.puzzles && Object.keys(input.puzzles).length > 0;
63
+ const completeness = input.puzzles_completeness ?? "empty";
64
+ checks.push({
65
+ dimension: "semantic",
66
+ status: hasPuzzles
67
+ ? completeness === "complete"
68
+ ? "PASS"
69
+ : completeness === "partial"
70
+ ? "WARN"
71
+ : "FAIL"
72
+ : "FAIL",
73
+ message: hasPuzzles
74
+ ? `Puzzles present with completeness: ${completeness}`
75
+ : "No puzzles found — call analyze_intent first",
76
+ });
77
+ if (hasPuzzles) {
78
+ const objectTypes = Object.keys(input.puzzles);
79
+ checks.push({
80
+ dimension: "tools",
81
+ status: "PASS",
82
+ message: `${objectTypes.length} object type(s) defined: ${objectTypes.join(", ")}`,
83
+ });
84
+ }
85
+ else {
86
+ checks.push({
87
+ dimension: "tools",
88
+ status: "FAIL",
89
+ message: "Cannot verify tools — no puzzles available",
90
+ });
91
+ }
92
+ checks.push({
93
+ dimension: "reversibility",
94
+ status: "PASS",
95
+ message: "Stage 2 is in-memory only (no on-chain state changes)",
96
+ });
97
+ checks.push({
98
+ dimension: "risk",
99
+ status: "PASS",
100
+ message: "Risk assessment happens in stage 3 (aggregate_risks)",
101
+ });
102
+ if (input.objects && input.objects.length > 0) {
103
+ const crossProject = input.objects.filter((o) => o.reused_from && o.reused_from.includes(":") && !o.reused_from.startsWith("0x"));
104
+ checks.push({
105
+ dimension: "isolation",
106
+ status: crossProject.length === 0 ? "PASS" : "FAIL",
107
+ message: crossProject.length === 0
108
+ ? "No cross-project object references detected"
109
+ : `${crossProject.length} object(s) reference external projects (§3.0 violation): ${crossProject.map((o) => o.entry_id).join(", ")}`,
110
+ });
111
+ }
112
+ else {
113
+ checks.push({
114
+ dimension: "isolation",
115
+ status: "PASS",
116
+ message: "No objects to check for isolation (stage 2)",
117
+ });
118
+ }
119
+ checks.push(buildGasBudgetCheck(input));
120
+ return checks;
121
+ }
122
+ function validateStage3Gate(input) {
123
+ const checks = [];
124
+ const hasRiskStatus = input.risk_status !== undefined && input.risk_status !== "";
125
+ checks.push({
126
+ dimension: "semantic",
127
+ status: hasRiskStatus ? "PASS" : "FAIL",
128
+ message: hasRiskStatus
129
+ ? `Risk status: ${input.risk_status}`
130
+ : "No risk assessment found — call aggregate_risks first",
131
+ });
132
+ checks.push({
133
+ dimension: "tools",
134
+ status: "PASS",
135
+ message: "Risk assessment uses puzzles from stage 2 (no additional tools)",
136
+ });
137
+ checks.push({
138
+ dimension: "reversibility",
139
+ status: "PASS",
140
+ message: "Stage 3 is reversible (re-run aggregate_risks to update)",
141
+ });
142
+ const canProceed = input.risk_can_proceed === true;
143
+ checks.push({
144
+ dimension: "risk",
145
+ status: canProceed ? "PASS" : "FAIL",
146
+ message: canProceed
147
+ ? "All CRITICAL risks resolved — may proceed"
148
+ : "CRITICAL risks remain — fix before proceeding (non-blocking principle: only CRITICAL blocks)",
149
+ });
150
+ checks.push({
151
+ dimension: "isolation",
152
+ status: "PASS",
153
+ message: "Isolation verified in stage 2",
154
+ });
155
+ checks.push(buildGasBudgetCheck(input));
156
+ return checks;
157
+ }
158
+ function validateStage4Gate(input) {
159
+ const checks = [];
160
+ const errorCount = input.doc_error_count ?? -1;
161
+ checks.push({
162
+ dimension: "semantic",
163
+ status: errorCount === 0 ? "PASS" : errorCount > 0 ? "FAIL" : "WARN",
164
+ message: errorCount === 0
165
+ ? "Deployment doc generated with 0 D-errors"
166
+ : errorCount > 0
167
+ ? `${errorCount} D-error(s) remain — fix before proceeding`
168
+ : "Doc error count unknown — call generate_deployment_doc first",
169
+ });
170
+ if (input.objects && input.edges) {
171
+ const objectIds = new Set(input.objects.map((o) => o.entry_id));
172
+ const danglingEdges = input.edges.filter((e) => !objectIds.has(e.from) || !objectIds.has(e.to));
173
+ checks.push({
174
+ dimension: "tools",
175
+ status: danglingEdges.length === 0 ? "PASS" : "FAIL",
176
+ message: danglingEdges.length === 0
177
+ ? `All ${input.edges.length} edge(s) reference defined objects`
178
+ : `${danglingEdges.length} edge(s) reference undefined objects`,
179
+ });
180
+ }
181
+ else {
182
+ checks.push({
183
+ dimension: "tools",
184
+ status: "WARN",
185
+ message: "Objects/edges not provided — cannot verify tool availability",
186
+ });
187
+ }
188
+ checks.push({
189
+ dimension: "reversibility",
190
+ status: "PASS",
191
+ message: "Stage 4 is reversible (regenerate deployment doc)",
192
+ });
193
+ const riskPassed = input.risk_status === "RISK_PASSED";
194
+ checks.push({
195
+ dimension: "risk",
196
+ status: riskPassed ? "PASS" : "WARN",
197
+ message: riskPassed
198
+ ? "Risk status is RISK_PASSED"
199
+ : `Risk status is ${input.risk_status ?? "unknown"} — recommend resolving before deployment`,
200
+ });
201
+ if (input.objects && input.objects.length > 0) {
202
+ const crossProject = input.objects.filter((o) => o.reused_from && !o.reused_from.startsWith("0x") && o.reused_from.includes(":"));
203
+ checks.push({
204
+ dimension: "isolation",
205
+ status: crossProject.length === 0 ? "PASS" : "FAIL",
206
+ message: crossProject.length === 0
207
+ ? "No cross-project references in deployment objects"
208
+ : `${crossProject.length} object(s) have cross-project reused_from (§3.0 violation)`,
209
+ });
210
+ }
211
+ else {
212
+ checks.push({
213
+ dimension: "isolation",
214
+ status: "PASS",
215
+ message: "No objects to check for isolation (stage 4)",
216
+ });
217
+ }
218
+ checks.push(buildGasBudgetCheck(input));
219
+ return checks;
220
+ }
221
+ function validateStage5Gate(input) {
222
+ const checks = [];
223
+ const coherent = input.trace_coherent === true;
224
+ checks.push({
225
+ dimension: "semantic",
226
+ status: coherent ? "PASS" : "FAIL",
227
+ message: coherent
228
+ ? "Substeps are coherent (no dangling/circular/missing)"
229
+ : "Substeps are not coherent — call trace_substeps and fix issues",
230
+ });
231
+ checks.push({
232
+ dimension: "tools",
233
+ status: coherent ? "PASS" : "FAIL",
234
+ message: coherent
235
+ ? "All substep dependencies resolve"
236
+ : "Substep dependencies have issues (see trace_substeps output)",
237
+ });
238
+ const hasPublished = input.has_published_object === true;
239
+ checks.push({
240
+ dimension: "reversibility",
241
+ status: hasPublished ? "WARN" : "PASS",
242
+ message: hasPublished
243
+ ? "Objects have been published on-chain — rollback requires fork (§3.3). " +
244
+ "Ensure all substeps are correct before executing on mainnet."
245
+ : "No objects published yet — stage 5 is still reversible",
246
+ });
247
+ checks.push({
248
+ dimension: "risk",
249
+ status: "PASS",
250
+ message: "Risks verified in stage 3",
251
+ });
252
+ checks.push({
253
+ dimension: "isolation",
254
+ status: "PASS",
255
+ message: "Isolation verified in stages 2 and 4",
256
+ });
257
+ checks.push(buildGasBudgetCheck(input));
258
+ return checks;
259
+ }
260
+ const STAGE_VALIDATORS = {
261
+ 1: validateStage1Gate,
262
+ 2: validateStage2Gate,
263
+ 3: validateStage3Gate,
264
+ 4: validateStage4Gate,
265
+ 5: validateStage5Gate,
266
+ };
267
+ export function validateStageGate(input) {
268
+ const validator = STAGE_VALIDATORS[input.stage];
269
+ const checks = validator(input);
270
+ const blockingIssues = checks
271
+ .filter((c) => c.status === "FAIL")
272
+ .map((c) => `[${c.dimension}] ${c.message}`);
273
+ const warnings = checks
274
+ .filter((c) => c.status === "WARN")
275
+ .map((c) => `[${c.dimension}] ${c.message}`);
276
+ return {
277
+ stage: input.stage,
278
+ passed: blockingIssues.length === 0,
279
+ checks,
280
+ blocking_issues: blockingIssues,
281
+ warnings,
282
+ can_proceed: blockingIssues.length === 0,
283
+ };
284
+ }
285
+ export function validateStageGateFromDisk(prefix, version, stage, extra) {
286
+ if (!projectExists(prefix, version)) {
287
+ return {
288
+ stage: stage ?? 1,
289
+ passed: false,
290
+ checks: [{
291
+ dimension: "semantic",
292
+ status: "FAIL",
293
+ message: `Project not found locally: ${prefix}_${version}`,
294
+ }],
295
+ blocking_issues: [`Project not found locally: ${prefix}_${version}`],
296
+ warnings: [],
297
+ can_proceed: false,
298
+ };
299
+ }
300
+ const state = loadStageState(prefix, version);
301
+ const effectiveStage = stage ?? state?.stage ?? 1;
302
+ const hasPublished = state?.has_published_object ?? false;
303
+ return validateStageGate({
304
+ stage: effectiveStage,
305
+ prefix,
306
+ version,
307
+ has_published_object: hasPublished,
308
+ ...extra,
309
+ });
310
+ }