openreflex 0.3.2__tar.gz → 0.5.0__tar.gz

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 (64) hide show
  1. {openreflex-0.3.2/src/openreflex.egg-info → openreflex-0.5.0}/PKG-INFO +38 -25
  2. {openreflex-0.3.2 → openreflex-0.5.0}/README.md +38 -25
  3. {openreflex-0.3.2 → openreflex-0.5.0}/pyproject.toml +2 -2
  4. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/__init__.py +1 -1
  5. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/__main__.py +1 -1
  6. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/benchmark.py +1 -3
  7. openreflex-0.5.0/src/openreflex/claude_ui.py +52 -0
  8. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/cli.py +142 -3
  9. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/decision.py +26 -12
  10. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/engine.py +71 -26
  11. openreflex-0.5.0/src/openreflex/entrypoint.py +457 -0
  12. openreflex-0.5.0/src/openreflex/execution_state.py +140 -0
  13. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/hooks.py +38 -5
  14. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/install.py +15 -1
  15. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/learning.py +36 -8
  16. openreflex-0.5.0/src/openreflex/mcp_contracts.py +158 -0
  17. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/mcp_server.py +126 -103
  18. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/metrics.py +14 -15
  19. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/models.py +37 -0
  20. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/policies/default.toml +101 -0
  21. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/privacy.py +5 -3
  22. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/project.py +2 -2
  23. openreflex-0.5.0/src/openreflex/project_map.py +362 -0
  24. openreflex-0.5.0/src/openreflex/project_memory.py +469 -0
  25. openreflex-0.5.0/src/openreflex/reflex_index.py +304 -0
  26. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/routing.py +23 -4
  27. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/store.py +53 -9
  28. openreflex-0.5.0/src/openreflex/tui.py +254 -0
  29. openreflex-0.5.0/src/openreflex/updater.py +193 -0
  30. openreflex-0.5.0/src/openreflex/usage.py +332 -0
  31. {openreflex-0.3.2 → openreflex-0.5.0/src/openreflex.egg-info}/PKG-INFO +38 -25
  32. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex.egg-info/SOURCES.txt +24 -1
  33. openreflex-0.5.0/src/openreflex.egg-info/entry_points.txt +2 -0
  34. openreflex-0.5.0/tests/test_completion_recap_semantics.py +86 -0
  35. {openreflex-0.3.2 → openreflex-0.5.0}/tests/test_engine.py +5 -3
  36. openreflex-0.5.0/tests/test_execution_state.py +116 -0
  37. {openreflex-0.3.2 → openreflex-0.5.0}/tests/test_mcp_metrics_benchmark.py +8 -3
  38. openreflex-0.5.0/tests/test_outcome_closure.py +106 -0
  39. {openreflex-0.3.2 → openreflex-0.5.0}/tests/test_policy_recap.py +3 -4
  40. openreflex-0.5.0/tests/test_primer_background.py +40 -0
  41. openreflex-0.5.0/tests/test_project_map.py +134 -0
  42. openreflex-0.5.0/tests/test_project_memory.py +66 -0
  43. openreflex-0.5.0/tests/test_project_scope.py +50 -0
  44. openreflex-0.5.0/tests/test_quality_hardening.py +93 -0
  45. openreflex-0.5.0/tests/test_reflex_index.py +151 -0
  46. openreflex-0.5.0/tests/test_release_consistency.py +24 -0
  47. {openreflex-0.3.2 → openreflex-0.5.0}/tests/test_routing_control.py +5 -1
  48. {openreflex-0.3.2 → openreflex-0.5.0}/tests/test_stress.py +2 -1
  49. openreflex-0.5.0/tests/test_tui_memory.py +199 -0
  50. openreflex-0.5.0/tests/test_update_cli.py +156 -0
  51. openreflex-0.5.0/tests/test_work_modes_tokens.py +218 -0
  52. openreflex-0.3.2/src/openreflex.egg-info/entry_points.txt +0 -2
  53. {openreflex-0.3.2 → openreflex-0.5.0}/LICENSE +0 -0
  54. {openreflex-0.3.2 → openreflex-0.5.0}/setup.cfg +0 -0
  55. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/control.py +0 -0
  56. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/detect.py +0 -0
  57. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/integrations/opencode.ts +0 -0
  58. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex/policy.py +0 -0
  59. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex.egg-info/dependency_links.txt +0 -0
  60. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex.egg-info/requires.txt +0 -0
  61. {openreflex-0.3.2 → openreflex-0.5.0}/src/openreflex.egg-info/top_level.txt +0 -0
  62. {openreflex-0.3.2 → openreflex-0.5.0}/tests/test_hooks.py +0 -0
  63. {openreflex-0.3.2 → openreflex-0.5.0}/tests/test_install_cli.py +0 -0
  64. {openreflex-0.3.2 → openreflex-0.5.0}/tests/test_reliability_lifecycle.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openreflex
3
- Version: 0.3.2
3
+ Version: 0.5.0
4
4
  Summary: Muscle memory for AI coding agents: learns from every task, advises the next one, and flags failure loops live
5
5
  Author: vishnu-77
6
6
  License-Expression: MIT
@@ -54,16 +54,17 @@ Dynamic: license-file
54
54
 
55
55
  ## What is OpenReflex
56
56
 
