revise-and-resubmit-cc 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +208 -0
  2. package/bin/install.js +43 -0
  3. package/bin/rnr-tools.js +184 -0
  4. package/bin/update.js +45 -0
  5. package/commands/rnr/assemble.md +24 -0
  6. package/commands/rnr/extract-comments.md +27 -0
  7. package/commands/rnr/help.md +20 -0
  8. package/commands/rnr/init.md +24 -0
  9. package/commands/rnr/process-comments.md +41 -0
  10. package/commands/rnr/synthesize-style.md +25 -0
  11. package/commands/rnr/update.md +16 -0
  12. package/package.json +30 -0
  13. package/src/__pycache__/assembler.cpython-311.pyc +0 -0
  14. package/src/__pycache__/orchestrator.cpython-311.pyc +0 -0
  15. package/src/__pycache__/parser.cpython-311.pyc +0 -0
  16. package/src/anthropic_docx_scripts/__init__.py +1 -0
  17. package/src/anthropic_docx_scripts/accept_changes.py +135 -0
  18. package/src/anthropic_docx_scripts/comment.py +318 -0
  19. package/src/anthropic_docx_scripts/office/helpers/__init__.py +0 -0
  20. package/src/anthropic_docx_scripts/office/helpers/merge_runs.py +199 -0
  21. package/src/anthropic_docx_scripts/office/helpers/simplify_redlines.py +197 -0
  22. package/src/anthropic_docx_scripts/office/pack.py +159 -0
  23. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  24. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  25. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  26. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  27. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  28. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  29. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  30. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  31. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  32. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  33. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  34. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  35. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  36. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  37. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  38. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  39. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  40. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  41. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  42. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  43. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  44. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  45. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  46. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  47. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  48. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  49. package/src/anthropic_docx_scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  50. package/src/anthropic_docx_scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  51. package/src/anthropic_docx_scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  52. package/src/anthropic_docx_scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  53. package/src/anthropic_docx_scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  54. package/src/anthropic_docx_scripts/office/schemas/mce/mc.xsd +75 -0
  55. package/src/anthropic_docx_scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
  56. package/src/anthropic_docx_scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
  57. package/src/anthropic_docx_scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
  58. package/src/anthropic_docx_scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
  59. package/src/anthropic_docx_scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
  60. package/src/anthropic_docx_scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  61. package/src/anthropic_docx_scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
  62. package/src/anthropic_docx_scripts/office/soffice.py +183 -0
  63. package/src/anthropic_docx_scripts/office/unpack.py +132 -0
  64. package/src/anthropic_docx_scripts/office/validate.py +111 -0
  65. package/src/anthropic_docx_scripts/office/validators/__init__.py +15 -0
  66. package/src/anthropic_docx_scripts/office/validators/base.py +847 -0
  67. package/src/anthropic_docx_scripts/office/validators/docx.py +446 -0
  68. package/src/anthropic_docx_scripts/office/validators/pptx.py +275 -0
  69. package/src/anthropic_docx_scripts/office/validators/redlining.py +247 -0
  70. package/src/anthropic_docx_scripts/templates/comments.xml +3 -0
  71. package/src/anthropic_docx_scripts/templates/commentsExtended.xml +3 -0
  72. package/src/anthropic_docx_scripts/templates/commentsExtensible.xml +3 -0
  73. package/src/anthropic_docx_scripts/templates/commentsIds.xml +3 -0
  74. package/src/anthropic_docx_scripts/templates/people.xml +3 -0
  75. package/src/assembler.py +114 -0
  76. package/src/parser.py +155 -0
