@bevel-software/platform-core-backend 0.4.1 → 0.5.1
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/THIRD-PARTY-NOTICES.md +6118 -0
- package/dist/core/core-ports.d.ts +15 -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 +40 -6
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +17 -1
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +153 -29
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/core-config.d.ts +70 -21
- package/dist/core-config.d.ts.map +1 -1
- package/dist/core-config.js +134 -58
- package/dist/core-config.js.map +1 -1
- package/dist/modules/access/access-control.interface.d.ts +6 -0
- package/dist/modules/access/access-control.interface.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +74 -5
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +116 -15
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/access/access-declarations.d.ts +93 -0
- package/dist/modules/access/access-declarations.d.ts.map +1 -0
- package/dist/modules/access/access-declarations.js +168 -0
- package/dist/modules/access/access-declarations.js.map +1 -0
- package/dist/modules/access/access-mutation.service.js +4 -4
- package/dist/modules/access/access-mutation.service.js.map +1 -1
- package/dist/modules/access/access-splice.d.ts +16 -1
- package/dist/modules/access/access-splice.d.ts.map +1 -1
- package/dist/modules/access/access-splice.js +40 -21
- package/dist/modules/access/access-splice.js.map +1 -1
- package/dist/modules/access/access.routes.d.ts.map +1 -1
- package/dist/modules/access/access.routes.js +51 -0
- package/dist/modules/access/access.routes.js.map +1 -1
- package/dist/modules/access/creator-access.d.ts +8 -0
- package/dist/modules/access/creator-access.d.ts.map +1 -1
- package/dist/modules/access/creator-access.js +21 -2
- package/dist/modules/access/creator-access.js.map +1 -1
- package/dist/modules/admin/admin-access.service.d.ts +1 -1
- package/dist/modules/admin/admin-access.service.d.ts.map +1 -1
- package/dist/modules/admin/admin-access.service.js +3 -2
- package/dist/modules/admin/admin-access.service.js.map +1 -1
- package/dist/modules/auth/auth.routes.d.ts.map +1 -1
- package/dist/modules/auth/auth.routes.js +50 -1
- package/dist/modules/auth/auth.routes.js.map +1 -1
- package/dist/modules/auth/auth.service.d.ts +39 -10
- package/dist/modules/auth/auth.service.d.ts.map +1 -1
- package/dist/modules/auth/auth.service.js +38 -16
- package/dist/modules/auth/auth.service.js.map +1 -1
- package/dist/modules/database/core-schema.d.ts +124 -0
- package/dist/modules/database/core-schema.d.ts.map +1 -1
- package/dist/modules/database/core-schema.js +45 -0
- package/dist/modules/database/core-schema.js.map +1 -1
- package/dist/modules/groups/group-provision.service.d.ts +130 -0
- package/dist/modules/groups/group-provision.service.d.ts.map +1 -0
- package/dist/modules/groups/group-provision.service.js +288 -0
- package/dist/modules/groups/group-provision.service.js.map +1 -0
- package/dist/modules/groups/groups.contract.d.ts +106 -0
- package/dist/modules/groups/groups.contract.d.ts.map +1 -0
- package/dist/modules/groups/groups.contract.js +36 -0
- package/dist/modules/groups/groups.contract.js.map +1 -0
- package/dist/modules/groups/groups.routes.d.ts +42 -0
- package/dist/modules/groups/groups.routes.d.ts.map +1 -0
- package/dist/modules/groups/groups.routes.js +379 -0
- package/dist/modules/groups/groups.routes.js.map +1 -0
- package/dist/modules/groups/groups.service.d.ts +60 -0
- package/dist/modules/groups/groups.service.d.ts.map +1 -0
- package/dist/modules/groups/groups.service.js +172 -0
- package/dist/modules/groups/groups.service.js.map +1 -0
- package/dist/modules/groups/index.d.ts +7 -0
- package/dist/modules/groups/index.d.ts.map +1 -0
- package/dist/modules/groups/index.js +6 -0
- package/dist/modules/groups/index.js.map +1 -0
- package/dist/modules/groups/join-proposals.d.ts +53 -0
- package/dist/modules/groups/join-proposals.d.ts.map +1 -0
- package/dist/modules/groups/join-proposals.js +67 -0
- package/dist/modules/groups/join-proposals.js.map +1 -0
- package/dist/modules/groups/join-requests.service.d.ts +81 -0
- package/dist/modules/groups/join-requests.service.d.ts.map +1 -0
- package/dist/modules/groups/join-requests.service.js +135 -0
- package/dist/modules/groups/join-requests.service.js.map +1 -0
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +20 -0
- package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -1
- package/dist/modules/secrets-vault/secrets-vault.routes.js +59 -11
- package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
- package/dist/modules/settings/deployment-settings.service.d.ts +129 -0
- package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -0
- package/dist/modules/settings/deployment-settings.service.js +368 -0
- package/dist/modules/settings/deployment-settings.service.js.map +1 -0
- package/dist/modules/settings/setup.routes.d.ts +49 -0
- package/dist/modules/settings/setup.routes.d.ts.map +1 -0
- package/dist/modules/settings/setup.routes.js +292 -0
- package/dist/modules/settings/setup.routes.js.map +1 -0
- package/dist/modules/skills/index.d.ts +2 -1
- package/dist/modules/skills/index.d.ts.map +1 -1
- package/dist/modules/skills/index.js +1 -0
- package/dist/modules/skills/index.js.map +1 -1
- package/dist/modules/skills/pending-skills.service.d.ts +40 -0
- package/dist/modules/skills/pending-skills.service.d.ts.map +1 -0
- package/dist/modules/skills/pending-skills.service.js +147 -0
- package/dist/modules/skills/pending-skills.service.js.map +1 -0
- package/dist/modules/skills/skills.contract.d.ts +32 -3
- package/dist/modules/skills/skills.contract.d.ts.map +1 -1
- package/dist/modules/skills/skills.contract.js +1 -1
- package/dist/modules/skills/skills.routes.d.ts +3 -2
- package/dist/modules/skills/skills.routes.d.ts.map +1 -1
- package/dist/modules/skills/skills.routes.js +18 -1
- package/dist/modules/skills/skills.routes.js.map +1 -1
- package/dist/modules/skills/skills.service.d.ts +22 -0
- package/dist/modules/skills/skills.service.d.ts.map +1 -1
- package/dist/modules/skills/skills.service.js +24 -12
- package/dist/modules/skills/skills.service.js.map +1 -1
- package/dist/modules/tool-manuals/index.d.ts +1 -1
- package/dist/modules/tool-manuals/index.d.ts.map +1 -1
- package/dist/modules/tool-manuals/index.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +47 -2
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.contract.js +1 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +4 -0
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.js +23 -0
- package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts +3 -1
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.js +84 -17
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.js +6 -2
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.js +4 -2
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
- package/dist/modules/workflow/event-bus.d.ts +11 -0
- package/dist/modules/workflow/event-bus.d.ts.map +1 -1
- package/dist/modules/workflow/event-bus.js +22 -0
- package/dist/modules/workflow/event-bus.js.map +1 -1
- package/dist/modules/workflow/file-lock.service.d.ts +9 -0
- package/dist/modules/workflow/file-lock.service.d.ts.map +1 -1
- package/dist/modules/workflow/file-lock.service.js +16 -0
- package/dist/modules/workflow/file-lock.service.js.map +1 -1
- package/dist/modules/workflow/git/branch-name.d.ts +1 -1
- package/dist/modules/workflow/git/branch-name.d.ts.map +1 -1
- package/dist/modules/workflow/git/branch-name.js +1 -1
- package/dist/modules/workflow/git/branch-name.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +31 -2
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +144 -52
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workflow/git/pull-request.service.d.ts +12 -6
- package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/pull-request.service.js +19 -9
- package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.js +12 -3
- package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
- package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.routes.js +95 -14
- package/dist/modules/workflow/workflow.routes.js.map +1 -1
- package/dist/modules/workflow/workflow.service.d.ts +92 -3
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +381 -108
- package/dist/modules/workflow/workflow.service.js.map +1 -1
- package/dist/modules/workspace/bevel-ignore.d.ts +5 -0
- package/dist/modules/workspace/bevel-ignore.d.ts.map +1 -1
- package/dist/modules/workspace/bevel-ignore.js +5 -1
- package/dist/modules/workspace/bevel-ignore.js.map +1 -1
- package/dist/modules/workspace/kb-seed.interface.d.ts +1 -1
- package/dist/modules/workspace/kb-seed.service.d.ts +60 -5
- package/dist/modules/workspace/kb-seed.service.d.ts.map +1 -1
- package/dist/modules/workspace/kb-seed.service.js +228 -51
- package/dist/modules/workspace/kb-seed.service.js.map +1 -1
- package/dist/modules/workspace/workspace.routes.d.ts +2 -1
- package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.routes.js +51 -18
- package/dist/modules/workspace/workspace.routes.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +16 -4
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +36 -9
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +8 -3
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/shared/kb-layout.test.js +2 -2
- package/dist/test-setup.d.ts +2 -0
- package/dist/test-setup.d.ts.map +1 -0
- package/dist/test-setup.js +18 -0
- package/dist/test-setup.js.map +1 -0
- package/kb-template/.bevelignore +6 -2
- package/kb-template/AGENTS.md +272 -0
- package/kb-template/KnowledgeBase/How to get started.md +65 -0
- package/kb-template/access.md +36 -36
- package/migrations/0002_user_onboarding_done.sql +1 -0
- package/migrations/0003_deployment_settings.sql +9 -0
- package/migrations/meta/0001_snapshot.json +1486 -0
- package/migrations/meta/0002_snapshot.json +1493 -0
- package/migrations/meta/0003_snapshot.json +1552 -0
- package/migrations/meta/_journal.json +15 -1
- package/package.json +5 -4
- package/src/__tests__/branch-model.test.ts +79 -0
- package/src/__tests__/core-config.admin.test.ts +114 -0
- package/src/__tests__/database-url.test.ts +70 -0
- package/src/core/core-ports.ts +15 -0
- package/src/core/create-core-server.ts +55 -6
- package/src/core/create-core-services.ts +201 -36
- package/src/core-config.ts +139 -59
- package/src/modules/access/__tests__/access-declarations.test.ts +195 -0
- package/src/modules/access/__tests__/access-md-format.test.ts +191 -0
- package/src/modules/access/__tests__/access-splice.test.ts +21 -0
- package/src/modules/access/__tests__/access.routes.overrides.test.ts +214 -0
- package/src/modules/access/access-control.interface.ts +11 -0
- package/src/modules/access/access-control.service.ts +113 -15
- package/src/modules/access/access-declarations.ts +251 -0
- package/src/modules/access/access-mutation.service.ts +4 -4
- package/src/modules/access/access-splice.ts +64 -21
- package/src/modules/access/access.routes.ts +61 -0
- package/src/modules/access/creator-access.ts +22 -2
- package/src/modules/admin/admin-access.service.ts +4 -3
- package/src/modules/auth/__tests__/auth.service.test.ts +57 -0
- package/src/modules/auth/__tests__/onboarding-done.route.test.ts +147 -0
- package/src/modules/auth/auth.routes.ts +50 -1
- package/src/modules/auth/auth.service.ts +55 -17
- package/src/modules/database/core-schema.ts +46 -0
- package/src/modules/groups/__tests__/group-index.service.test.ts +225 -0
- package/src/modules/groups/__tests__/group-provision.service.test.ts +247 -0
- package/src/modules/groups/__tests__/groups.routes.test.ts +493 -0
- package/src/modules/groups/__tests__/join-proposals.test.ts +101 -0
- package/src/modules/groups/__tests__/join-requests.service.test.ts +175 -0
- package/src/modules/groups/group-provision.service.ts +328 -0
- package/src/modules/groups/groups.contract.ts +107 -0
- package/src/modules/groups/groups.routes.ts +433 -0
- package/src/modules/groups/groups.service.ts +193 -0
- package/src/modules/groups/index.ts +17 -0
- package/src/modules/groups/join-proposals.ts +114 -0
- package/src/modules/groups/join-requests.service.ts +185 -0
- package/src/modules/secrets-vault/__tests__/oauth-return-to.route.test.ts +283 -0
- package/src/modules/secrets-vault/secrets-vault.routes.ts +68 -12
- package/src/modules/settings/__tests__/deployment-settings.service.test.ts +256 -0
- package/src/modules/settings/__tests__/setup.routes.test.ts +201 -0
- package/src/modules/settings/deployment-settings.service.ts +419 -0
- package/src/modules/settings/setup.routes.ts +317 -0
- package/src/modules/skills/__tests__/pending-skills.service.test.ts +240 -0
- package/src/modules/skills/__tests__/skills.service.test.ts +13 -13
- package/src/modules/skills/index.ts +3 -0
- package/src/modules/skills/pending-skills.service.ts +168 -0
- package/src/modules/skills/skills.contract.ts +34 -3
- package/src/modules/skills/skills.routes.ts +23 -2
- package/src/modules/skills/skills.service.ts +24 -16
- package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +262 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +2 -2
- package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +61 -23
- package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +156 -156
- package/src/modules/tool-manuals/index.ts +2 -0
- package/src/modules/tool-manuals/tool-manuals.contract.ts +50 -2
- package/src/modules/tool-manuals/tool-manuals.routes.ts +21 -0
- package/src/modules/tool-manuals/tool-manuals.service.ts +86 -17
- package/src/modules/tool-manuals/tool-manuals.tools.ts +206 -202
- package/src/modules/workflow/__tests__/event-bus.test.ts +35 -0
- package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +251 -5
- package/src/modules/workflow/agent-tools/workflow.tools.ts +4 -2
- package/src/modules/workflow/event-bus.ts +25 -0
- package/src/modules/workflow/file-lock.service.ts +17 -0
- package/src/modules/workflow/git/__tests__/git.service.accessGating.test.ts +9 -49
- package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +101 -0
- package/src/modules/workflow/git/__tests__/git.service.commitFile.test.ts +219 -211
- package/src/modules/workflow/git/__tests__/git.service.fileContentsAtCommit.test.ts +132 -0
- package/src/modules/workflow/git/__tests__/git.service.logForFile.test.ts +4 -2
- package/src/modules/workflow/git/__tests__/git.service.postMergePull.test.ts +275 -272
- package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +5 -0
- package/src/modules/workflow/git/__tests__/pull-request.service.viewer-can-cancel.test.ts +44 -0
- package/src/modules/workflow/git/branch-name.ts +5 -1
- package/src/modules/workflow/git/git.service.ts +159 -62
- package/src/modules/workflow/git/pull-request.service.ts +22 -11
- package/src/modules/workflow/review-workflow/__tests__/cancel-pr.test.ts +4 -1
- package/src/modules/workflow/review-workflow/review-workflow.service.ts +12 -3
- package/src/modules/workflow/workflow.routes.ts +91 -13
- package/src/modules/workflow/workflow.service.ts +353 -13
- package/src/modules/workspace/__tests__/kb-seed.service.test.ts +255 -24
- package/src/modules/workspace/__tests__/workspace.routes.create-grant.test.ts +236 -233
- package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +179 -176
- package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +320 -303
- package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +337 -276
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +14 -6
- package/src/modules/workspace/bevel-ignore.ts +66 -62
- package/src/modules/workspace/kb-seed.interface.ts +1 -1
- package/src/modules/workspace/kb-seed.service.ts +247 -53
- package/src/modules/workspace/workspace.routes.ts +54 -18
- package/src/modules/workspace/workspace.service.ts +45 -7
- package/src/modules/workspace/workspace.tools.ts +922 -917
- package/src/shared/__tests__/frontmatter-id.test.ts +53 -0
- package/src/shared/__tests__/join-request.test.ts +96 -0
- package/src/shared/__tests__/kb-layout.group.test.ts +45 -0
- package/src/shared/kb-layout.test.ts +2 -2
- package/src/test-setup.ts +18 -0
- package/kb-template/Agents/README.md +0 -38
- package/kb-template/CLAUDE.md +0 -419
- package/kb-template/Data/.gitkeep +0 -0
- package/kb-template/Data/README.md +0 -39
- package/kb-template/KnowledgeBase/README.md +0 -37
- package/kb-template/Pipelines/.gitkeep +0 -0
- package/kb-template/Pipelines/README.md +0 -38
- package/kb-template/Skills/.gitkeep +0 -0
- package/kb-template/Skills/README.md +0 -32
- package/kb-template/Tools/.gitkeep +0 -0
- package/kb-template/Tools/README.md +0 -42
- /package/kb-template/{Agents → Groups}/.gitkeep +0 -0
|
@@ -56,6 +56,59 @@ describe('dedupeById', () => {
|
|
|
56
56
|
expect(out.map((x) => x.at)).toEqual([1, 2]); // first `a` kept, second dropped
|
|
57
57
|
expect(onDup).toHaveBeenCalledWith('a', 3);
|
|
58
58
|
});
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* REGRESSION GUARD for the "one folder = one space" model.
|
|
62
|
+
*
|
|
63
|
+
* Spaces are grouping folders under the catalog root, and a tool or skill
|
|
64
|
+
* shared by two spaces is expected to be duplicated as two files with
|
|
65
|
+
* DISTINCT ids. Nothing enforces that convention — `seen` is a single
|
|
66
|
+
* global Set keyed on the declared id, with no notion of the folder the
|
|
67
|
+
* item came from. So the moment two spaces hold a same-named item, one of
|
|
68
|
+
* them silently disappears from the catalog.
|
|
69
|
+
*
|
|
70
|
+
* These tests pin that behaviour so it is a documented, observable
|
|
71
|
+
* property rather than a surprise. If dedup ever becomes folder-scoped,
|
|
72
|
+
* they are the tests that should change.
|
|
73
|
+
*/
|
|
74
|
+
test('same id in two different space folders: the second folder loses its copy', () => {
|
|
75
|
+
const onDup = vi.fn();
|
|
76
|
+
// Services sort by (name, path) before deduping, so path order is stable.
|
|
77
|
+
const items = [
|
|
78
|
+
{ name: 'notion', path: 'Tools/Everyone/notion.tool' },
|
|
79
|
+
{ name: 'notion', path: 'Tools/Finance/notion.tool' },
|
|
80
|
+
];
|
|
81
|
+
const out = dedupeById(items, (x) => x.name, (x, id) => onDup(id, x.path));
|
|
82
|
+
|
|
83
|
+
expect(out).toHaveLength(1);
|
|
84
|
+
expect(out[0].path).toBe('Tools/Everyone/notion.tool');
|
|
85
|
+
// The Finance space loses its tool entirely — only a server-side warning
|
|
86
|
+
// marks it, which is why the convention needs distinct ids per space.
|
|
87
|
+
expect(onDup).toHaveBeenCalledWith('notion', 'Tools/Finance/notion.tool');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('distinct ids per space folder keep BOTH copies — the supported pattern', () => {
|
|
91
|
+
const onDup = vi.fn();
|
|
92
|
+
const items = [
|
|
93
|
+
{ name: 'everyone_notion', path: 'Tools/Everyone/notion.tool' },
|
|
94
|
+
{ name: 'finance_notion', path: 'Tools/Finance/notion.tool' },
|
|
95
|
+
];
|
|
96
|
+
const out = dedupeById(items, (x) => x.name, (x, id) => onDup(id, x.path));
|
|
97
|
+
|
|
98
|
+
expect(out).toHaveLength(2);
|
|
99
|
+
expect(onDup).not.toHaveBeenCalled();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('the surviving copy is the alphabetically-first path, not scan order', () => {
|
|
103
|
+
// Deterministic winner matters: an unstable one means a space's tool
|
|
104
|
+
// appears or vanishes depending on filesystem iteration order.
|
|
105
|
+
const items = [
|
|
106
|
+
{ name: 'x', path: 'Tools/Zulu/x.tool' },
|
|
107
|
+
{ name: 'x', path: 'Tools/Alpha/x.tool' },
|
|
108
|
+
].sort((a, b) => a.name.localeCompare(b.name) || a.path.localeCompare(b.path));
|
|
109
|
+
|
|
110
|
+
expect(dedupeById(items, (i) => i.name)[0].path).toBe('Tools/Alpha/x.tool');
|
|
111
|
+
});
|
|
59
112
|
});
|
|
60
113
|
|
|
61
114
|
describe('setFrontmatterField (shared, line-based)', () => {
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { isJoinBranchFor, joinBranchFor, kebabGroupName } from '@bevel-software/platform-shared';
|
|
3
|
+
import { assertValidBranchName } from '../../modules/workflow/git/branch-name.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The join-branch convention. Two properties matter, and they pull in
|
|
7
|
+
* different directions:
|
|
8
|
+
*
|
|
9
|
+
* - UNIQUENESS (the write side): distinct requesters and distinct groups must
|
|
10
|
+
* never share a branch, or one person's commit lands on another's request.
|
|
11
|
+
* Both inputs the name is built from are lossy; the requester tag fixes it.
|
|
12
|
+
* - EXACT GROUP IDENTITY (the read side): the settle decision is "the diff
|
|
13
|
+
* is empty", so matching a branch to the WRONG group reads an unchanged
|
|
14
|
+
* file, sees an empty diff, and destroys somebody else's request. The
|
|
15
|
+
* group tag is recomputed from the exact name so shape-matching can never
|
|
16
|
+
* cross groups; only the requester half matches by shape (the reader has
|
|
17
|
+
* no email to recompute it from).
|
|
18
|
+
*/
|
|
19
|
+
const TAG = '[0-9a-z]{7}';
|
|
20
|
+
|
|
21
|
+
describe('joinBranchFor', () => {
|
|
22
|
+
it('produces a valid branch name that follows the draft convention', () => {
|
|
23
|
+
const branch = joinBranchFor('ali@bevel.software', 'GTM');
|
|
24
|
+
expect(branch).toMatch(new RegExp(`^ali/join-gtm-${TAG}-${TAG}$`));
|
|
25
|
+
expect(() => assertValidBranchName(branch)).not.toThrow();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('is deterministic, and case-insensitive in the email only', () => {
|
|
29
|
+
expect(joinBranchFor('Ali@Bevel.Software', 'GTM')).toBe(joinBranchFor('ali@bevel.software', 'GTM'));
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('separates requesters who share a localpart across domains', () => {
|
|
33
|
+
// Regression: without the requester tag both collapse to one branch, so
|
|
34
|
+
// the second requester's grant commit lands on the first one's branch.
|
|
35
|
+
expect(joinBranchFor('ali@bevel.software', 'GTM')).not.toBe(
|
|
36
|
+
joinBranchFor('ali@other.com', 'GTM'),
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('separates groups whose names kebab to the same slug', () => {
|
|
41
|
+
expect(joinBranchFor('ali@bevel.software', 'Finance!')).not.toBe(
|
|
42
|
+
joinBranchFor('ali@bevel.software', 'Finance'),
|
|
43
|
+
);
|
|
44
|
+
// Case is part of a group's identity (the folder name is case-sensitive).
|
|
45
|
+
expect(joinBranchFor('ali@bevel.software', 'finance')).not.toBe(
|
|
46
|
+
joinBranchFor('ali@bevel.software', 'Finance'),
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('still yields a valid, matchable branch for a group with no alphanumerics', () => {
|
|
51
|
+
const branch = joinBranchFor('ali@bevel.software', '!!!');
|
|
52
|
+
expect(kebabGroupName('!!!')).toBe('');
|
|
53
|
+
expect(branch).toMatch(new RegExp(`^ali/join-${TAG}-${TAG}$`));
|
|
54
|
+
expect(() => assertValidBranchName(branch)).not.toThrow();
|
|
55
|
+
expect(isJoinBranchFor(branch, '!!!')).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe('isJoinBranchFor', () => {
|
|
60
|
+
it("recognises somebody ELSE's join branch (the requester tag is not recomputed)", () => {
|
|
61
|
+
expect(isJoinBranchFor(joinBranchFor('juan@bevel.software', 'GTM'), 'GTM')).toBe(true);
|
|
62
|
+
expect(isJoinBranchFor(joinBranchFor('ali@other.com', 'GTM'), 'GTM')).toBe(true);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('rejects a branch for a different group', () => {
|
|
66
|
+
expect(isJoinBranchFor(joinBranchFor('ali@bevel.software', 'Finance'), 'GTM')).toBe(false);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('NEVER crosses slug-colliding groups — the destructive-settle regression', () => {
|
|
70
|
+
// `Finance!`, `finance` and `Finance` all slug to `finance`. A listing
|
|
71
|
+
// for one that matched another's branch would read that branch's copy of
|
|
72
|
+
// ITS OWN access.md (unchanged there), see an empty diff, and settle —
|
|
73
|
+
// closing a change request and deleting a branch belonging to a
|
|
74
|
+
// different group. The recomputed group tag is what forbids the match.
|
|
75
|
+
const forBang = joinBranchFor('ali@bevel.software', 'Finance!');
|
|
76
|
+
expect(isJoinBranchFor(forBang, 'finance')).toBe(false);
|
|
77
|
+
expect(isJoinBranchFor(forBang, 'Finance')).toBe(false);
|
|
78
|
+
expect(isJoinBranchFor(forBang, 'Finance!')).toBe(true);
|
|
79
|
+
expect(isJoinBranchFor(joinBranchFor('ali@bevel.software', 'finance'), 'Finance!')).toBe(false);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('rejects ordinary draft branches and near-misses', () => {
|
|
83
|
+
const good = joinBranchFor('ali@bevel.software', 'GTM');
|
|
84
|
+
const [, suffix] = good.split('/');
|
|
85
|
+
for (const branch of [
|
|
86
|
+
'ali/gtm',
|
|
87
|
+
'ali/join-gtm', // no tags — the pre-tag shape
|
|
88
|
+
'ali/join-gtm-abc1234', // one tag only
|
|
89
|
+
`ali/${suffix.toUpperCase()}`, // tags are lowercase base36
|
|
90
|
+
`ali/${suffix}/extra`,
|
|
91
|
+
suffix, // no author segment
|
|
92
|
+
]) {
|
|
93
|
+
expect(isJoinBranchFor(branch, 'GTM'), branch).toBe(false);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { groupOfPath, GROUPS_DIR } from '@bevel-software/platform-shared';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `groupOfPath` is the whole of the grouping contract — the sidebar, the
|
|
6
|
+
* catalog buckets and the access story all read a group off a path with it.
|
|
7
|
+
* The cases that matter are the ones where "has a group" and "is under the
|
|
8
|
+
* group root" come apart.
|
|
9
|
+
*/
|
|
10
|
+
describe('groupOfPath', () => {
|
|
11
|
+
it('reads the group from the Groups root', () => {
|
|
12
|
+
expect(groupOfPath(`${GROUPS_DIR}/GTM/heyreach-campaign/SKILL.md`)).toBe('GTM');
|
|
13
|
+
expect(groupOfPath(`${GROUPS_DIR}/GTM/heyreach.tool`)).toBe('GTM');
|
|
14
|
+
expect(groupOfPath(`${GROUPS_DIR}/Engineering/review/architecture-review`)).toBe(
|
|
15
|
+
'Engineering',
|
|
16
|
+
);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('returns null for content directly under the root — it has no group folder', () => {
|
|
20
|
+
// The regression this guards: `Groups/slack.tool` must NOT report a group
|
|
21
|
+
// called "slack.tool", and `Groups/GTM` must not report itself.
|
|
22
|
+
expect(groupOfPath(`${GROUPS_DIR}/slack.tool`)).toBeNull();
|
|
23
|
+
expect(groupOfPath(`${GROUPS_DIR}/GTM`)).toBeNull();
|
|
24
|
+
expect(groupOfPath(GROUPS_DIR)).toBeNull();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('returns null outside the group root', () => {
|
|
28
|
+
expect(groupOfPath('KnowledgeBase/Product/Knowledge/Foo.md')).toBeNull();
|
|
29
|
+
expect(groupOfPath('Data/Engineering/Knowledge/Bar.md')).toBeNull();
|
|
30
|
+
// The retired pre-merge roots are ordinary non-group folders now.
|
|
31
|
+
expect(groupOfPath('Skills/GTM/heyreach-campaign')).toBeNull();
|
|
32
|
+
expect(groupOfPath('Tools/NewsAgent/serper.tool')).toBeNull();
|
|
33
|
+
expect(groupOfPath('access.md')).toBeNull();
|
|
34
|
+
expect(groupOfPath('')).toBeNull();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('is not fooled by a prefix match on the root name', () => {
|
|
38
|
+
expect(groupOfPath('GroupsOld/GTM/x')).toBeNull();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('tolerates leading and doubled separators', () => {
|
|
42
|
+
expect(groupOfPath(`/${GROUPS_DIR}/GTM/x`)).toBe('GTM');
|
|
43
|
+
expect(groupOfPath(`${GROUPS_DIR}//GTM//x`)).toBe('GTM');
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -41,8 +41,8 @@ describe('ontologyOf', () => {
|
|
|
41
41
|
expect(ontologyOf('KnowledgeBase/Ops/Knowledge/x.md')).toBe('KnowledgeBase/Ops');
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
it('returns null for
|
|
45
|
-
expect(ontologyOf('
|
|
44
|
+
it('returns null for Groups and root config (neutral)', () => {
|
|
45
|
+
expect(ontologyOf('Groups/some-skill/SKILL.md')).toBeNull();
|
|
46
46
|
expect(ontologyOf('access.md')).toBeNull();
|
|
47
47
|
expect(ontologyOf('roles.yaml')).toBeNull();
|
|
48
48
|
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { branchModelFromEnv, configureBranchModel } from '@bevel-software/platform-shared';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Apply the branch model before any suite imports something that reads it.
|
|
5
|
+
*
|
|
6
|
+
* The shared module no longer reads `process.env` at import time — both sides
|
|
7
|
+
* configure it during boot instead (`createCoreServices` here, a fetch of
|
|
8
|
+
* `/api/config` in the browser). Suites exercise pieces of the server without
|
|
9
|
+
* going through `createCoreServices`, so the same call has to happen for them.
|
|
10
|
+
*
|
|
11
|
+
* It must live in `setupFiles` rather than `vitest.config.ts`: the config is
|
|
12
|
+
* evaluated in its own module graph, so a call there configures a copy of the
|
|
13
|
+
* shared module that no test ever sees.
|
|
14
|
+
*
|
|
15
|
+
* The values come from the environment the config pins, which keeps the one
|
|
16
|
+
* place the historical two-branch pair is written.
|
|
17
|
+
*/
|
|
18
|
+
configureBranchModel(branchModelFromEnv());
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Agents/
|
|
2
|
-
|
|
3
|
-
`.agent` files — **role definitions for agents**, and the main way anyone
|
|
4
|
-
(a person's own assistant or a background pipeline) connects to the platform.
|
|
5
|
-
Connecting "as" an `.agent` mints exactly that agent's tool surface — e.g. the
|
|
6
|
-
KB's MCP config is generated per `.agent`, not from everything the identity
|
|
7
|
-
can read.
|
|
8
|
-
|
|
9
|
-
## Structure
|
|
10
|
-
|
|
11
|
-
```text
|
|
12
|
-
Agents/
|
|
13
|
-
├── default.agent ← the safe floor: basic KB access only
|
|
14
|
-
├── developer.agent ← an admin-authored role: everything developers get
|
|
15
|
-
└── <role-or-pipeline>.agent
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
One file per role or per pipeline agent. (Exact file format: TBD.)
|
|
19
|
-
|
|
20
|
-
## What an `.agent` defines
|
|
21
|
-
|
|
22
|
-
- The **target harness** (e.g. Claude Code) and model / reasoning settings.
|
|
23
|
-
- The **skills** and **tools** composed in — selections from `Skills/` and
|
|
24
|
-
`Tools/`. The execution layer compiles these into the harness's native
|
|
25
|
-
plugin format and installs it.
|
|
26
|
-
- Permissions/allowlists, hooks, MCP servers, env vars, session defaults,
|
|
27
|
-
and injected instructions (the agent's charter).
|
|
28
|
-
- **References** to an identity and a budget — never credentials themselves.
|
|
29
|
-
|
|
30
|
-
## Rules
|
|
31
|
-
|
|
32
|
-
- An `.agent` only **narrows** what its identity's permissions already allow —
|
|
33
|
-
it never widens access. Identity remains the security boundary; `.agent`
|
|
34
|
-
is configuration.
|
|
35
|
-
- **No secret values** in these files — secrets are referenced by vault name.
|
|
36
|
-
- This folder sits under access control + change requests: editing a role
|
|
37
|
-
file changes the whole role's tooling, and is reviewed like any other
|
|
38
|
-
change.
|