@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.
- package/.eslintrc.json +22 -0
- package/.github/workflows/publish.yml +41 -0
- package/.prettierignore +17 -0
- package/LICENSE +21 -0
- package/README.md +183 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +2950 -0
- package/dist/index.d.ts +406 -0
- package/dist/index.js +2737 -0
- package/dist/mcp-server.d.ts +7 -0
- package/dist/mcp-server.js +2665 -0
- package/docs/research/crdt.md +777 -0
- package/docs/research/github-issues.md +684 -0
- package/docs/research/gql.md +876 -0
- package/docs/research/index.md +19 -0
- package/docs/specs/conflict-resolution.md +1254 -0
- package/docs/specs/hardcopy.md +742 -0
- package/docs/specs/patchwork-integration.md +227 -0
- package/docs/specs/plugin-architecture.md +747 -0
- package/mcp.json +8 -0
- package/package.json +64 -0
- package/scripts/install-graphqlite.ts +156 -0
- package/src/cli.ts +356 -0
- package/src/config.ts +104 -0
- package/src/conflict-store.ts +136 -0
- package/src/conflict.ts +147 -0
- package/src/crdt.ts +100 -0
- package/src/db.ts +600 -0
- package/src/env.ts +34 -0
- package/src/format.ts +72 -0
- package/src/formats/github-issue.ts +55 -0
- package/src/hardcopy/core.ts +78 -0
- package/src/hardcopy/diff.ts +188 -0
- package/src/hardcopy/index.ts +67 -0
- package/src/hardcopy/init.ts +24 -0
- package/src/hardcopy/push.ts +444 -0
- package/src/hardcopy/sync.ts +37 -0
- package/src/hardcopy/types.ts +49 -0
- package/src/hardcopy/views.ts +199 -0
- package/src/hardcopy.ts +1 -0
- package/src/index.ts +13 -0
- package/src/llm-merge.ts +109 -0
- package/src/mcp-server.ts +388 -0
- package/src/merge.ts +75 -0
- package/src/provider.ts +40 -0
- package/src/providers/a2a/index.ts +166 -0
- package/src/providers/git/index.ts +212 -0
- package/src/providers/github/index.ts +236 -0
- package/src/providers/github/issues.ts +66 -0
- package/src/providers.ts +7 -0
- package/src/types.ts +101 -0
- package/tsconfig.json +21 -0
- 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.**
|