@bevel-software/platform-core-backend 0.30.0 → 0.32.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 (210) hide show
  1. package/agent-guide/access-control.md +49 -4
  2. package/agent-guide/html-views.md +76 -2
  3. package/dist/core/catalog-revision.js +3 -3
  4. package/dist/core/create-core-server.d.ts.map +1 -1
  5. package/dist/core/create-core-server.js +2 -1
  6. package/dist/core/create-core-server.js.map +1 -1
  7. package/dist/core/create-core-services.d.ts +7 -0
  8. package/dist/core/create-core-services.d.ts.map +1 -1
  9. package/dist/core/create-core-services.js +16 -3
  10. package/dist/core/create-core-services.js.map +1 -1
  11. package/dist/index.d.ts +1 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +1 -0
  14. package/dist/index.js.map +1 -1
  15. package/dist/modules/access/access-control.service.d.ts.map +1 -1
  16. package/dist/modules/access/access-control.service.js +1 -5
  17. package/dist/modules/access/access-control.service.js.map +1 -1
  18. package/dist/modules/access-model/index.d.ts +14 -0
  19. package/dist/modules/access-model/index.d.ts.map +1 -0
  20. package/dist/modules/access-model/index.js +13 -0
  21. package/dist/modules/access-model/index.js.map +1 -0
  22. package/dist/modules/audit/agent-audit.service.d.ts.map +1 -1
  23. package/dist/modules/audit/agent-audit.service.js +66 -6
  24. package/dist/modules/audit/agent-audit.service.js.map +1 -1
  25. package/dist/modules/audit/audit.contract.d.ts +52 -8
  26. package/dist/modules/audit/audit.contract.d.ts.map +1 -1
  27. package/dist/modules/audit/audit.contract.js +37 -1
  28. package/dist/modules/audit/audit.contract.js.map +1 -1
  29. package/dist/modules/audit/audit.routes.d.ts +1 -1
  30. package/dist/modules/audit/audit.routes.d.ts.map +1 -1
  31. package/dist/modules/audit/audit.routes.js +15 -13
  32. package/dist/modules/audit/audit.routes.js.map +1 -1
  33. package/dist/modules/audit/request-audit.d.ts +21 -10
  34. package/dist/modules/audit/request-audit.d.ts.map +1 -1
  35. package/dist/modules/audit/request-audit.js +26 -10
  36. package/dist/modules/audit/request-audit.js.map +1 -1
  37. package/dist/modules/auth/account-hooks.d.ts +4 -6
  38. package/dist/modules/auth/account-hooks.d.ts.map +1 -1
  39. package/dist/modules/auth/account-hooks.js +7 -17
  40. package/dist/modules/auth/account-hooks.js.map +1 -1
  41. package/dist/modules/auth/auth.service.d.ts +9 -8
  42. package/dist/modules/auth/auth.service.d.ts.map +1 -1
  43. package/dist/modules/auth/auth.service.js +19 -18
  44. package/dist/modules/auth/auth.service.js.map +1 -1
  45. package/dist/modules/database/core-schema.d.ts +43 -4
  46. package/dist/modules/database/core-schema.d.ts.map +1 -1
  47. package/dist/modules/database/core-schema.js +31 -7
  48. package/dist/modules/database/core-schema.js.map +1 -1
  49. package/dist/modules/kb-fs/index.d.ts +1 -0
  50. package/dist/modules/kb-fs/index.d.ts.map +1 -1
  51. package/dist/modules/kb-fs/index.js +1 -0
  52. package/dist/modules/kb-fs/index.js.map +1 -1
  53. package/dist/modules/kb-fs/locking-filesystem.d.ts.map +1 -1
  54. package/dist/modules/kb-fs/locking-filesystem.js +3 -12
  55. package/dist/modules/kb-fs/locking-filesystem.js.map +1 -1
  56. package/dist/modules/kb-fs/mutex.d.ts +11 -0
  57. package/dist/modules/kb-fs/mutex.d.ts.map +1 -1
  58. package/dist/modules/kb-fs/mutex.js +14 -0
  59. package/dist/modules/kb-fs/mutex.js.map +1 -1
  60. package/dist/modules/mcp/mcp-auth.middleware.d.ts +14 -0
  61. package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
  62. package/dist/modules/mcp/mcp-auth.middleware.js +4 -0
  63. package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
  64. package/dist/modules/mcp/mcp.routes.d.ts +5 -0
  65. package/dist/modules/mcp/mcp.routes.d.ts.map +1 -1
  66. package/dist/modules/mcp/mcp.routes.js +67 -0
  67. package/dist/modules/mcp/mcp.routes.js.map +1 -1
  68. package/dist/modules/mcp/mcp.service.d.ts +107 -27
  69. package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
  70. package/dist/modules/mcp/mcp.service.js +257 -50
  71. package/dist/modules/mcp/mcp.service.js.map +1 -1
  72. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts +28 -0
  73. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
  74. package/dist/modules/mcp/oauth/bevel-oauth-provider.js +166 -39
  75. package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
  76. package/dist/modules/mcp/request-context.d.ts +25 -0
  77. package/dist/modules/mcp/request-context.d.ts.map +1 -0
  78. package/dist/modules/mcp/request-context.js +11 -0
  79. package/dist/modules/mcp/request-context.js.map +1 -0
  80. package/dist/modules/mcp/shared-definitions.d.ts +56 -0
  81. package/dist/modules/mcp/shared-definitions.d.ts.map +1 -0
  82. package/dist/modules/mcp/shared-definitions.js +117 -0
  83. package/dist/modules/mcp/shared-definitions.js.map +1 -0
  84. package/dist/modules/mcp/surface-cache.d.ts +70 -0
  85. package/dist/modules/mcp/surface-cache.d.ts.map +1 -0
  86. package/dist/modules/mcp/surface-cache.js +104 -0
  87. package/dist/modules/mcp/surface-cache.js.map +1 -0
  88. package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -1
  89. package/dist/modules/tool-helpers/tool-context.js +33 -12
  90. package/dist/modules/tool-helpers/tool-context.js.map +1 -1
  91. package/dist/modules/tool-helpers/tool.contract.d.ts +8 -0
  92. package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -1
  93. package/dist/modules/tool-helpers/tool.contract.js.map +1 -1
  94. package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts.map +1 -1
  95. package/dist/modules/workflow/agent-tools/change-request-read.tools.js +3 -14
  96. package/dist/modules/workflow/agent-tools/change-request-read.tools.js.map +1 -1
  97. package/dist/modules/workflow/agent-tools/change-request-summary.d.ts +10 -1
  98. package/dist/modules/workflow/agent-tools/change-request-summary.d.ts.map +1 -1
  99. package/dist/modules/workflow/agent-tools/change-request-summary.js +2 -0
  100. package/dist/modules/workflow/agent-tools/change-request-summary.js.map +1 -1
  101. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +18 -1
  102. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
  103. package/dist/modules/workflow/agent-tools/workflow.tools.js +458 -2
  104. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
  105. package/dist/modules/workflow/change-request-hooks.d.ts +78 -0
  106. package/dist/modules/workflow/change-request-hooks.d.ts.map +1 -0
  107. package/dist/modules/workflow/change-request-hooks.js +15 -0
  108. package/dist/modules/workflow/change-request-hooks.js.map +1 -0
  109. package/dist/modules/workflow/git/git.service.d.ts +113 -4
  110. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  111. package/dist/modules/workflow/git/git.service.js +470 -106
  112. package/dist/modules/workflow/git/git.service.js.map +1 -1
  113. package/dist/modules/workflow/git/pull-request.service.d.ts +10 -0
  114. package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
  115. package/dist/modules/workflow/git/pull-request.service.js +9 -0
  116. package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
  117. package/dist/modules/workflow/read-on-branch.d.ts +35 -0
  118. package/dist/modules/workflow/read-on-branch.d.ts.map +1 -0
  119. package/dist/modules/workflow/read-on-branch.js +58 -0
  120. package/dist/modules/workflow/read-on-branch.js.map +1 -0
  121. package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
  122. package/dist/modules/workflow/workflow.routes.js +22 -41
  123. package/dist/modules/workflow/workflow.routes.js.map +1 -1
  124. package/dist/modules/workflow/workflow.service.d.ts +124 -24
  125. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  126. package/dist/modules/workflow/workflow.service.js +326 -48
  127. package/dist/modules/workflow/workflow.service.js.map +1 -1
  128. package/dist/modules/workspace/index.d.ts +2 -0
  129. package/dist/modules/workspace/index.d.ts.map +1 -1
  130. package/dist/modules/workspace/index.js +4 -0
  131. package/dist/modules/workspace/index.js.map +1 -1
  132. package/dist/shared/git.contract.d.ts +7 -0
  133. package/dist/shared/git.contract.d.ts.map +1 -1
  134. package/dist/shared/git.contract.js +9 -0
  135. package/dist/shared/git.contract.js.map +1 -1
  136. package/dist/shared/listener-seam.d.ts +34 -0
  137. package/dist/shared/listener-seam.d.ts.map +1 -0
  138. package/dist/shared/listener-seam.js +42 -0
  139. package/dist/shared/listener-seam.js.map +1 -0
  140. package/dist/shared/no-link-below.d.ts +10 -0
  141. package/dist/shared/no-link-below.d.ts.map +1 -0
  142. package/dist/shared/no-link-below.js +30 -0
  143. package/dist/shared/no-link-below.js.map +1 -0
  144. package/migrations/0018_agent_events_page.sql +11 -0
  145. package/migrations/0019_oauth_token_rotated_at.sql +7 -0
  146. package/migrations/meta/0018_snapshot.json +2429 -0
  147. package/migrations/meta/0019_snapshot.json +2435 -0
  148. package/migrations/meta/_journal.json +15 -1
  149. package/package.json +3 -3
  150. package/src/core/catalog-revision.ts +3 -3
  151. package/src/core/create-core-server.ts +2 -1
  152. package/src/core/create-core-services.ts +21 -2
  153. package/src/index.ts +7 -0
  154. package/src/modules/access/access-control.service.ts +1 -6
  155. package/src/modules/access-model/index.ts +13 -0
  156. package/src/modules/agent-guide/__tests__/agent-guide.test.ts +22 -1
  157. package/src/modules/audit/__tests__/agent-audit.service.test.ts +78 -1
  158. package/src/modules/audit/__tests__/audit.routes.test.ts +43 -5
  159. package/src/modules/audit/agent-audit.service.ts +66 -6
  160. package/src/modules/audit/audit.contract.ts +62 -10
  161. package/src/modules/audit/audit.routes.ts +14 -12
  162. package/src/modules/audit/request-audit.ts +28 -13
  163. package/src/modules/auth/__tests__/account-deactivation.test.ts +38 -2
  164. package/src/modules/auth/account-hooks.ts +13 -21
  165. package/src/modules/auth/auth.service.ts +19 -18
  166. package/src/modules/database/core-schema.ts +31 -7
  167. package/src/modules/kb-fs/__tests__/mutex.canonical.test.ts +57 -0
  168. package/src/modules/kb-fs/index.ts +1 -0
  169. package/src/modules/kb-fs/locking-filesystem.ts +3 -12
  170. package/src/modules/kb-fs/mutex.ts +16 -0
  171. package/src/modules/mcp/__tests__/bevel-oauth-provider.pg.test.ts +279 -0
  172. package/src/modules/mcp/__tests__/bevel-oauth-provider.test.ts +190 -15
  173. package/src/modules/mcp/__tests__/mcp-routes-harness.ts +7 -1
  174. package/src/modules/mcp/__tests__/mcp.routes.page.test.ts +115 -0
  175. package/src/modules/mcp/__tests__/mcp.surface-cache.test.ts +521 -0
  176. package/src/modules/mcp/__tests__/shared-definitions.test.ts +28 -0
  177. package/src/modules/mcp/__tests__/surface-cache.test.ts +127 -0
  178. package/src/modules/mcp/mcp-auth.middleware.ts +21 -0
  179. package/src/modules/mcp/mcp.routes.ts +68 -0
  180. package/src/modules/mcp/mcp.service.ts +315 -51
  181. package/src/modules/mcp/oauth/bevel-oauth-provider.ts +214 -48
  182. package/src/modules/mcp/request-context.ts +34 -0
  183. package/src/modules/mcp/shared-definitions.ts +121 -0
  184. package/src/modules/mcp/surface-cache.ts +154 -0
  185. package/src/modules/tool-helpers/tool-context.ts +37 -18
  186. package/src/modules/tool-helpers/tool.contract.ts +8 -0
  187. package/src/modules/tool-registry/__tests__/own-tool-schemas.test.ts +1 -1
  188. package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +1 -1
  189. package/src/modules/workflow/__tests__/change-request-hooks.test.ts +62 -0
  190. package/src/modules/workflow/__tests__/workflow.routes.history-read-gate.test.ts +23 -12
  191. package/src/modules/workflow/__tests__/workflow.routes.open-change-request.test.ts +79 -0
  192. package/src/modules/workflow/__tests__/workflow.service.delete-branch.test.ts +9 -1
  193. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +508 -5
  194. package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +474 -4
  195. package/src/modules/workflow/agent-tools/change-request-read.tools.ts +4 -22
  196. package/src/modules/workflow/agent-tools/change-request-summary.ts +10 -1
  197. package/src/modules/workflow/agent-tools/workflow.tools.ts +468 -1
  198. package/src/modules/workflow/change-request-hooks.ts +96 -0
  199. package/src/modules/workflow/git/__tests__/git.service.diffFileBetweenBranches.test.ts +76 -11
  200. package/src/modules/workflow/git/__tests__/git.service.mergeIntoBranch.test.ts +721 -0
  201. package/src/modules/workflow/git/git.service.ts +537 -106
  202. package/src/modules/workflow/git/pull-request.service.ts +10 -0
  203. package/src/modules/workflow/read-on-branch.ts +79 -0
  204. package/src/modules/workflow/workflow.routes.ts +21 -39
  205. package/src/modules/workflow/workflow.service.ts +390 -55
  206. package/src/modules/workspace/index.ts +11 -0
  207. package/src/shared/__tests__/no-link-below.test.ts +45 -0
  208. package/src/shared/git.contract.ts +10 -0
  209. package/src/shared/listener-seam.ts +52 -0
  210. package/src/shared/no-link-below.ts +29 -0
