research-diff 0.1.0__tar.gz → 0.2.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 (68) hide show
  1. research_diff-0.2.0/.claude-plugin/marketplace.json +16 -0
  2. research_diff-0.2.0/.github/workflows/research-diff.yml +44 -0
  3. research_diff-0.2.0/PKG-INFO +224 -0
  4. research_diff-0.2.0/README.md +201 -0
  5. research_diff-0.2.0/docs/evidence.svg +128 -0
  6. {research_diff-0.1.0 → research_diff-0.2.0}/docs/research.svg +38 -17
  7. research_diff-0.2.0/examples/batch-size/configs/e2.yaml +12 -0
  8. {research_diff-0.1.0 → research_diff-0.2.0}/examples/batch-size/notes/ideas.md +7 -0
  9. research_diff-0.2.0/examples/batch-size/notes/results.md +16 -0
  10. research_diff-0.2.0/examples/batch-size/out/e2.json +1 -0
  11. research_diff-0.2.0/examples/batch-size/paper/main.tex +27 -0
  12. research_diff-0.2.0/mods/research-diff/.claude-plugin/plugin.json +11 -0
  13. research_diff-0.2.0/mods/research-diff/.mcp.json +8 -0
  14. research_diff-0.2.0/mods/research-diff/hooks/hooks.json +64 -0
  15. research_diff-0.2.0/mods/research-diff/hooks/page.tsx +223 -0
  16. research_diff-0.2.0/mods/research-diff/hooks/register.tsx +662 -0
  17. research_diff-0.2.0/mods/research-diff/scripts/run.sh +16 -0
  18. research_diff-0.2.0/mods/research-diff/skills/research-diff-explain/SKILL.md +22 -0
  19. research_diff-0.2.0/mods/research-diff/types/index.d.ts +49 -0
  20. {research_diff-0.1.0 → research_diff-0.2.0}/pyproject.toml +4 -4
  21. research_diff-0.2.0/src/research_diff/__init__.py +3 -0
  22. research_diff-0.2.0/src/research_diff/activity.py +91 -0
  23. research_diff-0.2.0/src/research_diff/agent.py +326 -0
  24. research_diff-0.2.0/src/research_diff/agents.py +280 -0
  25. research_diff-0.2.0/src/research_diff/cli.py +343 -0
  26. {research_diff-0.1.0 → research_diff-0.2.0}/src/research_diff/compare.py +42 -8
  27. {research_diff-0.1.0 → research_diff-0.2.0}/src/research_diff/config.py +6 -2
  28. {research_diff-0.1.0 → research_diff-0.2.0}/src/research_diff/diff.py +15 -3
  29. research_diff-0.2.0/src/research_diff/doctor.py +105 -0
  30. research_diff-0.2.0/src/research_diff/evgraph.py +423 -0
  31. research_diff-0.2.0/src/research_diff/evidence.py +295 -0
  32. {research_diff-0.1.0 → research_diff-0.2.0}/src/research_diff/extract.py +34 -5
  33. {research_diff-0.1.0 → research_diff-0.2.0}/src/research_diff/graph.py +10 -3
  34. research_diff-0.2.0/src/research_diff/history.py +102 -0
  35. research_diff-0.2.0/src/research_diff/mcp_server.py +210 -0
  36. research_diff-0.2.0/src/research_diff/narrate.py +30 -0
  37. research_diff-0.2.0/src/research_diff/objectives.py +160 -0
  38. research_diff-0.2.0/src/research_diff/page.py +372 -0
  39. research_diff-0.2.0/src/research_diff/rank.py +88 -0
  40. research_diff-0.2.0/src/research_diff/readme.py +55 -0
  41. research_diff-0.2.0/src/research_diff/statusline.py +48 -0
  42. research_diff-0.2.0/src/research_diff/store.py +67 -0
  43. {research_diff-0.1.0 → research_diff-0.2.0}/src/research_diff/suggest.py +109 -5
  44. research_diff-0.2.0/src/research_diff/tui.py +130 -0
  45. research_diff-0.2.0/src/research_diff/watch.py +237 -0
  46. research_diff-0.2.0/tests/test_evidence_and_agents.py +185 -0
  47. {research_diff-0.1.0 → research_diff-0.2.0}/tests/test_research_diff.py +39 -8
  48. research_diff-0.1.0/PKG-INFO +0 -111
  49. research_diff-0.1.0/README.md +0 -88
  50. research_diff-0.1.0/examples/batch-size/notes/results.md +0 -7
  51. research_diff-0.1.0/examples/batch-size/paper/main.tex +0 -7
  52. research_diff-0.1.0/src/research_diff/__init__.py +0 -2
  53. research_diff-0.1.0/src/research_diff/agent.py +0 -141
  54. research_diff-0.1.0/src/research_diff/cli.py +0 -153
  55. research_diff-0.1.0/src/research_diff/mcp_server.py +0 -112
  56. research_diff-0.1.0/src/research_diff/readme.py +0 -38
  57. research_diff-0.1.0/src/research_diff/watch.py +0 -69
  58. {research_diff-0.1.0 → research_diff-0.2.0}/.gitattributes +0 -0
  59. {research_diff-0.1.0 → research_diff-0.2.0}/.github/workflows/ci.yml +0 -0
  60. {research_diff-0.1.0 → research_diff-0.2.0}/.github/workflows/release.yml +0 -0
  61. {research_diff-0.1.0 → research_diff-0.2.0}/.gitignore +0 -0
  62. {research_diff-0.1.0 → research_diff-0.2.0}/LICENSE +0 -0
  63. {research_diff-0.1.0 → research_diff-0.2.0}/examples/batch-size/configs/e1.yaml +0 -0
  64. {research_diff-0.1.0 → research_diff-0.2.0}/examples/batch-size/out/e1.json +0 -0
  65. {research_diff-0.1.0 → research_diff-0.2.0}/research-diff.toml +0 -0
  66. {research_diff-0.1.0 → research_diff-0.2.0}/src/research_diff/__main__.py +0 -0
  67. {research_diff-0.1.0 → research_diff-0.2.0}/src/research_diff/trackers.py +0 -0
  68. {research_diff-0.1.0 → research_diff-0.2.0}/tests/conftest.py +0 -0
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "research-diff",
3
+ "owner": {
4
+ "name": "simplifiedmachine"
5
+ },
6
+ "metadata": {
7
+ "description": "research-diff for Claude Code: what supports and what contradicts each claim of your paper, live, while Claude and its agents run experiments and write."
8
+ },
9
+ "plugins": [
10
+ {
11
+ "name": "research-diff",
12
+ "source": "./mods/research-diff",
13
+ "description": "A Research diff pane beside the chat: the paper's claims with their evidence and contradictions, what changed since you last looked, and a team of agents on one study."
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,44 @@
1
+ name: research diff
2
+
3
+ # What a pull request does to the research, and above all to the evidence of the paper's claims (supported, contested,
4
+ # contradicted), as a comment on it and in the run's summary; the pictures (diff.svg, evidence.svg and the interactive
5
+ # evidence.html) are the run's "research-diff" artifact. Copy this file into another repository to get the same there
6
+ # (replace `pip install -e .` with `pip install research-diff`).
7
+ on:
8
+ pull_request:
9
+
10
+ permissions:
11
+ contents: read
12
+ pull-requests: write
13
+
14
+ jobs:
15
+ diff:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ with:
20
+ fetch-depth: 0
21
+ - uses: actions/setup-python@v5
22
+ with:
23
+ python-version: "3.12"
24
+ - run: python -m pip install -e .
25
+ - name: What this pull request does to the research and its evidence
26
+ run: |
27
+ research-diff diff --base "origin/${{ github.base_ref }}" --head HEAD --out research-diff-out
28
+ research-diff evidence --at HEAD --out research-diff-out
29
+ research-diff comment --base "origin/${{ github.base_ref }}" --head HEAD --out research-diff-out/comment.md
30
+ echo >> research-diff-out/comment.md
31
+ echo "The pictures: the **research-diff** artifact of [this run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})." >> research-diff-out/comment.md
32
+ cat research-diff-out/comment.md >> "$GITHUB_STEP_SUMMARY"
33
+ - uses: actions/upload-artifact@v4
34
+ with:
35
+ name: research-diff
36
+ path: research-diff-out
37
+ - name: Comment on the pull request
38
+ # A pull request from a fork gets a read-only token: it has the summary and the artifact instead.
39
+ if: github.event.pull_request.head.repo.full_name == github.repository
40
+ env:
41
+ GH_TOKEN: ${{ github.token }}
42
+ run: |
43
+ gh pr comment "${{ github.event.pull_request.number }}" --body-file research-diff-out/comment.md --edit-last \
44
+ || gh pr comment "${{ github.event.pull_request.number }}" --body-file research-diff-out/comment.md
@@ -0,0 +1,224 @@
1
+ Metadata-Version: 2.5
2
+ Name: research-diff
3
+ Version: 0.2.0
4
+ Summary: Maps your research from its notes, experiment configs, results and paper, draws which evidence supports and which contradicts each claim of the paper, and shows what each iteration (and each agent) changed. Built for doing research with AI coding agents.
5
+ Project-URL: Homepage, https://github.com/simplifiedmachine/research-diff
6
+ Project-URL: Documentation, https://github.com/simplifiedmachine/research-diff/wiki
7
+ Author: simplifiedmachine
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: ai-agents,argument-map,claude-code,contradictions,evidence,experiment-tracking,hypotheses,mcp,multi-agent,reproducibility,research
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Topic :: Scientific/Engineering
15
+ Requires-Python: >=3.11
16
+ Requires-Dist: system-diff==0.8.0
17
+ Provides-Extra: dev
18
+ Requires-Dist: mcp>=1.10; extra == 'dev'
19
+ Requires-Dist: pytest>=8; extra == 'dev'
20
+ Provides-Extra: mcp
21
+ Requires-Dist: mcp>=1.10; extra == 'mcp'
22
+ Description-Content-Type: text/markdown
23
+
24
+ # research-diff
25
+
26
+ ### `git diff` shows you lines. **research-diff shows you what your evidence says about your paper.**
27
+
28
+ When you run experiments and write a paper with Claude, and more so with a team of agents each on its own experiments
29
+ and sections, the paper's claims drift away from its evidence faster than anyone can re-read it. A new run quietly
30
+ weakens a hypothesis that three claims rely on; one agent's discussion contradicts another agent's results section; a
31
+ number in the paper no longer matches the results file.
32
+
33
+ **research-diff draws the paper's argument as a graph and keeps it current**: which findings and conclusions are
34
+ supported by which evidence, and above all **which evidence contradicts your own claims**, including where the paper
35
+ contradicts itself and where one agent's work contradicts another's. In plain colours: green supports, red contradicts.
36
+
37
+ <!-- research-map:begin -->
38
+ ![Evidence graph: what supports and what contradicts each claim of the paper](https://raw.githubusercontent.com/simplifiedmachine/research-diff/main/docs/evidence.svg)
39
+
40
+ ![Research map, generated from the notes, configs, results and paper](https://raw.githubusercontent.com/simplifiedmachine/research-diff/main/docs/research.svg)
41
+
42
+ <details><summary>3 open warnings</summary>
43
+
44
+ - C1 is contradicted by C2
45
+ - C3 expects E2.results acc.batch512 < 0.85, but it is 0.872
46
+ - H2 is open and no experiment tests it
47
+
48
+ </details>
49
+ <!-- research-map:end -->
50
+
51
+ The graph above is this repository's own example (`examples/batch-size`), regenerated from its files on every change:
52
+ two agents, `batch-agent` and `lr-agent`; the Discussion's C2 contradicts the Results' C1, and C3 expects a number
53
+ (batch 512 below 85%) that the experiment E2 does not give.
54
+
55
+ ## The evidence graph
56
+
57
+ Left to right: **evidence** (results, tracker runs, an experiment's numbers, optionally citations), **hypotheses**,
58
+ **findings**, **claims**, the paper's statements in a band per paper section. Every statement gets a verdict:
59
+
60
+ | | Verdict | Means |
61
+ |---|---|---|
62
+ | ✓ | supported | evidence for it, none against it |
63
+ | ◐ | contested | evidence for it and against it |
64
+ | ✗ | contradicted | evidence against it and none for it, or you marked it refuted |
65
+ | ○ | no evidence | nothing backs it, or only what has no evidence itself (an *ungrounded* support) |
66
+
67
+ A support only counts while its source holds. When a hypothesis is refuted, or a result is itself contradicted, the
68
+ support it gave becomes a **broken support** (dashed red), with why: *"C1 relies on H1, which R4 contradicts"*. So a
69
+ contradiction reaches every claim built on what it contradicts. A number a claim `expects:` supports it while it holds
70
+ and contradicts it when it does not.
71
+
72
+ ```sh
73
+ research-diff evidence --out docs # evidence.svg (README, appendix, slides), evidence.html (interactive),
74
+ # evidence.mmd (Mermaid), evidence.md (a table), evidence.json
75
+ research-diff evidence --strict # exit 1 while a statement is contradicted or contested (for CI)
76
+ research-diff show # the same, in any terminal; `research-diff show C3` for one claim's chain
77
+ research-diff suggest --links # your LLM proposes supports/contradicts links nobody wrote, as a patch
78
+ ```
79
+
80
+ The interactive page: click a claim and its evidence chain lights up; *Only contradictions* hides everything else; one
81
+ agent's work at a time.
82
+
83
+ ## What it reads
84
+
85
+ Markers in your own files, in one grammar: an id (`Q` question, `H` hypothesis, `E` experiment, `R` result, `F`
86
+ finding, `C` claim, and a number) and a title, then links and a status on the lines after it.
87
+
88
+ ```markdown
89
+ ## H2: Learning-rate warm-up removes the gap <- notes (Markdown): a heading or a list item
90
+ answers: Q1
91
+ status: open <- open | supported | refuted | anything you like
92
+ by: lr-agent <- who owns it (an agent of a team, or a person)
93
+ ```
94
+
95
+ ```latex
96
+ \section{Discussion} % the paper's sections become the graph's bands
97
+ % C2: Batch size does not matter once the learning rate is scaled
98
+ % relies on: F1, H3
99
+ % contradicts: C1 <- the paper contradicting itself, said out loud
100
+ % expects: E2.results acc.batch512 > 0.86 <- a number it needs; checked on every change
101
+ ```
102
+
103
+ | Where | How |
104
+ |---|---|
105
+ | Notes (`.md`) | definitions as above; `tests:`, `of:`, `supports:`, `weakens:`, `contradicts:`, `relies on:`, `metrics: acc=0.91`, `by:` |
106
+ | The paper (LaTeX, or Markdown) | a comment: `% C1: Small batches win` with the same lines; the paragraph's `\cite{…}` become its sources; its `\section{}` its band |
107
+ | Experiment configs (YAML, JSON, TOML) | a `research:` block: `id`, `title`, `tests`, `status`, and `results: out/e1.json`, whose numbers become the result `E1.results` |
108
+ | Scripts and notebooks | a comment: `# research-diff: E2 tests H2` |
109
+ | Either end of a link | `supported by: R1`, `contradicted by: R4`, `weakened by: R2` are the same links written on the claim |
110
+
111
+ The graph is built from markers only, so the same files always give the same graph. It warns when a claim relies on
112
+ nothing or on a refuted hypothesis, when a number no longer meets what a claim `expects:`, when an open hypothesis has
113
+ no experiment, and when a link points at nothing.
114
+
115
+ ## Install
116
+
117
+ 1. The engine (Python 3.11+):
118
+ ```sh
119
+ pip install "research-diff[mcp]" # or: pipx install "research-diff[mcp]"
120
+ ```
121
+ 2. The plugin, in Claude Code (the pane beside the chat, the hooks and the MCP server):
122
+ ```
123
+ /plugin marketplace add simplifiedmachine/research-diff
124
+ /plugin install research-diff
125
+ ```
126
+ Or without the pane: `research-diff setup claude` (hooks, status line, a skill and the MCP server; `--undo`).
127
+ 3. Restart Claude Code. The pane opens beside the chat; `/research-diff` opens it again.
128
+
129
+ ## In Claude Code
130
+
131
+ - **The pane**: `n` Now · `r` Review · `e` Evidence · `a` Agents · `h` History. Arrows pick a claim (its evidence
132
+ lights up), Enter zooms into its evidence chain, `b` goes back, `f` follows Claude. `/research-diff tui` opens the
133
+ same in a terminal of its own, and `research-diff watch` in a browser at `http://127.0.0.1:8766/`.
134
+ - **Now**: where Claude (or which agent) is working, every statement worst first, and what is **worth a look** since
135
+ you last looked, ranked by consequence (the paper contradicting itself first) and each with why it matters.
136
+ - **Review**: everything since your checkpoint, exactly, with a picture of only what changed.
137
+ - **Evidence**: every statement by paper section with what supports it and what contradicts it.
138
+ - **Agents**: the team, what each agent owns, its verdicts, where it contradicts another agent, and the bus.
139
+ - **History**: how the research got here: *"You asked: run the LR ablation → it got: R2, H1 supported → contested,
140
+ 1 new contradiction (C2 contradicts C1)"*, for the whole study or one claim.
141
+ - **In the chat**: one line when an edit or a run moves a claim's verdict or makes a contradiction, and one at the end
142
+ of the turn. The status line keeps the count of contradictions in view.
143
+ - **Ask Claude** "does C3 still hold?" or "what contradicts the paper?": it answers from the MCP tools
144
+ (`research_evidence`, `explain`, `research_diff`, `research_map`), with the picture.
145
+ - **Objectives**: research-diff learns what you keep asking for ("three seeds for every number", "don't claim beyond
146
+ the 8k split"), shows it, keeps it in front of Claude and every agent, and marks changes that touch it. `x` clears
147
+ one you disagree with; `research-diff objectives add TEXT` states one.
148
+
149
+ ## Teams of agents
150
+
151
+ For work across the study, Claude plans a team with `plan_agents`: one agent per paper section, or per hypothesis
152
+ (its experiments and their results), or as you say. Each agent gets a brief: what it owns, the evidence its work
153
+ relies on (owned by others), the contradictions already open on its nodes, and the rules.
154
+
155
+ - Each agent **claims** its nodes (`claim`) and writes `by: <name>` under its markers: the graph colours every box by
156
+ its agent.
157
+ - The **bus** has a topic per node. The hooks publish every change on the topic of the node it touched, as it happens;
158
+ a **new contradiction goes to the owner of the contradicted node**, naming both agents: *"CONTRADICTION: R4
159
+ contradicts C1 (R4 is lr-agent's, C1 is batch-agent's)"*. Agents `publish` their own notes too.
160
+ - Each agent hears the nodes it owns and everything upstream of them in the evidence graph, and its unread messages
161
+ reach it with its next tool result (the PostToolUse hook), without waiting on anyone.
162
+ - The Agents tab and the graph's *across agents* list show where one agent's work contradicts another's.
163
+
164
+ ```sh
165
+ research-diff agents plan "write the batch-size paper" # the same from a terminal: the briefs
166
+ research-diff agents # the team and the bus
167
+ ```
168
+
169
+ ## Use without Claude Code
170
+
171
+ ```sh
172
+ research-diff map --out docs # research.svg and research.json: the whole map
173
+ research-diff diff --base HEAD # what your uncommitted iteration did (--narrate: in plain words, by your LLM)
174
+ research-diff sync # MLflow / W&B runs into research/runs.json
175
+ research-diff checkpoint # mark what you have understood
176
+ research-diff diff # only what came after that (--base turn: this turn of your agent)
177
+ research-diff history --commits 50 # the research's history, from git too
178
+ research-diff readme # keep the README's evidence graph and map current (--check in CI)
179
+ research-diff doctor # why it is quiet, slow or wrong here
180
+ ```
181
+
182
+ A diff reads like: *1 new contradiction (C1 relies on H1, which is refuted); C1: no evidence → contradicted; adds 1
183
+ hypothesis (H3); H1: open → refuted; E1.results acc.b32: 0.874 → 0.881 (+0.8%); 1 new link.* It comes with the exact
184
+ list (`plan.txt`) and a picture of only what changed (`diff.svg`).
185
+
186
+ **Pull requests**: every pull request gets its research diff and the evidence table as a comment, with the evidence
187
+ graph in Mermaid, which GitHub draws (`.github/workflows/research-diff.yml`, which you can copy;
188
+ `research-diff comment` writes the comment).
189
+
190
+ ## Experiment trackers
191
+
192
+ Runs logged to MLflow (its local `mlruns/` store) or W&B (its local `wandb/` folders) become results of the experiment
193
+ they are tagged with: `research-diff.experiment` (or `research_id`) as an MLflow tag or param, `research_id` in the W&B
194
+ config. Tracker folders are usually git-ignored, so `research-diff sync` copies their runs into `research/runs.json`,
195
+ which is tracked: the runs are then on the map, in git and in the next diff. The hooks, the live page and the MCP tools
196
+ sync on their own.
197
+
198
+ ## Markers suggested by your LLM
199
+
200
+ ```sh
201
+ research-diff suggest # notes and paper files with no marker yet, or name the files
202
+ git apply .git/research-diff/suggest.patch
203
+ research-diff suggest --links # supports / contradicts / weakens links between the nodes you have
204
+ git apply .git/research-diff/links.patch
205
+ ```
206
+
207
+ Your LLM (the one your Claude Code uses) proposes markers for what the text already says, and links (above all the
208
+ contradictions) that the text and the numbers show. Each proposal is checked before it reaches the patch: a real line
209
+ of a file it was shown, a marker in that file's own form, ids that exist (or, for a new marker, are not used yet), a
210
+ link not already written. Nothing is written until you apply the patch.
211
+
212
+ ## Privacy
213
+
214
+ Everything stays on your machine, under `.git/research-diff/`: never committed, never sent anywhere. The only exception
215
+ is the optional LLM features (objectives, `suggest`, `--narrate`), which send your requests or the text of the files
216
+ you name to the LLM your own Claude Code already uses. `RESEARCH_DIFF_LLM=off` turns them off;
217
+ `RESEARCH_DIFF_WEB=off` keeps the hooks from starting the web page.
218
+
219
+ The pictures, git reading and LLM discovery are [system-diff](https://github.com/simplifiedmachine/system-diff)'s; the
220
+ pane is system-diff's pane, showing the research.
221
+
222
+ ## License
223
+
224
+ MIT
@@ -0,0 +1,201 @@
1
+ # research-diff
2
+
3
+ ### `git diff` shows you lines. **research-diff shows you what your evidence says about your paper.**
4
+
5
+ When you run experiments and write a paper with Claude, and more so with a team of agents each on its own experiments
6
+ and sections, the paper's claims drift away from its evidence faster than anyone can re-read it. A new run quietly
7
+ weakens a hypothesis that three claims rely on; one agent's discussion contradicts another agent's results section; a
8
+ number in the paper no longer matches the results file.
9
+
10
+ **research-diff draws the paper's argument as a graph and keeps it current**: which findings and conclusions are
11
+ supported by which evidence, and above all **which evidence contradicts your own claims**, including where the paper
12
+ contradicts itself and where one agent's work contradicts another's. In plain colours: green supports, red contradicts.
13
+
14
+ <!-- research-map:begin -->
15
+ ![Evidence graph: what supports and what contradicts each claim of the paper](https://raw.githubusercontent.com/simplifiedmachine/research-diff/main/docs/evidence.svg)
16
+
17
+ ![Research map, generated from the notes, configs, results and paper](https://raw.githubusercontent.com/simplifiedmachine/research-diff/main/docs/research.svg)
18
+
19
+ <details><summary>3 open warnings</summary>
20
+
21
+ - C1 is contradicted by C2
22
+ - C3 expects E2.results acc.batch512 < 0.85, but it is 0.872
23
+ - H2 is open and no experiment tests it
24
+
25
+ </details>
26
+ <!-- research-map:end -->
27
+
28
+ The graph above is this repository's own example (`examples/batch-size`), regenerated from its files on every change:
29
+ two agents, `batch-agent` and `lr-agent`; the Discussion's C2 contradicts the Results' C1, and C3 expects a number
30
+ (batch 512 below 85%) that the experiment E2 does not give.
31
+
32
+ ## The evidence graph
33
+
34
+ Left to right: **evidence** (results, tracker runs, an experiment's numbers, optionally citations), **hypotheses**,
35
+ **findings**, **claims**, the paper's statements in a band per paper section. Every statement gets a verdict:
36
+
37
+ | | Verdict | Means |
38
+ |---|---|---|
39
+ | ✓ | supported | evidence for it, none against it |
40
+ | ◐ | contested | evidence for it and against it |
41
+ | ✗ | contradicted | evidence against it and none for it, or you marked it refuted |
42
+ | ○ | no evidence | nothing backs it, or only what has no evidence itself (an *ungrounded* support) |
43
+
44
+ A support only counts while its source holds. When a hypothesis is refuted, or a result is itself contradicted, the
45
+ support it gave becomes a **broken support** (dashed red), with why: *"C1 relies on H1, which R4 contradicts"*. So a
46
+ contradiction reaches every claim built on what it contradicts. A number a claim `expects:` supports it while it holds
47
+ and contradicts it when it does not.
48
+
49
+ ```sh
50
+ research-diff evidence --out docs # evidence.svg (README, appendix, slides), evidence.html (interactive),
51
+ # evidence.mmd (Mermaid), evidence.md (a table), evidence.json
52
+ research-diff evidence --strict # exit 1 while a statement is contradicted or contested (for CI)
53
+ research-diff show # the same, in any terminal; `research-diff show C3` for one claim's chain
54
+ research-diff suggest --links # your LLM proposes supports/contradicts links nobody wrote, as a patch
55
+ ```
56
+
57
+ The interactive page: click a claim and its evidence chain lights up; *Only contradictions* hides everything else; one
58
+ agent's work at a time.
59
+
60
+ ## What it reads
61
+
62
+ Markers in your own files, in one grammar: an id (`Q` question, `H` hypothesis, `E` experiment, `R` result, `F`
63
+ finding, `C` claim, and a number) and a title, then links and a status on the lines after it.
64
+
65
+ ```markdown
66
+ ## H2: Learning-rate warm-up removes the gap <- notes (Markdown): a heading or a list item
67
+ answers: Q1
68
+ status: open <- open | supported | refuted | anything you like
69
+ by: lr-agent <- who owns it (an agent of a team, or a person)
70
+ ```
71
+
72
+ ```latex
73
+ \section{Discussion} % the paper's sections become the graph's bands
74
+ % C2: Batch size does not matter once the learning rate is scaled
75
+ % relies on: F1, H3
76
+ % contradicts: C1 <- the paper contradicting itself, said out loud
77
+ % expects: E2.results acc.batch512 > 0.86 <- a number it needs; checked on every change
78
+ ```
79
+
80
+ | Where | How |
81
+ |---|---|
82
+ | Notes (`.md`) | definitions as above; `tests:`, `of:`, `supports:`, `weakens:`, `contradicts:`, `relies on:`, `metrics: acc=0.91`, `by:` |
83
+ | The paper (LaTeX, or Markdown) | a comment: `% C1: Small batches win` with the same lines; the paragraph's `\cite{…}` become its sources; its `\section{}` its band |
84
+ | Experiment configs (YAML, JSON, TOML) | a `research:` block: `id`, `title`, `tests`, `status`, and `results: out/e1.json`, whose numbers become the result `E1.results` |
85
+ | Scripts and notebooks | a comment: `# research-diff: E2 tests H2` |
86
+ | Either end of a link | `supported by: R1`, `contradicted by: R4`, `weakened by: R2` are the same links written on the claim |
87
+
88
+ The graph is built from markers only, so the same files always give the same graph. It warns when a claim relies on
89
+ nothing or on a refuted hypothesis, when a number no longer meets what a claim `expects:`, when an open hypothesis has
90
+ no experiment, and when a link points at nothing.
91
+
92
+ ## Install
93
+
94
+ 1. The engine (Python 3.11+):
95
+ ```sh
96
+ pip install "research-diff[mcp]" # or: pipx install "research-diff[mcp]"
97
+ ```
98
+ 2. The plugin, in Claude Code (the pane beside the chat, the hooks and the MCP server):
99
+ ```
100
+ /plugin marketplace add simplifiedmachine/research-diff
101
+ /plugin install research-diff
102
+ ```
103
+ Or without the pane: `research-diff setup claude` (hooks, status line, a skill and the MCP server; `--undo`).
104
+ 3. Restart Claude Code. The pane opens beside the chat; `/research-diff` opens it again.
105
+
106
+ ## In Claude Code
107
+
108
+ - **The pane**: `n` Now · `r` Review · `e` Evidence · `a` Agents · `h` History. Arrows pick a claim (its evidence
109
+ lights up), Enter zooms into its evidence chain, `b` goes back, `f` follows Claude. `/research-diff tui` opens the
110
+ same in a terminal of its own, and `research-diff watch` in a browser at `http://127.0.0.1:8766/`.
111
+ - **Now**: where Claude (or which agent) is working, every statement worst first, and what is **worth a look** since
112
+ you last looked, ranked by consequence (the paper contradicting itself first) and each with why it matters.
113
+ - **Review**: everything since your checkpoint, exactly, with a picture of only what changed.
114
+ - **Evidence**: every statement by paper section with what supports it and what contradicts it.
115
+ - **Agents**: the team, what each agent owns, its verdicts, where it contradicts another agent, and the bus.
116
+ - **History**: how the research got here: *"You asked: run the LR ablation → it got: R2, H1 supported → contested,
117
+ 1 new contradiction (C2 contradicts C1)"*, for the whole study or one claim.
118
+ - **In the chat**: one line when an edit or a run moves a claim's verdict or makes a contradiction, and one at the end
119
+ of the turn. The status line keeps the count of contradictions in view.
120
+ - **Ask Claude** "does C3 still hold?" or "what contradicts the paper?": it answers from the MCP tools
121
+ (`research_evidence`, `explain`, `research_diff`, `research_map`), with the picture.
122
+ - **Objectives**: research-diff learns what you keep asking for ("three seeds for every number", "don't claim beyond
123
+ the 8k split"), shows it, keeps it in front of Claude and every agent, and marks changes that touch it. `x` clears
124
+ one you disagree with; `research-diff objectives add TEXT` states one.
125
+
126
+ ## Teams of agents
127
+
128
+ For work across the study, Claude plans a team with `plan_agents`: one agent per paper section, or per hypothesis
129
+ (its experiments and their results), or as you say. Each agent gets a brief: what it owns, the evidence its work
130
+ relies on (owned by others), the contradictions already open on its nodes, and the rules.
131
+
132
+ - Each agent **claims** its nodes (`claim`) and writes `by: <name>` under its markers: the graph colours every box by
133
+ its agent.
134
+ - The **bus** has a topic per node. The hooks publish every change on the topic of the node it touched, as it happens;
135
+ a **new contradiction goes to the owner of the contradicted node**, naming both agents: *"CONTRADICTION: R4
136
+ contradicts C1 (R4 is lr-agent's, C1 is batch-agent's)"*. Agents `publish` their own notes too.
137
+ - Each agent hears the nodes it owns and everything upstream of them in the evidence graph, and its unread messages
138
+ reach it with its next tool result (the PostToolUse hook), without waiting on anyone.
139
+ - The Agents tab and the graph's *across agents* list show where one agent's work contradicts another's.
140
+
141
+ ```sh
142
+ research-diff agents plan "write the batch-size paper" # the same from a terminal: the briefs
143
+ research-diff agents # the team and the bus
144
+ ```
145
+
146
+ ## Use without Claude Code
147
+
148
+ ```sh
149
+ research-diff map --out docs # research.svg and research.json: the whole map
150
+ research-diff diff --base HEAD # what your uncommitted iteration did (--narrate: in plain words, by your LLM)
151
+ research-diff sync # MLflow / W&B runs into research/runs.json
152
+ research-diff checkpoint # mark what you have understood
153
+ research-diff diff # only what came after that (--base turn: this turn of your agent)
154
+ research-diff history --commits 50 # the research's history, from git too
155
+ research-diff readme # keep the README's evidence graph and map current (--check in CI)
156
+ research-diff doctor # why it is quiet, slow or wrong here
157
+ ```
158
+
159
+ A diff reads like: *1 new contradiction (C1 relies on H1, which is refuted); C1: no evidence → contradicted; adds 1
160
+ hypothesis (H3); H1: open → refuted; E1.results acc.b32: 0.874 → 0.881 (+0.8%); 1 new link.* It comes with the exact
161
+ list (`plan.txt`) and a picture of only what changed (`diff.svg`).
162
+
163
+ **Pull requests**: every pull request gets its research diff and the evidence table as a comment, with the evidence
164
+ graph in Mermaid, which GitHub draws (`.github/workflows/research-diff.yml`, which you can copy;
165
+ `research-diff comment` writes the comment).
166
+
167
+ ## Experiment trackers
168
+
169
+ Runs logged to MLflow (its local `mlruns/` store) or W&B (its local `wandb/` folders) become results of the experiment
170
+ they are tagged with: `research-diff.experiment` (or `research_id`) as an MLflow tag or param, `research_id` in the W&B
171
+ config. Tracker folders are usually git-ignored, so `research-diff sync` copies their runs into `research/runs.json`,
172
+ which is tracked: the runs are then on the map, in git and in the next diff. The hooks, the live page and the MCP tools
173
+ sync on their own.
174
+
175
+ ## Markers suggested by your LLM
176
+
177
+ ```sh
178
+ research-diff suggest # notes and paper files with no marker yet, or name the files
179
+ git apply .git/research-diff/suggest.patch
180
+ research-diff suggest --links # supports / contradicts / weakens links between the nodes you have
181
+ git apply .git/research-diff/links.patch
182
+ ```
183
+
184
+ Your LLM (the one your Claude Code uses) proposes markers for what the text already says, and links (above all the
185
+ contradictions) that the text and the numbers show. Each proposal is checked before it reaches the patch: a real line
186
+ of a file it was shown, a marker in that file's own form, ids that exist (or, for a new marker, are not used yet), a
187
+ link not already written. Nothing is written until you apply the patch.
188
+
189
+ ## Privacy
190
+
191
+ Everything stays on your machine, under `.git/research-diff/`: never committed, never sent anywhere. The only exception
192
+ is the optional LLM features (objectives, `suggest`, `--narrate`), which send your requests or the text of the files
193
+ you name to the LLM your own Claude Code already uses. `RESEARCH_DIFF_LLM=off` turns them off;
194
+ `RESEARCH_DIFF_WEB=off` keeps the hooks from starting the web page.
195
+
196
+ The pictures, git reading and LLM discovery are [system-diff](https://github.com/simplifiedmachine/system-diff)'s; the
197
+ pane is system-diff's pane, showing the research.
198
+
199
+ ## License
200
+
201
+ MIT