patchwork-os 0.2.0-alpha.35 → 0.2.0-alpha.37

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 (207) hide show
  1. package/README.md +70 -15
  2. package/dist/activityLog.d.ts +49 -0
  3. package/dist/activityLog.js +78 -0
  4. package/dist/activityLog.js.map +1 -1
  5. package/dist/approvalHttp.d.ts +25 -0
  6. package/dist/approvalHttp.js +74 -18
  7. package/dist/approvalHttp.js.map +1 -1
  8. package/dist/approvalInsights.d.ts +49 -0
  9. package/dist/approvalInsights.js +97 -0
  10. package/dist/approvalInsights.js.map +1 -0
  11. package/dist/approvalQueue.d.ts +11 -0
  12. package/dist/approvalQueue.js +80 -1
  13. package/dist/approvalQueue.js.map +1 -1
  14. package/dist/approvalSignals.d.ts +124 -0
  15. package/dist/approvalSignals.js +512 -0
  16. package/dist/approvalSignals.js.map +1 -0
  17. package/dist/automation.d.ts +37 -0
  18. package/dist/automation.js +105 -61
  19. package/dist/automation.js.map +1 -1
  20. package/dist/automationSuggestions.d.ts +79 -0
  21. package/dist/automationSuggestions.js +150 -0
  22. package/dist/automationSuggestions.js.map +1 -0
  23. package/dist/bridge.js +46 -0
  24. package/dist/bridge.js.map +1 -1
  25. package/dist/ccPermissions.d.ts +15 -0
  26. package/dist/ccPermissions.js +15 -0
  27. package/dist/ccPermissions.js.map +1 -1
  28. package/dist/claudeDriver.js +74 -16
  29. package/dist/claudeDriver.js.map +1 -1
  30. package/dist/commands/patchworkInit.d.ts +8 -0
  31. package/dist/commands/patchworkInit.js +41 -5
  32. package/dist/commands/patchworkInit.js.map +1 -1
  33. package/dist/commands/recipe.d.ts +20 -0
  34. package/dist/commands/recipe.js +194 -5
  35. package/dist/commands/recipe.js.map +1 -1
  36. package/dist/commands/recipeInstall.js +93 -4
  37. package/dist/commands/recipeInstall.js.map +1 -1
  38. package/dist/commands/tracesExport.d.ts +83 -0
  39. package/dist/commands/tracesExport.js +269 -0
  40. package/dist/commands/tracesExport.js.map +1 -0
  41. package/dist/commands/tracesImport.d.ts +56 -0
  42. package/dist/commands/tracesImport.js +161 -0
  43. package/dist/commands/tracesImport.js.map +1 -0
  44. package/dist/config.d.ts +8 -0
  45. package/dist/config.js +9 -1
  46. package/dist/config.js.map +1 -1
  47. package/dist/connectorRoutes.d.ts +43 -0
  48. package/dist/connectorRoutes.js +1713 -0
  49. package/dist/connectorRoutes.js.map +1 -0
  50. package/dist/connectors/asana.js +6 -7
  51. package/dist/connectors/asana.js.map +1 -1
  52. package/dist/connectors/baseConnector.d.ts +20 -0
  53. package/dist/connectors/baseConnector.js +45 -4
  54. package/dist/connectors/baseConnector.js.map +1 -1
  55. package/dist/connectors/discord.js +6 -7
  56. package/dist/connectors/discord.js.map +1 -1
  57. package/dist/connectors/gmail.js +39 -10
  58. package/dist/connectors/gmail.js.map +1 -1
  59. package/dist/connectors/googleCalendar.js +36 -10
  60. package/dist/connectors/googleCalendar.js.map +1 -1
  61. package/dist/connectors/googleDrive.js +22 -6
  62. package/dist/connectors/googleDrive.js.map +1 -1
  63. package/dist/connectors/linear.js +2 -2
  64. package/dist/connectors/linear.js.map +1 -1
  65. package/dist/connectors/mcpOAuth.js +26 -2
  66. package/dist/connectors/mcpOAuth.js.map +1 -1
  67. package/dist/connectors/oauthStateStore.d.ts +31 -0
  68. package/dist/connectors/oauthStateStore.js +52 -0
  69. package/dist/connectors/oauthStateStore.js.map +1 -0
  70. package/dist/connectors/slack.d.ts +15 -0
  71. package/dist/connectors/slack.js +54 -4
  72. package/dist/connectors/slack.js.map +1 -1
  73. package/dist/connectors/tokenStorage.js +27 -2
  74. package/dist/connectors/tokenStorage.js.map +1 -1
  75. package/dist/connectors/zendesk.js +19 -1
  76. package/dist/connectors/zendesk.js.map +1 -1
  77. package/dist/cors.d.ts +10 -0
  78. package/dist/cors.js +29 -0
  79. package/dist/cors.js.map +1 -0
  80. package/dist/decisionReplay.d.ts +72 -0
  81. package/dist/decisionReplay.js +92 -0
  82. package/dist/decisionReplay.js.map +1 -0
  83. package/dist/decisionTraceLog.d.ts +6 -0
  84. package/dist/decisionTraceLog.js +54 -2
  85. package/dist/decisionTraceLog.js.map +1 -1
  86. package/dist/fp/automationInterpreter.js +25 -21
  87. package/dist/fp/automationInterpreter.js.map +1 -1
  88. package/dist/fp/automationState.js +4 -1
  89. package/dist/fp/automationState.js.map +1 -1
  90. package/dist/fp/policyParser.js +4 -1
  91. package/dist/fp/policyParser.js.map +1 -1
  92. package/dist/inboxRoutes.d.ts +22 -0
  93. package/dist/inboxRoutes.js +114 -0
  94. package/dist/inboxRoutes.js.map +1 -0
  95. package/dist/index.js +479 -17
  96. package/dist/index.js.map +1 -1
  97. package/dist/mcpRoutes.d.ts +37 -0
  98. package/dist/mcpRoutes.js +76 -0
  99. package/dist/mcpRoutes.js.map +1 -0
  100. package/dist/oauth.d.ts +3 -0
  101. package/dist/oauth.js +151 -26
  102. package/dist/oauth.js.map +1 -1
  103. package/dist/oauthRoutes.d.ts +32 -0
  104. package/dist/oauthRoutes.js +124 -0
  105. package/dist/oauthRoutes.js.map +1 -0
  106. package/dist/orchestrator/orchestratorBridge.js +2 -2
  107. package/dist/orchestrator/orchestratorBridge.js.map +1 -1
  108. package/dist/patchworkConfig.d.ts +7 -0
  109. package/dist/patchworkConfig.js.map +1 -1
  110. package/dist/pluginLoader.d.ts +12 -0
  111. package/dist/pluginLoader.js +43 -4
  112. package/dist/pluginLoader.js.map +1 -1
  113. package/dist/pluginWatcher.js +8 -3
  114. package/dist/pluginWatcher.js.map +1 -1
  115. package/dist/preToolUseHook.d.ts +12 -0
  116. package/dist/preToolUseHook.js +23 -0
  117. package/dist/preToolUseHook.js.map +1 -1
  118. package/dist/recipeOrchestration.d.ts +1 -0
  119. package/dist/recipeOrchestration.js +173 -13
  120. package/dist/recipeOrchestration.js.map +1 -1
  121. package/dist/recipeRoutes.d.ts +154 -0
  122. package/dist/recipeRoutes.js +1107 -0
  123. package/dist/recipeRoutes.js.map +1 -0
  124. package/dist/recipes/chainedRunner.d.ts +15 -0
  125. package/dist/recipes/chainedRunner.js +73 -8
  126. package/dist/recipes/chainedRunner.js.map +1 -1
  127. package/dist/recipes/compiler.js +3 -3
  128. package/dist/recipes/compiler.js.map +1 -1
  129. package/dist/recipes/installer.js +3 -3
  130. package/dist/recipes/installer.js.map +1 -1
  131. package/dist/recipes/migrationWarnings.d.ts +12 -0
  132. package/dist/recipes/migrationWarnings.js +44 -0
  133. package/dist/recipes/migrationWarnings.js.map +1 -0
  134. package/dist/recipes/resolveRecipePath.d.ts +69 -0
  135. package/dist/recipes/resolveRecipePath.js +202 -0
  136. package/dist/recipes/resolveRecipePath.js.map +1 -0
  137. package/dist/recipes/tools/file.d.ts +6 -0
  138. package/dist/recipes/tools/file.js +12 -8
  139. package/dist/recipes/tools/file.js.map +1 -1
  140. package/dist/recipes/tools/index.d.ts +2 -0
  141. package/dist/recipes/tools/index.js +2 -0
  142. package/dist/recipes/tools/index.js.map +1 -1
  143. package/dist/recipes/tools/jira.d.ts +14 -0
  144. package/dist/recipes/tools/jira.js +369 -0
  145. package/dist/recipes/tools/jira.js.map +1 -0
  146. package/dist/recipes/tools/linear.js +6 -3
  147. package/dist/recipes/tools/linear.js.map +1 -1
  148. package/dist/recipes/tools/sentry.d.ts +12 -0
  149. package/dist/recipes/tools/sentry.js +73 -0
  150. package/dist/recipes/tools/sentry.js.map +1 -0
  151. package/dist/recipes/tools/slack.js +7 -3
  152. package/dist/recipes/tools/slack.js.map +1 -1
  153. package/dist/recipes/validation.js +83 -14
  154. package/dist/recipes/validation.js.map +1 -1
  155. package/dist/recipes/yamlRunner.d.ts +7 -0
  156. package/dist/recipes/yamlRunner.js +107 -13
  157. package/dist/recipes/yamlRunner.js.map +1 -1
  158. package/dist/recipesHttp.d.ts +44 -1
  159. package/dist/recipesHttp.js +168 -15
  160. package/dist/recipesHttp.js.map +1 -1
  161. package/dist/runLog.d.ts +14 -0
  162. package/dist/runLog.js +88 -4
  163. package/dist/runLog.js.map +1 -1
  164. package/dist/schemas/dry-run-plan.v1.json +139 -0
  165. package/dist/schemas/recipe.v1.json +684 -0
  166. package/dist/server.d.ts +71 -10
  167. package/dist/server.js +363 -1703
  168. package/dist/server.js.map +1 -1
  169. package/dist/ssrfGuard.d.ts +54 -0
  170. package/dist/ssrfGuard.js +122 -0
  171. package/dist/ssrfGuard.js.map +1 -0
  172. package/dist/streamableHttp.d.ts +8 -0
  173. package/dist/streamableHttp.js +112 -21
  174. package/dist/streamableHttp.js.map +1 -1
  175. package/dist/tools/getDocumentSymbols.d.ts +24 -0
  176. package/dist/tools/getDocumentSymbols.js +74 -8
  177. package/dist/tools/getDocumentSymbols.js.map +1 -1
  178. package/dist/tools/getSecurityAdvisories.js +10 -1
  179. package/dist/tools/getSecurityAdvisories.js.map +1 -1
  180. package/dist/tools/getSessionUsage.d.ts +3 -0
  181. package/dist/tools/getSessionUsage.js +3 -0
  182. package/dist/tools/getSessionUsage.js.map +1 -1
  183. package/dist/tools/index.d.ts +8 -0
  184. package/dist/tools/index.js +32 -2
  185. package/dist/tools/index.js.map +1 -1
  186. package/dist/tools/transaction.d.ts +19 -0
  187. package/dist/tools/transaction.js +29 -0
  188. package/dist/tools/transaction.js.map +1 -1
  189. package/dist/traceEncryption.d.ts +46 -0
  190. package/dist/traceEncryption.js +124 -0
  191. package/dist/traceEncryption.js.map +1 -0
  192. package/dist/transport.d.ts +39 -0
  193. package/dist/transport.js +88 -8
  194. package/dist/transport.js.map +1 -1
  195. package/package.json +4 -2
  196. package/templates/policies/README.md +72 -0
  197. package/templates/policies/conservative.json +14 -0
  198. package/templates/policies/developer.json +14 -0
  199. package/templates/policies/headless-ci.json +24 -0
  200. package/templates/policies/personal-assistant.json +15 -0
  201. package/templates/policies/regulated-industry.json +18 -0
  202. package/templates/recipes/webhook/README.md +70 -0
  203. package/templates/recipes/webhook/capture-thought.yaml +26 -0
  204. package/templates/recipes/webhook/customer-escalation.yaml +49 -0
  205. package/templates/recipes/webhook/incident-intake.yaml +46 -0
  206. package/templates/recipes/webhook/meeting-prep.yaml +48 -0
  207. package/templates/recipes/webhook/morning-brief.yaml +57 -0
