overleaf-review 0.3.0 → 0.5.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.
- package/README.md +198 -15
- package/dist/cli.js +3725 -371
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -35,14 +35,24 @@ workflow and carries the review layer Git can't represent.
|
|
|
35
35
|
- 📥 **`pull`** — read comments + tracked changes (with anchors) into a Git-friendly sidecar
|
|
36
36
|
(`.overleaf/reviews.md` + `.json`), so your tools have every co-author note in context.
|
|
37
37
|
- 📤 **`push`** — turn local edits into **tracked-change suggestions**, mapping files to Overleaf
|
|
38
|
-
docs by path (one file, or every changed `.tex` at once).
|
|
39
|
-
|
|
38
|
+
docs by path (one file, or every changed `.tex` at once). A saved Base/Local/Live merge keeps
|
|
39
|
+
non-overlapping co-author edits, while overlapping edits and active tracked-change ranges stop
|
|
40
|
+
the push for inspection. `--direct` sends plain edits instead of suggestions.
|
|
40
41
|
- 🔄 **`fetch`** — write Overleaf's current text back down into your repo (read-only on Overleaf, so
|
|
41
|
-
it cannot disturb a single comment or tracked change)
|
|
42
|
+
it cannot disturb a single comment or tracked change) and save the synchronization base used by
|
|
43
|
+
future pushes. Existing local files are snapshotted before replacement.
|
|
44
|
+
- 📋 **`review plan` / `review submit`** — save a complete, binding push plan, inspect it, then
|
|
45
|
+
submit it only if the local file, saved base, live document version, and review ranges are still
|
|
46
|
+
unchanged.
|
|
42
47
|
- 🖼️ **`upload`** — push figures, PDFs, or new files into Overleaf.
|
|
43
48
|
- 💬 **`comment` / `reply` / `resolve` / `delete-comment` / `delete-message`** — full comment
|
|
44
49
|
control: start a thread, reply, resolve/reopen, delete a whole thread or a single message.
|
|
45
|
-
|
|
50
|
+
Identical recent comments and replies are retry-safe by default; `--force` deliberately posts
|
|
51
|
+
another copy.
|
|
52
|
+
- ✅ **`accept` / `reject`** — act on collaborators' tracked changes and verify removal of every
|
|
53
|
+
requested change id before reporting success; rejection also verifies the exact resulting text.
|
|
54
|
+
- 🧾 **Review receipts** — pushes, accept/reject actions, comments, and replies leave durable JSON
|
|
55
|
+
records under `.overleaf/receipts/` showing what was verified or left ambiguous.
|
|
46
56
|
- 🔑 **`login`** — validated auth stored outside your repo (chmod 600); `--browser` mode is
|
|
47
57
|
institutional-SSO friendly.
|
|
48
58
|
|
|
@@ -60,9 +70,11 @@ ops that Overleaf *transforms the review ranges against*, so comments and tracke
|
|
|
60
70
|
|
|
61
71
|
| Need | Command |
|
|
62
72
|
| --- | --- |
|
|
63
|
-
|
|
|
73
|
+
| Begin a local review session | `review start` |
|
|
74
|
+
| Overleaf text → your repo and save Base | `fetch` |
|
|
64
75
|
| Your edits → Overleaf, as suggestions | `push` |
|
|
65
76
|
| Your edits → Overleaf, directly | `push --direct` |
|
|
77
|
+
| Inspect, then submit the exact same change | `review plan --out plan.json`, then `review submit --plan plan.json` |
|
|
66
78
|
| Figures / new files → Overleaf | `upload` |
|
|
67
79
|
|
|
68
80
|
Your Git repo stays a completely normal repo — commit whatever you like, `.tex` included — and
|
|
@@ -85,14 +97,28 @@ overleaf-review login --browser # opens your Chrome, log in normally (SSO work
|
|
|
85
97
|
# 2. Link this repo to an Overleaf project (id from the project URL)
|
|
86
98
|
overleaf-review link --project 6a4c…bec5a
|
|
87
99
|
|
|
88
|
-
# 3.
|
|
89
|
-
overleaf-review
|
|
90
|
-
|
|
91
|
-
|
|
100
|
+
# 3. Start from Overleaf's current text and review state
|
|
101
|
+
overleaf-review review start # fetch text + save Base + pull reviews
|
|
102
|
+
|
|
103
|
+
# 4. Edit locally, then inspect and submit a binding plan
|
|
104
|
+
overleaf-review review plan --out .overleaf/push-plan.json
|
|
105
|
+
overleaf-review review submit --plan .overleaf/push-plan.json
|
|
106
|
+
|
|
107
|
+
# Or use the safe one-shot form when a separate approval step is unnecessary
|
|
108
|
+
overleaf-review push --dry-run # transient preview; sends nothing
|
|
109
|
+
overleaf-review push # plan, validate, send, and verify
|
|
110
|
+
|
|
111
|
+
# 5. Work with review threads
|
|
92
112
|
overleaf-review comment --anchor "Introduction" --message "Expand this section"
|
|
93
113
|
overleaf-review resolve --thread <id> # thread ids come from `pull`
|
|
94
114
|
```
|
|
95
115
|
|
|
116
|
+
`fetch` and `review start` write Overleaf's text into the local files, so commit or otherwise
|
|
117
|
+
preserve local-only work before running them. They save `.overleaf/base.json`; edit only after that
|
|
118
|
+
base is established. Existing installations should run one of these commands once before their
|
|
119
|
+
first safe push. If an upgraded repository already has unpushed edits, copy or stash them, run
|
|
120
|
+
`fetch`, then restore the edits so the new Base remains the Overleaf version they were based on.
|
|
121
|
+
|
|
96
122
|
## 🧭 Commands
|
|
97
123
|
|
|
98
124
|
| Command | What it does |
|
|
@@ -100,11 +126,16 @@ overleaf-review resolve --thread <id> # thread ids come from `pull`
|
|
|
100
126
|
| `login [--cookie <v>] [--browser]` | Authenticate and store your session (SSO-friendly `--browser`) |
|
|
101
127
|
| `link --project <id>` | Link this repo to an Overleaf project (`.overleaf/config.json`) |
|
|
102
128
|
| `pull [--out <dir>]` | Read comments + tracked changes into a sidecar |
|
|
103
|
-
| `fetch [--file <f>] [--dry-run]` | Write Overleaf
|
|
129
|
+
| `fetch [--file <f>] [--dry-run]` | Write Overleaf text locally, snapshot replaced files, and save Base (read-only on Overleaf) |
|
|
130
|
+
| `review start [--file <f>] [--out <dir>]` | Fetch text, save the synchronization base, and pull the review sidecar |
|
|
131
|
+
| `review plan --out <plan.json> [--file <f>] [--edits <blocks.json>] [--doc <name>] [--direct] [--allow-overlap] [--unsafe-no-base]` | Create a complete binding plan without changing Overleaf |
|
|
132
|
+
| `review submit --plan <plan.json> [--acknowledge-ambiguous]` | Submit that plan only if all recorded preconditions still match |
|
|
133
|
+
| `review consolidate --doc <path> --author <user-id> --out <preview.json> [--change <id> …]` | Preview consolidation of existing suggestions and save a full backup; no Overleaf changes |
|
|
134
|
+
| `review consolidate --apply --plan <plan.json>` | Apply and verify a checked consolidation plan for your own suggestions |
|
|
104
135
|
| `upload <path…> [--folder <name>]` | Upload figures / new files into Overleaf |
|
|
105
|
-
| `push [--file <f>] [--doc <name>] [--direct] [--dry-run]` |
|
|
106
|
-
| `comment --anchor <text> --message <text> [--doc <name>] [--nth <n>]` | Add
|
|
107
|
-
| `reply --thread <id> --message <text
|
|
136
|
+
| `push [--file <f>] [--doc <name>] [--direct] [--dry-run] [--plan-out <path>] [--plan <path>] [--allow-overlap] [--unsafe-no-base] [--acknowledge-ambiguous]` | Safely merge and send local edits (all changed `.tex` if no `--file`) |
|
|
137
|
+
| `comment --anchor <text> --message <text> [--doc <name>] [--nth <n>] [--force]` | Add an anchored comment; recent identical retries are skipped unless forced |
|
|
138
|
+
| `reply --thread <id> --message <text> [--force]` | Reply to a thread; recent identical retries are skipped unless forced |
|
|
108
139
|
| `resolve --thread <id> [--reopen]` | Resolve (or reopen) a comment thread |
|
|
109
140
|
| `delete-comment --thread <id>` | Delete a whole comment thread |
|
|
110
141
|
| `delete-message --message-id <id> [--thread <id>]` | Delete a single message within a thread |
|
|
@@ -113,6 +144,154 @@ overleaf-review resolve --thread <id> # thread ids come from `pull`
|
|
|
113
144
|
|
|
114
145
|
Thread and change ids are listed by `pull` (in `.overleaf/reviews.md`).
|
|
115
146
|
|
|
147
|
+
### Safe pushes
|
|
148
|
+
|
|
149
|
+
A normal push compares three versions of each document:
|
|
150
|
+
|
|
151
|
+
- **Base** — the Overleaf text saved by the last `fetch` or successful push;
|
|
152
|
+
- **Local** — your current file;
|
|
153
|
+
- **Live** — the document as it exists in Overleaf when planning.
|
|
154
|
+
|
|
155
|
+
Your Base→Local intent is rebased onto Live. Non-overlapping live edits are preserved; genuinely
|
|
156
|
+
overlapping Base→Local and Base→Live edits abort instead of silently undoing a collaborator's
|
|
157
|
+
work. A proposed edit that intersects an active tracked-change range is also blocked by default and
|
|
158
|
+
the relevant change ids are listed.
|
|
159
|
+
|
|
160
|
+
For intentional sentence or paragraph rewrites, agents should preserve their chosen edit boundaries
|
|
161
|
+
with `--edits`, rather than relying on automatic diff grouping. Edit the local file normally, then
|
|
162
|
+
describe every change in a JSON manifest:
|
|
163
|
+
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"replacements": [
|
|
167
|
+
{
|
|
168
|
+
"before": "This is the old paragraph. Its explanation is unclear.",
|
|
169
|
+
"after": "This is the revised paragraph. Its explanation is clearer."
|
|
170
|
+
}
|
|
171
|
+
]
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
```sh
|
|
176
|
+
overleaf-review review plan --file main.tex --edits blocks.json --out plan.json
|
|
177
|
+
overleaf-review review submit --plan plan.json
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Each block becomes one deletion and/or insertion, even across multiple sentences or LaTeX markup.
|
|
181
|
+
Overleaf controls the resulting review UI; a replacement is generally two tracked ranges, not a
|
|
182
|
+
guaranteed single accept/reject button. Keep typo corrections small, group a coherent rewrite,
|
|
183
|
+
and keep independent decisions separate. Author attribution remains unchanged.
|
|
184
|
+
|
|
185
|
+
`before` must match the saved Base exactly. Repeated text requires a 1-based `occurrence`.
|
|
186
|
+
Blocks must be separated and must explain the entire local diff. The plan embeds the resolved
|
|
187
|
+
blocks; it never rereads or silently reinterprets the manifest during submission. Concurrent edits
|
|
188
|
+
outside blocks are preserved; any comment, pending suggestion, or concurrent edit touching a block
|
|
189
|
+
stops planning rather than silently fragmenting it. Narrow the block or resolve the conflict.
|
|
190
|
+
`--edits` requires `--file` and a saved base; it cannot be combined with `--direct` or `--unsafe-no-base`.
|
|
191
|
+
|
|
192
|
+
Without explicit blocks, tracked suggestions group nearby word edits into phrase replacements. For example, rewriting
|
|
193
|
+
“old model predicts low” as “revised model explains high” produces one deletion and one insertion,
|
|
194
|
+
instead of six separate word operations. Isolated corrections stay small. Grouping bridges at most
|
|
195
|
+
three unchanged words (40 characters), limits combined spans to 320 characters, and stops at detected
|
|
196
|
+
sentence/clause boundaries, paragraph breaks, and LaTeX markup. This is a deterministic readability
|
|
197
|
+
heuristic; it does not infer which scientific claims should be accepted together. An existing
|
|
198
|
+
multiword insertion remains a single insertion.
|
|
199
|
+
|
|
200
|
+
Unchanged comment anchors, tracked ranges, and edits made on Live since Base prevent grouping across
|
|
201
|
+
them. Overlap checks use the full grouped footprint, and submission reproduces the same grouping.
|
|
202
|
+
`--direct` retains the narrower word-level operations. Plans from before this grouping change must
|
|
203
|
+
be regenerated; submitting an old plan does not silently regroup its approved operations.
|
|
204
|
+
|
|
205
|
+
Planning and submission check a conservative range budget: existing tracked ranges plus proposed
|
|
206
|
+
insert/delete operations must not exceed 2,000 per document. The preview shows both counts.
|
|
207
|
+
Overlap transformations can alter the actual count, so this is a preflight guard rather than an
|
|
208
|
+
exact prediction. Splitting a revision into batches does not remove accumulated pending ranges.
|
|
209
|
+
Grouping applies to new pushes; it does not consolidate or accept suggestions already on Overleaf.
|
|
210
|
+
|
|
211
|
+
### Consolidation of existing suggestions
|
|
212
|
+
|
|
213
|
+
`review consolidate --doc main.tex --author <user-id> --out .overleaf/consolidation.json`
|
|
214
|
+
captures the live text, all document ranges, and project comment threads. It reconstructs the text
|
|
215
|
+
with that author's selected suggestions rejected, then plans a grouped revision back to the current
|
|
216
|
+
proposed text. By default it considers all current suggestions by that author, including older
|
|
217
|
+
fragments; repeat `--change` to select a subset. Use the author user ID from range metadata.
|
|
218
|
+
|
|
219
|
+
The artifact records both text hashes, a reverse/forward reconstruction proof, projected range
|
|
220
|
+
counts, and any comment or unselected-suggestion blockers. It preserves the *current pending
|
|
221
|
+
proposal*, not a historical review state before older suggestions were absorbed. Consolidation
|
|
222
|
+
would assign new IDs and timestamps. Counts remain projections until server transformations are
|
|
223
|
+
verified. Touching comment anchors or unselected changes blocks the candidate; these are not
|
|
224
|
+
automatically removed or accepted.
|
|
225
|
+
|
|
226
|
+
For offline analysis, use `--snapshot <file.json>` instead of `--doc`. The snapshot must contain
|
|
227
|
+
`projectId`, `docId`, `docPath`, `version`, `text`, `ranges: { changes, comments }`, and `threads`;
|
|
228
|
+
the preview embeds this complete object as `backup`. A normal review sidecar alone is insufficient.
|
|
229
|
+
|
|
230
|
+
Planning sends nothing. Inspect the complete plan, then apply it separately:
|
|
231
|
+
|
|
232
|
+
```sh
|
|
233
|
+
overleaf-review review consolidate --apply --plan .overleaf/consolidation.json
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Only suggestions owned by the authenticated account can be reapplied. Blocked/no-reduction plans
|
|
237
|
+
cannot be submitted. The command reproduces the plan from its backup and requires unchanged text,
|
|
238
|
+
document version, ranges, and project threads. It journals the full snapshot before sending undo
|
|
239
|
+
and reapply operations together in one update. It never accepts suggestions as a prerequisite.
|
|
240
|
+
|
|
241
|
+
Verification checks the proposed text, text with selected suggestions rejected, text with all
|
|
242
|
+
suggestions rejected, disappearance of old IDs, new-ID attribution, reduced range count, and
|
|
243
|
+
unchanged unselected ranges, comment anchors and thread messages. New IDs and timestamps are
|
|
244
|
+
expected. Any uncertain send or failed verification quarantines subsequent attempts: inspect the
|
|
245
|
+
receipt and live document before manually reconciling it; there is no automatic rollback/retry.
|
|
246
|
+
Reusing an already successful plan reports its receipt without sending it again.
|
|
247
|
+
|
|
248
|
+
Coordinate a quiet editing window for consolidation. Overleaf has no conditional transaction
|
|
249
|
+
covering text, ranges and threads, so preflight cannot prevent every last-moment collaborator race;
|
|
250
|
+
readback detects discrepancies but cannot make an already-sent operation un-happen. A backup is
|
|
251
|
+
recovery evidence, not a promise of automatic review-history restoration.
|
|
252
|
+
|
|
253
|
+
Development check `npm run probe:consolidation-model` exercises pinned upstream range logic in
|
|
254
|
+
memory without accessing an Overleaf project. The opt-in `npm run probe:review-live -- --project
|
|
255
|
+
<id> --confirm-test-project` creates and retains a new scratch document in the specified test
|
|
256
|
+
project, verifies consolidation and protected review state, and checks that existing documents
|
|
257
|
+
were unchanged. It does not require or spoof another account. Foreign-author preservation is also
|
|
258
|
+
covered by the upstream model check. Never run this probe against a manuscript project.
|
|
259
|
+
|
|
260
|
+
### Push overrides and submission
|
|
261
|
+
|
|
262
|
+
Use `--allow-overlap` only after inspecting those tracked changes. `--unsafe-no-base` is a deliberate
|
|
263
|
+
legacy escape hatch that treats the current Live document as Base; it loses the protection against
|
|
264
|
+
co-author edits made since your local file was obtained. `--direct` changes how the validated ops
|
|
265
|
+
are represented in Overleaf, not the merge and conflict checks.
|
|
266
|
+
|
|
267
|
+
For a separate approval step, `review plan --out plan.json` stores the full operation list and its
|
|
268
|
+
preconditions, active tracked ranges, and any comment overlaps. `review submit --plan plan.json`
|
|
269
|
+
re-derives the plan from Base/Local/Live and aborts if preflight finds that the project, local source,
|
|
270
|
+
synchronization base, live document version/content, or active review ranges changed. Plans contain
|
|
271
|
+
manuscript fragments, so store or commit them with the same care as the source itself. `push
|
|
272
|
+
--plan-out <path>` and `push --plan <path>` expose the same workflow through the one-level command.
|
|
273
|
+
|
|
274
|
+
Overleaf can transform an update that races with a collaborator after the final preflight. The tool
|
|
275
|
+
therefore reads every result back and fails rather than claiming success when the exact planned text
|
|
276
|
+
is not present. A multi-file submission is not transactional; if a later file fails, its receipt
|
|
277
|
+
identifies every earlier file already verified on Overleaf.
|
|
278
|
+
|
|
279
|
+
Pushes, accept/reject actions, comments, and replies write audit receipts beneath
|
|
280
|
+
`.overleaf/receipts/`. Keep an ambiguous receipt: it means the request may have reached Overleaf but
|
|
281
|
+
readback could not prove the result, so inspect the live project before retrying. For comments and
|
|
282
|
+
replies, an identical recent message is treated as a retry and skipped; pass `--force` only when a
|
|
283
|
+
second identical message is intentional.
|
|
284
|
+
|
|
285
|
+
An ambiguous push quarantines its affected documents even if a newly generated plan has a different
|
|
286
|
+
timestamp or tracked-change seed. After waiting for delayed updates and manually reconciling the
|
|
287
|
+
receipt against live Overleaf, `--acknowledge-ambiguous` explicitly clears that submission-time
|
|
288
|
+
guard; it should never be used as an automatic retry flag.
|
|
289
|
+
|
|
290
|
+
Mutating commands are serialized by a working-tree-specific lock in the system temporary directory,
|
|
291
|
+
preventing two local agents from racing through the same preflight. A normal exit removes the lock.
|
|
292
|
+
If a process crashes and leaves it behind, the next command prints its exact path; inspect any
|
|
293
|
+
relevant receipt and the live Overleaf document before removing it manually.
|
|
294
|
+
|
|
116
295
|
## 🧠 How it works
|
|
117
296
|
|
|
118
297
|
overleaf.com's editor speaks an old **socket.io 0.9** protocol over a WebSocket. The client
|
|
@@ -122,8 +301,12 @@ overleaf.com's editor speaks an old **socket.io 0.9** protocol over a WebSocket.
|
|
|
122
301
|
- a **tracked change** is an insert/delete op with a `meta.tc` flag;
|
|
123
302
|
- a **comment** is a `c` op plus a REST post of the message text.
|
|
124
303
|
|
|
125
|
-
`push`
|
|
126
|
-
sequential OT ops,
|
|
304
|
+
`push` performs the Base/Local/Live merge described above, translates Live→merged text into
|
|
305
|
+
sequential OT ops, and waits for Overleaf's applied-update event. It then reads the document back
|
|
306
|
+
and verifies the final text—and, in suggestion mode, tracked-change ids—before updating the saved
|
|
307
|
+
base. Accept and reject operations verify that the requested ids disappeared; rejection also
|
|
308
|
+
verifies the exact planned text. Push, accept/reject, comment, and reply fail loudly when their
|
|
309
|
+
readback cannot prove success.
|
|
127
310
|
|
|
128
311
|
## ⚠️ Disclaimer
|
|
129
312
|
|