@runfusion/fusion 0.24.0 → 0.26.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 (167) hide show
  1. package/README.md +6 -0
  2. package/dist/bin.js +18646 -15669
  3. package/dist/client/assets/AgentDetailView-Cv-vgOj3.js +18 -0
  4. package/dist/client/assets/{AgentsView-BkB9FiMT.js → AgentsView-D6Zi5zfP.js} +4 -4
  5. package/dist/client/assets/ChatView-CAHjY9uO.js +1 -0
  6. package/dist/client/assets/{DevServerView-BkvtjZBa.js → DevServerView--_WBvIDQ.js} +1 -1
  7. package/dist/client/assets/{DirectoryPicker-BK-KbnhP.js → DirectoryPicker-xedtR-Rd.js} +1 -1
  8. package/dist/client/assets/{DocumentsView-BEg1CQAk.js → DocumentsView-Bg2oaZks.js} +1 -1
  9. package/dist/client/assets/{EvalsView-Berf9bQm.js → EvalsView-B3uOCXfr.js} +1 -1
  10. package/dist/client/assets/{ExperimentalAgentOnboardingModal-jcInE50G.js → ExperimentalAgentOnboardingModal-Bx6yXVS5.js} +1 -1
  11. package/dist/client/assets/{InsightsView-BX5bSF1J.js → InsightsView-Q1zvtF4F.js} +1 -1
  12. package/dist/client/assets/MemoryView-xcN_eouf.js +2 -0
  13. package/dist/client/assets/MemoryView-zaXewZzi.css +1 -0
  14. package/dist/client/assets/{NodesView-DLUOBLf6.js → NodesView-RxXg58_Q.js} +1 -1
  15. package/dist/client/assets/{PiExtensionsManager-COlJf0Kx.js → PiExtensionsManager-Cc8aAZXg.js} +2 -2
  16. package/dist/client/assets/PluginManager-BEkyBajl.js +1 -0
  17. package/dist/client/assets/{ResearchView-BzCcDAS4.css → ResearchView-BEI4ZSGs.css} +1 -1
  18. package/dist/client/assets/ResearchView-CERNf7sJ.js +1 -0
  19. package/dist/client/assets/{SettingsModal-yRqM4DV8.js → SettingsModal-B1r0yASu.js} +1 -1
  20. package/dist/client/assets/SettingsModal-BLsac7CJ.js +31 -0
  21. package/dist/client/assets/SettingsModal-Cis-4Lot.css +1 -0
  22. package/dist/client/assets/{SetupWizardModal-uUZk3TKT.js → SetupWizardModal-D1q548_L.js} +1 -1
  23. package/dist/client/assets/{SkillsView-CP8JX0P_.js → SkillsView-ClLM6u6p.js} +1 -1
  24. package/dist/client/assets/StashRecoveryView-B_8WIQEo.css +1 -0
  25. package/dist/client/assets/StashRecoveryView-ze0pEZ5U.js +1 -0
  26. package/dist/client/assets/{TodoView-DCRIkDZ-.js → TodoView-CTmIfy2M.js} +1 -1
  27. package/dist/client/assets/{dashboard-view-lR7YYmSC.js → dashboard-view-4xAN3yO5.js} +2 -2
  28. package/dist/client/assets/{folder-open-DHjELt8-.js → folder-open-BZuKESeq.js} +1 -1
  29. package/dist/client/assets/index-Bdw6llW6.js +692 -0
  30. package/dist/client/assets/index-CZGlyJuS.css +1 -0
  31. package/dist/client/assets/{star-DYesq1AV.js → star-D75YKEq-.js} +1 -1
  32. package/dist/client/assets/{upload-DTWF3Db5.js → upload-BYYTgWFj.js} +1 -1
  33. package/dist/client/assets/{users--syrel4l.js → users-RS90Aii3.js} +1 -1
  34. package/dist/client/index.html +2 -2
  35. package/dist/client/version.json +1 -1
  36. package/dist/droid-cli/package.json +1 -1
  37. package/dist/extension.js +5640 -3618
  38. package/dist/pi-claude-cli/package.json +1 -1
  39. package/dist/plugins/fusion-plugin-cli-printing-press/manifest.json +6 -0
  40. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +26 -0
  41. package/dist/plugins/fusion-plugin-cli-printing-press/src/__tests__/manifest.test.ts +20 -0
  42. package/dist/plugins/fusion-plugin-cli-printing-press/src/index.ts +14 -0
  43. package/dist/plugins/fusion-plugin-cursor-runtime/bundled.js +9 -11
  44. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  45. package/dist/plugins/fusion-plugin-dependency-graph/bundled.js +30 -0
  46. package/dist/plugins/fusion-plugin-dependency-graph/package.json +3 -28
  47. package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +899 -895
  48. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  49. package/dist/plugins/fusion-plugin-hermes-runtime/bundled.js +68 -71
  50. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  51. package/dist/plugins/fusion-plugin-openclaw-runtime/bundled.js +47 -50
  52. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  53. package/dist/plugins/fusion-plugin-paperclip-runtime/bundled.js +155 -109
  54. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  55. package/dist/plugins/fusion-plugin-reports/package.json +1 -1
  56. package/dist/plugins/fusion-plugin-reports/src/index.ts +49 -3
  57. package/dist/plugins/fusion-plugin-reports/src/report-schema.ts +38 -0
  58. package/dist/plugins/fusion-plugin-reports/src/store/__tests__/report-schema.test.ts +66 -0
  59. package/dist/plugins/fusion-plugin-reports/src/store/__tests__/report-store.test.ts +177 -0
  60. package/dist/plugins/fusion-plugin-reports/src/store/report-store.ts +341 -0
  61. package/dist/plugins/fusion-plugin-reports/src/store/report-types.ts +77 -0
  62. package/dist/plugins/fusion-plugin-roadmap/{src/dashboard/RoadmapsView.css → bundled.css} +13 -219
  63. package/dist/plugins/fusion-plugin-roadmap/bundled.js +29535 -0
  64. package/dist/plugins/fusion-plugin-roadmap/package.json +4 -41
  65. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
  66. package/package.json +2 -3
  67. package/dist/client/assets/AgentDetailView-gy_5SUj2.js +0 -18
  68. package/dist/client/assets/ChatView-B_-B8fqu.js +0 -1
  69. package/dist/client/assets/MemoryView-CKElJY_3.js +0 -2
  70. package/dist/client/assets/MemoryView-DiajLXby.css +0 -1
  71. package/dist/client/assets/PluginManager-CfW55BF4.js +0 -1
  72. package/dist/client/assets/ResearchView-B256Lr8I.js +0 -1
  73. package/dist/client/assets/SettingsModal-BeA_nQtW.js +0 -31
  74. package/dist/client/assets/SettingsModal-DzsLquBu.css +0 -1
  75. package/dist/client/assets/index-CQyVRLOb.js +0 -692
  76. package/dist/client/assets/index-CxA2Nn0_.css +0 -1
  77. package/dist/plugins/fusion-plugin-dependency-graph/src/DependencyGraph.css +0 -58
  78. package/dist/plugins/fusion-plugin-dependency-graph/src/DependencyGraph.tsx +0 -301
  79. package/dist/plugins/fusion-plugin-dependency-graph/src/GraphHighlight.css +0 -27
  80. package/dist/plugins/fusion-plugin-dependency-graph/src/GraphTaskNode.css +0 -157
  81. package/dist/plugins/fusion-plugin-dependency-graph/src/GraphTaskNode.tsx +0 -126
  82. package/dist/plugins/fusion-plugin-dependency-graph/src/GraphToolbar.css +0 -35
  83. package/dist/plugins/fusion-plugin-dependency-graph/src/GraphToolbar.tsx +0 -36
  84. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/DependencyGraph.highlighting.test.tsx +0 -112
  85. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/DependencyGraph.persistence.test.tsx +0 -115
  86. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/DependencyGraph.test.tsx +0 -128
  87. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/GraphTaskNode.drag.test.tsx +0 -82
  88. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/GraphTaskNode.test.tsx +0 -307
  89. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/GraphToolbar.test.tsx +0 -60
  90. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/edges.test.tsx +0 -75
  91. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/filtering.test.tsx +0 -62
  92. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/filters.test.ts +0 -78
  93. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/graphPositionStorage.test.ts +0 -95
  94. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/host-integration.test.ts +0 -74
  95. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/index.test.ts +0 -58
  96. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/interactions.test.tsx +0 -121
  97. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/layout.test.ts +0 -70
  98. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/persistence.test.tsx +0 -89
  99. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useGraphData.test.ts +0 -86
  100. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useGraphInteraction.test.ts +0 -167
  101. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useGraphPositions.test.ts +0 -66
  102. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useNodeDrag.test.ts +0 -81
  103. package/dist/plugins/fusion-plugin-dependency-graph/src/dashboard-interop.d.ts +0 -35
  104. package/dist/plugins/fusion-plugin-dependency-graph/src/dashboard-view.tsx +0 -19
  105. package/dist/plugins/fusion-plugin-dependency-graph/src/edges.tsx +0 -70
  106. package/dist/plugins/fusion-plugin-dependency-graph/src/filters.ts +0 -8
  107. package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/__tests__/useDependencyChain.test.ts +0 -53
  108. package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/useDependencyChain.ts +0 -60
  109. package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/useGraphPositions.ts +0 -45
  110. package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/useNodeDrag.ts +0 -114
  111. package/dist/plugins/fusion-plugin-dependency-graph/src/index.ts +0 -24
  112. package/dist/plugins/fusion-plugin-dependency-graph/src/layout.ts +0 -91
  113. package/dist/plugins/fusion-plugin-dependency-graph/src/styles/drag.css +0 -15
  114. package/dist/plugins/fusion-plugin-dependency-graph/src/types.ts +0 -21
  115. package/dist/plugins/fusion-plugin-dependency-graph/src/useGraphData.ts +0 -17
  116. package/dist/plugins/fusion-plugin-dependency-graph/src/useGraphInteraction.ts +0 -292
  117. package/dist/plugins/fusion-plugin-dependency-graph/src/utils/graphPositionStorage.ts +0 -65
  118. package/dist/plugins/fusion-plugin-roadmap/src/__tests__/api-client.test.ts +0 -101
  119. package/dist/plugins/fusion-plugin-roadmap/src/__tests__/index.test.ts +0 -92
  120. package/dist/plugins/fusion-plugin-roadmap/src/__tests__/roadmap-routes.test.ts +0 -48
  121. package/dist/plugins/fusion-plugin-roadmap/src/__tests__/roadmap-suggestions.test.ts +0 -31
  122. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/RoadmapsView.tsx +0 -2559
  123. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/__tests__/RoadmapsView.test.tsx +0 -1144
  124. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/__tests__/useRoadmaps.test.ts +0 -1756
  125. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/api.ts +0 -70
  126. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/test-setup.ts +0 -7
  127. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/types.ts +0 -1
  128. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/useConfirm.ts +0 -8
  129. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/useRoadmaps.ts +0 -1188
  130. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/useViewportMode.ts +0 -20
  131. package/dist/plugins/fusion-plugin-roadmap/src/dashboard-view.tsx +0 -6
  132. package/dist/plugins/fusion-plugin-roadmap/src/index.ts +0 -74
  133. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-routes.ts +0 -1
  134. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-schema.ts +0 -41
  135. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-suggestions.d.ts +0 -15
  136. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-suggestions.ts +0 -15
  137. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.d.ts +0 -283
  138. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.d.ts.map +0 -1
  139. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.js +0 -21
  140. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.js.map +0 -1
  141. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.ts +0 -310
  142. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.d.ts +0 -5
  143. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.d.ts.map +0 -1
  144. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.js +0 -361
  145. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.js.map +0 -1
  146. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.ts +0 -408
  147. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.d.ts +0 -68
  148. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.d.ts.map +0 -1
  149. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.js +0 -300
  150. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.js.map +0 -1
  151. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.ts +0 -381
  152. package/dist/plugins/fusion-plugin-roadmap/src/server/index.d.ts +0 -3
  153. package/dist/plugins/fusion-plugin-roadmap/src/server/index.ts +0 -1
  154. package/dist/plugins/fusion-plugin-roadmap/src/store/__tests__/roadmap-handoff.test.ts +0 -445
  155. package/dist/plugins/fusion-plugin-roadmap/src/store/__tests__/roadmap-ordering.test.ts +0 -334
  156. package/dist/plugins/fusion-plugin-roadmap/src/store/__tests__/roadmap-store.test.ts +0 -1318
  157. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-handoff.ts +0 -163
  158. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.d.ts +0 -37
  159. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.d.ts.map +0 -1
  160. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.js +0 -188
  161. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.js.map +0 -1
  162. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.ts +0 -311
  163. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.d.ts +0 -299
  164. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.d.ts.map +0 -1
  165. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.js +0 -765
  166. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.js.map +0 -1
  167. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.ts +0 -1001