@@ -0,0 +1,269 @@
1
+ /**
2
+ * patchwork traces export — bundle the four local trace logs into a
3
+ * single round-trippable file so a user can move machines, take a
4
+ * compliance snapshot, or share traces with another tool without the
5
+ * fragile-glob ritual of finding each .jsonl by hand.
6
+ *
7
+ * Output format (Decision 1 / option A in the 2026-05-02 strategic walk-through):
8
+ * a single gzipped JSONL file. Line 1 is a manifest envelope; every
9
+ * subsequent line is a per-row envelope. Encryption is intentionally NOT
10
+ * in this PR — encryption is a 2-hour follow-up once we know which
11
+ * passphrase / KMS UX the user wants.
12
+ *
13
+ * {"type":"manifest","version":1,"exportedAt":"...","sources":[...],"counts":{...}}
14
+ * {"source":"runs","entry":{...one runs.jsonl row...}}
15
+ * {"source":"decision_traces","entry":{...one decision_traces.jsonl row...}}
16
+ * ...
17
+ *
18
+ * Round-trip with `gunzip -c file.jsonl.gz | jq`. Filter one source with
19
+ * `gunzip -c file.jsonl.gz | jq 'select(.source=="decision_traces") | .entry'`.
20
+ *
21
+ * Memory/Ecosystem strategic-plan agent (2026-05-02) flagged trace
22
+ * durability as the top backlog item — see
23
+ * `docs/strategic/2026-05-02/memory-ecosystem-report.md` items 1, 3, 12.
24
+ * Without this, every claim about "years of personal AI memory" is
25
+ * undercut by the existing 1 MB / 10 000-line silent rotation.
26
+ */
27
+ import { createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, statSync, } from "node:fs";
28
+ import os from "node:os";
29
+ import path from "node:path";
30
+ import { createInterface } from "node:readline";
31
+ import { pipeline } from "node:stream/promises";
32
+ import { createGzip } from "node:zlib";
33
+ export const TRACES_EXPORT_VERSION = 1;
34
+ function defaultPatchworkDir() {
35
+ return path.join(os.homedir(), ".patchwork");
36
+ }
37
+ function defaultActivityDir() {
38
+ return path.join(os.homedir(), ".claude", "ide");
39
+ }
40
+ /** Single-file sources live at fixed names in the patchwork dir. */
41
+ const SINGLE_FILE_SOURCES = [
42
+ { source: "runs", filename: "runs.jsonl" },
43
+ { source: "decision_traces", filename: "decision_traces.jsonl" },
44
+ { source: "commit_issue_links", filename: "commit_issue_links.jsonl" },
45
+ ];
46
+ /**
47
+ * Discover activity-log files. Bridge instances each persist to
48
+ * `activity-{port}.jsonl` so we glob for that pattern and include any
49
+ * file that exists. Single explicit `activity.jsonl` (no port suffix)
50
+ * is also picked up — some test harnesses use that name.
51
+ */
52
+ function discoverActivityFiles(activityDir) {
53
+ if (!existsSync(activityDir))
54
+ return [];
55
+ let entries;
56
+ try {
57
+ entries = readdirSync(activityDir);
58
+ }
59
+ catch {
60
+ return [];
61
+ }
62
+ return entries
63
+ .filter((name) => /^activity(-\d+)?\.jsonl$/i.test(name) ||
64
+ /^activity-log\.jsonl$/i.test(name))
65
+ .map((name) => path.join(activityDir, name))
66
+ .filter((p) => {
67
+ try {
68
+ return statSync(p).isFile();
69
+ }
70
+ catch {
71
+ return false;
72
+ }
73
+ })
74
+ .sort();
75
+ }
76
+ async function readJsonlRows(filePath) {
77
+ const rows = [];
78
+ let bytes = 0;
79
+ try {
80
+ bytes = statSync(filePath).size;
81
+ }
82
+ catch {
83
+ return { rows, bytes: 0 };
84
+ }
85
+ const stream = createReadStream(filePath, { encoding: "utf8" });
86
+ const rl = createInterface({ input: stream, crlfDelay: Infinity });
87
+ for await (const line of rl) {
88
+ const trimmed = line.trim();
89
+ if (trimmed.length === 0)
90
+ continue;
91
+ try {
92
+ rows.push(JSON.parse(trimmed));
93
+ }
94
+ catch {
95
+ // Drop unparseable rows. The export's invariant is "every line is
96
+ // valid JSON"; preserving a malformed line would break consumers.
97
+ }
98
+ }
99
+ return { rows, bytes };
100
+ }
101
+ /**
102
+ * Run the export. Pure function over filesystem state — no log instance
103
+ * handles needed, so it works headless (e.g. in CI restoring a snapshot)
104
+ * and during a running bridge alike (the export reads files atomically
105
+ * line-by-line; concurrent appends only add new rows beyond the export's
106
+ * point-in-time view).
107
+ */
108
+ export async function runTracesExport(opts = {}) {
109
+ const exportedAt = new Date().toISOString();
110
+ const patchworkDir = opts.patchworkDir ?? defaultPatchworkDir();
111
+ const activityDir = opts.activityDir ?? defaultActivityDir();
112
+ // Default output: `<patchworkDir>/traces-export-<safeIso>.jsonl.gz`. ISO
113
+ // colons are filename-hostile on Windows so swap them for hyphens.
114
+ const safeStamp = exportedAt.replace(/:/g, "-").replace(/\..+$/, "");
115
+ const outputPath = opts.output ??
116
+ path.join(patchworkDir, `traces-export-${safeStamp}.jsonl.gz`);
117
+ // Discover sources.
118
+ const files = [];
119
+ for (const { source, filename } of SINGLE_FILE_SOURCES) {
120
+ const p = path.join(patchworkDir, filename);
121
+ if (!existsSync(p))
122
+ continue;
123
+ const { rows, bytes } = await readJsonlRows(p);
124
+ files.push({ source, path: p, relativePath: filename, rows, bytes });
125
+ }
126
+ for (const p of discoverActivityFiles(activityDir)) {
127
+ const { rows, bytes } = await readJsonlRows(p);
128
+ files.push({
129
+ source: "activity",
130
+ path: p,
131
+ relativePath: path.basename(p),
132
+ rows,
133
+ bytes,
134
+ activityFile: path.basename(p),
135
+ });
136
+ }
137
+ // Ensure output dir exists.
138
+ const outputDir = path.dirname(outputPath);
139
+ if (!existsSync(outputDir))
140
+ mkdirSync(outputDir, { recursive: true });
141
+ // Build manifest from discovered files (even ones with zero rows are
142
+ // recorded — "we looked here and found this" is more useful than silence).
143
+ const totalCount = files.reduce((sum, f) => sum + f.rows.length, 0);
144
+ const sources = [
145
+ ...new Set(files.map((f) => f.source)),
146
+ ].sort();
147
+ const manifest = {
148
+ type: "manifest",
149
+ version: TRACES_EXPORT_VERSION,
150
+ exportedAt,
151
+ sources,
152
+ files: files.map((f) => ({
153
+ source: f.source,
154
+ relativePath: f.relativePath,
155
+ count: f.rows.length,
156
+ bytes: f.bytes,
157
+ })),
158
+ totalCount,
159
+ };
160
+ // Emit: manifest line + one envelope per row, gzip-piped to disk.
161
+ // Use a Readable source so pipeline() owns backpressure end-to-end —
162
+ // writing directly to gzip outside the pipeline ignores the drain signal
163
+ // and silently buffers everything in memory on large exports.
164
+ const { Readable } = await import("node:stream");
165
+ const source = Readable.from((function* () {
166
+ yield `${JSON.stringify(manifest)}\n`;
167
+ for (const f of files) {
168
+ for (const entry of f.rows) {
169
+ const env = { source: f.source, entry };
170
+ if (f.activityFile)
171
+ env.file = f.activityFile;
172
+ yield `${JSON.stringify(env)}\n`;
173
+ }
174
+ }
175
+ })(), { objectMode: false });
176
+ const sink = createWriteStream(outputPath, { mode: 0o600 });
177
+ await pipeline(source, createGzip(), sink);
178
+ return {
179
+ outputPath,
180
+ exportedAt,
181
+ files: files.map((f) => ({
182
+ source: f.source,
183
+ path: f.path,
184
+ count: f.rows.length,
185
+ bytes: f.bytes,
186
+ })),
187
+ totalCount,
188
+ totalBytes: files.reduce((sum, f) => sum + f.bytes, 0),
189
+ };
190
+ }
191
+ /**
192
+ * Stream-variant of `runTracesExport` — writes gzip-compressed JSONL
193
+ * directly into a caller-supplied `Writable` (e.g. an HTTP response).
194
+ * No temp file is created; the manifest/rows are emitted in one pass.
195
+ *
196
+ * The caller is responsible for setting `Content-Type`,
197
+ * `Content-Encoding`, and `Content-Disposition` headers BEFORE calling
198
+ * this function because Node's HTTP response is not writable after headers
199
+ * have been flushed.
200
+ *
201
+ * Returns row/byte accounting but omits `outputPath` (no disk file).
202
+ */
203
+ export async function runTracesExportToStream(writable, opts = {}) {
204
+ const exportedAt = new Date().toISOString();
205
+ const patchworkDir = opts.patchworkDir ?? defaultPatchworkDir();
206
+ const activityDir = opts.activityDir ?? defaultActivityDir();
207
+ const files = [];
208
+ for (const { source, filename } of SINGLE_FILE_SOURCES) {
209
+ const p = path.join(patchworkDir, filename);
210
+ if (!existsSync(p))
211
+ continue;
212
+ const { rows, bytes } = await readJsonlRows(p);
213
+ files.push({ source, path: p, relativePath: filename, rows, bytes });
214
+ }
215
+ for (const p of discoverActivityFiles(activityDir)) {
216
+ const { rows, bytes } = await readJsonlRows(p);
217
+ files.push({
218
+ source: "activity",
219
+ path: p,
220
+ relativePath: path.relative(activityDir, p),
221
+ rows,
222
+ bytes,
223
+ activityFile: path.basename(p),
224
+ });
225
+ }
226
+ const totalCount = files.reduce((s, f) => s + f.rows.length, 0);
227
+ const sources = [
228
+ ...new Set(files.map((f) => f.source)),
229
+ ].sort();
230
+ const manifest = {
231
+ type: "manifest",
232
+ version: TRACES_EXPORT_VERSION,
233
+ exportedAt,
234
+ sources,
235
+ files: files.map((f) => ({
236
+ source: f.source,
237
+ relativePath: f.relativePath,
238
+ count: f.rows.length,
239
+ bytes: f.bytes,
240
+ })),
241
+ totalCount,
242
+ };
243
+ // Use a Readable source so pipeline() owns backpressure end-to-end.
244
+ const { Readable } = await import("node:stream");
245
+ const source = Readable.from((function* () {
246
+ yield `${JSON.stringify(manifest)}\n`;
247
+ for (const f of files) {
248
+ for (const entry of f.rows) {
249
+ const env = { source: f.source, entry };
250
+ if (f.activityFile)
251
+ env.file = f.activityFile;
252
+ yield `${JSON.stringify(env)}\n`;
253
+ }
254
+ }
255
+ })(), { objectMode: false });
256
+ await pipeline(source, createGzip(), writable);
257
+ return {
258
+ exportedAt,
259
+ files: files.map((f) => ({
260
+ source: f.source,
261
+ path: f.path,
262
+ count: f.rows.length,
263
+ bytes: f.bytes,
264
+ })),
265
+ totalCount,
266
+ totalBytes: files.reduce((sum, f) => sum + f.bytes, 0),
267
+ };
268
+ }
269
+ //# sourceMappingURL=tracesExport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracesExport.js","sourceRoot":"","sources":["../../src/commands/tracesExport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * patchwork traces import — restore a bundle written by `tracesExport` into
3
+ * the local patchwork dirs. Closes the export → backup → restore-on-new-
4
+ * machine loop that was half-shipped (export landed, import did not).
5
+ *
6
+ * Bundle format is the manifest+row-envelope schema from tracesExport.ts:
7
+ *
8
+ * {"type":"manifest","version":1,"exportedAt":"...","sources":[...],"files":[...]}
9
+ * {"source":"runs","entry":{...}}
10
+ * {"source":"decision_traces","entry":{...}}
11
+ * ...
12
+ *
13
+ * Modes:
14
+ * - "append" (default) — entries are appended to the target file. The
15
+ * bundle's row order is preserved. No dedup; if you import the same
16
+ * bundle twice, you get duplicates. This is by design — dedup needs
17
+ * a stable key choice per source and we'd rather ship the simple
18
+ * thing now and add it as a follow-up.
19
+ * - "overwrite" — target file is truncated before any writes. Use
20
+ * this for "clean restore on a fresh machine" — never use it when
21
+ * there's local data you want to keep.
22
+ *
23
+ * Encryption: `.age` bundles must be decrypted out-of-band first
24
+ * (`age -d bundle.jsonl.gz.age | gunzip > bundle.jsonl`). A `--decrypt`
25
+ * flag is a small follow-up.
26
+ */
27
+ import { type TraceSource } from "./tracesExport.js";
28
+ export type ImportMode = "append" | "overwrite";
29
+ export interface TracesImportOptions {
30
+ /** Path to a `.jsonl.gz` (or plain `.jsonl`) bundle written by tracesExport. */
31
+ input: string;
32
+ /** Where to restore single-file sources. Default: `~/.patchwork/`. */
33
+ patchworkDir?: string;
34
+ /** Where to restore activity-*.jsonl. Default: `~/.claude/ide/`. */
35
+ activityDir?: string;
36
+ /** "append" (default) or "overwrite". */
37
+ mode?: ImportMode;
38
+ /** Don't write anything — return what would happen. */
39
+ dryRun?: boolean;
40
+ }
41
+ export interface TracesImportResult {
42
+ inputPath: string;
43
+ exportedAt: string;
44
+ mode: ImportMode;
45
+ dryRun: boolean;
46
+ /** Per target-file accounting. Multiple files possible for activity (one per source bridge instance). */
47
+ files: Array<{
48
+ source: TraceSource;
49
+ targetPath: string;
50
+ /** Rows written (or that would be written, in dry-run). */
51
+ count: number;
52
+ }>;
53
+ /** Total rows across all target files. */
54
+ totalCount: number;
55
+ }
56
+ export declare function runTracesImport(opts: TracesImportOptions): Promise<TracesImportResult>;
@@ -0,0 +1,161 @@
1
+ /**
2
+ * patchwork traces import — restore a bundle written by `tracesExport` into
3
+ * the local patchwork dirs. Closes the export → backup → restore-on-new-
4
+ * machine loop that was half-shipped (export landed, import did not).
5
+ *
6
+ * Bundle format is the manifest+row-envelope schema from tracesExport.ts:
7
+ *
8
+ * {"type":"manifest","version":1,"exportedAt":"...","sources":[...],"files":[...]}
9
+ * {"source":"runs","entry":{...}}
10
+ * {"source":"decision_traces","entry":{...}}
11
+ * ...
12
+ *
13
+ * Modes:
14
+ * - "append" (default) — entries are appended to the target file. The
15
+ * bundle's row order is preserved. No dedup; if you import the same
16
+ * bundle twice, you get duplicates. This is by design — dedup needs
17
+ * a stable key choice per source and we'd rather ship the simple
18
+ * thing now and add it as a follow-up.
19
+ * - "overwrite" — target file is truncated before any writes. Use
20
+ * this for "clean restore on a fresh machine" — never use it when
21
+ * there's local data you want to keep.
22
+ *
23
+ * Encryption: `.age` bundles must be decrypted out-of-band first
24
+ * (`age -d bundle.jsonl.gz.age | gunzip > bundle.jsonl`). A `--decrypt`
25
+ * flag is a small follow-up.
26
+ */
27
+ import { appendFileSync, createReadStream, existsSync, mkdirSync, writeFileSync, } from "node:fs";
28
+ import os from "node:os";
29
+ import path from "node:path";
30
+ import { createInterface } from "node:readline";
31
+ import { createGunzip } from "node:zlib";
32
+ import { TRACES_EXPORT_VERSION } from "./tracesExport.js";
33
+ const SINGLE_FILE_TARGETS = {
34
+ runs: "runs.jsonl",
35
+ decision_traces: "decision_traces.jsonl",
36
+ commit_issue_links: "commit_issue_links.jsonl",
37
+ };
38
+ function defaultPatchworkDir() {
39
+ return path.join(os.homedir(), ".patchwork");
40
+ }
41
+ function defaultActivityDir() {
42
+ return path.join(os.homedir(), ".claude", "ide");
43
+ }
44
+ function resolveTargetPath(source, envelopeFile, patchworkDir, activityDir) {
45
+ if (source === "activity") {
46
+ // activity rows carry the original file name — preserve it so a
47
+ // multi-instance export round-trips per-port. Default fallback if
48
+ // the envelope didn't include one.
49
+ const name = envelopeFile ?? "activity.jsonl";
50
+ return path.join(activityDir, name);
51
+ }
52
+ return path.join(patchworkDir, SINGLE_FILE_TARGETS[source]);
53
+ }
54
+ export async function runTracesImport(opts) {
55
+ const inputPath = path.resolve(opts.input);
56
+ if (!existsSync(inputPath)) {
57
+ throw new Error(`Input bundle not found: ${inputPath}`);
58
+ }
59
+ const mode = opts.mode ?? "append";
60
+ const dryRun = opts.dryRun === true;
61
+ const patchworkDir = opts.patchworkDir ?? defaultPatchworkDir();
62
+ const activityDir = opts.activityDir ?? defaultActivityDir();
63
+ if (!dryRun) {
64
+ if (!existsSync(patchworkDir))
65
+ mkdirSync(patchworkDir, { recursive: true });
66
+ if (!existsSync(activityDir))
67
+ mkdirSync(activityDir, { recursive: true });
68
+ }
69
+ // Stream-read the bundle. Auto-detect gzip via `.gz` suffix; users who
70
+ // already gunzipped manually can pass the plain .jsonl.
71
+ const baseStream = createReadStream(inputPath);
72
+ const lineStream = inputPath.endsWith(".gz")
73
+ ? baseStream.pipe(createGunzip())
74
+ : baseStream;
75
+ const rl = createInterface({ input: lineStream, crlfDelay: Infinity });
76
+ let manifest = null;
77
+ // Group writes by target so we can truncate-once for overwrite mode and
78
+ // batch the appends. Memory cost is one row's worth of buffer per target,
79
+ // which is acceptable for a CLI command operating on user-machine-sized
80
+ // data.
81
+ const buffers = new Map();
82
+ let lineNum = 0;
83
+ for await (const raw of rl) {
84
+ lineNum++;
85
+ const line = raw.trim();
86
+ if (line === "")
87
+ continue;
88
+ let parsed;
89
+ try {
90
+ parsed = JSON.parse(line);
91
+ }
92
+ catch {
93
+ throw new Error(`Bundle parse error at line ${lineNum}: not valid JSON`);
94
+ }
95
+ if (lineNum === 1) {
96
+ // First non-empty line must be the manifest.
97
+ if (!parsed ||
98
+ typeof parsed !== "object" ||
99
+ parsed.type !== "manifest") {
100
+ throw new Error(`First line of bundle is not a manifest envelope (got: ${line.slice(0, 80)}…)`);
101
+ }
102
+ manifest = parsed;
103
+ if (manifest.version !== TRACES_EXPORT_VERSION) {
104
+ throw new Error(`Bundle version ${manifest.version} not supported (expected ${TRACES_EXPORT_VERSION})`);
105
+ }
106
+ continue;
107
+ }
108
+ if (manifest === null) {
109
+ throw new Error("Bundle has rows before a manifest line");
110
+ }
111
+ const env = parsed;
112
+ if (typeof env.source !== "string" || env.entry === undefined) {
113
+ throw new Error(`Bundle row at line ${lineNum} missing source/entry`);
114
+ }
115
+ const source = env.source;
116
+ const file = typeof env.file === "string" ? env.file : undefined;
117
+ const targetPath = resolveTargetPath(source, file, patchworkDir, activityDir);
118
+ const buf = buffers.get(targetPath) ?? { source, lines: [] };
119
+ // Re-serialize the entry as one JSONL line. Tools downstream of these
120
+ // files expect one JSON object per line, no envelope.
121
+ buf.lines.push(JSON.stringify(env.entry));
122
+ buffers.set(targetPath, buf);
123
+ }
124
+ if (manifest === null) {
125
+ throw new Error("Bundle is empty (no manifest line)");
126
+ }
127
+ // Apply: in overwrite mode, truncate each target before appending its
128
+ // batch. In append mode, just append.
129
+ const files = [];
130
+ let totalCount = 0;
131
+ for (const [targetPath, buf] of buffers) {
132
+ const count = buf.lines.length;
133
+ totalCount += count;
134
+ if (!dryRun) {
135
+ // Ensure the target directory exists (activity-port files might
136
+ // land in a dir we don't control — covered by the mkdir above for
137
+ // the configured activityDir, but parent dir of arbitrary path
138
+ // needs its own check).
139
+ const parent = path.dirname(targetPath);
140
+ if (!existsSync(parent))
141
+ mkdirSync(parent, { recursive: true });
142
+ const payload = `${buf.lines.join("\n")}\n`;
143
+ if (mode === "overwrite") {
144
+ writeFileSync(targetPath, payload, "utf-8");
145
+ }
146
+ else {
147
+ appendFileSync(targetPath, payload, "utf-8");
148
+ }
149
+ }
150
+ files.push({ source: buf.source, targetPath, count });
151
+ }
152
+ return {
153
+ inputPath,
154
+ exportedAt: manifest.exportedAt,
155
+ mode,
156
+ dryRun,
157
+ files: files.sort((a, b) => a.targetPath.localeCompare(b.targetPath)),
158
+ totalCount,
159
+ };
160
+ }
161
+ //# sourceMappingURL=tracesImport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracesImport.js","sourceRoot":"","sources":["../../src/commands/tracesImport.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -24,6 +24,14 @@ export interface Config {
24
24
  toolRateLimit: number;