57
- OpenReflex gives AI coding agents muscle memory. It plugs into Claude Code, Codex, Cursor, and OpenCode through
58
- lifecycle hooks and MCP, quietly records how each task actually went, and hands the next similar task what worked
59
- before: the approach, the files that mattered, and the fix for the error you hit last time.
57
+ OpenReflex gives AI coding agents muscle memory across coding, investigation, and reasoning work. It plugs into
58
+ Claude Code, Codex, Cursor, and OpenCode through lifecycle hooks and MCP, quietly records how each task actually
59
+ went, and hands the next similar task the useful parts of that experience.
60
60
 
61
- You install it once and keep working normally. Everything stays on your machine in a local SQLite database.
62
- There is no account, no service, and no telemetry.
61
+ You install it once and keep working normally. Core memory stays on your machine in a local SQLite database.
62
+ There is no OpenReflex account or hosted service. Optional Claude token accounting uses Claude Code's local
63
+ OpenTelemetry export to a loopback-only OpenReflex receiver and stores counts only.
63
64
 
64
65
  <p align="center">
65
66
  <a href="docs/walkthrough.md">
66
- <img alt="Recording of a real Claude Code session with OpenReflex: OpenReflex reports one similar past task and adds 162 context tokens, Claude finds and fixes the coupon bug, runs the tests, records the verified outcome through OpenReflex's MCP tool, and OpenReflex shows the completion recap with the path taken, cost and regret" src="https://raw.githubusercontent.com/vishnu-77/openreflex/main/docs/screenshots/claude-code-session.gif" width="860">
67
+ <img alt="Recording of a real Claude Code session with OpenReflex: OpenReflex reports one similar past task and adds 162 context tokens, Claude finds and fixes the coupon bug, runs the tests, records the verified outcome through OpenReflex's MCP tool, and OpenReflex shows the completion recap with the path taken and observed cost" src="https://raw.githubusercontent.com/vishnu-77/openreflex/main/docs/screenshots/claude-code-session.gif" width="860">
67
68
  </a>
68
69
  <br>
69
70
  <sub>A real Claude Code session, recorded from the terminal and sped up. OpenReflex had seen one similar task in this repository, so it adds 162 tokens of context before the first tool call; after the fix, Claude records the outcome through OpenReflex's MCP tool. The step-by-step walkthrough is in <a href="docs/walkthrough.md">docs/walkthrough.md</a>.</sub>
@@ -77,15 +78,16 @@ There is no account, no service, and no telemetry.
77
78
  - **It catches loops while they happen.** Repeated failing commands, identical retries, stalled progress, and
78
79
  runaway context growth raise one alert that says whether to continue, pivot to another approach, or stop and
79
80
  check in with you, never a stream of nags.
80
- - **It learns after every task.** OpenReflex infers the outcome from real verification (a test or build that
81
- passed or failed after the last edit), estimates Execution Regret against the alternatives, and extracts lessons.
81
+ - **It learns after every task.** Build work closes against tests/lint/build evidence; investigations can close
82
+ against cross-checked sources; reasoning-only work can complete without external tools. A simple **Path check**
83
+ only names a better option when comparable past tasks actually support one.
82
84
  - **It is private by design.** Only coarse, project-relative metadata is stored. File contents, commands, tool
83
85
  output, and transcripts never are, and capture is off until you approve a project.
84
86
 
85
87
  <p align="center">
86
88
  <picture>
87
89
  <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/how-it-works-dark.svg">
88
- <img alt="Before a task: retrieve similar experience, score candidate paths, inject context and a budget. During a task: watch every tool call, flag loops and stalls, advise continue, pivot or stop. After a task: infer the outcome from checks, estimate Execution Regret, extract lessons. Lessons feed the Experience Graph for the next task." src="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/how-it-works-light.svg" width="860">
90
+ <img alt="Before a task: retrieve similar experience, score candidate paths, inject context and a budget. During a task: watch every tool call, flag loops and stalls, advise continue, pivot or stop. After a task: close the outcome using evidence appropriate to the work, run a simple Path check, extract lessons. Lessons feed the Experience Graph for the next task." src="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/how-it-works-light.svg" width="860">
89
91
  </picture>
90
92
  </p>
91
93
 
@@ -118,8 +120,14 @@ Then work as usual. After a few tasks:
118
120
  openreflex context "fix the login redirect bug" # preview the context a task would receive
119
121
  openreflex status # what has been captured and learned
120
122
  openreflex doctor # installation checks and recent hook errors
123
+ openreflex update --check # check the latest stable release
121
124
  ```
122
125
 
126
+ Package updates preserve local memory and project configuration. Managed `pipx` and `uv tool` installs can use
127
+ `openreflex update`, `openreflex update --reinstall`, or `openreflex self reinstall`. To remove only the package,
128
+ use `openreflex self uninstall --yes`; project memory is preserved. A fresh bootstrap still starts with
129
+ `pipx install openreflex` or `uv tool install openreflex` because the `openreflex` command does not exist before installation.
130
+
123
131
  ## Use it with your agent
124
132
 
125
133
  OpenReflex installs per project with `openreflex install <agent>`, or as a plugin.
@@ -147,12 +155,11 @@ Execution -failed_with-> ToolCall -resolved_by-> ToolCall
147
155
  Execution -caused-> Outcome -caused-> Experience -caused-> Lesson
148
156
  ```
149
157
 