@@ -9,6 +9,8 @@ import type { WorkspaceService } from '../../../workspace/workspace.service.js';
9
9
  import { WorkflowHooks } from '../../workflow-hooks.js';
10
10
  import { GitService } from '../git.service.js';
11
11
  import { WorkflowValidationError, BranchNameError } from '../../../../shared/domain-errors.js';
12
+ import { GitRunError, type IGitRunner } from '../../../../shared/git.contract.js';
13
+ import { NodeGitRunner } from '../node-git-runner.js';
12
14
 
13
15
  const execFileAsync = promisify(execFile);
14
16
  const PROCESS_MAP_DIR = 'knowledge-base';
@@ -107,7 +109,7 @@ describe('GitService.diffFileBetweenBranches', () => {
107
109
  await runGit(repo, ['checkout', '-b', 'alice/edit-foo']);
108
110
  await commitFile(repo, 'Knowledge/Foo.md', 'line one\nline two\n', 'add line two');
109
111
 
110
- const diff = await svc.diffFileBetweenBranches(
112
+ const { diff } = await svc.diffFileBetweenBranches(
111
113
  workspaceId,
112
114
  'Knowledge/Foo.md',
113
115
  'current-company-state',
@@ -117,6 +119,69 @@ describe('GitService.diffFileBetweenBranches', () => {
117
119
  expect(diff).toContain('+line two');
118
120
  });
119
121
 
122
+ it('asks the caller\'s verdict at the two commits served, before the path is described at either', async () => {
123
+ const { workspaceDir, repo } = await seedWorkspace(root, workspaceId);
124
+ const svc = new GitService(stubWorkspaceService(workspaceId, workspaceDir), new WorkflowHooks(), testKbContext());
125
+ await commitFile(repo, 'Knowledge/Foo.md', 'line one\n', 'base');
126
+ await commitFile(repo, 'Docs/a.md', 'a\n', 'a folder');
127
+ const base = (await execFileAsync('git', ['rev-parse', 'HEAD'], { cwd: repo })).stdout.trim();
128
+ await runGit(repo, ['checkout', '-b', 'alice/edit-foo']);
129
+ await commitFile(repo, 'Knowledge/Foo.md', 'line one\nline two\n', 'add line two');
130
+ const tip = (await execFileAsync('git', ['rev-parse', 'HEAD'], { cwd: repo })).stdout.trim();
131
+
132
+ const asked: unknown[] = [];
133
+ // Local branches only: each side resolves to the one commit it was served from.
134
+ const sides = { from: [base], to: [tip] };
135
+ const { diff } = await svc.diffFileBetweenBranches(workspaceId, 'Knowledge/Foo.md', 'current-company-state', 'alice/edit-foo', async (s) => {
136
+ asked.push(s);
137
+ });
138
+ expect(diff).toContain('+line two');
139
+ expect(asked).toEqual([sides]);
140
+
141
+ // A folder the caller may not read is refused as unreadable, never as a folder.
142
+ const refuse = async (s: unknown): Promise<void> => {
143
+ asked.push(s);
144
+ throw new WorkflowValidationError('not yours to read');
145
+ };
146
+ await expect(svc.diffFileBetweenBranches(workspaceId, 'Docs', 'current-company-state', 'alice/edit-foo', refuse)).rejects.toThrow(/not yours to read/);
147
+ expect(asked).toEqual([sides, sides]);
148
+ });
149
+
150
+ it('fails closed when a lookup of a side\'s other tip fails for any reason but absence: no diff, the verdict never asked', async () => {
151
+ const { workspaceDir, repo } = await seedWorkspace(root, workspaceId);
152
+ await commitFile(repo, 'Knowledge/Foo.md', 'line one\n', 'base');
153
+ await runGit(repo, ['checkout', '-b', 'alice/edit-foo']);
154
+ await commitFile(repo, 'Knowledge/Foo.md', 'line one\nline two\n', 'add line two');
155
+ const inner = new NodeGitRunner();
156
+ // The secondary lookup (`refs/remotes/origin/alice/edit-foo`, absent in
157
+ // this local-only repository) fails the way a corrupt repository or a
158
+ // deadline fails — not the way an absent ref answers.
159
+ let failure: GitRunError | null = null;
160
+ const gitRunner = {
161
+ defaultTimeoutMs: inner.defaultTimeoutMs,
162
+ credentials: inner.credentials,
163
+ run: async (cwd: string, args: string[], opts?: object) => {
164
+ if (failure && args[0] === 'rev-parse' && args.includes('refs/remotes/origin/alice/edit-foo')) throw failure;
165
+ return inner.run(cwd, args, opts as never);
166
+ },
167
+ } as unknown as IGitRunner;
168
+ const svc = new GitService(stubWorkspaceService(workspaceId, workspaceDir), new WorkflowHooks(), testKbContext(), undefined, null, gitRunner);
169
+ const asked: unknown[] = [];
170
+ const authorize = async (s: unknown): Promise<void> => { asked.push(s); };
171
+ for (const f of [
172
+ new GitRunError('git rev-parse failed', { exitCode: 128, stderr: 'fatal: bad object' }),
173
+ new GitRunError('git rev-parse timed out', { timedOut: true }),
174
+ ]) {
175
+ failure = f;
176
+ await expect(svc.diffFileBetweenBranches(workspaceId, 'Knowledge/Foo.md', 'current-company-state', 'alice/edit-foo', authorize)).rejects.toBe(f);
177
+ }
178
+ expect(asked).toEqual([]);
179
+ // An absent ref is the one answer that is "no such commit": the diff goes on.
180
+ failure = null;
181
+ expect((await svc.diffFileBetweenBranches(workspaceId, 'Knowledge/Foo.md', 'current-company-state', 'alice/edit-foo', authorize)).diff).toContain('+line two');
182
+ expect(asked).toHaveLength(1);
183
+ });
184
+
120
185
  it('returns the empty string when the file is identical on both branches', async () => {
121
186
  const { workspaceDir, repo } = await seedWorkspace(root, workspaceId);
122
187
  const svc = new GitService(
@@ -130,7 +195,7 @@ describe('GitService.diffFileBetweenBranches', () => {
130
195
  // no edits to Same.md on the new branch
131
196
  await commitFile(repo, 'Knowledge/Other.md', 'sidecar\n', 'unrelated edit');
132
197
 
133
- const diff = await svc.diffFileBetweenBranches(
198
+ const { diff } = await svc.diffFileBetweenBranches(
134
199
  workspaceId,
135
200
  'Knowledge/Same.md',
136
201
  'current-company-state',
@@ -151,7 +216,7 @@ describe('GitService.diffFileBetweenBranches', () => {
151
216
  await runGit(repo, ['checkout', '-b', 'alice/cleanup']);
152
217
  await deleteFileCommit(repo, 'Knowledge/Old.md', 'remove Old.md');
153
218
 
154
- const diff = await svc.diffFileBetweenBranches(
219
+ const { diff } = await svc.diffFileBetweenBranches(
155
220
  workspaceId,
156
221
  'Knowledge/Old.md',
157
222
  'current-company-state',
@@ -173,7 +238,7 @@ describe('GitService.diffFileBetweenBranches', () => {
173
238
  await runGit(repo, ['checkout', '-b', 'alice/add-new']);
174
239
  await commitFile(repo, 'Knowledge/New.md', 'brand new\n', 'add New.md');
175
240
 
176
- const diff = await svc.diffFileBetweenBranches(
241
+ const { diff } = await svc.diffFileBetweenBranches(
177
242
  workspaceId,
178
243
  'Knowledge/New.md',
179
244
  'current-company-state',
@@ -211,7 +276,7 @@ describe('GitService.diffFileBetweenBranches', () => {
211
276
  testKbContext(),
212
277
  );
213
278
 
214
- const diff = await svc.diffFileBetweenBranches(
279
+ const { diff } = await svc.diffFileBetweenBranches(
215
280
  workspaceId,
216
281
  'Knowledge/Foo.md',
217
282
  'current-company-state',
@@ -240,7 +305,7 @@ describe('GitService.diffFileBetweenBranches', () => {
240
305
  await runGit(repo, ['checkout', '-b', 'alice/edit-foo']);
241
306
  await commitFile(repo, 'Knowledge/Foo.md', 'baseline\nedit\n', 'edit');
242
307
 
243
- const diff = await svc.diffFileBetweenBranches(
308
+ const { diff } = await svc.diffFileBetweenBranches(
244
309
  workspaceId,
245
310
  'knowledge-base/Knowledge/Foo.md',
246
311
  'current-company-state',
@@ -267,7 +332,7 @@ describe('GitService.diffFileBetweenBranches', () => {
267
332
  // and pressing save before sharing.
268
333
  await writeFile(repo, 'Knowledge/Foo.md', 'baseline\nfresh edit\n');
269
334
 
270
- const diff = await svc.diffFileBetweenBranches(
335
+ const { diff } = await svc.diffFileBetweenBranches(
271
336
  workspaceId,
272
337
  'Knowledge/Foo.md',
273
338
  'current-company-state',
@@ -291,7 +356,7 @@ describe('GitService.diffFileBetweenBranches', () => {
291
356
  // Brand-new file, never committed — only on disk.
292
357
  await writeFile(repo, 'Knowledge/Brandnew.md', 'fresh content\n');
293
358
 
294
- const diff = await svc.diffFileBetweenBranches(
359
+ const { diff } = await svc.diffFileBetweenBranches(
295
360
  workspaceId,
296
361
  'Knowledge/Brandnew.md',
297
362
  'current-company-state',
@@ -313,7 +378,7 @@ describe('GitService.diffFileBetweenBranches', () => {
313
378
  await runGit(repo, ['checkout', '-b', 'alice/draft']);
314
379
  await writeFile(repo, 'Knowledge/Brandnew.md', 'fresh content\n');
315
380
 
316
- const diff = await svc.diffFileBetweenBranches(
381
+ const { diff } = await svc.diffFileBetweenBranches(
317
382
  workspaceId,
318
383
  'Knowledge/Brandnew.md',
319
384
  'alice/draft',
@@ -339,7 +404,7 @@ describe('GitService.diffFileBetweenBranches', () => {
339
404
  // side. Lines added on current-company-state — i.e. the *removal* of
340
405
  // "draft edit" — should appear as `+` on the to side, and "draft edit"
341
406
  // should appear as `-`.
342
- const diff = await svc.diffFileBetweenBranches(
407
+ const { diff } = await svc.diffFileBetweenBranches(
343
408
  workspaceId,
344
409
  'Knowledge/Foo.md',
345
410
  'alice/edit-foo',
@@ -443,7 +508,7 @@ describe('GitService.diffFileBetweenBranches', () => {
443
508
  await writeFile(repo, relPath, 'base content\nfeature edit\n');
444
509
  await svc.commitFile(workspaceId, user, relPath, 'feature edit');
445
510
 
446
- const diff = await svc.diffFileBetweenBranches(
511
+ const { diff } = await svc.diffFileBetweenBranches(
447
512
  workspaceId,
448
513
  relPath,
449
514
  'current-company-state',