25
25
  /** Patchwork: gate tool dispatch on human approval via dashboard. "high" = only high-risk tools (default-safe); "all" = every tool; "off" = disabled. */
26
26
  approvalGate: "off" | "high" | "all";
27
+ /**
28
+ * Patchwork: opt-in switch for the time-of-day anomaly heuristic
29
+ * (h10 in src/approvalSignals.ts). Off by default — catalog flags it
30
+ * as medium-FP for power users with irregular schedules. Enable via
31
+ * --enable-time-of-day-anomaly (CLI) or `personalSignals.timeOfDayAnomaly: true`
32
+ * in ~/.patchwork/config.json.
33
+ */
34
+ enableTimeOfDayAnomaly: boolean;
27
35
  /** Patchwork: admin-controlled managed settings file (highest rule precedence, cannot be overridden). */
28
36
  managedSettingsPath: string | null;
29
37
  /** Patchwork: outbound webhook URL for approval queue notifications (from dashboard.webhookUrl in patchwork config). */
package/dist/config.js CHANGED
@@ -311,6 +311,8 @@ export function parseConfig(argv) {
311
311
  let automationPolicyPath = fileConfig.automationPolicyPath ?? null;
312
312
  let approvalGate = fileConfig.approvalGate ??
313
313
  "off";
314
+ let enableTimeOfDayAnomaly = fileConfig
315
+ .enableTimeOfDayAnomaly ?? false;
314
316
  let managedSettingsPath = null;
315
317
  // Read approvalWebhookUrl, approvalGate, driver, and apiKeys from patchwork config
316
318
  // (non-fatal; CLI flags and bridge config file take precedence over patchwork config)
@@ -482,6 +484,11 @@ export function parseConfig(argv) {
482
484
  approvalGate = val;
483
485
  break;
484
486
  }
487
+ case "--enable-time-of-day-anomaly": {
488
+ // Boolean flag — opt-in for personalSignals h10. No value arg.
489
+ enableTimeOfDayAnomaly = true;
490
+ break;
491
+ }
485
492
  case "--managed-settings": {
486
493
  const mp = requireArg(args, ++i, "--managed-settings");
487
494
  if (mp.length > 4096)
@@ -632,7 +639,7 @@ Options:
632
639
  --help Show this help
633
640
 
634
641
  Patchwork:
635
- --approval-gate <level> Gate tool calls via oversight dashboard: "off" | "high" | "all" (default: "off")
642
+ --approval-gate <level> Delegation policy: gate tool calls via oversight dashboard: "off" | "high" | "all" (default: "off")
636
643
  --managed-settings <path> Admin-controlled settings file (highest rule precedence, cannot be overridden by users)
637
644
 
638
645
  Automation:
@@ -785,6 +792,7 @@ Environment Variables:
785
792
  automationEnabled,
786
793
  automationPolicyPath,
787
794
  approvalGate,
795
+ enableTimeOfDayAnomaly,
788
796
  managedSettingsPath,
789
797
  approvalWebhookUrl,
790
798
  toolRateLimit,