overleaf-review 0.4.0 → 0.6.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 CHANGED
@@ -128,8 +128,10 @@ first safe push. If an upgraded repository already has unpushed edits, copy or s
128
128
  | `pull [--out <dir>]` | Read comments + tracked changes into a sidecar |
129
129
  | `fetch [--file <f>] [--dry-run]` | Write Overleaf text locally, snapshot replaced files, and save Base (read-only on Overleaf) |
130
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>] [--doc <name>] [--direct] [--allow-overlap] [--unsafe-no-base]` | Create a complete binding plan without changing Overleaf |
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
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 |
133
135
  | `upload <path…> [--folder <name>]` | Upload figures / new files into Overleaf |
134
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`) |
135
137
  | `comment --anchor <text> --message <text> [--doc <name>] [--nth <n>] [--force]` | Add an anchored comment; recent identical retries are skipped unless forced |
@@ -155,6 +157,183 @@ overlapping Base→Local and Base→Live edits abort instead of silently undoing
155
157
  work. A proposed edit that intersects an active tracked-change range is also blocked by default and
156
158
  the relevant change ids are listed.
157
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 ordinary block planning rather than silently fragmenting it. For deliberately reviewed
190
+ overlaps, use the manifest fields below; otherwise narrow the block or resolve the conflict.
191
+ `--edits` requires `--file` and a saved base; it cannot be combined with `--direct` or `--unsafe-no-base`.
192
+
193
+ Without explicit blocks, tracked suggestions group nearby word edits into phrase replacements. For example, rewriting
194
+ “old model predicts low” as “revised model explains high” produces one deletion and one insertion,
195
+ instead of six separate word operations. Isolated corrections stay small. Grouping bridges at most
196
+ three unchanged words (40 characters), limits combined spans to 320 characters, and stops at detected
197
+ sentence/clause boundaries, paragraph breaks, and LaTeX markup. This is a deterministic readability
198
+ heuristic; it does not infer which scientific claims should be accepted together. An existing
199
+ multiword insertion remains a single insertion.
200
+
201
+ Unchanged comment anchors, tracked ranges, and edits made on Live since Base prevent grouping across
202
+ them. Overlap checks use the full grouped footprint, and submission reproduces the same grouping.
203
+ `--direct` retains the narrower word-level operations. Plans from before this grouping change must
204
+ be regenerated; submitting an old plan does not silently regroup its approved operations.
205
+
206
+ Planning and submission check a conservative range budget: existing tracked ranges plus proposed
207
+ insert/delete operations must not exceed 2,000 per document. The preview shows both counts.
208
+ Overlap transformations can alter the actual count, so this is a preflight guard rather than an
209
+ exact prediction. Splitting a revision into batches does not remove accumulated pending ranges.
210
+ Grouping applies to new pushes; it does not consolidate or accept suggestions already on Overleaf.
211
+
212
+ ### Holistic paragraph rewrites over reviewed suggestions and comments
213
+
214
+ Use this when a paragraph rewrite intentionally incorporates or supersedes existing suggestions.
215
+ It differs from consolidation: the proposed text may change, and selected older suggestion cards
216
+ are replaced by a new pending revision under the authenticated account.
217
+
218
+ Fetch the current text/review state, edit the local file, and extend the normal block manifest:
219
+
220
+ ```json
221
+ {
222
+ "replacements": [
223
+ {
224
+ "before": "The current paragraph, including pending suggestions.",
225
+ "after": "The coherently rewritten paragraph. Its explanation incorporates the correction.",
226
+ "supersedes": ["existing-change-id-1", "existing-change-id-2"],
227
+ "reason": "Incorporates the correction into a more coherent explanation.",
228
+ "comments": [
229
+ {
230
+ "thread": "existing-thread-id",
231
+ "anchorAfter": "Its explanation incorporates the correction.",
232
+ "reply": "Rewritten to incorporate your correction and clarify the explanation."
233
+ }
234
+ ]
235
+ }
236
+ ]
237
+ }
238
+ ```
239
+
240
+ ```sh
241
+ overleaf-review review plan --file main.tex --edits blocks.json --out reviewed-plan.json
242
+ overleaf-review review submit --plan reviewed-plan.json
243
+ ```
244
+
245
+ The `supersedes`, `comments`, or `reason` fields select reviewed-overlap planning automatically.
246
+ Every block needs a paragraph-level `reason`. Omit `supersedes`/`comments` or use empty arrays
247
+ when that block has no corresponding overlaps. `reply` is optional. Use `occurrence` in a comment
248
+ mapping when `anchorAfter` occurs more than once in the revised block. To highlight the entire
249
+ revised paragraph, set `anchorAfter` equal to `after`.
250
+
251
+ The tool lists unapproved overlapping IDs and threads. All fragments of each selected suggestion
252
+ and the full affected comment anchor must be contained in its approved block; it will not silently
253
+ expand the scope. Suggestions from other authors may be explicitly superseded. Their original
254
+ content and attribution are retained in the full plan/receipt, not falsely attributed to the new
255
+ revision. Existing thread IDs, messages, author metadata, and resolution state are preserved;
256
+ only approved anchors move. Suggestions and comments outside the blocks retain their identities
257
+ and content, with positions shifted as needed.
258
+
259
+ The plan shows **underlying**, **current**, and **proposed** text for each block. The underlying
260
+ text excludes the selected pending suggestions. Submission undoes those ranges and writes the
261
+ new whole-block revision, then reanchors the existing threads in the same OT update. It does
262
+ not accept older suggestions first. Rejecting the new revision restores that underlying text;
263
+ it does not recreate the old suggestion cards. Later manual review uses Overleaf's native anchor
264
+ behavior; this command is not a background service that restores anchors after future rejections.
265
+
266
+ Reviewed rewrites require a saved plan and synchronization base, use a separate plan kind, and
267
+ cannot be forced with `--allow-overlap`, `--direct`, `--unsafe-no-base` or `--acknowledge-ambiguous`.
268
+ Any unapproved overlap, changed local intent, or changed document/review state before submission
269
+ blocks the write. Coordinate a quiet editing window: the server does not provide a conditional
270
+ transaction spanning text, ranges and threads, and post-write verification is not a rollback.
271
+
272
+ Replies are posted only after the manuscript, anchors, range identities, author attribution and
273
+ rejection baseline have been verified. A receipt separately tracks text verification and each
274
+ reply. If a definite reply failure leaves follow-up pending, resubmitting the same plan resumes
275
+ without rewriting the manuscript. A lost reply acknowledgement can be reconciled from its new
276
+ message ID or an unambiguous new same-author message; without proof it remains quarantined and
277
+ is not automatically reposted. An uncertain text update always requires manual reconciliation.
278
+ Keep the plan and receipts when resuming; do not use a fresh plan to bypass an uncertain attempt.
279
+
280
+ Verification: `npm run probe:reviewed-model` covers other-author suggestions and existing-thread
281
+ reanchoring against pinned upstream range logic. The opt-in
282
+ `npm run probe:reviewed-live -- --project <test-id> --confirm-test-project` creates a new scratch
283
+ document and threads, verifies anchor movement, a reviewed rewrite, explanatory reply and retry,
284
+ and checks existing documents were unchanged. It does not impersonate another account.
285
+
286
+ ### Consolidation of existing suggestions
287
+
288
+ `review consolidate --doc main.tex --author <user-id> --out .overleaf/consolidation.json`
289
+ captures the live text, all document ranges, and project comment threads. It reconstructs the text
290
+ with that author's selected suggestions rejected, then plans a grouped revision back to the current
291
+ proposed text. By default it considers all current suggestions by that author, including older
292
+ fragments; repeat `--change` to select a subset. Use the author user ID from range metadata.
293
+
294
+ The artifact records both text hashes, a reverse/forward reconstruction proof, projected range
295
+ counts, and any comment or unselected-suggestion blockers. It preserves the *current pending
296
+ proposal*, not a historical review state before older suggestions were absorbed. Consolidation
297
+ would assign new IDs and timestamps. Counts remain projections until server transformations are
298
+ verified. Touching comment anchors or unselected changes blocks the candidate; these are not
299
+ automatically removed or accepted.
300
+
301
+ For offline analysis, use `--snapshot <file.json>` instead of `--doc`. The snapshot must contain
302
+ `projectId`, `docId`, `docPath`, `version`, `text`, `ranges: { changes, comments }`, and `threads`;
303
+ the preview embeds this complete object as `backup`. A normal review sidecar alone is insufficient.
304
+
305
+ Planning sends nothing. Inspect the complete plan, then apply it separately:
306
+
307
+ ```sh
308
+ overleaf-review review consolidate --apply --plan .overleaf/consolidation.json
309
+ ```
310
+
311
+ Only suggestions owned by the authenticated account can be reapplied. Blocked/no-reduction plans
312
+ cannot be submitted. The command reproduces the plan from its backup and requires unchanged text,
313
+ document version, ranges, and project threads. It journals the full snapshot before sending undo
314
+ and reapply operations together in one update. It never accepts suggestions as a prerequisite.
315
+
316
+ Verification checks the proposed text, text with selected suggestions rejected, text with all
317
+ suggestions rejected, disappearance of old IDs, new-ID attribution, reduced range count, and
318
+ unchanged unselected ranges, comment anchors and thread messages. New IDs and timestamps are
319
+ expected. Any uncertain send or failed verification quarantines subsequent attempts: inspect the
320
+ receipt and live document before manually reconciling it; there is no automatic rollback/retry.
321
+ Reusing an already successful plan reports its receipt without sending it again.
322
+
323
+ Coordinate a quiet editing window for consolidation. Overleaf has no conditional transaction
324
+ covering text, ranges and threads, so preflight cannot prevent every last-moment collaborator race;
325
+ readback detects discrepancies but cannot make an already-sent operation un-happen. A backup is
326
+ recovery evidence, not a promise of automatic review-history restoration.
327
+
328
+ Development check `npm run probe:consolidation-model` exercises pinned upstream range logic in
329
+ memory without accessing an Overleaf project. The opt-in `npm run probe:review-live -- --project
330
+ <id> --confirm-test-project` creates and retains a new scratch document in the specified test
331
+ project, verifies consolidation and protected review state, and checks that existing documents
332
+ were unchanged. It does not require or spoof another account. Foreign-author preservation is also
333
+ covered by the upstream model check. Never run this probe against a manuscript project.
334
+
335
+ ### Push overrides and submission
336
+
158
337
  Use `--allow-overlap` only after inspecting those tracked changes. `--unsafe-no-base` is a deliberate
159
338
  legacy escape hatch that treats the current Live document as Base; it loses the protection against
160
339
  co-author edits made since your local file was obtained. `--direct` changes how the validated ops