@bevel-software/platform-core-backend 0.28.1 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent-guide/access-control.md +15 -0
- package/agent-guide/skills.md +8 -0
- package/dist/__tests__/test-repositories.d.ts +3 -0
- package/dist/__tests__/test-repositories.d.ts.map +1 -0
- package/dist/__tests__/test-repositories.js +18 -0
- package/dist/__tests__/test-repositories.js.map +1 -0
- package/dist/core/catalog-revision.d.ts.map +1 -1
- package/dist/core/catalog-revision.js +4 -2
- package/dist/core/catalog-revision.js.map +1 -1
- package/dist/core/compose-embed.d.ts +35 -0
- package/dist/core/compose-embed.d.ts.map +1 -0
- package/dist/core/compose-embed.js +14 -0
- package/dist/core/compose-embed.js.map +1 -0
- package/dist/core/core-ports.d.ts +10 -0
- package/dist/core/core-ports.d.ts.map +1 -1
- package/dist/core/core-ports.js.map +1 -1
- package/dist/core/create-core-server.d.ts.map +1 -1
- package/dist/core/create-core-server.js +8 -2
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +4 -1
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +57 -18
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/core/lifecycle.d.ts +19 -6
- package/dist/core/lifecycle.d.ts.map +1 -1
- package/dist/core/lifecycle.js +17 -6
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/modules/access/access-control.interface.d.ts +20 -0
- package/dist/modules/access/access-control.interface.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +68 -15
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +282 -58
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/access/access.routes.d.ts.map +1 -1
- package/dist/modules/access/access.routes.js +20 -6
- package/dist/modules/access/access.routes.js.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.d.ts +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.js +1 -1
- package/dist/modules/auth/index.d.ts +15 -0
- package/dist/modules/auth/index.d.ts.map +1 -0
- package/dist/modules/auth/index.js +20 -0
- package/dist/modules/auth/index.js.map +1 -0
- package/dist/modules/diff/diff.service.d.ts.map +1 -1
- package/dist/modules/diff/diff.service.js +7 -1
- package/dist/modules/diff/diff.service.js.map +1 -1
- package/dist/modules/embed/embed.interface.d.ts +22 -0
- package/dist/modules/embed/embed.interface.d.ts.map +1 -1
- package/dist/modules/embed/embed.service.d.ts +28 -14
- package/dist/modules/embed/embed.service.d.ts.map +1 -1
- package/dist/modules/embed/embed.service.js +38 -17
- package/dist/modules/embed/embed.service.js.map +1 -1
- package/dist/modules/embed/embed.tools.d.ts.map +1 -1
- package/dist/modules/embed/embed.tools.js +10 -2
- package/dist/modules/embed/embed.tools.js.map +1 -1
- package/dist/modules/kb-fs/git-dir.d.ts +21 -0
- package/dist/modules/kb-fs/git-dir.d.ts.map +1 -0
- package/dist/modules/kb-fs/git-dir.js +58 -0
- package/dist/modules/kb-fs/git-dir.js.map +1 -0
- package/dist/modules/kb-fs/index.d.ts +9 -0
- package/dist/modules/kb-fs/index.d.ts.map +1 -0
- package/dist/modules/kb-fs/index.js +3 -0
- package/dist/modules/kb-fs/index.js.map +1 -0
- package/dist/modules/kb-fs/ref-files.d.ts +63 -0
- package/dist/modules/kb-fs/ref-files.d.ts.map +1 -0
- package/dist/modules/kb-fs/ref-files.js +249 -0
- package/dist/modules/kb-fs/ref-files.js.map +1 -0
- package/dist/modules/plugins/join-request-jobs.service.d.ts.map +1 -1
- package/dist/modules/plugins/join-request-jobs.service.js +43 -8
- package/dist/modules/plugins/join-request-jobs.service.js.map +1 -1
- package/dist/modules/plugins/teams.routes.d.ts +4 -0
- package/dist/modules/plugins/teams.routes.d.ts.map +1 -1
- package/dist/modules/plugins/teams.routes.js +9 -1
- package/dist/modules/plugins/teams.routes.js.map +1 -1
- package/dist/modules/skills/skills.contract.d.ts.map +1 -1
- package/dist/modules/skills/skills.tools.d.ts +8 -1
- package/dist/modules/skills/skills.tools.d.ts.map +1 -1
- package/dist/modules/skills/skills.tools.js +115 -11
- package/dist/modules/skills/skills.tools.js.map +1 -1
- package/dist/modules/tool-auth/internal-token.service.d.ts +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts +1 -2
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.js +1 -2
- package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
- package/dist/modules/tool-helpers/default-branch-write.d.ts +69 -0
- package/dist/modules/tool-helpers/default-branch-write.d.ts.map +1 -0
- package/dist/modules/tool-helpers/default-branch-write.js +63 -0
- package/dist/modules/tool-helpers/default-branch-write.js.map +1 -0
- package/dist/modules/tool-helpers/index.d.ts +1 -0
- package/dist/modules/tool-helpers/index.d.ts.map +1 -1
- package/dist/modules/tool-helpers/index.js +1 -0
- package/dist/modules/tool-helpers/index.js.map +1 -1
- package/dist/modules/tool-helpers/tool-handler.d.ts +2 -2
- package/dist/modules/tool-helpers/tool.contract.d.ts +2 -2
- package/dist/modules/workflow/file-lock.service.d.ts +27 -5
- package/dist/modules/workflow/file-lock.service.d.ts.map +1 -1
- package/dist/modules/workflow/file-lock.service.js +70 -18
- package/dist/modules/workflow/file-lock.service.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +42 -0
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +201 -24
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workflow/index.d.ts +8 -0
- package/dist/modules/workflow/index.d.ts.map +1 -0
- package/dist/modules/workflow/index.js +8 -0
- package/dist/modules/workflow/index.js.map +1 -0
- package/dist/modules/workflow/pending-commits.service.d.ts +2 -17
- package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -1
- package/dist/modules/workflow/pending-commits.service.js +4 -24
- package/dist/modules/workflow/pending-commits.service.js.map +1 -1
- package/dist/modules/workflow/workflow-hooks.d.ts +1 -1
- package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.routes.js +20 -1
- package/dist/modules/workflow/workflow.routes.js.map +1 -1
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +5 -3
- package/dist/modules/workflow/workflow.service.js.map +1 -1
- package/dist/modules/workspace/agent-access.gate.d.ts +2 -2
- package/dist/modules/workspace/agent-access.gate.js +2 -2
- package/dist/modules/workspace/bounded-matcher.d.ts +79 -0
- package/dist/modules/workspace/bounded-matcher.d.ts.map +1 -0
- package/dist/modules/workspace/bounded-matcher.js +261 -0
- package/dist/modules/workspace/bounded-matcher.js.map +1 -0
- package/dist/modules/workspace/fetch-instant.d.ts +9 -0
- package/dist/modules/workspace/fetch-instant.d.ts.map +1 -0
- package/dist/modules/workspace/fetch-instant.js +13 -0
- package/dist/modules/workspace/fetch-instant.js.map +1 -0
- package/dist/modules/workspace/index.d.ts +17 -0
- package/dist/modules/workspace/index.d.ts.map +1 -0
- package/dist/modules/workspace/index.js +16 -0
- package/dist/modules/workspace/index.js.map +1 -0
- package/dist/modules/workspace/kb-repository.contract.d.ts +124 -0
- package/dist/modules/workspace/kb-repository.contract.d.ts.map +1 -0
- package/dist/modules/workspace/kb-repository.contract.js +19 -0
- package/dist/modules/workspace/kb-repository.contract.js.map +1 -0
- package/dist/modules/workspace/kb-repository.d.ts +236 -0
- package/dist/modules/workspace/kb-repository.d.ts.map +1 -0
- package/dist/modules/workspace/kb-repository.js +811 -0
- package/dist/modules/workspace/kb-repository.js.map +1 -0
- package/dist/modules/workspace/pattern-matcher.contract.d.ts +50 -0
- package/dist/modules/workspace/pattern-matcher.contract.d.ts.map +1 -0
- package/dist/modules/workspace/pattern-matcher.contract.js +27 -0
- package/dist/modules/workspace/pattern-matcher.contract.js.map +1 -0
- package/dist/modules/workspace/routine-write-policy.d.ts +0 -7
- package/dist/modules/workspace/routine-write-policy.d.ts.map +1 -1
- package/dist/modules/workspace/routine-write-policy.js +0 -5
- package/dist/modules/workspace/routine-write-policy.js.map +1 -1
- package/dist/modules/workspace/set-aside-clone.d.ts +40 -0
- package/dist/modules/workspace/set-aside-clone.d.ts.map +1 -1
- package/dist/modules/workspace/set-aside-clone.js +139 -0
- package/dist/modules/workspace/set-aside-clone.js.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts +99 -0
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.js +407 -29
- package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +68 -32
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +240 -161
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/modules/workspace/workspace.tools.d.ts +13 -4
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +268 -356
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/shared/workspace-id.d.ts +17 -0
- package/dist/shared/workspace-id.d.ts.map +1 -1
- package/dist/shared/workspace-id.js +24 -0
- package/dist/shared/workspace-id.js.map +1 -1
- package/dist/test-setup.js +4 -0
- package/dist/test-setup.js.map +1 -1
- package/mcp-app/page.html +142 -8
- package/package.json +3 -3
- package/src/__tests__/test-repositories.ts +22 -0
- package/src/__tests__/workspace-service.ts +69 -0
- package/src/core/__tests__/compose-embed.test.ts +65 -0
- package/src/core/__tests__/lifecycle.test.ts +45 -26
- package/src/core/catalog-revision.ts +4 -2
- package/src/core/compose-embed.ts +50 -0
- package/src/core/core-ports.ts +10 -0
- package/src/core/create-core-server.ts +8 -2
- package/src/core/create-core-services.ts +63 -24
- package/src/core/lifecycle.ts +34 -12
- package/src/modules/access/__tests__/access-control.atref-cache.test.ts +443 -25
- package/src/modules/access/__tests__/access-control.group-read.test.ts +73 -0
- package/src/modules/access/__tests__/access.routes.group-grant.test.ts +66 -0
- package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +2 -0
- package/src/modules/access/access-control.interface.ts +22 -0
- package/src/modules/access/access-control.service.ts +302 -58
- package/src/modules/access/access.routes.ts +22 -6
- package/src/modules/agent-instructions/shared-file-rules.ts +1 -1
- package/src/modules/auth/index.ts +29 -0
- package/src/modules/diff/__tests__/diff.service.seed-atomicity.test.ts +2 -1
- package/src/modules/diff/__tests__/diff.service.test.ts +2 -1
- package/src/modules/diff/__tests__/diff.service.worktree.test.ts +76 -0
- package/src/modules/diff/diff.service.ts +6 -4
- package/src/modules/embed/__tests__/embed.service.test.ts +76 -3
- package/src/modules/embed/__tests__/embed.tools.test.ts +29 -0
- package/src/modules/embed/embed.interface.ts +24 -0
- package/src/modules/embed/embed.service.ts +44 -19
- package/src/modules/embed/embed.tools.ts +10 -2
- package/src/modules/kb-fs/__tests__/git-dir.test.ts +77 -0
- package/src/modules/kb-fs/__tests__/ref-files.test.ts +338 -0
- package/src/modules/kb-fs/git-dir.ts +53 -0
- package/src/modules/kb-fs/index.ts +8 -0
- package/src/modules/kb-fs/ref-files.ts +279 -0
- package/src/modules/plugins/__tests__/join-request-jobs.service.test.ts +73 -6
- package/src/modules/plugins/__tests__/teams.routes.test.ts +55 -0
- package/src/modules/plugins/join-request-jobs.service.ts +45 -8
- package/src/modules/plugins/teams.routes.ts +14 -1
- package/src/modules/settings/__tests__/setup.routes.layout-phase.test.ts +2 -2
- package/src/modules/settings/__tests__/setup.routes.managed-phase.test.ts +2 -2
- package/src/modules/skills/__tests__/branch-skills.tools.test.ts +1 -1
- package/src/modules/skills/skills.contract.ts +4 -0
- package/src/modules/skills/skills.tools.ts +120 -10
- package/src/modules/tool-auth/internal-token.service.ts +1 -1
- package/src/modules/tool-auth/tool-auth.middleware.ts +1 -2
- package/src/modules/tool-helpers/__tests__/branch-declaration.test.ts +2 -2
- package/src/modules/tool-helpers/__tests__/can-write.tools.test.ts +581 -0
- package/src/modules/tool-helpers/default-branch-write.ts +90 -0
- package/src/modules/tool-helpers/index.ts +5 -0
- package/src/modules/tool-helpers/tool-handler.ts +2 -2
- package/src/modules/tool-helpers/tool.contract.ts +2 -2
- package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +42 -3
- package/src/modules/workflow/__tests__/fake-file-lock-db.ts +13 -2
- package/src/modules/workflow/__tests__/workflow.routes.lock-path.test.ts +168 -1
- package/src/modules/workflow/__tests__/workflow.service.delete-branch.test.ts +102 -6
- package/src/modules/workflow/file-lock.service.ts +79 -18
- package/src/modules/workflow/git/__tests__/git.service.changedPathsMemo.test.ts +175 -0
- package/src/modules/workflow/git/__tests__/git.service.readFileAtRef.test.ts +42 -0
- package/src/modules/workflow/git/__tests__/git.service.worktrees.test.ts +284 -0
- package/src/modules/workflow/git/git.service.ts +207 -22
- package/src/modules/workflow/index.ts +7 -0
- package/src/modules/workflow/pending-commits.service.ts +4 -23
- package/src/modules/workflow/workflow-hooks.ts +1 -1
- package/src/modules/workflow/workflow.routes.ts +24 -1
- package/src/modules/workflow/workflow.service.ts +3 -2
- package/src/modules/workspace/__tests__/agent-downloads.test.ts +2 -2
- package/src/modules/workspace/__tests__/bounded-matcher.test.ts +213 -0
- package/src/modules/workspace/__tests__/git-internals.security.test.ts +22 -7
- package/src/modules/workspace/__tests__/kb-repository.test.ts +481 -0
- package/src/modules/workspace/__tests__/rest-tool-arguments.test.ts +14 -0
- package/src/modules/workspace/__tests__/routine-write-policy.test.ts +0 -11
- package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +2 -2
- package/src/modules/workspace/__tests__/workspace.routes.folder-zip-access.test.ts +2 -2
- package/src/modules/workspace/__tests__/workspace.routes.folders.test.ts +4 -3
- package/src/modules/workspace/__tests__/workspace.service.any-workspace-credentials.test.ts +2 -2
- package/src/modules/workspace/__tests__/workspace.service.ensure-remotes-fetched.test.ts +2 -2
- package/src/modules/workspace/__tests__/workspace.service.forget-clone-races.test.ts +12 -5
- package/src/modules/workspace/__tests__/workspace.service.list-cloned.test.ts +6 -6
- package/src/modules/workspace/__tests__/workspace.service.move-never-overwrites.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.replaced-repository.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.test.ts +24 -23
- package/src/modules/workspace/__tests__/workspace.service.unknown-branch.test.ts +2 -1
- package/src/modules/workspace/__tests__/workspace.service.worktrees.test.ts +620 -0
- package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +15 -1
- package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +71 -5
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +174 -309
- package/src/modules/workspace/agent-access.gate.ts +2 -2
- package/src/modules/workspace/bounded-matcher.ts +328 -0
- package/src/modules/workspace/fetch-instant.ts +13 -0
- package/src/modules/workspace/index.ts +26 -0
- package/src/modules/workspace/kb-repository.contract.ts +124 -0
- package/src/modules/workspace/kb-repository.ts +844 -0
- package/src/modules/workspace/pattern-matcher.contract.ts +69 -0
- package/src/modules/workspace/routine-write-policy.ts +0 -15
- package/src/modules/workspace/set-aside-clone.ts +140 -0
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.degraded.test.ts +3 -2
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +12 -10
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.worktrees.test.ts +613 -0
- package/src/modules/workspace/startup/kb-startup-runner.ts +422 -29
- package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +4 -3
- package/src/modules/workspace/workspace.service.ts +247 -169
- package/src/modules/workspace/workspace.tools.ts +299 -385
- package/src/shared/workspace-id.ts +24 -0
- package/src/test-setup.ts +5 -0
|
@@ -4,8 +4,8 @@ import path from 'node:path';
|
|
|
4
4
|
import os from 'node:os';
|
|
5
5
|
import { testKbContext } from '../../../__tests__/kb-context.js';
|
|
6
6
|
import { NodeFs } from '../../kb-fs/node-fs.js';
|
|
7
|
-
import { WorkspaceService } from '../workspace.service.js';
|
|
8
7
|
import type { IGitRunner } from '../../../shared/git.contract.js';
|
|
8
|
+
import { newWorkspaceService } from '../../../__tests__/workspace-service.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* What happens to work ALREADY IN FLIGHT when the knowledge-base repository is
|
|
@@ -56,7 +56,7 @@ function heldRunner() {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
function service(runner: IGitRunner) {
|
|
59
|
-
return
|
|
59
|
+
return newWorkspaceService(
|
|
60
60
|
workspacesRoot,
|
|
61
61
|
() => `${root}/configured.git`,
|
|
62
62
|
testKbContext({ branchModel: { defaultBranch: BRANCH, protectedBranches: [BRANCH] } }),
|
|
@@ -138,12 +138,19 @@ describe('a bootstrap in flight when the working copy is taken away', () => {
|
|
|
138
138
|
|
|
139
139
|
// The replacement lands while the clone runs.
|
|
140
140
|
svc.forgetClone(WORKSPACE_ID);
|
|
141
|
-
// Let the
|
|
142
|
-
|
|
141
|
+
// Let the checkout — and every git call after it — finish. Until the open
|
|
142
|
+
// has settled, not until no call is pending for a moment: making the
|
|
143
|
+
// repository does filesystem work between its git calls.
|
|
144
|
+
let settled = false;
|
|
145
|
+
void opening.then(
|
|
146
|
+
() => (settled = true),
|
|
147
|
+
() => (settled = true),
|
|
148
|
+
);
|
|
149
|
+
for (let i = 0; i < 400 && !settled; i++) {
|
|
143
150
|
const pending = calls.splice(0, calls.length);
|
|
144
151
|
for (const call of pending) call.settle();
|
|
145
152
|
await Promise.resolve();
|
|
146
|
-
await new Promise((r) => setTimeout(r,
|
|
153
|
+
await new Promise((r) => setTimeout(r, 5));
|
|
147
154
|
}
|
|
148
155
|
|
|
149
156
|
await refused;
|
|
@@ -4,7 +4,7 @@ import { NodeFs } from '../../kb-fs/node-fs.js';
|
|
|
4
4
|
import fs from 'node:fs/promises';
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import os from 'node:os';
|
|
7
|
-
import {
|
|
7
|
+
import { newWorkspaceService } from '../../../__tests__/workspace-service.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* `listClonedWorkspaces` is what the remote sync enumerates. It must read the
|
|
@@ -37,7 +37,7 @@ describe('WorkspaceService.listClonedWorkspaces', () => {
|
|
|
37
37
|
// A stray file at the root is ignored.
|
|
38
38
|
await fs.writeFile(path.join(root, 'notes.txt'), 'x');
|
|
39
39
|
|
|
40
|
-
const svc =
|
|
40
|
+
const svc = newWorkspaceService(root, 'https://example.test/kb.git', testKbContext(), new NodeFs());
|
|
41
41
|
const found = await svc.listClonedWorkspaces();
|
|
42
42
|
expect(found.sort((a, b) => a.branch.localeCompare(b.branch))).toEqual([
|
|
43
43
|
{ id: 'ali%2Fnew-skill', branch: 'ali/new-skill' },
|
|
@@ -46,7 +46,7 @@ describe('WorkspaceService.listClonedWorkspaces', () => {
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
it('is empty when the workspaces root does not exist yet', async () => {
|
|
49
|
-
const svc =
|
|
49
|
+
const svc = newWorkspaceService(path.join(root, 'missing'), 'https://example.test/kb.git', testKbContext(), new NodeFs());
|
|
50
50
|
expect(await svc.listClonedWorkspaces()).toEqual([]);
|
|
51
51
|
});
|
|
52
52
|
});
|
|
@@ -67,14 +67,14 @@ describe('WorkspaceService.listClonedWorkspaces — what is not a clone', () =>
|
|
|
67
67
|
for (const name of ['main', 'foo!', '-leading-dash', 'a..b', 'has space']) {
|
|
68
68
|
await fs.mkdir(path.join(root, name, 'knowledge-base', '.git'), { recursive: true });
|
|
69
69
|
}
|
|
70
|
-
const svc =
|
|
70
|
+
const svc = newWorkspaceService(root, 'https://example.test/kb.git', testKbContext(), new NodeFs());
|
|
71
71
|
expect(await svc.listClonedWorkspaces()).toEqual([{ id: 'main', branch: 'main' }]);
|
|
72
72
|
});
|
|
73
73
|
|
|
74
74
|
it('a branch whose bootstrap is in flight right now', async () => {
|
|
75
75
|
await fs.mkdir(path.join(root, 'main', 'knowledge-base', '.git'), { recursive: true });
|
|
76
76
|
await fs.mkdir(path.join(root, 'ali%2Fx', 'knowledge-base', '.git'), { recursive: true });
|
|
77
|
-
const svc =
|
|
77
|
+
const svc = newWorkspaceService(root, 'https://example.test/kb.git', testKbContext(), new NodeFs());
|
|
78
78
|
// While a clone runs, `.git` exists but the tree is not checked out yet.
|
|
79
79
|
// The listing asks the public predicate, which is stubbed here rather than
|
|
80
80
|
// the tracker behind it — no public seam can hold a real clone open.
|
|
@@ -89,7 +89,7 @@ describe('WorkspaceService.listClonedWorkspaces — what is not a clone', () =>
|
|
|
89
89
|
// to stage one in a temp dir; the code path is the same `throw err`.
|
|
90
90
|
const file = path.join(root, 'not-a-dir');
|
|
91
91
|
await fs.writeFile(file, 'x');
|
|
92
|
-
const svc =
|
|
92
|
+
const svc = newWorkspaceService(file, 'https://example.test/kb.git', testKbContext(), new NodeFs());
|
|
93
93
|
expect(await svc.listClonedWorkspaces()).toEqual([]);
|
|
94
94
|
});
|
|
95
95
|
});
|
|
@@ -6,6 +6,7 @@ import os from 'node:os';
|
|
|
6
6
|
import { NodeFs } from '../../kb-fs/node-fs.js';
|
|
7
7
|
import { WorkspaceService } from '../workspace.service.js';
|
|
8
8
|
import { workspaceIdForBranch } from '../../../shared/workspace-id.js';
|
|
9
|
+
import { newWorkspaceService } from '../../../__tests__/workspace-service.js';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* A rename never overwrites.
|
|
@@ -55,7 +56,7 @@ describe('WorkspaceService.moveEntry — a name that is taken is refused, never
|
|
|
55
56
|
// The inner `.git` is what lets `resolveWorkspaceDir` accept the workspace
|
|
56
57
|
// without trying to clone.
|
|
57
58
|
await fs.mkdir(path.join(workspaceDir, KB, '.git'), { recursive: true });
|
|
58
|
-
svc =
|
|
59
|
+
svc = newWorkspaceService(
|
|
59
60
|
root,
|
|
60
61
|
'https://github.com/Bevel-Software/knowledge-base.git',
|
|
61
62
|
testKbContext({ kbDirName: KB }),
|
|
@@ -6,6 +6,7 @@ import path from 'node:path';
|
|
|
6
6
|
import os from 'node:os';
|
|
7
7
|
import { WorkspaceService, type ReadTreeFilter } from '../workspace.service.js';
|
|
8
8
|
import { workspaceIdForBranch } from '../../../shared/workspace-id.js';
|
|
9
|
+
import { newWorkspaceService } from '../../../__tests__/workspace-service.js';
|
|
9
10
|
|
|
10
11
|
const KB = 'knowledge-base';
|
|
11
12
|
|
|
@@ -48,7 +49,7 @@ describe('WorkspaceService.listFiles — read filter', () => {
|
|
|
48
49
|
// readers, say), and its files are readable.
|
|
49
50
|
await mkFile(workspaceDir, 'Scopes/Deploy/SKILL.md');
|
|
50
51
|
await mkFile(workspaceDir, 'Scopes/other.md');
|
|
51
|
-
svc =
|
|
52
|
+
svc = newWorkspaceService(root, 'https://example.invalid/repo.git', testKbContext({ kbDirName: KB }), new NodeFs());
|
|
52
53
|
await svc.getWorkspacePath(workspaceId);
|
|
53
54
|
});
|
|
54
55
|
|
|
@@ -8,6 +8,7 @@ import path from 'node:path';
|
|
|
8
8
|
import os from 'node:os';
|
|
9
9
|
import { WorkspaceService } from '../workspace.service.js';
|
|
10
10
|
import { NodeGitRunner } from '../../workflow/git/node-git-runner.js';
|
|
11
|
+
import { newWorkspaceService } from '../../../__tests__/workspace-service.js';
|
|
11
12
|
|
|
12
13
|
const execFileAsync = promisify(execFile);
|
|
13
14
|
|
|
@@ -77,7 +78,7 @@ function service(
|
|
|
77
78
|
aroundSetAside?: (workspaceId: string, move: () => Promise<void>) => Promise<void>,
|
|
78
79
|
gitRunner: NodeGitRunner = new NodeGitRunner(),
|
|
79
80
|
) {
|
|
80
|
-
return
|
|
81
|
+
return newWorkspaceService(
|
|
81
82
|
workspacesRoot,
|
|
82
83
|
kbRepoUrl,
|
|
83
84
|
testKbContext({ branchModel: { defaultBranch: BRANCH, protectedBranches: [BRANCH] } }),
|
|
@@ -8,6 +8,7 @@ import path from 'node:path';
|
|
|
8
8
|
import os from 'node:os';
|
|
9
9
|
import { WorkspaceService } from '../workspace.service.js';
|
|
10
10
|
import { workspaceIdForBranch } from '../../../shared/workspace-id.js';
|
|
11
|
+
import { newWorkspaceService } from '../../../__tests__/workspace-service.js';
|
|
11
12
|
|
|
12
13
|
const execFileAsync = promisify(execFile);
|
|
13
14
|
|
|
@@ -66,7 +67,7 @@ describe('WorkspaceService — branch-keyed identity', () => {
|
|
|
66
67
|
});
|
|
67
68
|
|
|
68
69
|
it('a malformed workspace id (bad percent-escape) rejects as a 400 BranchNameError, not a 500', async () => {
|
|
69
|
-
const svc =
|
|
70
|
+
const svc = newWorkspaceService(root, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
70
71
|
// `%zz` fails decodeURIComponent, falls back to itself, and `%` never
|
|
71
72
|
// passes the branch-name rules — the cold-path bootstrap must surface
|
|
72
73
|
// that as the status-carrying domain error, not a wrapped plain Error.
|
|
@@ -78,7 +79,7 @@ describe('WorkspaceService — branch-keyed identity', () => {
|
|
|
78
79
|
|
|
79
80
|
it('returns workspace info derived from the branch — no .workspace.json on disk', async () => {
|
|
80
81
|
const { workspaceId, workspaceDir } = await seedBranchWorkspace(root, 'target-company-state');
|
|
81
|
-
const svc =
|
|
82
|
+
const svc = newWorkspaceService(root, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
82
83
|
const info = await svc.getOrCreateForBranch('target-company-state');
|
|
83
84
|
|
|
84
85
|
expect(info.id).toBe(workspaceId);
|
|
@@ -91,7 +92,7 @@ describe('WorkspaceService — branch-keyed identity', () => {
|
|
|
91
92
|
it('two branches map to distinct directories', async () => {
|
|
92
93
|
const a = await seedBranchWorkspace(root, 'target-company-state');
|
|
93
94
|
const b = await seedBranchWorkspace(root, 'alice/feature');
|
|
94
|
-
const svc =
|
|
95
|
+
const svc = newWorkspaceService(root, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
95
96
|
|
|
96
97
|
const infoA = await svc.getOrCreateForBranch('target-company-state');
|
|
97
98
|
const infoB = await svc.getOrCreateForBranch('alice/feature');
|
|
@@ -114,7 +115,7 @@ describe('WorkspaceService — branch-keyed identity', () => {
|
|
|
114
115
|
const squatter = path.join(workspaceDir, 'knowledge-base');
|
|
115
116
|
await fs.writeFile(squatter, 'not a clone', 'utf8');
|
|
116
117
|
|
|
117
|
-
const svc =
|
|
118
|
+
const svc = newWorkspaceService(root, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
118
119
|
await expect(svc.getOrCreateForBranch('target-company-state')).rejects.toThrow(
|
|
119
120
|
/"knowledge-base" in this workspace exists but is not a directory/,
|
|
120
121
|
);
|
|
@@ -122,21 +123,21 @@ describe('WorkspaceService — branch-keyed identity', () => {
|
|
|
122
123
|
});
|
|
123
124
|
|
|
124
125
|
it('rejects invalid branch names before touching disk', async () => {
|
|
125
|
-
const svc =
|
|
126
|
+
const svc = newWorkspaceService(root, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
126
127
|
await expect(svc.getOrCreateForBranch('')).rejects.toThrow();
|
|
127
128
|
await expect(svc.getOrCreateForBranch('-bad-leading-dash')).rejects.toThrow();
|
|
128
129
|
});
|
|
129
130
|
|
|
130
131
|
it('getOrCreateForUser falls back to target-company-state when no branch is supplied', async () => {
|
|
131
132
|
await seedBranchWorkspace(root, 'target-company-state');
|
|
132
|
-
const svc =
|
|
133
|
+
const svc = newWorkspaceService(root, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
133
134
|
const info = await svc.getOrCreateForUser({ id: 'u', email: 'a@b.c', name: 'A' });
|
|
134
135
|
expect(info.id).toBe(workspaceIdForBranch('target-company-state'));
|
|
135
136
|
});
|
|
136
137
|
|
|
137
138
|
it('getOrCreateForUser respects an explicit branch override', async () => {
|
|
138
139
|
await seedBranchWorkspace(root, 'alice/feature');
|
|
139
|
-
const svc =
|
|
140
|
+
const svc = newWorkspaceService(root, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
140
141
|
const info = await svc.getOrCreateForUser({ id: 'u', email: 'a@b.c', name: 'A' }, 'alice/feature');
|
|
141
142
|
expect(info.id).toBe(workspaceIdForBranch('alice/feature'));
|
|
142
143
|
});
|
|
@@ -156,7 +157,7 @@ describe('WorkspaceService.createDirectory', () => {
|
|
|
156
157
|
workspaceDir = seeded.workspaceDir;
|
|
157
158
|
repoDir = path.join(workspaceDir, 'knowledge-base');
|
|
158
159
|
workspaceId = seeded.workspaceId;
|
|
159
|
-
svc =
|
|
160
|
+
svc = newWorkspaceService(root, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
160
161
|
// Hydrate the in-memory map so subsequent ops resolve fast.
|
|
161
162
|
await svc.getWorkspacePath(workspaceId);
|
|
162
163
|
});
|
|
@@ -267,7 +268,7 @@ describe('WorkspaceService.writeFile — expectedContent', () => {
|
|
|
267
268
|
const seeded = await seedBranchWorkspace(root, 'target-company-state');
|
|
268
269
|
workspaceDir = seeded.workspaceDir;
|
|
269
270
|
workspaceId = seeded.workspaceId;
|
|
270
|
-
svc =
|
|
271
|
+
svc = newWorkspaceService(root, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
271
272
|
});
|
|
272
273
|
|
|
273
274
|
afterEach(async () => {
|
|
@@ -408,7 +409,7 @@ describe('WorkspaceService.withPathTurn', () => {
|
|
|
408
409
|
const seeded = await seedBranchWorkspace(root, 'target-company-state');
|
|
409
410
|
workspaceDir = seeded.workspaceDir;
|
|
410
411
|
workspaceId = seeded.workspaceId;
|
|
411
|
-
svc =
|
|
412
|
+
svc = newWorkspaceService(root, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
412
413
|
});
|
|
413
414
|
|
|
414
415
|
afterEach(async () => {
|
|
@@ -636,7 +637,7 @@ describe('WorkspaceService.assertContentMatches', () => {
|
|
|
636
637
|
const seeded = await seedBranchWorkspace(root, 'target-company-state');
|
|
637
638
|
workspaceDir = seeded.workspaceDir;
|
|
638
639
|
workspaceId = seeded.workspaceId;
|
|
639
|
-
svc =
|
|
640
|
+
svc = newWorkspaceService(root, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
640
641
|
});
|
|
641
642
|
|
|
642
643
|
afterEach(async () => {
|
|
@@ -681,7 +682,7 @@ describe('WorkspaceService.createFolderZip', () => {
|
|
|
681
682
|
workspaceDir = seeded.workspaceDir;
|
|
682
683
|
repoDir = path.join(workspaceDir, 'knowledge-base');
|
|
683
684
|
workspaceId = seeded.workspaceId;
|
|
684
|
-
svc =
|
|
685
|
+
svc = newWorkspaceService(root, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
685
686
|
await svc.getWorkspacePath(workspaceId);
|
|
686
687
|
});
|
|
687
688
|
|
|
@@ -879,7 +880,7 @@ describe('WorkspaceService — clone bootstrap & sibling reference', () => {
|
|
|
879
880
|
});
|
|
880
881
|
|
|
881
882
|
it('clones a branch on first bootstrap and checks out the right ref', async () => {
|
|
882
|
-
const svc =
|
|
883
|
+
const svc = newWorkspaceService(workspacesRoot, upstream, testKbContext(), new NodeFs());
|
|
883
884
|
const info = await svc.getOrCreateForBranch('target-company-state');
|
|
884
885
|
|
|
885
886
|
const repo = path.join(info.absolutePath, 'knowledge-base');
|
|
@@ -888,7 +889,7 @@ describe('WorkspaceService — clone bootstrap & sibling reference', () => {
|
|
|
888
889
|
});
|
|
889
890
|
|
|
890
891
|
it('uses an existing sibling clone as a --reference and stays dissociated', async () => {
|
|
891
|
-
const svc =
|
|
892
|
+
const svc = newWorkspaceService(workspacesRoot, upstream, testKbContext(), new NodeFs());
|
|
892
893
|
// First branch: plain clone — becomes the sibling for the next bootstrap.
|
|
893
894
|
await svc.getOrCreateForBranch('target-company-state');
|
|
894
895
|
// Second branch: should borrow the first clone's objects, then dissociate.
|
|
@@ -916,7 +917,7 @@ describe('WorkspaceService — clone bootstrap & sibling reference', () => {
|
|
|
916
917
|
// post-merge pull of a target branch. Every clone this service hands out must
|
|
917
918
|
// therefore track exactly one upstream ref through exactly one refspec.
|
|
918
919
|
it('stamps a single fetch refspec and upstream ref on a fresh clone', async () => {
|
|
919
|
-
const svc =
|
|
920
|
+
const svc = newWorkspaceService(workspacesRoot, upstream, testKbContext(), new NodeFs());
|
|
920
921
|
const info = await svc.getOrCreateForBranch('target-company-state');
|
|
921
922
|
const repo = path.join(info.absolutePath, 'knowledge-base');
|
|
922
923
|
|
|
@@ -940,7 +941,7 @@ describe('WorkspaceService — clone bootstrap & sibling reference', () => {
|
|
|
940
941
|
await runGit(repo, ['config', '--add', 'remote.origin.fetch', '+refs/heads/*:refs/remotes/origin/*']);
|
|
941
942
|
await runGit(repo, ['config', '--add', 'branch.alice/draft.merge', 'refs/heads/target-company-state']);
|
|
942
943
|
|
|
943
|
-
const svc =
|
|
944
|
+
const svc = newWorkspaceService(workspacesRoot, upstream, testKbContext(), new NodeFs());
|
|
944
945
|
await svc.getOrCreateForBranch('alice/draft');
|
|
945
946
|
|
|
946
947
|
expect(await gitOut(repo, ['config', '--get-all', 'remote.origin.fetch']))
|
|
@@ -952,7 +953,7 @@ describe('WorkspaceService — clone bootstrap & sibling reference', () => {
|
|
|
952
953
|
});
|
|
953
954
|
|
|
954
955
|
it('notifies the cloned-workspace listener with the workspace id after a clone', async () => {
|
|
955
|
-
const svc =
|
|
956
|
+
const svc = newWorkspaceService(workspacesRoot, upstream, testKbContext(), new NodeFs());
|
|
956
957
|
const cloned: string[] = [];
|
|
957
958
|
svc.setWorkspaceClonedListener((id) => cloned.push(id));
|
|
958
959
|
|
|
@@ -980,7 +981,7 @@ describe('WorkspaceService — symbolic links', () => {
|
|
|
980
981
|
const seeded = await seedBranchWorkspace(root, 'main');
|
|
981
982
|
workspaceDir = seeded.workspaceDir;
|
|
982
983
|
workspaceId = seeded.workspaceId;
|
|
983
|
-
svc =
|
|
984
|
+
svc = newWorkspaceService(root, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
984
985
|
});
|
|
985
986
|
|
|
986
987
|
afterEach(async () => {
|
|
@@ -1065,7 +1066,7 @@ describe('WorkspaceService — symbolic links', () => {
|
|
|
1065
1066
|
// A mounted-volume shape: the whole workspaces root reached through a link.
|
|
1066
1067
|
const mount = path.join(root, 'mount');
|
|
1067
1068
|
await fs.symlink(root, mount, linkType);
|
|
1068
|
-
const viaMount =
|
|
1069
|
+
const viaMount = newWorkspaceService(mount, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
1069
1070
|
expect(await viaMount.readFile(workspaceId, rel)).toBe('Hello.');
|
|
1070
1071
|
await viaMount.writeFile(workspaceId, rel, 'Hello again.');
|
|
1071
1072
|
expect(await fs.readFile(path.join(workspaceDir, rel), 'utf-8')).toBe('Hello again.');
|
|
@@ -1098,7 +1099,7 @@ describe('WorkspaceService.sweepOrphanedWorkspaces', () => {
|
|
|
1098
1099
|
|
|
1099
1100
|
it('removes the clone of a branch that is not in the known set', async () => {
|
|
1100
1101
|
const { workspaceId, workspaceDir } = await seedBranchWorkspace(root, 'target-company-state');
|
|
1101
|
-
const svc =
|
|
1102
|
+
const svc = newWorkspaceService(root, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
1102
1103
|
await svc.getOrCreateForBranch('target-company-state');
|
|
1103
1104
|
|
|
1104
1105
|
// The branch vanishes from the known set; the sweep reclaims its clone.
|
|
@@ -1119,7 +1120,7 @@ describe('WorkspaceService.readAllKbFiles', () => {
|
|
|
1119
1120
|
const seeded = await seedBranchWorkspace(root, 'target-company-state');
|
|
1120
1121
|
repoRoot = path.join(seeded.workspaceDir, 'knowledge-base');
|
|
1121
1122
|
workspaceId = seeded.workspaceId;
|
|
1122
|
-
svc =
|
|
1123
|
+
svc = newWorkspaceService(root, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
1123
1124
|
await svc.getWorkspacePath(workspaceId);
|
|
1124
1125
|
});
|
|
1125
1126
|
|
|
@@ -1178,7 +1179,7 @@ describe('WorkspaceService.unzipFile — per-entry write guard', () => {
|
|
|
1178
1179
|
workspaceDir = seeded.workspaceDir;
|
|
1179
1180
|
repoDir = path.join(workspaceDir, 'knowledge-base');
|
|
1180
1181
|
workspaceId = seeded.workspaceId;
|
|
1181
|
-
svc =
|
|
1182
|
+
svc = newWorkspaceService(root, 'https://github.com/Bevel-Software/knowledge-base.git', testKbContext(), new NodeFs());
|
|
1182
1183
|
await svc.getWorkspacePath(workspaceId);
|
|
1183
1184
|
});
|
|
1184
1185
|
|
|
@@ -1389,7 +1390,7 @@ describe('WorkspaceService — every operation resolves inside the repository',
|
|
|
1389
1390
|
workspaceDir = seeded.workspaceDir;
|
|
1390
1391
|
repoDir = path.join(workspaceDir, 'knowledge-base');
|
|
1391
1392
|
workspaceId = seeded.workspaceId;
|
|
1392
|
-
svc =
|
|
1393
|
+
svc = newWorkspaceService(root, 'https://example.invalid/kb.git', testKbContext(), new NodeFs());
|
|
1393
1394
|
await svc.getWorkspacePath(workspaceId);
|
|
1394
1395
|
});
|
|
1395
1396
|
|
|
@@ -8,6 +8,7 @@ import os from 'node:os';
|
|
|
8
8
|
import { NodeFs } from '../../kb-fs/node-fs.js';
|
|
9
9
|
import { WorkspaceService } from '../workspace.service.js';
|
|
10
10
|
import { workspaceIdForBranch } from '../../../shared/workspace-id.js';
|
|
11
|
+
import { newWorkspaceService } from '../../../__tests__/workspace-service.js';
|
|
11
12
|
|
|
12
13
|
const execFileAsync = promisify(execFile);
|
|
13
14
|
|
|
@@ -64,7 +65,7 @@ describe('WorkspaceService — a branch origin does not have', () => {
|
|
|
64
65
|
const deleteOnHost = (branch: string): Promise<void> => runGit(upstream, ['branch', '-D', branch]);
|
|
65
66
|
|
|
66
67
|
const service = (repoUrl = upstream): WorkspaceService =>
|
|
67
|
-
|
|
68
|
+
newWorkspaceService(workspacesRoot, repoUrl, testKbContext(), new NodeFs());
|
|
68
69
|
|
|
69
70
|
it('a name nothing has ever cloned or listed is a 404 that names only the branch', async () => {
|
|
70
71
|
const svc = service();
|