@bevel-software/platform-core-backend 0.25.2 → 0.27.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 +251 -0
- package/agent-guide/conventions.md +35 -0
- package/agent-guide/directory-structure.md +145 -0
- package/agent-guide/finding-things.md +7 -0
- package/agent-guide/html-views.md +83 -0
- package/agent-guide/introduction.md +27 -0
- package/agent-guide/new-knowledge-base.md +24 -0
- package/agent-guide/skills.md +47 -0
- package/agent-guide/tool-manuals.md +227 -0
- package/agent-guide/where-a-new-file-goes.md +36 -0
- package/dist/assets.d.ts +26 -0
- package/dist/assets.d.ts.map +1 -1
- package/dist/assets.js +35 -2
- package/dist/assets.js.map +1 -1
- package/dist/core/catalog-revision.d.ts +19 -1
- package/dist/core/catalog-revision.d.ts.map +1 -1
- package/dist/core/catalog-revision.js +14 -3
- package/dist/core/catalog-revision.js.map +1 -1
- package/dist/core/core-ports.d.ts +11 -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 +5 -0
- package/dist/core/create-core-server.d.ts.map +1 -1
- package/dist/core/create-core-server.js +65 -3
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +35 -0
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +114 -12
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/core/lifecycle.d.ts +16 -1
- package/dist/core/lifecycle.d.ts.map +1 -1
- package/dist/core/lifecycle.js +18 -1
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/core-config.d.ts +21 -0
- package/dist/core-config.d.ts.map +1 -1
- package/dist/core-config.js +22 -1
- package/dist/core-config.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/modules/access/access-control.interface.d.ts +17 -0
- package/dist/modules/access/access-control.interface.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +2 -0
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +27 -0
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/access/directory-sync-bot.js +1 -1
- package/dist/modules/access/directory-sync-bot.js.map +1 -1
- package/dist/modules/agent-guide/agent-guide.d.ts +145 -0
- package/dist/modules/agent-guide/agent-guide.d.ts.map +1 -0
- package/dist/modules/agent-guide/agent-guide.js +199 -0
- package/dist/modules/agent-guide/agent-guide.js.map +1 -0
- package/dist/modules/agent-guide/agent-guide.tools.d.ts +24 -0
- package/dist/modules/agent-guide/agent-guide.tools.d.ts.map +1 -0
- package/dist/modules/agent-guide/agent-guide.tools.js +100 -0
- package/dist/modules/agent-guide/agent-guide.tools.js.map +1 -0
- package/dist/modules/agent-guide/index.d.ts +4 -0
- package/dist/modules/agent-guide/index.d.ts.map +1 -0
- package/dist/modules/agent-guide/index.js +4 -0
- package/dist/modules/agent-guide/index.js.map +1 -0
- package/dist/modules/agent-instructions/agent-instructions.routes.d.ts +3 -2
- package/dist/modules/agent-instructions/agent-instructions.routes.d.ts.map +1 -1
- package/dist/modules/agent-instructions/agent-instructions.routes.js +3 -2
- package/dist/modules/agent-instructions/agent-instructions.routes.js.map +1 -1
- package/dist/modules/agent-instructions/compose.d.ts +14 -6
- package/dist/modules/agent-instructions/compose.d.ts.map +1 -1
- package/dist/modules/agent-instructions/compose.js +28 -8
- package/dist/modules/agent-instructions/compose.js.map +1 -1
- package/dist/modules/agent-instructions/index.d.ts +1 -1
- package/dist/modules/agent-instructions/index.d.ts.map +1 -1
- package/dist/modules/agent-instructions/index.js +1 -1
- package/dist/modules/agent-instructions/index.js.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.d.ts +10 -50
- package/dist/modules/agent-instructions/shared-file-rules.d.ts.map +1 -1
- package/dist/modules/agent-instructions/shared-file-rules.js +51 -104
- package/dist/modules/agent-instructions/shared-file-rules.js.map +1 -1
- package/dist/modules/audit/agent-audit.service.d.ts +21 -2
- package/dist/modules/audit/agent-audit.service.d.ts.map +1 -1
- package/dist/modules/audit/agent-audit.service.js +43 -2
- package/dist/modules/audit/agent-audit.service.js.map +1 -1
- package/dist/modules/audit/agent-connection.routes.d.ts +34 -0
- package/dist/modules/audit/agent-connection.routes.d.ts.map +1 -0
- package/dist/modules/audit/agent-connection.routes.js +38 -0
- package/dist/modules/audit/agent-connection.routes.js.map +1 -0
- package/dist/modules/audit/audit.contract.d.ts +24 -0
- package/dist/modules/audit/audit.contract.d.ts.map +1 -1
- package/dist/modules/audit/audit.contract.js.map +1 -1
- package/dist/modules/audit/index.d.ts +1 -0
- package/dist/modules/audit/index.d.ts.map +1 -1
- package/dist/modules/audit/index.js +1 -0
- package/dist/modules/audit/index.js.map +1 -1
- package/dist/modules/auth/account.routes.d.ts.map +1 -1
- package/dist/modules/auth/account.routes.js +10 -3
- package/dist/modules/auth/account.routes.js.map +1 -1
- package/dist/modules/auth/auth.middleware.d.ts +7 -0
- package/dist/modules/auth/auth.middleware.d.ts.map +1 -1
- package/dist/modules/auth/auth.middleware.js +1 -1
- package/dist/modules/auth/auth.middleware.js.map +1 -1
- package/dist/modules/code-mode/code-mode.tool.d.ts.map +1 -1
- package/dist/modules/code-mode/code-mode.tool.js +11 -3
- package/dist/modules/code-mode/code-mode.tool.js.map +1 -1
- package/dist/modules/database/core-schema.d.ts +96 -0
- package/dist/modules/database/core-schema.d.ts.map +1 -1
- package/dist/modules/database/core-schema.js +32 -3
- package/dist/modules/database/core-schema.js.map +1 -1
- package/dist/modules/embed/account-link.service.d.ts +42 -0
- package/dist/modules/embed/account-link.service.d.ts.map +1 -0
- package/dist/modules/embed/account-link.service.js +50 -0
- package/dist/modules/embed/account-link.service.js.map +1 -0
- package/dist/modules/embed/embed-link.d.ts +58 -0
- package/dist/modules/embed/embed-link.d.ts.map +1 -0
- package/dist/modules/embed/embed-link.js +160 -0
- package/dist/modules/embed/embed-link.js.map +1 -0
- package/dist/modules/embed/embed.errors.d.ts +30 -0
- package/dist/modules/embed/embed.errors.d.ts.map +1 -0
- package/dist/modules/embed/embed.errors.js +42 -0
- package/dist/modules/embed/embed.errors.js.map +1 -0
- package/dist/modules/embed/embed.interface.d.ts +204 -0
- package/dist/modules/embed/embed.interface.d.ts.map +1 -0
- package/dist/modules/embed/embed.interface.js +2 -0
- package/dist/modules/embed/embed.interface.js.map +1 -0
- package/dist/modules/embed/embed.routes.d.ts +59 -0
- package/dist/modules/embed/embed.routes.d.ts.map +1 -0
- package/dist/modules/embed/embed.routes.js +343 -0
- package/dist/modules/embed/embed.routes.js.map +1 -0
- package/dist/modules/embed/embed.service.d.ts +169 -0
- package/dist/modules/embed/embed.service.d.ts.map +1 -0
- package/dist/modules/embed/embed.service.js +627 -0
- package/dist/modules/embed/embed.service.js.map +1 -0
- package/dist/modules/embed/embed.tools.d.ts +51 -0
- package/dist/modules/embed/embed.tools.d.ts.map +1 -0
- package/dist/modules/embed/embed.tools.js +170 -0
- package/dist/modules/embed/embed.tools.js.map +1 -0
- package/dist/modules/embed/mcp-app.d.ts +64 -0
- package/dist/modules/embed/mcp-app.d.ts.map +1 -0
- package/dist/modules/embed/mcp-app.js +147 -0
- package/dist/modules/embed/mcp-app.js.map +1 -0
- package/dist/modules/embed/mcp-app.routes.d.ts +21 -0
- package/dist/modules/embed/mcp-app.routes.d.ts.map +1 -0
- package/dist/modules/embed/mcp-app.routes.js +36 -0
- package/dist/modules/embed/mcp-app.routes.js.map +1 -0
- package/dist/modules/github-app/github-app.connection.d.ts +15 -0
- package/dist/modules/github-app/github-app.connection.d.ts.map +1 -1
- package/dist/modules/github-app/github-app.connection.js +34 -3
- package/dist/modules/github-app/github-app.connection.js.map +1 -1
- package/dist/modules/kb-fs/locking-filesystem.d.ts +65 -0
- package/dist/modules/kb-fs/locking-filesystem.d.ts.map +1 -1
- package/dist/modules/kb-fs/locking-filesystem.js +300 -0
- package/dist/modules/kb-fs/locking-filesystem.js.map +1 -1
- package/dist/modules/kb-sync/kb-sync.interface.d.ts +5 -0
- package/dist/modules/kb-sync/kb-sync.interface.d.ts.map +1 -1
- package/dist/modules/kb-sync/kb-sync.service.d.ts.map +1 -1
- package/dist/modules/kb-sync/kb-sync.service.js +6 -0
- package/dist/modules/kb-sync/kb-sync.service.js.map +1 -1
- package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
- package/dist/modules/mcp/mcp-auth.middleware.js +2 -1
- package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
- package/dist/modules/mcp/mcp.service.d.ts +57 -3
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.service.js +177 -24
- package/dist/modules/mcp/mcp.service.js.map +1 -1
- package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts +24 -0
- package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js +32 -4
- package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
- package/dist/modules/mcp/tool-schema-guard.d.ts +105 -0
- package/dist/modules/mcp/tool-schema-guard.d.ts.map +1 -0
- package/dist/modules/mcp/tool-schema-guard.js +171 -0
- package/dist/modules/mcp/tool-schema-guard.js.map +1 -0
- package/dist/modules/onboarding/onboarding.contract.d.ts +80 -0
- package/dist/modules/onboarding/onboarding.contract.d.ts.map +1 -0
- package/dist/modules/onboarding/onboarding.contract.js +7 -0
- package/dist/modules/onboarding/onboarding.contract.js.map +1 -0
- package/dist/modules/onboarding/onboarding.routes.d.ts +18 -0
- package/dist/modules/onboarding/onboarding.routes.d.ts.map +1 -0
- package/dist/modules/onboarding/onboarding.routes.js +81 -0
- package/dist/modules/onboarding/onboarding.routes.js.map +1 -0
- package/dist/modules/onboarding/starter-pack.service.d.ts +213 -0
- package/dist/modules/onboarding/starter-pack.service.d.ts.map +1 -0
- package/dist/modules/onboarding/starter-pack.service.js +492 -0
- package/dist/modules/onboarding/starter-pack.service.js.map +1 -0
- package/dist/modules/onboarding/starter-packs.d.ts +78 -0
- package/dist/modules/onboarding/starter-packs.d.ts.map +1 -0
- package/dist/modules/onboarding/starter-packs.js +156 -0
- package/dist/modules/onboarding/starter-packs.js.map +1 -0
- package/dist/modules/plugins/index.d.ts +1 -1
- package/dist/modules/plugins/index.d.ts.map +1 -1
- package/dist/modules/plugins/index.js +1 -1
- package/dist/modules/plugins/index.js.map +1 -1
- package/dist/modules/plugins/plugin-provision.service.d.ts +19 -0
- package/dist/modules/plugins/plugin-provision.service.d.ts.map +1 -1
- package/dist/modules/plugins/plugin-provision.service.js +18 -1
- package/dist/modules/plugins/plugin-provision.service.js.map +1 -1
- package/dist/modules/plugins/plugins.routes.d.ts +0 -36
- package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
- package/dist/modules/plugins/plugins.routes.js +31 -0
- package/dist/modules/plugins/plugins.routes.js.map +1 -1
- package/dist/modules/plugins/plugins.tools.d.ts +36 -2
- package/dist/modules/plugins/plugins.tools.d.ts.map +1 -1
- package/dist/modules/plugins/plugins.tools.js +71 -14
- package/dist/modules/plugins/plugins.tools.js.map +1 -1
- package/dist/modules/settings/deployment-settings.service.d.ts +34 -7
- package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
- package/dist/modules/settings/deployment-settings.service.js +148 -54
- package/dist/modules/settings/deployment-settings.service.js.map +1 -1
- package/dist/modules/settings/repository-source.d.ts +1 -0
- package/dist/modules/settings/repository-source.d.ts.map +1 -1
- package/dist/modules/settings/repository-source.js +3 -3
- package/dist/modules/settings/repository-source.js.map +1 -1
- package/dist/modules/settings/setup.routes.d.ts.map +1 -1
- package/dist/modules/settings/setup.routes.js +3 -6
- package/dist/modules/settings/setup.routes.js.map +1 -1
- package/dist/modules/skills/skills.tools.d.ts.map +1 -1
- package/dist/modules/skills/skills.tools.js +103 -43
- package/dist/modules/skills/skills.tools.js.map +1 -1
- package/dist/modules/tool-auth/connection-key-rejection.d.ts +10 -1
- package/dist/modules/tool-auth/connection-key-rejection.d.ts.map +1 -1
- package/dist/modules/tool-auth/connection-key-rejection.js +11 -3
- package/dist/modules/tool-auth/connection-key-rejection.js.map +1 -1
- package/dist/modules/tool-auth/external-api-key.interface.d.ts +8 -0
- package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -1
- package/dist/modules/tool-auth/external-api-key.service.d.ts +24 -2
- package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
- package/dist/modules/tool-auth/external-api-key.service.js +59 -2
- package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
- package/dist/modules/tool-auth/tool-auth.middleware.js +9 -4
- package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
- package/dist/modules/tool-helpers/index.d.ts +28 -1
- package/dist/modules/tool-helpers/index.d.ts.map +1 -1
- package/dist/modules/tool-helpers/index.js +28 -1
- package/dist/modules/tool-helpers/index.js.map +1 -1
- package/dist/modules/tool-helpers/route-argument-check.d.ts +10 -0
- package/dist/modules/tool-helpers/route-argument-check.d.ts.map +1 -0
- package/dist/modules/tool-helpers/route-argument-check.js +132 -0
- package/dist/modules/tool-helpers/route-argument-check.js.map +1 -0
- package/dist/modules/tool-helpers/route-tool-schemas.d.ts +89 -0
- package/dist/modules/tool-helpers/route-tool-schemas.d.ts.map +1 -0
- package/dist/modules/tool-helpers/route-tool-schemas.js +113 -0
- package/dist/modules/tool-helpers/route-tool-schemas.js.map +1 -0
- package/dist/modules/tool-helpers/tool-def.d.ts +71 -0
- package/dist/modules/tool-helpers/tool-def.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool-def.js +70 -6
- package/dist/modules/tool-helpers/tool-def.js.map +1 -1
- package/dist/modules/tool-helpers/tool-handler.d.ts +46 -6
- package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool-handler.js +157 -8
- package/dist/modules/tool-helpers/tool-handler.js.map +1 -1
- package/dist/modules/tool-helpers/tool.contract.d.ts +9 -0
- package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -1
- package/dist/modules/tool-helpers/tool.contract.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +23 -4
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.contract.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts +4 -0
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.js +14 -0
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +7 -0
- package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.js +77 -38
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
- package/dist/modules/tool-registry/description-length.d.ts +20 -16
- package/dist/modules/tool-registry/description-length.d.ts.map +1 -1
- package/dist/modules/tool-registry/description-length.js +50 -30
- package/dist/modules/tool-registry/description-length.js.map +1 -1
- package/dist/modules/tool-registry/guide-first.d.ts +27 -0
- package/dist/modules/tool-registry/guide-first.d.ts.map +1 -0
- package/dist/modules/tool-registry/guide-first.js +40 -0
- package/dist/modules/tool-registry/guide-first.js.map +1 -0
- package/dist/modules/tool-registry/tool-registry.d.ts +6 -0
- package/dist/modules/tool-registry/tool-registry.d.ts.map +1 -1
- package/dist/modules/tool-registry/tool-registry.js +9 -2
- package/dist/modules/tool-registry/tool-registry.js.map +1 -1
- package/dist/modules/workflow/agent-tools/change-request-read-shape.d.ts +449 -0
- package/dist/modules/workflow/agent-tools/change-request-read-shape.d.ts.map +1 -0
- package/dist/modules/workflow/agent-tools/change-request-read-shape.js +481 -0
- package/dist/modules/workflow/agent-tools/change-request-read-shape.js.map +1 -0
- package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts +126 -0
- package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts.map +1 -0
- package/dist/modules/workflow/agent-tools/change-request-read.tools.js +611 -0
- package/dist/modules/workflow/agent-tools/change-request-read.tools.js.map +1 -0
- package/dist/modules/workflow/agent-tools/change-request-summary.d.ts +12 -1
- package/dist/modules/workflow/agent-tools/change-request-summary.d.ts.map +1 -1
- package/dist/modules/workflow/agent-tools/change-request-summary.js +5 -1
- package/dist/modules/workflow/agent-tools/change-request-summary.js.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +8 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.js +133 -37
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
- package/dist/modules/workflow/file-lock.service.d.ts +29 -5
- package/dist/modules/workflow/file-lock.service.d.ts.map +1 -1
- package/dist/modules/workflow/file-lock.service.js +62 -5
- package/dist/modules/workflow/file-lock.service.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +282 -14
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +627 -126
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workflow/git/merge-commit.d.ts +73 -0
- package/dist/modules/workflow/git/merge-commit.d.ts.map +1 -0
- package/dist/modules/workflow/git/merge-commit.js +89 -0
- package/dist/modules/workflow/git/merge-commit.js.map +1 -0
- package/dist/modules/workflow/git/node-git-runner.d.ts +15 -0
- package/dist/modules/workflow/git/node-git-runner.d.ts.map +1 -1
- package/dist/modules/workflow/git/node-git-runner.js +78 -6
- package/dist/modules/workflow/git/node-git-runner.js.map +1 -1
- package/dist/modules/workflow/git/pull-request.service.d.ts +94 -1
- package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/pull-request.service.js +332 -37
- package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
- package/dist/modules/workflow/pending-commits.service.d.ts +15 -0
- package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -1
- package/dist/modules/workflow/pending-commits.service.js +25 -1
- package/dist/modules/workflow/pending-commits.service.js.map +1 -1
- package/dist/modules/workflow/pending-commits.worker.d.ts +6 -1
- package/dist/modules/workflow/pending-commits.worker.d.ts.map +1 -1
- package/dist/modules/workflow/pending-commits.worker.js +23 -6
- package/dist/modules/workflow/pending-commits.worker.js.map +1 -1
- package/dist/modules/workflow/recovery-bot.js +1 -1
- package/dist/modules/workflow/recovery-bot.js.map +1 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts +35 -0
- package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/review-workflow/review-workflow.service.js +180 -13
- package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
- package/dist/modules/workflow/sanitize-error.d.ts +16 -0
- package/dist/modules/workflow/sanitize-error.d.ts.map +1 -1
- package/dist/modules/workflow/sanitize-error.js +45 -0
- package/dist/modules/workflow/sanitize-error.js.map +1 -1
- package/dist/modules/workflow/workflow.routes.d.ts +6 -2
- package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.routes.js +7 -2
- package/dist/modules/workflow/workflow.routes.js.map +1 -1
- package/dist/modules/workflow/workflow.service.d.ts +187 -15
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +808 -106
- package/dist/modules/workflow/workflow.service.js.map +1 -1
- package/dist/modules/workspace/agent-download.builder.d.ts +105 -0
- package/dist/modules/workspace/agent-download.builder.d.ts.map +1 -0
- package/dist/modules/workspace/agent-download.builder.js +238 -0
- package/dist/modules/workspace/agent-download.builder.js.map +1 -0
- package/dist/modules/workspace/agent-download.routes.d.ts +77 -0
- package/dist/modules/workspace/agent-download.routes.d.ts.map +1 -0
- package/dist/modules/workspace/agent-download.routes.js +156 -0
- package/dist/modules/workspace/agent-download.routes.js.map +1 -0
- package/dist/modules/workspace/agent-download.store.d.ts +225 -0
- package/dist/modules/workspace/agent-download.store.d.ts.map +1 -0
- package/dist/modules/workspace/agent-download.store.js +423 -0
- package/dist/modules/workspace/agent-download.store.js.map +1 -0
- package/dist/modules/workspace/agent-upload.store.d.ts +10 -1
- package/dist/modules/workspace/agent-upload.store.d.ts.map +1 -1
- package/dist/modules/workspace/agent-upload.store.js +16 -6
- package/dist/modules/workspace/agent-upload.store.js.map +1 -1
- package/dist/modules/workspace/file-readers/raw-mime.d.ts +6 -0
- package/dist/modules/workspace/file-readers/raw-mime.d.ts.map +1 -0
- package/dist/modules/workspace/file-readers/raw-mime.js +38 -0
- package/dist/modules/workspace/file-readers/raw-mime.js.map +1 -0
- package/dist/modules/workspace/file-readers/text-reader.d.ts +5 -5
- package/dist/modules/workspace/file-readers/text-reader.d.ts.map +1 -1
- package/dist/modules/workspace/file-readers/text-reader.js +5 -8
- package/dist/modules/workspace/file-readers/text-reader.js.map +1 -1
- package/dist/modules/workspace/first-run.d.ts +111 -0
- package/dist/modules/workspace/first-run.d.ts.map +1 -0
- package/dist/modules/workspace/first-run.js +181 -0
- package/dist/modules/workspace/first-run.js.map +1 -0
- package/dist/modules/workspace/move-links.d.ts +92 -0
- package/dist/modules/workspace/move-links.d.ts.map +1 -0
- package/dist/modules/workspace/move-links.js +173 -0
- package/dist/modules/workspace/move-links.js.map +1 -0
- package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.js +24 -39
- package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
- package/dist/modules/workspace/startup/steps/template-files.step.d.ts +58 -52
- package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/template-files.step.js +209 -223
- package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
- package/dist/modules/workspace/startup/steps/template-source.d.ts +5 -3
- package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/template-source.js +5 -3
- package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
- package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.routes.js +63 -22
- package/dist/modules/workspace/workspace.routes.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +75 -2
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +197 -24
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/modules/workspace/workspace.tools.d.ts +68 -1
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +642 -71
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/modules/write-access/write-access.d.ts.map +1 -1
- package/dist/modules/write-access/write-access.js +9 -0
- package/dist/modules/write-access/write-access.js.map +1 -1
- package/dist/shared/domain-errors.d.ts +84 -1
- package/dist/shared/domain-errors.d.ts.map +1 -1
- package/dist/shared/domain-errors.js +100 -12
- package/dist/shared/domain-errors.js.map +1 -1
- package/dist/shared/git.contract.d.ts +10 -1
- package/dist/shared/git.contract.d.ts.map +1 -1
- package/dist/shared/git.contract.js.map +1 -1
- package/dist/shared/hidden-tools.d.ts +44 -0
- package/dist/shared/hidden-tools.d.ts.map +1 -0
- package/dist/shared/hidden-tools.js +13 -0
- package/dist/shared/hidden-tools.js.map +1 -0
- package/dist/shared/utf8-text.d.ts +15 -0
- package/dist/shared/utf8-text.d.ts.map +1 -0
- package/dist/shared/utf8-text.js +20 -0
- package/dist/shared/utf8-text.js.map +1 -0
- package/dist/tenancy/static-tenant-source.d.ts +2 -1
- package/dist/tenancy/static-tenant-source.d.ts.map +1 -1
- package/dist/tenancy/static-tenant-source.js +9 -2
- package/dist/tenancy/static-tenant-source.js.map +1 -1
- package/kb-template/.bevelignore +0 -5
- package/mcp-app/page.html +349 -0
- package/migrations/0017_atlassian_account_links.sql +37 -0
- package/migrations/meta/0017_snapshot.json +2396 -0
- package/migrations/meta/_journal.json +8 -1
- package/package.json +6 -3
- package/src/__tests__/kb-layout-config.test.ts +10 -100
- package/src/__tests__/packaged-assets-ship.test.ts +66 -0
- package/src/assets.ts +38 -2
- package/src/core/__tests__/catalog-revision.test.ts +40 -0
- package/src/core/__tests__/gated-boot.test.ts +1 -0
- package/src/core/__tests__/lifecycle.test.ts +14 -0
- package/src/core/catalog-revision.ts +15 -2
- package/src/core/core-ports.ts +11 -0
- package/src/core/create-core-server.ts +78 -3
- package/src/core/create-core-services.ts +168 -10
- package/src/core/lifecycle.ts +28 -2
- package/src/core-config.ts +24 -1
- package/src/index.ts +2 -2
- package/src/modules/access/__tests__/access-control.atref-batch.test.ts +58 -0
- package/src/modules/access/__tests__/access-control.platform-restore.test.ts +8 -7
- package/src/modules/access/__tests__/access-control.service.test.ts +19 -0
- package/src/modules/access/__tests__/access-personal-plugin.test.ts +1 -18
- package/src/modules/access/access-control.interface.ts +28 -0
- package/src/modules/access/access-control.service.ts +37 -0
- package/src/modules/access/directory-sync-bot.ts +1 -1
- package/src/modules/agent-guide/__tests__/agent-guide.test.ts +386 -0
- package/src/modules/agent-guide/__tests__/agent-guide.tools.test.ts +207 -0
- package/src/modules/agent-guide/agent-guide.tools.ts +122 -0
- package/src/modules/agent-guide/agent-guide.ts +300 -0
- package/src/modules/agent-guide/index.ts +22 -0
- package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +39 -118
- package/src/modules/agent-instructions/agent-instructions.routes.ts +3 -2
- package/src/modules/agent-instructions/compose.ts +26 -8
- package/src/modules/agent-instructions/index.ts +0 -3
- package/src/modules/agent-instructions/shared-file-rules.ts +50 -112
- package/src/modules/audit/__tests__/agent-audit.service.test.ts +64 -4
- package/src/modules/audit/__tests__/agent-connection.routes.test.ts +102 -0
- package/src/modules/audit/agent-audit.service.ts +58 -3
- package/src/modules/audit/agent-connection.routes.ts +56 -0
- package/src/modules/audit/audit.contract.ts +26 -0
- package/src/modules/audit/index.ts +1 -0
- package/src/modules/auth/__tests__/account.routes.test.ts +5 -3
- package/src/modules/auth/account.routes.ts +10 -3
- package/src/modules/auth/auth.middleware.ts +1 -1
- package/src/modules/code-mode/__tests__/code-mode.tool.test.ts +18 -2
- package/src/modules/code-mode/code-mode.tool.ts +13 -2
- package/src/modules/database/core-schema.ts +33 -3
- package/src/modules/embed/__tests__/account-links.migration.test.ts +98 -0
- package/src/modules/embed/__tests__/embed-link.test.ts +122 -0
- package/src/modules/embed/__tests__/embed.routes.test.ts +362 -0
- package/src/modules/embed/__tests__/embed.service.lock.test.ts +193 -0
- package/src/modules/embed/__tests__/embed.service.test.ts +805 -0
- package/src/modules/embed/__tests__/embed.tools.test.ts +304 -0
- package/src/modules/embed/__tests__/mcp-app.test.ts +207 -0
- package/src/modules/embed/account-link.service.ts +76 -0
- package/src/modules/embed/embed-link.ts +180 -0
- package/src/modules/embed/embed.errors.ts +43 -0
- package/src/modules/embed/embed.interface.ts +203 -0
- package/src/modules/embed/embed.routes.ts +363 -0
- package/src/modules/embed/embed.service.ts +705 -0
- package/src/modules/embed/embed.tools.ts +206 -0
- package/src/modules/embed/mcp-app.routes.ts +41 -0
- package/src/modules/embed/mcp-app.ts +173 -0
- package/src/modules/github-app/__tests__/github-app.test.ts +76 -0
- package/src/modules/github-app/github-app.connection.ts +38 -4
- package/src/modules/kb-fs/__tests__/move-with-edits.test.ts +304 -0
- package/src/modules/kb-fs/locking-filesystem.ts +287 -0
- package/src/modules/kb-sync/__tests__/kb-sync.service.test.ts +35 -0
- package/src/modules/kb-sync/kb-sync.interface.ts +2 -0
- package/src/modules/kb-sync/kb-sync.service.ts +6 -0
- package/src/modules/mcp/__tests__/bevel-oauth-provider.test.ts +68 -11
- package/src/modules/mcp/__tests__/fake-downstream-mcp-server.ts +14 -3
- package/src/modules/mcp/__tests__/mcp-proxy-helpers.test.ts +37 -2
- package/src/modules/mcp/__tests__/mcp.app.e2e.test.ts +200 -0
- package/src/modules/mcp/__tests__/mcp.e2e.test.ts +252 -0
- package/src/modules/mcp/__tests__/mcp.service.test.ts +42 -24
- package/src/modules/mcp/__tests__/tool-call-interface.e2e.test.ts +499 -0
- package/src/modules/mcp/__tests__/tool-schema-guard.test.ts +266 -0
- package/src/modules/mcp/mcp-auth.middleware.ts +2 -1
- package/src/modules/mcp/mcp.service.ts +218 -31
- package/src/modules/mcp/oauth/bevel-oauth-provider.ts +42 -4
- package/src/modules/mcp/tool-schema-guard.ts +196 -0
- package/src/modules/onboarding/__tests__/onboarding.routes.test.ts +163 -0
- package/src/modules/onboarding/__tests__/starter-pack.service.test.ts +635 -0
- package/src/modules/onboarding/__tests__/starter-packs.test.ts +169 -0
- package/src/modules/onboarding/onboarding.contract.ts +85 -0
- package/src/modules/onboarding/onboarding.routes.ts +85 -0
- package/src/modules/onboarding/starter-pack.service.ts +580 -0
- package/src/modules/onboarding/starter-packs.ts +182 -0
- package/src/modules/plugins/__tests__/plugins.tools.test.ts +177 -4
- package/src/modules/plugins/index.ts +1 -0
- package/src/modules/plugins/plugin-provision.service.ts +22 -1
- package/src/modules/plugins/plugins.routes.ts +29 -0
- package/src/modules/plugins/plugins.tools.ts +75 -15
- package/src/modules/settings/__tests__/deployment-settings.service.test.ts +176 -56
- package/src/modules/settings/__tests__/repository-source.test.ts +9 -0
- package/src/modules/settings/deployment-settings.service.ts +144 -55
- package/src/modules/settings/repository-source.ts +4 -4
- package/src/modules/settings/setup.routes.ts +3 -6
- package/src/modules/skills/__tests__/skills.tools.description.test.ts +95 -0
- package/src/modules/skills/skills.tools.ts +112 -46
- package/src/modules/tool-auth/__tests__/connection-key-rejection.test.ts +32 -0
- package/src/modules/tool-auth/__tests__/external-api-key.service.test.ts +65 -0
- package/src/modules/tool-auth/connection-key-rejection.ts +13 -3
- package/src/modules/tool-auth/external-api-key.interface.ts +9 -0
- package/src/modules/tool-auth/external-api-key.service.ts +61 -4
- package/src/modules/tool-auth/tool-auth.middleware.ts +13 -4
- package/src/modules/tool-helpers/__tests__/branch-declaration.test.ts +502 -0
- package/src/modules/tool-helpers/__tests__/route-argument-check.test.ts +337 -0
- package/src/modules/tool-helpers/index.ts +34 -1
- package/src/modules/tool-helpers/route-argument-check.ts +149 -0
- package/src/modules/tool-helpers/route-tool-schemas.ts +171 -0
- package/src/modules/tool-helpers/tool-def.ts +132 -7
- package/src/modules/tool-helpers/tool-handler.ts +196 -8
- package/src/modules/tool-helpers/tool.contract.ts +9 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +57 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +73 -4
- package/src/modules/tool-manuals/tool-manuals.contract.ts +24 -4
- package/src/modules/tool-manuals/tool-manuals.service.ts +17 -0
- package/src/modules/tool-manuals/tool-manuals.tools.ts +86 -38
- package/src/modules/tool-registry/__tests__/own-tool-schemas.test.ts +173 -0
- package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +81 -66
- package/src/modules/tool-registry/description-length.ts +57 -32
- package/src/modules/tool-registry/guide-first.ts +41 -0
- package/src/modules/tool-registry/tool-registry.ts +9 -2
- package/src/modules/workflow/__tests__/apply-failure.test.ts +6 -1
- package/src/modules/workflow/__tests__/file-lock.service.deletion-gate.test.ts +104 -0
- package/src/modules/workflow/__tests__/pending-commits.repository-replaced.test.ts +66 -0
- package/src/modules/workflow/__tests__/pending-commits.worker.test.ts +31 -2
- package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +110 -6
- package/src/modules/workflow/__tests__/sanitize-error.test.ts +89 -1
- package/src/modules/workflow/__tests__/workflow.routes.push-refused.test.ts +202 -0
- package/src/modules/workflow/__tests__/workflow.service.branch-in-use.test.ts +6 -6
- package/src/modules/workflow/__tests__/workflow.service.delete-branch.test.ts +1026 -0
- package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +468 -10
- package/src/modules/workflow/__tests__/workflow.service.folder-proposals.test.ts +4 -0
- package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +5 -4
- package/src/modules/workflow/__tests__/workflow.service.update-from-target.test.ts +54 -2
- package/src/modules/workflow/agent-tools/__tests__/change-request-read-shape.test.ts +705 -0
- package/src/modules/workflow/agent-tools/__tests__/change-request-read.tools.test.ts +1554 -0
- package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +150 -4
- package/src/modules/workflow/agent-tools/change-request-read-shape.ts +712 -0
- package/src/modules/workflow/agent-tools/change-request-read.tools.ts +759 -0
- package/src/modules/workflow/agent-tools/change-request-summary.ts +5 -1
- package/src/modules/workflow/agent-tools/workflow.tools.ts +137 -35
- package/src/modules/workflow/file-lock.service.ts +67 -5
- package/src/modules/workflow/git/__tests__/git.service.appliedChange.test.ts +285 -0
- package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +124 -0
- package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +164 -0
- package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +334 -0
- package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +48 -1
- package/src/modules/workflow/git/__tests__/node-git-runner.test.ts +231 -2
- package/src/modules/workflow/git/__tests__/pull-request.service.list-fetch.test.ts +72 -2
- package/src/modules/workflow/git/__tests__/pull-request.service.placeholder.test.ts +24 -2
- package/src/modules/workflow/git/__tests__/pull-request.service.test.ts +620 -1
- package/src/modules/workflow/git/git.service.ts +714 -133
- package/src/modules/workflow/git/merge-commit.ts +88 -0
- package/src/modules/workflow/git/node-git-runner.ts +82 -7
- package/src/modules/workflow/git/pull-request.service.ts +380 -54
- package/src/modules/workflow/pending-commits.service.ts +29 -1
- package/src/modules/workflow/pending-commits.worker.ts +24 -6
- package/src/modules/workflow/recovery-bot.ts +1 -1
- package/src/modules/workflow/review-workflow/__tests__/approval-states.test.ts +7 -1
- package/src/modules/workflow/review-workflow/__tests__/merge-records-own-commit.test.ts +407 -0
- package/src/modules/workflow/review-workflow/review-workflow.service.ts +191 -12
- package/src/modules/workflow/sanitize-error.ts +50 -0
- package/src/modules/workflow/workflow.routes.ts +7 -2
- package/src/modules/workflow/workflow.service.ts +886 -112
- package/src/modules/workspace/__tests__/agent-downloads.test.ts +823 -0
- package/src/modules/workspace/__tests__/escape-sequences.routes.test.ts +4 -3
- package/src/modules/workspace/__tests__/first-run.test.ts +234 -0
- package/src/modules/workspace/__tests__/git-internals.security.test.ts +5 -2
- package/src/modules/workspace/__tests__/md-links.test.ts +353 -0
- package/src/modules/workspace/__tests__/move-links.test.ts +261 -0
- package/src/modules/workspace/__tests__/rest-tool-arguments.test.ts +219 -0
- package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +3 -0
- package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +102 -0
- package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +52 -5
- package/src/modules/workspace/__tests__/workspace.routes.folder-zip-access.test.ts +190 -0
- package/src/modules/workspace/__tests__/workspace.routes.move-platform-files.test.ts +21 -10
- package/src/modules/workspace/__tests__/workspace.service.forget-clone-races.test.ts +8 -4
- package/src/modules/workspace/__tests__/workspace.service.test.ts +50 -8
- package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +33 -55
- package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +44 -1
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +664 -34
- package/src/modules/workspace/agent-download.builder.ts +308 -0
- package/src/modules/workspace/agent-download.routes.ts +183 -0
- package/src/modules/workspace/agent-download.store.ts +533 -0
- package/src/modules/workspace/agent-upload.store.ts +23 -7
- package/src/modules/workspace/file-readers/raw-mime.ts +40 -0
- package/src/modules/workspace/file-readers/text-reader.ts +5 -8
- package/src/modules/workspace/first-run.ts +222 -0
- package/src/modules/workspace/move-links.ts +237 -0
- package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +191 -489
- package/src/modules/workspace/startup/steps/seed-tree.ts +23 -38
- package/src/modules/workspace/startup/steps/template-files.step.ts +217 -249
- package/src/modules/workspace/startup/steps/template-source.ts +5 -3
- package/src/modules/workspace/workspace.routes.ts +64 -22
- package/src/modules/workspace/workspace.service.ts +202 -25
- package/src/modules/workspace/workspace.tools.ts +707 -68
- package/src/modules/write-access/__tests__/write-access.test.ts +13 -0
- package/src/modules/write-access/write-access.ts +9 -0
- package/src/shared/domain-errors.ts +123 -11
- package/src/shared/git.contract.ts +8 -1
- package/src/shared/hidden-tools.ts +45 -0
- package/src/shared/utf8-text.ts +21 -0
- package/src/tenancy/__tests__/static-tenant-source.test.ts +1 -0
- package/src/tenancy/static-tenant-source.ts +10 -2
- package/starter-packs/README.md +103 -0
- package/starter-packs/engineering/KnowledgeBase/About us.md +9 -0
- package/starter-packs/engineering/KnowledgeBase/Architecture.md +9 -0
- package/starter-packs/engineering/KnowledgeBase/Glossary.md +9 -0
- package/starter-packs/engineering/KnowledgeBase/How we ship.md +9 -0
- package/starter-packs/engineering/Plugins/engineering-starter/LICENSE +21 -0
- package/starter-packs/engineering/Plugins/engineering-starter/SOURCE.md +20 -0
- package/starter-packs/engineering/Plugins/engineering-starter/access.md +19 -0
- package/starter-packs/engineering/Plugins/engineering-starter/plugin.json +10 -0
- package/starter-packs/engineering/Plugins/engineering-starter/skills/office-hours/SKILL.md +171 -0
- package/starter-packs/engineering/Plugins/engineering-starter/skills/office-hours/sections/phase-2a-startup-diagnostic.md +157 -0
- package/starter-packs/engineering/Plugins/engineering-starter/skills/office-hours/sections/phase-2b-builder-brainstorm.md +39 -0
- package/starter-packs/engineering/Plugins/engineering-starter/skills/plan-ceo-review/SKILL.md +144 -0
- package/starter-packs/engineering/Plugins/engineering-starter/skills/plan-eng-review/SKILL.md +144 -0
- package/starter-packs/engineering/Plugins/engineering-starter/skills/review/SKILL.md +80 -0
- package/starter-packs/engineering/Plugins/engineering-starter/skills/review/checklist.md +184 -0
- package/starter-packs/engineering/pack.yaml +11 -0
- package/starter-packs/general/KnowledgeBase/About us.md +9 -0
- package/starter-packs/general/KnowledgeBase/Glossary.md +9 -0
- package/starter-packs/general/KnowledgeBase/How we work.md +9 -0
- package/starter-packs/general/Plugins/general-starter/LICENSE +202 -0
- package/starter-packs/general/Plugins/general-starter/SOURCE.md +10 -0
- package/starter-packs/general/Plugins/general-starter/access.md +19 -0
- package/starter-packs/general/Plugins/general-starter/plugin.json +10 -0
- package/starter-packs/general/Plugins/general-starter/skills/memory-management/SKILL.md +332 -0
- package/starter-packs/general/Plugins/general-starter/skills/productivity-start/SKILL.md +163 -0
- package/starter-packs/general/Plugins/general-starter/skills/productivity-update/SKILL.md +167 -0
- package/starter-packs/general/Plugins/general-starter/skills/task-management/SKILL.md +83 -0
- package/starter-packs/general/pack.yaml +10 -0
- package/starter-packs/operations/KnowledgeBase/Glossary.md +9 -0
- package/starter-packs/operations/KnowledgeBase/How we work.md +9 -0
- package/starter-packs/operations/KnowledgeBase/Processes.md +9 -0
- package/starter-packs/operations/KnowledgeBase/Tools we use.md +9 -0
- package/starter-packs/operations/KnowledgeBase/Vendors.md +9 -0
- package/starter-packs/operations/Plugins/operations-starter/LICENSE +202 -0
- package/starter-packs/operations/Plugins/operations-starter/SOURCE.md +10 -0
- package/starter-packs/operations/Plugins/operations-starter/access.md +19 -0
- package/starter-packs/operations/Plugins/operations-starter/plugin.json +10 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/capacity-plan/SKILL.md +111 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/change-request/SKILL.md +119 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/compliance-tracking/SKILL.md +44 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/process-doc/SKILL.md +80 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/process-optimization/SKILL.md +39 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/risk-assessment/SKILL.md +40 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/runbook/SKILL.md +85 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/status-report/SKILL.md +75 -0
- package/starter-packs/operations/Plugins/operations-starter/skills/vendor-review/SKILL.md +102 -0
- package/starter-packs/operations/pack.yaml +12 -0
- package/starter-packs/sales/KnowledgeBase/About us.md +9 -0
- package/starter-packs/sales/KnowledgeBase/Customers.md +9 -0
- package/starter-packs/sales/KnowledgeBase/Glossary.md +9 -0
- package/starter-packs/sales/KnowledgeBase/How we sell.md +9 -0
- package/starter-packs/sales/KnowledgeBase/Objections.md +9 -0
- package/starter-packs/sales/KnowledgeBase/Pricing.md +9 -0
- package/starter-packs/sales/Plugins/sales-starter/LICENSE +202 -0
- package/starter-packs/sales/Plugins/sales-starter/SOURCE.md +10 -0
- package/starter-packs/sales/Plugins/sales-starter/access.md +19 -0
- package/starter-packs/sales/Plugins/sales-starter/plugin.json +10 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/account-context/SKILL.md +94 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/account-plan/SKILL.md +95 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/account-research/SKILL.md +99 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/account-tiering/SKILL.md +101 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/call-prep/SKILL.md +111 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/call-summary/SKILL.md +111 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/close-plan/SKILL.md +106 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/competitive-intelligence/SKILL.md +102 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/create-an-asset/SKILL.md +105 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/crm-hygiene-check/SKILL.md +103 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/customer-health/SKILL.md +108 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/customer-voice/SKILL.md +94 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/daily-briefing/SKILL.md +61 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/deal-advance-gap/SKILL.md +102 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/deal-review/SKILL.md +105 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/deal-signals/SKILL.md +96 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/deal-slip-scenario/SKILL.md +104 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/draft-outreach/SKILL.md +116 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/end-of-day/SKILL.md +114 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/expansion-whitespace/SKILL.md +97 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/forecast/SKILL.md +100 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/handle-objection/SKILL.md +93 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/inbox-sweep/SKILL.md +114 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/lead-triage/SKILL.md +106 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/log-activity/SKILL.md +111 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/pipeline-review/SKILL.md +97 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/renewal-radar/SKILL.md +95 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/rep-context/SKILL.md +90 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/route-lead/SKILL.md +111 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/sales-setup/SKILL.md +200 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/schedule-meeting/SKILL.md +99 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/stakeholder-map/SKILL.md +107 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/team-pipeline/SKILL.md +105 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/update-opportunity/SKILL.md +112 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/weekly-wrap/SKILL.md +90 -0
- package/starter-packs/sales/Plugins/sales-starter/skills/win-loss-review/SKILL.md +88 -0
- package/starter-packs/sales/pack.yaml +13 -0
- package/starter-packs/support/KnowledgeBase/Escalations.md +9 -0
- package/starter-packs/support/KnowledgeBase/Glossary.md +9 -0
- package/starter-packs/support/KnowledgeBase/Known issues.md +9 -0
- package/starter-packs/support/KnowledgeBase/Products.md +9 -0
- package/starter-packs/support/KnowledgeBase/Tone of voice.md +9 -0
- package/starter-packs/support/Plugins/support-starter/LICENSE +202 -0
- package/starter-packs/support/Plugins/support-starter/SOURCE.md +10 -0
- package/starter-packs/support/Plugins/support-starter/access.md +19 -0
- package/starter-packs/support/Plugins/support-starter/plugin.json +10 -0
- package/starter-packs/support/Plugins/support-starter/skills/customer-escalation/SKILL.md +246 -0
- package/starter-packs/support/Plugins/support-starter/skills/customer-research/SKILL.md +250 -0
- package/starter-packs/support/Plugins/support-starter/skills/draft-response/SKILL.md +416 -0
- package/starter-packs/support/Plugins/support-starter/skills/kb-article/SKILL.md +350 -0
- package/starter-packs/support/Plugins/support-starter/skills/ticket-triage/SKILL.md +273 -0
- package/starter-packs/support/pack.yaml +12 -0
- package/kb-template/AGENTS.md +0 -730
|
@@ -49,6 +49,8 @@ interface Harness {
|
|
|
49
49
|
server: Server;
|
|
50
50
|
baseUrl: string;
|
|
51
51
|
canDownload: ReturnType<typeof vi.fn>;
|
|
52
|
+
canReadBatch: ReturnType<typeof vi.fn>;
|
|
53
|
+
canDownloadBatch: ReturnType<typeof vi.fn>;
|
|
52
54
|
canWrite: ReturnType<typeof vi.fn>;
|
|
53
55
|
createFolderZip: ReturnType<typeof vi.fn>;
|
|
54
56
|
}
|
|
@@ -70,14 +72,21 @@ async function makeHarness(opts: {
|
|
|
70
72
|
return opts.canDownload;
|
|
71
73
|
});
|
|
72
74
|
const canWrite = vi.fn();
|
|
75
|
+
// The /file/raw route now read-gates before the download gate; these tests
|
|
76
|
+
// exercise the download verb, so reads pass.
|
|
77
|
+
const canReadBatch = vi.fn(async (_w: string, _e: string, paths: string[]) => new Map(paths.map((p) => [p, true])));
|
|
78
|
+
// Every entry of a folder is judged for download too; by default each gets
|
|
79
|
+
// the folder's own verdict.
|
|
80
|
+
const canDownloadBatch = vi.fn(async (_w: string, _e: string, paths: string[]) =>
|
|
81
|
+
new Map(paths.map((p) => [p, opts.canDownload])),
|
|
82
|
+
);
|
|
73
83
|
const accessControl: IAccessControl = {
|
|
74
84
|
canWrite,
|
|
75
85
|
canWriteBatch: vi.fn(),
|
|
76
|
-
// The /file/raw route now read-gates before the download gate; these tests
|
|
77
|
-
// exercise the download verb, so reads pass.
|
|
78
86
|
canRead: vi.fn(async () => true),
|
|
79
|
-
canReadBatch
|
|
87
|
+
canReadBatch,
|
|
80
88
|
canDownload,
|
|
89
|
+
canDownloadBatch,
|
|
81
90
|
eligibleWriters: vi.fn(),
|
|
82
91
|
eligibleWriterEmails: vi.fn(),
|
|
83
92
|
invalidate: vi.fn(),
|
|
@@ -152,7 +161,7 @@ async function makeHarness(opts: {
|
|
|
152
161
|
throw new Error(`Unexpected server.address() shape: ${JSON.stringify(addr)}`);
|
|
153
162
|
}
|
|
154
163
|
const port = (addr as AddressInfo).port;
|
|
155
|
-
return { server, baseUrl: `http://127.0.0.1:${port}`, canDownload, canWrite, createFolderZip };
|
|
164
|
+
return { server, baseUrl: `http://127.0.0.1:${port}`, canDownload, canReadBatch, canDownloadBatch, canWrite, createFolderZip };
|
|
156
165
|
}
|
|
157
166
|
|
|
158
167
|
async function closeServer(server: Server): Promise<void> {
|
|
@@ -338,6 +347,8 @@ describe('GET /workspace/:id/folder/zip — gated on Download role', () => {
|
|
|
338
347
|
expect(res.status).toBe(200);
|
|
339
348
|
expect(res.headers.get('content-type')).toBe('application/zip');
|
|
340
349
|
expect(res.headers.get('x-content-type-options')).toBe('nosniff');
|
|
350
|
+
// The archive holds one caller's verdicts, so a shared cache never keeps it.
|
|
351
|
+
expect(res.headers.get('cache-control')).toBe('private, no-store');
|
|
341
352
|
const dispo = res.headers.get('content-disposition');
|
|
342
353
|
expect(dispo).toBeTruthy();
|
|
343
354
|
expect(dispo).toContain('attachment');
|
|
@@ -349,7 +360,43 @@ describe('GET /workspace/:id/folder/zip — gated on Download role', () => {
|
|
|
349
360
|
// verb is resolved on its repo-relative form, and the service is handed the
|
|
350
361
|
// repository path it was judged as.
|
|
351
362
|
expect(h.canDownload).toHaveBeenCalledWith(WORKSPACE_ID, USER.email, 'Knowledge/Sales');
|
|
352
|
-
expect(h.createFolderZip).
|
|
363
|
+
expect(h.createFolderZip.mock.calls[0]!.slice(0, 2)).toEqual([WORKSPACE_ID, `${KB}/Knowledge/Sales`]);
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
it('judges every file the zip would pack: unreadable ones and undownloadable ones are left out', async () => {
|
|
367
|
+
h = await makeHarness({ canDownload: true });
|
|
368
|
+
// What the service finds under the folder; the route's filter decides.
|
|
369
|
+
const found = ['Knowledge/Sales/open.md', 'Knowledge/Sales/hidden.md', 'Knowledge/Sales/no-save.md'];
|
|
370
|
+
h.canReadBatch.mockImplementation(async (_w: string, _e: string, paths: string[]) =>
|
|
371
|
+
new Map(paths.map((p) => [p, p !== 'Knowledge/Sales/hidden.md'])),
|
|
372
|
+
);
|
|
373
|
+
h.canDownloadBatch.mockImplementation(async (_w: string, _e: string, paths: string[]) =>
|
|
374
|
+
new Map(paths.map((p) => [p, p !== 'Knowledge/Sales/no-save.md'])),
|
|
375
|
+
);
|
|
376
|
+
let packed: ReadonlySet<string> | null = null;
|
|
377
|
+
h.createFolderZip.mockImplementation(
|
|
378
|
+
async (_id: string, _p: string, include: (paths: string[]) => Promise<ReadonlySet<string>>) => {
|
|
379
|
+
packed = await include(found);
|
|
380
|
+
return ZIP_BYTES;
|
|
381
|
+
},
|
|
382
|
+
);
|
|
383
|
+
|
|
384
|
+
const res = await fetch(
|
|
385
|
+
`${h.baseUrl}/api/workspace/${WORKSPACE_ID}/folder/zip?path=${encodeURIComponent('Knowledge/Sales')}&download=1`,
|
|
386
|
+
);
|
|
387
|
+
|
|
388
|
+
expect(res.status).toBe(200);
|
|
389
|
+
expect([...packed!]).toEqual(['Knowledge/Sales/open.md']);
|
|
390
|
+
// Read first, then download on what is readable: a file the caller may
|
|
391
|
+
// not see is never asked about for download, so nothing about it is
|
|
392
|
+
// computed or counted.
|
|
393
|
+
expect(h.canReadBatch).toHaveBeenCalledWith(WORKSPACE_ID, USER.email, found);
|
|
394
|
+
expect(h.canDownloadBatch).toHaveBeenCalledWith(WORKSPACE_ID, USER.email, [
|
|
395
|
+
'Knowledge/Sales/open.md',
|
|
396
|
+
'Knowledge/Sales/no-save.md',
|
|
397
|
+
]);
|
|
398
|
+
// The count covers the readable file left out, not the hidden one.
|
|
399
|
+
expect(res.headers.get('x-withheld-files')).toBe('1');
|
|
353
400
|
});
|
|
354
401
|
|
|
355
402
|
it('user without Download role gets 403 and no zip is built', async () => {
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import type { Server } from 'node:http';
|
|
2
|
+
import type { AddressInfo } from 'node:net';
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import express from 'express';
|
|
7
|
+
import AdmZip from 'adm-zip';
|
|
8
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
9
|
+
import { testKbContext } from '../../../__tests__/kb-context.js';
|
|
10
|
+
import { NodeFs } from '../../kb-fs/node-fs.js';
|
|
11
|
+
import type { IWorkflowService } from '@bevel-software/platform-shared';
|
|
12
|
+
import type { ICreatorAccess } from '../../access-model/creator.js';
|
|
13
|
+
import type { IAdminAccessService } from '../../admin/admin.interface.js';
|
|
14
|
+
import type { WorkflowEventBus } from '../../workflow/event-bus.js';
|
|
15
|
+
import type { AuthService } from '../../auth/auth.service.js';
|
|
16
|
+
import { AccessControlService } from '../../access/access-control.service.js';
|
|
17
|
+
import { createWorkspaceRoutes } from '../workspace.routes.js';
|
|
18
|
+
import { WorkspaceService } from '../workspace.service.js';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The folder download over the REAL resolver and the REAL zip builder.
|
|
22
|
+
*
|
|
23
|
+
* `download` on a folder let the caller ask for its zip, and the zip then
|
|
24
|
+
* packed every file under the folder: no file was judged against its own
|
|
25
|
+
* rules, so a caller got files whose frontmatter denied them `download`, files
|
|
26
|
+
* whose frontmatter denied them `read`, and whole sub-folders a nested
|
|
27
|
+
* access.md closed to them — files the per-file route refused and the file
|
|
28
|
+
* tree never showed (found 2026-10-07). The four cases below are the ones
|
|
29
|
+
* that were verified leaking; each must now be absent from the archive, and
|
|
30
|
+
* the one the caller may download must still be in it.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
const KB = 'knowledge-base';
|
|
34
|
+
const WORKSPACE_ID = 'target-company-state';
|
|
35
|
+
|
|
36
|
+
const stubCreatorAccess: ICreatorAccess = {
|
|
37
|
+
planForCreate: async () => null,
|
|
38
|
+
grantInExtractedFile: async () => null,
|
|
39
|
+
noteAccessFileWritten: () => {},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
let caller = { id: 'user-1', email: 'ana@x.io', name: 'Ana' };
|
|
43
|
+
|
|
44
|
+
const ROLES_YAML = `roles:
|
|
45
|
+
Admin:
|
|
46
|
+
- admin@x.io
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
/** The folder Ana may download, with the files the rules below decide over. */
|
|
50
|
+
const FILES: Record<string, string> = {
|
|
51
|
+
'Shared/access.md': '---\n---\ndownload:\n - Ana <ana@x.io>\n',
|
|
52
|
+
'Shared/Open.md': '# open\n',
|
|
53
|
+
'Shared/Node-Deny-Download.md': '---\ndownload:\n - deny Ana <ana@x.io>\n---\n# no save\n',
|
|
54
|
+
'Shared/Node-Deny-Read.md': '---\nread:\n - deny Ana <ana@x.io>\n---\n# hidden\n',
|
|
55
|
+
'Shared/Inner/access.md': '---\n---\nread:\n - deny Ana <ana@x.io>\ndownload:\n - deny Ana <ana@x.io>\n',
|
|
56
|
+
'Shared/Inner/Plan.md': '# hidden plan\n',
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
interface Harness {
|
|
60
|
+
server: Server;
|
|
61
|
+
baseUrl: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
describe('GET /folder/zip judges every file it packs (real resolver, real zip)', () => {
|
|
65
|
+
let root: string;
|
|
66
|
+
let h: Harness | null = null;
|
|
67
|
+
|
|
68
|
+
beforeEach(async () => {
|
|
69
|
+
root = await fs.mkdtemp(path.join(os.tmpdir(), 'bevel-zip-access-'));
|
|
70
|
+
caller = { id: 'user-1', email: 'ana@x.io', name: 'Ana' };
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
afterEach(async () => {
|
|
74
|
+
if (h) {
|
|
75
|
+
await new Promise<void>((resolve, reject) => h!.server.close((e) => (e ? reject(e) : resolve())));
|
|
76
|
+
h = null;
|
|
77
|
+
}
|
|
78
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
async function makeHarness(files: Record<string, string>): Promise<Harness> {
|
|
82
|
+
const workspaceDir = path.join(root, WORKSPACE_ID);
|
|
83
|
+
const repo = path.join(workspaceDir, KB);
|
|
84
|
+
// A `.git` folder is what makes the service adopt the clone without cloning.
|
|
85
|
+
await fs.mkdir(path.join(repo, '.git'), { recursive: true });
|
|
86
|
+
for (const [rel, contents] of Object.entries({ 'roles.yaml': ROLES_YAML, ...files })) {
|
|
87
|
+
const abs = path.join(repo, rel);
|
|
88
|
+
await fs.mkdir(path.dirname(abs), { recursive: true });
|
|
89
|
+
await fs.writeFile(abs, contents);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const workspaceService = new WorkspaceService(
|
|
93
|
+
root,
|
|
94
|
+
'https://example.invalid/kb.git',
|
|
95
|
+
testKbContext({ kbDirName: KB }),
|
|
96
|
+
new NodeFs(),
|
|
97
|
+
);
|
|
98
|
+
const accessControl = new AccessControlService(workspaceService, KB, new NodeFs());
|
|
99
|
+
const authService = { getUserById: async () => caller } as unknown as AuthService;
|
|
100
|
+
|
|
101
|
+
const app = express();
|
|
102
|
+
app.use(express.json());
|
|
103
|
+
app.use('/api', (req, _res, next) => {
|
|
104
|
+
(req as unknown as { userId: string }).userId = caller.id;
|
|
105
|
+
next();
|
|
106
|
+
});
|
|
107
|
+
app.use(
|
|
108
|
+
'/api',
|
|
109
|
+
createWorkspaceRoutes(
|
|
110
|
+
workspaceService,
|
|
111
|
+
authService,
|
|
112
|
+
{} as unknown as IWorkflowService,
|
|
113
|
+
{} as unknown as WorkflowEventBus,
|
|
114
|
+
accessControl,
|
|
115
|
+
testKbContext({ kbDirName: KB }),
|
|
116
|
+
stubCreatorAccess,
|
|
117
|
+
{ isAdmin: async () => false } as unknown as IAdminAccessService,
|
|
118
|
+
new NodeFs(),
|
|
119
|
+
),
|
|
120
|
+
);
|
|
121
|
+
const server = await new Promise<Server>((resolve) => {
|
|
122
|
+
const s = app.listen(0, () => resolve(s));
|
|
123
|
+
});
|
|
124
|
+
const addr = server.address() as AddressInfo;
|
|
125
|
+
return { server, baseUrl: `http://127.0.0.1:${addr.port}` };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const zipOf = (base: string, folder: string) =>
|
|
129
|
+
fetch(`${base}/api/workspace/${WORKSPACE_ID}/folder/zip?path=${encodeURIComponent(folder)}&download=1`);
|
|
130
|
+
|
|
131
|
+
const entriesOf = async (res: Response) =>
|
|
132
|
+
new AdmZip(Buffer.from(await res.arrayBuffer()))
|
|
133
|
+
.getEntries()
|
|
134
|
+
.map((e) => e.entryName)
|
|
135
|
+
.sort();
|
|
136
|
+
|
|
137
|
+
it('packs the file the caller may download, and none of the ones their own rules withhold', async () => {
|
|
138
|
+
h = await makeHarness(FILES);
|
|
139
|
+
|
|
140
|
+
const res = await zipOf(h.baseUrl, `${KB}/Shared`);
|
|
141
|
+
|
|
142
|
+
expect(res.status).toBe(200);
|
|
143
|
+
expect(res.headers.get('content-type')).toBe('application/zip');
|
|
144
|
+
// Ana's archive, with Ana's verdicts: never served to anyone else from a cache.
|
|
145
|
+
expect(res.headers.get('cache-control')).toBe('private, no-store');
|
|
146
|
+
expect(await entriesOf(res)).toEqual(['Shared/Open.md', 'Shared/access.md']);
|
|
147
|
+
// One file Ana can see but not save is counted; the two she cannot see
|
|
148
|
+
// and the closed folder are not — the count says nothing the tree does not.
|
|
149
|
+
expect(res.headers.get('x-withheld-files')).toBe('1');
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('the per-file route agrees on every one of them', async () => {
|
|
153
|
+
h = await makeHarness(FILES);
|
|
154
|
+
const raw = (p: string) =>
|
|
155
|
+
fetch(`${h!.baseUrl}/api/workspace/${WORKSPACE_ID}/file/raw?path=${encodeURIComponent(`${KB}/${p}`)}&download=1`);
|
|
156
|
+
|
|
157
|
+
expect((await raw('Shared/Open.md')).status).toBe(200);
|
|
158
|
+
expect((await raw('Shared/Node-Deny-Download.md')).status).toBe(403);
|
|
159
|
+
expect((await raw('Shared/Node-Deny-Read.md')).status).toBe(403);
|
|
160
|
+
expect((await raw('Shared/Inner/Plan.md')).status).toBe(403);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('still refuses the folder itself to someone with no download grant', async () => {
|
|
164
|
+
h = await makeHarness(FILES);
|
|
165
|
+
caller = { id: 'user-2', email: 'mallory@x.io', name: 'Mallory' };
|
|
166
|
+
|
|
167
|
+
const res = await zipOf(h.baseUrl, `${KB}/Shared`);
|
|
168
|
+
|
|
169
|
+
expect(res.status).toBe(403);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// `access.md` itself stays in HERE: this fixture's declares nothing for
|
|
173
|
+
// itself (its frontmatter is empty), so the folder's rules — which admit
|
|
174
|
+
// the caller — admit the file too. That is not a guarantee: an `access.md`
|
|
175
|
+
// is judged like any file, by its own frontmatter and the folder chain, and
|
|
176
|
+
// one whose frontmatter denies the caller its read is left out of the
|
|
177
|
+
// archive exactly as the single-file route would refuse it.
|
|
178
|
+
it('answers an archive holding only the grant file, not an error, when every content file is withheld', async () => {
|
|
179
|
+
h = await makeHarness({
|
|
180
|
+
'Shared/access.md': '---\n---\ndownload:\n - Ana <ana@x.io>\n',
|
|
181
|
+
'Shared/Only.md': '---\ndownload:\n - deny Ana <ana@x.io>\n---\n# no save\n',
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const res = await zipOf(h.baseUrl, `${KB}/Shared`);
|
|
185
|
+
|
|
186
|
+
expect(res.status).toBe(200);
|
|
187
|
+
expect(await entriesOf(res)).toEqual(['Shared/access.md']);
|
|
188
|
+
expect(res.headers.get('x-withheld-files')).toBe('1');
|
|
189
|
+
});
|
|
190
|
+
});
|
|
@@ -136,14 +136,14 @@ describe('a platform file stays in its folder', () => {
|
|
|
136
136
|
await fs.rm(h.workspaceDir, { recursive: true, force: true });
|
|
137
137
|
});
|
|
138
138
|
|
|
139
|
-
// Each of the
|
|
140
|
-
// `.bevelignore` are read wherever they sit; `roles.yaml`
|
|
141
|
-
//
|
|
139
|
+
// Each of the three, at a place the platform reads it from. `access.md` and
|
|
140
|
+
// `.bevelignore` are read wherever they sit; `roles.yaml` is read from the
|
|
141
|
+
// repository root only. (`AGENTS.md` is not among them: the agent guide is
|
|
142
|
+
// served from code, so a root `AGENTS.md` is the organisation's own page.)
|
|
142
143
|
const PLATFORM_FILES = [
|
|
143
144
|
{ name: 'access.md', at: `${KB}/Sales/access.md` },
|
|
144
145
|
{ name: '.bevelignore', at: `${KB}/Sales/.bevelignore` },
|
|
145
146
|
{ name: 'roles.yaml', at: `${KB}/roles.yaml` },
|
|
146
|
-
{ name: 'AGENTS.md', at: `${KB}/AGENTS.md` },
|
|
147
147
|
];
|
|
148
148
|
|
|
149
149
|
it.each(PLATFORM_FILES)('refuses a rename of $name with the sentence', async ({ name, at }) => {
|
|
@@ -188,13 +188,12 @@ describe('a platform file stays in its folder', () => {
|
|
|
188
188
|
},
|
|
189
189
|
);
|
|
190
190
|
|
|
191
|
-
// The recovery move, for each of the
|
|
191
|
+
// The recovery move, for each of the three, from the place a misplaced copy
|
|
192
192
|
// is actually found to the place the platform reads it.
|
|
193
193
|
const RESTORES = [
|
|
194
194
|
{ name: 'access.md', from: `${KB}/Misplaced/access.md`, to: `${KB}/access.md`, dest: 'access.md' },
|
|
195
195
|
{ name: '.bevelignore', from: `${KB}/Misplaced/.bevelignore`, to: `${KB}/.bevelignore`, dest: '.bevelignore' },
|
|
196
196
|
{ name: 'roles.yaml', from: `${KB}/Misplaced/roles.yaml`, to: `${KB}/roles.yaml`, dest: 'roles.yaml' },
|
|
197
|
-
{ name: 'AGENTS.md', from: `${KB}/Misplaced/AGENTS.md`, to: `${KB}/AGENTS.md`, dest: 'AGENTS.md' },
|
|
198
197
|
];
|
|
199
198
|
|
|
200
199
|
it.each(RESTORES)(
|
|
@@ -265,6 +264,14 @@ describe('a platform file stays in its folder', () => {
|
|
|
265
264
|
|
|
266
265
|
expect(h.moveEntry).not.toHaveBeenCalled();
|
|
267
266
|
expect(h.acquireLock).not.toHaveBeenCalled();
|
|
267
|
+
|
|
268
|
+
// A root `AGENTS.md` is NOT a platform file any more — the guide is served
|
|
269
|
+
// from code — so a note renamed to it is an ordinary move that lands.
|
|
270
|
+
const guide = await move(h, `${KB}/Sales/deal.md`, `${KB}/AGENTS.md`);
|
|
271
|
+
expect(guide.status).toBe(200);
|
|
272
|
+
expect(guide.body).toEqual({ status: 'moved' });
|
|
273
|
+
expect(h.moveEntry).toHaveBeenCalledTimes(1);
|
|
274
|
+
expect(h.moveEntry).toHaveBeenCalledWith(WORKSPACE_ID, `${KB}/Sales/deal.md`, `${KB}/AGENTS.md`);
|
|
268
275
|
});
|
|
269
276
|
|
|
270
277
|
it('a destination that fills up after the access check is caught under the lock', async () => {
|
|
@@ -318,11 +325,15 @@ describe('a platform file stays in its folder', () => {
|
|
|
318
325
|
}
|
|
319
326
|
});
|
|
320
327
|
|
|
321
|
-
it('a nested roles.yaml
|
|
322
|
-
//
|
|
323
|
-
//
|
|
328
|
+
it('a nested roles.yaml, and an AGENTS.md anywhere, are ordinary content and move freely', async () => {
|
|
329
|
+
// `roles.yaml` is read from the root and nowhere else, so a nested file
|
|
330
|
+
// of that name carries no platform meaning to protect. An `AGENTS.md` is
|
|
331
|
+
// never read as configuration: the platform's guide is served from code,
|
|
332
|
+
// so the organisation's own file moves and renames like any page, at the
|
|
333
|
+
// root included.
|
|
324
334
|
expect((await move(h, `${KB}/Sales/roles.yaml`, `${KB}/Sales/old-roles.yaml`)).status).toBe(200);
|
|
325
335
|
expect((await move(h, `${KB}/Sales/AGENTS.md`, `${KB}/Legal/AGENTS.md`)).status).toBe(200);
|
|
326
|
-
expect(h.
|
|
336
|
+
expect((await move(h, `${KB}/AGENTS.md`, `${KB}/Handbook/AGENTS.md`)).status).toBe(200);
|
|
337
|
+
expect(h.moveEntry).toHaveBeenCalledTimes(3);
|
|
327
338
|
});
|
|
328
339
|
});
|
|
@@ -127,6 +127,13 @@ describe('a bootstrap in flight when the working copy is taken away', () => {
|
|
|
127
127
|
const svc = service(runner);
|
|
128
128
|
// Nothing on disk: this is a first clone, which is what takes seconds.
|
|
129
129
|
const opening = svc.getOrCreateForBranch(BRANCH);
|
|
130
|
+
// Told, rather than handed a cached path to a working copy of the
|
|
131
|
+
// repository that was replaced — which every later read would ENOENT on,
|
|
132
|
+
// with nothing left to re-clone it. The expectation is attached NOW: the
|
|
133
|
+
// refusal lands somewhere inside the timer turns below, and a rejection
|
|
134
|
+
// with no handler on it across a turn is what Vitest reports as unhandled
|
|
135
|
+
// — a flake that failed the suite on CI with every test green.
|
|
136
|
+
const refused = expect(opening).rejects.toThrow(/replaced while the "main" working copy was being created/);
|
|
130
137
|
await vi.waitFor(() => expect(calls.length).toBeGreaterThan(0));
|
|
131
138
|
|
|
132
139
|
// The replacement lands while the clone runs.
|
|
@@ -139,9 +146,6 @@ describe('a bootstrap in flight when the working copy is taken away', () => {
|
|
|
139
146
|
await new Promise((r) => setTimeout(r, 0));
|
|
140
147
|
}
|
|
141
148
|
|
|
142
|
-
|
|
143
|
-
// repository that was replaced — which every later read would ENOENT on,
|
|
144
|
-
// with nothing left to re-clone it.
|
|
145
|
-
await expect(opening).rejects.toThrow(/replaced while the "main" working copy was being created/);
|
|
149
|
+
await refused;
|
|
146
150
|
});
|
|
147
151
|
});
|
|
@@ -698,13 +698,55 @@ describe('WorkspaceService.createFolderZip', () => {
|
|
|
698
698
|
}));
|
|
699
699
|
}
|
|
700
700
|
|
|
701
|
+
/** The filter a caller with every permission passes: pack everything found. */
|
|
702
|
+
const ALL = async (paths: string[]) => new Set(paths);
|
|
703
|
+
|
|
704
|
+
it('packs only what the filter allows, and asks it once with every file as a repository path', async () => {
|
|
705
|
+
const dir = path.join(repoDir, 'judged');
|
|
706
|
+
await fs.mkdir(path.join(dir, 'inner'), { recursive: true });
|
|
707
|
+
await fs.writeFile(path.join(dir, 'open.md'), 'open');
|
|
708
|
+
await fs.writeFile(path.join(dir, 'withheld.md'), 'withheld');
|
|
709
|
+
await fs.writeFile(path.join(dir, 'inner', 'deep.md'), 'deep');
|
|
710
|
+
const asked: string[][] = [];
|
|
711
|
+
const include = async (paths: string[]) => {
|
|
712
|
+
asked.push([...paths].sort());
|
|
713
|
+
return new Set(paths.filter((p) => p !== 'judged/withheld.md'));
|
|
714
|
+
};
|
|
715
|
+
|
|
716
|
+
const buf = await svc.createFolderZip(workspaceId, 'judged', include);
|
|
717
|
+
|
|
718
|
+
// Asked once, with every file the walk found, keyed the way the access
|
|
719
|
+
// rules are: relative to the repository, not to the folder or the workspace.
|
|
720
|
+
expect(asked).toEqual([['judged/inner/deep.md', 'judged/open.md', 'judged/withheld.md']]);
|
|
721
|
+
const names = (await unzipEntries(buf)).map((e) => e.name).sort();
|
|
722
|
+
expect(names).toEqual(['judged/inner/deep.md', 'judged/open.md']);
|
|
723
|
+
});
|
|
724
|
+
|
|
725
|
+
it('keys the files the same way whether the folder is written with a trailing slash or not', async () => {
|
|
726
|
+
const dir = path.join(repoDir, 'slashed');
|
|
727
|
+
await fs.mkdir(dir, { recursive: true });
|
|
728
|
+
await fs.writeFile(path.join(dir, 'a.md'), 'a');
|
|
729
|
+
const asked: string[][] = [];
|
|
730
|
+
const include = async (paths: string[]) => {
|
|
731
|
+
asked.push(paths);
|
|
732
|
+
return new Set(paths);
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
await svc.createFolderZip(workspaceId, 'slashed/', include);
|
|
736
|
+
await svc.createFolderZip(workspaceId, `${'knowledge-base'}/slashed//`, include);
|
|
737
|
+
|
|
738
|
+
// A `slashed//a.md` key would match no verdict, and the filter would
|
|
739
|
+
// withhold the whole folder without a word.
|
|
740
|
+
expect(asked).toEqual([['slashed/a.md'], ['slashed/a.md']]);
|
|
741
|
+
});
|
|
742
|
+
|
|
701
743
|
it('zips a folder prefixing entries with the folder name', async () => {
|
|
702
744
|
const dir = path.join(repoDir, 'docs');
|
|
703
745
|
await fs.mkdir(dir, { recursive: true });
|
|
704
746
|
await fs.writeFile(path.join(dir, 'a.md'), 'alpha');
|
|
705
747
|
await fs.writeFile(path.join(dir, 'b.md'), 'beta');
|
|
706
748
|
|
|
707
|
-
const buf = await svc.createFolderZip(workspaceId, 'docs');
|
|
749
|
+
const buf = await svc.createFolderZip(workspaceId, 'docs', ALL);
|
|
708
750
|
const entries = await unzipEntries(buf);
|
|
709
751
|
const names = entries.map((e) => e.name).sort();
|
|
710
752
|
expect(names).toEqual(['docs/a.md', 'docs/b.md']);
|
|
@@ -719,7 +761,7 @@ describe('WorkspaceService.createFolderZip', () => {
|
|
|
719
761
|
await fs.writeFile(path.join(dir, 'nested', 'mid.md'), 'mid');
|
|
720
762
|
await fs.writeFile(path.join(dir, 'nested', 'deep', 'leaf.md'), 'leaf');
|
|
721
763
|
|
|
722
|
-
const buf = await svc.createFolderZip(workspaceId, 'tree');
|
|
764
|
+
const buf = await svc.createFolderZip(workspaceId, 'tree', ALL);
|
|
723
765
|
const names = (await unzipEntries(buf)).map((e) => e.name).sort();
|
|
724
766
|
expect(names).toEqual([
|
|
725
767
|
'tree/nested/deep/leaf.md',
|
|
@@ -736,7 +778,7 @@ describe('WorkspaceService.createFolderZip', () => {
|
|
|
736
778
|
await fs.writeFile(path.join(dir, '.gitkeep'), '');
|
|
737
779
|
await fs.writeFile(path.join(dir, 'real.md'), 'real');
|
|
738
780
|
|
|
739
|
-
const buf = await svc.createFolderZip(workspaceId, 'mixed');
|
|
781
|
+
const buf = await svc.createFolderZip(workspaceId, 'mixed', ALL);
|
|
740
782
|
const names = (await unzipEntries(buf)).map((e) => e.name).sort();
|
|
741
783
|
expect(names).toEqual(['mixed/real.md']);
|
|
742
784
|
});
|
|
@@ -748,7 +790,7 @@ describe('WorkspaceService.createFolderZip', () => {
|
|
|
748
790
|
await fs.writeFile(path.join(dir, 'public.md'), 'pub');
|
|
749
791
|
await fs.writeFile(path.join(dir, 'secret.md'), 'shh');
|
|
750
792
|
|
|
751
|
-
const buf = await svc.createFolderZip(workspaceId, 'with-ignore');
|
|
793
|
+
const buf = await svc.createFolderZip(workspaceId, 'with-ignore', ALL);
|
|
752
794
|
const names = (await unzipEntries(buf)).map((e) => e.name).sort();
|
|
753
795
|
expect(names).toContain('with-ignore/public.md');
|
|
754
796
|
expect(names).not.toContain('with-ignore/secret.md');
|
|
@@ -756,17 +798,17 @@ describe('WorkspaceService.createFolderZip', () => {
|
|
|
756
798
|
|
|
757
799
|
it('refuses to zip a file (not a directory)', async () => {
|
|
758
800
|
await fs.writeFile(path.join(repoDir, 'lone.md'), 'one');
|
|
759
|
-
await expect(svc.createFolderZip(workspaceId, 'lone.md')).rejects.toThrow('Not a directory');
|
|
801
|
+
await expect(svc.createFolderZip(workspaceId, 'lone.md', ALL)).rejects.toThrow('Not a directory');
|
|
760
802
|
});
|
|
761
803
|
|
|
762
804
|
it('refuses a traversing path, and reads an unprefixed one as the repository folder', async () => {
|
|
763
|
-
await expect(svc.createFolderZip(workspaceId, '../escape')).rejects.toThrow(
|
|
805
|
+
await expect(svc.createFolderZip(workspaceId, '../escape', ALL)).rejects.toThrow(
|
|
764
806
|
'is outside the knowledge base repository',
|
|
765
807
|
);
|
|
766
808
|
// The unprefixed spelling is the repository's own folder, so it zips.
|
|
767
809
|
await fs.mkdir(path.join(repoDir, 'unprefixed'), { recursive: true });
|
|
768
810
|
await fs.writeFile(path.join(repoDir, 'unprefixed', 'a.md'), 'a');
|
|
769
|
-
const buf = await svc.createFolderZip(workspaceId, 'unprefixed');
|
|
811
|
+
const buf = await svc.createFolderZip(workspaceId, 'unprefixed', ALL);
|
|
770
812
|
expect((await unzipEntries(buf)).map((e) => e.name)).toEqual(['unprefixed/a.md']);
|
|
771
813
|
});
|
|
772
814
|
|
|
@@ -796,7 +838,7 @@ describe('WorkspaceService.createFolderZip', () => {
|
|
|
796
838
|
return result;
|
|
797
839
|
});
|
|
798
840
|
try {
|
|
799
|
-
await expect(svc.createFolderZip(workspaceId, 'too-big'))
|
|
841
|
+
await expect(svc.createFolderZip(workspaceId, 'too-big', ALL))
|
|
800
842
|
.rejects.toBeInstanceOf(FolderTooLargeError);
|
|
801
843
|
} finally {
|
|
802
844
|
statSpy.mockRestore();
|
|
@@ -5,6 +5,7 @@ import { tmpdir } from 'node:os';
|
|
|
5
5
|
import { DEFAULT_KB_LAYOUT } from '@bevel-software/platform-shared';
|
|
6
6
|
import { testKbContext } from '../../../__tests__/kb-context.js';
|
|
7
7
|
import { ToolRegistry } from '../../tool-registry/tool-registry.js';
|
|
8
|
+
import { GUIDE_FIRST_SENTENCE } from '../../tool-registry/guide-first.js';
|
|
8
9
|
import { createToolHandlerFactory } from '../../tool-helpers/tool-handler.js';
|
|
9
10
|
import type { ToolAuth } from '../../tool-auth/tool-auth.middleware.js';
|
|
10
11
|
import type { IAccessControl } from '../../access/access-control.interface.js';
|
|
@@ -14,19 +15,18 @@ import { SpillStore } from '../spill-store.js';
|
|
|
14
15
|
import { WorkflowHooks } from '../../workflow/workflow-hooks.js';
|
|
15
16
|
import { ToolDescriptionNotes } from '../../workspace/agent-access.gate.js';
|
|
16
17
|
import { registerWorkspaceTools } from '../workspace.tools.js';
|
|
17
|
-
import { sharedFileRulesSection
|
|
18
|
+
import { sharedFileRulesSection } from '../../agent-instructions/shared-file-rules.js';
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
|
-
* What the platform TELLS AN AGENT about the
|
|
21
|
-
* default name and under a deployment's own.
|
|
21
|
+
* What the platform TELLS AN AGENT about the guide.
|
|
22
22
|
*
|
|
23
|
-
* The conventions reminder and the platform-file list are SHARED RULES
|
|
24
|
-
* stated in the handshake instructions and in the
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
23
|
+
* The conventions reminder and the platform-file list are SHARED RULES —
|
|
24
|
+
* stated in the handshake instructions and in the guide, once each — so their
|
|
25
|
+
* wording is asserted against that one text. What each tool description has
|
|
26
|
+
* to get right is its OPENING: the one sentence saying to call
|
|
27
|
+
* `get_agent_guide` first, which the catalog puts at the front of every tool
|
|
28
|
+
* (see tool-registry/guide-first.ts); a remote agent has no checkout, so that
|
|
29
|
+
* sentence and the rule are the only places it learns what to read first.
|
|
30
30
|
*/
|
|
31
31
|
const KB_DIR = 'knowledge-base';
|
|
32
32
|
/** The context the tools read; a case applies a deployment's own names to it. */
|
|
@@ -64,70 +64,48 @@ async function listed(registry: ToolRegistry): Promise<Map<string, string>> {
|
|
|
64
64
|
|
|
65
65
|
afterEach(() => kb.applyLayout({ ...DEFAULT_KB_LAYOUT }));
|
|
66
66
|
|
|
67
|
-
describe(
|
|
68
|
-
it('
|
|
67
|
+
describe('what tells an agent to read the guide first', () => {
|
|
68
|
+
it('tells an agent to call get_agent_guide first, and that AGENTS.md answers with the same guide after the organisation\'s own', () => {
|
|
69
69
|
const rules = sharedFileRulesSection(kb.layout);
|
|
70
|
-
expect(rules).toContain(
|
|
71
|
-
|
|
72
|
-
);
|
|
70
|
+
expect(rules).toContain("call `get_agent_guide` and read the platform's guide");
|
|
71
|
+
expect(rules).toContain('read_file on `AGENTS.md` at the KB root answers with the same guide');
|
|
72
|
+
expect(rules).toContain("after the organisation's own conventions file of that name");
|
|
73
|
+
expect(rules).toContain('`CLAUDE.md`');
|
|
74
|
+
// One name on every deployment: the rule names no other.
|
|
75
|
+
expect(rules).not.toContain('HEXIS.md');
|
|
73
76
|
});
|
|
74
77
|
|
|
75
|
-
it(
|
|
78
|
+
it('opens every entrypoint with the guide-first sentence, reads included', async () => {
|
|
76
79
|
const byName = await descriptions();
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
for (const name of ['grep', 'list_files', 'file_stat', 'read_file', 'write_file', 'move_file', 'start_session']) {
|
|
81
|
+
expect(byName.get(name)!.startsWith(`${GUIDE_FIRST_SENTENCE} `), name).toBe(true);
|
|
82
|
+
// Once, at the front — never again further down.
|
|
83
|
+
expect(byName.get(name)!.split(GUIDE_FIRST_SENTENCE), name).toHaveLength(2);
|
|
80
84
|
}
|
|
81
85
|
});
|
|
82
86
|
|
|
83
|
-
it(
|
|
84
|
-
kb.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: 'HEXIS.md' });
|
|
85
|
-
const note = sharedFileRulesSection(kb.layout);
|
|
86
|
-
expect(note).toContain('read `HEXIS.md` at the KB root, then `AGENTS.md` if it also exists');
|
|
87
|
-
expect(note).toContain("the organisation's own conventions");
|
|
88
|
-
// Ours first: an agent that reads only one must read the platform's.
|
|
89
|
-
expect(note.indexOf('`HEXIS.md`')).toBeLessThan(note.indexOf('`AGENTS.md`'));
|
|
90
|
-
// The legacy name is still offered, for a KB seeded before the rename.
|
|
91
|
-
expect(note).toContain('`CLAUDE.md`');
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it('lists the platform files under the configured name, and no longer under AGENTS.md', () => {
|
|
87
|
+
it('lists the guide under no name as a platform file, and ignores a name a deployment saved for it', () => {
|
|
95
88
|
kb.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: 'HEXIS.md' });
|
|
96
89
|
const rules = sharedFileRulesSection(kb.layout);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
// `HEXIS.md` it may rename.
|
|
101
|
-
expect(rules).toContain('`access.md` or `.bevelignore` in any folder, `roles.yaml` or `HEXIS.md` at the repository root');
|
|
102
|
-
// The customer's file is content on such a deployment, so the rule that
|
|
103
|
-
// refuses a move must not claim it.
|
|
104
|
-
expect(rules.replace(/`AGENTS\.md` if it also exists/g, '')).not.toContain('`AGENTS.md`');
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it('keeps naming AGENTS.md as a platform file under the default name', () => {
|
|
108
|
-
expect(sharedFileRulesSection(kb.layout)).toContain(
|
|
109
|
-
'`access.md` or `.bevelignore` in any folder, `roles.yaml` or `AGENTS.md` at the repository root',
|
|
110
|
-
);
|
|
90
|
+
expect(rules).toContain('`access.md` or `.bevelignore` in any folder, `roles.yaml` at the repository root');
|
|
91
|
+
expect(rules).not.toContain('HEXIS.md');
|
|
92
|
+
expect(rules).toBe(sharedFileRulesSection(DEFAULT_KB_LAYOUT));
|
|
111
93
|
});
|
|
112
94
|
|
|
113
95
|
/**
|
|
114
96
|
* First-run setup on a fresh deployment: the tools are mounted at boot, under
|
|
115
97
|
* the defaults, and the save that COMPLETES setup applies the admin's names
|
|
116
|
-
* in that same request — without a restart
|
|
117
|
-
*
|
|
118
|
-
* would go on naming `AGENTS.md` to every agent that connected afterwards.
|
|
98
|
+
* in that same request — without a restart. Nothing in the opening sentence
|
|
99
|
+
* moves with a name, so what the catalog said at boot is what it says after.
|
|
119
100
|
*/
|
|
120
|
-
it('
|
|
101
|
+
it('says the same thing after a layout is applied as it did at the mount', async () => {
|
|
121
102
|
const registry = new ToolRegistry();
|
|
122
103
|
const atMount = await descriptions(registry);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
kb.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: 'HEXIS.md' });
|
|
126
|
-
|
|
104
|
+
kb.applyLayout({ ...DEFAULT_KB_LAYOUT, knowledgeBaseDir: 'Docs' });
|
|
127
105
|
const now = await listed(registry);
|
|
128
106
|
for (const name of ['grep', 'file_stat', 'delete_file', 'move_file']) {
|
|
129
|
-
expect(now.get(name), name).
|
|
130
|
-
expect(now.get(name), name).
|
|
107
|
+
expect(now.get(name)!.startsWith(GUIDE_FIRST_SENTENCE), name).toBe(true);
|
|
108
|
+
expect(now.get(name), name).toBe(atMount.get(name));
|
|
131
109
|
}
|
|
132
110
|
});
|
|
133
111
|
});
|