150
- - **Before a task:** similar experiences are retrieved and three strategies (`inspect-first`, `test-first`,
151
- `incremental`) are estimated on success probability, time, tool calls, context cost, risk, uncertainty,
152
- reversibility, and expected regret. Strategies that another one beats on every measure are dropped as
153
- dominated (Pareto efficiency), the rest are ranked by utility within any limits you set, and the chosen path
154
- gets an execution budget for time, tool calls, and context. A context of at most 1,400 characters is
155
- injected; nothing is injected without relevant experience.
158
+ - **Before a task:** similar experiences are retrieved and OpenReflex first identifies the work mode. **BUILD**
159
+ uses `inspect-first`, `test-first`, and `incremental`; **INVESTIGATE** uses `source-first`,
160
+ `cross-check`, and `broad-then-deep`; **THINK** uses `reason-first`, `compare-options`, and
161
+ `evidence-first`. Paths are ranked using past evidence, estimated cost, risk, uncertainty and reversibility.
162
+ A compact context is injected only when relevant experience exists.
156
163
  - **During a task:** when a detector finds a failure loop, repeated calls, stalled progress, context growth,
157
164
  or work past the budget, OpenReflex estimates the marginal value of more work. The current path's success
158
165
  estimate is updated with each call that makes no progress or fails, and compared with the cost of the work
@@ -160,9 +167,9 @@ Execution -caused-> Outcome -caused-> Experience -caused-> Lesson
160
167
  to another strategy, or **stop** and ask the user. Each problem, pivot, or stop is raised once, with a cooldown
161
168
  between messages.
162
169
  - **After a task:** outcome and chosen path come from the agent's `record_outcome` / `choose_path` MCP calls when
163
- available, and are otherwise inferred from tool activity. Execution Regret compares the path taken with the
164
- best plausible alternative; it is withheld when the outcome is unknown, and feeds back into how strategies
165
- are ranked next time, along with success, cost, and how often a strategy ran into trouble.
170
+ available, and are otherwise inferred from work-mode-appropriate evidence. The **Path check** says either
171
+ `better option: <path>` when comparable completed tasks support it or `better option: none proven`.
172
+ Recommendations are never presented as paths that were actually executed.
166
173
 
167
174
  Every recommendation is stored as a decision snapshot with a **Reflex Score** (0-100): how strong the
168
175
  recommendation is, which is separate from the estimated chance that the task succeeds. `openreflex why` explains
@@ -183,7 +190,7 @@ Agents can also query OpenReflex directly through its MCP server.
183
190
  | `get_execution_context` | Plan a task: similar past tasks, the suggested strategy with alternatives, a budget, likely files, lessons. Optional `max_tool_calls`, `max_minutes`, `max_context_tokens`. |
184
191
  | `check_progress` | Whether more work on the current path is worth it: continue, pivot or stop. |
185
192
  | `choose_path` | Declare the strategy being followed when it differs from the suggestion. |
186
- | `record_outcome` | Record a verified outcome (tests passed, user confirmed, or failure) and learn from it. |
193
+ | `record_outcome` | Record a confirmed outcome (tests/builds, cross-checked research, user confirmation, or failure) and learn from it. |
187
194
  | `explain_decision` | Why the latest recommendation was made: Reflex Score, signals, confidence, next-best route. |
188
195
  | `get_execution_trace` | The decision timeline of the most recent task. |
189
196
  | `get_reflex_score` | The latest Reflex Score and its components as JSON. |
@@ -201,12 +208,16 @@ Agents can also query OpenReflex directly through its MCP server.
201
208
  |---|---|
202
209
  | `install <agent> [--dry-run]` | Write project hooks and MCP config, and enable the project |
203
210
  | `uninstall <agent> [--dry-run]` | Remove OpenReflex's project hooks and MCP config; captured memory is kept |
211
+ | `update [--check] [--reinstall]` | Check or update a managed pipx/uv-tool installation; optionally force a reinstall |
212
+ | `self reinstall` | Repair/reinstall the managed OpenReflex package while preserving memory/config |
213
+ | `self uninstall --yes` | Remove only the managed OpenReflex package; memory/config remain on disk |
204
214
  | `approve` / `revoke` | Enable or disable capture for the current project |
205
215
  | `context "<task>"` | Preview the Execution Context a task would receive |
206
- | `status [--json]` | What has been captured, reused, and learned |
216
+ | `status [--json]` | What has been captured, reused, learned, and how model-token usage compares |
207
217
  | `why` / `trace` | Explain the latest recommendation, or show the decision timeline |
208
218
  | `doctor` | Installation, project resolution, and recent hook activity checks |
209
219
  | `forget --yes` | Delete the project's data |
220
+ | `tokens enable` / `tokens status` / `tokens disable` | Opt in to local Claude Code token accounting, inspect it, or remove OpenReflex-owned telemetry settings |
210
221
  | `benchmark` | Run the simulated benchmark |
211
222
  | `hook <agent> <event>` / `mcp` | Used by agent configs |
212
223
 
@@ -218,8 +229,9 @@ Agents can also query OpenReflex directly through its MCP server.
218
229
  | A fingerprint of the arguments | Command text |
219
230
  | Project-relative file paths | Tool output |
220
231
  | Pass or fail, duration, output size | Transcripts and model output |
232
+ | Optional model-token counts, model/source label, estimated cost | Prompt/response/tool contents from Claude telemetry |
221
233
  | A masked one-line error signature | Paths outside the project |
222
- | The prompt as a task description (up to 1,000 characters, secrets redacted) | Anything sent to a server: there is none |
234
+ | The prompt as a task description (up to 1,000 characters, secrets redacted) | Anything sent to an OpenReflex-hosted service: there is none |
223
235
 
