@aprovan/hardcopy 0.1.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 (53) hide show
  1. package/.eslintrc.json +22 -0
  2. package/.github/workflows/publish.yml +41 -0
  3. package/.prettierignore +17 -0
  4. package/LICENSE +21 -0
  5. package/README.md +183 -0
  6. package/dist/cli.d.ts +1 -0
  7. package/dist/cli.js +2950 -0
  8. package/dist/index.d.ts +406 -0
  9. package/dist/index.js +2737 -0
  10. package/dist/mcp-server.d.ts +7 -0
  11. package/dist/mcp-server.js +2665 -0
  12. package/docs/research/crdt.md +777 -0
  13. package/docs/research/github-issues.md +684 -0
  14. package/docs/research/gql.md +876 -0
  15. package/docs/research/index.md +19 -0
  16. package/docs/specs/conflict-resolution.md +1254 -0
  17. package/docs/specs/hardcopy.md +742 -0
  18. package/docs/specs/patchwork-integration.md +227 -0
  19. package/docs/specs/plugin-architecture.md +747 -0
  20. package/mcp.json +8 -0
  21. package/package.json +64 -0
  22. package/scripts/install-graphqlite.ts +156 -0
  23. package/src/cli.ts +356 -0
  24. package/src/config.ts +104 -0
  25. package/src/conflict-store.ts +136 -0
  26. package/src/conflict.ts +147 -0
  27. package/src/crdt.ts +100 -0
  28. package/src/db.ts +600 -0
  29. package/src/env.ts +34 -0
  30. package/src/format.ts +72 -0
  31. package/src/formats/github-issue.ts +55 -0
  32. package/src/hardcopy/core.ts +78 -0
  33. package/src/hardcopy/diff.ts +188 -0
  34. package/src/hardcopy/index.ts +67 -0
  35. package/src/hardcopy/init.ts +24 -0
  36. package/src/hardcopy/push.ts +444 -0
  37. package/src/hardcopy/sync.ts +37 -0
  38. package/src/hardcopy/types.ts +49 -0
  39. package/src/hardcopy/views.ts +199 -0
  40. package/src/hardcopy.ts +1 -0
  41. package/src/index.ts +13 -0
  42. package/src/llm-merge.ts +109 -0
  43. package/src/mcp-server.ts +388 -0
  44. package/src/merge.ts +75 -0
  45. package/src/provider.ts +40 -0
  46. package/src/providers/a2a/index.ts +166 -0
  47. package/src/providers/git/index.ts +212 -0
  48. package/src/providers/github/index.ts +236 -0
  49. package/src/providers/github/issues.ts +66 -0
  50. package/src/providers.ts +7 -0
  51. package/src/types.ts +101 -0
  52. package/tsconfig.json +21 -0
  53. package/tsup.config.ts +10 -0
