mcp-cognition-engine 1.0.0-alpha.1
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/LICENSE +201 -0
- package/README.md +281 -0
- package/dist/cli.d.ts +18 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +66 -0
- package/dist/cli.js.map +1 -0
- package/dist/cognition-engine/ast-constraint-solver.d.ts +67 -0
- package/dist/cognition-engine/ast-constraint-solver.d.ts.map +1 -0
- package/dist/cognition-engine/ast-constraint-solver.js +294 -0
- package/dist/cognition-engine/ast-constraint-solver.js.map +1 -0
- package/dist/cognition-engine/constraint-validator.d.ts +35 -0
- package/dist/cognition-engine/constraint-validator.d.ts.map +1 -0
- package/dist/cognition-engine/constraint-validator.js +55 -0
- package/dist/cognition-engine/constraint-validator.js.map +1 -0
- package/dist/cognition-engine/graph-traverser.d.ts +43 -0
- package/dist/cognition-engine/graph-traverser.d.ts.map +1 -0
- package/dist/cognition-engine/graph-traverser.js +205 -0
- package/dist/cognition-engine/graph-traverser.js.map +1 -0
- package/dist/cognition-engine/index.d.ts +51 -0
- package/dist/cognition-engine/index.d.ts.map +1 -0
- package/dist/cognition-engine/index.js +60 -0
- package/dist/cognition-engine/index.js.map +1 -0
- package/dist/cognition-engine/intent-recognizer.d.ts +25 -0
- package/dist/cognition-engine/intent-recognizer.d.ts.map +1 -0
- package/dist/cognition-engine/intent-recognizer.js +226 -0
- package/dist/cognition-engine/intent-recognizer.js.map +1 -0
- package/dist/cognition-engine/types.d.ts +96 -0
- package/dist/cognition-engine/types.d.ts.map +1 -0
- package/dist/cognition-engine/types.js +17 -0
- package/dist/cognition-engine/types.js.map +1 -0
- package/dist/conflict/arbitrator.d.ts +24 -0
- package/dist/conflict/arbitrator.d.ts.map +1 -0
- package/dist/conflict/arbitrator.js +43 -0
- package/dist/conflict/arbitrator.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +90 -0
- package/dist/index.js.map +1 -0
- package/dist/legacy-engine/ast-diff.d.ts +23 -0
- package/dist/legacy-engine/ast-diff.d.ts.map +1 -0
- package/dist/legacy-engine/ast-diff.js +146 -0
- package/dist/legacy-engine/ast-diff.js.map +1 -0
- package/dist/legacy-engine/ast-node.d.ts +24 -0
- package/dist/legacy-engine/ast-node.d.ts.map +1 -0
- package/dist/legacy-engine/ast-node.js +52 -0
- package/dist/legacy-engine/ast-node.js.map +1 -0
- package/dist/legacy-engine/parsers.d.ts +34 -0
- package/dist/legacy-engine/parsers.d.ts.map +1 -0
- package/dist/legacy-engine/parsers.js +134 -0
- package/dist/legacy-engine/parsers.js.map +1 -0
- package/dist/legacy-engine/regex-fallback.d.ts +23 -0
- package/dist/legacy-engine/regex-fallback.d.ts.map +1 -0
- package/dist/legacy-engine/regex-fallback.js +40 -0
- package/dist/legacy-engine/regex-fallback.js.map +1 -0
- package/dist/legacy-engine/rule-generator.d.ts +31 -0
- package/dist/legacy-engine/rule-generator.d.ts.map +1 -0
- package/dist/legacy-engine/rule-generator.js +54 -0
- package/dist/legacy-engine/rule-generator.js.map +1 -0
- package/dist/legacy-engine/rule-matcher.d.ts +28 -0
- package/dist/legacy-engine/rule-matcher.d.ts.map +1 -0
- package/dist/legacy-engine/rule-matcher.js +79 -0
- package/dist/legacy-engine/rule-matcher.js.map +1 -0
- package/dist/legacy-engine/token-controller.d.ts +31 -0
- package/dist/legacy-engine/token-controller.d.ts.map +1 -0
- package/dist/legacy-engine/token-controller.js +66 -0
- package/dist/legacy-engine/token-controller.js.map +1 -0
- package/dist/middleware/response-validation.d.ts +27 -0
- package/dist/middleware/response-validation.d.ts.map +1 -0
- package/dist/middleware/response-validation.js +50 -0
- package/dist/middleware/response-validation.js.map +1 -0
- package/dist/modes/confirm.d.ts +29 -0
- package/dist/modes/confirm.d.ts.map +1 -0
- package/dist/modes/confirm.js +27 -0
- package/dist/modes/confirm.js.map +1 -0
- package/dist/modes/silent.d.ts +24 -0
- package/dist/modes/silent.d.ts.map +1 -0
- package/dist/modes/silent.js +24 -0
- package/dist/modes/silent.js.map +1 -0
- package/dist/resources/cognition-resources.d.ts +28 -0
- package/dist/resources/cognition-resources.d.ts.map +1 -0
- package/dist/resources/cognition-resources.js +124 -0
- package/dist/resources/cognition-resources.js.map +1 -0
- package/dist/storage/client.d.ts +26 -0
- package/dist/storage/client.d.ts.map +1 -0
- package/dist/storage/client.js +45 -0
- package/dist/storage/client.js.map +1 -0
- package/dist/storage/cognition-repository.d.ts +55 -0
- package/dist/storage/cognition-repository.d.ts.map +1 -0
- package/dist/storage/cognition-repository.js +287 -0
- package/dist/storage/cognition-repository.js.map +1 -0
- package/dist/storage/cognition-types.d.ts +96 -0
- package/dist/storage/cognition-types.d.ts.map +1 -0
- package/dist/storage/cognition-types.js +41 -0
- package/dist/storage/cognition-types.js.map +1 -0
- package/dist/storage/conflict-repo.d.ts +41 -0
- package/dist/storage/conflict-repo.d.ts.map +1 -0
- package/dist/storage/conflict-repo.js +67 -0
- package/dist/storage/conflict-repo.js.map +1 -0
- package/dist/storage/diff-log-repo.d.ts +48 -0
- package/dist/storage/diff-log-repo.d.ts.map +1 -0
- package/dist/storage/diff-log-repo.js +51 -0
- package/dist/storage/diff-log-repo.js.map +1 -0
- package/dist/storage/metric-repo.d.ts +20 -0
- package/dist/storage/metric-repo.d.ts.map +1 -0
- package/dist/storage/metric-repo.js +36 -0
- package/dist/storage/metric-repo.js.map +1 -0
- package/dist/storage/rule-repo.d.ts +66 -0
- package/dist/storage/rule-repo.d.ts.map +1 -0
- package/dist/storage/rule-repo.js +188 -0
- package/dist/storage/rule-repo.js.map +1 -0
- package/dist/tools/analyze-workspace.d.ts +26 -0
- package/dist/tools/analyze-workspace.d.ts.map +1 -0
- package/dist/tools/analyze-workspace.js +147 -0
- package/dist/tools/analyze-workspace.js.map +1 -0
- package/dist/tools/capture-diff.d.ts +26 -0
- package/dist/tools/capture-diff.d.ts.map +1 -0
- package/dist/tools/capture-diff.js +58 -0
- package/dist/tools/capture-diff.js.map +1 -0
- package/dist/tools/cognition-tools.d.ts +60 -0
- package/dist/tools/cognition-tools.d.ts.map +1 -0
- package/dist/tools/cognition-tools.js +170 -0
- package/dist/tools/cognition-tools.js.map +1 -0
- package/dist/tools/config-tools.d.ts +29 -0
- package/dist/tools/config-tools.d.ts.map +1 -0
- package/dist/tools/config-tools.js +58 -0
- package/dist/tools/config-tools.js.map +1 -0
- package/dist/tools/confirm-rule.d.ts +32 -0
- package/dist/tools/confirm-rule.d.ts.map +1 -0
- package/dist/tools/confirm-rule.js +64 -0
- package/dist/tools/confirm-rule.js.map +1 -0
- package/dist/tools/injection-approval.d.ts +43 -0
- package/dist/tools/injection-approval.d.ts.map +1 -0
- package/dist/tools/injection-approval.js +102 -0
- package/dist/tools/injection-approval.js.map +1 -0
- package/dist/tools/list-rules.d.ts +24 -0
- package/dist/tools/list-rules.d.ts.map +1 -0
- package/dist/tools/list-rules.js +20 -0
- package/dist/tools/list-rules.js.map +1 -0
- package/dist/tools/query-rules.d.ts +25 -0
- package/dist/tools/query-rules.d.ts.map +1 -0
- package/dist/tools/query-rules.js +65 -0
- package/dist/tools/query-rules.js.map +1 -0
- package/dist/tools/resolve-conflict.d.ts +33 -0
- package/dist/tools/resolve-conflict.d.ts.map +1 -0
- package/dist/tools/resolve-conflict.js +35 -0
- package/dist/tools/resolve-conflict.js.map +1 -0
- package/dist/types.d.ts +190 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +50 -0
- package/dist/types.js.map +1 -0
- package/docs/api-reference.md +1229 -0
- package/docs/community/feedback-playbook.md +94 -0
- package/docs/integration-snippets.md +100 -0
- package/docs/mcp-integration-guide.md +151 -0
- package/docs/phase4-mcp-feedback.md +155 -0
- package/docs/trust-governance-protocol.md +72 -0
- package/package.json +74 -0
- package/prisma/schema.prisma +145 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 熊高锐
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { parseToAST } from "../legacy-engine/parsers.js";
|
|
17
|
+
// ── DSL Parser ────────────────────────────────────────────
|
|
18
|
+
/**
|
|
19
|
+
* Parse templateDsl JSON string into AstConstraint array.
|
|
20
|
+
*/
|
|
21
|
+
export function parseConstraintDsl(dsl) {
|
|
22
|
+
try {
|
|
23
|
+
const parsed = JSON.parse(dsl);
|
|
24
|
+
if (Array.isArray(parsed))
|
|
25
|
+
return parsed;
|
|
26
|
+
if (parsed && typeof parsed === "object" && parsed.nodeType) {
|
|
27
|
+
return [parsed];
|
|
28
|
+
}
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// If plain text, try line-based DSL format:
|
|
33
|
+
// NODE:FunctionDeclaration
|
|
34
|
+
// FIELD:name MATCH:{{placeholder}}
|
|
35
|
+
// FIELD:returnType EXISTS:true
|
|
36
|
+
return parseLineBasedDsl(dsl);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function parseLineBasedDsl(dsl) {
|
|
40
|
+
const constraints = [];
|
|
41
|
+
let current = null;
|
|
42
|
+
for (const line of dsl.split("\n")) {
|
|
43
|
+
const trimmed = line.trim();
|
|
44
|
+
if (!trimmed)
|
|
45
|
+
continue;
|
|
46
|
+
if (trimmed.startsWith("NODE:")) {
|
|
47
|
+
if (current)
|
|
48
|
+
constraints.push(current);
|
|
49
|
+
current = { nodeType: trimmed.slice(5).trim(), fields: {} };
|
|
50
|
+
}
|
|
51
|
+
else if (trimmed.startsWith("FIELD:") && current) {
|
|
52
|
+
const rest = trimmed.slice(6);
|
|
53
|
+
const matchMatcher = rest.match(/^(\S+)\s+MATCH:(.+)$/);
|
|
54
|
+
const existsMatcher = rest.match(/^(\S+)\s+EXISTS:(true|false)$/);
|
|
55
|
+
const childTypeMatcher = rest.match(/^(\S+)\s+CHILD_TYPE:(.+)$/);
|
|
56
|
+
if (matchMatcher) {
|
|
57
|
+
current.fields[matchMatcher[1]] = { match: matchMatcher[2] };
|
|
58
|
+
}
|
|
59
|
+
else if (existsMatcher) {
|
|
60
|
+
current.fields[existsMatcher[1]] = { exists: existsMatcher[2] === "true" };
|
|
61
|
+
}
|
|
62
|
+
else if (childTypeMatcher) {
|
|
63
|
+
current.fields[childTypeMatcher[1]] = { childType: childTypeMatcher[2] };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (current)
|
|
68
|
+
constraints.push(current);
|
|
69
|
+
return constraints;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Bind {{placeholder}} values in a constraint to actual AST node text.
|
|
73
|
+
* Walks the AST to find nodes matching each constraint's nodeType,
|
|
74
|
+
* then extracts text values for placeholders.
|
|
75
|
+
*/
|
|
76
|
+
export function bindConstraints(constraints, ast) {
|
|
77
|
+
const bindings = {};
|
|
78
|
+
const bound = constraints.map((c) => ({
|
|
79
|
+
...c,
|
|
80
|
+
fields: Object.fromEntries(Object.entries(c.fields).map(([key, fc]) => {
|
|
81
|
+
const boundFc = { ...fc };
|
|
82
|
+
if (fc.match && fc.match.includes("{{")) {
|
|
83
|
+
const placeholder = fc.match.match(/\{\{(.+?)\}\}/)?.[1];
|
|
84
|
+
if (placeholder) {
|
|
85
|
+
const actualValue = extractFieldValue(ast, c.nodeType, key);
|
|
86
|
+
if (actualValue) {
|
|
87
|
+
bindings[placeholder] = actualValue;
|
|
88
|
+
boundFc.match = fc.match.replace(/\{\{(.+?)\}\}/, actualValue);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return [key, boundFc];
|
|
93
|
+
})),
|
|
94
|
+
}));
|
|
95
|
+
return { bound, bindings };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Extract a field value from an AST node.
|
|
99
|
+
* Simplified: checks node type match, then children for field values.
|
|
100
|
+
*/
|
|
101
|
+
function extractFieldValue(ast, nodeType, field) {
|
|
102
|
+
const matchingNodes = findNodesByType(ast, nodeType);
|
|
103
|
+
if (matchingNodes.length === 0)
|
|
104
|
+
return null;
|
|
105
|
+
const node = matchingNodes[0];
|
|
106
|
+
// Check if any child's type matches the field name
|
|
107
|
+
for (const child of node.children) {
|
|
108
|
+
if (child.type === field) {
|
|
109
|
+
return child.text;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Fallback: return node text itself
|
|
113
|
+
return field === "name" ? node.text : null;
|
|
114
|
+
}
|
|
115
|
+
function findNodesByType(node, type) {
|
|
116
|
+
const results = [];
|
|
117
|
+
if (node.type === type)
|
|
118
|
+
results.push(node);
|
|
119
|
+
for (const child of node.children) {
|
|
120
|
+
results.push(...findNodesByType(child, type));
|
|
121
|
+
}
|
|
122
|
+
return results;
|
|
123
|
+
}
|
|
124
|
+
// ── Constraint Validation ─────────────────────────────────
|
|
125
|
+
/**
|
|
126
|
+
* Validate an AST against a set of bound constraints.
|
|
127
|
+
*
|
|
128
|
+
* @param constraints Parsed + bound AstConstraint array
|
|
129
|
+
* @param nodeId Source cognition node ID (for traceability)
|
|
130
|
+
* @param templateDsl Original template DSL string
|
|
131
|
+
* @param ast Target AST to validate
|
|
132
|
+
* @returns Structured validation result
|
|
133
|
+
*/
|
|
134
|
+
export function validateConstraints(constraints, nodeId, templateDsl, ast) {
|
|
135
|
+
const failures = [];
|
|
136
|
+
for (const constraint of constraints) {
|
|
137
|
+
const matchingNodes = findNodesByType(ast, constraint.nodeType);
|
|
138
|
+
if (matchingNodes.length === 0) {
|
|
139
|
+
failures.push({
|
|
140
|
+
nodeId,
|
|
141
|
+
templateDsl,
|
|
142
|
+
constraintPath: '$.type',
|
|
143
|
+
expected: constraint.nodeType,
|
|
144
|
+
actual: `(no matching node)`,
|
|
145
|
+
});
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
for (const matchingNode of matchingNodes) {
|
|
149
|
+
for (const [fieldName, fieldConstraint] of Object.entries(constraint.fields)) {
|
|
150
|
+
const result = checkFieldConstraint(fieldName, fieldConstraint, matchingNode);
|
|
151
|
+
if (result) {
|
|
152
|
+
failures.push({ nodeId, templateDsl, ...result });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
isValid: failures.length === 0,
|
|
159
|
+
failures,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function checkFieldConstraint(fieldName, fc, node) {
|
|
163
|
+
// Check existence
|
|
164
|
+
if (fc.exists !== undefined) {
|
|
165
|
+
const exists = node.children.some((c) => c.type === fieldName);
|
|
166
|
+
if (fc.exists && !exists) {
|
|
167
|
+
return {
|
|
168
|
+
constraintPath: '$.children.',
|
|
169
|
+
expected: 'exists: true',
|
|
170
|
+
actual: `(child "${fieldName}" not found)`,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Check match (literal or bound placeholder)
|
|
175
|
+
if (fc.match) {
|
|
176
|
+
const actual = node.text;
|
|
177
|
+
if (actual !== fc.match) {
|
|
178
|
+
return {
|
|
179
|
+
constraintPath: '$.text',
|
|
180
|
+
expected: fc.match,
|
|
181
|
+
actual,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Check child type
|
|
186
|
+
if (fc.childType) {
|
|
187
|
+
const hasChild = node.children.some((c) => c.type === fc.childType);
|
|
188
|
+
if (!hasChild) {
|
|
189
|
+
return {
|
|
190
|
+
constraintPath: '$.children.' + fieldName,
|
|
191
|
+
expected: fc.childType,
|
|
192
|
+
actual: `(child "${fc.childType}" not found)`,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Check child count
|
|
197
|
+
if (fc.childCount) {
|
|
198
|
+
const count = node.children.length;
|
|
199
|
+
if (fc.childCount.min !== undefined && count < fc.childCount.min) {
|
|
200
|
+
return {
|
|
201
|
+
constraintPath: '$.children.length',
|
|
202
|
+
expected: '>= ' + fc.childCount.min,
|
|
203
|
+
actual: String(count),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
if (fc.childCount.max !== undefined && count > fc.childCount.max) {
|
|
207
|
+
return {
|
|
208
|
+
constraintPath: '$.children.length',
|
|
209
|
+
expected: '<= ' + fc.childCount.max,
|
|
210
|
+
actual: String(count),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
// ── Transform Patch Generation ────────────────────────────
|
|
217
|
+
/**
|
|
218
|
+
* Generate a transform patch from validation failures.
|
|
219
|
+
* Creates operations that would fix the validation failures.
|
|
220
|
+
*/
|
|
221
|
+
export function generatePatchFromFailures(failures, ast) {
|
|
222
|
+
const patches = new Map();
|
|
223
|
+
for (const failure of failures) {
|
|
224
|
+
const nodeId = failure.nodeId;
|
|
225
|
+
if (!patches.has(nodeId)) {
|
|
226
|
+
patches.set(nodeId, { nodeId, operations: [], description: "" });
|
|
227
|
+
}
|
|
228
|
+
const patch = patches.get(nodeId);
|
|
229
|
+
const ops = [];
|
|
230
|
+
if (failure.actual.includes("(no matching node)")) {
|
|
231
|
+
ops.push({
|
|
232
|
+
type: "INSERT",
|
|
233
|
+
path: "$",
|
|
234
|
+
value: failure.expected,
|
|
235
|
+
originalText: undefined,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
else if (failure.constraintPath === "$.text") {
|
|
239
|
+
ops.push({
|
|
240
|
+
type: "REPLACE",
|
|
241
|
+
path: "$.text",
|
|
242
|
+
value: failure.expected,
|
|
243
|
+
originalText: failure.actual,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
patch.operations.push(...ops);
|
|
247
|
+
const briefDesc = `${failure.constraintPath}: "${failure.actual}" → "${failure.expected}"`;
|
|
248
|
+
patch.description = patch.description
|
|
249
|
+
? `${patch.description}; `
|
|
250
|
+
: briefDesc;
|
|
251
|
+
}
|
|
252
|
+
return [...patches.values()];
|
|
253
|
+
}
|
|
254
|
+
// ── High-level API ────────────────────────────────────────
|
|
255
|
+
/**
|
|
256
|
+
* Run the full constraint-solving pipeline:
|
|
257
|
+
* 1. Parse templateDSL from cognition nodes
|
|
258
|
+
* 2. Parse file content to AST
|
|
259
|
+
* 3. Bind {{placeholder}} values
|
|
260
|
+
* 4. Validate constraints
|
|
261
|
+
* 5. Generate transform patches
|
|
262
|
+
*
|
|
263
|
+
* @param cognitionNodes Nodes with astTemplate to check
|
|
264
|
+
* @param fileContent Source code to validate against
|
|
265
|
+
* @param language Language for AST parsing
|
|
266
|
+
* @returns Validation + patch results
|
|
267
|
+
*/
|
|
268
|
+
export async function solveConstraints(cognitionNodes, fileContent, language) {
|
|
269
|
+
const allValidations = [];
|
|
270
|
+
const allPatches = [];
|
|
271
|
+
const allBindings = {};
|
|
272
|
+
const { ast } = await parseToAST(fileContent, language);
|
|
273
|
+
for (const node of cognitionNodes) {
|
|
274
|
+
if (!node.astTemplate)
|
|
275
|
+
continue;
|
|
276
|
+
const constraints = parseConstraintDsl(node.astTemplate.templateDsl);
|
|
277
|
+
if (constraints.length === 0)
|
|
278
|
+
continue;
|
|
279
|
+
const { bound, bindings } = bindConstraints(constraints, ast);
|
|
280
|
+
Object.assign(allBindings, bindings);
|
|
281
|
+
const validation = validateConstraints(bound, node.id, node.astTemplate.templateDsl, ast);
|
|
282
|
+
allValidations.push(validation);
|
|
283
|
+
if (!validation.isValid) {
|
|
284
|
+
const patches = generatePatchFromFailures(validation.failures, ast);
|
|
285
|
+
allPatches.push(...patches);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return {
|
|
289
|
+
validations: allValidations,
|
|
290
|
+
patches: allPatches,
|
|
291
|
+
boundValues: allBindings,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=ast-constraint-solver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast-constraint-solver.js","sourceRoot":"","sources":["../../src/cognition-engine/ast-constraint-solver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAYH,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAYzD,6DAA6D;AAE7D;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,MAAyB,CAAC;QAC5D,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC5D,OAAO,CAAC,MAAuB,CAAC,CAAC;QACnC,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,4CAA4C;QAC5C,6BAA6B;QAC7B,qCAAqC;QACrC,iCAAiC;QACjC,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAW;IACpC,MAAM,WAAW,GAAoB,EAAE,CAAC;IACxC,IAAI,OAAO,GAAyB,IAAI,CAAC;IAEzC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,SAAS;QAEvB,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,IAAI,OAAO;gBAAE,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvC,OAAO,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QAC9D,CAAC;aAAM,IAAI,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,OAAO,EAAE,CAAC;YACnD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;YACxD,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;YAClE,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAEjE,IAAI,YAAY,EAAE,CAAC;gBACjB,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,CAAC;iBAAM,IAAI,aAAa,EAAE,CAAC;gBACzB,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;YAC7E,CAAC;iBAAM,IAAI,gBAAgB,EAAE,CAAC;gBAC5B,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3E,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,OAAO;QAAE,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvC,OAAO,WAAW,CAAC;AACrB,CAAC;AAUD;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,WAA4B,EAC5B,GAAY;IAEZ,MAAM,QAAQ,GAA2B,EAAE,CAAC;IAE5C,MAAM,KAAK,GAAoB,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACrD,GAAG,CAAC;QACJ,MAAM,EAAE,MAAM,CAAC,WAAW,CACxB,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE;YACzC,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;YAC1B,IAAI,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxC,MAAM,WAAW,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBACzD,IAAI,WAAW,EAAE,CAAC;oBAChB,MAAM,WAAW,GAAG,iBAAiB,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;oBAC5D,IAAI,WAAW,EAAE,CAAC;wBAChB,QAAQ,CAAC,WAAW,CAAC,GAAG,WAAW,CAAC;wBACpC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;oBACjE,CAAC;gBACH,CAAC;YACH,CAAC;YACD,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACxB,CAAC,CAAC,CACH;KACF,CAAC,CAAC,CAAC;IAEJ,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB,CAAC,GAAY,EAAE,QAAgB,EAAE,KAAa;IACtE,MAAM,aAAa,GAAG,eAAe,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACrD,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE5C,MAAM,IAAI,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAC9B,mDAAmD;IACnD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClC,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;IACD,oCAAoC;IACpC,OAAO,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAED,SAAS,eAAe,CAAC,IAAa,EAAE,IAAY;IAClD,MAAM,OAAO,GAAc,EAAE,CAAC;IAC9B,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;QAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,6DAA6D;AAE7D;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,WAA4B,EAC5B,MAAc,EACd,WAAmB,EACnB,GAAY;IAEZ,MAAM,QAAQ,GAAwB,EAAE,CAAC;IAEzC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,MAAM,aAAa,GAAG,eAAe,CAAC,GAAG,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;QAEhE,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM;gBACN,WAAW;gBACX,cAAc,EAAE,QAAQ;gBACxB,QAAQ,EAAE,UAAU,CAAC,QAAQ;gBAC7B,MAAM,EAAE,oBAAoB;aAC7B,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QAED,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;YACzC,KAAK,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC7E,MAAM,MAAM,GAAG,oBAAoB,CAAC,SAAS,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC;gBAC9E,IAAI,MAAM,EAAE,CAAC;oBACX,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;gBACpD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC;QAC9B,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAC3B,SAAiB,EACjB,EAAmB,EACnB,IAAa;IAEb,kBAAkB;IAClB,IAAI,EAAE,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;QAC/D,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;YACzB,OAAO;gBACL,cAAc,EAAE,aAAa;gBAC7B,QAAQ,EAAE,cAAc;gBACxB,MAAM,EAAE,WAAW,SAAS,cAAc;aAC3C,CAAC;QACJ,CAAC;IACH,CAAC;IAED,6CAA6C;IAC7C,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC;QACzB,IAAI,MAAM,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC;YACxB,OAAO;gBACL,cAAc,EAAE,QAAQ;gBACxB,QAAQ,EAAE,EAAE,CAAC,KAAK;gBAClB,MAAM;aACP,CAAC;QACJ,CAAC;IACH,CAAC;IAED,mBAAmB;IACnB,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC;QACjB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,SAAS,CAAC,CAAC;QACpE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;gBACL,cAAc,EAAE,aAAa,GAAG,SAAS;gBACzC,QAAQ,EAAE,EAAE,CAAC,SAAS;gBACtB,MAAM,EAAE,WAAW,EAAE,CAAC,SAAS,cAAc;aAC9C,CAAC;QACJ,CAAC;IACH,CAAC;IAED,oBAAoB;IACpB,IAAI,EAAE,CAAC,UAAU,EAAE,CAAC;QAClB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QACnC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,GAAG,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;YACjE,OAAO;gBACH,cAAc,EAAE,mBAAmB;gBACnC,QAAQ,EAAE,KAAK,GAAG,EAAE,CAAC,UAAU,CAAC,GAAG;gBACrC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC;aACtB,CAAC;QACJ,CAAC;QACD,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,GAAG,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;YACjE,OAAO;gBACL,cAAc,EAAE,mBAAmB;gBACnC,QAAQ,EAAE,KAAK,GAAG,EAAE,CAAC,UAAU,CAAC,GAAG;gBACnC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC;aACtB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6DAA6D;AAE7D;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CACvC,QAA6B,EAC7B,GAAY;IAEZ,MAAM,OAAO,GAAgC,IAAI,GAAG,EAAE,CAAC;IAEvD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC9B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC;QACnC,MAAM,GAAG,GAAkB,EAAE,CAAC;QAE9B,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;YAClD,GAAG,CAAC,IAAI,CAAC;gBACP,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,OAAO,CAAC,QAAQ;gBACvB,YAAY,EAAE,SAAS;aACxB,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,OAAO,CAAC,cAAc,KAAK,QAAQ,EAAE,CAAC;YAC/C,GAAG,CAAC,IAAI,CAAC;gBACP,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,OAAO,CAAC,QAAQ;gBACvB,YAAY,EAAE,OAAO,CAAC,MAAM;aAC7B,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;QAC9B,MAAM,SAAS,GAAG,GAAG,OAAO,CAAC,cAAc,MAAM,OAAO,CAAC,MAAM,QAAQ,OAAO,CAAC,QAAQ,GAAG,CAAC;QAC3F,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW;YACnC,CAAC,CAAC,GAAG,KAAK,CAAC,WAAW,IAAI;YAC1B,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IAED,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AAC/B,CAAC;AAED,6DAA6D;AAE7D;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,cAAmC,EACnC,WAAmB,EACnB,QAAgB;IAMhB,MAAM,cAAc,GAAuB,EAAE,CAAC;IAC9C,MAAM,UAAU,GAAqB,EAAE,CAAC;IACxC,MAAM,WAAW,GAA2B,EAAE,CAAC;IAE/C,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,UAAU,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAExD,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,SAAS;QAEhC,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QACrE,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAEvC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,eAAe,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QAC9D,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAErC,MAAM,UAAU,GAAG,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QAC1F,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAEhC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,yBAAyB,CAAC,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACpE,UAAU,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,OAAO;QACL,WAAW,EAAE,cAAc;QAC3B,OAAO,EAAE,UAAU;QACnB,WAAW,EAAE,WAAW;KACzB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 熊高锐
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
export type ValidationMode = "REJECT" | "WARN";
|
|
17
|
+
export type RuleLevel = "GLOBAL" | "PROJECT";
|
|
18
|
+
export interface ConstraintViolation {
|
|
19
|
+
ruleId: string;
|
|
20
|
+
ruleLevel: RuleLevel;
|
|
21
|
+
mode: ValidationMode;
|
|
22
|
+
constraintPath: string;
|
|
23
|
+
expected: string;
|
|
24
|
+
actual: string;
|
|
25
|
+
message: string;
|
|
26
|
+
}
|
|
27
|
+
export interface ValidationReport {
|
|
28
|
+
passed: boolean;
|
|
29
|
+
violations: ConstraintViolation[];
|
|
30
|
+
hardBlocks: number;
|
|
31
|
+
softWarnings: number;
|
|
32
|
+
}
|
|
33
|
+
/** Validate code content against constraints. */
|
|
34
|
+
export declare function validateCode(codeContent: string, language: string, projectId?: string): Promise<ValidationReport>;
|
|
35
|
+
//# sourceMappingURL=constraint-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constraint-validator.d.ts","sourceRoot":"","sources":["../../src/cognition-engine/constraint-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AASH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,MAAM,CAAC;AAC/C,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE7C,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,SAAS,CAAC;IACrB,IAAI,EAAE,cAAc,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,iDAAiD;AACjD,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAqBvH"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 熊高锐
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* @file Constraint Validator — Trust & Governance Layer
|
|
18
|
+
* Reuses Phase 3 AstTemplate DSL parser for dual-mode validation.
|
|
19
|
+
*/
|
|
20
|
+
import { parseConstraintDsl, validateConstraints } from "../cognition-engine/ast-constraint-solver.js";
|
|
21
|
+
import { CognitionRepository } from "../storage/cognition-repository.js";
|
|
22
|
+
/** Validate code content against constraints. */
|
|
23
|
+
export async function validateCode(codeContent, language, projectId) {
|
|
24
|
+
const repo = new CognitionRepository();
|
|
25
|
+
const violations = [];
|
|
26
|
+
const hash = simpleHash("NEGATIVE_CONSTRAINT:" + language);
|
|
27
|
+
const negativeNodes = await repo.findNodesBySemanticHash(hash);
|
|
28
|
+
let hardBlocks = 0;
|
|
29
|
+
let softWarnings = 0;
|
|
30
|
+
for (const node of negativeNodes) {
|
|
31
|
+
if (!node.astTemplate)
|
|
32
|
+
continue;
|
|
33
|
+
const constraints = parseConstraintDsl(node.astTemplate.templateDsl);
|
|
34
|
+
if (constraints.length === 0)
|
|
35
|
+
continue;
|
|
36
|
+
const { ast } = await import("../legacy-engine/parsers.js").then(m => m.parseToAST(codeContent, language));
|
|
37
|
+
const result = validateConstraints(constraints, node.id, node.astTemplate.templateDsl, ast);
|
|
38
|
+
if (!result.isValid) {
|
|
39
|
+
for (const f of result.failures) {
|
|
40
|
+
violations.push({ ruleId: node.id, ruleLevel: "GLOBAL", mode: "REJECT", constraintPath: f.constraintPath, expected: f.expected, actual: f.actual, message: "Hard block: " + f.constraintPath });
|
|
41
|
+
hardBlocks++;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return { passed: hardBlocks === 0, violations, hardBlocks, softWarnings };
|
|
46
|
+
}
|
|
47
|
+
function simpleHash(s) {
|
|
48
|
+
let hash = 0;
|
|
49
|
+
for (let i = 0; i < s.length; i++) {
|
|
50
|
+
hash = ((hash << 5) - hash) + s.charCodeAt(i);
|
|
51
|
+
hash |= 0;
|
|
52
|
+
}
|
|
53
|
+
return Math.abs(hash).toString(16);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=constraint-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constraint-validator.js","sourceRoot":"","sources":["../../src/cognition-engine/constraint-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;GAGG;AACH,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAC;AACvG,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAsBzE,iDAAiD;AACjD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB,EAAE,QAAgB,EAAE,SAAkB;IAC1F,MAAM,IAAI,GAAG,IAAI,mBAAmB,EAAE,CAAC;IACvC,MAAM,UAAU,GAA0B,EAAE,CAAC;IAC7C,MAAM,IAAI,GAAG,UAAU,CAAC,sBAAsB,GAAG,QAAQ,CAAC,CAAC;IAC3D,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAC/D,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,SAAS;QAChC,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QACrE,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACvC,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC3G,MAAM,MAAM,GAAG,mBAAmB,CAAC,WAAW,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QAC5F,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;gBAChC,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC,cAAc,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC;gBAChM,UAAU,EAAE,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,UAAU,KAAK,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC;AAC5E,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAAC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAAC,IAAI,IAAI,CAAC,CAAC;IAAC,CAAC;IAChG,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 熊高锐
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* @file Graph Traverser
|
|
18
|
+
* Replaces the legacy rule-matcher by performing weighted BFS/DFS traversal
|
|
19
|
+
* over the cognition graph, starting from nodes matching the current code context.
|
|
20
|
+
*
|
|
21
|
+
* Reuses: ast-node.ts (computeSemanticHash-like logic via cognition-repository)
|
|
22
|
+
*/
|
|
23
|
+
import { CognitionRepository } from "../storage/cognition-repository.js";
|
|
24
|
+
import type { TraversalOptions, TraversalResult } from "./types.js";
|
|
25
|
+
export declare class GraphTraverser {
|
|
26
|
+
private repo;
|
|
27
|
+
constructor(repo?: CognitionRepository);
|
|
28
|
+
/**
|
|
29
|
+
* Traverse the cognition graph starting from nodes relevant to the given code context.
|
|
30
|
+
*
|
|
31
|
+
* @param language Programming language (e.g., "typescript", "python")
|
|
32
|
+
* @param filePath File path for context extraction
|
|
33
|
+
* @param content Code snippet or AST signature for semantic matching
|
|
34
|
+
* @param options Traversal options
|
|
35
|
+
* @returns Scored cognition nodes sorted by relevance
|
|
36
|
+
*/
|
|
37
|
+
traverse(language: string, filePath: string, content: string, options?: TraversalOptions, contextHash?: string): Promise<TraversalResult>;
|
|
38
|
+
/** Check if moving from sourceLevel to targetLevel is compatible. */
|
|
39
|
+
private isLevelCompatible;
|
|
40
|
+
/** Compute a relevance score [0, 1] for a frontier entry. */
|
|
41
|
+
private computeNodeScore;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=graph-traverser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-traverser.d.ts","sourceRoot":"","sources":["../../src/cognition-engine/graph-traverser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;GAMG;AAEH,OAAO,EAAE,mBAAmB,EAAuB,MAAM,oCAAoC,CAAC;AAI9F,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAuB,MAAM,YAAY,CAAC;AAoCzF,qBAAa,cAAc;IACzB,OAAO,CAAC,IAAI,CAAsB;gBAEtB,IAAI,CAAC,EAAE,mBAAmB;IAItC;;;;;;;;OAQG;IACG,QAAQ,CACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,gBAAqB,EAC9B,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,eAAe,CAAC;IA2H3B,qEAAqE;IACrE,OAAO,CAAC,iBAAiB;IAyBzB,6DAA6D;IAC7D,OAAO,CAAC,gBAAgB;CAezB"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 熊高锐
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* @file Graph Traverser
|
|
18
|
+
* Replaces the legacy rule-matcher by performing weighted BFS/DFS traversal
|
|
19
|
+
* over the cognition graph, starting from nodes matching the current code context.
|
|
20
|
+
*
|
|
21
|
+
* Reuses: ast-node.ts (computeSemanticHash-like logic via cognition-repository)
|
|
22
|
+
*/
|
|
23
|
+
import { CognitionRepository, computeSemanticHash } from "../storage/cognition-repository.js";
|
|
24
|
+
// ── Constants ─────────────────────────────────────────────
|
|
25
|
+
/** Edge relation multipliers for weighted traversal. */
|
|
26
|
+
const RELATION_MULTIPLIERS = {
|
|
27
|
+
CAUSES: 1.5,
|
|
28
|
+
PRECEDES: 1.3,
|
|
29
|
+
REFINES: 1.2,
|
|
30
|
+
GENERALIZES: 0.5,
|
|
31
|
+
MUTEX: 0.3,
|
|
32
|
+
};
|
|
33
|
+
/** Intent bias: adjusts abstraction level preference based on intent. */
|
|
34
|
+
const INTENT_BIAS = {
|
|
35
|
+
REFACTOR: [2, 3, 1, 0], // prefer architecture/module level
|
|
36
|
+
BUGFIX: [0, 1, 2, 3], // prefer concrete/function level
|
|
37
|
+
BOILERPLATE: [1, 2, 0, 3], // prefer module/function level
|
|
38
|
+
};
|
|
39
|
+
const DEFAULT_MAX_DEPTH = 5;
|
|
40
|
+
const DEFAULT_MIN_RELEVANCE = 0.1;
|
|
41
|
+
const DEFAULT_MAX_DURATION_MS = 500;
|
|
42
|
+
// ── Graph Traverser ───────────────────────────────────────
|
|
43
|
+
export class GraphTraverser {
|
|
44
|
+
repo;
|
|
45
|
+
constructor(repo) {
|
|
46
|
+
this.repo = repo ?? new CognitionRepository();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Traverse the cognition graph starting from nodes relevant to the given code context.
|
|
50
|
+
*
|
|
51
|
+
* @param language Programming language (e.g., "typescript", "python")
|
|
52
|
+
* @param filePath File path for context extraction
|
|
53
|
+
* @param content Code snippet or AST signature for semantic matching
|
|
54
|
+
* @param options Traversal options
|
|
55
|
+
* @returns Scored cognition nodes sorted by relevance
|
|
56
|
+
*/
|
|
57
|
+
async traverse(language, filePath, content, options = {}, contextHash) {
|
|
58
|
+
const startTime = performance.now();
|
|
59
|
+
const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
|
|
60
|
+
const minRelevance = options.minRelevance ?? DEFAULT_MIN_RELEVANCE;
|
|
61
|
+
const maxDuration = options.maxDurationMs ?? DEFAULT_MAX_DURATION_MS;
|
|
62
|
+
const intentHint = options.intentHint;
|
|
63
|
+
// 1. Compute semantic hash from code content
|
|
64
|
+
const semanticHash = contextHash ?? computeSemanticHash(language + ":" + filePath.split(".").pop(), { contentHash: simpleHash(content) });
|
|
65
|
+
// 2. Find matching nodes in the graph
|
|
66
|
+
const matchedNodes = await this.repo.findNodesBySemanticHash(semanticHash);
|
|
67
|
+
// If no exact match, try a broader search using file extension
|
|
68
|
+
let startNodes = matchedNodes;
|
|
69
|
+
if (startNodes.length === 0) {
|
|
70
|
+
const extHash = computeSemanticHash(language, { ext: filePath.split(".").pop() });
|
|
71
|
+
startNodes = await this.repo.findNodesBySemanticHash(extHash);
|
|
72
|
+
}
|
|
73
|
+
// 3. If still no matches, return empty result
|
|
74
|
+
if (startNodes.length === 0) {
|
|
75
|
+
return {
|
|
76
|
+
nodes: [],
|
|
77
|
+
edges: [],
|
|
78
|
+
durationMs: performance.now() - startTime,
|
|
79
|
+
truncated: false,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// 4. Weighted BFS traversal from matched nodes
|
|
83
|
+
const visitedNodeIds = new Set();
|
|
84
|
+
const visitedEdgeIds = new Set();
|
|
85
|
+
const scoredNodes = new Map();
|
|
86
|
+
const allEdges = new Map();
|
|
87
|
+
const frontier = [];
|
|
88
|
+
// Initialize frontier with start nodes
|
|
89
|
+
for (const node of startNodes) {
|
|
90
|
+
visitedNodeIds.add(node.id);
|
|
91
|
+
frontier.push({
|
|
92
|
+
nodeId: node.id,
|
|
93
|
+
node,
|
|
94
|
+
depth: 0,
|
|
95
|
+
pathWeight: 1.0,
|
|
96
|
+
trace: [],
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
let elapsed = performance.now() - startTime;
|
|
100
|
+
let truncated = false;
|
|
101
|
+
while (frontier.length > 0 && elapsed < maxDuration) {
|
|
102
|
+
// Sort frontier: highest pathWeight first, then lowest depth
|
|
103
|
+
frontier.sort((a, b) => b.pathWeight - a.pathWeight || a.depth - b.depth);
|
|
104
|
+
const current = frontier.shift();
|
|
105
|
+
// Score and store
|
|
106
|
+
const score = this.computeNodeScore(current, intentHint);
|
|
107
|
+
if (score >= minRelevance) {
|
|
108
|
+
scoredNodes.set(current.node.id, {
|
|
109
|
+
node: current.node,
|
|
110
|
+
relevanceScore: score,
|
|
111
|
+
trace: current.trace,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
// Stop at max depth
|
|
115
|
+
if (current.depth >= maxDepth)
|
|
116
|
+
continue;
|
|
117
|
+
// Fetch outgoing edges for this node
|
|
118
|
+
const subgraph = await this.repo.getSubgraph(current.nodeId, 1);
|
|
119
|
+
const outgoingEdges = subgraph.edges.filter(e => e.sourceId === current.nodeId && !visitedEdgeIds.has(e.id));
|
|
120
|
+
for (const edge of outgoingEdges) {
|
|
121
|
+
visitedEdgeIds.add(edge.id);
|
|
122
|
+
allEdges.set(edge.id, edge);
|
|
123
|
+
// Apply abstraction level filter
|
|
124
|
+
const targetNode = subgraph.nodes.find(n => n.id === edge.targetId);
|
|
125
|
+
if (!targetNode)
|
|
126
|
+
continue;
|
|
127
|
+
if (!this.isLevelCompatible(current.node.abstractionLevel, targetNode.abstractionLevel, edge.relation, intentHint)) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
// Apply GENERALIZES pruning
|
|
131
|
+
const multiplier = RELATION_MULTIPLIERS[edge.relation] ?? 0.5;
|
|
132
|
+
if (edge.relation === "GENERALIZES" && current.depth > 1)
|
|
133
|
+
continue;
|
|
134
|
+
if (!visitedNodeIds.has(edge.targetId)) {
|
|
135
|
+
visitedNodeIds.add(edge.targetId);
|
|
136
|
+
frontier.push({
|
|
137
|
+
nodeId: edge.targetId,
|
|
138
|
+
node: targetNode,
|
|
139
|
+
depth: current.depth + 1,
|
|
140
|
+
pathWeight: current.pathWeight * multiplier * Math.max(0.5, edge.weight / 1.0),
|
|
141
|
+
trace: [...current.trace, edge.relation + ' → ' + targetNode.type + ':' + targetNode.abstractionLevel],
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
elapsed = performance.now() - startTime;
|
|
146
|
+
}
|
|
147
|
+
if (frontier.length > 0)
|
|
148
|
+
truncated = true;
|
|
149
|
+
// 5. Sort by score descending
|
|
150
|
+
const sorted = [...scoredNodes.values()]
|
|
151
|
+
.sort((a, b) => b.relevanceScore - a.relevanceScore);
|
|
152
|
+
return {
|
|
153
|
+
nodes: sorted,
|
|
154
|
+
edges: [...allEdges.values()],
|
|
155
|
+
durationMs: performance.now() - startTime,
|
|
156
|
+
truncated,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
// ── Private Helpers ────────────────────────────────────
|
|
160
|
+
/** Check if moving from sourceLevel to targetLevel is compatible. */
|
|
161
|
+
isLevelCompatible(sourceLevel, targetLevel, relation, intentHint) {
|
|
162
|
+
const absDiff = Math.abs(sourceLevel - targetLevel);
|
|
163
|
+
// Always allow same or adjacent levels
|
|
164
|
+
if (absDiff <= 1)
|
|
165
|
+
return true;
|
|
166
|
+
// Jumping from 0→2 or 1→3 (or reverse) needs REFINES connection
|
|
167
|
+
if (absDiff === 2 && relation === "REFINES")
|
|
168
|
+
return true;
|
|
169
|
+
// Intent-based filtering
|
|
170
|
+
if (intentHint) {
|
|
171
|
+
const bias = INTENT_BIAS[intentHint] ?? [0, 1, 2, 3];
|
|
172
|
+
// If target level is prioritized by intent, allow
|
|
173
|
+
if (bias.indexOf(targetLevel) <= bias.indexOf(sourceLevel) + 1)
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
// Skip large level jumps unless explicitly connected
|
|
177
|
+
return absDiff <= 2 && (relation === "CAUSES" || relation === "REFINES");
|
|
178
|
+
}
|
|
179
|
+
/** Compute a relevance score [0, 1] for a frontier entry. */
|
|
180
|
+
computeNodeScore(entry, intentHint) {
|
|
181
|
+
const depthPenalty = 1 - 0.15 * entry.depth;
|
|
182
|
+
const weightScore = Math.min(1, entry.pathWeight / 1.5);
|
|
183
|
+
const levelScore = intentHint
|
|
184
|
+
? 1 - Math.abs(INTENT_BIAS[intentHint].indexOf(entry.node.abstractionLevel) - INTENT_BIAS[intentHint].indexOf(0)) * 0.2
|
|
185
|
+
: 1 - Math.abs(entry.node.abstractionLevel - 1) * 0.15;
|
|
186
|
+
// Base score
|
|
187
|
+
let score = Math.max(0, weightScore * depthPenalty * levelScore);
|
|
188
|
+
// Bonus for nodes with AST templates (more actionable)
|
|
189
|
+
if (entry.node.astTemplate)
|
|
190
|
+
score = Math.min(1, score * 1.2);
|
|
191
|
+
return Math.round(score * 100) / 100;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// ── Utility ───────────────────────────────────────────────
|
|
195
|
+
function simpleHash(s) {
|
|
196
|
+
if (!s)
|
|
197
|
+
return "0";
|
|
198
|
+
let hash = 0;
|
|
199
|
+
for (let i = 0; i < s.length; i++) {
|
|
200
|
+
hash = ((hash << 5) - hash) + s.charCodeAt(i);
|
|
201
|
+
hash |= 0;
|
|
202
|
+
}
|
|
203
|
+
return Math.abs(hash).toString(16);
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=graph-traverser.js.map
|