@orangepro/orangepro-mcp 0.2.3 → 0.2.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 +39 -12
- package/dist/local/analyze/analyzer.js +61 -2
- package/dist/local/analyze/behaviorContracts.js +78 -5
- package/dist/local/analyze/parseCache.js +17 -3
- package/dist/local/analyze/treeSitter/engine.js +81 -4
- package/dist/local/autoProve.js +39 -21
- package/dist/local/cli.js +13 -3
- package/dist/local/enrich/markdown.js +11 -0
- package/dist/local/flows/flowWalker.js +11 -6
- package/dist/local/generate/generator.js +54 -3
- package/dist/local/generate/promptV5.js +12 -1
- package/dist/local/graph/ontology.js +3 -1
- package/dist/local/operations.js +61 -10
- package/dist/local/proofDoctor.js +28 -3
- package/dist/local/rtm.js +30 -26
- package/dist/local/score/risk.js +128 -37
- package/dist/local/util/walk.js +5 -4
- package/dist/local/viz/behaviorReportData.js +393 -23
- package/dist/local/viz/behaviorReportHtml.js +225 -10
- package/dist/local/viz/coverageReveal.js +29 -0
- package/dist/local/viz/payload.js +12 -5
- package/dist/local/workspace.js +25 -2
- package/package.json +7 -2
- package/scripts/spikes/go-dynamic-proof-spike.mjs +17 -13
- package/scripts/spikes/go-mutate.go +60 -21
- package/scripts/spikes/java-dynamic-proof-spike.mjs +6 -4
- package/scripts/spikes/java-mutate.mjs +3 -2
|
@@ -2,11 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
// go-mutate.go — AST-based body replacer for the Go dynamic-proof spike (G-1).
|
|
4
4
|
//
|
|
5
|
-
// Locates ONE free function `func Name(
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
5
|
+
// Locates ONE function declaration by exact name — a free function `func Name(...)`
|
|
6
|
+
// or a receiver method `func (r Recv) Name(...)` — and replaces its BODY with a
|
|
7
|
+
// signature-derived sentinel, then writes the mutated file. Invoked by
|
|
8
|
+
// go-dynamic-proof-spike.mjs (the product Go proof path); it writes ONLY the
|
|
9
|
+
// mutated file inside the sandbox copy — no graph or product artifacts. The
|
|
10
|
+
// name must resolve to exactly ONE declaration — in the whole file without
|
|
11
|
+
// --recv, or on the selected base receiver with --recv <T> (receiver-exact
|
|
12
|
+
// selection for receiver-qualified `Recv.M` targets — never the wrong decl,
|
|
13
|
+
// so A.M and B.M can coexist and still be individually mutable). Ambiguity
|
|
14
|
+
// within that filter fails(3); generic receivers are refused (not found).
|
|
10
15
|
//
|
|
11
16
|
// Modes:
|
|
12
17
|
// sentinel — replace body with a type-compatible, deliberately-wrong value
|
|
@@ -19,9 +24,10 @@
|
|
|
19
24
|
// Exit codes (distinct, so the Node orchestrator can classify precisely):
|
|
20
25
|
// 0 ok, mutated file written
|
|
21
26
|
// 2 usage / IO / parse error
|
|
22
|
-
// 3 ambiguous: more than one free
|
|
23
|
-
// 4 not found: no free function with that name
|
|
24
|
-
// 5
|
|
27
|
+
// 3 ambiguous: more than one declaration (free and/or method) with that name
|
|
28
|
+
// 4 not found: no free function or method with that name
|
|
29
|
+
// 5 RETIRED — was "method out of scope (G-2)" before methods became mutable;
|
|
30
|
+
// no longer emitted (kept so codes 3/4/6 stay stable for the orchestrator)
|
|
25
31
|
// 6 not mutable: the function has no return values (no signature-derived
|
|
26
32
|
// sentinel is possible) -> fail closed, never mutated
|
|
27
33
|
package main
|
|
@@ -51,7 +57,8 @@ func fail(code int, format string, args ...any) {
|
|
|
51
57
|
|
|
52
58
|
func main() {
|
|
53
59
|
file := flag.String("file", "", "path to the Go source file to mutate")
|
|
54
|
-
fn := flag.String("func", "", "exact name of the free function to mutate")
|
|
60
|
+
fn := flag.String("func", "", "exact name of the free function or method to mutate")
|
|
61
|
+
recv := flag.String("recv", "", "receiver base type name; when set, match only methods on this receiver")
|
|
55
62
|
out := flag.String("out", "", "path to write the mutated file (defaults to --file)")
|
|
56
63
|
mode := flag.String("mode", "sentinel", "sentinel | equivalent")
|
|
57
64
|
flag.Parse()
|
|
@@ -73,31 +80,47 @@ func main() {
|
|
|
73
80
|
fail(2, "parse error: %v", err)
|
|
74
81
|
}
|
|
75
82
|
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
// Collect BOTH free functions and methods named *fn. The proof lane only ever
|
|
84
|
+
// targets a method whose name is UNIQUE in its package (the analyzer's
|
|
85
|
+
// uniqueGoPackageSymbol refuses cross-file collisions before an edge is minted);
|
|
86
|
+
// this file-scoped count is the in-file backstop, so free+method or two-method
|
|
87
|
+
// collisions fail(3) as ambiguous — never a mislabeled mutation. A lone decl
|
|
88
|
+
// (free OR method) is mutated identically via the receiver-agnostic sentinel.
|
|
89
|
+
var matches []*ast.FuncDecl
|
|
78
90
|
for _, decl := range astFile.Decls {
|
|
79
91
|
fd, ok := decl.(*ast.FuncDecl)
|
|
80
92
|
if !ok || fd.Name == nil || fd.Name.Name != *fn {
|
|
81
93
|
continue
|
|
82
94
|
}
|
|
83
|
-
|
|
84
|
-
|
|
95
|
+
// Refuse generic receivers (r T[U]) — receiver base type is not a bare Ident.
|
|
96
|
+
if fd.Recv != nil && recvBaseIdent(fd) == nil {
|
|
85
97
|
continue
|
|
86
98
|
}
|
|
87
|
-
|
|
99
|
+
// Receiver-exact selection: when --recv is set, only a method on that base
|
|
100
|
+
// receiver type matches — a free function or another receiver never can, so
|
|
101
|
+
// a receiver-qualified target can never mutate the wrong declaration.
|
|
102
|
+
if *recv != "" {
|
|
103
|
+
if fd.Recv == nil {
|
|
104
|
+
continue
|
|
105
|
+
}
|
|
106
|
+
if id := recvBaseIdent(fd); id == nil || id.Name != *recv {
|
|
107
|
+
continue
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
matches = append(matches, fd)
|
|
88
111
|
}
|
|
89
112
|
|
|
90
|
-
if len(
|
|
91
|
-
fail(3, "ambiguous: %d
|
|
113
|
+
if len(matches) > 1 {
|
|
114
|
+
fail(3, "ambiguous: %d declarations named %q (free and/or methods)", len(matches), *fn)
|
|
92
115
|
}
|
|
93
|
-
if len(
|
|
94
|
-
if
|
|
95
|
-
fail(
|
|
116
|
+
if len(matches) == 0 {
|
|
117
|
+
if *recv != "" {
|
|
118
|
+
fail(4, "not found: no method named %q on receiver %q", *fn, *recv)
|
|
96
119
|
}
|
|
97
|
-
fail(4, "not found: no free function named %q", *fn)
|
|
120
|
+
fail(4, "not found: no free function or method named %q", *fn)
|
|
98
121
|
}
|
|
99
122
|
|
|
100
|
-
target :=
|
|
123
|
+
target := matches[0]
|
|
101
124
|
results := target.Type.Results
|
|
102
125
|
if results == nil || len(results.List) == 0 {
|
|
103
126
|
fail(6, "not mutable: %q has no return values; no signature-derived sentinel is possible", *fn)
|
|
@@ -160,6 +183,22 @@ func blankUnusedImports(f *ast.File) {
|
|
|
160
183
|
}
|
|
161
184
|
}
|
|
162
185
|
|
|
186
|
+
// recvBaseIdent returns the receiver type's base identifier for a method decl
|
|
187
|
+
// (unwrapping a pointer receiver `*T` to `T`), or nil for a generic/unsupported
|
|
188
|
+
// receiver. Used only to refuse generic receivers; value-vs-pointer is irrelevant
|
|
189
|
+
// to body mutation (Go auto-(de)refs at the call site).
|
|
190
|
+
func recvBaseIdent(fd *ast.FuncDecl) *ast.Ident {
|
|
191
|
+
if fd.Recv == nil || len(fd.Recv.List) != 1 {
|
|
192
|
+
return nil
|
|
193
|
+
}
|
|
194
|
+
t := fd.Recv.List[0].Type
|
|
195
|
+
if star, ok := t.(*ast.StarExpr); ok {
|
|
196
|
+
t = star.X
|
|
197
|
+
}
|
|
198
|
+
id, _ := t.(*ast.Ident)
|
|
199
|
+
return id
|
|
200
|
+
}
|
|
201
|
+
|
|
163
202
|
// sentinelBody builds `{ return <zero>, <zero>, ... }` matching the function's
|
|
164
203
|
// result signature so the mutant COMPILES. Zero values are type-derived and
|
|
165
204
|
// deliberately wrong for any function whose real return is non-zero; when a
|
|
@@ -21,9 +21,11 @@
|
|
|
21
21
|
// classify as `unrunnable`, never `proven`. An equivalent-value mutation survives ->
|
|
22
22
|
// `associated_survived`. An ambiguous method name is refused -> `unrunnable`.
|
|
23
23
|
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
24
|
+
// PRODUCT-WIRED: `opro` routes Java dynamic proof through this script (operations.ts
|
|
25
|
+
// dynamicProofSpikePathFor("java")). The script itself writes no graph edges or
|
|
26
|
+
// product artifacts — it emits a JSON verdict; the orchestrator is the sole
|
|
27
|
+
// interpreter and the only place proof is minted. Pin: Maven + Surefire + JUnit 5
|
|
28
|
+
// (the Spring Boot default). Gradle / JUnit4 are later parsers.
|
|
27
29
|
import { spawnSync } from "node:child_process";
|
|
28
30
|
import { cpSync, existsSync, lstatSync, mkdtempSync, mkdirSync, readFileSync, readdirSync, rmSync } from "node:fs";
|
|
29
31
|
import { tmpdir } from "node:os";
|
|
@@ -40,7 +42,7 @@ function usage() {
|
|
|
40
42
|
"",
|
|
41
43
|
"Runs ONE Surefire target test on a byte-copy of a single-module Maven + JUnit 5 project, mutates the target method body via a signature-derived sentinel, reruns the SAME test, and classifies from the structured surefire report.",
|
|
42
44
|
"J-1 scope: SIMPLEST SHAPE ONLY — a concrete non-void return, a single top-level return, no generics, no overloads. Equivalent-value mutations survive (associated_survived). Ambiguous names are refused (unrunnable).",
|
|
43
|
-
"
|
|
45
|
+
"Product wiring: opro prove/auto-prove invokes this script for Java targets; it writes no graph edges or product artifacts itself — the caller interprets the JSON verdict."
|
|
44
46
|
].join("\n");
|
|
45
47
|
}
|
|
46
48
|
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
// by exact name via tree-sitter Java (the SAME grammar the static layer already
|
|
6
6
|
// uses — tree-sitter-wasms + web-tree-sitter, no new dependency) and replaces its
|
|
7
7
|
// BODY with a signature-derived, type-compatible sentinel by splicing the body
|
|
8
|
-
// block's byte range.
|
|
9
|
-
//
|
|
8
|
+
// block's byte range. Invoked by java-dynamic-proof-spike.mjs (the product Java
|
|
9
|
+
// proof path); it writes ONLY the mutated file inside the sandbox copy — no graph
|
|
10
|
+
// or product artifacts.
|
|
10
11
|
//
|
|
11
12
|
// J-1 scope is the SIMPLEST SHAPE ONLY: a concrete non-void, non-type-variable
|
|
12
13
|
// return type, EXACTLY one top-level `return <expr>;` (no nested return in an
|