@@ -0,0 +1,227 @@
1
+ # Hardcopy + Patchwork: Filesystem as Interface
2
+
3
+ Hardcopy and Patchwork are **independent tools** that don't reference each other. They integrate via the filesystem—the universal interface.
4
+
5
+ ---
6
+
7
+ ## Core Principle
8
+
9
+ ```
10
+ ┌──────────────────────────────────────────────────────────────────────┐
11
+ │ The Filesystem IS the Interface │
12
+ ├──────────────────────────────────────────────────────────────────────┤
13
+ │ │
14
+ │ ┌─────────────┐ ┌─────────────┐ │
15
+ │ │ Patchwork │ │ Hardcopy │ │
16
+ │ │ (browser) │ │ (CLI/bg) │ │
17
+ │ └──────┬──────┘ └──────┬──────┘ │
18
+ │ │ │ │
19
+ │ │ ┌─────────────────────┐ │ │
20
+ │ └────────►│ Local Directory │◄──────────┘ │
21
+ │ │ ~/project/docs/ │ │
22
+ │ └─────────────────────┘ │
23
+ │ │
24
+ └──────────────────────────────────────────────────────────────────────┘
25
+ ```
26
+
27
+ **No shared code. No direct APIs. No bespoke protocols.**
28
+
29
+ Both tools read and write files. That's how they communicate.
30
+
31
+ ---
32
+
33
+ ## How They Work Together
34
+
35
+ ### Scenario: Editing GitHub Issues Locally
36
+
37
+ ```
38
+ 1. User runs: hardcopy sync && hardcopy refresh docs/issues
39
+ 2. Hardcopy creates: ~/project/docs/issues/42.md (from GitHub API)
40
+ 3. User opens: Patchwork, pointed at ~/project/
41
+ 4. User edits: 42.md via Patchwork's Monaco editor
42
+ 5. Patchwork saves: ~/project/docs/issues/42.md (local file)
43
+ 6. User runs: hardcopy push docs/issues/42.md
44
+ 7. Hardcopy pushes: Changes to GitHub API
45
+ ```
46
+
47
+ At no point do Patchwork and Hardcopy talk to each other. They both talk to files.
48
+
49
+ ### File Watching
50
+
51
+ Both tools can watch for file changes using **standard OS mechanisms**:
52
+
53
+ | Tool | Watch Method | Standard |
54
+ |------|--------------|----------|
55
+ | Patchwork (Node/stitchery) | `fs.watch()` | Node.js |
56
+ | Patchwork (browser) | Polling / HTTP `If-Modified-Since` | HTTP |
57
+ | Hardcopy | `fs.watch()` or `chokidar` | Node.js |
58
+
59
+ No custom event streams. No Hardcopy-specific SSE. Standard file watching.
60
+
61
+ ---
62
+
63
+ ## Responsibility Split
64
+
65
+ | Concern | Patchwork | Hardcopy | Shared |
66
+ |---------|-----------|----------|--------|
67
+ | File editing UI | ✓ | - | - |
68
+ | File compilation/preview | ✓ | - | - |
69
+ | LLM-driven file edits | ✓ | - | - |
70
+ | Conflict resolution UI | ✓ (local-wins) | - | - |
71
+ | Remote API sync | - | ✓ | - |
72
+ | Three-way merge | - | ✓ | - |
73
+ | CRDT state tracking | - | ✓ | - |
74
+ | LLM conflict resolution | - | ✓ | - |
75
+ | File watching | ✓ | ✓ | via OS |
76
+ | **File read/write** | ✓ | ✓ | **Filesystem** |
77
+
78
+ ---
79
+
80
+ ## Conflict Handling
81
+
82
+ ### Patchwork's Approach
83
+
84
+ Patchwork is **local-first**. When syncing with a backend:
85
+
86
+ ```typescript
87
+ // Patchwork conflict strategy (default)
88
+ conflictStrategy: 'local-wins'
89
+ ```
90
+
91
+ Patchwork does NOT:
92
+ - Know about three-way merges
93
+ - Know about remote APIs
94
+ - Know about Hardcopy
95
+
96
+ If the user wants advanced conflict resolution, they run Hardcopy separately.
97
+
98
+ ### Hardcopy's Approach
99
+
100
+ Hardcopy handles conflicts when syncing with remote APIs:
101
+
102
+ 1. **Auto-merge** - List fields (labels, assignees) → union
103
+ 2. **LLM-assisted** - Body content with divergent changes → LLM merge
104
+ 3. **Manual** - Creates conflict artifact file with markers
105
+
106
+ The conflict artifact is just a file:
107
+
108
+ ```markdown
109
+ ---
110
+ nodeId: github:AprovanLabs/core/issues/42
111
+ conflict: true
112
+ ---
113
+
114
+ ## body
115
+
116
+ <<<<<<< LOCAL
117
+ I changed this line locally
118
+ ||||||| BASE
119
+ Original content
120
+ =======
121
+ Someone else changed this remotely
122
+ >>>>>>> REMOTE
123
+ ```
124
+
125
+ Patchwork might display this file. It doesn't know it's a "conflict file"—it's just markdown with a specific format.
126
+
127
+ ---
128
+
129
+ ## MCP Server (Optional)
130
+
131
+ If Hardcopy tools need to be available to LLMs in Patchwork's chat interface, Hardcopy can expose an **MCP server**:
132
+
133
+ ```yaml
134
+ # In user's MCP config for Patchwork
135
+ servers:
136
+ hardcopy:
137
+ command: hardcopy
138
+ args: [mcp-serve]
139
+ ```
140
+
141
+ This MCP server is **generic to Hardcopy**, not Patchwork-specific. It might expose tools like:
142
+
143
+ - `hardcopy_sync` - Sync remote sources
144
+ - `hardcopy_push` - Push local changes
145
+ - `hardcopy_status` - Show sync status
146
+ - `hardcopy_resolve_conflict` - Resolve a conflict
147
+
148
+ Patchwork's LLM can call these tools via the standard service proxy flow. Patchwork has no Hardcopy-specific code.
149
+
150
+ ---
151
+
152
+ ## Implementation Notes
153
+
154
+ ### For Hardcopy
155
+
156
+ 1. **No VFS server** - Don't build HTTP routes for Patchwork. Manage files directly.
157
+ 2. **Standard file watching** - Use `fs.watch()` or `chokidar` to detect local edits.
158
+ 3. **Conflict artifacts** - Write conflict files with git-style markers.
159
+ 4. **MCP server (optional)** - Expose Hardcopy CLI as MCP tools for LLM integration.
160
+
161
+ ### For Patchwork
162
+
163
+ 1. **No Hardcopy imports** - Patchwork knows nothing about Hardcopy.
164
+ 2. **Local-first** - Default to `local-wins` conflict strategy.
165
+ 3. **Standard backends** - HTTP backend talks to stitchery, which reads local files.
166
+ 4. **File watching** - Use standard SSE from stitchery's `/vfs?watch=path` (Node.js `fs.watch`).
167
+
168
+ ### Shared Directory Setup
169
+
170
+ Both tools point at the same directory:
171
+
172
+ ```bash
173
+ # Start Patchwork's stitchery server
174
+ stitchery --vfs-dir ~/project/
175
+
176
+ # Run Hardcopy in the same directory
177
+ cd ~/project/
178
+ hardcopy sync
179
+ hardcopy refresh docs/issues
180
+ ```
181
+
182
+ Patchwork sees files via HTTP→stitchery→local disk.
183
+ Hardcopy manages files directly on local disk.
184
+
185
+ ---
186
+
187
+ ## Non-Goals
188
+
189
+ 1. **Hardcopy HTTP server for Patchwork** - Not needed. Filesystem is the interface.
190
+ 2. **Hardcopy SSE events for Patchwork** - Use standard file watching.
191
+ 3. **Shared TypeScript interfaces** - No shared code between projects.
192
+ 4. **Patchwork conflict delegation** - Patchwork doesn't know Hardcopy exists.
193
+
194
+ ---
195
+
196
+ ## Future Considerations
197
+
198
+ ### Real-time Collaboration
199
+
200
+ If needed in the future, both tools could use **standard CRDTs** (like Yjs or Loro) with a **standard sync protocol**. But this would be:
201
+
202
+ - A separate shared library (not Hardcopy-specific)
203
+ - Based on web standards (WebRTC, WebSocket)
204
+ - Implemented independently in each tool
205
+
206
+ ### Event Streaming
207
+
208
+ If cross-tool events are ever needed:
209
+
210
+ - Use filesystem events (inotify, kqueue)
211
+ - Or use a standard event bus (Redis, NATS)
212
+ - NOT a bespoke Hardcopy↔Patchwork protocol
213
+
214
+ ---
215
+
216
+ ## Summary
217
+
218
+ | Question | Answer |
219
+ |----------|--------|
220
+ | Does Patchwork depend on Hardcopy? | **No** |
221
+ | Does Hardcopy depend on Patchwork? | **No** |
222
+ | How do they communicate? | **Files on disk** |
223
+ | How does Patchwork detect file changes? | **Standard file watching** |
224
+ | How does Hardcopy provide LLM tools? | **MCP server (optional)** |
225
+ | What about conflicts? | **Hardcopy writes conflict files** |
226
+
227
+ **The filesystem is the interface. Keep it that way.**