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,1229 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
Auto-generated from JSDoc comments. Generated: 2026-06-15
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Module: `cognition-engine/ast-constraint-solver`
|
|
8
|
+
|
|
9
|
+
> Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
10
|
+
|
|
11
|
+
### `parseConstraintDsl`
|
|
12
|
+
|
|
13
|
+
Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
/**
|
|
17
|
+
* @file AST Constraint Solver
|
|
18
|
+
* Transforms cognition AstTemplate DSL into executable AST constraints.
|
|
19
|
+
* Outputs structured validation results and transform patches.
|
|
20
|
+
* NEVER generates natural language — all output is machine-readable.
|
|
21
|
+
*
|
|
22
|
+
* Reuses: legacy-engine/ast-node.ts (computeSignature), legacy-engine/parsers.ts (parseToAST)
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { computeSignature } from "../legacy-engine/ast-node.js";
|
|
26
|
+
import { parseToAST } from "../legacy-engine/parsers.js";
|
|
27
|
+
import type { ASTNode, NodeSignature } from "../types.js";
|
|
28
|
+
import type { CognitionNodeData } from "../storage/cognition-types.js";
|
|
29
|
+
import type {
|
|
30
|
+
AstConstraint,
|
|
31
|
+
FieldConstraint,
|
|
32
|
+
ValidationResult,
|
|
33
|
+
ValidationFailure,
|
|
34
|
+
TransformPatch,
|
|
35
|
+
TransformOp,
|
|
36
|
+
} from "./types.js";
|
|
37
|
+
|
|
38
|
+
// ── DSL Parser ────────────────────────────────────────────
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Parse templateDsl JSON string into AstConstraint array.
|
|
42
|
+
*/
|
|
43
|
+
export function parseConstraintDsl
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### `bindConstraints`
|
|
47
|
+
|
|
48
|
+
Map of placeholder → bound value
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
bindings: Record<string, string>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Bind {{placeholder}} values in a constraint to actual AST node text.
|
|
56
|
+
* Walks the AST to find nodes matching each constraint's nodeType,
|
|
57
|
+
* then extracts text values for placeholders.
|
|
58
|
+
*/
|
|
59
|
+
export function bindConstraints
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### `validateConstraints`
|
|
63
|
+
|
|
64
|
+
Extract a field value from an AST node.
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
function extractFieldValue(ast: ASTNode, nodeType: string, field: string): string | null {
|
|
68
|
+
const matchingNodes = findNodesByType(ast, nodeType);
|
|
69
|
+
if (matchingNodes.length === 0) return null;
|
|
70
|
+
|
|
71
|
+
const node = matchingNodes[0];
|
|
72
|
+
// Check if any child's type matches the field name
|
|
73
|
+
for (const child of node.children) {
|
|
74
|
+
if (child.type === field) {
|
|
75
|
+
return child.text;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Fallback: return node text itself
|
|
79
|
+
return field === "name" ? node.text : null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function findNodesByType(node: ASTNode, type: string): ASTNode[] {
|
|
83
|
+
const results: ASTNode[] = [];
|
|
84
|
+
if (node.type === type) results.push(node);
|
|
85
|
+
for (const child of node.children) {
|
|
86
|
+
results.push(...findNodesByType(child, type));
|
|
87
|
+
}
|
|
88
|
+
return results;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ── Constraint Validation ─────────────────────────────────
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Validate an AST against a set of bound constraints.
|
|
95
|
+
*
|
|
96
|
+
* @param constraints Parsed + bound AstConstraint array
|
|
97
|
+
* @param nodeId Source cognition node ID (for traceability)
|
|
98
|
+
* @param templateDsl Original template DSL string
|
|
99
|
+
* @param ast Target AST to validate
|
|
100
|
+
* @returns Structured validation result
|
|
101
|
+
*/
|
|
102
|
+
export function validateConstraints
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### `generatePatchFromFailures`
|
|
106
|
+
|
|
107
|
+
Generate a transform patch from validation failures.
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
export function generatePatchFromFailures
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### `solveConstraints`
|
|
114
|
+
|
|
115
|
+
Run the full constraint-solving pipeline:
|
|
116
|
1. Parse templateDSL from cognition nodes
|
|
1
117
|
2. Parse file content to AST
|
|
2
118
|
3. Bind {{placeholder}} values
|
|
3
119
|
4. Validate constraints
|
|
4
120
|
5. Generate transform patches
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
export async function solveConstraints
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Parameters:**
|
|
127
|
+
|
|
128
|
+
| Name | Description |
|
|
129
|
+
|------|-------------|
|
|
130
|
+
| `cognitionNodes` | Nodes with astTemplate to check |
|
|
131
|
+
| `fileContent` | Source code to validate against |
|
|
132
|
+
| `language` | Language for AST parsing |
|
|
133
|
+
|
|
134
|
+
**Returns:** Validation + patch results
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Module: `cognition-engine/constraint-validator`
|
|
139
|
+
|
|
140
|
+
> Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. / Reuses Phase 3 AstTemplate DSL parser for dual-mode validation. /
|
|
141
|
+
|
|
142
|
+
### `validateCode`
|
|
143
|
+
|
|
144
|
+
Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
/**
|
|
148
|
+
* @file Constraint Validator — Trust & Governance Layer
|
|
149
|
+
* Reuses Phase 3 AstTemplate DSL parser for dual-mode validation.
|
|
150
|
+
*/
|
|
151
|
+
import { parseConstraintDsl, validateConstraints } from "../cognition-engine/ast-constraint-solver.js";
|
|
152
|
+
import { CognitionRepository } from "../storage/cognition-repository.js";
|
|
153
|
+
|
|
154
|
+
export type ValidationMode = "REJECT" | "WARN";
|
|
155
|
+
export type RuleLevel = "GLOBAL" | "PROJECT";
|
|
156
|
+
|
|
157
|
+
export interface ConstraintViolation {
|
|
158
|
+
ruleId: string;
|
|
159
|
+
ruleLevel: RuleLevel;
|
|
160
|
+
mode: ValidationMode;
|
|
161
|
+
constraintPath: string;
|
|
162
|
+
expected: string;
|
|
163
|
+
actual: string;
|
|
164
|
+
message: string;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export interface ValidationReport {
|
|
168
|
+
passed: boolean;
|
|
169
|
+
violations: ConstraintViolation[];
|
|
170
|
+
hardBlocks: number;
|
|
171
|
+
softWarnings: number;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Validate code content against constraints. */
|
|
175
|
+
export async function validateCode
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Module: `cognition-engine/index`
|
|
181
|
+
|
|
182
|
+
> Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
183
|
+
|
|
184
|
+
### `analyzeCodeContext`
|
|
185
|
+
|
|
186
|
+
Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
/**
|
|
190
|
+
* @file Cognition Engine — unified entry point.
|
|
191
|
+
*
|
|
192
|
+
* The cognition engine replaces the legacy rule-matcher with a
|
|
193
|
+
* three-component pipeline:
|
|
194
|
+
*
|
|
195
|
+
* 1. IntentRecognizer — classifies diff type (REFACTOR / BUGFIX / BOILERPLATE)
|
|
196
|
+
* 2. GraphTraverser — weighted BFS over cognition graph
|
|
197
|
+
* 3. AstConstraintSolver — transforms templates into AST-level checks
|
|
198
|
+
*
|
|
199
|
+
* Usage:
|
|
200
|
+
* import { analyzeCodeContext } from "./cognition-engine/index.js";
|
|
201
|
+
* const result = await analyzeCodeContext(lang, path, content);
|
|
202
|
+
*/
|
|
203
|
+
|
|
204
|
+
export { recognizeIntent } from "./intent-recognizer.js";
|
|
205
|
+
export type { IntentResult, IntentType } from "./types.js";
|
|
206
|
+
|
|
207
|
+
export { GraphTraverser } from "./graph-traverser.js";
|
|
208
|
+
export type { TraversalOptions, TraversalResult, ScoredCognitionNode } from "./types.js";
|
|
209
|
+
|
|
210
|
+
export {
|
|
211
|
+
solveConstraints,
|
|
212
|
+
parseConstraintDsl,
|
|
213
|
+
bindConstraints,
|
|
214
|
+
validateConstraints,
|
|
215
|
+
generatePatchFromFailures,
|
|
216
|
+
} from "./ast-constraint-solver.js";
|
|
217
|
+
export type { AstConstraint, FieldConstraint, ValidationResult, TransformPatch } from "./types.js";
|
|
218
|
+
|
|
219
|
+
import { recognizeIntent } from "./intent-recognizer.js";
|
|
220
|
+
import { GraphTraverser } from "./graph-traverser.js";
|
|
221
|
+
import { solveConstraints } from "./ast-constraint-solver.js";
|
|
222
|
+
import type { TraversalResult, ValidationResult, TransformPatch, IntentResult } from "./types.js";
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Full pipeline: analyze diff → traverse graph → solve AST constraints.
|
|
226
|
+
* The one-shot entry point for the cognition engine.
|
|
227
|
+
*/
|
|
228
|
+
export async function analyzeCodeContext
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Module: `cognition-engine/intent-recognizer`
|
|
234
|
+
|
|
235
|
+
> Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
236
|
+
|
|
237
|
+
### `recognizeIntent`
|
|
238
|
+
|
|
239
|
+
Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
/**
|
|
243
|
+
* @file Intent Recognizer
|
|
244
|
+
* Analyzes code diffs and classifies the developer intent behind them.
|
|
245
|
+
* Maps to three intent levels: REFACTOR, BUGFIX, BOILERPLATE.
|
|
246
|
+
* The result biases Graph Traverser traversal strategy.
|
|
247
|
+
*
|
|
248
|
+
* Reuses: legacy-engine/parsers.ts (parseToAST) for optional AST analysis
|
|
249
|
+
*/
|
|
250
|
+
|
|
251
|
+
import { parseToAST } from "../legacy-engine/parsers.js";
|
|
252
|
+
import type { ASTNode } from "../types.js";
|
|
253
|
+
import type { IntentResult, IntentType } from "./types.js";
|
|
254
|
+
|
|
255
|
+
// ── Constants ─────────────────────────────────────────────
|
|
256
|
+
|
|
257
|
+
const REFACTOR_THRESHOLD = { minFiles: 2, minAddedRatio: 0.3, minNodeTypes: 3 };
|
|
258
|
+
const BUGFIX_THRESHOLD = { maxFiles: 2, maxChangedLines: 50, errorKeywordRatio: 0.1 };
|
|
259
|
+
const BOILERPLATE_THRESHOLD = { addRemoveRatio: 5.0, minAddedLines: 20 };
|
|
260
|
+
|
|
261
|
+
const ERROR_KEYWORDS = [
|
|
262
|
+
"error", "undefined", "null", "catch", "throw", "try",
|
|
263
|
+
"fail", "invalid", "missing", "fallback", "guard", "check",
|
|
264
|
+
"assert", "validate", "optional", "??", "?. ", "??=",
|
|
265
|
+
];
|
|
266
|
+
|
|
267
|
+
const REFACTOR_KEYWORDS = [
|
|
268
|
+
"extract", "rename", "move", "split", "merge", "inline",
|
|
269
|
+
"abstract", "interface", "type",
|
|
270
|
+
];
|
|
271
|
+
|
|
272
|
+
// ── Diff Parsing ──────────────────────────────────────────
|
|
273
|
+
|
|
274
|
+
interface DiffStats {
|
|
275
|
+
filesChanged: number;
|
|
276
|
+
addedLines: number;
|
|
277
|
+
removedLines: number;
|
|
278
|
+
perFile: Map<string, { added: number; removed: number }>;
|
|
279
|
+
hunks: number;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function parseDiffStats(diffContent: string): DiffStats {
|
|
283
|
+
const stats: DiffStats = {
|
|
284
|
+
filesChanged: 0,
|
|
285
|
+
addedLines: 0,
|
|
286
|
+
removedLines: 0,
|
|
287
|
+
perFile: new Map(),
|
|
288
|
+
hunks: 0,
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
let currentFile = "unknown";
|
|
292
|
+
for (const line of diffContent.split("\n")) {
|
|
293
|
+
if (line.startsWith("diff --git ")) {
|
|
294
|
+
stats.filesChanged++;
|
|
295
|
+
const match = line.match(/diff --git a\/(.+) b\//);
|
|
296
|
+
if (match) currentFile = match[1];
|
|
297
|
+
if (!stats.perFile.has(currentFile)) {
|
|
298
|
+
stats.perFile.set(currentFile, { added: 0, removed: 0 });
|
|
299
|
+
}
|
|
300
|
+
} else if (line.startsWith("@@ ")) {
|
|
301
|
+
stats.hunks++;
|
|
302
|
+
} else if (line.startsWith("+") && !line.startsWith("+++")) {
|
|
303
|
+
stats.addedLines++;
|
|
304
|
+
const pf = stats.perFile.get(currentFile);
|
|
305
|
+
if (pf) pf.added++;
|
|
306
|
+
} else if (line.startsWith("-") && !line.startsWith("---")) {
|
|
307
|
+
stats.removedLines++;
|
|
308
|
+
const pf = stats.perFile.get(currentFile);
|
|
309
|
+
if (pf) pf.removed++;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return stats;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// ── Node Type Analysis ────────────────────────────────────
|
|
316
|
+
|
|
317
|
+
async function analyzeNodeTypes(
|
|
318
|
+
diffContent: string,
|
|
319
|
+
filePath?: string,
|
|
320
|
+
): Promise<string[]> {
|
|
321
|
+
const nodeTypes = new Set<string>();
|
|
322
|
+
const lines = diffContent.split("\n");
|
|
323
|
+
|
|
324
|
+
// Try AST analysis on file content (best effort)
|
|
325
|
+
if (filePath) {
|
|
326
|
+
for (const line of lines) {
|
|
327
|
+
if (line.startsWith("+") && !line.startsWith("+++")) {
|
|
328
|
+
const code = line.slice(1).trim();
|
|
329
|
+
if (code.length > 3) {
|
|
330
|
+
try {
|
|
331
|
+
const lang = filePath.endsWith(".ts") || filePath.endsWith(".tsx")
|
|
332
|
+
? "typescript" : filePath.endsWith(".py") ? "python" : "javascript";
|
|
333
|
+
const result = await parseToAST(code, lang);
|
|
334
|
+
collectNodeTypes(result.ast, nodeTypes);
|
|
335
|
+
} catch {
|
|
336
|
+
// Silently continue — AST analysis is best-effort
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Fallback: keyword-based detection
|
|
344
|
+
const allText = lines.filter(l => l.startsWith("+") || l.startsWith("-")).join(" ").toLowerCase();
|
|
345
|
+
if (!nodeTypes.size) {
|
|
346
|
+
const keywordMap: Record<string, string[]> = {
|
|
347
|
+
function_declaration: ["function", "=>", "=>"],
|
|
348
|
+
class_declaration: ["class "],
|
|
349
|
+
variable_declaration: ["const ", "let ", "var "],
|
|
350
|
+
if_statement: ["if ", "else "],
|
|
351
|
+
try_statement: ["try ", "catch ", "finally"],
|
|
352
|
+
import_statement: ["import ", "require("],
|
|
353
|
+
export_statement: ["export "],
|
|
354
|
+
interface_declaration: ["interface "],
|
|
355
|
+
type_alias: ["type ", "| ", "& "],
|
|
356
|
+
return_statement: ["return "],
|
|
357
|
+
};
|
|
358
|
+
for (const [nt, keywords] of Object.entries(keywordMap)) {
|
|
359
|
+
if (keywords.some(k => allText.includes(k))) {
|
|
360
|
+
nodeTypes.add(nt);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return [...nodeTypes];
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function collectNodeTypes(node: ASTNode, types: Set<string>): void {
|
|
369
|
+
types.add(node.type);
|
|
370
|
+
for (const child of node.children) {
|
|
371
|
+
collectNodeTypes(child, types);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// ── Intent Classification ─────────────────────────────────
|
|
376
|
+
|
|
377
|
+
function classifyIntent(
|
|
378
|
+
stats: DiffStats,
|
|
379
|
+
nodeTypes: string[],
|
|
380
|
+
diffContent: string,
|
|
381
|
+
): { intent: IntentType; confidence: number; reasoning: string[] } {
|
|
382
|
+
const totalChanged = stats.addedLines + stats.removedLines;
|
|
383
|
+
const addRemoveRatio = stats.removedLines > 0
|
|
384
|
+
? stats.addedLines / stats.removedLines
|
|
385
|
+
: stats.addedLines > 0 ? Infinity : 0;
|
|
386
|
+
const allText = diffContent.toLowerCase();
|
|
387
|
+
const errorHits = ERROR_KEYWORDS.filter(k => allText.includes(k)).length;
|
|
388
|
+
const errorRatio = allText.length > 0 ? errorHits / (allText.split("\n").length) : 0;
|
|
389
|
+
const refactorHits = REFACTOR_KEYWORDS.filter(k => allText.includes(k)).length;
|
|
390
|
+
const uniqueNodeTypes = new Set(nodeTypes);
|
|
391
|
+
|
|
392
|
+
const reasoning: string[] = [];
|
|
393
|
+
let scores = { refactor: 0, bugfix: 0, boilerplate: 0 };
|
|
394
|
+
|
|
395
|
+
// REFACTOR signals
|
|
396
|
+
if (stats.filesChanged >= REFACTOR_THRESHOLD.minFiles) {
|
|
397
|
+
scores.refactor += 0.3;
|
|
398
|
+
reasoning.push(`multi-file change (${stats.filesChanged} files)`);
|
|
399
|
+
}
|
|
400
|
+
if (uniqueNodeTypes.size >= REFACTOR_THRESHOLD.minNodeTypes) {
|
|
401
|
+
scores.refactor += 0.2;
|
|
402
|
+
reasoning.push(`diverse AST types affected (${uniqueNodeTypes.size} types)`);
|
|
403
|
+
}
|
|
404
|
+
if (refactorHits > 2) {
|
|
405
|
+
scores.refactor += 0.2;
|
|
406
|
+
reasoning.push('refactoring keywords detected');
|
|
407
|
+
}
|
|
408
|
+
if (stats.hunks > 3 && stats.filesChanged > 1) {
|
|
409
|
+
scores.refactor += 0.3;
|
|
410
|
+
reasoning.push('cross-module structural changes');
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// BUGFIX signals
|
|
414
|
+
if (totalChanged <= BUGFIX_THRESHOLD.maxChangedLines) {
|
|
415
|
+
scores.bugfix += 0.2;
|
|
416
|
+
reasoning.push(`small change footprint (${totalChanged} lines)`);
|
|
417
|
+
}
|
|
418
|
+
if (stats.filesChanged <= BUGFIX_THRESHOLD.maxFiles) {
|
|
419
|
+
scores.bugfix += 0.1;
|
|
420
|
+
}
|
|
421
|
+
if (errorRatio >= BUGFIX_THRESHOLD.errorKeywordRatio) {
|
|
422
|
+
scores.bugfix += 0.3;
|
|
423
|
+
reasoning.push('error-handling keywords present');
|
|
424
|
+
}
|
|
425
|
+
if (uniqueNodeTypes.has("try_statement") || uniqueNodeTypes.has("if_statement")) {
|
|
426
|
+
scores.bugfix += 0.2;
|
|
427
|
+
reasoning.push(`conditional / guard patterns`);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// BOILERPLATE signals
|
|
431
|
+
if (addRemoveRatio >= BOILERPLATE_THRESHOLD.addRemoveRatio) {
|
|
432
|
+
scores.boilerplate += 0.3;
|
|
433
|
+
reasoning.push(`high add/remove ratio (${addRemoveRatio.toFixed(1)})`);
|
|
434
|
+
}
|
|
435
|
+
if (stats.addedLines >= BOILERPLATE_THRESHOLD.minAddedLines && stats.removedLines < 5) {
|
|
436
|
+
scores.boilerplate += 0.3;
|
|
437
|
+
reasoning.push('net-new code addition');
|
|
438
|
+
}
|
|
439
|
+
if (uniqueNodeTypes.size <= 2 && stats.addedLines > 10) {
|
|
440
|
+
scores.boilerplate += 0.2;
|
|
441
|
+
reasoning.push('repetitive / template-like structure');
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const maxScore = Math.max(scores.refactor, scores.bugfix, scores.boilerplate);
|
|
445
|
+
if (maxScore === 0) {
|
|
446
|
+
return { intent: "BUGFIX", confidence: 0.3, reasoning: ["no clear signal"] };
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
let intent: IntentType;
|
|
450
|
+
if (scores.refactor >= maxScore && scores.refactor >= 0.4) intent = "REFACTOR";
|
|
451
|
+
else if (scores.boilerplate >= maxScore && scores.boilerplate >= 0.3) intent = "BOILERPLATE";
|
|
452
|
+
else intent = "BUGFIX";
|
|
453
|
+
|
|
454
|
+
const confidence = Math.min(0.95, maxScore + 0.2);
|
|
455
|
+
|
|
456
|
+
if (reasoning.length === 0) reasoning.push("default classification");
|
|
457
|
+
return { intent, confidence, reasoning };
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// ── Public API ────────────────────────────────────────────
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Analyze a code diff and classify the developer intent.
|
|
464
|
+
*
|
|
465
|
+
* @param diffContent Unified diff text (from git diff output)
|
|
466
|
+
* @param filePath Optional file path for AST analysis
|
|
467
|
+
* @returns Structured intent classification
|
|
468
|
+
*/
|
|
469
|
+
export async function recognizeIntent
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
## Module: `cognition-engine/types`
|
|
475
|
+
|
|
476
|
+
> Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
477
|
+
|
|
478
|
+
### `AstConstraint`
|
|
479
|
+
|
|
480
|
+
Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
481
|
+
|
|
482
|
+
```typescript
|
|
483
|
+
/**
|
|
484
|
+
* @file Cognition Engine — type definitions.
|
|
485
|
+
* These types are specific to the cognition engine pipeline.
|
|
486
|
+
* Shared types consumed by tools live in ../types.js.
|
|
487
|
+
*/
|
|
488
|
+
|
|
489
|
+
import type {
|
|
490
|
+
CognitionNodeData,
|
|
491
|
+
CognitionEdgeData,
|
|
492
|
+
CognitionTypeStr,
|
|
493
|
+
EdgeRelationStr,
|
|
494
|
+
} from "../storage/cognition-types.js";
|
|
495
|
+
|
|
496
|
+
// ── Intent Recognition ────────────────────────────────────
|
|
497
|
+
|
|
498
|
+
export type IntentType = "REFACTOR" | "BUGFIX" | "BOILERPLATE";
|
|
499
|
+
|
|
500
|
+
export interface IntentResult {
|
|
501
|
+
intent: IntentType;
|
|
502
|
+
confidence: number; // 0.0 – 1.0
|
|
503
|
+
reasoning: string[];
|
|
504
|
+
/** Diff statistics used for classification. */
|
|
505
|
+
stats: {
|
|
506
|
+
addedLines: number;
|
|
507
|
+
removedLines: number;
|
|
508
|
+
filesChanged: number;
|
|
509
|
+
nodeTypeChanges: string[];
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// ── Graph Traversal ───────────────────────────────────────
|
|
514
|
+
|
|
515
|
+
export interface TraversalOptions {
|
|
516
|
+
/** Max BFS depth. Default 5. */
|
|
517
|
+
maxDepth?: number;
|
|
518
|
+
/** Minimum relevance score [0, 1] to include in results. */
|
|
519
|
+
minRelevance?: number;
|
|
520
|
+
/** Optional intent hint to bias edge weights. */
|
|
521
|
+
intentHint?: IntentType;
|
|
522
|
+
/** If set, only include nodes at these abstraction levels. */
|
|
523
|
+
abstractionLevelFilter?: number[];
|
|
524
|
+
/** Hard timeout in ms. Default 500. */
|
|
525
|
+
maxDurationMs?: number;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
export interface ScoredCognitionNode {
|
|
529
|
+
node: CognitionNodeData;
|
|
530
|
+
relevanceScore: number;
|
|
531
|
+
/** Path trace: how this node was reached (edge trail). */
|
|
532
|
+
trace: string[];
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
export interface TraversalResult {
|
|
536
|
+
nodes: ScoredCognitionNode[];
|
|
537
|
+
edges: CognitionEdgeData[];
|
|
538
|
+
durationMs: number;
|
|
539
|
+
truncated: boolean;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// ── AST Constraint Solving ────────────────────────────────
|
|
543
|
+
|
|
544
|
+
/** DSL constraint: must be JSON-serializable for storage. */
|
|
545
|
+
export interface AstConstraint
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
---
|
|
549
|
+
|
|
550
|
+
## Module: `legacy-engine/parsers`
|
|
551
|
+
|
|
552
|
+
### `parseToAST`
|
|
553
|
+
|
|
554
|
+
Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
555
|
+
|
|
556
|
+
```typescript
|
|
557
|
+
/**
|
|
558
|
+
* @deprecated LEGACY ENGINE MODULE — Preserved for reference only.
|
|
559
|
+
* Do NOT modify. The new cognition-engine module replaces this entire subsystem.
|
|
560
|
+
* See src/cognition-engine/ for the replacement.
|
|
561
|
+
*/
|
|
562
|
+
|
|
563
|
+
import { fileURLToPath } from "node:url";
|
|
564
|
+
import path from "node:path";
|
|
565
|
+
import { ASTNode, AtomicOp, DiffResult } from "../types.js";
|
|
566
|
+
import { computeDiff } from "./ast-diff.js";
|
|
567
|
+
import { regexDiff } from "./regex-fallback.js";
|
|
568
|
+
|
|
569
|
+
// ── Path Resolution ──────────────────────────────────────────
|
|
570
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
571
|
+
const projectRoot = path.resolve(__dirname, "../..");
|
|
572
|
+
|
|
573
|
+
const WASM_PATHS: Record<string, string> = {
|
|
574
|
+
javascript: path.join(projectRoot, "node_modules", "tree-sitter-javascript", "tree-sitter-javascript.wasm"),
|
|
575
|
+
typescript: path.join(projectRoot, "node_modules", "tree-sitter-typescript", "tree-sitter-typescript.wasm"),
|
|
576
|
+
tsx: path.join(projectRoot, "node_modules", "tree-sitter-typescript", "tree-sitter-tsx.wasm"),
|
|
577
|
+
python: path.join(projectRoot, "node_modules", "tree-sitter-python", "tree-sitter-python.wasm"),
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
function getLanguageForFile(filePath: string): string {
|
|
581
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
582
|
+
if (ext === ".tsx") return "tsx";
|
|
583
|
+
if (ext === ".ts") return "typescript";
|
|
584
|
+
if (ext === ".js" || ext === ".jsx" || ext === ".mjs" || ext === ".cjs") return "javascript";
|
|
585
|
+
if (ext === ".py") return "python";
|
|
586
|
+
return "javascript"; // default fallback
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// ── Tree-sitter WASM Initialization ──────────────────────────
|
|
590
|
+
let tsInitialized = false;
|
|
591
|
+
let tsFailed = false;
|
|
592
|
+
const grammarCache = new Map<string, any>();
|
|
593
|
+
let ParserModule: any = null;
|
|
594
|
+
|
|
595
|
+
async function ensureTreeSitter(): Promise<boolean> {
|
|
596
|
+
if (tsInitialized) return true;
|
|
597
|
+
if (tsFailed) return false;
|
|
598
|
+
try {
|
|
599
|
+
ParserModule = await import("web-tree-sitter");
|
|
600
|
+
await ParserModule.Parser.init();
|
|
601
|
+
tsInitialized = true;
|
|
602
|
+
return true;
|
|
603
|
+
} catch (err) {
|
|
604
|
+
tsFailed = true;
|
|
605
|
+
console.error("[parsers] web-tree-sitter init failed:", err);
|
|
606
|
+
return false;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
async function loadGrammar(language: string): Promise<any> {
|
|
611
|
+
if (grammarCache.has(language)) return grammarCache.get(language);
|
|
612
|
+
const wasmPath = WASM_PATHS[language];
|
|
613
|
+
if (!wasmPath) throw new Error(`No WASM path for language: ${language}`);
|
|
614
|
+
|
|
615
|
+
const fs = await import("node:fs");
|
|
616
|
+
if (!fs.existsSync(wasmPath)) {
|
|
617
|
+
throw new Error(`WASM file not found: ${wasmPath}`);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
const lang = await ParserModule.Language.load(wasmPath);
|
|
621
|
+
grammarCache.set(language, lang);
|
|
622
|
+
return lang;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// ── Tree-sitter → ASTNode Conversion ────────────────────────
|
|
626
|
+
function treeSitterToAST(node: any): ASTNode {
|
|
627
|
+
return {
|
|
628
|
+
type: node.type,
|
|
629
|
+
text: node.text,
|
|
630
|
+
startByte: node.startIndex,
|
|
631
|
+
endByte: node.endIndex,
|
|
632
|
+
children: node.namedChildren.map((c: any) => treeSitterToAST(c)),
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// ── Public API ───────────────────────────────────────────────
|
|
637
|
+
|
|
638
|
+
export interface ParserResult {
|
|
639
|
+
ast: ASTNode;
|
|
640
|
+
language: string;
|
|
641
|
+
parseSuccess: boolean;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/** Parse code to AST using web-tree-sitter, falling back to line-based AST on failure. */
|
|
645
|
+
export async function parseToAST
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
### `computeDiffWithFallback`
|
|
649
|
+
|
|
650
|
+
Compute diff with automatic AST → regex fallback chain.
|
|
651
|
+
|
|
652
|
+
```typescript
|
|
653
|
+
export async function computeDiffWithFallback
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
---
|
|
657
|
+
|
|
658
|
+
## Module: `resources/cognition-resources`
|
|
659
|
+
|
|
660
|
+
> Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
661
|
+
|
|
662
|
+
### `readCognitionSchema`
|
|
663
|
+
|
|
664
|
+
Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
665
|
+
|
|
666
|
+
```typescript
|
|
667
|
+
/**
|
|
668
|
+
* @file Cognition Engine MCP Resources
|
|
669
|
+
* Exposes three resources for Agent discovery:
|
|
670
|
+
* cognition://schema — Graph data model JSON Schema
|
|
671
|
+
* cognition://stats — Graph statistics (node/edge counts)
|
|
672
|
+
* cognition://docs — Integration documentation
|
|
673
|
+
*/
|
|
674
|
+
|
|
675
|
+
import { readFileSync } from "node:fs";
|
|
676
|
+
import { join, dirname } from "node:path";
|
|
677
|
+
import { fileURLToPath } from "node:url";
|
|
678
|
+
import { getPrismaClient } from "../storage/client.js";
|
|
679
|
+
|
|
680
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
681
|
+
const projectRoot = join(__dirname, "../..");
|
|
682
|
+
|
|
683
|
+
// ── Resource Definitions ───────────────────────────────────
|
|
684
|
+
|
|
685
|
+
export const RESOURCES = [
|
|
686
|
+
{
|
|
687
|
+
uri: "cognition://schema",
|
|
688
|
+
name: "Cognition Graph Schema",
|
|
689
|
+
description: "JSON Schema of the cognition graph data model, including CognitionNode, CognitionEdge, and AstTemplate tables and their relationships.",
|
|
690
|
+
mimeType: "application/json",
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
uri: "cognition://stats",
|
|
694
|
+
name: "Cognition Engine Statistics",
|
|
695
|
+
description: "Current graph statistics: node count, edge count, feedback event count, and average traversal latency. Useful for health checks and capacity planning.",
|
|
696
|
+
mimeType: "application/json",
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
uri: "cognition://docs",
|
|
700
|
+
name: "Cognition Engine Documentation",
|
|
701
|
+
description: "Full MCP tool documentation from docs/phase4-mcp-feedback.md. Agents can read this to learn how to use cognition_query, cognition_validate, and cognition_feedback.",
|
|
702
|
+
mimeType: "text/markdown",
|
|
703
|
+
},
|
|
704
|
+
{
|
|
705
|
+
uri: "cognition://rules-changelog",
|
|
706
|
+
name: "Rules Changelog",
|
|
707
|
+
description: "Versioned changelog of global rule changes. Returns version = SHA-256 prefix of updated_at field. Agents must read this before making rule modifications.",
|
|
708
|
+
mimeType: "application/json",
|
|
709
|
+
},
|
|
710
|
+
];
|
|
711
|
+
|
|
712
|
+
// ── Resource Readers ──────────────────────────────────────
|
|
713
|
+
|
|
714
|
+
/** Return the JSON schema for the cognition graph data model. */
|
|
715
|
+
export async function readCognitionSchema
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
### `readCognitionStats`
|
|
719
|
+
|
|
720
|
+
Return current graph statistics with approval rate.
|
|
721
|
+
|
|
722
|
+
```typescript
|
|
723
|
+
export async function readCognitionStats
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
### `readCognitionDocs`
|
|
727
|
+
|
|
728
|
+
Return the integration documentation markdown.
|
|
729
|
+
|
|
730
|
+
```typescript
|
|
731
|
+
export async function readCognitionDocs
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
---
|
|
735
|
+
|
|
736
|
+
## Module: `storage/client`
|
|
737
|
+
|
|
738
|
+
### `resetPrismaClient`
|
|
739
|
+
|
|
740
|
+
Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
741
|
+
|
|
742
|
+
```typescript
|
|
743
|
+
import { PrismaClient } from "@prisma/client";
|
|
744
|
+
|
|
745
|
+
let client: PrismaClient | null = null;
|
|
746
|
+
|
|
747
|
+
export function getPrismaClient(): PrismaClient {
|
|
748
|
+
if (!client) {
|
|
749
|
+
client = new PrismaClient({ log: ["warn", "error"] });
|
|
750
|
+
// Enable SQLite WAL mode for concurrent read/write performance (P1)
|
|
751
|
+
client.$queryRawUnsafe("PRAGMA journal_mode=WAL").catch(() => {});
|
|
752
|
+
}
|
|
753
|
+
return client;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
export async function disconnectPrisma(): Promise<void> {
|
|
757
|
+
if (client) {
|
|
758
|
+
await client.$disconnect();
|
|
759
|
+
client = null;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
/**
|
|
764
|
+
* Reset the Prisma client singleton, optionally with a new DATABASE_URL.
|
|
765
|
+
* Used by vitest setup to give each worker an isolated database file,
|
|
766
|
+
* preventing cross-worker FK race conditions.
|
|
767
|
+
* Calling with no URL re-creates the client with the current env var value.
|
|
768
|
+
*/
|
|
769
|
+
export async function resetPrismaClient
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
---
|
|
773
|
+
|
|
774
|
+
## Module: `storage/cognition-repository`
|
|
775
|
+
|
|
776
|
+
### `computeSemanticHash`
|
|
777
|
+
|
|
778
|
+
Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
779
|
+
|
|
780
|
+
```typescript
|
|
781
|
+
import { Prisma } from "@prisma/client";
|
|
782
|
+
import { getPrismaClient } from "./client.js";
|
|
783
|
+
import {
|
|
784
|
+
CognitionTypeStr,
|
|
785
|
+
EdgeRelationStr,
|
|
786
|
+
CognitionNodeInput,
|
|
787
|
+
CognitionEdgeInput,
|
|
788
|
+
AstTemplateInput,
|
|
789
|
+
CognitionNodeData,
|
|
790
|
+
CognitionEdgeData,
|
|
791
|
+
AstTemplateData,
|
|
792
|
+
SubgraphResult,
|
|
793
|
+
COGNITION_TYPES,
|
|
794
|
+
EDGE_RELATIONS,
|
|
795
|
+
} from "./cognition-types.js";
|
|
796
|
+
|
|
797
|
+
// ── Helpers ────────────────────────────────────────────────
|
|
798
|
+
|
|
799
|
+
/** Simple hash for semantic dedup. Consistent with ast-node.ts legacy style. */
|
|
800
|
+
function simpleHash(s: string): string {
|
|
801
|
+
if (!s) return "0";
|
|
802
|
+
let hash = 0;
|
|
803
|
+
for (let i = 0; i < s.length; i++) {
|
|
804
|
+
hash = ((hash << 5) - hash) + s.charCodeAt(i);
|
|
805
|
+
hash |= 0;
|
|
806
|
+
}
|
|
807
|
+
return Math.abs(hash).toString(16);
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
/** Generate a semantic hash from type + payload for deduplication. */
|
|
811
|
+
export function computeSemanticHash
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
### `isValidCognitionType`
|
|
815
|
+
|
|
816
|
+
Validate that a type string is a valid CognitionType.
|
|
817
|
+
|
|
818
|
+
```typescript
|
|
819
|
+
export function isValidCognitionType
|
|
820
|
+
```
|
|
821
|
+
|
|
822
|
+
### `isValidEdgeRelation`
|
|
823
|
+
|
|
824
|
+
Validate that a relation string is a valid EdgeRelation.
|
|
825
|
+
|
|
826
|
+
```typescript
|
|
827
|
+
export function isValidEdgeRelation
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
---
|
|
831
|
+
|
|
832
|
+
## Module: `storage/cognition-types`
|
|
833
|
+
|
|
834
|
+
### `COGNITION_TYPES`
|
|
835
|
+
|
|
836
|
+
Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
837
|
+
|
|
838
|
+
```typescript
|
|
839
|
+
// ── Cognition Graph Type Definitions ───────────────────────
|
|
840
|
+
// Independent from src/types.ts. Do NOT modify existing types.
|
|
841
|
+
// Use String for JSON fields (SQLite limitation, consistent with codebase conventions).
|
|
842
|
+
|
|
843
|
+
/** Valid cognition node type values. */
|
|
844
|
+
export const COGNITION_TYPES
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
### `EDGE_RELATIONS`
|
|
848
|
+
|
|
849
|
+
Valid edge relation values.
|
|
850
|
+
|
|
851
|
+
```typescript
|
|
852
|
+
export const EDGE_RELATIONS
|
|
853
|
+
```
|
|
854
|
+
|
|
855
|
+
### `ABSTRACTION_LEVELS`
|
|
856
|
+
|
|
857
|
+
Abstraction levels for cognition nodes.
|
|
858
|
+
|
|
859
|
+
```typescript
|
|
860
|
+
export const ABSTRACTION_LEVELS
|
|
861
|
+
```
|
|
862
|
+
|
|
863
|
+
### `SubgraphResult`
|
|
864
|
+
|
|
865
|
+
Structured data only (AST template JSON, constraint expressions). NEVER natural language.
|
|
866
|
+
|
|
867
|
+
```typescript
|
|
868
|
+
payload: Record<string, unknown>;
|
|
869
|
+
metadata?: Record<string, unknown>;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
export interface CognitionEdgeInput {
|
|
873
|
+
sourceId: string;
|
|
874
|
+
targetId: string;
|
|
875
|
+
relation: EdgeRelationStr;
|
|
876
|
+
weight?: number;
|
|
877
|
+
metadata?: Record<string, unknown>;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
export interface AstTemplateInput {
|
|
881
|
+
nodeId: string;
|
|
882
|
+
language: string;
|
|
883
|
+
/** DSL/JSON pattern for AST-level validation or transformation. NEVER natural language. */
|
|
884
|
+
templateDsl: string;
|
|
885
|
+
/** JSON Schema for validating templateDsl content. */
|
|
886
|
+
validationSchema?: Record<string, unknown>;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
// ── Output types (for read operations) ─────────────────────
|
|
890
|
+
|
|
891
|
+
export interface CognitionNodeData {
|
|
892
|
+
id: string;
|
|
893
|
+
type: CognitionTypeStr;
|
|
894
|
+
semanticHash: string;
|
|
895
|
+
abstractionLevel: number;
|
|
896
|
+
payload: Record<string, unknown>;
|
|
897
|
+
metadata: Record<string, unknown> | null;
|
|
898
|
+
createdAt: Date;
|
|
899
|
+
updatedAt: Date;
|
|
900
|
+
astTemplate: AstTemplateData | null;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
export interface CognitionEdgeData {
|
|
904
|
+
id: string;
|
|
905
|
+
sourceId: string;
|
|
906
|
+
targetId: string;
|
|
907
|
+
relation: EdgeRelationStr;
|
|
908
|
+
weight: number;
|
|
909
|
+
metadata: Record<string, unknown> | null;
|
|
910
|
+
createdAt: Date;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
export interface AstTemplateData {
|
|
914
|
+
id: string;
|
|
915
|
+
nodeId: string;
|
|
916
|
+
language: string;
|
|
917
|
+
templateDsl: string;
|
|
918
|
+
validationSchema: Record<string, unknown> | null;
|
|
919
|
+
createdAt: Date;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
/** Result of a subgraph traversal. */
|
|
923
|
+
export interface SubgraphResult
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
---
|
|
927
|
+
|
|
928
|
+
## Module: `tools/cognition-tools`
|
|
929
|
+
|
|
930
|
+
> Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
931
|
+
|
|
932
|
+
### `handleCognitionQuery`
|
|
933
|
+
|
|
934
|
+
Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
935
|
+
|
|
936
|
+
```typescript
|
|
937
|
+
/**
|
|
938
|
+
* @file Cognition engine MCP Tool handlers.
|
|
939
|
+
* Three new tools for the MCP protocol:
|
|
940
|
+
* cognition_query — Query the cognition graph
|
|
941
|
+
* cognition_validate — Validate code against AST templates
|
|
942
|
+
* cognition_feedback — Provide feedback to update edge weights
|
|
943
|
+
*
|
|
944
|
+
* These are independent from legacy tools in this directory.
|
|
945
|
+
*/
|
|
946
|
+
|
|
947
|
+
import { GraphTraverser } from "../cognition-engine/graph-traverser.js";
|
|
948
|
+
import { recognizeIntent } from "../cognition-engine/intent-recognizer.js";
|
|
949
|
+
import { solveConstraints } from "../cognition-engine/ast-constraint-solver.js";
|
|
950
|
+
import { CognitionRepository } from "../storage/cognition-repository.js";
|
|
951
|
+
import type { TraversalOptions } from "../cognition-engine/types.js";
|
|
952
|
+
|
|
953
|
+
// ── Input Types ─────────────────────────────────────────────
|
|
954
|
+
|
|
955
|
+
interface CognitionQueryInput {
|
|
956
|
+
contextHash: string;
|
|
957
|
+
intentHint?: "REFACTOR" | "BUGFIX" | "BOILERPLATE";
|
|
958
|
+
maxDepth?: number;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
interface CognitionValidateInput {
|
|
962
|
+
nodeId: string;
|
|
963
|
+
targetFileContent: string;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
interface CognitionFeedbackInput {
|
|
967
|
+
nodeId: string;
|
|
968
|
+
edgeId?: string;
|
|
969
|
+
outcome: "ACCEPTED" | "REJECTED" | "MODIFIED";
|
|
970
|
+
comment?: string;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
// ── Handlers ────────────────────────────────────────────────
|
|
974
|
+
|
|
975
|
+
/**
|
|
976
|
+
* cognition_query — Traverse the cognition graph starting from a context hash.
|
|
977
|
+
* If intentHint is omitted, first runs intent recognition on the content hash string.
|
|
978
|
+
*/
|
|
979
|
+
export async function handleCognitionQuery
|
|
980
|
+
```
|
|
981
|
+
|
|
982
|
+
### `handleCognitionValidate`
|
|
983
|
+
|
|
984
|
+
cognition_validate — Validate code content against a cognition node's AST template.
|
|
985
|
+
|
|
986
|
+
```typescript
|
|
987
|
+
export async function handleCognitionValidate
|
|
988
|
+
```
|
|
989
|
+
|
|
990
|
+
### `handleCognitionFeedback`
|
|
991
|
+
|
|
992
|
+
cognition_feedback — Record user feedback and adjust edge weights.
|
|
993
|
+
|
|
994
|
+
```typescript
|
|
995
|
+
export async function handleCognitionFeedback
|
|
996
|
+
```
|
|
997
|
+
|
|
998
|
+
---
|
|
999
|
+
|
|
1000
|
+
## Module: `tools/config-tools`
|
|
1001
|
+
|
|
1002
|
+
> Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. / Updates threshold values stored as CognitionNode(type=HEURISTIC). Old nodes marked with supersededBy field in metadata. Requires X-Expert-Mode header (simulated via input check). /
|
|
1003
|
+
|
|
1004
|
+
### `handleUpdateConfig`
|
|
1005
|
+
|
|
1006
|
+
Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
1007
|
+
|
|
1008
|
+
```typescript
|
|
1009
|
+
/**
|
|
1010
|
+
* @file Config Hot Update Tool
|
|
1011
|
+
* Updates threshold values stored as CognitionNode(type=HEURISTIC).
|
|
1012
|
+
* Old nodes marked with supersededBy field in metadata.
|
|
1013
|
+
* Requires X-Expert-Mode header (simulated via input check).
|
|
1014
|
+
*/
|
|
1015
|
+
import { CognitionRepository, computeSemanticHash } from "../storage/cognition-repository.js";
|
|
1016
|
+
import { COGNITION_TYPES } from "../storage/cognition-types.js";
|
|
1017
|
+
|
|
1018
|
+
interface UpdateConfigInput {
|
|
1019
|
+
key: string;
|
|
1020
|
+
value: number;
|
|
1021
|
+
expertMode?: boolean;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
/** Handle cognition_update_config MCP Tool call. */
|
|
1025
|
+
export async function handleUpdateConfig
|
|
1026
|
+
```
|
|
1027
|
+
|
|
1028
|
+
---
|
|
1029
|
+
|
|
1030
|
+
## Module: `tools/injection-approval`
|
|
1031
|
+
|
|
1032
|
+
> Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. / Manages proposal-based approval workflow with TTL. Proposal lifecycle: implicit CREATE (via query/validate) -> explicit APPROVE/REJECT/OVERRIDE. /
|
|
1033
|
+
|
|
1034
|
+
### `createProposal`
|
|
1035
|
+
|
|
1036
|
+
Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
1037
|
+
|
|
1038
|
+
```typescript
|
|
1039
|
+
/**
|
|
1040
|
+
* @file Injection Approval Tool
|
|
1041
|
+
* Manages proposal-based approval workflow with TTL.
|
|
1042
|
+
* Proposal lifecycle: implicit CREATE (via query/validate) -> explicit APPROVE/REJECT/OVERRIDE.
|
|
1043
|
+
*/
|
|
1044
|
+
|
|
1045
|
+
import { CognitionRepository } from "../storage/cognition-repository.js";
|
|
1046
|
+
import { getPrismaClient } from "../storage/client.js";
|
|
1047
|
+
import { writeFileSync, existsSync, mkdirSync } from "node:fs";
|
|
1048
|
+
import { join, dirname } from "node:path";
|
|
1049
|
+
import { fileURLToPath } from "node:url";
|
|
1050
|
+
|
|
1051
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
1052
|
+
const LOG_DIR = join(__dirname, "../../logs");
|
|
1053
|
+
const TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
1054
|
+
|
|
1055
|
+
interface Proposal {
|
|
1056
|
+
proposalId: string;
|
|
1057
|
+
contextHash: string;
|
|
1058
|
+
createdAt: number;
|
|
1059
|
+
expiresAt: number;
|
|
1060
|
+
status: "PENDING" | "APPROVED" | "REJECTED" | "OVERRIDDEN" | "EXPIRED";
|
|
1061
|
+
nodeIds: string[];
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
const proposals = new Map<string, Proposal>();
|
|
1065
|
+
|
|
1066
|
+
function generateId(): string {
|
|
1067
|
+
return "prop_" + Math.random().toString(36).substring(2, 10) + Date.now().toString(36);
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
/** Create a new proposal implicitly (called after query/validate). */
|
|
1071
|
+
export function createProposal
|
|
1072
|
+
```
|
|
1073
|
+
|
|
1074
|
+
### `handleApproveInjection`
|
|
1075
|
+
|
|
1076
|
+
Handle cognition_approve_injection MCP Tool call.
|
|
1077
|
+
|
|
1078
|
+
```typescript
|
|
1079
|
+
export async function handleApproveInjection
|
|
1080
|
+
```
|
|
1081
|
+
|
|
1082
|
+
### `getProposalStats`
|
|
1083
|
+
|
|
1084
|
+
Record audit event (async, non-blocking).
|
|
1085
|
+
|
|
1086
|
+
```typescript
|
|
1087
|
+
async function recordAuditLog(eventType: string, props: Record<string, unknown>): Promise<void> {
|
|
1088
|
+
try {
|
|
1089
|
+
const prisma = getPrismaClient();
|
|
1090
|
+
await prisma.metricEvent.create({ data: { eventType, properties: JSON.stringify({ ...props, timestamp: new Date().toISOString() }) } });
|
|
1091
|
+
} catch {
|
|
1092
|
+
// Fallback to local log file
|
|
1093
|
+
try {
|
|
1094
|
+
if (!existsSync(LOG_DIR)) mkdirSync(LOG_DIR, { recursive: true });
|
|
1095
|
+
writeFileSync(join(LOG_DIR, "fallback.log"), JSON.stringify({ eventType, props, timestamp: new Date().toISOString() }) + "\n", { flag: "a" });
|
|
1096
|
+
} catch { /* silent */ }
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
/** Get proposal stats. */
|
|
1101
|
+
export function getProposalStats
|
|
1102
|
+
```
|
|
1103
|
+
|
|
1104
|
+
---
|
|
1105
|
+
|
|
1106
|
+
## Module: `types`
|
|
1107
|
+
|
|
1108
|
+
### `ASTNode`
|
|
1109
|
+
|
|
1110
|
+
Copyright 2026 熊高锐 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. /
|
|
1111
|
+
|
|
1112
|
+
```typescript
|
|
1113
|
+
export interface ASTNode
|
|
1114
|
+
```
|
|
1115
|
+
|
|
1116
|
+
### `SKIP_PATTERNS`
|
|
1117
|
+
|
|
1118
|
+
Optional file content for pattern matching. If empty, content-based matching is skipped.
|
|
1119
|
+
|
|
1120
|
+
```typescript
|
|
1121
|
+
fileContent?: string;
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
export interface ScoredRule {
|
|
1125
|
+
rule: Rule;
|
|
1126
|
+
score: number;
|
|
1127
|
+
matchReasons: string[];
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
export interface MatchResult {
|
|
1131
|
+
rules: ScoredRule[];
|
|
1132
|
+
totalTokens: number;
|
|
1133
|
+
truncated: boolean;
|
|
1134
|
+
queryDurationMs: number;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
export type ConflictResolution = "keep_a" | "keep_b" | "merge" | "skip";
|
|
1138
|
+
|
|
1139
|
+
export interface ConflictInfo {
|
|
1140
|
+
id: string;
|
|
1141
|
+
ruleA: Rule;
|
|
1142
|
+
ruleB: Rule;
|
|
1143
|
+
scopeKey: string;
|
|
1144
|
+
resolution?: ConflictResolution;
|
|
1145
|
+
createdAt: Date;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
export interface CaptureDiffInput {
|
|
1149
|
+
filePath: string;
|
|
1150
|
+
originalContent: string;
|
|
1151
|
+
modifiedContent: string;
|
|
1152
|
+
language: string;
|
|
1153
|
+
projectId?: string;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
export interface QueryRulesInput {
|
|
1157
|
+
language: string;
|
|
1158
|
+
filePath: string;
|
|
1159
|
+
projectId?: string;
|
|
1160
|
+
tags?: string[];
|
|
1161
|
+
taskId?: string;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
export interface ConfirmRuleInput {
|
|
1165
|
+
ruleId: string;
|
|
1166
|
+
action: "accept" | "reject" | "edit" | "skip";
|
|
1167
|
+
editedPattern?: string;
|
|
1168
|
+
editedSuggestion?: string;
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
export interface ResolveConflictInput {
|
|
1172
|
+
conflictId: string;
|
|
1173
|
+
resolution: ConflictResolution;
|
|
1174
|
+
batchAllSession?: boolean;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
export interface ListRulesInput {
|
|
1178
|
+
language?: string;
|
|
1179
|
+
scope?: RuleScope;
|
|
1180
|
+
status?: RuleStatus;
|
|
1181
|
+
projectId?: string;
|
|
1182
|
+
limit?: number;
|
|
1183
|
+
offset?: number;
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
export const DEFAULT_WEIGHTS = {
|
|
1187
|
+
typeWeight: 0.4,
|
|
1188
|
+
timeWeight: 0.3,
|
|
1189
|
+
matchWeight: 0.3,
|
|
1190
|
+
timeDecayLambda: 0.01,
|
|
1191
|
+
} as const;
|
|
1192
|
+
|
|
1193
|
+
export const SCOPE_PRIORITIES: Record<RuleScope, number> = {
|
|
1194
|
+
project: 1.0,
|
|
1195
|
+
user: 0.8,
|
|
1196
|
+
global: 0.5,
|
|
1197
|
+
};
|
|
1198
|
+
|
|
1199
|
+
export const TOKEN_LIMITS = {
|
|
1200
|
+
maxInjectionTokens: 2000,
|
|
1201
|
+
maxSingleRuleTokens: 100,
|
|
1202
|
+
maxRulesPerProject: 2000,
|
|
1203
|
+
maxRulesGlobal: 3000,
|
|
1204
|
+
} as const;
|
|
1205
|
+
|
|
1206
|
+
export const RULE_GENERATION_THRESHOLDS = {
|
|
1207
|
+
minDistinctFiles: 3,
|
|
1208
|
+
minRepeatsInDays: 5,
|
|
1209
|
+
repeatWindowDays: 7,
|
|
1210
|
+
} as const;
|
|
1211
|
+
|
|
1212
|
+
export interface AnalyzeWorkspaceInput {
|
|
1213
|
+
baseCommit: string;
|
|
1214
|
+
headCommit?: string;
|
|
1215
|
+
paths?: string[];
|
|
1216
|
+
taskId?: string;
|
|
1217
|
+
/** Concurrent analysis: max files processed in parallel. Defaults to 5 or CPU core count. */
|
|
1218
|
+
concurrency?: number;
|
|
1219
|
+
fileContents?: { path: string; originalContent?: string; modifiedContent: string }[];
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
export interface AnalyzeResult {
|
|
1223
|
+
analyzedFiles: number;
|
|
1224
|
+
skippedFiles: number;
|
|
1225
|
+
generatedRules: { rule: RuleSpec; filePath: string }[];
|
|
1226
|
+
conflicts: { ruleA: RuleSpec; ruleB: RuleSpec; reason: string }[];
|
|
1227
|
+
errors: { filePath: string; error: string }[];
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
/** File extensions to skip in workspace analysis */
|
|
1231
|
+
export const SKIP_PATTERNS
|
|
1232
|
+
```
|
|
1233
|
+
|
|
1234
|
+
---
|