chiasmus 0.1.2 → 0.1.5
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/README.md +103 -11
- package/dist/formalize/engine.d.ts.map +1 -1
- package/dist/formalize/engine.js +11 -6
- package/dist/formalize/engine.js.map +1 -1
- package/dist/formalize/feedback.d.ts +8 -0
- package/dist/formalize/feedback.d.ts.map +1 -0
- package/dist/formalize/feedback.js +43 -0
- package/dist/formalize/feedback.js.map +1 -0
- package/dist/graph/analyses.d.ts +18 -0
- package/dist/graph/analyses.d.ts.map +1 -0
- package/dist/graph/analyses.js +145 -0
- package/dist/graph/analyses.js.map +1 -0
- package/dist/graph/extractor.d.ts +7 -0
- package/dist/graph/extractor.d.ts.map +1 -0
- package/dist/graph/extractor.js +246 -0
- package/dist/graph/extractor.js.map +1 -0
- package/dist/graph/facts.d.ts +8 -0
- package/dist/graph/facts.d.ts.map +1 -0
- package/dist/graph/facts.js +92 -0
- package/dist/graph/facts.js.map +1 -0
- package/dist/graph/mermaid.d.ts +3 -0
- package/dist/graph/mermaid.d.ts.map +1 -0
- package/dist/graph/mermaid.js +160 -0
- package/dist/graph/mermaid.js.map +1 -0
- package/dist/graph/parser.d.ts +7 -0
- package/dist/graph/parser.d.ts.map +1 -0
- package/dist/graph/parser.js +69 -0
- package/dist/graph/parser.js.map +1 -0
- package/dist/graph/types.d.ts +32 -0
- package/dist/graph/types.d.ts.map +1 -0
- package/dist/graph/types.js +2 -0
- package/dist/graph/types.js.map +1 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +228 -6
- package/dist/mcp-server.js.map +1 -1
- package/dist/skills/craft.d.ts +35 -0
- package/dist/skills/craft.d.ts.map +1 -0
- package/dist/skills/craft.js +132 -0
- package/dist/skills/craft.js.map +1 -0
- package/dist/skills/library.d.ts +3 -0
- package/dist/skills/library.d.ts.map +1 -1
- package/dist/skills/library.js +5 -0
- package/dist/skills/library.js.map +1 -1
- package/dist/skills/relationships.d.ts +8 -0
- package/dist/skills/relationships.d.ts.map +1 -0
- package/dist/skills/relationships.js +36 -0
- package/dist/skills/relationships.js.map +1 -0
- package/dist/solvers/correction-loop.d.ts +1 -1
- package/dist/solvers/correction-loop.d.ts.map +1 -1
- package/dist/solvers/correction-loop.js +1 -1
- package/dist/solvers/correction-loop.js.map +1 -1
- package/dist/solvers/prolog-solver.d.ts.map +1 -1
- package/dist/solvers/prolog-solver.js +58 -1
- package/dist/solvers/prolog-solver.js.map +1 -1
- package/dist/solvers/types.d.ts +3 -0
- package/dist/solvers/types.d.ts.map +1 -1
- package/dist/solvers/z3-solver.d.ts.map +1 -1
- package/dist/solvers/z3-solver.js +14 -2
- package/dist/solvers/z3-solver.js.map +1 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Chiasmus
|
|
2
2
|
|
|
3
|
-
MCP server that gives LLMs access to formal verification via Z3 (SMT solver) and Tau Prolog. Translates natural language problems into formal logic using a template-based pipeline, verifies results with mathematical certainty.
|
|
3
|
+
MCP server that gives LLMs access to formal verification via Z3 (SMT solver) and Tau Prolog, plus tree-sitter-based source code analysis. Translates natural language problems into formal logic using a template-based pipeline, verifies results with mathematical certainty, and analyzes call graphs for reachability, dead code, and impact analysis.
|
|
4
4
|
|
|
5
5
|
### Example use cases
|
|
6
6
|
|
|
@@ -9,6 +9,8 @@ MCP server that gives LLMs access to formal verification via Z3 (SMT solver) and
|
|
|
9
9
|
- **"Can user input reach the database?"** → Prolog traces all paths through the call graph, flags taint flows to sensitive sinks
|
|
10
10
|
- **"Are our frontend and backend validations consistent?"** → Z3 finds concrete inputs that pass one but fail the other (e.g. age=15 passes frontend min=13 but fails backend min=18)
|
|
11
11
|
- **"Does our workflow have dead-end or unreachable states?"** → Prolog checks reachability from the initial state, identifies orphaned and terminal nodes
|
|
12
|
+
- **"What's the dead code in this module?"** → tree-sitter parses source files, Prolog finds functions unreachable from any entry point
|
|
13
|
+
- **"What breaks if I change this function?"** → call graph impact analysis shows all transitive callers
|
|
12
14
|
|
|
13
15
|
## Setup
|
|
14
16
|
|
|
@@ -68,34 +70,80 @@ Add to `opencode.json`:
|
|
|
68
70
|
|
|
69
71
|
## Tools
|
|
70
72
|
|
|
71
|
-
**`chiasmus_verify`** — Submit raw SMT-LIB or Prolog, get a verified result.
|
|
73
|
+
**`chiasmus_verify`** — Submit raw SMT-LIB or Prolog, get a verified result. Z3 UNSAT results include an `unsatCore` showing which assertions conflict. Prolog supports `explain=true` for derivation traces showing which rules fired.
|
|
72
74
|
|
|
73
75
|
```
|
|
74
76
|
chiasmus_verify solver="z3" input="
|
|
75
77
|
(declare-const x Int)
|
|
76
|
-
(
|
|
77
|
-
(assert (
|
|
78
|
-
(assert (> x 0))
|
|
79
|
-
(assert (> y 0))
|
|
78
|
+
(assert (! (> x 10) :named gt10))
|
|
79
|
+
(assert (! (< x 5) :named lt5))
|
|
80
80
|
"
|
|
81
|
-
→ { status: "
|
|
81
|
+
→ { status: "unsat", unsatCore: ["gt10", "lt5"] }
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|
```
|
|
85
85
|
chiasmus_verify solver="prolog"
|
|
86
86
|
input="parent(tom, bob). parent(bob, ann). ancestor(X,Y) :- parent(X,Y). ancestor(X,Y) :- parent(X,Z), ancestor(Z,Y)."
|
|
87
87
|
query="ancestor(tom, Who)."
|
|
88
|
-
|
|
88
|
+
explain=true
|
|
89
|
+
→ { status: "success", answers: [...], trace: ["ancestor(tom,bob)", "ancestor(bob,ann)", "ancestor(tom,ann)"] }
|
|
89
90
|
```
|
|
90
91
|
|
|
91
|
-
**`
|
|
92
|
+
**`chiasmus_verify`** also accepts `format="mermaid"` with `solver="prolog"` to parse Mermaid flowcharts and state diagrams directly into Prolog facts:
|
|
92
93
|
|
|
93
|
-
|
|
94
|
+
```
|
|
95
|
+
chiasmus_verify solver="prolog" format="mermaid"
|
|
96
|
+
input="graph TD\n UserInput --> Validator\n Validator --> DB\n Validator --> Logger"
|
|
97
|
+
query="reaches(userinput, db)."
|
|
98
|
+
→ { status: "success", answers: [{}] }
|
|
99
|
+
|
|
100
|
+
chiasmus_verify solver="prolog" format="mermaid"
|
|
101
|
+
input="stateDiagram-v2\n Idle --> Active : start\n Active --> Done : finish"
|
|
102
|
+
query="can_reach(idle, done)."
|
|
103
|
+
→ { status: "success", answers: [{}] }
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**`chiasmus_graph`** — Analyze source code call graphs via tree-sitter + Prolog. Parses TS/JS files, extracts cross-module call graphs, runs formal analyses.
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
chiasmus_graph files=["src/server.ts", "src/db.ts"] analysis="callers" target="query"
|
|
110
|
+
→ { analysis: "callers", result: ["handleRequest"] }
|
|
111
|
+
|
|
112
|
+
chiasmus_graph files=["src/**/*.ts"] analysis="dead-code"
|
|
113
|
+
→ { analysis: "dead-code", result: ["unusedHelper", "legacyParser"] }
|
|
114
|
+
|
|
115
|
+
chiasmus_graph files=["src/**/*.ts"] analysis="reachability" from="handleRequest" to="dbQuery"
|
|
116
|
+
→ { analysis: "reachability", result: { reachable: true } }
|
|
117
|
+
|
|
118
|
+
chiasmus_graph files=["src/**/*.ts"] analysis="impact" target="validate"
|
|
119
|
+
→ { analysis: "impact", result: ["handleRequest", "main"] }
|
|
120
|
+
```
|
|
94
121
|
|
|
95
|
-
|
|
122
|
+
Analyses: `summary`, `callers`, `callees`, `reachability`, `dead-code`, `cycles`, `path`, `impact`, `facts`.
|
|
123
|
+
|
|
124
|
+
**`chiasmus_skills`** — Search the template library. Ships with 8 starter templates covering authorization, configuration, dependency resolution, validation, rule inference, and graph reachability. By-name lookups include related template suggestions.
|
|
125
|
+
|
|
126
|
+
**`chiasmus_formalize`** — Find the best template for a problem, get slot-filling instructions plus suggestions for related verification checks. Fill the slots using your context, then call `chiasmus_verify`.
|
|
127
|
+
|
|
128
|
+
**`chiasmus_solve`** — End-to-end: selects template, fills slots via LLM, runs lint and correction loops with enriched feedback (unsat cores, structured error classification), returns a verified result. Optional — the same result is achieved by using `chiasmus_formalize` → fill slots → `chiasmus_verify`, which is the recommended workflow since the calling LLM has full conversation context.
|
|
129
|
+
|
|
130
|
+
**`chiasmus_craft`** — Create a new template and add it to the skill library. The calling LLM designs the template — no API key needed. Describe a problem type, then submit a skeleton with `{{SLOT:name}}` markers, slot definitions, and normalization recipes. Validates slot/skeleton consistency and name uniqueness. Optionally tests the example through the solver.
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
chiasmus_craft name="api-rate-limit" domain="configuration" solver="z3"
|
|
134
|
+
signature="Check if rate limit configs across services are consistent"
|
|
135
|
+
skeleton="{{SLOT:declarations}}\n(assert (not (= {{SLOT:limit_a}} {{SLOT:limit_b}})))"
|
|
136
|
+
slots=[{name: "declarations", ...}, {name: "limit_a", ...}, {name: "limit_b", ...}]
|
|
137
|
+
normalizations=[{source: "YAML config", transform: "Map rate limits to Int constants"}]
|
|
138
|
+
→ { created: true, template: "api-rate-limit", slots: 3 }
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
After creation, the template appears in `chiasmus_skills` searches and `chiasmus_formalize`.
|
|
96
142
|
|
|
97
143
|
**`chiasmus_learn`** — Extract a reusable template from a verified solution. Candidates get promoted after 3+ successful reuses.
|
|
98
144
|
|
|
145
|
+
**`chiasmus_lint`** — Fast structural validation of specs without running the solver.
|
|
146
|
+
|
|
99
147
|
## Recommended Workflow
|
|
100
148
|
|
|
101
149
|
The calling LLM (Claude, GPT, etc.) drives the process — no API key needed:
|
|
@@ -114,6 +162,50 @@ Use a solver when the LLM alone can't guarantee correctness:
|
|
|
114
162
|
- **"Can X reach Y through any path?"** — transitive closure / reachability
|
|
115
163
|
- **Access control, configs, dependencies** — where correctness is non-negotiable
|
|
116
164
|
|
|
165
|
+
Use `chiasmus_graph` when you need structural reasoning about code:
|
|
166
|
+
|
|
167
|
+
- **"What calls this function?"** — impact analysis before refactoring
|
|
168
|
+
- **"What's dead code?"** — find functions unreachable from entry points
|
|
169
|
+
- **"Can user input reach this SQL query?"** — taint analysis via call graph reachability
|
|
170
|
+
- **"What breaks if I change X?"** — blast radius via reverse reachability
|
|
171
|
+
- **"Are there circular dependencies?"** — cycle detection in call graphs
|
|
172
|
+
|
|
173
|
+
## Why `chiasmus_graph` over grep
|
|
174
|
+
|
|
175
|
+
When an LLM needs to understand code structure, it typically greps for function names and manually traces call chains. This works for direct references but breaks down for transitive questions. Here's a real comparison using chiasmus's own codebase:
|
|
176
|
+
|
|
177
|
+
**Question: "What's the blast radius of changing `lintSpec`?"**
|
|
178
|
+
|
|
179
|
+
With grep, this takes multiple rounds — first find direct callers, then callers of those callers, reconstructing the chain manually:
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
grep lintSpec src/**/*.ts → found in engine.ts (lintLoop) and mcp-server.ts (handleLint)
|
|
183
|
+
grep lintLoop src/**/*.ts → called from solve() at lines 75 and 87
|
|
184
|
+
grep handleSolve src/**/*.ts → called from createChiasmusServer switch...
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Three rounds of grep, manual reasoning at each step, and you've still only traced part of the chain. With `chiasmus_graph`, one call gives the complete transitive answer:
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
chiasmus_graph analysis="impact" target="lintSpec"
|
|
191
|
+
→ ["lintLoop", "handleLint", "solve", "correctionLoop",
|
|
192
|
+
"handleVerify", "handleSolve", "handleGraph",
|
|
193
|
+
"createChiasmusServer", "runAnalysis", "runAnalysisFromGraph"]
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
10 affected functions found in a single call — including paths through `correctionLoop` and `runAnalysis` that the grep approach missed entirely.
|
|
197
|
+
|
|
198
|
+
The same applies to other structural questions:
|
|
199
|
+
|
|
200
|
+
| Question | Grep | chiasmus_graph |
|
|
201
|
+
|----------|------|----------------|
|
|
202
|
+
| Impact of changing X | Multiple greps + manual trace; misses transitive paths | 1 call, complete transitive chain |
|
|
203
|
+
| Dead code detection | Grep every function name against all call sites — impractical | 1 call, definitive answer |
|
|
204
|
+
| Can A reach B? | Manually reconstruct call chain across files | 1 call, true/false |
|
|
205
|
+
| Call chain A→B | Multiple greps, mentally reconstruct path | 1 call, exact chain e.g. `[handleSolve,solve,lintLoop,lintSpec]` |
|
|
206
|
+
|
|
207
|
+
The key difference: grep finds string matches, `chiasmus_graph` answers structural questions. Transitive reachability, dead code, and impact analysis are formally impossible with grep alone.
|
|
208
|
+
|
|
117
209
|
## Configuration
|
|
118
210
|
|
|
119
211
|
| Variable | Default | Purpose |
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/formalize/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAe,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/formalize/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAe,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAIvE,0EAA0E;AAC1E,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,aAAa,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,sEAAsE;AACtE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,wDAAwD;IACxD,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAmBD,qBAAa,mBAAmB;IAE5B,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,GAAG;gBADH,OAAO,EAAE,YAAY,EACrB,GAAG,EAAE,UAAU;IAGzB;;;OAGG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAU1D;;;OAGG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,SAAI,GAAG,OAAO,CAAC,WAAW,CAAC;IAwCjE,OAAO,CAAC,iBAAiB;YAwCX,OAAO;YAUP,MAAM;IAwBpB,OAAO,CAAC,gBAAgB;IAsBxB;;;OAGG;YACW,QAAQ;IAuCtB,gEAAgE;IAChE,OAAO,CAAC,aAAa;CAMtB"}
|
package/dist/formalize/engine.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { correctionLoop } from "../solvers/correction-loop.js";
|
|
2
2
|
import { lintSpec } from "./validate.js";
|
|
3
|
+
import { classifyFeedback } from "./feedback.js";
|
|
3
4
|
const FORMALIZE_SYSTEM = `Formalization engine. Translate natural language → formal logic.
|
|
4
5
|
|
|
5
6
|
Template = starting point. Fill slots, but adapt structure if needed. Add/remove variables, assertions, rules.
|
|
@@ -11,7 +12,10 @@ Prolog: valid ISO Prolog. All clauses end with period.
|
|
|
11
12
|
Precise syntax — spec goes directly to solver.`;
|
|
12
13
|
const FIX_SYSTEM = `Fix failed formal spec. Return ONLY corrected spec. No explanation, no fences.
|
|
13
14
|
|
|
14
|
-
Common fixes
|
|
15
|
+
Common fixes by feedback type:
|
|
16
|
+
- Solver error: type mismatches → matching types | missing declarations → declare before use | unbalanced parens | Prolog missing periods
|
|
17
|
+
- UNSAT with core: conflicting assertions identified → remove or weaken one of the conflicting constraints
|
|
18
|
+
- No Prolog solutions: missing facts/rules → add covering clauses | wrong query pattern → fix unification`;
|
|
15
19
|
export class FormalizationEngine {
|
|
16
20
|
library;
|
|
17
21
|
llm;
|
|
@@ -44,8 +48,9 @@ export class FormalizationEngine {
|
|
|
44
48
|
// Build solver input
|
|
45
49
|
const initialInput = this.buildSolverInput(template, filledSpec);
|
|
46
50
|
// Run correction loop with LLM as fixer
|
|
47
|
-
const correctionResult = await correctionLoop(initialInput, async (attempt, error) => {
|
|
48
|
-
const
|
|
51
|
+
const correctionResult = await correctionLoop(initialInput, async (attempt, error, _round, result) => {
|
|
52
|
+
const feedback = result ? classifyFeedback(result) : error;
|
|
53
|
+
const fixed = await this.llmFix(attempt, feedback, template);
|
|
49
54
|
// Lint the fix before resubmitting to the solver
|
|
50
55
|
const linted = await this.lintLoop(fixed, template, 2);
|
|
51
56
|
return this.buildSolverInput(template, linted);
|
|
@@ -104,7 +109,7 @@ Output ONLY filled spec.`;
|
|
|
104
109
|
]);
|
|
105
110
|
return this.cleanResponse(response);
|
|
106
111
|
}
|
|
107
|
-
async llmFix(attempt,
|
|
112
|
+
async llmFix(attempt, feedback, template) {
|
|
108
113
|
const spec = attempt.type === "z3" ? attempt.smtlib : attempt.program;
|
|
109
114
|
const response = await this.llm.complete(FIX_SYSTEM, [
|
|
110
115
|
{
|
|
@@ -113,8 +118,8 @@ Output ONLY filled spec.`;
|
|
|
113
118
|
SPECIFICATION:
|
|
114
119
|
${spec}
|
|
115
120
|
|
|
116
|
-
|
|
117
|
-
${
|
|
121
|
+
FEEDBACK:
|
|
122
|
+
${feedback}
|
|
118
123
|
|
|
119
124
|
Fix the specification and return only the corrected version.`,
|
|
120
125
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/formalize/engine.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/formalize/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SolverResult } from "../solvers/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Classify a SolverResult into a human-readable feedback string
|
|
4
|
+
* for the correction loop. This helps the LLM understand what went
|
|
5
|
+
* wrong and how to fix it.
|
|
6
|
+
*/
|
|
7
|
+
export declare function classifyFeedback(result: SolverResult): string;
|
|
8
|
+
//# sourceMappingURL=feedback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feedback.d.ts","sourceRoot":"","sources":["../../src/formalize/feedback.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAwC7D"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Classify a SolverResult into a human-readable feedback string
|
|
3
|
+
* for the correction loop. This helps the LLM understand what went
|
|
4
|
+
* wrong and how to fix it.
|
|
5
|
+
*/
|
|
6
|
+
export function classifyFeedback(result) {
|
|
7
|
+
switch (result.status) {
|
|
8
|
+
case "error":
|
|
9
|
+
return `Solver error: ${result.error}`;
|
|
10
|
+
case "unsat": {
|
|
11
|
+
// Forward-compatible with Phase 1 unsatCore
|
|
12
|
+
const core = result.unsatCore;
|
|
13
|
+
if (core && core.length > 0) {
|
|
14
|
+
return `UNSAT — these assertions conflict:\n${core.map((c) => ` - ${c}`).join("\n")}\nThe specification is over-constrained. Remove or weaken one of the conflicting assertions.`;
|
|
15
|
+
}
|
|
16
|
+
return "UNSAT — the constraints are contradictory. The specification is over-constrained.";
|
|
17
|
+
}
|
|
18
|
+
case "sat": {
|
|
19
|
+
const entries = Object.entries(result.model);
|
|
20
|
+
if (entries.length === 0) {
|
|
21
|
+
return "SAT — the constraints are satisfiable (trivially, no variables).";
|
|
22
|
+
}
|
|
23
|
+
const modelStr = entries.map(([k, v]) => `${k} = ${v}`).join(", ");
|
|
24
|
+
return `SAT — the solver found a satisfying assignment: ${modelStr}. If this was unexpected, the spec may be under-constrained.`;
|
|
25
|
+
}
|
|
26
|
+
case "success": {
|
|
27
|
+
if (result.answers.length === 0) {
|
|
28
|
+
return "No Prolog solutions found. Check if facts and rules cover the query pattern. Verify clause heads match.";
|
|
29
|
+
}
|
|
30
|
+
const ansStr = result.answers
|
|
31
|
+
.slice(0, 5)
|
|
32
|
+
.map((a) => a.formatted)
|
|
33
|
+
.join("; ");
|
|
34
|
+
const suffix = result.answers.length > 5
|
|
35
|
+
? ` (and ${result.answers.length - 5} more)`
|
|
36
|
+
: "";
|
|
37
|
+
return `Prolog found ${result.answers.length} answer(s): ${ansStr}${suffix}`;
|
|
38
|
+
}
|
|
39
|
+
case "unknown":
|
|
40
|
+
return "Solver returned UNKNOWN — the problem may be too complex or outside the solver's decidable fragment. Try simplifying constraints.";
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=feedback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feedback.js","sourceRoot":"","sources":["../../src/formalize/feedback.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAoB;IACnD,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,OAAO;YACV,OAAO,iBAAiB,MAAM,CAAC,KAAK,EAAE,CAAC;QAEzC,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,4CAA4C;YAC5C,MAAM,IAAI,GAAI,MAAc,CAAC,SAAiC,CAAC;YAC/D,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5B,OAAO,uCAAuC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,8FAA8F,CAAC;YACrL,CAAC;YACD,OAAO,mFAAmF,CAAC;QAC7F,CAAC;QAED,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC7C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,kEAAkE,CAAC;YAC5E,CAAC;YACD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnE,OAAO,mDAAmD,QAAQ,8DAA8D,CAAC;QACnI,CAAC;QAED,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAChC,OAAO,yGAAyG,CAAC;YACnH,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO;iBAC1B,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;iBACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;iBACvB,IAAI,CAAC,IAAI,CAAC,CAAC;YACd,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;gBACtC,CAAC,CAAC,SAAS,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,QAAQ;gBAC5C,CAAC,CAAC,EAAE,CAAC;YACP,OAAO,gBAAgB,MAAM,CAAC,OAAO,CAAC,MAAM,eAAe,MAAM,GAAG,MAAM,EAAE,CAAC;QAC/E,CAAC;QAED,KAAK,SAAS;YACZ,OAAO,mIAAmI,CAAC;IAC/I,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CodeGraph } from "./types.js";
|
|
2
|
+
export type AnalysisType = "summary" | "callers" | "callees" | "reachability" | "dead-code" | "cycles" | "path" | "impact" | "facts";
|
|
3
|
+
export interface AnalysisRequest {
|
|
4
|
+
analysis: AnalysisType;
|
|
5
|
+
target?: string;
|
|
6
|
+
from?: string;
|
|
7
|
+
to?: string;
|
|
8
|
+
entryPoints?: string[];
|
|
9
|
+
}
|
|
10
|
+
export interface AnalysisResult {
|
|
11
|
+
analysis: AnalysisType;
|
|
12
|
+
result: unknown;
|
|
13
|
+
}
|
|
14
|
+
/** Run a graph analysis on the given source files */
|
|
15
|
+
export declare function runAnalysis(filePaths: string[], request: AnalysisRequest): Promise<AnalysisResult>;
|
|
16
|
+
/** Also accept pre-built graph + program for testing without file I/O */
|
|
17
|
+
export declare function runAnalysisFromGraph(graph: CodeGraph, request: AnalysisRequest): Promise<AnalysisResult>;
|
|
18
|
+
//# sourceMappingURL=analyses.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyses.d.ts","sourceRoot":"","sources":["../../src/graph/analyses.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,MAAM,YAAY,GACpB,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,cAAc,GAClD,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEzD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,qDAAqD;AACrD,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EAAE,EACnB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,cAAc,CAAC,CAiCzB;AAED,yEAAyE;AACzE,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,cAAc,CAAC,CAuBzB"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { extractGraph } from "./extractor.js";
|
|
3
|
+
import { graphToProlog } from "./facts.js";
|
|
4
|
+
import { createPrologSolver } from "../solvers/prolog-solver.js";
|
|
5
|
+
/** Run a graph analysis on the given source files */
|
|
6
|
+
export async function runAnalysis(filePaths, request) {
|
|
7
|
+
// Read files from disk
|
|
8
|
+
const files = filePaths.map((p) => ({
|
|
9
|
+
path: p,
|
|
10
|
+
content: readFileSync(p, "utf-8"),
|
|
11
|
+
}));
|
|
12
|
+
const graph = extractGraph(files);
|
|
13
|
+
const program = graphToProlog(graph, request.entryPoints);
|
|
14
|
+
if (request.analysis === "facts") {
|
|
15
|
+
return { analysis: "facts", result: program };
|
|
16
|
+
}
|
|
17
|
+
if (request.analysis === "summary") {
|
|
18
|
+
return {
|
|
19
|
+
analysis: "summary",
|
|
20
|
+
result: buildSummary(graph),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
const query = buildQuery(request);
|
|
24
|
+
if (!query) {
|
|
25
|
+
return { analysis: request.analysis, result: { error: "Missing required parameters" } };
|
|
26
|
+
}
|
|
27
|
+
const solver = createPrologSolver();
|
|
28
|
+
try {
|
|
29
|
+
const solverResult = await solver.solve({ type: "prolog", program, query });
|
|
30
|
+
return { analysis: request.analysis, result: formatResult(request.analysis, solverResult) };
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
solver.dispose();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** Also accept pre-built graph + program for testing without file I/O */
|
|
37
|
+
export async function runAnalysisFromGraph(graph, request) {
|
|
38
|
+
const program = graphToProlog(graph, request.entryPoints);
|
|
39
|
+
if (request.analysis === "facts") {
|
|
40
|
+
return { analysis: "facts", result: program };
|
|
41
|
+
}
|
|
42
|
+
if (request.analysis === "summary") {
|
|
43
|
+
return { analysis: "summary", result: buildSummary(graph) };
|
|
44
|
+
}
|
|
45
|
+
const query = buildQuery(request);
|
|
46
|
+
if (!query) {
|
|
47
|
+
return { analysis: request.analysis, result: { error: "Missing required parameters" } };
|
|
48
|
+
}
|
|
49
|
+
const solver = createPrologSolver();
|
|
50
|
+
try {
|
|
51
|
+
const solverResult = await solver.solve({ type: "prolog", program, query });
|
|
52
|
+
return { analysis: request.analysis, result: formatResult(request.analysis, solverResult) };
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
solver.dispose();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function buildSummary(graph) {
|
|
59
|
+
const files = new Set(graph.defines.map((d) => d.file));
|
|
60
|
+
const functions = graph.defines.filter((d) => d.kind === "function" || d.kind === "method").length;
|
|
61
|
+
const classes = graph.defines.filter((d) => d.kind === "class").length;
|
|
62
|
+
return {
|
|
63
|
+
files: files.size,
|
|
64
|
+
functions,
|
|
65
|
+
classes,
|
|
66
|
+
callEdges: graph.calls.length,
|
|
67
|
+
imports: graph.imports.length,
|
|
68
|
+
exports: graph.exports.length,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function buildQuery(request) {
|
|
72
|
+
switch (request.analysis) {
|
|
73
|
+
case "callers":
|
|
74
|
+
if (!request.target)
|
|
75
|
+
return null;
|
|
76
|
+
return `caller_of(${request.target}, X).`;
|
|
77
|
+
case "callees":
|
|
78
|
+
if (!request.target)
|
|
79
|
+
return null;
|
|
80
|
+
return `callee_of(${request.target}, X).`;
|
|
81
|
+
case "reachability":
|
|
82
|
+
if (!request.from || !request.to)
|
|
83
|
+
return null;
|
|
84
|
+
return `reaches(${request.from}, ${request.to}).`;
|
|
85
|
+
case "dead-code":
|
|
86
|
+
return "dead(X).";
|
|
87
|
+
case "cycles":
|
|
88
|
+
return "reaches(X, X).";
|
|
89
|
+
case "path":
|
|
90
|
+
if (!request.from || !request.to)
|
|
91
|
+
return null;
|
|
92
|
+
return `path(${request.from}, ${request.to}, Path).`;
|
|
93
|
+
case "impact":
|
|
94
|
+
if (!request.target)
|
|
95
|
+
return null;
|
|
96
|
+
return `reaches(X, ${request.target}).`;
|
|
97
|
+
default:
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function formatResult(analysis, solverResult) {
|
|
102
|
+
if (solverResult.status === "error") {
|
|
103
|
+
return { error: solverResult.error };
|
|
104
|
+
}
|
|
105
|
+
if (solverResult.status !== "success") {
|
|
106
|
+
return { error: `Unexpected solver status: ${solverResult.status}` };
|
|
107
|
+
}
|
|
108
|
+
const answers = solverResult.answers;
|
|
109
|
+
switch (analysis) {
|
|
110
|
+
case "callers":
|
|
111
|
+
case "callees":
|
|
112
|
+
case "dead-code":
|
|
113
|
+
return extractUniqueValues(answers, "X");
|
|
114
|
+
case "reachability":
|
|
115
|
+
return { reachable: answers.length > 0 };
|
|
116
|
+
case "cycles": {
|
|
117
|
+
return extractUniqueValues(answers, "X");
|
|
118
|
+
}
|
|
119
|
+
case "path": {
|
|
120
|
+
if (answers.length === 0)
|
|
121
|
+
return { paths: [] };
|
|
122
|
+
// Path binding is a Prolog list — parse it
|
|
123
|
+
return {
|
|
124
|
+
paths: answers.map((a) => a.bindings.Path ?? a.formatted),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
case "impact":
|
|
128
|
+
return extractUniqueValues(answers, "X");
|
|
129
|
+
default:
|
|
130
|
+
return answers.map((a) => a.bindings);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function extractUniqueValues(answers, variable) {
|
|
134
|
+
const seen = new Set();
|
|
135
|
+
const result = [];
|
|
136
|
+
for (const a of answers) {
|
|
137
|
+
const val = a.bindings[variable];
|
|
138
|
+
if (val && !seen.has(val)) {
|
|
139
|
+
seen.add(val);
|
|
140
|
+
result.push(val);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=analyses.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyses.js","sourceRoot":"","sources":["../../src/graph/analyses.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/graph/extractor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAkE,MAAM,YAAY,CAAC;AAE5G,8DAA8D;AAC9D,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,SAAS,CAsBvF"}
|