@@ -1,9 +1,9 @@
1
- // ../plugin-sdk/dist/index.js
1
+ // ../plugin-sdk/src/index.ts
2
2
  function definePlugin(plugin2) {
3
3
  return plugin2;
4
4
  }
5
5
 
6
- // ../../plugins/fusion-plugin-paperclip-runtime/dist/paperclip-client.js
6
+ // ../../plugins/fusion-plugin-paperclip-runtime/src/paperclip-client.ts
7
7
  var ConflictError = class extends Error {
8
8
  status = 409;
9
9
  constructor(message) {
@@ -38,19 +38,18 @@ async function parseJsonBody(response) {
38
38
  try {
39
39
  return { value: JSON.parse(raw), raw };
40
40
  } catch {
41
- throw new Error(`Paperclip API ${response.status} ${response.statusText}: invalid JSON response body`);
41
+ throw new Error(
42
+ `Paperclip API ${response.status} ${response.statusText}: invalid JSON response body`
43
+ );
42
44
  }
43
45
  }
44
46
  function toErrorMessage(status, statusText, body, raw) {
45
47
  if (body && typeof body === "object") {
46
48
  const b = body;
47
- if (typeof b.error === "string")
48
- return b.error;
49
- if (typeof b.message === "string")
50
- return b.message;
49
+ if (typeof b.error === "string") return b.error;
50
+ if (typeof b.message === "string") return b.message;
51
51
  }
52
- if (raw.trim() !== "")
53
- return raw.slice(0, 200).trim();
52
+ if (raw.trim() !== "") return raw.slice(0, 200).trim();
54
53
  return `${status} ${statusText}`.trim();
55
54
  }
56
55
  async function request(apiUrl, path, options) {
@@ -73,8 +72,7 @@ async function request(apiUrl, path, options) {
73
72
  if (!response.ok) {
74
73
  const msg = toErrorMessage(response.status, response.statusText, value, raw);
75
74
  const full = `Paperclip API ${response.status} (${method} ${path}): ${msg}`;
76
- if (response.status === 409)
77
- throw new ConflictError(full);
75
+ if (response.status === 409) throw new ConflictError(full);
78
76
  throw new Error(full);
79
77
  }
80
78
  return value;
@@ -84,7 +82,9 @@ function getSettingString(settings, key) {
84
82
  return typeof v === "string" && v.trim() !== "" ? v.trim() : void 0;
85
83
  }
86
84
  function resolvePaperclipConfig(settings) {
87
- const apiUrl = normalizeApiUrl(getSettingString(settings, "apiUrl") ?? process.env.PAPERCLIP_API_URL?.trim() ?? "http://localhost:3100");
85
+ const apiUrl = normalizeApiUrl(
86
+ getSettingString(settings, "apiUrl") ?? process.env.PAPERCLIP_API_URL?.trim() ?? "http://localhost:3100"
87
+ );
88
88
  const apiKey = getSettingString(settings, "apiKey") ?? (process.env.PAPERCLIP_API_KEY?.trim() || void 0);
89
89
  const agentId = getSettingString(settings, "agentId") ?? process.env.PAPERCLIP_AGENT_ID?.trim() ?? void 0;
90
90
  const companyId = getSettingString(settings, "companyId") ?? process.env.PAPERCLIP_COMPANY_ID?.trim() ?? void 0;
@@ -96,9 +96,18 @@ function resolvePaperclipConfig(settings) {
96
96
  const parentIssueId = getSettingString(settings, "parentIssueId") ?? process.env.PAPERCLIP_PARENT_ISSUE_ID?.trim() ?? void 0;
97
97
  const projectId = getSettingString(settings, "projectId") ?? process.env.PAPERCLIP_PROJECT_ID?.trim() ?? void 0;
98
98
  const goalId = getSettingString(settings, "goalId") ?? process.env.PAPERCLIP_GOAL_ID?.trim() ?? void 0;
99
- const runTimeoutMs = parseInt(getSettingString(settings, "runTimeoutMs") ?? process.env.PAPERCLIP_RUN_TIMEOUT_MS ?? "600000", 10);
100
- const pollIntervalMs = parseInt(getSettingString(settings, "pollIntervalMs") ?? process.env.PAPERCLIP_POLL_INTERVAL_MS ?? "500", 10);
101
- const pollIntervalMaxMs = parseInt(getSettingString(settings, "pollIntervalMaxMs") ?? process.env.PAPERCLIP_POLL_INTERVAL_MAX_MS ?? "2000", 10);
99
+ const runTimeoutMs = parseInt(
100
+ getSettingString(settings, "runTimeoutMs") ?? process.env.PAPERCLIP_RUN_TIMEOUT_MS ?? "600000",
101
+ 10
102
+ );
103
+ const pollIntervalMs = parseInt(
104
+ getSettingString(settings, "pollIntervalMs") ?? process.env.PAPERCLIP_POLL_INTERVAL_MS ?? "500",
105
+ 10
106
+ );
107
+ const pollIntervalMaxMs = parseInt(
108
+ getSettingString(settings, "pollIntervalMaxMs") ?? process.env.PAPERCLIP_POLL_INTERVAL_MAX_MS ?? "2000",
109
+ 10
110
+ );
102
111
  return {
103
112
  apiUrl,
104
113
  apiKey,
@@ -191,25 +200,20 @@ async function getRunEvents(apiUrl, apiKey, runId, afterSeq, limit = 100) {
191
200
  apiKey,
192
201
  query
193
202
  });
194
- if (Array.isArray(result))
195
- return result;
203
+ if (Array.isArray(result)) return result;
196
204
  const r = result;
197
- if (Array.isArray(r.events))
198
- return r.events;
205
+ if (Array.isArray(r.events)) return r.events;
199
206
  return [];
200
207
  }
201
208
  async function listCompanies(apiUrl, apiKey) {
202
209
  const raw = await request(apiUrl, "/companies", { apiKey });
203
- if (!Array.isArray(raw))
204
- return [];
210
+ if (!Array.isArray(raw)) return [];
205
211
  const out = [];
206
212
  for (const entry of raw) {
207
- if (!entry || typeof entry !== "object")
208
- continue;
213
+ if (!entry || typeof entry !== "object") continue;
209
214
  const r = entry;
210
215
  const id = typeof r.id === "string" ? r.id : void 0;
211
- if (!id)
212
- continue;
216
+ if (!id) continue;
213
217
  const name = typeof r.name === "string" ? r.name : id;
214
218
  const urlKey = typeof r.urlKey === "string" ? r.urlKey : typeof r.slug === "string" ? r.slug : void 0;
215
219
  out.push({ id, name, urlKey });
@@ -218,16 +222,13 @@ async function listCompanies(apiUrl, apiKey) {
218
222
  }
219
223
  async function listCompanyAgents(apiUrl, apiKey, companyId) {
220
224
  const raw = await request(apiUrl, `/companies/${companyId}/agents`, { apiKey });
221
- if (!Array.isArray(raw))
222
- return [];
225
+ if (!Array.isArray(raw)) return [];
223
226
  const out = [];
224
227
  for (const entry of raw) {
225
- if (!entry || typeof entry !== "object")
226
- continue;
228
+ if (!entry || typeof entry !== "object") continue;
227
229
  const r = entry;
228
230
  const id = typeof r.id === "string" ? r.id : void 0;
229
- if (!id)
230
- continue;
231
+ if (!id) continue;
231
232
  const name = typeof r.name === "string" ? r.name : id;
232
233
  const role = typeof r.role === "string" ? r.role : void 0;
233
234
  const cId = typeof r.companyId === "string" ? r.companyId : companyId;
@@ -337,7 +338,11 @@ async function mintAgentApiKeyViaCli(opts) {
337
338
  } catch (err) {
338
339
  const code = err.code;
339
340
  if (code === "ENOENT") {
340
- reject(new Error(`paperclipai binary not found at ${bin}; install via \`npm i -g paperclipai\``));
341
+ reject(
342
+ new Error(
343
+ `paperclipai binary not found at ${bin}; install via \`npm i -g paperclipai\``
344
+ )
345
+ );
341
346
  } else {
342
347
  reject(err instanceof Error ? err : new Error(String(err)));
343
348
  }
@@ -358,22 +363,24 @@ async function mintAgentApiKeyViaCli(opts) {
358
363
  const lines = chunk.toString("utf-8").split("\n");
359
364
  for (const line of lines) {
360
365
  const stripped = stripAnsi(line).trim();
361
- if (stripped)
362
- stderrLines.push(stripped);
366
+ if (stripped) stderrLines.push(stripped);
363
367
  }
364
368
  });
365
369
  child.on("error", (err) => {
366
370
  clearTimeout(timer);
367
371
  if (err.code === "ENOENT") {
368
- reject(new Error(`paperclipai binary not found at ${bin}; install via \`npm i -g paperclipai\``));
372
+ reject(
373
+ new Error(
374
+ `paperclipai binary not found at ${bin}; install via \`npm i -g paperclipai\``
375
+ )
376
+ );
369
377
  } else {
370
378
  reject(err);
371
379
  }
372
380
  });
373
381
  child.on("close", (code) => {
374
382
  clearTimeout(timer);
375
- if (killed)
376
- return;
383
+ if (killed) return;
377
384
  const rawStdout = Buffer.concat(stdoutChunks).toString("utf-8");
378
385
  const cleanedStdout = stripAnsi(rawStdout).trim();
379
386
  if (code !== 0) {
@@ -385,20 +392,30 @@ async function mintAgentApiKeyViaCli(opts) {
385
392
  }
386
393
  if (!cleanedStdout) {
387
394
  const hint = "run `paperclipai onboard` to authenticate the CLI";
388
- reject(new Error(`paperclipai agent local-cli produced no output \u2014 ${hint}`));
395
+ reject(
396
+ new Error(`paperclipai agent local-cli produced no output \u2014 ${hint}`)
397
+ );
389
398
  return;
390
399
  }
391
400
  let parsed;
392
401
  try {
393
402
  parsed = JSON.parse(cleanedStdout);
394
403
  } catch {
395
- reject(new Error(`paperclipai agent local-cli returned non-JSON output: ${cleanedStdout.slice(0, 200)}`));
404
+ reject(
405
+ new Error(
406
+ `paperclipai agent local-cli returned non-JSON output: ${cleanedStdout.slice(0, 200)}`
407
+ )
408
+ );
396
409
  return;
397
410
  }
398
411
  const r = parsed;
399
412
  const apiKey = (typeof r.apiKey === "string" ? r.apiKey : void 0) ?? (typeof r.api_key === "string" ? r.api_key : void 0) ?? (typeof r.token === "string" ? r.token : void 0);
400
413
  if (!apiKey) {
401
- reject(new Error(`paperclipai agent local-cli JSON missing apiKey/api_key/token field: ${cleanedStdout.slice(0, 200)}`));
414
+ reject(
415
+ new Error(
416
+ `paperclipai agent local-cli JSON missing apiKey/api_key/token field: ${cleanedStdout.slice(0, 200)}`
417
+ )
418
+ );
402
419
  return;
403
420
  }
404
421
  const apiBase = (typeof r.apiBase === "string" ? r.apiBase : void 0) ?? (typeof r.api_base === "string" ? r.api_base : void 0);
@@ -411,7 +428,9 @@ async function mintAgentApiKeyViaCli(opts) {
411
428
  function remapSpawnError(err, bin) {
412
429
  const code = err?.code;
413
430
  if (code === "ENOENT") {
414
- return new Error(`paperclipai binary not found at ${bin}; install via \`npm i -g paperclipai\``);
431
+ return new Error(
432
+ `paperclipai binary not found at ${bin}; install via \`npm i -g paperclipai\``
433
+ );
415
434
  }
416
435
  return err instanceof Error ? err : new Error(String(err));
417
436
  }
@@ -447,8 +466,7 @@ async function spawnPaperclipCliJson(args, opts) {
447
466
  const lines = chunk.toString("utf-8").split("\n");
448
467
  for (const line of lines) {
449
468
  const stripped = stripAnsi(line).trim();
450
- if (stripped)
451
- stderrLines.push(stripped);
469
+ if (stripped) stderrLines.push(stripped);
452
470
  }
453
471
  });
454
472
  child.on("error", (err) => {
@@ -457,12 +475,17 @@ async function spawnPaperclipCliJson(args, opts) {
457
475
  });
458
476
  child.on("close", (code) => {
459
477
  clearTimeout(timer);
460
- if (killed)
461
- return;
462
- const cleaned = stripAnsi(Buffer.concat(stdoutChunks).toString("utf-8")).trim();
478
+ if (killed) return;
479
+ const cleaned = stripAnsi(
480
+ Buffer.concat(stdoutChunks).toString("utf-8")
481
+ ).trim();
463
482
  if (code !== 0) {
464
483
  const lastErr = stderrLines.filter(Boolean).pop() ?? "";
465
- reject(new Error(lastErr ? `${label} exited ${code}: ${lastErr}` : `${label} exited ${code}`));
484
+ reject(
485
+ new Error(
486
+ lastErr ? `${label} exited ${code}: ${lastErr}` : `${label} exited ${code}`
487
+ )
488
+ );
466
489
  return;
467
490
  }
468
491
  if (!cleaned) {
@@ -472,23 +495,22 @@ async function spawnPaperclipCliJson(args, opts) {
472
495
  try {
473
496
  resolve(JSON.parse(cleaned));
474
497
  } catch {
475
- reject(new Error(`${label} returned non-JSON output: ${cleaned.slice(0, 200)}`));
498
+ reject(
499
+ new Error(`${label} returned non-JSON output: ${cleaned.slice(0, 200)}`)
500
+ );
476
501
  }
477
502
  });
478
503
  });
479
504
  }
480
505
  async function listCompaniesViaCli(opts) {
481
506
  const raw = await spawnPaperclipCliJson(["company", "list"], opts);
482
- if (!Array.isArray(raw))
483
- return [];
507
+ if (!Array.isArray(raw)) return [];
484
508
  const out = [];
485
509
  for (const entry of raw) {
486
- if (!entry || typeof entry !== "object")
487
- continue;
510
+ if (!entry || typeof entry !== "object") continue;
488
511
  const r = entry;
489
512
  const id = typeof r.id === "string" ? r.id : void 0;
490
- if (!id)
491
- continue;
513
+ if (!id) continue;
492
514
  const name = typeof r.name === "string" ? r.name : id;
493
515
  const urlKey = typeof r.urlKey === "string" ? r.urlKey : typeof r.slug === "string" ? r.slug : void 0;
494
516
  out.push({ id, name, urlKey });
@@ -496,17 +518,17 @@ async function listCompaniesViaCli(opts) {
496
518
  return out;
497
519
  }
498
520
  async function listCompanyAgentsViaCli(opts) {
499
- const raw = await spawnPaperclipCliJson(["agent", "list", "--company-id", opts.companyId], opts);
500
- if (!Array.isArray(raw))
501
- return [];
521
+ const raw = await spawnPaperclipCliJson(
522
+ ["agent", "list", "--company-id", opts.companyId],
523
+ opts
524
+ );
525
+ if (!Array.isArray(raw)) return [];
502
526
  const out = [];
503
527
  for (const entry of raw) {
504
- if (!entry || typeof entry !== "object")
505
- continue;
528
+ if (!entry || typeof entry !== "object") continue;
506
529
  const r = entry;
507
530
  const id = typeof r.id === "string" ? r.id : void 0;
508
- if (!id)
509
- continue;
531
+ if (!id) continue;
510
532
  const name = typeof r.name === "string" ? r.name : id;
511
533
  const role = typeof r.role === "string" ? r.role : void 0;
512
534
  const cId = typeof r.companyId === "string" ? r.companyId : opts.companyId;
@@ -518,40 +540,49 @@ async function listCompanyAgentsViaCli(opts) {
518
540
  async function createIssueViaCli(opts) {
519
541
  const args = ["issue", "create", "--company-id", opts.companyId];
520
542
  args.push("--title", opts.body.title);
521
- if (opts.body.description)
522
- args.push("--description", opts.body.description);
523
- if (opts.body.status)
524
- args.push("--status", opts.body.status);
543
+ if (opts.body.description) args.push("--description", opts.body.description);
544
+ if (opts.body.status) args.push("--status", opts.body.status);
525
545
  if (opts.body.assigneeAgentId)
526
546
  args.push("--assignee-agent-id", opts.body.assigneeAgentId);
527
- if (opts.body.parentId)
528
- args.push("--parent-id", opts.body.parentId);
529
- if (opts.body.projectId)
530
- args.push("--project-id", opts.body.projectId);
531
- if (opts.body.goalId)
532
- args.push("--goal-id", opts.body.goalId);
547
+ if (opts.body.parentId) args.push("--parent-id", opts.body.parentId);
548
+ if (opts.body.projectId) args.push("--project-id", opts.body.projectId);
549
+ if (opts.body.goalId) args.push("--goal-id", opts.body.goalId);
533
550
  const raw = await spawnPaperclipCliJson(args, opts);
534
551
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
535
- throw new Error(`paperclipai issue create returned unexpected payload: ${JSON.stringify(raw).slice(0, 200)}`);
552
+ throw new Error(
553
+ `paperclipai issue create returned unexpected payload: ${JSON.stringify(raw).slice(0, 200)}`
554
+ );
536
555
  }
537
556
  return raw;
538
557
  }
539
558
  async function getIssueViaCli(opts) {
540
- const raw = await spawnPaperclipCliJson(["issue", "get", opts.issueId], opts);
559
+ const raw = await spawnPaperclipCliJson(
560
+ ["issue", "get", opts.issueId],
561
+ opts
562
+ );
541
563
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
542
- throw new Error(`paperclipai issue get returned unexpected payload: ${JSON.stringify(raw).slice(0, 200)}`);
564
+ throw new Error(
565
+ `paperclipai issue get returned unexpected payload: ${JSON.stringify(raw).slice(0, 200)}`
566
+ );
543
567
  }
544
568
  return raw;
545
569
  }
546
570
  async function agentsMeViaCli(opts) {
547
- const raw = await spawnPaperclipCliJson(["agent", "get", opts.agentId], opts);
571
+ const raw = await spawnPaperclipCliJson(
572
+ ["agent", "get", opts.agentId],
573
+ opts
574
+ );
548
575
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
549
- throw new Error(`paperclipai agent get returned unexpected payload: ${JSON.stringify(raw).slice(0, 200)}`);
576
+ throw new Error(
577
+ `paperclipai agent get returned unexpected payload: ${JSON.stringify(raw).slice(0, 200)}`
578
+ );
550
579
  }
551
580
  const id = typeof raw.id === "string" ? raw.id : void 0;
552
581
  const cId = typeof raw.companyId === "string" ? raw.companyId : void 0;
553
582
  if (!id || !cId) {
554
- throw new Error("paperclipai agent get returned a response missing `id` or `companyId`");
583
+ throw new Error(
584
+ "paperclipai agent get returned a response missing `id` or `companyId`"
585
+ );
555
586
  }
556
587
  return {
557
588
  agentId: id,
@@ -566,8 +597,7 @@ async function probePaperclipViaCli(opts) {
566
597
  let apiUrl = "(via paperclipai CLI)";
567
598
  try {
568
599
  const disc = await discoverPaperclipCliConfig({ configPath: opts.cliConfigPath });
569
- if (disc.ok)
570
- apiUrl = disc.apiUrl;
600
+ if (disc.ok) apiUrl = disc.apiUrl;
571
601
  } catch {
572
602
  }
573
603
  try {
@@ -583,7 +613,7 @@ async function probePaperclipViaCli(opts) {
583
613
  }
584
614
  }
585
615
 
586
- // ../../plugins/fusion-plugin-paperclip-runtime/dist/runtime-adapter.js
616
+ // ../../plugins/fusion-plugin-paperclip-runtime/src/runtime-adapter.ts
587
617
  import { randomUUID } from "node:crypto";
588
618
  var TERMINAL_RUN_STATUSES = /* @__PURE__ */ new Set([
589
619
  "succeeded",
@@ -623,8 +653,7 @@ function pickIssueId(issue) {
623
653
  return issueId;
624
654
  }
625
655
  function normalizeMode(mode) {
626
- if (mode && VALID_MODES.has(mode))
627
- return mode;
656
+ if (mode && VALID_MODES.has(mode)) return mode;
628
657
  return "rolling-issue";
629
658
  }
630
659
  var PaperclipRuntimeAdapter = class {
@@ -633,7 +662,9 @@ var PaperclipRuntimeAdapter = class {
633
662
  config;
634
663
  logger;
635
664
  constructor(config, logger) {
636
- const resolved = resolvePaperclipConfig(config);
665
+ const resolved = resolvePaperclipConfig(
666
+ config
667
+ );
637
668
  this.config = {
638
669
  ...resolved,
639
670
  mode: normalizeMode(resolved.mode),
@@ -649,13 +680,17 @@ var PaperclipRuntimeAdapter = class {
649
680
  configPath: this.config.cliConfigPath
650
681
  });
651
682
  if (!discovery.ok) {
652
- throw new Error(`Paperclip CLI mode failed: ${discovery.reason} (Switch to API mode in settings if paperclipai isn't installed.)`);
683
+ throw new Error(
684
+ `Paperclip CLI mode failed: ${discovery.reason} (Switch to API mode in settings if paperclipai isn't installed.)`
685
+ );
653
686
  }
654
687
  effectiveApiUrl = discovery.apiUrl;
655
688
  if (!effectiveApiKey) {
656
689
  effectiveApiKey = discovery.apiKey;
657
690
  }
658
- this.logger.info(`Paperclip CLI mode resolved apiUrl=${effectiveApiUrl} (deploymentMode=${discovery.deploymentMode ?? "unknown"})`);
691
+ this.logger.info(
692
+ `Paperclip CLI mode resolved apiUrl=${effectiveApiUrl} (deploymentMode=${discovery.deploymentMode ?? "unknown"})`
693
+ );
659
694
  }
660
695
  let agentId = this.config.agentId;
661
696
  let companyId = this.config.companyId;
@@ -663,7 +698,9 @@ var PaperclipRuntimeAdapter = class {
663
698
  try {
664
699
  if (this.config.transport === "cli") {
665
700
  if (!agentId) {
666
- throw new Error("agentId is required in Local CLI mode (paperclipai has no `agents/me` equivalent \u2014 pick an agent in settings)");
701
+ throw new Error(
702
+ "agentId is required in Local CLI mode (paperclipai has no `agents/me` equivalent \u2014 pick an agent in settings)"
703
+ );
667
704
  }
668
705
  const me = await agentsMeViaCli({
669
706
  agentId,
@@ -678,11 +715,15 @@ var PaperclipRuntimeAdapter = class {
678
715
  }
679
716
  } catch (error) {
680
717
  const reason = error instanceof Error ? error.message : String(error);
681
- throw new Error(`Paperclip runtime could not derive agentId/companyId. Configure them explicitly or check the API key / CLI auth. Underlying error: ${reason}`);
718
+ throw new Error(
719
+ `Paperclip runtime could not derive agentId/companyId. Configure them explicitly or check the API key / CLI auth. Underlying error: ${reason}`
720
+ );
682
721
  }
683
722
  }
684
723
  if (!agentId || !companyId) {
685
- throw new Error("Paperclip runtime is missing required config: agentId or companyId. Configure plugin settings (apiUrl, apiKey, agentId, companyId) or PAPERCLIP_* env vars.");
724
+ throw new Error(
725
+ "Paperclip runtime is missing required config: agentId or companyId. Configure plugin settings (apiUrl, apiKey, agentId, companyId) or PAPERCLIP_* env vars."
726
+ );
686
727
  }
687
728
  const session = {
688
729
  apiUrl: effectiveApiUrl,
@@ -779,18 +820,15 @@ var PaperclipRuntimeAdapter = class {
779
820
  if (!finalText) {
780
821
  const comments = await getIssueComments(session.apiUrl, session.apiKey, issueId);
781
822
  const latest = pickLatestVisibleComment(comments);
782
- if (latest)
783
- finalText = latest;
823
+ if (latest) finalText = latest;
784
824
  }
785
825
  } catch (error) {
786
826
  const reason = error instanceof Error ? error.message : String(error);
787
827
  this.logger.warn(`Paperclip post-run fetch failed: ${reason}`);
788
828
  }
789
829
  }
790
- if (finalText)
791
- session.onText?.(finalText);
792
- if (stream.thinking)
793
- session.onThinking?.(stream.thinking);
830
+ if (finalText) session.onText?.(finalText);
831
+ if (stream.thinking) session.onThinking?.(stream.thinking);
794
832
  const isError = stream.runStatus === "failed" || stream.runStatus === "timed_out";
795
833
  session.onToolEnd?.("paperclip.run", isError || stream.timedOutLocally, {
796
834
  runId,
@@ -838,24 +876,27 @@ var PaperclipRuntimeAdapter = class {
838
876
  while (true) {
839
877
  let events = [];
840
878
  try {
841
- events = await getRunEvents(session.apiUrl, session.apiKey, runId, afterSeq, 200);
879
+ events = await getRunEvents(
880
+ session.apiUrl,
881
+ session.apiKey,
882
+ runId,
883
+ afterSeq,
884
+ 200
885
+ );
842
886
  } catch (error) {
843
887
  const reason = error instanceof Error ? error.message : String(error);
844
888
  this.logger.warn(`Paperclip getRunEvents failed: ${reason}`);
845
889
  }
846
890
  for (const ev of events) {
847
- if (typeof ev.seq === "number" && ev.seq > afterSeq)
848
- afterSeq = ev.seq;
891
+ if (typeof ev.seq === "number" && ev.seq > afterSeq) afterSeq = ev.seq;
849
892
  const type = ev.type ?? "";
850
893
  const payload = ev.payload ?? {};
851
894
  if (type === "heartbeat.run.status") {
852
895
  const next = asString(payload.status);
853
- if (next)
854
- runStatus = next;
896
+ if (next) runStatus = next;
855
897
  } else if (type === "heartbeat.run.log") {
856
898
  const chunk = asString(payload.chunk) ?? "";
857
- if (!chunk)
858
- continue;
899
+ if (!chunk) continue;
859
900
  if (payload.stream === "stdout") {
860
901
  textBuf += chunk;
861
902
  session.onText?.(chunk);
@@ -867,11 +908,12 @@ var PaperclipRuntimeAdapter = class {
867
908
  }
868
909
  }
869
910
  }
870
- if (TERMINAL_RUN_STATUSES.has(runStatus))
871
- break;
911
+ if (TERMINAL_RUN_STATUSES.has(runStatus)) break;
872
912
  if (Date.now() - startedAt > session.runTimeoutMs) {
873
913
  timedOutLocally = true;
874
- this.logger.warn(`Paperclip run ${runId} exceeded local runTimeoutMs=${session.runTimeoutMs}; abandoning poll. Run continues server-side.`);
914
+ this.logger.warn(
915
+ `Paperclip run ${runId} exceeded local runTimeoutMs=${session.runTimeoutMs}; abandoning poll. Run continues server-side.`
916
+ );
875
917
  break;
876
918
  }
877
919
  await sleep(interval);
@@ -884,19 +926,21 @@ function pickLatestVisibleComment(comments) {
884
926
  for (let i = comments.length - 1; i >= 0; i--) {
885
927
  const c = comments[i];
886
928
  const body = asString(c.body)?.trim();
887
- if (body)
888
- return body;
929
+ if (body) return body;
889
930
  }
890
931
  return void 0;
891
932
  }
892
933
 
893
- // ../../plugins/fusion-plugin-paperclip-runtime/dist/index.js
934
+ // ../../plugins/fusion-plugin-paperclip-runtime/src/index.ts
894
935
  function getSettingsConfig(settings) {
895
936
  return resolvePaperclipConfig(settings ?? {});
896
937
  }
897
938
  async function paperclipRuntimeFactory(ctx) {
898
939
  const config = getSettingsConfig(ctx.settings);
899
- return new PaperclipRuntimeAdapter(config, ctx.logger);
940
+ return new PaperclipRuntimeAdapter(
941
+ config,
942
+ ctx.logger
943
+ );
900
944
  }
901
945
  var paperclipRuntime = {
902
946
  metadata: {
@@ -936,7 +980,9 @@ var plugin = definePlugin({
936
980
  });
937
981
  if (status.available) {
938
982
  const ident = status.identity;
939
- ctx.logger.info(ident ? `Paperclip reachable as ${ident.agentName} (${ident.role ?? "agent"}) at ${ident.companyName ?? ident.companyId}` : `Paperclip reachable at ${config.apiUrl}`);
983
+ ctx.logger.info(
984
+ ident ? `Paperclip reachable as ${ident.agentName} (${ident.role ?? "agent"}) at ${ident.companyName ?? ident.companyId}` : `Paperclip reachable at ${config.apiUrl}`
985
+ );
940
986
  } else {
941
987
  ctx.logger.warn(`Paperclip probe failed: ${status.reason ?? "unknown"}`);
942
988
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion-plugin-examples/paperclip-runtime",
3
- "version": "0.2.32",
3
+ "version": "0.2.34",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion-plugin-examples/reports",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "description": "Reports plugin for Fusion",
6
6
  "private": true,
@@ -1,7 +1,10 @@
1
1
  import type { PluginContext } from "@fusion/core";
2
2
  import { definePlugin } from "@fusion/plugin-sdk";
3
3
  import { runReviewPanel } from "./review-panel.js";
4
+ import { ensureReportSchema } from "./report-schema.js";
4
5
  import type { CombinedReview, ReviewPanelMember, RunReviewPanelInput } from "./review-types.js";
6
+ import type { ReportCadence, ReportCreateInput } from "./store/report-types.js";
7
+ import { ReportStore } from "./store/report-store.js";
5
8
  import { settingsSchema } from "./settings.js";
6
9
 
7
10
  const plugin = definePlugin({
@@ -15,7 +18,9 @@ const plugin = definePlugin({
15
18
  settingsSchema,
16
19
  },
17
20
  state: "installed",
18
- hooks: {},
21
+ hooks: {
22
+ onSchemaInit: ensureReportSchema,
23
+ },
19
24
  });
20
25
 
21
26
  export interface RunGeneratedReportReviewInput {
@@ -25,13 +30,51 @@ export interface RunGeneratedReportReviewInput {
25
30
  cwd: string;
26
31
  }
27
32
 
33
+ const reportStoreCache = new WeakMap<object, ReportStore>();
34
+
35
+ export function getReportStore(ctx: PluginContext): ReportStore {
36
+ const key = ctx.taskStore as object;
37
+ const cached = reportStoreCache.get(key);
38
+ if (cached) return cached;
39
+
40
+ const store = new ReportStore(ctx.taskStore.getDatabase());
41
+ reportStoreCache.set(key, store);
42
+ return store;
43
+ }
44
+
45
+ function toCadence(cadence: RunReviewPanelInput["reportMetadata"]["cadence"]): ReportCadence {
46
+ return cadence;
47
+ }
48
+
28
49
  export async function runGeneratedReportReview(input: RunGeneratedReportReviewInput, ctx: PluginContext): Promise<CombinedReview> {
29
- return runReviewPanel({
50
+ const store = getReportStore(ctx);
51
+ const reportInput: ReportCreateInput = {
52
+ cadence: toCadence(input.reportMetadata.cadence),
53
+ periodStart: input.reportMetadata.periodStart,
54
+ periodEnd: input.reportMetadata.periodEnd,
55
+ title: `Generated ${input.reportMetadata.cadence} report`,
56
+ draftMarkdown: input.reportDraft,
57
+ metadata: {
58
+ reportMetadata: input.reportMetadata,
59
+ source: "runGeneratedReportReview",
60
+ },
61
+ };
62
+ const report = store.createReport(reportInput);
63
+ store.setStatus(report.id, "review_pending");
64
+ store.setStatus(report.id, "review_in_progress");
65
+
66
+ const combinedReview = await runReviewPanel({
30
67
  reportDraft: input.reportDraft,
31
- reportMetadata: input.reportMetadata,
68
+ reportMetadata: {
69
+ ...input.reportMetadata,
70
+ reportId: report.id,
71
+ },
32
72
  panel: input.panel,
33
73
  cwd: input.cwd,
34
74
  }, ctx);
75
+
76
+ store.attachReview(report.id, combinedReview);
77
+ return combinedReview;
35
78
  }
36
79
 
37
80
  export default plugin;
@@ -39,3 +82,6 @@ export default plugin;
39
82
  export * from "./settings.js";
40
83
  export * from "./review-types.js";
41
84
  export * from "./review-panel.js";
85
+ export { ensureReportSchema } from "./report-schema.js";
86
+ export { ReportStore, ReportStoreError, type ReportStoreEvents } from "./store/report-store.js";
87
+ export * from "./store/report-types.js";