224
236
  Data lives in `~/.openreflex/projects/<hash>/experience.sqlite3`. Set `OPENREFLEX_HOME` to move it,
225
237
  `OPENREFLEX_DISABLE=1` to turn capture off everywhere, `openreflex forget --yes` to delete a project's data, or ask
@@ -228,9 +240,10 @@ your agent to `forget_experience` a single task.
228
240
  ## Research
229
241
 
230
242
  OpenReflex is also a research project in budget-aware execution: instead of treating success as a yes or no, it
231
- studies how agents choose execution paths, spend tool calls and context, respond to uncertainty, and whether more
232
- computation still adds value. The loop is experience retrieval, Pareto path selection, budget-aware execution and
233
- counterfactual regret. The [Researcher view](https://openreflex.cc/?view=research) on the site explains the idea,
243
+ studies how agents choose execution paths, spend tool calls, model tokens and context, respond to uncertainty, and
244
+ whether past work makes similar future work cheaper without reducing outcome quality. The loop is experience
245
+ retrieval, evidence-aware path selection, budget-aware execution, work-mode-specific completion and plain-language
246
+ path comparison. The [Researcher view](https://openreflex.cc/?view=research) on the site explains the idea,
234
247
  lets you step through one reflex forming in the graph, and places it next to related work.
235
248
 
236
249
  ## Community & Contributing
@@ -22,16 +22,17 @@
22
22
 
23
23
  ## What is OpenReflex
24
24
 
25
- OpenReflex gives AI coding agents muscle memory. It plugs into Claude Code, Codex, Cursor, and OpenCode through
26
- lifecycle hooks and MCP, quietly records how each task actually went, and hands the next similar task what worked
27
- before: the approach, the files that mattered, and the fix for the error you hit last time.
25
+ OpenReflex gives AI coding agents muscle memory across coding, investigation, and reasoning work. It plugs into
26
+ Claude Code, Codex, Cursor, and OpenCode through lifecycle hooks and MCP, quietly records how each task actually
27
+ went, and hands the next similar task the useful parts of that experience.
28
28
 
29
- You install it once and keep working normally. Everything stays on your machine in a local SQLite database.
30
- There is no account, no service, and no telemetry.
29
+ You install it once and keep working normally. Core memory stays on your machine in a local SQLite database.
30
+ There is no OpenReflex account or hosted service. Optional Claude token accounting uses Claude Code's local
31
+ OpenTelemetry export to a loopback-only OpenReflex receiver and stores counts only.
31
32
 
32
33
  <p align="center">
33
34
  <a href="docs/walkthrough.md">
34
- <img alt="Recording of a real Claude Code session with OpenReflex: OpenReflex reports one similar past task and adds 162 context tokens, Claude finds and fixes the coupon bug, runs the tests, records the verified outcome through OpenReflex's MCP tool, and OpenReflex shows the completion recap with the path taken, cost and regret" src="https://raw.githubusercontent.com/vishnu-77/openreflex/main/docs/screenshots/claude-code-session.gif" width="860">
35
+ <img alt="Recording of a real Claude Code session with OpenReflex: OpenReflex reports one similar past task and adds 162 context tokens, Claude finds and fixes the coupon bug, runs the tests, records the verified outcome through OpenReflex's MCP tool, and OpenReflex shows the completion recap with the path taken and observed cost" src="https://raw.githubusercontent.com/vishnu-77/openreflex/main/docs/screenshots/claude-code-session.gif" width="860">
35
36
  </a>
36
37
  <br>
37
38
  <sub>A real Claude Code session, recorded from the terminal and sped up. OpenReflex had seen one similar task in this repository, so it adds 162 tokens of context before the first tool call; after the fix, Claude records the outcome through OpenReflex's MCP tool. The step-by-step walkthrough is in <a href="docs/walkthrough.md">docs/walkthrough.md</a>.</sub>
@@ -45,15 +46,16 @@ There is no account, no service, and no telemetry.
45
46
  - **It catches loops while they happen.** Repeated failing commands, identical retries, stalled progress, and
46
47
  runaway context growth raise one alert that says whether to continue, pivot to another approach, or stop and
47
48
  check in with you, never a stream of nags.
48
- - **It learns after every task.** OpenReflex infers the outcome from real verification (a test or build that
49
- passed or failed after the last edit), estimates Execution Regret against the alternatives, and extracts lessons.
49
+ - **It learns after every task.** Build work closes against tests/lint/build evidence; investigations can close
50
+ against cross-checked sources; reasoning-only work can complete without external tools. A simple **Path check**
51
+ only names a better option when comparable past tasks actually support one.
50
52
  - **It is private by design.** Only coarse, project-relative metadata is stored. File contents, commands, tool
51
53
  output, and transcripts never are, and capture is off until you approve a project.
52
54
 
53
55
  <p align="center">
54
56
  <picture>
55
57
  <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/how-it-works-dark.svg">
56
- <img alt="Before a task: retrieve similar experience, score candidate paths, inject context and a budget. During a task: watch every tool call, flag loops and stalls, advise continue, pivot or stop. After a task: infer the outcome from checks, estimate Execution Regret, extract lessons. Lessons feed the Experience Graph for the next task." src="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/how-it-works-light.svg" width="860">
58
+ <img alt="Before a task: retrieve similar experience, score candidate paths, inject context and a budget. During a task: watch every tool call, flag loops and stalls, advise continue, pivot or stop. After a task: close the outcome using evidence appropriate to the work, run a simple Path check, extract lessons. Lessons feed the Experience Graph for the next task." src="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/how-it-works-light.svg" width="860">
57
59
  </picture>
58
60
  </p>
59
61
 
@@ -86,8 +88,14 @@ Then work as usual. After a few tasks:
86
88
  openreflex context "fix the login redirect bug" # preview the context a task would receive
87
89
  openreflex status # what has been captured and learned
88
90
  openreflex doctor # installation checks and recent hook errors
91
+ openreflex update --check # check the latest stable release
89
92
  ```
90
93
 
94
+ Package updates preserve local memory and project configuration. Managed `pipx` and `uv tool` installs can use
95
+ `openreflex update`, `openreflex update --reinstall`, or `openreflex self reinstall`. To remove only the package,
96
+ use `openreflex self uninstall --yes`; project memory is preserved. A fresh bootstrap still starts with
97
+ `pipx install openreflex` or `uv tool install openreflex` because the `openreflex` command does not exist before installation.
98
+
91
99
  ## Use it with your agent
92
100
 
93
101
  OpenReflex installs per project with `openreflex install <agent>`, or as a plugin.
@@ -115,12 +123,11 @@ Execution -failed_with-> ToolCall -resolved_by-> ToolCall
115
123
  Execution -caused-> Outcome -caused-> Experience -caused-> Lesson
116
124
  ```
117
125
 
118
- - **Before a task:** similar experiences are retrieved and three strategies (`inspect-first`, `test-first`,
119
- `incremental`) are estimated on success probability, time, tool calls, context cost, risk, uncertainty,
120
- reversibility, and expected regret. Strategies that another one beats on every measure are dropped as
121
- dominated (Pareto efficiency), the rest are ranked by utility within any limits you set, and the chosen path
122
- gets an execution budget for time, tool calls, and context. A context of at most 1,400 characters is
123
- injected; nothing is injected without relevant experience.
126
+ - **Before a task:** similar experiences are retrieved and OpenReflex first identifies the work mode. **BUILD**
127
+ uses `inspect-first`, `test-first`, and `incremental`; **INVESTIGATE** uses `source-first`,
128
+ `cross-check`, and `broad-then-deep`; **THINK** uses `reason-first`, `compare-options`, and
129
+ `evidence-first`. Paths are ranked using past evidence, estimated cost, risk, uncertainty and reversibility.
130
+ A compact context is injected only when relevant experience exists.
124
131
  - **During a task:** when a detector finds a failure loop, repeated calls, stalled progress, context growth,
125
132
  or work past the budget, OpenReflex estimates the marginal value of more work. The current path's success
126
133
  estimate is updated with each call that makes no progress or fails, and compared with the cost of the work
@@ -128,9 +135,9 @@ Execution -caused-> Outcome -caused-> Experience -caused-> Lesson
128
135
  to another strategy, or **stop** and ask the user. Each problem, pivot, or stop is raised once, with a cooldown
129
136
  between messages.
130
137
  - **After a task:** outcome and chosen path come from the agent's `record_outcome` / `choose_path` MCP calls when
131
- available, and are otherwise inferred from tool activity. Execution Regret compares the path taken with the
132
- best plausible alternative; it is withheld when the outcome is unknown, and feeds back into how strategies
133
- are ranked next time, along with success, cost, and how often a strategy ran into trouble.
138
+ available, and are otherwise inferred from work-mode-appropriate evidence. The **Path check** says either
139
+ `better option: <path>` when comparable completed tasks support it or `better option: none proven`.
140
+ Recommendations are never presented as paths that were actually executed.
134
141
 
135
142
  Every recommendation is stored as a decision snapshot with a **Reflex Score** (0-100): how strong the
136
143
  recommendation is, which is separate from the estimated chance that the task succeeds. `openreflex why` explains
@@ -151,7 +158,7 @@ Agents can also query OpenReflex directly through its MCP server.
151
158
  | `get_execution_context` | Plan a task: similar past tasks, the suggested strategy with alternatives, a budget, likely files, lessons. Optional `max_tool_calls`, `max_minutes`, `max_context_tokens`. |
152
159
  | `check_progress` | Whether more work on the current path is worth it: continue, pivot or stop. |
153
160
  | `choose_path` | Declare the strategy being followed when it differs from the suggestion. |
154
- | `record_outcome` | Record a verified outcome (tests passed, user confirmed, or failure) and learn from it. |
161
+ | `record_outcome` | Record a confirmed outcome (tests/builds, cross-checked research, user confirmation, or failure) and learn from it. |
155
162
  | `explain_decision` | Why the latest recommendation was made: Reflex Score, signals, confidence, next-best route. |
156
163
  | `get_execution_trace` | The decision timeline of the most recent task. |
157
164
  | `get_reflex_score` | The latest Reflex Score and its components as JSON. |
@@ -169,12 +176,16 @@ Agents can also query OpenReflex directly through its MCP server.
169
176
  |---|---|
170
177
  | `install <agent> [--dry-run]` | Write project hooks and MCP config, and enable the project |
171
178
  | `uninstall <agent> [--dry-run]` | Remove OpenReflex's project hooks and MCP config; captured memory is kept |
179
+ | `update [--check] [--reinstall]` | Check or update a managed pipx/uv-tool installation; optionally force a reinstall |
180
+ | `self reinstall` | Repair/reinstall the managed OpenReflex package while preserving memory/config |
181
+ | `self uninstall --yes` | Remove only the managed OpenReflex package; memory/config remain on disk |
172
182
  | `approve` / `revoke` | Enable or disable capture for the current project |
173
183
  | `context "<task>"` | Preview the Execution Context a task would receive |
174
- | `status [--json]` | What has been captured, reused, and learned |
184
+ | `status [--json]` | What has been captured, reused, learned, and how model-token usage compares |
175
185
  | `why` / `trace` | Explain the latest recommendation, or show the decision timeline |
176
186
  | `doctor` | Installation, project resolution, and recent hook activity checks |
177
187
  | `forget --yes` | Delete the project's data |
188
+ | `tokens enable` / `tokens status` / `tokens disable` | Opt in to local Claude Code token accounting, inspect it, or remove OpenReflex-owned telemetry settings |
178
189
  | `benchmark` | Run the simulated benchmark |
179
190
  | `hook <agent> <event>` / `mcp` | Used by agent configs |
180
191
 
@@ -186,8 +197,9 @@ Agents can also query OpenReflex directly through its MCP server.
186
197
  | A fingerprint of the arguments | Command text |
187
198
  | Project-relative file paths | Tool output |
188
199
  | Pass or fail, duration, output size | Transcripts and model output |
200
+ | Optional model-token counts, model/source label, estimated cost | Prompt/response/tool contents from Claude telemetry |
189
201
  | A masked one-line error signature | Paths outside the project |
190
- | The prompt as a task description (up to 1,000 characters, secrets redacted) | Anything sent to a server: there is none |
202
+ | The prompt as a task description (up to 1,000 characters, secrets redacted) | Anything sent to an OpenReflex-hosted service: there is none |
191
203
 
192
204
  Data lives in `~/.openreflex/projects/<hash>/experience.sqlite3`. Set `OPENREFLEX_HOME` to move it,
193
205
  `OPENREFLEX_DISABLE=1` to turn capture off everywhere, `openreflex forget --yes` to delete a project's data, or ask
@@ -196,9 +208,10 @@ your agent to `forget_experience` a single task.
196
208
  ## Research
197
209
 
198
210
  OpenReflex is also a research project in budget-aware execution: instead of treating success as a yes or no, it
199
- studies how agents choose execution paths, spend tool calls and context, respond to uncertainty, and whether more
200
- computation still adds value. The loop is experience retrieval, Pareto path selection, budget-aware execution and
201
- counterfactual regret. The [Researcher view](https://openreflex.cc/?view=research) on the site explains the idea,
211
+ studies how agents choose execution paths, spend tool calls, model tokens and context, respond to uncertainty, and
212
+ whether past work makes similar future work cheaper without reducing outcome quality. The loop is experience
213
+ retrieval, evidence-aware path selection, budget-aware execution, work-mode-specific completion and plain-language
214
+ path comparison. The [Researcher view](https://openreflex.cc/?view=research) on the site explains the idea,
202
215
  lets you step through one reflex forming in the graph, and places it next to related work.
203
216
 
204
217
  ## Community & Contributing
@@ -225,4 +238,4 @@ OpenReflex is listed in the [MCP Registry](https://registry.modelcontextprotocol
225
238
 
226
239
  ## License
227
240
 
228
- OpenReflex is released under the [MIT License](https://github.com/vishnu-77/openreflex/blob/main/LICENSE).
241
+ OpenReflex is released under the [MIT License](https://github.com/vishnu-77/openreflex/blob/main/LICENSE).
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "openreflex"
7
- version = "0.3.2"
7
+ version = "0.5.0"
8
8
  description = "Muscle memory for AI coding agents: learns from every task, advises the next one, and flags failure loops live"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -35,7 +35,7 @@ Issues = "https://github.com/vishnu-77/openreflex/issues"
35
35
  dev = ["pytest>=8,<9", "ruff>=0.12", "build>=1.2", "twine>=6"]
36
36
 
37
37
  [project.scripts]
38
- openreflex = "openreflex.cli:main"
38
+ openreflex = "openreflex.entrypoint:main"
39
39
 
40
40
  [tool.setuptools.packages.find]
41
41
  where = ["src"]
@@ -1,3 +1,3 @@
1
1
  """Ambient, local execution intelligence."""
2
2
 
3
- __version__ = "0.3.2"
3
+ __version__ = "0.5.0"
@@ -1,5 +1,5 @@
1
1
  import sys
2
2
 
3
- from .cli import main
3
+ from .entrypoint import main
4
4
 
5
5
  sys.exit(main())
@@ -206,11 +206,9 @@ def format_report(report: dict) -> str:
206
206
  b, g, c = report["baseline"], report["guided"], report["relative_change"]
207
207
  rows = [
208
208
  ("tool calls / task", b["tool_calls"], g["tool_calls"], f"{c['tool_calls']:+.0%}"),
209
- ("output tokens / task", b["tokens"], g["tokens"], f"{c['tokens']:+.0%}"),
209
+ ("sim. tool-output tokens / task", b["tokens"], g["tokens"], f"{c['tokens']:+.0%}"),
210
210
  ("time / task (s)", b["seconds"], g["seconds"], f"{c['time']:+.0%}"),
211
211
  ("success rate", b["success_rate"], g["success_rate"], f"{c['success_rate_points']:+.3f} pts"),
212
- ("regret, first quarter", b["regret_first_quarter"], g["regret_first_quarter"], ""),
213
- ("regret, last quarter", b["regret_last_quarter"], g["regret_last_quarter"], ""),
214
212
  ("routing agreement (2nd half)", "-", g["routing_agreement_second_half"], ""),
215
213
  ]
216
214
  lines = [f"SIMULATED benchmark - {report['episodes_per_arm']} tasks/arm x {report['seeds']} seeds "
@@ -0,0 +1,52 @@
1
+ """Claude Code presentation integration.
2
+
3
+ OpenReflex only installs its status line when the project has no existing custom
4
+ statusLine. A user-owned status line is never replaced.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ import os
11
+ from pathlib import Path
12
+
13
+ STATUSLINE_COMMAND = "openreflex statusline"
14
+
15
+
16
+ def _load(path: Path) -> dict:
17
+ try:
18
+ value = json.loads(path.read_text(encoding="utf-8"))
19
+ return value if isinstance(value, dict) else {}
20
+ except (OSError, ValueError):
21
+ return {}
22
+
23
+
24
+ def _write(path: Path, data: dict) -> None:
25
+ path.parent.mkdir(parents=True, exist_ok=True)
26
+ temp = path.with_suffix(path.suffix + ".tmp")
27
+ temp.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
28
+ os.replace(temp, path)
29
+
30
+
31
+ def configure_statusline(project: Path) -> str:
32
+ path = project / ".claude" / "settings.json"
33
+ data = _load(path)
34
+ existing = data.get("statusLine")
35
+ if isinstance(existing, dict):
36
+ if existing.get("command") == STATUSLINE_COMMAND:
37
+ return "already-configured"
38
+ return "preserved-existing"
39
+ data["statusLine"] = {"type": "command", "command": STATUSLINE_COMMAND, "padding": 0, "refreshInterval": 2}
40
+ _write(path, data)
41
+ return "configured"
42
+
43
+
44
+ def remove_statusline(project: Path) -> bool:
45
+ path = project / ".claude" / "settings.json"
46
+ data = _load(path)
47
+ current = data.get("statusLine")
48
+ if not isinstance(current, dict) or current.get("command") != STATUSLINE_COMMAND:
49
+ return False
50
+ data.pop("statusLine", None)
51
+ _write(path, data)
52
+ return True
@@ -117,7 +117,7 @@ def cmd_status(args) -> int:
117
117
  if args.json:
118
118
  print(json.dumps(data, indent=2))
119
119
  return 0
120
- reuse, regret, routing = data["experience_reuse"], data["execution_regret"], data["routing"]
120
+ reuse, path_check, routing = data["experience_reuse"], data["path_check"], data["routing"]
121
121
  eff = data["efficiency_observational"]
122
122
  print(f"OpenReflex {__version__} - {project}")
123
123
  print(f" enabled: {data['enabled']} agents: {', '.join(data['engagement']['agents']) or '-'}")
@@ -128,7 +128,10 @@ def cmd_status(args) -> int:
128
128
  print(f" success rate (known outcomes): {data['outcomes']['success_rate']} verified: {data['outcomes']['verified']}")
129
129
  print(f" tool calls with vs without prior experience: {eff['with_prior_experience']['tool_calls']} vs "
130
130
  f"{eff['without_prior_experience']['tool_calls']} (observational)")
131
- print(f" mean execution regret: {regret['mean']} routing agreement: {routing['agreement']}")
131
+ print(f" model tokens with vs without prior experience: {eff['with_prior_experience']['model_tokens']} vs "
132
+ f"{eff['without_prior_experience']['model_tokens']} (observational)")
133
+ print(f" path checks: {path_check['comparisons']} better option found: {path_check['better_option_found']} "
134
+ f"routing agreement: {routing['agreement']}")
132
135
  print(f" live alerts: {data['live_alerts'] or '-'}")
133
136
  control = data["execution_control"]
134
137
  print(f" verdicts: {control['verdicts'] or '-'} tasks within tool-call budget: {control['tasks_within_tool_call_budget']}")
@@ -168,6 +171,128 @@ def cmd_trace(args) -> int:
168
171
  return 0
169
172
 
170
173
 
174
+ def cmd_update(args) -> int:
175
+ from .updater import (
176
+ check_for_update,
177
+ detect_install_plan,
178
+ installed_version_after_update,
179
+ run_reinstall,
180
+ run_update,
181
+ )
182
+
183
+ print("OPENREFLEX / UPDATE")
184
+ try:
185
+ status = check_for_update(__version__)
186
+ except RuntimeError as exc:
187
+ print(f" current {__version__}")
188
+ print(f" check failed ({exc})")
189
+ print("\nNo changes were made.")
190
+ return 1
191
+
192
+ plan = detect_install_plan()
193
+ print(f" current {status.current}")
194
+ print(f" latest {status.latest}")
195
+ print(f" install {plan.method}")
196
+
197
+ if args.check:
198
+ if status.update_available:
199
+ print("\n update available")
200
+ print("Run `openreflex update` to install it.")
201
+ elif status.current == status.latest:
202
+ print("\n [ok] already up to date")
203
+ else:
204
+ print("\n [ok] current build is newer than the latest PyPI release")
205
+ return 0
206
+
207
+ if args.reinstall:
208
+ if plan.reinstall_command is None:
209
+ print(f"\n [--] automatic reinstall unavailable: {plan.detail}")
210
+ print("No changes were made.")
211
+ return 2
212
+ print(f" method {' '.join(plan.reinstall_command)}")
213
+ print("\nReinstalling OpenReflex...")
214
+ returncode = run_reinstall(plan)
215
+ else:
216
+ if not status.update_available:
217
+ if status.current == status.latest:
218
+ print("\n [ok] already up to date")
219
+ else:
220
+ print("\n [ok] current build is newer than the latest PyPI release")
221
+ return 0
222
+ if plan.command is None:
223
+ print(f"\n [--] automatic update unavailable: {plan.detail}")
224
+ print("No changes were made.")
225
+ return 2
226
+ print(f" method {' '.join(plan.command)}")
227
+ print("\nUpdating OpenReflex...")
228
+ returncode = run_update(plan)
229
+
230
+ if returncode != 0:
231
+ action = "reinstall" if args.reinstall else "update"
232
+ print(f"\n [--] {action} failed with exit code {returncode}")
233
+ print("Your project memory and agent configuration were not modified by OpenReflex.")
234
+ return returncode or 1
235
+
236
+ installed = installed_version_after_update()
237
+ action = "reinstalled" if args.reinstall else "updated"
238
+ print(f"\n [ok] {action} {installed or status.latest}")
239
+ if not args.reinstall and installed and installed != status.latest:
240
+ print(f" note expected {status.latest}; executable reports {installed}")
241
+ print(" memory preserved")
242
+ print(" config preserved")
243
+ print("\nRestart active Claude Code, Codex, Cursor, or OpenCode sessions to reload hooks and MCP.")
244
+ return 0
245
+
246
+
247
+ def cmd_self(args) -> int:
248
+ from .updater import detect_install_plan, run_reinstall, run_uninstall
249
+
250
+ plan = detect_install_plan()
251
+ print("OPENREFLEX / SELF")
252
+ print(f" action {args.self_action}")
253
+ print(f" install {plan.method}")
254
+
255
+ if args.self_action == "reinstall":
256
+ if plan.reinstall_command is None:
257
+ print(f"\n [--] automatic reinstall unavailable: {plan.detail}")
258
+ print("No changes were made.")
259
+ return 2
260
+ print(f" method {' '.join(plan.reinstall_command)}")
261
+ print("\nReinstalling OpenReflex...")
262
+ returncode = run_reinstall(plan)
263
+ if returncode != 0:
264
+ print(f"\n [--] reinstall failed with exit code {returncode}")
265
+ return returncode or 1
266
+ print("\n [ok] package reinstalled")
267
+ print(" memory preserved")
268
+ print(" config preserved")
269
+ print("\nRestart active agent sessions to reload hooks and MCP.")
270
+ return 0
271
+
272
+ if args.self_action == "uninstall":
273
+ if not args.yes:
274
+ print("\nThis removes the OpenReflex executable/package but preserves ~/.openreflex memory and project configuration.")
275
+ print("Re-run with `openreflex self uninstall --yes` to confirm.")
276
+ return 1
277
+ if plan.uninstall_command is None:
278
+ print(f"\n [--] automatic uninstall unavailable: {plan.detail}")
279
+ print("No changes were made.")
280
+ return 2
281
+ print(f" method {' '.join(plan.uninstall_command)}")
282
+ print("\nUninstalling OpenReflex package...")
283
+ returncode = run_uninstall(plan)
284
+ if returncode != 0:
285
+ print(f"\n [--] uninstall failed with exit code {returncode}")
286
+ return returncode or 1
287
+ print("\n [ok] package uninstalled")
288
+ print(" memory preserved")
289
+ print(" config preserved")
290
+ print("\nProject hooks/config remain on disk but cannot run until OpenReflex is installed again.")
291
+ return 0
292
+
293
+ return 2
294
+
295
+
171
296
  def _json(path: Path) -> dict:
172
297
  try:
173
298
  value = json.loads(path.read_text(encoding="utf-8"))
@@ -300,7 +425,21 @@ def build_parser() -> argparse.ArgumentParser:
300
425
  command.add_argument("--dry-run", action="store_true")
301
426
  command.set_defaults(func=func)
302
427
 
303
- status = sub.add_parser("status", help="Show capture, reuse, regret, and routing metrics")
428
+ update = sub.add_parser("update", help="Check PyPI and safely update the managed OpenReflex installation")
429
+ update_group = update.add_mutually_exclusive_group()
430
+ update_group.add_argument("--check", action="store_true", help="Only report whether an update is available")
431
+ update_group.add_argument("--reinstall", action="store_true", help="Reinstall the stable package even if already current")
432
+ update.set_defaults(func=cmd_update)
433
+
434
+ self_cmd = sub.add_parser("self", help="Manage the installed OpenReflex package without deleting memory")
435
+ self_sub = self_cmd.add_subparsers(dest="self_action", required=True)
436
+ self_reinstall = self_sub.add_parser("reinstall", help="Reinstall the managed OpenReflex package")
437
+ self_reinstall.set_defaults(func=cmd_self)
438
+ self_uninstall = self_sub.add_parser("uninstall", help="Remove the OpenReflex package but preserve memory/config")
439
+ self_uninstall.add_argument("--yes", action="store_true", help="Confirm package removal")
440
+ self_uninstall.set_defaults(func=cmd_self)
441
+
442
+ status = sub.add_parser("status", help="Show capture, reuse, token efficiency, path checks, and routing metrics")
304
443
  status.add_argument("--project")
305
444
  status.add_argument("--json", action="store_true")
306
445
  status.set_defaults(func=cmd_status)