@orangepro/orangepro-mcp 0.1.0

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.
Files changed (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +328 -0
  3. package/dist/local/agentWorkflow.js +81 -0
  4. package/dist/local/aiGraph/links.js +635 -0
  5. package/dist/local/analyze/analyzer.js +2129 -0
  6. package/dist/local/analyze/behaviorContracts.js +169 -0
  7. package/dist/local/analyze/boilerplate.js +42 -0
  8. package/dist/local/analyze/callGraph.js +458 -0
  9. package/dist/local/analyze/classify.js +219 -0
  10. package/dist/local/analyze/clustering.js +357 -0
  11. package/dist/local/analyze/confirm.js +2422 -0
  12. package/dist/local/analyze/coverage.js +518 -0
  13. package/dist/local/analyze/coverageArtifacts.js +607 -0
  14. package/dist/local/analyze/frameworks.js +115 -0
  15. package/dist/local/analyze/linkage/conventions.js +160 -0
  16. package/dist/local/analyze/parseCache.js +164 -0
  17. package/dist/local/analyze/selfAssert.js +53 -0
  18. package/dist/local/analyze/symbols.js +430 -0
  19. package/dist/local/analyze/testLayer.js +135 -0
  20. package/dist/local/analyze/treeSitter/engine.js +1253 -0
  21. package/dist/local/analyze/treeSitter/languages.js +101 -0
  22. package/dist/local/autoProve.js +620 -0
  23. package/dist/local/cli.js +1468 -0
  24. package/dist/local/cliArgs.js +112 -0
  25. package/dist/local/corpusScope.js +162 -0
  26. package/dist/local/enrich/csv.js +348 -0
  27. package/dist/local/enrich/index.js +43 -0
  28. package/dist/local/enrich/markdown.js +193 -0
  29. package/dist/local/explain/explain.js +91 -0
  30. package/dist/local/exportCli.js +26 -0
  31. package/dist/local/flows/flowWalker.js +215 -0
  32. package/dist/local/flows/llmFlowDiscovery.js +567 -0
  33. package/dist/local/freshness/changed.js +280 -0
  34. package/dist/local/freshness/manifest.js +35 -0
  35. package/dist/local/freshness/status.js +30 -0
  36. package/dist/local/gaps/gaps.js +114 -0
  37. package/dist/local/generate/buckets.js +73 -0
  38. package/dist/local/generate/compareJudge.js +124 -0
  39. package/dist/local/generate/compareReport.js +538 -0
  40. package/dist/local/generate/compareScore.js +105 -0
  41. package/dist/local/generate/deriveImports.js +91 -0
  42. package/dist/local/generate/generator.js +2586 -0
  43. package/dist/local/generate/prompt.js +144 -0
  44. package/dist/local/generate/promptV5.js +438 -0
  45. package/dist/local/generate/providers.js +400 -0
  46. package/dist/local/generate/runHints.js +304 -0
  47. package/dist/local/graph/citations.js +73 -0
  48. package/dist/local/graph/confirmable.js +72 -0
  49. package/dist/local/graph/factories.js +210 -0
  50. package/dist/local/graph/ontology.js +18 -0
  51. package/dist/local/interactive.js +53 -0
  52. package/dist/local/jobs/jobStore.js +80 -0
  53. package/dist/local/jobs/notify.js +29 -0
  54. package/dist/local/jobs/runner.js +75 -0
  55. package/dist/local/ledger.js +117 -0
  56. package/dist/local/localConfig.js +112 -0
  57. package/dist/local/mcp.js +548 -0
  58. package/dist/local/operations.js +1749 -0
  59. package/dist/local/pack/coverageReport.js +192 -0
  60. package/dist/local/pack/exporter.js +195 -0
  61. package/dist/local/pack/schema.js +128 -0
  62. package/dist/local/pack/summary.js +127 -0
  63. package/dist/local/pack/validate.js +25 -0
  64. package/dist/local/proofRunnability.js +366 -0
  65. package/dist/local/recipe/dbSqljs.js +255 -0
  66. package/dist/local/reprove/paths.js +13 -0
  67. package/dist/local/reprove/scoped.js +136 -0
  68. package/dist/local/resolve/barrelWalker.js +178 -0
  69. package/dist/local/resolve/exportIndex.js +270 -0
  70. package/dist/local/resolve/importGraph.js +347 -0
  71. package/dist/local/resolve/resolver.js +122 -0
  72. package/dist/local/resolve/resolverCache.js +117 -0
  73. package/dist/local/rtm.js +413 -0
  74. package/dist/local/score/coverage.js +99 -0
  75. package/dist/local/score/doctor.js +67 -0
  76. package/dist/local/score/risk.js +362 -0
  77. package/dist/local/score/score.js +182 -0
  78. package/dist/local/types.js +1 -0
  79. package/dist/local/util/hash.js +16 -0
  80. package/dist/local/util/ids.js +16 -0
  81. package/dist/local/util/progress.js +8 -0
  82. package/dist/local/util/redact.js +39 -0
  83. package/dist/local/util/time.js +1 -0
  84. package/dist/local/util/walk.js +174 -0
  85. package/dist/local/viz/behaviorReportData.js +367 -0
  86. package/dist/local/viz/behaviorReportHtml.js +664 -0
  87. package/dist/local/viz/d3.bundle.js +3 -0
  88. package/dist/local/viz/html.js +1152 -0
  89. package/dist/local/viz/payload.js +525 -0
  90. package/dist/local/workspace.js +99 -0
  91. package/docs/agent-workflow.md +167 -0
  92. package/docs/agents/claude-code.md +43 -0
  93. package/docs/agents/codex.md +52 -0
  94. package/docs/agents/cursor.md +39 -0
  95. package/docs/agents/opencode.md +43 -0
  96. package/docs/agents/vscode.md +34 -0
  97. package/docs/local-proof-kit.md +269 -0
  98. package/package.json +92 -0
  99. package/scripts/spikes/dynamic-proof-jest-reporter.cjs +66 -0
  100. package/scripts/spikes/dynamic-proof-mocha-reporter.cjs +105 -0
  101. package/scripts/spikes/dynamic-proof-spike.mjs +2335 -0
  102. package/scripts/spikes/dynamic-proof-vitest-reporter.mjs +81 -0
  103. package/scripts/spikes/failure-summary.mjs +29 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OrangePro (OrangeproAI)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,328 @@
1
+ # OrangePro (`opro`)
2
+
3
+ **Point your coding agent at a pull request and it writes grounded, traceable tests for exactly the code that changed** — local-first, bring-your-own-key, with **no tenant, no repo access, and metadata-only artifacts**.
4
+
5
+ `opro` builds a lightweight evidence **Knowledge Graph** from a local checkout, finds the behaviors a diff touches, and generates tests that are *grounded* in real symbols, files, and existing tests — so an AI agent stops hallucinating imports and selectors and starts citing evidence. It runs as a **CLI** and an **MCP server**, so Cursor, Claude Code, Codex, or any MCP client can drive it.
6
+
7
+ > **Try it in ~60 seconds** (offline, no key needed):
8
+ > ```bash
9
+ > git clone https://github.com/OrangeproAI/orangepro-mcp.git
10
+ > cd orangepro-mcp && npm ci && npm run build && npm link
11
+ > node scripts/demo-local-proof-kit.mjs --repo . --provider deterministic
12
+ > ```
13
+
14
+ ## What it does
15
+
16
+ ```
17
+ opro # analyze, optional AI links + flows, report, RTM, agent next actions
18
+ opro start --base main # same flow, scoped to a branch/PR diff
19
+ opro start . --generate-coverage # run repo-native coverage first, then graph + optional AI
20
+ opro analyze . --ai-flows # build graph + AI candidate-flow worklist + report
21
+ opro score # how test-ready is this repo? (with reasons)
22
+ opro gaps --limit 10 # behaviors with weak / missing tests
23
+ opro generate --base main # PR-scoped: tests ONLY for what the diff touches
24
+ opro generate --pr 1234 # check out PR #1234 (gh) and target its diff
25
+ opro generate --changed # target the current branch's diff vs main/master
26
+ opro generate --single --limit 3 # whole-repo: top-gap behavior, grounded tests
27
+ opro export --out evidence-pack.json --graph-html # metadata-only evidence pack + explorer
28
+ opro mcp # run as an MCP server (stdio)
29
+ ```
30
+
31
+ Add `--json` to any read command for machine output. Run `opro help` for the full reference.
32
+
33
+ ## Quickstart — your first Proven
34
+
35
+ **"Proven" counts only a real test that kills a targeted mutant of a behavior.** Two things follow, and they surprise people:
36
+
37
+ - **You need a BYOK model key to reach Proven** — it's what generates the test. `export OPENAI_API_KEY=…` (or `ANTHROPIC_API_KEY=…`). No key → no generated tests → `Proven 0`, and OrangePro tells you so.
38
+ - **`Proven 0` on a fresh `opro analyze` is normal, not broken.** It means no proof has run yet. Static tests and associations show as **Associated signal**, never Proven, until a real test kills a targeted mutant. That's the whole trust model — nothing is labeled Proven on faith.
39
+
40
+ **The intended path is one ask, not a command sequence.** In Cursor / Claude Code / Codex with the OrangePro MCP, tell your agent to cover a behavior — it runs `orangepro_generate_tests`, writes and runs the test, then `orangepro_prove`, and the behavior turns Proven. See [Use with your coding agent](#use-with-your-coding-agent-the-headline-workflow) for the exact setup.
41
+
42
+ Open `.orangepro/behavior-coverage.html` and click any behavior to see its evidence tier and exactly what to do next.
43
+
44
+ ## Languages supported
45
+
46
+ OrangePro reports behavioral gaps, not “unit test count.” Coverage is reported as
47
+ separate behavior-status lanes — never blended into one proof number. Public
48
+ glossary:
49
+
50
+ - **Dynamically Proven** (shown as "Dynamically Proven" in the report, CLI, and RTM) — a dynamic targeted-proof ledger certificate closed for the behavior: baseline green, target mutated, same test failed at an assertion, and the target was not mocked. OrangePro maps the whole repo statically, then dynamically proves only the top few eligible behaviors per run (default 5, raise with `--auto-limit`); everything else stays a static signal, never Proven.
51
+ - **Runtime-covered** — the repo's own coverage tool executed the code. This is actual runtime coverage, but not assertion-level proof.
52
+ - **Static Associated signal** — a name, path, import, or structural match links a test to the code. Useful for triage, but not semantic proof and never counted as Dynamically Proven. The HTML report labels this tier **Statically Linked**.
53
+ - **No integration signal** — no direct static test signal was found yet. This does not mean “untested”; broad integration/e2e coverage may exist without mapping one-to-one to a symbol. In the HTML report this tier is shown as **Reachable Untested** (the symbol appears in a static flow from an entry point) or **No Signal** (no test or static-flow signal yet) — a display-only split that changes no classification.
54
+
55
+ OrangePro can ingest Go coverprofiles, JS/TS `lcov.info`, Python `coverage.xml`
56
+ from coverage.py/pytest-cov, and Java JaCoCo XML. `opro coverage --generate`
57
+ auto-runs Go coverage, repo-defined JS/TS coverage scripts, pytest-cov XML, and
58
+ Maven/Gradle JaCoCo where the repo has the standard local tooling installed.
59
+
60
+ | Language | Symbol extraction | Generated tests | Runtime coverage | Static assertion candidates |
61
+ |---|---:|---:|---:|---:|
62
+ | TypeScript / JavaScript | ✓ | ✓ Jest/Vitest/AVA/etc. | ✓ `lcov.info` | ✓ strongest support |
63
+ | Go | ✓ | ✓ same-package `*_test.go` | ✓ coverprofile | ✓ limited shapes |
64
+ | Python | ✓ | ✓ pytest drafts + marker-aware run hints | ✓ coverage.py / pytest-cov XML | ✓ limited pytest assert shapes |
65
+ | Java | ✓ | ✓ JUnit 4/5 drafts + run hints | ✓ JaCoCo XML | ✓ limited JUnit assert shapes |
66
+
67
+ > **Static assertion candidates are strongest for TypeScript/JavaScript.** “Strongest support” does not mean public Proven; it means TS/JS has the most complete deterministic static association resolver today. Public Proven is stricter and requires the dynamic targeted-proof ledger certificate. **Runtime coverage** is a first-class signal for Go, Java, Python, and TS/JS. Runtime-covered, static candidates, and associated signals never move the Proven percentage.
68
+
69
+ Extraction is language-agnostic (tree-sitter), so more languages are additive — a config entry plus a grammar.
70
+
71
+ ### Open-source proof snapshot
72
+
73
+ These numbers are a reproducible snapshot, not a universal benchmark. They come from
74
+ the fresh-history public export of this repo at `5de25ca`, with AI disabled and no
75
+ runtime coverage generation:
76
+
77
+ ```bash
78
+ node scripts/export-public-local-repo.mjs /tmp/orangepro-public
79
+ opro start /tmp/orangepro-public --no-ai
80
+ ```
81
+
82
+ | Signal | Count |
83
+ |---|---:|
84
+ | Files scanned | 344 |
85
+ | Eligible behaviors | 258 |
86
+ | Static assertion candidates | 133 (51.6%) |
87
+ | Runtime-covered | 0 *(coverage generation was not run for this snapshot)* |
88
+ | Associated signal | 91 |
89
+ | No integration signal | 34 |
90
+
91
+ This snapshot predates the dynamic-Proven gate, so those 133 rows are static
92
+ assertion candidates, not public Proven. `Runtime-covered` and `Associated signal`
93
+ also remain separate lanes and never move the Proven percentage.
94
+
95
+ ## Test cases we generate
96
+
97
+ Generation is **evidence-gated** — a category is produced only when the graph has supporting evidence for it, never padded with generic filler. The categories:
98
+
99
+ | Category | What it targets |
100
+ |----------|-----------------|
101
+ | **Happy path** | The primary expected behavior |
102
+ | **Validation error** | Bad/invalid input handling |
103
+ | **Edge case** | Boundaries, empty/null, limits, concurrency, retries |
104
+ | **Integration flow** | Multi-step behavior across components |
105
+ | **Security / privacy** | Authz, sensitive-data, injection-style concerns |
106
+ | **Regression** | Pinning a previously-broken behavior |
107
+
108
+ Each generated test carries its **grounding** (the real files/symbols/tests it cites) and **run hints** (where to put it, how to run it), so an agent can write it, run it, and report pass/fail.
109
+
110
+ For runnable Python and Go output, the local validator must be able to call the normal language tools on your PATH (`python3` for pytest syntax checks, `gofmt` for Go syntax checks). If a generated body cannot be validated, OrangePro returns it as a grounded draft with no run command instead of pretending it is runnable.
111
+
112
+ ## Use with your coding agent (the headline workflow)
113
+
114
+ The agent already has shell access, so `opro` prepares the graph/RTM and then generates test **code** with run hints — the agent writes the file, runs it, and reports back. `opro` itself never writes source/test files into your repo and never runs commands.
115
+
116
+ Run `opro` first in the repo. It writes `.orangepro/behavior-coverage.html`, `.orangepro/rtm.md`, and next actions. If a real model provider is configured through your environment, local `.env.provider.local` / `.env.local` / `.env`, or `opro setup`, weak AI grounding and AI-suggested candidate flows run automatically; otherwise the deterministic artifacts are still produced and AI is clearly skipped.
117
+
118
+ Report commands default to `.orangepro/`, but explicit `--out` paths can point at another local review/artifact directory, for example `opro rtm --format json --out /tmp/orangepro-run/rtm.json`.
119
+
120
+ For large repos, `opro start` prints a preflight breakdown before long work starts. It shows the biggest top-level directories, suggests focused scopes such as `opro start server/public --generate-coverage`, and still offers `opro start . --generate-coverage --no-ai` for a full deterministic local graph.
121
+
122
+ On large repos, the AI grounding lane is budgeted instead of sending the whole symbol catalog to the model. OrangePro shortlists product CodeSymbols per behavior, batches requests, and records partial progress in `.orangepro/ai/links.json`. These links are weak suggestions for generation only; they never change Proven coverage. Tune the automatic pass with:
123
+
124
+ | Env | Default | Meaning |
125
+ |---|---:|---|
126
+ | `ORANGEPRO_AI_LINK_MAX_BEHAVIORS` | `80` | Maximum behavior gaps processed in one AI-link run |
127
+ | `ORANGEPRO_AI_LINK_SYMBOLS_PER_BEHAVIOR` | `40` | Product CodeSymbol shortlist size per behavior |
128
+ | `ORANGEPRO_AI_LINK_MAX_PROMPT_TOKENS` | `30000` | Approximate prompt token ceiling per batch |
129
+
130
+ For a wider one-off link run, use `opro ai-links --max-behaviors 300 --symbols-per-behavior 50 --max-prompt-tokens 30000` followed by `opro ai-links --apply`. For explicit candidate-flow discovery outside `opro start`, use `opro analyze --ai-flows` or the lower-level `opro ai-flows && opro ai-flows --apply`.
131
+
132
+ For Codex, install the plugin when it is available in your configured marketplace:
133
+
134
+ ```bash
135
+ codex plugin add orangepro
136
+ ```
137
+
138
+ Until OrangePro is accepted into a default marketplace, add this repo as a Codex marketplace and install from it:
139
+
140
+ ```bash
141
+ codex plugin marketplace add OrangeproAI/orangepro-mcp --sparse .agents/plugins --sparse plugins/orangepro
142
+ codex plugin add orangepro@orangepro
143
+ ```
144
+
145
+ For maintainer-local development before npm publishing, use the personal marketplace entry:
146
+
147
+ ```bash
148
+ codex plugin add orangepro@personal
149
+ ```
150
+
151
+ For Claude Code, add the OrangePro marketplace and install the bundled MCP plugin:
152
+
153
+ ```text
154
+ /plugin marketplace add OrangeproAI/orangepro-mcp
155
+ /plugin install orangepro@orangepro
156
+ /reload-plugins
157
+ ```
158
+
159
+ For Cursor, install OrangePro from the Cursor Marketplace when listed. Until then, use the bundled Cursor plugin at `plugins/orangepro` for local testing, or add the MCP server manually from [docs/agents/cursor.md](docs/agents/cursor.md).
160
+
161
+ Run `opro agent --client claude-code|cursor|codex|opencode` to print a client-ready MCP config and copy-paste agent instructions for clients that do not install plugins yet. See [docs/agent-workflow.md](docs/agent-workflow.md) for the full write/run/report loop and the per-agent install notes:
162
+
163
+ - [Codex](docs/agents/codex.md)
164
+ - [Claude Code](docs/agents/claude-code.md)
165
+ - [Cursor](docs/agents/cursor.md)
166
+ - [OpenCode](docs/agents/opencode.md)
167
+ - [VS Code / Copilot](docs/agents/vscode.md)
168
+
169
+ ### Public plugin publishing checklist
170
+
171
+ Before announcing plugin installs publicly:
172
+
173
+ 1. Publish the npm package with the `opro` bin: `npm publish --access public`.
174
+ 2. Create the fresh-history public export and verify it has one commit, no private history, and no private artifacts.
175
+ 3. Codex: keep `.agents/plugins/marketplace.json` + `plugins/orangepro`; the repo marketplace install works from this public repo. The bare `codex plugin add orangepro` path requires OrangePro to be present in a configured/default Codex marketplace.
176
+ 4. Claude Code: keep `.claude-plugin/marketplace.json` + `plugins/orangepro`; users can add this repo as a Claude plugin marketplace. Directory-style discovery requires submitting/listing the marketplace through Claude's plugin ecosystem.
177
+ 5. Cursor: keep `plugins/orangepro/.cursor-plugin/plugin.json`, `rules/`, and `.mcp.json`; submit the same plugin bundle to the Cursor Marketplace when ready.
178
+ 6. OpenCode / VS Code: publish the documented MCP config snippets using `npx -y -p @orangepro/orangepro-mcp@latest opro mcp`.
179
+ 7. Smoke each install path in a clean repo and confirm `orangepro_start` works with no pinned model and no committed key.
180
+
181
+ **On a pull request**, point your agent at the changed code:
182
+
183
+ ```
184
+ You (to your agent): "Use orangepro_start, then use orangepro_generate_tests with base_ref=main.
185
+ Write each
186
+ test to its suggested_path, run it, and report pass/fail."
187
+ ```
188
+
189
+ The `orangepro_generate_tests` tool returns, per test: the body, the **grounding** it used (real files/symbols/tests it cites), `run_hints` (a `suggested_path` next to the linked test + a `run_command` like `npx jest …`), and an `agent_workflow`:
190
+
191
+ 1. Write each test body to its `suggested_path`.
192
+ 2. Run its `run_command` (or the repo's own `npm test` / `pytest`).
193
+ 3. After a pass, call the returned `prove_run` args so OrangePro can dynamically prove the target. `record_run` is static diagnostics only.
194
+ 4. Report pass/fail + stack traces, and propose fixes.
195
+
196
+ Generation never fabricates a PR: a non-git checkout, a missing base ref, or a docs-only diff returns structured guidance (`not_a_git_repo` / `missing_base_ref` / `no_diff` / `no_code_changes`), never invented tests.
197
+
198
+ ## Why it's safe to run
199
+
200
+ - **No stored source.** Source is read in-process to ground analysis/generation. When model generation is enabled, redacted source excerpts may be sent to your configured BYOK provider; OrangePro does not upload repos to an OrangePro tenant and does not store raw source in local artifacts.
201
+ - **No source/test writes.** It never writes source or test files into your repo. The only writes are workspace metadata under `.orangepro/` — analyze from a throwaway directory for zero writes inside the target checkout.
202
+ - **Metadata-only exports.** The evidence pack and graph HTML carry file paths, names, hashes, frameworks, provenance, and scores — **not** raw source, prompts, scoring weights, or ranking traces. Generated test bodies are opt-in (`export --include-generated-bodies`).
203
+ - **Your keys stay yours.** Model keys are read from the environment at call time and never written into the graph, config, or pack.
204
+
205
+ ## Trust-loop smoke
206
+
207
+ After `npm run build`, run the repeatable gap-fill smoke:
208
+
209
+ ```bash
210
+ node scripts/smoke-gap-fill-loop.mjs
211
+ ```
212
+
213
+ It creates a disposable TypeScript/Vitest repo with an unproven behavior, confirms
214
+ the row starts at `No integration signal`, writes a real assertion test, then runs
215
+ `opro prove` to execute the dynamic targeted-proof oracle. The row becomes
216
+ `Reproven (this run)` only after baseline-green → mutant assertion-fail closes a
217
+ metadata-only ledger certificate. This is the smallest local proof that OrangePro's
218
+ public Proven number moves because a real dynamic kill happened, not because an
219
+ LLM or static matcher claimed coverage.
220
+
221
+ ## Install
222
+
223
+ ```bash
224
+ git clone https://github.com/OrangeproAI/orangepro-mcp.git
225
+ cd orangepro-mcp
226
+ npm ci
227
+ npm run build # compiles the CLI to dist/local/cli.js
228
+ npm link # one-time: puts the `opro` command on your PATH
229
+ ```
230
+
231
+ Prefer not to link? Every `opro <command>` is equivalent to `node dist/local/cli.js <command>`.
232
+
233
+ ## Model selection (BYOK)
234
+
235
+ Generation uses **your** model key. Pick one provider; with none set, auto-detect order is **OpenAI-compatible → Ollama → Anthropic**.
236
+
237
+ | Provider | Env |
238
+ |---|---|
239
+ | OpenAI-compatible | `OPENAI_API_KEY`, optional `OPENAI_BASE_URL`, `OPENAI_MODEL` |
240
+ | Anthropic | `ANTHROPIC_API_KEY`, optional `ANTHROPIC_MODEL`, `ANTHROPIC_BASE_URL` |
241
+ | Ollama (local, no key) | `OLLAMA_BASE_URL`, optional `OLLAMA_MODEL` |
242
+
243
+ `--provider openai|anthropic|ollama|deterministic` and `--model <name>` override the env. With `OPENAI_API_KEY` set and no explicit model, OrangePro defaults to `gpt-4.1` for generation quality. Run **`opro setup`** once to pick a provider + model interactively (saved to `.orangepro/config.json`; **keys stay in your env, never saved**), or just run `opro generate` with no provider in a terminal and it prompts you. Newer OpenAI reasoning models (`gpt-5*`, o-series) work automatically.
244
+
245
+ For local agent runs, you may also put provider values in `.env.provider.local`, `.env.local`, or `.env` in the repo/workspace. OrangePro reads only provider-related keys from those files at runtime; real environment variables override file values, and keys are never written to graph, RTM, HTML, or export artifacts.
246
+
247
+ **No silent fallback.** With no key set, `generate` returns setup guidance and produces **no tests**. The offline deterministic stand-in is opt-in only (`--provider deterministic`). Analyze, score, gaps, and export never need a model.
248
+
249
+ > Use a strong current model for real evaluation. Cheaper/smaller models may be fine for smoke tests, but they produce more draft or non-runnable tests on real repos.
250
+
251
+ ## Current Language Support
252
+
253
+ OrangePro separates **what it can parse**, **what it can prove**, and **what it can generate/run**. Those are intentionally different bars.
254
+
255
+ | Capability | Current status |
256
+ |---|---|
257
+ | Product/test/config/doc parsing | TypeScript/JavaScript, Python, Go, Java, Kotlin, Rust, PHP, C#, Ruby, Swift, C, C++, Markdown/config metadata |
258
+ | Structural associations | Broad non-TS graph signals: imports/calls/test naming/framework/package signals stay **Associated signal**, never Proven |
259
+ | Static assertion candidates | TypeScript/JavaScript (strongest deterministic confirmer), plus limited exact-resolved shapes for Go, Python, and Java can mint hard `COVERS`/`TESTED_BY` graph edges for diagnostics. These render as **Associated signal**, not public Proven. Public Proven requires a dynamic targeted-proof ledger certificate from `opro prove`. |
260
+ | Runnable generated tests | TypeScript/JavaScript (including AVA), Python (marker-aware pytest hints), Go, and Java (JUnit 4/5), with framework/path/run hints and safe draft fallback when the output cannot be validated |
261
+ | Runtime coverage ingestion | Go coverprofiles, JS/TS `lcov.info`, Python `coverage.xml`, Java JaCoCo XML. Go, repo-defined JS/TS coverage scripts, pytest-cov XML, and Maven/Gradle JaCoCo can be generated locally with `--generate-coverage` when the repo's normal test tooling is installed. |
262
+ | AI grounding | Optional weak `AI-linked` behavior→symbol suggestions and AI-suggested candidate flow worklists. These guide generation/review but **do not** change Proven coverage, deterministic flow counts, or tiers. |
263
+
264
+ Coming next:
265
+
266
+ - Listing OrangePro in the public Codex/Claude/Cursor/OpenCode plugin marketplaces (bundled plugins and a publishing checklist already ship in this repo — see the install steps above).
267
+ - More deterministic proof recall for non-TS/Go languages, only when false-confirm tests make it safe.
268
+
269
+ ## MCP setup (any client)
270
+
271
+ `opro` runs as a standard MCP server over stdio. Add this block to your client's MCP config (only the file location differs per client):
272
+
273
+ ```json
274
+ {
275
+ "mcpServers": {
276
+ "orangepro-local": {
277
+ "command": "node",
278
+ "args": ["/absolute/path/to/orangepro-mcp/dist/local/cli.js", "mcp"],
279
+ "env": {}
280
+ }
281
+ }
282
+ }
283
+ ```
284
+
285
+ Provider keys and model defaults are inherited from the agent process environment, `.env.provider.local` / `.env.local` / `.env`, or `opro setup`. Add `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `OLLAMA_BASE_URL`, or a model env var to the client config only if that client does not inherit your shell. OrangePro does not pin a model in the MCP config.
286
+
287
+ | Client | Config location |
288
+ |--------|-----------------|
289
+ | Claude Code | project `.mcp.json` or `~/.claude.json` |
290
+ | Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) · `%APPDATA%\Claude\claude_desktop_config.json` (Windows) |
291
+ | Cursor | `~/.cursor/mcp.json` (or Settings → MCP) |
292
+ | Codex / OpenCode / Cline / Continue / Windsurf / other | that client's MCP / `mcpServers` settings |
293
+
294
+ **Tools.** *Start here*: `orangepro_start`. *Baseline* (no diff/PR needed): `orangepro_analyze_sources`, `orangepro_status`, `orangepro_graph_score`, `orangepro_doctor`, `orangepro_find_test_gaps`, `orangepro_rtm`, `orangepro_generate_tests`, `orangepro_prove`, `orangepro_record_run`, `orangepro_stats`, `orangepro_explain_test`, `orangepro_export_evidence_pack`. *Diff/PR* (require a git repo + real diff vs a base): `orangepro_changed_impact`. *Optional AI lanes*: `orangepro_ai_links` for weak behavior↔symbol suggestions, `orangepro_ai_flows` for candidate flow worklists.
295
+
296
+ ## How grounding works
297
+
298
+ `generate` targets one behavior at a time (the top gap, your `--target`, or what a diff touches) and produces up to `--limit` tests, each in a different scenario bucket when the evidence supports it — `happy_path`, `validation_error`, `edge_case`, `integration_flow`, `security_privacy`, `regression`. A bucket is never padded with a smoke test; each test reports its bucket and **cites the evidence it used**. Imports are reconstructed from the repo's own linked test for that area when one exists, rather than guessed.
299
+
300
+ - **Evidence pack** (`export`): a strict-schema JSON pack (+ Markdown summary) of facts, provenance, evidence strength, grounding, and score metadata — no prompts, weights, traces, or raw source. Test bodies excluded unless `--include-generated-bodies`.
301
+ - **Graph explorer**: a self-contained, **offline** HTML view written to `.orangepro/graph.html` by default (`--no-graph-html` to skip). Click a symbol to see the files, tests, behaviors, and provenance behind it — the visual "why these tests are grounded." Tabs: Gap Heatmap · Connectivity Graph · All Behaviors.
302
+
303
+ <details>
304
+ <summary><b>Comparison mode</b></summary>
305
+
306
+ `opro generate` can compare a prompt-only baseline with the graph-grounded output using the same selected model. The comparison report is local-only and helps show whether the evidence graph improved the result on your repo. Use `opro generate --single` for the normal shipping workflow: one graph-grounded output, persisted to the graph.
307
+
308
+ </details>
309
+
310
+ ## What's deferred (hosted platform)
311
+
312
+ This kit is the local adoption surface. The hosted OrangePro platform owns: tenant-scale lifecycle Knowledge Graph, verified unknown-to-known grounding, multi-source memory, scoring gates, retrieval/ranking, repo writing (safe patch workflow), source promotion, clean reproducible CI runs, and the full product workflow. Also deferred here: Jira/Confluence/TestRail/OpenAPI enrichers, Docker/watch mode, PDF/DOCX export.
313
+
314
+ ## Development
315
+
316
+ ```bash
317
+ npm run build # compile to dist/
318
+ npm test # vitest
319
+ npm run typecheck # type check without emitting
320
+ npm run local -- analyze . # run the CLI via tsx in dev
321
+ node scripts/smoke-local.mjs # offline end-to-end smoke test
322
+ ```
323
+
324
+ Deep reference: [docs/local-proof-kit.md](docs/local-proof-kit.md). Development helpers are source-checkout utilities; the published package includes only the `opro` / `orangepro-local` runtime, this README, LICENSE, and public docs.
325
+
326
+ ## License
327
+
328
+ [MIT](LICENSE) © OrangePro (OrangeproAI)
@@ -0,0 +1,81 @@
1
+ import { AGENT_RUN_WORKFLOW, GROUNDING_CONTRACT } from "./generate/runHints.js";
2
+ const CLIENT_CONFIG_LOCATION = {
3
+ generic: "Use your MCP client's mcpServers settings.",
4
+ "claude-code": "Project .mcp.json or ~/.claude.json.",
5
+ cursor: "~/.cursor/mcp.json or Cursor Settings -> MCP.",
6
+ codex: "Use MCP server settings when available; otherwise use the CLI fallback commands.",
7
+ opencode: "opencode MCP/server settings.",
8
+ windsurf: "Windsurf MCP/server settings."
9
+ };
10
+ export function normalizeAgentClient(value) {
11
+ if (typeof value !== "string")
12
+ return "generic";
13
+ const v = value.trim().toLowerCase().replace(/_/g, "-");
14
+ if (v === "claude" || v === "claude-code")
15
+ return "claude-code";
16
+ if (v === "cursor")
17
+ return "cursor";
18
+ if (v === "codex" || v === "openai")
19
+ return "codex";
20
+ if (v === "opencode" || v === "open-code")
21
+ return "opencode";
22
+ if (v === "windsurf")
23
+ return "windsurf";
24
+ return "generic";
25
+ }
26
+ export function buildAgentWorkflowPack(cliPath, client = "generic") {
27
+ return {
28
+ client,
29
+ config_location: CLIENT_CONFIG_LOCATION[client],
30
+ mcp_config: {
31
+ mcpServers: {
32
+ "orangepro-local": {
33
+ command: "node",
34
+ args: [cliPath, "mcp"],
35
+ env: {}
36
+ }
37
+ }
38
+ },
39
+ agent_instructions: [
40
+ "Before writing tests, call OrangePro on the local checkout.",
41
+ "Start with `orangepro_start`; it preflights large repos, builds the graph, applies weak AI grounding and AI candidate flows only when a provider is configured, writes behavior-coverage.html + rtm.md, and returns next actions.",
42
+ "For PR work after start, use `orangepro_generate_tests` with `base_ref=main`; do not invent a PR if there is no diff.",
43
+ "For baseline work after start, use `orangepro_find_test_gaps`, choose a high-priority gap, then call `orangepro_generate_tests` for that target.",
44
+ "Use only generated tests that include `run_hints`; grounded drafts are context, not runnable claims.",
45
+ "Write each runnable test body to its `suggested_path`, run its `run_command` from the owning package, then call the returned `prove_run` args after a pass to attempt public Proven. Use `record_run` only for static diagnostics.",
46
+ "Report pass/fail with stack traces; if the command fails because dependencies or tools are missing, report the setup issue instead of editing around it.",
47
+ "Summarize whether the graph status changed: Proven, Reproven, Runtime-covered, Associated signal, or No integration signal."
48
+ ],
49
+ cli_fallback: [
50
+ "opro",
51
+ "opro start . --generate-coverage",
52
+ "opro gaps --limit 10",
53
+ "opro generate --base main --single --limit 3",
54
+ "opro generate --target <target-id> --single --limit 1",
55
+ "opro explain <generated-test-id>"
56
+ ],
57
+ grounding_contract: GROUNDING_CONTRACT.concat(AGENT_RUN_WORKFLOW)
58
+ };
59
+ }
60
+ export function renderAgentWorkflowPack(pack) {
61
+ const lines = [];
62
+ lines.push(`OrangePro agent workflow (${pack.client})`);
63
+ lines.push("");
64
+ lines.push(`Config location: ${pack.config_location}`);
65
+ lines.push("");
66
+ lines.push("MCP config:");
67
+ lines.push(JSON.stringify(pack.mcp_config, null, 2));
68
+ lines.push("");
69
+ lines.push("Agent instructions:");
70
+ for (const item of pack.agent_instructions)
71
+ lines.push(`- ${item}`);
72
+ lines.push("");
73
+ lines.push("CLI fallback:");
74
+ for (const item of pack.cli_fallback)
75
+ lines.push(`- ${item}`);
76
+ lines.push("");
77
+ lines.push("Grounding contract:");
78
+ for (const item of pack.grounding_contract)
79
+ lines.push(`- ${item}`);
80
+ return lines.join("\n");
81
+ }