package/README.md ADDED
@@ -0,0 +1,208 @@
1
+ <div align="center">
2
+
3
+ # REVISE & RESUBMIT (R&R)
4
+
5
+ **A light-weight and powerful meta-prompting and context engineering system for automating academic revisions directly inside Claude Code.**
6
+
7
+ **Solves formatting rot — the style degradation and context loss that happens when LLMs edit complex academic documents.**
8
+
9
+ [![npm version](https://img.shields.io/npm/v/revise-and-resubmit-cc?style=for-the-badge&logo=npm&logoColor=white&color=CB3837)](#)
10
+ [![License](https://img.shields.io/badge/license-MIT-blue?style=for-the-badge)](LICENSE)
11
+
12
+ <br>
13
+
14
+ ```bash
15
+ node bin/install.js --claude --local
16
+ ```
17
+
18
+ **Works on Mac, Windows, and Linux.**
19
+
20
+ <br>
21
+
22
+ # Revise & Resubmit (R&R) Framework
23
+ *An automated, agent-based academic revision ecosystem powered by Claude Code.*
24
+
25
+ ## What is R&R?
26
+ When you submit an academic paper, peer reviewers often send back a Microsoft Word `.docx` file filled with dozens (or hundreds) of comments and edit suggestions.
27
+
28
+ Manually going through every comment, finding the context, researching the change, negotiating with the reviewer, and rewriting the text can take weeks.
29
+
30
+ **Revise & Resubmit (R&R)** is a custom `get-shit-done` style framework for Claude Code that automates this entire process. You simply point R&R at the `.docx` file, and a specialized team of AI "subagents" will extract the comments, edit the manuscript based on your personal writing style, research external data if needed, ask you clarifying questions, and quickly repack a finished `.docx` file ready for submission.
31
+
32
+ ---
33
+
34
+ ## How It Works: The Subagent Ecosystem (In Layman's Terms)
35
+
36
+ R&R doesn't just use one massive AI that tries to do everything at once (which usually leads to the AI getting confused, skipping comments, or making things up).
37
+
38
+ Instead, it relies on a **Subagent Ecosystem**—a highly specialized team of mini-AIs where each agent has exactly one precise job.
39
+
40
+ Here is the assembly line:
41
+
42
+ ### 1. The Extractors & Assemblers
43
+ * **The Extractor:** When you run `/rnr:extract-comments`, R&R spawns a specialized python-runner agent. Its only job is to silently open your `.docx`, find every single Reviewer comment and Edit Suggestion, extract the exact paragraph they attached it to, and save them as individual files (e.g., `COMMENT_1.md`, `COMMENT_2.md`).
44
+ * **The Assembler:** At the very end, when you run `/rnr:assemble`, a new dedicated agent takes all the revised paragraphs and perfectly injects them back into a clean, formatted `.docx` file without messing up your citations or graphs.
45
+
46
+ ### 2. The Processors (The Heavy Lifters)
47
+ When you tell R&R to get to work (`/rnr:process-comments`), it looks at the extracted files and sorts them:
48
+ * **Isolated Comments:** Typos or localized changes that don't affect anything else. R&R spawns one **Fresh Processor Agent** for *each* isolated comment simultaneously.
49
+ * **Interlaced Comments:** If a reviewer says "move this here" in comment 4, and "delete this" in comment 5, R&R groups them. It assigns one **Dedicated Processor Agent** to handle that specific group together so the edits make sense.
50
+
51
+ *Crucially, Processor Agents do NOT talk to you, and they do NOT search the internet. They only look at the comment, look at your style guide, and rewrite the text.*
52
+
53
+ ### 3. The Delegates (The Specialists)
54
+ If a Processor Agent encounters a problem it can't solve by just rewriting text, it asks for help from the specialists:
55
+ * **The Researcher:** If the reviewer asks "Can you add a citation for this claim?", the Processor stops and spawns a **Researcher Agent**. The Researcher silently connects to your Google NotebookLM (containing all your PDFs and research), finds the exact answer, and hands it back to the Processor to write the revision.
56
+ * **The Clarifier:** If the reviewer leaves a vague comment like "I don't like this," the Processor stops and spawns a **Clarifier Agent**. The Clarifier will pop up in your terminal, explain the ambiguity, and chat with you to figure out what you want to do. Once you decide, the Clarifier hands your instruction back to the Processor to execute the edit.
57
+
58
+ ---
59
+
60
+ ## Getting Started
61
+
62
+ ### Prerequisites
63
+ 1. You must have **Claude Code** installed.
64
+ 2. Your terminal must be running in the folder where your manuscript `.docx` is located.
65
+ 3. *(Highly Recommended)* Install the NotebookLM MCP tool so R&R can do automated research:
66
+ `claude mcp add notebooklm notebooklm-mcp-cli`
67
+
68
+ ### Installation
69
+ Clone this repository to your machine. Then, in your terminal, run:
70
+ ```bash
71
+ node /path/to/rnr/bin/install.js
72
+ ```
73
+ This registers the R&R commands with Claude Code.
74
+
75
+ ### Step 1: Initialize the Project
76
+ Navigate to the directory containing your `.docx` manuscript and run:
77
+ ```bash
78
+ /rnr:init
79
+ ```
80
+ This sets up the hidden environment (`.rnr/`) that allows the Subagents to run perfectly isolated scripts. It will also ask you to link a specific NotebookLM notebook so the **Researcher Agents** know where to look.
81
+
82
+ ### Step 2: Extract the Comments
83
+ Extract the reviewer comments and map them to the document:
84
+ ```bash
85
+ /rnr:extract-comments manuscript.docx "Reviewer 1"
86
+ ```
87
+
88
+ ### Step 3: Define Your Style
89
+ Ensure the AI edits sound exactly like you:
90
+ ```bash
91
+ /rnr:synthesize-style
92
+ ```
93
+ This crawls your manuscript to map your tone, vocabulary, and sentence structures.
94
+
95
+ ### Step 4: Unleash the Ecosystem
96
+ Start the automated revision factory:
97
+ ```bash
98
+ /rnr:process-comments
99
+ ```
100
+ Grab a coffee. The subagents will negotiate, research, and edit every comment asynchronously. If they need you, the **Clarifier** will ping you in the terminal.
101
+
102
+ ### Step 5: Assemble the Final Document
103
+ Once processing is complete, repack the manuscript:
104
+ ```bash
105
+ /rnr:assemble final_manuscript.docx
106
+ ```
107
+ Your paper is now ready to resubmit!
108
+
109
+ ---
110
+
111
+ ### 5. Assemble Final Document
112
+
113
+ ```
114
+ /rnr:assemble output_revised.docx
115
+ ```
116
+
117
+ The system:
118
+
119
+ 1. **Validates** — Ensures all XML nodes are closed.
120
+ 2. **Injects** — Adds the drafted "Response to Reviewers" as nested comments in the document.
121
+ 3. **Packs** — Flawlessly recompiles the `.docx`.
122
+
123
+ Walk away, come back to a completed revision.
124
+
125
+ ---
126
+
127
+ ## Why It Works
128
+
129
+ ### Lean Orchestration (Zero Context Bleeding)
130
+ A major problem with using LLMs for full document revision is "Context Rot." If the AI reads a 50-page document and 100 comments, it will start forgetting instructions, ignoring style guides, and hallucinating facts simply because its token window is exhausted.
131
+
132
+ R&R solves this with **Lean Orchestration**:
133
+ 1. **The Orchestrator is Blind:** The main AI running the `/rnr:process-comments` command is strictly forbidden from reading your manuscript or your style guide. It only coordinates the workflow. This guarantees the orchestrator never runs out of tokens and never requires you to type `/clear`.
134
+ 2. **Subagents read files natively:** When the orchestrator spawns a subagent to fix a comment, it uses a native `<files_to_read>` block to pass the *paths* to the required files (e.g., `style_skill.md`, `COMMENT_12.md`).
135
+ 3. **Fresh Context:** That subagent boots up with a completely fresh, empty context window. It uses its built-in read tools to ingest the exact style rules and the exact paragraph it needs to fix.
136
+
137
+ This strict separation guarantees that every single comment receives 100% of Claude's analytical focus, with zero context degradation, no matter how many comments your document has.
138
+
139
+ ### XML Prompt Formatting
140
+
141
+ Every agent is structured XML optimized for Claude:
142
+
143
+ ```xml
144
+ <classification type="needs_context">
145
+ <reasoning>The reviewer asks us to cite the 2023 review by Johnson et al. We need human input.</reasoning>
146
+ <prompt_for_human>Please provide the full citation and a brief summary for Johnson et al. 2023.</prompt_for_human>
147
+ </classification>
148
+ ```
149
+
150
+ Precise instructions. No guessing.
151
+
152
+ ### Dedicated Python Tools
153
+
154
+ R&R hooks directly into Anthropic's validated `unpack.py` and `pack.py` python toolkit via `/bash`. This is how it guarantees it will not destroy your page margins or tables when modifying the `.docx` text.
155
+
156
+ ---
157
+
158
+ ## Commands
159
+
160
+ ### Core Workflow
161
+
162
+ | Command | What it does |
163
+ |---------|--------------|
164
+ | `/rnr:init` | Installs the parser and assembler scripts to a `.rnr/` folder in the current directory |
165
+ | `/rnr:extract-comments <file>` | Unpacks the `.docx` into XML and extracts Reviewer 1/2 comments |
166
+ | `/rnr:synthesize-style` | Constructs `style_skill.md` from your writing |
167
+ | `/rnr:process-comments` | Iterates through each comment, prompting for human context when needed |
168
+ | `/rnr:assemble <output>` | Repacks XML into a fully valid, formatted `.docx` |
169
+
170
+ ### Utilities
171
+
172
+ | Command | What it does |
173
+ |---------|--------------|
174
+ | `/rnr:help` | Show all commands and usage guide |
175
+ | `/rnr:update` | Updates the framework and scripts to the latest version via `git pull` |
176
+
177
+ ### Updating from Version 1
178
+
179
+ If you installed the framework before the `/rnr:update` command existed, you must manually fetch the new updates once to activate the auto-updater. Simply run:
180
+
181
+ ```bash
182
+ cd rnr
183
+ git pull origin main
184
+ node bin/install.js --claude --global
185
+ ```
186
+ You can now use `/rnr:update` inside Claude Code going forward.
187
+
188
+ ---
189
+
190
+ ## Security
191
+
192
+ ### Protecting Your Manuscript
193
+
194
+ Since R&R is entirely open source and relies strictly on your local Anthropic API and Claude Code environment, your manuscript is never uploaded to third-party databases (like ChatGPT's training pipeline) beyond the standard Anthropic backend.
195
+
196
+ ---
197
+
198
+ ## License
199
+
200
+ MIT License. See [LICENSE](LICENSE) for details.
201
+
202
+ ---
203
+
204
+ <div align="center">
205
+
206
+ **Claude Code is powerful. R&R makes it academic.**
207
+
208
+ </div>
package/bin/install.js ADDED
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { execSync } = require('child_process');
6
+
7
+ const args = process.argv.slice(2);
8
+ const isGlobal = args.includes('--global') || args.includes('-g');
9
+
10
+ const CLAUDE_DIR = isGlobal
11
+ ? path.join(require('os').homedir(), '.claude')
12
+ : path.join(process.cwd(), '.claude');
13
+
14
+ const COMMANDS_SRC = path.join(__dirname, '..', 'commands', 'rnr');
15
+ const COMMANDS_DEST = path.join(CLAUDE_DIR, 'commands', 'rnr');
16
+
17
+ console.log('Installing Revise & Resubmit (R&R) Framework for Claude Code...');
18
+
19
+ try {
20
+ // Ensure destination exists
21
+ fs.mkdirSync(COMMANDS_DEST, { recursive: true });
22
+
23
+ // Copy command files
24
+ const files = fs.readdirSync(COMMANDS_SRC);
25
+ files.forEach(file => {
26
+ if (file.endsWith('.md')) {
27
+ fs.copyFileSync(
28
+ path.join(COMMANDS_SRC, file),
29
+ path.join(COMMANDS_DEST, file)
30
+ );
31
+ console.log(`✓ Installed command: /rnr:${file.replace('.md', '')}`);
32
+ }
33
+ });
34
+
35
+ console.log('\nSuccess! R&R Framework installed.');
36
+ console.log(`Commands were installed to: ${COMMANDS_DEST}`);
37
+ console.log('\nTo use, open Claude Code and run:');
38
+ console.log(' /rnr:help');
39
+
40
+ } catch (err) {
41
+ console.error('\nInstallation failed:', err.message);
42
+ process.exit(1);
43
+ }
@@ -0,0 +1,184 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const command = process.argv[2];
7
+
8
+ if (command === 'get-grouped-comments') {
9
+ const mapPath = path.join(process.cwd(), 'data', 'document_map.json');
10
+ if (!fs.existsSync(mapPath)) {
11
+ console.error('Document map not found.');
12
+ process.exit(1);
13
+ }
14
+
15
+ const comments = JSON.parse(fs.readFileSync(mapPath, 'utf8'));
16
+
17
+ // Very naive grouping for demonstration - in reality this would be better defined
18
+ // For the sake of matching the user's issue, we will just randomly group them
19
+ // into interlaced and isolated for testing purposes.
20
+ // In a robust implementation, the user/agent would have defined these groupings prior.
21
+
22
+ const isolated = [];
23
+ const interlacedGroups = [];
24
+
25
+ // Example grouping logic based on proximity or target text overlap
26
+ // Since we don't have the full text, we will just simulate finding groups
27
+ // by grouping comments from the same author that are adjacent in ID, or just
28
+ // pass them back for the agent to classify.
29
+
30
+ // A better approach for the script: Let the agent classify them FIRST, save to a file,
31
+ // then the script reads the classification and outputs the subagent spawning instructions.
32
+
33
+ const classificationPath = path.join(process.cwd(), 'data', 'classification.json');
34
+ if (fs.existsSync(classificationPath)) {
35
+ const classifications = JSON.parse(fs.readFileSync(classificationPath, 'utf8'));
36
+ console.log(JSON.stringify(classifications, null, 2));
37
+ } else {
38
+ console.error('Classification file not found. Please run the classification phase first.');
39
+ process.exit(1);
40
+ }
41
+ }
42
+
43
+ if (command === 'generate-extract-task') {
44
+ const targetFile = process.argv[3];
45
+ const reviewer = process.argv[4] ? ` --reviewer "${process.argv[4]}"` : '';
46
+
47
+ if (!targetFile) {
48
+ console.error('Missing target file for extraction.');
49
+ process.exit(1);
50
+ }
51
+
52
+ console.log(`Task(
53
+ subagent_type="rnr-extractor",
54
+ model="claude-3-haiku-20240307",
55
+ prompt="Execute the comment extraction tool. Run this exact bash command: \\"python .rnr/src/parser.py ${targetFile}${reviewer}\\". Report the output back to me."
56
+ )`);
57
+ process.exit(0);
58
+ }
59
+
60
+ if (command === 'generate-assemble-task') {
61
+ const originalFile = process.argv[3];
62
+ const outputFile = process.argv[4] || 'output.docx';
63
+
64
+ if (!originalFile) {
65
+ console.error('Missing original file path for assembly.');
66
+ process.exit(1);
67
+ }
68
+
69
+ console.log(`Task(
70
+ subagent_type="rnr-assembler",
71
+ model="claude-3-haiku-20240307",
72
+ prompt="Execute the document assembly tool. Run this exact bash command: \\"python .rnr/src/assembler.py ${originalFile} ${outputFile}\\". Report the outcome."
73
+ )`);
74
+ process.exit(0);
75
+ }
76
+
77
+ if (command === 'generate-prompts') {
78
+ // Generate the exact XML strings that the agent needs to execute as Tasks
79
+ const classificationPath = path.join(process.cwd(), 'data', 'classification.json');
80
+ if (!fs.existsSync(classificationPath)) {
81
+ console.error('Classification file not found.');
82
+ process.exit(1);
83
+ }
84
+
85
+ const configPath = path.join(process.cwd(), '.rnr', 'config.json');
86
+ let notebookId = 'none';
87
+ if (fs.existsSync(configPath)) {
88
+ try {
89
+ notebookId = JSON.parse(fs.readFileSync(configPath, 'utf8')).notebook_id || 'none';
90
+ } catch (e) { }
91
+ }
92
+
93
+ const classifications = JSON.parse(fs.readFileSync(classificationPath, 'utf8'));
94
+
95
+ console.log(`\n### Generated Execution Tasks ###\n`);
96
+ console.log(`Copy and execute these tasks. Wait for one wave to finish before starting the next.\n`);
97
+
98
+ // Wave 1: Isolated
99
+ if (classifications.isolated && classifications.isolated.length > 0) {
100
+ console.log(`\n#### Wave 1: Isolated Comments ####\n`);
101
+ classifications.isolated.forEach(id => {
102
+ const resolvedPath = path.join(process.cwd(), 'data', `COMMENT_${id}_RESOLVED.md`);
103
+ if (fs.existsSync(resolvedPath)) {
104
+ console.log(`// COMMENT_${id} already resolved. Skipping.`);
105
+ return;
106
+ }
107
+
108
+ console.log(`Task(
109
+ subagent_type="rnr-processor-isolated",
110
+ model="claude-3-7-sonnet-20250219",
111
+ prompt="
112
+ <objective>
113
+ Resolve the isolated comment. You must adhere strictly to the author's conventions in skills/style_skill.md.
114
+ </objective>
115
+
116
+ <files_to_read>
117
+ Read these files at execution start using the Read tool:
118
+ - skills/style_skill.md
119
+ - data/COMMENT_${id}.md
120
+ </files_to_read>
121
+
122
+ <rules>
123
+ 1. DO NOT use NotebookLM or ask the user questions directly. If you need external research context, you MUST spawn this exact subagent to get it: Task(subagent_type=\\"rnr-researcher\\", prompt=\\"Query notebook ${notebookId} for: [Your concise question]\\")
124
+ 2. If the comment is vague or explicitly non-actionable as-is, you MUST spawn this exact subagent to negotiate it: Task(subagent_type=\\"rnr-clarifier\\", prompt=\\"Present this ambiguity to the user and ask how they want to proceed: [The context]\\"). Wait for its return string.
125
+ 3. Draft the exact revised text block that will replace the original text in the document. You MUST execute the revision yourself. Do NOT output manual instructions to the user.
126
+ 4. Draft a strict, swift revision note (1 sentence maximum) replying to the reviewer stating what was done.
127
+ 5. Save your output to data/COMMENT_${id}_RESOLVED.md using strictly this XML format:
128
+ <revised_text>
129
+ [The exact revised text block]
130
+ </revised_text>
131
+ <reviewer_reply>
132
+ [The drafted reply]
133
+ </reviewer_reply>
134
+ </rules>
135
+ "
136
+ )`);
137
+ });
138
+ }
139
+
140
+ // Wave 2: Interlaced Groups
141
+ if (classifications.interlaced && classifications.interlaced.length > 0) {
142
+ console.log(`\n#### Wave 2: Interlaced Groups ####\n`);
143
+ classifications.interlaced.forEach((group, index) => {
144
+ // Check if all are resolved
145
+ const allResolved = group.every(id => fs.existsSync(path.join(process.cwd(), 'data', `COMMENT_${id}_RESOLVED.md`)));
146
+ if (allResolved) {
147
+ console.log(`// Group ${index} already resolved. Skipping.`);
148
+ return;
149
+ }
150
+
151
+ const filesList = group.map(id => `- data/COMMENT_${id}.md`).join('\\n ');
152
+
153
+ console.log(`Task(
154
+ subagent_type="rnr-processor-interlaced",
155
+ model="claude-3-7-sonnet-20250219",
156
+ prompt="
157
+ <objective>
158
+ Resolve the following related comments together to ensure consistency. You must adhere strictly to skills/style_skill.md.
159
+ </objective>
160
+
161
+ <files_to_read>
162
+ Read these files at execution start using the Read tool:
163
+ - skills/style_skill.md
164
+ ${filesList}
165
+ </files_to_read>
166
+
167
+ <rules>
168
+ 1. DO NOT use NotebookLM or ask the user questions directly. If you need external research context, you MUST spawn this exact subagent to get it: Task(subagent_type=\\"rnr-researcher\\", prompt=\\"Query notebook ${notebookId} for: [Your concise question]\\")
169
+ 2. If any comment is vague or explicitly non-actionable as-is, you MUST spawn this exact subagent to negotiate it: Task(subagent_type=\\"rnr-clarifier\\", prompt=\\"Present this ambiguity to the user and ask how they want to proceed: [The context]\\"). Wait for its return string.
170
+ 3. Review how these comments relate to each other and draft the exact revised text blocks for each. You MUST execute the revisions yourself.
171
+ 4. Draft a strict, swift revision note (1 sentence maximum) for each comment.
172
+ 5. Save your output by creating a separate data/COMMENT_<ID>_RESOLVED.md file for EACH comment in your group, using strictly this XML format in each file:
173
+ <revised_text>
174
+ [The exact revised text block]
175
+ </revised_text>
176
+ <reviewer_reply>
177
+ [The drafted reply]
178
+ </reviewer_reply>
179
+ </rules>
180
+ "
181
+ )`);
182
+ });
183
+ }
184
+ }
package/bin/update.js ADDED
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { execSync } = require('child_process');
4
+ const path = require('path');
5
+ const os = require('os');
6
+ const fs = require('fs');
7
+
8
+ console.log('Updating Revise & Resubmit (R&R) Framework...');
9
+
10
+ const rnrDir = path.join(__dirname, '..');
11
+
12
+ try {
13
+ // 1. Pull the latest code from GitHub
14
+ console.log('\nFetching latest updates from GitHub...');
15
+ execSync('git pull origin main', { cwd: rnrDir, stdio: 'inherit' });
16
+
17
+ // 2. We need to determine if the installation was global or local.
18
+ // We can do this by checking if the `.claude/commands/rnr` folder exists in the project root vs home dir.
19
+
20
+ const localClaudeDir = path.join(process.cwd(), '.claude', 'commands', 'rnr');
21
+ const globalClaudeDir = path.join(os.homedir(), '.claude', 'commands', 'rnr');
22
+
23
+ let installCommand = 'node bin/install.js --claude';
24
+
25
+ if (fs.existsSync(localClaudeDir)) {
26
+ console.log('\nDetected local installation.');
27
+ installCommand += ' --local';
28
+ } else if (fs.existsSync(globalClaudeDir)) {
29
+ console.log('\nDetected global installation.');
30
+ installCommand += ' --global';
31
+ } else {
32
+ console.log('\nCould not detect an existing installation. Defaulting to global update.');
33
+ installCommand += ' --global';
34
+ }
35
+
36
+ // 3. Re-run the install script to copy the newly fetched .md files
37
+ console.log('\nRe-installing Claude Code commands...');
38
+ execSync(installCommand, { cwd: rnrDir, stdio: 'inherit' });
39
+
40
+ console.log('\nSuccess! R&R Framework has been updated to the latest version.');
41
+
42
+ } catch (err) {
43
+ console.error('\nUpdate failed:', err.message);
44
+ process.exit(1);
45
+ }
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: rnr:assemble
3
+ description: Repacks XML into a fully valid, formatted .docx
4
+ argument-hint: "<output_file>"
5
+ allowed-tools:
6
+ - Bash
7
+ - Read
8
+ ---
9
+
10
+ <objective>
11
+ Run the Python script `.rnr/src/assembler.py` to inject the resolved comments back into the raw XML and repack the `.docx` file.
12
+ </objective>
13
+
14
+ <process>
15
+ 1. Check if the `.rnr/bin/rnr-tools.js` script exists. If it does not, prompt the user to run `/rnr:init` first.
16
+ 2. Determine the path of the original `.docx` file. You can usually find this by checking `tests/` or asking the user if it isn't obvious in the working directory.
17
+ 3. Determine the requested output file name (e.g., `manuscript_revised.docx`).
18
+ 4. Run the following node command to generate the subagent context:
19
+ ```bash
20
+ node .rnr/bin/rnr-tools.js generate-assemble-task <original_path> <output_path>
21
+ ```
22
+ 5. Do NOT execute the python script directly. Execute the literal `Task(...)` string outputted by the node command exactly as written. This will spawn the `rnr-assembler` subagent which isolates the assembly execution and reporting.
23
+ 6. Report the assembler's success to the user.
24
+ </process>
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: rnr:extract-comments
3
+ description: Unpacks the .docx into XML and extracts Reviewer comments
4
+ argument-hint: "<file> [reviewer]"
5
+ allowed-tools:
6
+ - Bash
7
+ - Read
8
+ - AskUserQuestion
9
+ ---
10
+
11
+ <objective>
12
+ Run the Python script `.rnr/src/parser.py` on the provided `.docx` file to extract its embedded reviewer comments and map them to their corresponding text blocks.
13
+ </objective>
14
+
15
+ <process>
16
+ 1. Check if the `.rnr/bin/rnr-tools.js` script exists. If it does not, politely ask the user to run `/rnr:init` first to install the framework to the working directory, and halt.
17
+ 2. Check if the provided file path exists. If not, ask the user to provide a valid path.
18
+ 3. Check if the reviewer name was provided as an argument. If not, ask the user for the name of the reviewer whose comments and edit suggestions should be extracted.
19
+ 4. If the file exists and the reviewer name is known, run the following command to generate the subagent context:
20
+ ```bash
21
+ node .rnr/bin/rnr-tools.js generate-extract-task {file} "{reviewer}"
22
+ ```
23
+ 5. Do NOT execute the python script directly. Execute the literal `Task(...)` string outputted by the node command exactly as written. This will spawn the `rnr-extractor` subagent which isolates the execution.
24
+ 6. Once the subagent finishes and returns the output to you, read the extracted metadata in `data/document_map.json`.
25
+ 7. Output a brief, user-friendly summary of how many comments were found and extracted.
26
+ 8. Remind the user they can now run `/rnr:synthesize-style` or proceed straight to `/rnr:process-comments`.
27
+ </process>
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: rnr:help
3
+ description: Show all commands and usage guide
4
+ allowed-tools:
5
+ - Read
6
+ ---
7
+
8
+ <objective>
9
+ Provide the user with a helpful overview of the R&R commands and workflow.
10
+ </objective>
11
+
12
+ <process>
13
+ 1. Briefly parse the `README.md` in the root of the project to understand the context.
14
+ 2. Explain the 4-step workflow to the user clearly:
15
+ **1. Extraction** (`/rnr:extract-comments <file>`)
16
+ **2. Synthesis** (`/rnr:synthesize-style`)
17
+ **3. Processing** (`/rnr:process-comments`)
18
+ **4. Assembly** (`/rnr:assemble <output_file>`)
19
+ 3. Ask the user if they'd like you to start the extraction step.
20
+ </process>
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: rnr:init
3
+ description: Initializes the R&R Framework in the current directory by copying required scripts.
4
+ allowed-tools:
5
+ - Bash
6
+ ---
7
+
8
+ <objective>
9
+ Find the original R&R installation directory and copy its `src/` folder into a hidden `.rnr/` directory in the current working directory. This ensures the parser and assembler scripts are available to the local Claude Code subagents.
10
+ </objective>
11
+
12
+ <process>
13
+ 1. Ask the user for the path to the cloned `rnr` repository if it isn't obvious. You can also try searching common locations like `~/Documents/rnr`, `~/rnr`, or checking if the commands in `~/.claude/commands/rnr` have symlinks you can trace.
14
+ 2. Once the R&R source directory is known, run a bash command to create a `.rnr` directory in the current working directory: `mkdir -p .rnr`
15
+ 3. Run a bash command to copy the `src/` directory from the R&R source to the `.rnr/` folder: `cp -r <rnr_path>/src .rnr/`
16
+ 4. Use the `AskUserQuestion` tool to ask if they want to connect a NotebookLM notebook to this project. Ask them to provide the notebook ID or URL, or reply "none" to skip.
17
+ 5. If they provide an ID or URL, extract the ID and write it to `.rnr/config.json` like this: `{"notebook_id": "the_id"}`.
18
+ 6. If they provided an ID, use bash to execute: `claude mcp add notebooklm notebooklm-mcp-cli` to ensure the server is configured. If they reply "none", write `{"notebook_id": null}`.
19
+ 7. If an ID was provided and the MCP server was added, perform a test query to verify the connection is active. Spawn a test subagent locally or use the appropriate MCP tool to simply ask the given NotebookLM ID: "What is the title of this notebook?".
20
+ - *If the test query succeeds:* Report to the user that NotebookLM is successfully connected.
21
+ - *If the test query fails:* Warn the user that the NotebookLM connection failed, and they may need to authenticate or troubleshoot their MCP setup.
22
+ 8. Verify that `.rnr/src/parser.py` exists using bash.
23
+ 9. Report success to the user and politely remind them to add `.rnr` to their `.gitignore` file. Let them know they can now run `/rnr:extract-comments`.
24
+ </process>
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: rnr:process-comments
3
+ description: Iterates through each extracted comment and processes the revisions
4
+ allowed-tools:
5
+ - Bash
6
+ - Read
7
+ - Write
8
+ - AskUserQuestion
9
+ ---
10
+
11
+ <objective>
12
+ Iterate through every `COMMENT_<ID>.md` file in `data/`, resolve the requested revisions strictly adhering to `skills/style_skill.md`, and output a `COMMENT_<ID>_RESOLVED.md` file for each.
13
+ </objective>
14
+
15
+ <core_principle>
16
+ Orchestrator coordinates, not executes. DO NOT read `skills/style_skill.md`, `.rnr/config.json`, or the `COMMENT_<ID>.md` files into your own context. Your job is to trigger the tools that generate `Task()` strings and execute them. The subagents will read the files themselves using their fresh 200k context.
17
+ </core_principle>
18
+
19
+ <process>
20
+ 1. Check that you are in the project root.
21
+ 2. **Classification Phase**: Run the following node script to classify all comments in `data/document_map.json`:
22
+ ```bash
23
+ node .rnr/bin/rnr-tools.js get-grouped-comments
24
+ ```
25
+ *Note: If a classification doesn't exist yet, analyze the `data/document_map.json` yourself and create `data/classification.json` using this schema:*
26
+ `{"isolated": ["ID1", "ID2"], "interlaced": [["ID3", "ID4"], ["ID5", "ID6"]]}`
27
+
28
+ 3. **Execution Phase**:
29
+ Do NOT attempt to loop through the comments yourself. Instead, use the Node.js tool to generate exactly the `Task()` definitions you must execute.
30
+
31
+ Run the following command:
32
+ ```bash
33
+ node .rnr/bin/rnr-tools.js generate-prompts
34
+ ```
35
+
36
+ The script will output a series of `Task(...)` blocks. You MUST literally execute each `Task()` exactly as outputted by the script.
37
+
38
+ **CRITICAL RULE**: Do NOT batch them. You must pass the raw `Task(...)` string identically to the framework so it spawns a fresh subagent for each isolated item and each interlaced group. Execute Wave 1 (Isolated) in parallel. When Wave 1 finishes, execute Wave 2 (Interlaced groups).
39
+
40
+ 4. Confirm to the user when all comments have a resolved file. Advise them they can run `/rnr:assemble output.docx` when ready.
41
+ </process>
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: rnr:synthesize-style
3
+ description: Synthesizes the author's writing style from the document
4
+ allowed-tools:
5
+ - Bash
6
+ - Read
7
+ - Write
8
+ ---
9
+
10
+ <objective>
11
+ Analyze the parsed document text to create a comprehensive `skills/style_skill.md`. This file captures the author's unique voice, terminology, and citation style, and will be used as the ultimate formatting rulebook for all future revisions.
12
+ </objective>
13
+
14
+ <process>
15
+ 1. Make sure you are in the project root. Read the `data/document_map.json` and optionally peek inside `unpacked/word/document.xml` to gather a large enough sample of the original author's written text (e.g., the first 500 words).
16
+ 2. Deeply analyze the text for the following elements:
17
+ - **Tone & Voice**: Is it formal, conversational, dense, accessible, objective, or persuasive?
18
+ - **Vocabulary**: Notice any specific terminology, jargon, or recurring phrases. Are they using British or American spelling?
19
+ - **Sentence Structure**: Does the author prefer long complex sentences, or short punchy ones? Active or passive voice?
20
+ - **Transitions & Flow**: How does the author connect ideas between paragraphs and sentences?
21
+ - **Citation Style**: Analyze the in-text citations. Are they APA (Author, Year), IEEE [1], Chicago footnotes, etc.? Detail the exact formatting rules including punctuation around citations.
22
+ 3. Produce a meticulously structured markdown file and save it to `skills/style_skill.md`.
23
+ 4. The markdown file MUST contain explicit instructions for an AI to follow when writing new text, formatted elegantly with sections for Voice, Vocabulary, Structure, and Citations.
24
+ 5. Confirm to the user that the style has been synthesized and saved.
25
+ </process>
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: rnr:update
3
+ description: Updates the R&R Framework to the latest version from GitHub
4
+ allowed-tools:
5
+ - Bash
6
+ ---
7
+
8
+ <objective>
9
+ Run the Node.js update script `bin/update.js` located in the R&R installation directory to pull the latest updates from GitHub and immediately sync the new Claude commands.
10
+ </objective>
11
+
12
+ <process>
13
+ 1. Determine the path to the R&R installation directory (the folder where `bin/update.js` exists). Use `Bash` to `find` or `locate` `bin/update.js` if it isn't obvious, starting from the current directory or `~/.claude/commands/rnr` context.
14
+ 2. Once the R&R source directory is known, execute the script via bash: `node /path/to/rnr/bin/update.js`.
15
+ 3. Report success or display any terminal errors to the user.
16
+ </process>