@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.
- package/dist/customer/index.d.ts +2 -2
- package/dist/customer/index.js +1 -1
- package/dist/customer/info-puzzle.d.ts +39 -2
- package/dist/customer/info-puzzle.js +370 -29
- package/dist/customer/risk-assessment.js +51 -14
- package/dist/customer/types.d.ts +85 -0
- package/dist/index.js +46 -6
- package/dist/knowledge/guard-design-patterns.js +104 -1
- package/dist/knowledge/guard-ledger.js +3 -3
- package/dist/knowledge/guard-lint.js +3 -3
- package/dist/knowledge/guard-risk.js +23 -15
- package/dist/knowledge/guard-templates.js +174 -2
- package/dist/knowledge/guard-translation.js +3 -3
- package/dist/knowledge/index.d.ts +3 -0
- package/dist/knowledge/index.js +9 -0
- package/dist/knowledge/machine-context.d.ts +1 -1
- package/dist/knowledge/machine-context.js +21 -0
- package/dist/knowledge/machine-ledger.d.ts +1 -0
- package/dist/knowledge/machine-ledger.js +60 -37
- package/dist/knowledge/machine-risk.js +23 -0
- package/dist/knowledge/machine-templates.js +150 -164
- package/dist/knowledge/overrides-loader.d.ts +13 -0
- package/dist/knowledge/overrides-loader.js +67 -0
- package/dist/knowledge/payment-risk.d.ts +4 -0
- package/dist/knowledge/payment-risk.js +67 -0
- package/dist/knowledge/repository-confirm.d.ts +4 -0
- package/dist/knowledge/repository-confirm.js +44 -0
- package/dist/knowledge/repository-risk.d.ts +8 -2
- package/dist/knowledge/repository-risk.js +61 -0
- package/dist/knowledge/repository-translation.js +23 -0
- package/dist/knowledge/reward-templates.d.ts +1 -1
- package/dist/knowledge/reward-templates.js +77 -5
- package/dist/knowledge/scenario-modes.js +22 -5
- package/dist/knowledge/service-templates.js +38 -0
- package/dist/knowledge/treasury-templates.js +42 -0
- package/dist/knowledge/trust-metrics.d.ts +4 -0
- package/dist/knowledge/trust-metrics.js +67 -7
- package/dist/loop-engineering/context-collect.d.ts +7 -0
- package/dist/loop-engineering/context-collect.js +83 -0
- package/dist/loop-engineering/improve.d.ts +29 -0
- package/dist/loop-engineering/improve.js +178 -0
- package/dist/project/context-assembly.d.ts +16 -0
- package/dist/project/context-assembly.js +130 -0
- package/dist/project/deployment-doc.d.ts +115 -0
- package/dist/project/deployment-doc.js +595 -0
- package/dist/project/index.js +37 -1
- package/dist/project/migration.d.ts +22 -0
- package/dist/project/migration.js +125 -0
- package/dist/project/project-store.d.ts +110 -0
- package/dist/project/project-store.js +425 -0
- package/dist/project/rollback-policy.d.ts +45 -0
- package/dist/project/rollback-policy.js +290 -0
- package/dist/project/stage-gate.d.ts +49 -0
- package/dist/project/stage-gate.js +310 -0
- package/dist/schema/call/allocation.d.ts +5 -0
- package/dist/schema/call/arbitration.d.ts +59 -54
- package/dist/schema/call/base.d.ts +3 -0
- package/dist/schema/call/base.js +1 -0
- package/dist/schema/call/bridge.d.ts +24 -0
- package/dist/schema/call/contact.d.ts +5 -0
- package/dist/schema/call/demand.d.ts +53 -48
- package/dist/schema/call/guard.d.ts +15 -0
- package/dist/schema/call/machine.d.ts +10 -0
- package/dist/schema/call/order.d.ts +5 -0
- package/dist/schema/call/payment.d.ts +5 -0
- package/dist/schema/call/permission.d.ts +5 -0
- package/dist/schema/call/personal.d.ts +5 -0
- package/dist/schema/call/progress.d.ts +5 -0
- package/dist/schema/call/proof.d.ts +10 -0
- package/dist/schema/call/repository.d.ts +5 -0
- package/dist/schema/call/reward.d.ts +5 -0
- package/dist/schema/call/service.d.ts +5 -0
- package/dist/schema/call/treasury.d.ts +5 -0
- package/dist/schema/operations.d.ts +286 -76
- package/dist/schema/operations.js +24 -0
- package/dist/schema/project/index.d.ts +2633 -120
- package/dist/schema/project/index.js +622 -2
- package/dist/schema/query/index.d.ts +601 -0
- package/dist/schema/query/index.js +61 -0
- package/dist/schema/trust/index.d.ts +10 -10
- package/dist/schemas/bridge_operation.schema.json +4 -0
- package/dist/schemas/guard2file.schema.json +4 -0
- package/dist/schemas/index.json +1 -1
- package/dist/schemas/machineNode2file.schema.json +4 -0
- package/dist/schemas/onchain_operations.schema.json +20 -0
- package/dist/schemas/onchain_operations_allocation.schema.json +4 -0
- package/dist/schemas/onchain_operations_arbitration.schema.json +4 -0
- package/dist/schemas/onchain_operations_contact.schema.json +4 -0
- package/dist/schemas/onchain_operations_demand.schema.json +4 -0
- package/dist/schemas/onchain_operations_gen_passport.schema.json +8 -0
- package/dist/schemas/onchain_operations_gen_proof.schema.json +8 -0
- package/dist/schemas/onchain_operations_guard.schema.json +4 -0
- package/dist/schemas/onchain_operations_machine.schema.json +4 -0
- package/dist/schemas/onchain_operations_order.schema.json +4 -0
- package/dist/schemas/onchain_operations_payment.schema.json +4 -0
- package/dist/schemas/onchain_operations_permission.schema.json +4 -0
- package/dist/schemas/onchain_operations_personal.schema.json +4 -0
- package/dist/schemas/onchain_operations_progress.schema.json +4 -0
- package/dist/schemas/onchain_operations_proof.schema.json +4 -0
- package/dist/schemas/onchain_operations_repository.schema.json +4 -0
- package/dist/schemas/onchain_operations_reward.schema.json +4 -0
- package/dist/schemas/onchain_operations_service.schema.json +4 -0
- package/dist/schemas/onchain_operations_treasury.schema.json +4 -0
- package/dist/schemas/project_operation.output.json +1798 -0
- package/dist/schemas/project_operation.schema.json +132 -2
- package/dist/schemas/query_toolkit.output.json +407 -1
- package/dist/schemas/query_toolkit.schema.json +132 -0
- package/dist/tools/handlers/project.js +742 -1
- package/dist/tools/handlers/query.js +38 -2
- package/package.json +2 -2
|
@@ -38,16 +38,51 @@ export function computeServiceTrustScore(metrics) {
|
|
|
38
38
|
}
|
|
39
39
|
function computeArbitrationDimension(metrics) {
|
|
40
40
|
const maxScore = 30;
|
|
41
|
-
if (metrics.arbitrationScore === undefined) {
|
|
42
|
-
return {
|
|
41
|
+
if (metrics.arbitrationScore === undefined && metrics.arbitrationVotingGuardCount === undefined) {
|
|
42
|
+
return {
|
|
43
|
+
name: "arbitration",
|
|
44
|
+
score: maxScore * 0.25,
|
|
45
|
+
maxScore,
|
|
46
|
+
description: "Arbitration trust score (no data; default low because arbitration is critical)",
|
|
47
|
+
humanReadable: "Arbitration: no data (default low — critical missing)",
|
|
48
|
+
};
|
|
43
49
|
}
|
|
44
|
-
|
|
50
|
+
let score = 0;
|
|
51
|
+
const parts = [];
|
|
52
|
+
if (metrics.arbitrationScore !== undefined) {
|
|
53
|
+
const baseScore = Math.round((metrics.arbitrationScore / 100) * 10);
|
|
54
|
+
score += baseScore;
|
|
55
|
+
parts.push(`score ${metrics.arbitrationScore}/100`);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
score += 3;
|
|
59
|
+
}
|
|
60
|
+
if (metrics.arbitrationVotingGuardCount !== undefined && metrics.arbitrationVotingGuardCount > 0) {
|
|
61
|
+
score += 5;
|
|
62
|
+
parts.push(`${metrics.arbitrationVotingGuardCount} voting_guard(s)`);
|
|
63
|
+
}
|
|
64
|
+
if (metrics.arbitrationFeeBalance !== undefined && metrics.arbitrationFeeBalance > 0n) {
|
|
65
|
+
score += 5;
|
|
66
|
+
parts.push("fee funded");
|
|
67
|
+
}
|
|
68
|
+
if (metrics.arbitrationPaused === false) {
|
|
69
|
+
score += 5;
|
|
70
|
+
parts.push("active");
|
|
71
|
+
}
|
|
72
|
+
else if (metrics.arbitrationPaused === true) {
|
|
73
|
+
parts.push("paused");
|
|
74
|
+
}
|
|
75
|
+
if (metrics.arbitrationCases !== undefined && metrics.arbitrationCases > 0) {
|
|
76
|
+
score += 5;
|
|
77
|
+
parts.push(`${metrics.arbitrationCases} case(s)`);
|
|
78
|
+
}
|
|
79
|
+
score = Math.min(maxScore, score);
|
|
45
80
|
return {
|
|
46
81
|
name: "arbitration",
|
|
47
82
|
score,
|
|
48
83
|
maxScore,
|
|
49
|
-
description: `Arbitration
|
|
50
|
-
humanReadable: `Arbitration
|
|
84
|
+
description: `Arbitration config: ${parts.join(", ")}`,
|
|
85
|
+
humanReadable: `Arbitration: ${parts.join(", ")}`,
|
|
51
86
|
};
|
|
52
87
|
}
|
|
53
88
|
function computeReviewDimension(metrics) {
|
|
@@ -94,6 +129,31 @@ function computeFundDimension(metrics) {
|
|
|
94
129
|
if (metrics.compensationFundBalance === undefined || metrics.compensationFundBalance === 0n) {
|
|
95
130
|
return { name: "fund_safety", score: 0, maxScore, description: "No compensation fund", humanReadable: "Compensation fund: none" };
|
|
96
131
|
}
|
|
132
|
+
const fund = metrics.compensationFundBalance;
|
|
133
|
+
if (metrics.typicalOrderAmount !== undefined && metrics.typicalOrderAmount > 0n) {
|
|
134
|
+
const ratio = Number((fund * 100n) / metrics.typicalOrderAmount) / 100;
|
|
135
|
+
let score;
|
|
136
|
+
let humanReadable;
|
|
137
|
+
if (ratio >= 10) {
|
|
138
|
+
score = maxScore;
|
|
139
|
+
humanReadable = `Compensation fund: ${ratio.toFixed(1)}x order amount (excellent)`;
|
|
140
|
+
}
|
|
141
|
+
else if (ratio >= 1) {
|
|
142
|
+
score = 10 + Math.round((ratio - 1) / 9 * 5);
|
|
143
|
+
humanReadable = `Compensation fund: ${ratio.toFixed(1)}x order amount (covers ≥1 payout)`;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
score = Math.round(ratio * 10);
|
|
147
|
+
humanReadable = `Compensation fund: ${ratio.toFixed(1)}x order amount (insufficient)`;
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
name: "fund_safety",
|
|
151
|
+
score: Math.min(maxScore, score),
|
|
152
|
+
maxScore,
|
|
153
|
+
description: `Fund ${fund.toString()} / typical order ${metrics.typicalOrderAmount.toString()} = ${ratio.toFixed(2)}x`,
|
|
154
|
+
humanReadable,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
97
157
|
const threshold = 1000000000000n;
|
|
98
158
|
const ratio = Number(metrics.compensationFundBalance * 100n / threshold) / 100;
|
|
99
159
|
const score = Math.min(maxScore, Math.round(ratio * maxScore));
|
|
@@ -101,8 +161,8 @@ function computeFundDimension(metrics) {
|
|
|
101
161
|
name: "fund_safety",
|
|
102
162
|
score,
|
|
103
163
|
maxScore,
|
|
104
|
-
description: `Compensation fund ${metrics.compensationFundBalance} smallest unit`,
|
|
105
|
-
humanReadable: `Compensation fund:
|
|
164
|
+
description: `Compensation fund ${metrics.compensationFundBalance} smallest unit (absolute threshold fallback)`,
|
|
165
|
+
humanReadable: `Compensation fund: ${ratio.toFixed(2)}x absolute threshold`,
|
|
106
166
|
};
|
|
107
167
|
}
|
|
108
168
|
function computeTransparencyDimension(metrics) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AssembleContextResult } from "../project/context-assembly.js";
|
|
2
|
+
export interface ContextCollectionResult {
|
|
3
|
+
signature_recorded: boolean;
|
|
4
|
+
proposal_created: boolean;
|
|
5
|
+
proposal_id?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function collectContextExperience(result: AssembleContextResult, network: string): ContextCollectionResult;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { recordSignature } from "../experience/index.js";
|
|
2
|
+
import { persistImprovementQueue } from "./improve.js";
|
|
3
|
+
export function collectContextExperience(result, network) {
|
|
4
|
+
const objectTypes = extractObjectTypes(result.objects);
|
|
5
|
+
const hasEmbeddedHistory = !!result.embedded_history;
|
|
6
|
+
const hasEvents = !!result.events && result.events.length > 0;
|
|
7
|
+
const signature = {
|
|
8
|
+
intent: "assemble_context",
|
|
9
|
+
signals: {
|
|
10
|
+
object_types: objectTypes,
|
|
11
|
+
object_count: result.objects.length,
|
|
12
|
+
has_embedded_history: hasEmbeddedHistory,
|
|
13
|
+
has_events: hasEvents,
|
|
14
|
+
context_digest: result.context_digest,
|
|
15
|
+
network,
|
|
16
|
+
},
|
|
17
|
+
timestamp: Date.now(),
|
|
18
|
+
outcome: "success",
|
|
19
|
+
};
|
|
20
|
+
let signatureRecorded = false;
|
|
21
|
+
try {
|
|
22
|
+
recordSignature(signature);
|
|
23
|
+
signatureRecorded = true;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
}
|
|
27
|
+
let proposal;
|
|
28
|
+
if (objectTypes.length >= 3) {
|
|
29
|
+
proposal = {
|
|
30
|
+
proposal_id: `PROP-CTX-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
|
|
31
|
+
source_diagnosis_id: `CTX-${result.context_digest}`,
|
|
32
|
+
type: "description_rewrite",
|
|
33
|
+
priority: "P3",
|
|
34
|
+
automation: "semi",
|
|
35
|
+
apply_mode: "config_override",
|
|
36
|
+
override_category: "descriptions",
|
|
37
|
+
title: `Enrich assemble_context for ${objectTypes.join("+")} patterns`,
|
|
38
|
+
description: `Assembled context with ${objectTypes.length} object types (${objectTypes.join(", ")}). ` +
|
|
39
|
+
`Consider enriching the assemble_context action description to guide AI toward ` +
|
|
40
|
+
`common ${objectTypes.join("+")} business patterns.`,
|
|
41
|
+
target: "assemble_context",
|
|
42
|
+
proposed_change: {
|
|
43
|
+
action: "enrich_description",
|
|
44
|
+
object_types: objectTypes,
|
|
45
|
+
has_embedded_history: hasEmbeddedHistory,
|
|
46
|
+
has_events: hasEvents,
|
|
47
|
+
context_digest: result.context_digest,
|
|
48
|
+
},
|
|
49
|
+
evidence: {
|
|
50
|
+
context_digest: result.context_digest,
|
|
51
|
+
object_count: result.objects.length,
|
|
52
|
+
object_types: objectTypes,
|
|
53
|
+
network,
|
|
54
|
+
},
|
|
55
|
+
review_status: "pending",
|
|
56
|
+
ab_test_recommended: false,
|
|
57
|
+
};
|
|
58
|
+
try {
|
|
59
|
+
persistImprovementQueue([proposal]);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
signature_recorded: signatureRecorded,
|
|
66
|
+
proposal_created: !!proposal,
|
|
67
|
+
proposal_id: proposal?.proposal_id,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function extractObjectTypes(objects) {
|
|
71
|
+
const types = new Set();
|
|
72
|
+
for (const obj of objects) {
|
|
73
|
+
const data = obj?.data ?? obj;
|
|
74
|
+
const type = data?.type;
|
|
75
|
+
if (typeof type === "string") {
|
|
76
|
+
const match = type.match(/::(\w+)$/);
|
|
77
|
+
if (match) {
|
|
78
|
+
types.add(match[1]);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return Array.from(types);
|
|
83
|
+
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import type { DiagnosisReport } from "./diagnose.js";
|
|
2
2
|
export type ProposalType = "error_rule_addition" | "intent_rule_addition" | "description_rewrite" | "skill_creation" | "recovery_priority_adjustment" | "investigation" | "industry_update_application";
|
|
3
3
|
export type AutomationLevel = "full" | "semi" | "manual";
|
|
4
|
+
export type ApplyMode = "config_override" | "source_patch";
|
|
4
5
|
export interface ImprovementProposal {
|
|
5
6
|
proposal_id: string;
|
|
6
7
|
source_diagnosis_id: string;
|
|
7
8
|
type: ProposalType;
|
|
8
9
|
priority: string;
|
|
9
10
|
automation: AutomationLevel;
|
|
11
|
+
apply_mode: ApplyMode;
|
|
12
|
+
override_category?: OverrideCategory;
|
|
10
13
|
title: string;
|
|
11
14
|
description: string;
|
|
12
15
|
target: string;
|
|
@@ -14,7 +17,10 @@ export interface ImprovementProposal {
|
|
|
14
17
|
evidence: Record<string, unknown>;
|
|
15
18
|
review_status: "pending" | "approved" | "rejected" | "applied";
|
|
16
19
|
ab_test_recommended: boolean;
|
|
20
|
+
persisted_at?: string;
|
|
21
|
+
reviewed_at?: string;
|
|
17
22
|
}
|
|
23
|
+
export type OverrideCategory = "risk-thresholds" | "descriptions" | "industry-profiles" | "scenario-defaults" | "recovery-priorities";
|
|
18
24
|
export interface ImprovementReport {
|
|
19
25
|
report_id: string;
|
|
20
26
|
generated_date: string;
|
|
@@ -24,3 +30,26 @@ export interface ImprovementReport {
|
|
|
24
30
|
summary: string;
|
|
25
31
|
}
|
|
26
32
|
export declare function generateImprovements(report: DiagnosisReport): ImprovementReport;
|
|
33
|
+
export declare function persistImprovementQueue(proposals: ImprovementProposal[]): number;
|
|
34
|
+
export interface QueueFilter {
|
|
35
|
+
status?: "pending" | "approved" | "rejected" | "applied";
|
|
36
|
+
type?: string;
|
|
37
|
+
priority?: string;
|
|
38
|
+
}
|
|
39
|
+
export declare function loadImprovementQueue(filter?: QueueFilter): ImprovementProposal[];
|
|
40
|
+
export declare function updateProposalReviewStatus(proposalId: string, newStatus: "approved" | "rejected" | "applied"): ImprovementProposal | undefined;
|
|
41
|
+
export declare function applyConfigOverride(proposal: ImprovementProposal): string;
|
|
42
|
+
export declare function produceSourcePatch(proposal: ImprovementProposal): string;
|
|
43
|
+
export interface FlywheelConfigSummary {
|
|
44
|
+
queue_path: string;
|
|
45
|
+
overrides_dir: string;
|
|
46
|
+
patches_dir: string;
|
|
47
|
+
total_proposals: number;
|
|
48
|
+
pending_count: number;
|
|
49
|
+
approved_count: number;
|
|
50
|
+
applied_count: number;
|
|
51
|
+
rejected_count: number;
|
|
52
|
+
override_files: string[];
|
|
53
|
+
recent_proposals: ImprovementProposal[];
|
|
54
|
+
}
|
|
55
|
+
export declare function getFlywheelConfigSummary(): FlywheelConfigSummary;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { getPendingSuggestions } from "../knowledge/flywheel-loop.js";
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, appendFileSync, readdirSync } from "fs";
|
|
3
|
+
import { join, dirname } from "path";
|
|
4
|
+
import { homedir } from "os";
|
|
2
5
|
function proposeErrorRuleAddition(diagnosis) {
|
|
3
6
|
const evidence = diagnosis.evidence;
|
|
4
7
|
const topMessages = evidence.top_error_messages || [];
|
|
@@ -20,6 +23,7 @@ function proposeErrorRuleAddition(diagnosis) {
|
|
|
20
23
|
type: "error_rule_addition",
|
|
21
24
|
priority: diagnosis.severity,
|
|
22
25
|
automation: "semi",
|
|
26
|
+
apply_mode: "source_patch",
|
|
23
27
|
title: `Add ERROR_RULES entries for ${diagnosis.target}`,
|
|
24
28
|
description: `Generate new error classification rules to cover patterns currently falling into 'unknown'. AI should draft regex patterns; human reviewer validates accuracy and assigns correct error_code.`,
|
|
25
29
|
target: "ERROR_RULES",
|
|
@@ -47,6 +51,8 @@ function proposeDescriptionRewrite(diagnosis) {
|
|
|
47
51
|
type: "description_rewrite",
|
|
48
52
|
priority: diagnosis.severity,
|
|
49
53
|
automation: "semi",
|
|
54
|
+
apply_mode: "config_override",
|
|
55
|
+
override_category: "descriptions",
|
|
50
56
|
title: `Rewrite description for ${evidence.tool_name || diagnosis.target}`,
|
|
51
57
|
description: `The semantic layer produces no summary for ${((1 - (evidence.semantic_hit_rate || 0)) * 100).toFixed(1)}% of calls to this tool. AI should rewrite the tool description and INTENT_RULES to improve coverage. A/B test before merging.`,
|
|
52
58
|
target: diagnosis.target,
|
|
@@ -73,6 +79,7 @@ function proposeSkillCreation(diagnosis) {
|
|
|
73
79
|
type: "skill_creation",
|
|
74
80
|
priority: diagnosis.severity,
|
|
75
81
|
automation: "semi",
|
|
82
|
+
apply_mode: "source_patch",
|
|
76
83
|
title: `Create new Skill for '${evidence.operation_type}' operations`,
|
|
77
84
|
description: `This operation type has a ${(evidence.success_rate ? (1 - evidence.success_rate) * 100 : 0).toFixed(1)}% failure rate across ${evidence.total_calls} calls. A Skill with R1-R10 dialogue scripts, decision trees, and failure playbooks could guide users to success.`,
|
|
78
85
|
target: `wowok-${evidence.operation_type}-guide`,
|
|
@@ -99,6 +106,8 @@ function proposeRecoveryAdjustment(diagnosis) {
|
|
|
99
106
|
type: "recovery_priority_adjustment",
|
|
100
107
|
priority: diagnosis.severity,
|
|
101
108
|
automation: "semi",
|
|
109
|
+
apply_mode: "config_override",
|
|
110
|
+
override_category: "recovery-priorities",
|
|
102
111
|
title: `Review recovery strategy for '${evidence.error_code}' errors`,
|
|
103
112
|
description: `Error code '${evidence.error_code}' accounts for ${evidence.count} failures (${((evidence.percentage || 0) * 100).toFixed(1)}%). The current recovery strategy may need tuning — consider increasing max_attempts, adjusting automation level, or addressing the root cause.`,
|
|
104
113
|
target: `RECOVERY_RULES['${evidence.error_code}']`,
|
|
@@ -124,6 +133,7 @@ function proposeInvestigation(diagnosis) {
|
|
|
124
133
|
type: "investigation",
|
|
125
134
|
priority: diagnosis.severity,
|
|
126
135
|
automation: "manual",
|
|
136
|
+
apply_mode: "source_patch",
|
|
127
137
|
title: diagnosis.title,
|
|
128
138
|
description: `Manual investigation required. ${diagnosis.description}`,
|
|
129
139
|
target: diagnosis.target,
|
|
@@ -162,6 +172,8 @@ function proposeIndustryUpdate(diagnosis) {
|
|
|
162
172
|
type: "industry_update_application",
|
|
163
173
|
priority: diagnosis.severity,
|
|
164
174
|
automation: isHealthCritical ? "semi" : "manual",
|
|
175
|
+
apply_mode: "config_override",
|
|
176
|
+
override_category: "industry-profiles",
|
|
165
177
|
title: `Apply ${pendingSuggestions.length} evolution suggestions for industry '${industry}'`,
|
|
166
178
|
description: `Industry '${industry}' has health anomaly (health score ${evidence.health_score ?? "N/A"}, level ${evidence.health_level ?? "N/A"}). ` +
|
|
167
179
|
`Has ${pendingSuggestions.length} pending evolution suggestions (${(evidence.high_priority_count ?? 0)} high priority). ` +
|
|
@@ -218,6 +230,11 @@ export function generateImprovements(report) {
|
|
|
218
230
|
const summary = `${proposals.length} proposals generated from ${report.total_diagnoses} diagnoses. ` +
|
|
219
231
|
`${p0Count} P0, ${semiCount} semi-automatic, ${abTestCount} recommend A/B testing. ` +
|
|
220
232
|
`All proposals require human review before application.`;
|
|
233
|
+
try {
|
|
234
|
+
persistImprovementQueue(proposals);
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
}
|
|
221
238
|
return {
|
|
222
239
|
report_id: `IMPROVE-REPORT-${Date.now()}`,
|
|
223
240
|
generated_date: new Date().toISOString(),
|
|
@@ -227,3 +244,164 @@ export function generateImprovements(report) {
|
|
|
227
244
|
summary,
|
|
228
245
|
};
|
|
229
246
|
}
|
|
247
|
+
function wowokRootDir() {
|
|
248
|
+
return process.env.WOWOK_CONFIG_DIR
|
|
249
|
+
? process.env.WOWOK_CONFIG_DIR
|
|
250
|
+
: join(homedir(), ".wowok");
|
|
251
|
+
}
|
|
252
|
+
function improvementQueuePath() {
|
|
253
|
+
return join(wowokRootDir(), "improvement-queue.jsonl");
|
|
254
|
+
}
|
|
255
|
+
function overridesDir() {
|
|
256
|
+
return join(wowokRootDir(), "overrides");
|
|
257
|
+
}
|
|
258
|
+
function patchesDir() {
|
|
259
|
+
return join(wowokRootDir(), "patches");
|
|
260
|
+
}
|
|
261
|
+
export function persistImprovementQueue(proposals) {
|
|
262
|
+
if (proposals.length === 0)
|
|
263
|
+
return 0;
|
|
264
|
+
const queuePath = improvementQueuePath();
|
|
265
|
+
mkdirSync(dirname(queuePath), { recursive: true });
|
|
266
|
+
const now = new Date().toISOString();
|
|
267
|
+
const lines = proposals.map((p) => JSON.stringify({ ...p, persisted_at: now }));
|
|
268
|
+
appendFileSync(queuePath, lines.join("\n") + "\n", "utf-8");
|
|
269
|
+
return proposals.length;
|
|
270
|
+
}
|
|
271
|
+
export function loadImprovementQueue(filter) {
|
|
272
|
+
const queuePath = improvementQueuePath();
|
|
273
|
+
if (!existsSync(queuePath))
|
|
274
|
+
return [];
|
|
275
|
+
const raw = readFileSync(queuePath, "utf-8");
|
|
276
|
+
const lines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
277
|
+
const proposals = [];
|
|
278
|
+
for (const line of lines) {
|
|
279
|
+
try {
|
|
280
|
+
const p = JSON.parse(line);
|
|
281
|
+
if (filter?.status && p.review_status !== filter.status)
|
|
282
|
+
continue;
|
|
283
|
+
if (filter?.type && p.type !== filter.type)
|
|
284
|
+
continue;
|
|
285
|
+
if (filter?.priority && p.priority !== filter.priority)
|
|
286
|
+
continue;
|
|
287
|
+
proposals.push(p);
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return proposals;
|
|
293
|
+
}
|
|
294
|
+
export function updateProposalReviewStatus(proposalId, newStatus) {
|
|
295
|
+
const all = loadImprovementQueue();
|
|
296
|
+
let updated;
|
|
297
|
+
const now = new Date().toISOString();
|
|
298
|
+
for (const p of all) {
|
|
299
|
+
if (p.proposal_id === proposalId) {
|
|
300
|
+
p.review_status = newStatus;
|
|
301
|
+
p.reviewed_at = now;
|
|
302
|
+
updated = p;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (!updated)
|
|
306
|
+
return undefined;
|
|
307
|
+
const queuePath = improvementQueuePath();
|
|
308
|
+
if (all.length === 0) {
|
|
309
|
+
writeFileSync(queuePath, "", "utf-8");
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
const lines = all.map((p) => JSON.stringify(p));
|
|
313
|
+
writeFileSync(queuePath, lines.join("\n") + "\n", "utf-8");
|
|
314
|
+
}
|
|
315
|
+
return updated;
|
|
316
|
+
}
|
|
317
|
+
export function applyConfigOverride(proposal) {
|
|
318
|
+
if (proposal.apply_mode !== "config_override") {
|
|
319
|
+
throw new Error(`Proposal ${proposal.proposal_id} has apply_mode=${proposal.apply_mode}, not config_override`);
|
|
320
|
+
}
|
|
321
|
+
if (!proposal.override_category) {
|
|
322
|
+
throw new Error(`Proposal ${proposal.proposal_id} has no override_category`);
|
|
323
|
+
}
|
|
324
|
+
const dir = overridesDir();
|
|
325
|
+
mkdirSync(dir, { recursive: true });
|
|
326
|
+
const filePath = join(dir, `${proposal.override_category}.json`);
|
|
327
|
+
let existing = {};
|
|
328
|
+
if (existsSync(filePath)) {
|
|
329
|
+
try {
|
|
330
|
+
existing = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
331
|
+
}
|
|
332
|
+
catch {
|
|
333
|
+
existing = {};
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
const merged = { ...existing, ...proposal.proposed_change, _last_applied_proposal: proposal.proposal_id, _last_applied_at: new Date().toISOString() };
|
|
337
|
+
writeFileSync(filePath, JSON.stringify(merged, null, 2), "utf-8");
|
|
338
|
+
return filePath;
|
|
339
|
+
}
|
|
340
|
+
export function produceSourcePatch(proposal) {
|
|
341
|
+
if (proposal.apply_mode !== "source_patch") {
|
|
342
|
+
throw new Error(`Proposal ${proposal.proposal_id} has apply_mode=${proposal.apply_mode}, not source_patch`);
|
|
343
|
+
}
|
|
344
|
+
const dir = patchesDir();
|
|
345
|
+
mkdirSync(dir, { recursive: true });
|
|
346
|
+
const baseName = `${proposal.proposal_id}.md`;
|
|
347
|
+
const filePath = join(dir, baseName);
|
|
348
|
+
const content = [
|
|
349
|
+
`# Source Patch Proposal: ${proposal.title}`,
|
|
350
|
+
"",
|
|
351
|
+
`- **Proposal ID**: ${proposal.proposal_id}`,
|
|
352
|
+
`- **Type**: ${proposal.type}`,
|
|
353
|
+
`- **Priority**: ${proposal.priority}`,
|
|
354
|
+
`- **Target**: ${proposal.target}`,
|
|
355
|
+
`- **Generated**: ${new Date().toISOString()}`,
|
|
356
|
+
"",
|
|
357
|
+
"## Description",
|
|
358
|
+
proposal.description,
|
|
359
|
+
"",
|
|
360
|
+
"## Proposed Change",
|
|
361
|
+
"```json",
|
|
362
|
+
JSON.stringify(proposal.proposed_change, null, 2),
|
|
363
|
+
"```",
|
|
364
|
+
"",
|
|
365
|
+
"## Evidence",
|
|
366
|
+
"```json",
|
|
367
|
+
JSON.stringify(proposal.evidence, null, 2),
|
|
368
|
+
"```",
|
|
369
|
+
"",
|
|
370
|
+
"## Application",
|
|
371
|
+
"This proposal requires manual review and merge into the MCP source code.",
|
|
372
|
+
"Do NOT auto-apply. After merging, republish the MCP server.",
|
|
373
|
+
"",
|
|
374
|
+
"## Override Whiteline (§4.4)",
|
|
375
|
+
"This proposal type is NOT in the config_override whitelist and must go",
|
|
376
|
+
"through source patch (risk rules, skill structure, schema fields).",
|
|
377
|
+
].join("\n");
|
|
378
|
+
writeFileSync(filePath, content, "utf-8");
|
|
379
|
+
return filePath;
|
|
380
|
+
}
|
|
381
|
+
export function getFlywheelConfigSummary() {
|
|
382
|
+
const all = loadImprovementQueue();
|
|
383
|
+
const overrideFiles = [];
|
|
384
|
+
const oDir = overridesDir();
|
|
385
|
+
if (existsSync(oDir)) {
|
|
386
|
+
try {
|
|
387
|
+
for (const f of readdirSync(oDir)) {
|
|
388
|
+
if (f.endsWith(".json"))
|
|
389
|
+
overrideFiles.push(f);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
catch {
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return {
|
|
396
|
+
queue_path: improvementQueuePath(),
|
|
397
|
+
overrides_dir: oDir,
|
|
398
|
+
patches_dir: patchesDir(),
|
|
399
|
+
total_proposals: all.length,
|
|
400
|
+
pending_count: all.filter((p) => p.review_status === "pending").length,
|
|
401
|
+
approved_count: all.filter((p) => p.review_status === "approved").length,
|
|
402
|
+
applied_count: all.filter((p) => p.review_status === "applied").length,
|
|
403
|
+
rejected_count: all.filter((p) => p.review_status === "rejected").length,
|
|
404
|
+
override_files: overrideFiles,
|
|
405
|
+
recent_proposals: all.slice(-5),
|
|
406
|
+
};
|
|
407
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { ProjectOperationInputSchema } from "../schema/project/index.js";
|
|
3
|
+
import { type ContextCollectionResult } from "../loop-engineering/context-collect.js";
|
|
4
|
+
type ValidatedInput = z.infer<typeof ProjectOperationInputSchema>;
|
|
5
|
+
export interface AssembleContextResult {
|
|
6
|
+
action: "assemble_context";
|
|
7
|
+
objects: unknown[];
|
|
8
|
+
events?: unknown[];
|
|
9
|
+
embedded_history?: Record<string, unknown>;
|
|
10
|
+
semantic_summary?: unknown;
|
|
11
|
+
context_digest: string;
|
|
12
|
+
next_action: string;
|
|
13
|
+
flywheel_collected?: ContextCollectionResult;
|
|
14
|
+
}
|
|
15
|
+
export declare function assembleContext(validated: ValidatedInput): Promise<AssembleContextResult>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { createHash } from "crypto";
|
|
2
|
+
import { query_objects, query_events } from "@wowok/wowok";
|
|
3
|
+
import { buildDataSemantic } from "../schema/call/semantic.js";
|
|
4
|
+
import { collectContextExperience } from "../loop-engineering/context-collect.js";
|
|
5
|
+
const STATE_TRANSITION_EVENTS = [
|
|
6
|
+
"NewOrderEvent",
|
|
7
|
+
"ProgressEvent",
|
|
8
|
+
"ArbEvent",
|
|
9
|
+
"DemandPresentEvent",
|
|
10
|
+
"DemandFeedbackEvent",
|
|
11
|
+
"NewEntityEvent",
|
|
12
|
+
];
|
|
13
|
+
export async function assembleContext(validated) {
|
|
14
|
+
const contextObjects = validated.context_objects;
|
|
15
|
+
if (!contextObjects || contextObjects.length === 0) {
|
|
16
|
+
throw new Error("assemble_context requires 'context_objects' — an array of object IDs or LocalMark names.");
|
|
17
|
+
}
|
|
18
|
+
const network = (validated.context_network ?? "testnet");
|
|
19
|
+
const includeEvents = validated.include_events ?? false;
|
|
20
|
+
const objectsResult = await query_objects({
|
|
21
|
+
objects: contextObjects,
|
|
22
|
+
no_cache: false,
|
|
23
|
+
network,
|
|
24
|
+
});
|
|
25
|
+
const objects = objectsResult?.objects ?? [];
|
|
26
|
+
const embeddedHistory = extractEmbeddedHistory(objects);
|
|
27
|
+
const hasEmbeddedHistory = Object.keys(embeddedHistory).length > 0;
|
|
28
|
+
let events;
|
|
29
|
+
if (includeEvents) {
|
|
30
|
+
events = [];
|
|
31
|
+
for (const eventType of STATE_TRANSITION_EVENTS) {
|
|
32
|
+
try {
|
|
33
|
+
const eventResult = await query_events({
|
|
34
|
+
type: eventType,
|
|
35
|
+
limit: 5,
|
|
36
|
+
order: "descending",
|
|
37
|
+
network,
|
|
38
|
+
});
|
|
39
|
+
if (eventResult?.data && eventResult.data.length > 0) {
|
|
40
|
+
events.push(...eventResult.data);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (events.length === 0) {
|
|
47
|
+
events = undefined;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const semanticCtx = {
|
|
51
|
+
operation_type: "assemble_context",
|
|
52
|
+
data: { context_objects: objects, embedded_history: embeddedHistory, events },
|
|
53
|
+
};
|
|
54
|
+
const semanticSummary = buildDataSemantic({ objects, embedded_history: embeddedHistory, events }, semanticCtx);
|
|
55
|
+
const digestParts = objects.map((obj) => `${obj?.object ?? obj?.data?.object ?? "?"}:${obj?.version ?? obj?.data?.version ?? "?"}`);
|
|
56
|
+
digestParts.push(`ts:${Date.now()}`);
|
|
57
|
+
const contextDigest = createHash("sha256")
|
|
58
|
+
.update(digestParts.join("|"))
|
|
59
|
+
.digest("hex")
|
|
60
|
+
.substring(0, 16);
|
|
61
|
+
const nextAction = hasEmbeddedHistory
|
|
62
|
+
? "Context assembled with embedded operation history. Use onchain_transaction with a specific digest to verify a past operation, or proceed with onchain_operations (consider dry_run=true first to validate)."
|
|
63
|
+
: events && events.length > 0
|
|
64
|
+
? "Context assembled with recent events. Use onchain_transaction with a specific digest to verify any event's tx, or proceed with onchain_operations."
|
|
65
|
+
: "Context assembled (current state only). Proceed with onchain_operations (consider dry_run=true first to validate).";
|
|
66
|
+
let flywheelCollected;
|
|
67
|
+
try {
|
|
68
|
+
flywheelCollected = collectContextExperience({
|
|
69
|
+
action: "assemble_context",
|
|
70
|
+
objects,
|
|
71
|
+
events,
|
|
72
|
+
embedded_history: hasEmbeddedHistory ? embeddedHistory : undefined,
|
|
73
|
+
semantic_summary: semanticSummary,
|
|
74
|
+
context_digest: contextDigest,
|
|
75
|
+
next_action: nextAction,
|
|
76
|
+
}, network);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
action: "assemble_context",
|
|
82
|
+
objects,
|
|
83
|
+
events,
|
|
84
|
+
embedded_history: hasEmbeddedHistory ? embeddedHistory : undefined,
|
|
85
|
+
semantic_summary: semanticSummary,
|
|
86
|
+
context_digest: contextDigest,
|
|
87
|
+
next_action: nextAction,
|
|
88
|
+
flywheel_collected: flywheelCollected,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function extractEmbeddedHistory(objects) {
|
|
92
|
+
const history = {};
|
|
93
|
+
for (const obj of objects) {
|
|
94
|
+
const data = obj?.data ?? obj;
|
|
95
|
+
const objectId = obj?.object ?? data?.object;
|
|
96
|
+
if (!objectId)
|
|
97
|
+
continue;
|
|
98
|
+
const objectType = data?.type ?? "";
|
|
99
|
+
const extracted = {};
|
|
100
|
+
if (objectType.includes("Progress") && data?.session?.forwards) {
|
|
101
|
+
extracted.operation_history = data.session.forwards.map((f) => ({
|
|
102
|
+
operation: f.forward,
|
|
103
|
+
operator: f.who,
|
|
104
|
+
accomplished: f.accomplished,
|
|
105
|
+
time: f.time,
|
|
106
|
+
message: f.msg,
|
|
107
|
+
}));
|
|
108
|
+
extracted.next_node = data.session?.next_node;
|
|
109
|
+
extracted.threshold = data.session?.threshold;
|
|
110
|
+
}
|
|
111
|
+
if (objectType.includes("Order")) {
|
|
112
|
+
if (data?.dispute && Array.isArray(data.dispute) && data.dispute.length > 0) {
|
|
113
|
+
extracted.disputes = data.dispute;
|
|
114
|
+
}
|
|
115
|
+
if (data?.claimed_by) {
|
|
116
|
+
extracted.claimed_by = data.claimed_by;
|
|
117
|
+
}
|
|
118
|
+
if (data?.progress) {
|
|
119
|
+
extracted.progress_object = data.progress;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (objectType.includes("Service") && data?.sales) {
|
|
123
|
+
extracted.sale_count = Array.isArray(data.sales) ? data.sales.length : 0;
|
|
124
|
+
}
|
|
125
|
+
if (Object.keys(extracted).length > 0) {
|
|
126
|
+
history[objectId] = extracted;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return history;
|
|
130
|
+
}
|