@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
|
@@ -14,11 +14,10 @@ import { PluginManifestsStep } from '../plugin-manifests.step.js';
|
|
|
14
14
|
import { PersonalSpacesStep } from '../personal-spaces.step.js';
|
|
15
15
|
import { RolesYamlStep } from '../roles-yaml.step.js';
|
|
16
16
|
import { renderRolesYaml } from '../../../../access-model/render-roles-yaml.js';
|
|
17
|
-
import { mergeGroupsIntoRoles, parseRolesYaml } from '../../../../access-model/access-grammar.js';
|
|
18
17
|
import { TemplateFilesStep } from '../template-files.step.js';
|
|
19
18
|
import { buildSeedTree } from '../seed-tree.js';
|
|
20
19
|
import { defaultKbTemplateDir } from '../../../../../assets.js';
|
|
21
|
-
import { DEFAULT_KB_LAYOUT
|
|
20
|
+
import { DEFAULT_KB_LAYOUT } from '@bevel-software/platform-shared';
|
|
22
21
|
import { renderTemplateText } from '../template-source.js';
|
|
23
22
|
import { TOOL_PREFIX_LINE, composeAgentInstructions, platformInstructions } from '../../../../agent-instructions/index.js';
|
|
24
23
|
import { testKbContext } from '../../../../../__tests__/kb-context.js';
|
|
@@ -139,6 +138,11 @@ async function readJson(dir: string, rel: string): Promise<Record<string, any>>
|
|
|
139
138
|
}
|
|
140
139
|
|
|
141
140
|
const norm = (text: string) => text.replace(/\r\n?/g, '\n');
|
|
141
|
+
|
|
142
|
+
/** What a release that wrote the guide to disk left at the root: the header that proves the copy ours. */
|
|
143
|
+
const MANAGED_GUIDE_COPY =
|
|
144
|
+
'# Knowledge base\n\n> **This file is managed by the platform.** It lives at the repository root as\n' +
|
|
145
|
+
'> `AGENTS.md`, and every server restart replaces it with the current template.\n\n## Directory Structure\n';
|
|
142
146
|
const PREAMBLE_IGNORE_BLOCK =
|
|
143
147
|
'\n# Added by the platform: agent instructions are edited from External agent access.\n' +
|
|
144
148
|
'/mcp-description.md\n';
|
|
@@ -155,7 +159,6 @@ async function template(name: string): Promise<string> {
|
|
|
155
159
|
async function fullScaffold(): Promise<Record<string, string>> {
|
|
156
160
|
return {
|
|
157
161
|
'access.md': await template('access.md'),
|
|
158
|
-
'AGENTS.md': await template('AGENTS.md'),
|
|
159
162
|
'.bevelignore': await template('.bevelignore'),
|
|
160
163
|
'.gitignore': await template('gitignore.template'),
|
|
161
164
|
'mcp-description.md': await template('mcp-description.md'),
|
|
@@ -172,7 +175,7 @@ describe('TemplateFilesStep', () => {
|
|
|
172
175
|
|
|
173
176
|
for (const b of PROTECTED) {
|
|
174
177
|
const dir = await checkout(b);
|
|
175
|
-
for (const rel of ['access.md', '
|
|
178
|
+
for (const rel of ['access.md', '.bevelignore', '.gitignore', 'mcp-description.md']) {
|
|
176
179
|
expect(await exists(dir, rel), `${b}: ${rel}`).toBe(true);
|
|
177
180
|
}
|
|
178
181
|
// The packaged template cannot ship a literal .gitignore (npm strips
|
|
@@ -199,12 +202,10 @@ describe('TemplateFilesStep', () => {
|
|
|
199
202
|
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
200
203
|
|
|
201
204
|
const dir = await checkout(DEFAULT_BRANCH);
|
|
202
|
-
|
|
203
|
-
expect(
|
|
204
|
-
expect(agents).toContain('`docs/`');
|
|
205
|
-
expect(agents).not.toContain('{{');
|
|
206
|
-
expect(agents).not.toContain('KnowledgeBase/');
|
|
205
|
+
// No guide is written: the platform serves it (see modules/agent-guide).
|
|
206
|
+
expect(await exists(dir, 'AGENTS.md')).toBe(false);
|
|
207
207
|
const ignore = norm(await fs.readFile(path.join(dir, '.bevelignore'), 'utf8')).split('\n').map((l) => l.trim());
|
|
208
|
+
expect(ignore).not.toContain('AGENTS.md');
|
|
208
209
|
// Both roots stay VISIBLE, whatever they are called: the Skills & Tools
|
|
209
210
|
// sidebar reads each from the workspace tree.
|
|
210
211
|
expect(ignore).not.toContain('plugins/');
|
|
@@ -228,44 +229,6 @@ describe('TemplateFilesStep', () => {
|
|
|
228
229
|
* written file (an MCP session reads the branch's copy of it), under the
|
|
229
230
|
* deployment's own root names rather than the placeholders.
|
|
230
231
|
*/
|
|
231
|
-
it('writes the "Where a new file goes" placement rule, named for the deployment\'s roots', async () => {
|
|
232
|
-
kbContext.applyLayout({ knowledgeBaseDir: 'Docs', skillsDir: 'Abilities', pluginsDir: 'Extensions' });
|
|
233
|
-
await seedUpstream({ 'marker.txt': 'seeded' });
|
|
234
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
235
|
-
|
|
236
|
-
const dir = await checkout(DEFAULT_BRANCH);
|
|
237
|
-
const agents = norm(await fs.readFile(path.join(dir, 'AGENTS.md'), 'utf8'));
|
|
238
|
-
const start = agents.indexOf('## Where a new file goes\n');
|
|
239
|
-
expect(start, 'the written guide has no placement section').toBeGreaterThan(-1);
|
|
240
|
-
// The section alone, so a phrase matched elsewhere in the guide cannot
|
|
241
|
-
// stand in for a rule that is missing here.
|
|
242
|
-
const section = agents.slice(start).split('\n## ')[0]!;
|
|
243
|
-
|
|
244
|
-
// A document goes to the knowledge root, a shared skill to the skills
|
|
245
|
-
// root or the plugin's own skills folder, machinery inside a plugin.
|
|
246
|
-
expect(section).toContain('`Docs/`');
|
|
247
|
-
expect(section).toContain('`Abilities/`');
|
|
248
|
-
expect(section).toContain('Extensions/<Plugin>/skills/<skill>/SKILL.md');
|
|
249
|
-
expect(section).toContain('Extensions/<Plugin>/software.bevel.hexis/tools/');
|
|
250
|
-
for (const kind of ['notes', 'reports', 'tickets', 'mcp.json', 'plugin.json']) {
|
|
251
|
-
expect(section, kind).toContain(kind);
|
|
252
|
-
}
|
|
253
|
-
// And the two rules the tester's agent broke.
|
|
254
|
-
expect(section).toMatch(/never holds a document/);
|
|
255
|
-
expect(section).toMatch(/\bask\b/);
|
|
256
|
-
|
|
257
|
-
// Rendered, not raw: a leftover placeholder would name a folder that is
|
|
258
|
-
// not there in a section whose whole job is naming the right folder.
|
|
259
|
-
expect(section).not.toContain('{{');
|
|
260
|
-
expect(section).not.toContain('KnowledgeBase/');
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* The step is built at boot, while the process still runs the defaults; the
|
|
265
|
-
* save that completes first-run setup applies the admin's names afterwards.
|
|
266
|
-
* A root list snapshotted at construction scaffolded `Skills/` beside the
|
|
267
|
-
* `skills/` they had just chosen — the very bug the names exist to avoid.
|
|
268
|
-
*/
|
|
269
232
|
it('scaffolds the layout in effect when it RUNS, not the one it was built under', async () => {
|
|
270
233
|
const builtAtBoot = new TemplateFilesStep(new NodeFs(), kbContext);
|
|
271
234
|
await seedUpstream({ 'skills/deploy/SKILL.md': '# deploy\n' });
|
|
@@ -287,82 +250,6 @@ describe('TemplateFilesStep', () => {
|
|
|
287
250
|
expect(subject).not.toContain('Skills/');
|
|
288
251
|
});
|
|
289
252
|
|
|
290
|
-
it('replaces a drifted AGENTS.md, and says so when that is the only change', async () => {
|
|
291
|
-
await seedUpstream({ ...(await fullScaffold()), 'AGENTS.md': 'stale conventions\n' });
|
|
292
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
293
|
-
|
|
294
|
-
const dir = await checkout(DEFAULT_BRANCH);
|
|
295
|
-
expect(norm(await fs.readFile(path.join(dir, 'AGENTS.md'), 'utf8'))).toBe(norm(await template('AGENTS.md')));
|
|
296
|
-
const subject = (await git(dir, ['log', '--format=%s', '-1'])).trim();
|
|
297
|
-
expect(subject).toBe('Update AGENTS.md to the current platform template');
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
it('ships the roles-vs-groups guide, and a deployment on an older template receives it at boot', async () => {
|
|
301
|
-
const guide = await template('AGENTS.md');
|
|
302
|
-
// The section runs from its own heading to the next heading of any level (or the end).
|
|
303
|
-
const section = guide.split(/\n(?=#{1,6} )/).find((s) => s.startsWith('### Roles are pre-set')) ?? '';
|
|
304
|
-
const prose = section.replace(/\s+/g, ' ');
|
|
305
|
-
// What roles are, that agents never create them, the group test, what to do instead.
|
|
306
|
-
expect(prose).toContain('A role in `roles.yaml` is an app role');
|
|
307
|
-
expect(prose).toContain('**Agents never create roles.**');
|
|
308
|
-
expect(prose).toContain('**Is it really a group?**');
|
|
309
|
-
expect(prose).toContain('**What to do instead.**');
|
|
310
|
-
expect(prose).toContain('add people to existing roles, and use a GROUP for a task- or team-scoped set of people');
|
|
311
|
-
|
|
312
|
-
// An existing deployment's AGENTS.md from before the guide existed.
|
|
313
|
-
await seedUpstream({ ...(await fullScaffold()), 'AGENTS.md': guide.replace(section, '') });
|
|
314
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
315
|
-
|
|
316
|
-
const dir = await checkout(DEFAULT_BRANCH);
|
|
317
|
-
expect(norm(await fs.readFile(path.join(dir, 'AGENTS.md'), 'utf8'))).toContain('**Agents never create roles.**');
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
it('documents giving a role to a group, with a valid example, in the guide the step writes', async () => {
|
|
321
|
-
const guide = await template('AGENTS.md');
|
|
322
|
-
const section = guide.split(/\n(?=#{2,3} )/).find((s) => s.startsWith('### Giving a role to a group')) ?? '';
|
|
323
|
-
const prose = section.replace(/\s+/g, ' ');
|
|
324
|
-
expect(prose).toContain('`- group:<Name>`');
|
|
325
|
-
expect(prose).toContain('case- and whitespace-insensitively against the active group source');
|
|
326
|
-
expect(prose).toContain('validation error');
|
|
327
|
-
expect(prose).toContain('names the entry');
|
|
328
|
-
expect(prose).toContain("removes the role's contribution for everyone in the group");
|
|
329
|
-
// A bare name resolves to a same-named group first, so role denials use `role/`.
|
|
330
|
-
expect(prose).toContain('`deny role/Reviewer`');
|
|
331
|
-
// Closeness first: a person's own entry wins only inside the same access.md.
|
|
332
|
-
expect(prose).toContain('The nearest `access.md` that says anything about the person decides');
|
|
333
|
-
expect(prose).toContain('in the SAME `access.md` as the denial keeps that access');
|
|
334
|
-
expect(prose).toContain('A group under `Admin` makes every member a full admin');
|
|
335
|
-
// A change request cannot carry a roles.yaml edit — the merge restores the
|
|
336
|
-
// base file — so the guide says who changes roles and where, and never
|
|
337
|
-
// walks an agent through drafting one.
|
|
338
|
-
expect(prose).toContain('Only an Admin changes `roles.yaml`');
|
|
339
|
-
expect(prose).toContain('A change request cannot carry the edit');
|
|
340
|
-
expect(prose).toContain('Do not propose one');
|
|
341
|
-
expect(prose).toContain('`edit_file`');
|
|
342
|
-
for (const tool of ['create_branch', 'commit_change', 'open_change_request']) {
|
|
343
|
-
expect(prose).not.toContain(`\`${tool}\``);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// The example parses as a roles.yaml whose group entry names a real group.
|
|
347
|
-
const example = /```yaml\n([\s\S]*?)```/.exec(section)?.[1] ?? '';
|
|
348
|
-
expect(example).toContain('- group:Platform Team');
|
|
349
|
-
const parsed = parseRolesYaml(example);
|
|
350
|
-
expect(parsed.ok).toBe(true);
|
|
351
|
-
if (!parsed.ok) return;
|
|
352
|
-
const groups = new Map([['platform team', { displayName: 'Platform Team', emails: new Set(['pat@example.com']) }]]);
|
|
353
|
-
expect(mergeGroupsIntoRoles(parsed.index, groups, 'groups.yaml')).toEqual([]);
|
|
354
|
-
// The example hands out an ordinary role, never Admin.
|
|
355
|
-
expect(parsed.index.byEmail.get('pat@example.com')?.has('reviewer')).toBe(true);
|
|
356
|
-
expect(parsed.index.byEmail.get('pat@example.com')?.has('role/admin')).toBe(false);
|
|
357
|
-
|
|
358
|
-
// What the step writes — the file agents read through the MCP server — carries it.
|
|
359
|
-
await seedUpstream({ ...(await fullScaffold()), 'AGENTS.md': guide.replace(section, '') });
|
|
360
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
361
|
-
const written = norm(await fs.readFile(path.join(await checkout(DEFAULT_BRANCH), 'AGENTS.md'), 'utf8'));
|
|
362
|
-
expect(written).toContain('### Giving a role to a group');
|
|
363
|
-
expect(written).toContain(example);
|
|
364
|
-
});
|
|
365
|
-
|
|
366
253
|
it('rejects the git folder — in any spelling — as a reserved root name', async () => {
|
|
367
254
|
for (const bad of ['.git', '.GIT', '.Git', '.git.', '%2egit']) {
|
|
368
255
|
expect(() => new TemplateFilesStep(new NodeFs(), kbContext, [bad]), bad).toThrow(/must not name the git folder/);
|
|
@@ -375,7 +262,6 @@ describe('TemplateFilesStep', () => {
|
|
|
375
262
|
// so the declared content itself must arrive with the rule in it.
|
|
376
263
|
const customTemplate = path.join(root, 'custom-template');
|
|
377
264
|
await fs.mkdir(customTemplate, { recursive: true });
|
|
378
|
-
await fs.writeFile(path.join(customTemplate, 'AGENTS.md'), await template('AGENTS.md'), 'utf8');
|
|
379
265
|
await fs.writeFile(path.join(customTemplate, '.bevelignore'), '# custom\nMyStuff/\n', 'utf8');
|
|
380
266
|
const scaffold = await fullScaffold();
|
|
381
267
|
delete scaffold['.bevelignore']; // the one file the step will declare from the template
|
|
@@ -386,7 +272,7 @@ describe('TemplateFilesStep', () => {
|
|
|
386
272
|
const dir = await checkout(DEFAULT_BRANCH);
|
|
387
273
|
const lines = norm(await fs.readFile(path.join(dir, '.bevelignore'), 'utf8')).split('\n').map((l) => l.trim());
|
|
388
274
|
expect(lines).toContain('MyStuff/'); // the operator's rules survive
|
|
389
|
-
expect(lines).toContain('AGENTS.md'); // the
|
|
275
|
+
expect(lines).not.toContain('AGENTS.md'); // no rule for the guide: it is not on disk
|
|
390
276
|
expect(lines).toContain('/mcp-description.md');
|
|
391
277
|
expect(lines).not.toContain('Skills/'); // never the skills root — the Library's tree needs it
|
|
392
278
|
});
|
|
@@ -531,7 +417,7 @@ describe('TemplateFilesStep', () => {
|
|
|
531
417
|
await expect(fs.readFile(path.join(dir, 'notes.md'), 'utf8')).rejects.toMatchObject({ code: 'ENOENT' });
|
|
532
418
|
await expect(fs.readdir(path.join(dir, '.git'))).rejects.toMatchObject({ code: 'ENOENT' });
|
|
533
419
|
// The rest of the template still seeded.
|
|
534
|
-
expect(await fs.readFile(path.join(dir, '
|
|
420
|
+
expect(await fs.readFile(path.join(dir, 'access.md'), 'utf8')).toContain('---');
|
|
535
421
|
});
|
|
536
422
|
|
|
537
423
|
it('seeds a binary template file byte for byte and keeps a script executable — text is what decodes', async () => {
|
|
@@ -564,7 +450,6 @@ describe('TemplateFilesStep', () => {
|
|
|
564
450
|
// must arrive already reconciled.
|
|
565
451
|
const customTemplate = path.join(root, 'custom-template-stale');
|
|
566
452
|
await fs.mkdir(customTemplate, { recursive: true });
|
|
567
|
-
await fs.writeFile(path.join(customTemplate, 'AGENTS.md'), await template('AGENTS.md'), 'utf8');
|
|
568
453
|
await fs.writeFile(
|
|
569
454
|
path.join(customTemplate, '.bevelignore'),
|
|
570
455
|
'# custom\nMyStuff/\n# The shared-skills root is rendered by the Skills & Tools app, like {{pluginsDir}}/.\n{{skillsDir}}/\n',
|
|
@@ -717,7 +602,6 @@ describe('TemplateFilesStep', () => {
|
|
|
717
602
|
// comment. The packaged copy stands in, and the log says so once.
|
|
718
603
|
const customTemplate = path.join(root, 'custom-template-old');
|
|
719
604
|
await fs.mkdir(customTemplate, { recursive: true });
|
|
720
|
-
await fs.writeFile(path.join(customTemplate, 'AGENTS.md'), await template('AGENTS.md'), 'utf8');
|
|
721
605
|
await fs.writeFile(path.join(customTemplate, 'access.md'), await template('access.md'), 'utf8');
|
|
722
606
|
const scaffold = await fullScaffold();
|
|
723
607
|
delete scaffold['mcp-description.md'];
|
|
@@ -736,327 +620,169 @@ describe('TemplateFilesStep', () => {
|
|
|
736
620
|
it('gives the stand-in to that file only: a custom template missing access.md still fails loudly', async () => {
|
|
737
621
|
const stricter = path.join(root, 'custom-template-broken');
|
|
738
622
|
await fs.mkdir(stricter, { recursive: true });
|
|
739
|
-
await fs.writeFile(path.join(stricter, 'AGENTS.md'), await template('AGENTS.md'), 'utf8');
|
|
740
623
|
const scaffold = await fullScaffold();
|
|
741
624
|
delete scaffold['access.md'];
|
|
742
625
|
await seedUpstream(scaffold);
|
|
743
626
|
await expect(makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)], stricter).runAll()).rejects.toThrow(/ENOENT/);
|
|
744
627
|
});
|
|
628
|
+
});
|
|
745
629
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
630
|
+
/**
|
|
631
|
+
* The guide copies earlier releases wrote to the repository root, and the
|
|
632
|
+
* ignore rules that hid them. The guide is served from code now (see
|
|
633
|
+
* modules/agent-guide), so a copy on disk is a stale file under a header
|
|
634
|
+
* that says the platform owns it — taken out on the first start, on every
|
|
635
|
+
* protected branch, and only when that header proves it ours.
|
|
636
|
+
*/
|
|
637
|
+
describe('TemplateFilesStep: the guide copies earlier releases wrote', () => {
|
|
638
|
+
/** The ignore file the last release that wrote the guide shipped, verbatim. */
|
|
639
|
+
const OLD_RELEASE_IGNORE =
|
|
640
|
+
'# Entries listed here are hidden from the Bevel file tree / agent view.\n\n.git/\n\n' +
|
|
641
|
+
'# Repo hygiene files that clutter the tree without being node content.\n.gitignore\n.gitattributes\n' +
|
|
642
|
+
"# The platform's agent guide.\nAGENTS.md\n" +
|
|
643
|
+
'# The deployment preamble is edited from External agent access, not as a KB page.\n/mcp-description.md\n' +
|
|
644
|
+
'# The pre-rename name. Listed so a knowledge base carrying both files hides\n' +
|
|
645
|
+
'# both — top-up adds AGENTS.md but never deletes the CLAUDE.md beside it.\nCLAUDE.md\n\n' +
|
|
646
|
+
'**/.gitkeep\n\n**/access.md\nroles.yaml\n';
|
|
647
|
+
const CUSTOMER_GUIDE = '# Acme conventions\n\nWrite tickets in the present tense.\n';
|
|
648
|
+
const ignoreLines = async (dir: string) =>
|
|
649
|
+
norm(await fs.readFile(path.join(dir, '.bevelignore'), 'utf8')).split('\n').map((l) => l.trim());
|
|
650
|
+
|
|
651
|
+
it('removes the platform-written AGENTS.md from every protected branch, and the rules that hid it', async () => {
|
|
652
|
+
await seedUpstream({ ...(await fullScaffold()), 'AGENTS.md': MANAGED_GUIDE_COPY, '.bevelignore': OLD_RELEASE_IGNORE });
|
|
758
653
|
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
759
654
|
|
|
760
|
-
const
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
/**
|
|
765
|
-
* The guide under a name of the deployment's own — and what becomes of the
|
|
766
|
-
* `AGENTS.md` beside it, which on such a deployment is the CUSTOMER'S file.
|
|
767
|
-
*/
|
|
768
|
-
describe('a renamed agent guide', () => {
|
|
769
|
-
/** The scaffold minus the guide, so each test says for itself what `AGENTS.md` holds. */
|
|
770
|
-
async function scaffoldWithoutGuide(): Promise<Record<string, string>> {
|
|
771
|
-
const scaffold = await fullScaffold();
|
|
772
|
-
delete scaffold['AGENTS.md'];
|
|
773
|
-
return scaffold;
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
const CUSTOMER_GUIDE = '# Acme conventions\n\nWrite tickets in the present tense.\n';
|
|
777
|
-
|
|
778
|
-
it('writes and refreshes the guide under the configured name, on every protected branch', async () => {
|
|
779
|
-
kbContext.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: 'HEXIS.md' });
|
|
780
|
-
await seedUpstream({ 'marker.txt': 'seeded' });
|
|
781
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
782
|
-
|
|
783
|
-
for (const branch of PROTECTED) {
|
|
784
|
-
const dir = await checkout(branch);
|
|
785
|
-
const guide = norm(await fs.readFile(path.join(dir, 'HEXIS.md'), 'utf8'));
|
|
786
|
-
// The header names the file it lives in, not the name it ships under.
|
|
787
|
-
expect(guide).toContain('`HEXIS.md`');
|
|
788
|
-
expect(guide).not.toContain('{{');
|
|
789
|
-
expect(await exists(dir, 'AGENTS.md')).toBe(false);
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
// A second boot sees the rendered guide as current: no churn commit…
|
|
793
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
794
|
-
expect((await git(await checkout(DEFAULT_BRANCH), ['rev-list', '--count', 'HEAD'])).trim()).toBe('2');
|
|
795
|
-
|
|
796
|
-
// …and a drifted copy is replaced, exactly as `AGENTS.md` is by default.
|
|
797
|
-
const dir = await checkout(DEFAULT_BRANCH);
|
|
798
|
-
await fs.writeFile(path.join(dir, 'HEXIS.md'), 'stale conventions\n', 'utf8');
|
|
799
|
-
await git(dir, ['commit', '-am', 'drift']);
|
|
800
|
-
await git(dir, ['push', 'origin', DEFAULT_BRANCH]);
|
|
801
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
802
|
-
const after = await checkout(DEFAULT_BRANCH);
|
|
803
|
-
expect(norm(await fs.readFile(path.join(after, 'HEXIS.md'), 'utf8'))).toContain('# Knowledge base');
|
|
804
|
-
expect((await git(after, ['log', '--format=%s', '-1'])).trim()).toBe(
|
|
805
|
-
'Update HEXIS.md to the current platform template',
|
|
806
|
-
);
|
|
807
|
-
});
|
|
808
|
-
|
|
809
|
-
it('leaves a customer AGENTS.md byte for byte alone, and shows it in the tree', async () => {
|
|
810
|
-
kbContext.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: 'HEXIS.md' });
|
|
811
|
-
// Their file already names the guide, so the pointer has nothing to add
|
|
812
|
-
// — this test is about the bytes and the ignore rules alone.
|
|
813
|
-
const theirs = `${CUSTOMER_GUIDE}\nSee HEXIS.md for the platform.\n`;
|
|
814
|
-
await seedUpstream({ ...(await scaffoldWithoutGuide()), 'AGENTS.md': theirs });
|
|
815
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
816
|
-
|
|
817
|
-
const dir = await checkout(DEFAULT_BRANCH);
|
|
818
|
-
expect(norm(await fs.readFile(path.join(dir, 'AGENTS.md'), 'utf8'))).toBe(theirs);
|
|
819
|
-
expect(await exists(dir, 'HEXIS.md')).toBe(true);
|
|
820
|
-
const ignore = norm(await fs.readFile(path.join(dir, '.bevelignore'), 'utf8'))
|
|
821
|
-
.split('\n')
|
|
822
|
-
.map((l) => l.trim());
|
|
823
|
-
// The configured file is hidden; the customer's shows.
|
|
824
|
-
expect(ignore).toContain('HEXIS.md');
|
|
825
|
-
expect(ignore).not.toContain('AGENTS.md');
|
|
826
|
-
});
|
|
827
|
-
|
|
828
|
-
it('removes the platform-written AGENTS.md — only its own header proves it ours', async () => {
|
|
829
|
-
// A knowledge base the platform seeded, whose admin then renames the guide.
|
|
830
|
-
await seedUpstream({ 'marker.txt': 'seeded' });
|
|
831
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
832
|
-
expect(await exists(await checkout(DEFAULT_BRANCH), 'AGENTS.md')).toBe(true);
|
|
833
|
-
|
|
834
|
-
kbContext.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: 'HEXIS.md' });
|
|
835
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
836
|
-
|
|
837
|
-
// On EVERY protected branch: the step tops up each one, and a rename
|
|
838
|
-
// that only reached the default branch would leave the others carrying a
|
|
839
|
-
// stale platform guide under the customer's name.
|
|
840
|
-
for (const branch of PROTECTED) {
|
|
841
|
-
const dir = await checkout(branch);
|
|
842
|
-
expect(await exists(dir, 'AGENTS.md'), branch).toBe(false);
|
|
843
|
-
expect(await exists(dir, 'HEXIS.md'), branch).toBe(true);
|
|
844
|
-
const message = await git(dir, ['log', '--format=%B', '-1']);
|
|
845
|
-
expect(message, branch).toContain(
|
|
846
|
-
'Remove the platform-written AGENTS.md — the agent guide is now HEXIS.md',
|
|
847
|
-
);
|
|
848
|
-
}
|
|
849
|
-
});
|
|
850
|
-
|
|
851
|
-
it('keeps an AGENTS.md it cannot prove it wrote, and says so', async () => {
|
|
852
|
-
kbContext.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: 'HEXIS.md' });
|
|
853
|
-
// Edited by the customer: the managed header is gone, so it is theirs.
|
|
854
|
-
const edited = `${CUSTOMER_GUIDE}\nMentions HEXIS.md already.\n`;
|
|
855
|
-
await seedUpstream({ ...(await scaffoldWithoutGuide()), 'AGENTS.md': edited });
|
|
856
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
857
|
-
|
|
858
|
-
for (const branch of PROTECTED) {
|
|
859
|
-
const dir = await checkout(branch);
|
|
860
|
-
expect(norm(await fs.readFile(path.join(dir, 'AGENTS.md'), 'utf8')), branch).toBe(edited);
|
|
861
|
-
expect(await git(dir, ['log', '--format=%B', '-1']), branch).toContain('Keep AGENTS.md');
|
|
862
|
-
}
|
|
863
|
-
});
|
|
864
|
-
|
|
865
|
-
it('leaves a root AGENTS.md that is a symbolic link exactly where it points', async () => {
|
|
866
|
-
// Following the link would read the managed header at the other end and
|
|
867
|
-
// delete the customer's entry — or, with the pointer on, write our
|
|
868
|
-
// sentence into a file nobody asked us to edit.
|
|
869
|
-
kbContext.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: 'HEXIS.md' });
|
|
870
|
-
await seedUpstream({ ...(await scaffoldWithoutGuide()), 'conventions/ours.md': await template('AGENTS.md') });
|
|
871
|
-
// Committed as a link, so every checkout the step makes carries one.
|
|
872
|
-
const seeding = await checkout(DEFAULT_BRANCH);
|
|
873
|
-
await fs.symlink('conventions/ours.md', path.join(seeding, 'AGENTS.md'));
|
|
874
|
-
await git(seeding, ['add', '-A']);
|
|
875
|
-
await git(seeding, ['commit', '-m', 'link AGENTS.md at our own file']);
|
|
876
|
-
await git(seeding, ['push', 'origin', DEFAULT_BRANCH]);
|
|
877
|
-
|
|
878
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
879
|
-
|
|
880
|
-
const dir = await checkout(DEFAULT_BRANCH);
|
|
881
|
-
expect((await fs.lstat(path.join(dir, 'AGENTS.md'))).isSymbolicLink()).toBe(true);
|
|
882
|
-
expect(await fs.readlink(path.join(dir, 'AGENTS.md'))).toBe('conventions/ours.md');
|
|
883
|
-
// The file at the other end is untouched — neither removed nor appended to.
|
|
884
|
-
expect(norm(await fs.readFile(path.join(dir, 'conventions/ours.md'), 'utf8'))).toBe(
|
|
885
|
-
norm(await template('AGENTS.md')),
|
|
886
|
-
);
|
|
887
|
-
});
|
|
888
|
-
|
|
889
|
-
it("keeps an operator's own AGENTS.md ignore rule while dropping the platform's", async () => {
|
|
890
|
-
kbContext.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: 'HEXIS.md' });
|
|
891
|
-
const scaffold = await scaffoldWithoutGuide();
|
|
892
|
-
// Their own rule, written by hand, nowhere near the template's slot.
|
|
893
|
-
scaffold['.bevelignore'] = '# mine\nAGENTS.md\nMyStuff/\n';
|
|
894
|
-
scaffold['AGENTS.md'] = `${CUSTOMER_GUIDE}\nSee HEXIS.md.\n`;
|
|
895
|
-
await seedUpstream(scaffold);
|
|
896
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
897
|
-
|
|
898
|
-
const text = norm(
|
|
899
|
-
await fs.readFile(path.join(await checkout(DEFAULT_BRANCH), '.bevelignore'), 'utf8'),
|
|
900
|
-
);
|
|
901
|
-
expect(text).toContain('# mine\nAGENTS.md\nMyStuff/');
|
|
902
|
-
expect(text.split('\n').map((l) => l.trim())).toContain('HEXIS.md');
|
|
903
|
-
});
|
|
904
|
-
|
|
905
|
-
it("keeps an operator's rule that merely happens to sit under .gitattributes", async () => {
|
|
906
|
-
kbContext.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: 'HEXIS.md' });
|
|
907
|
-
const scaffold = await scaffoldWithoutGuide();
|
|
908
|
-
// Hand-written, and by coincidence in the position the template's own
|
|
909
|
-
// rule used to occupy. One matching line above is not provenance — the
|
|
910
|
-
// block the template wrote is not there, so the rule is theirs.
|
|
911
|
-
scaffold['.bevelignore'] = '# ours\n.gitattributes\nAGENTS.md\nMyStuff/\n';
|
|
912
|
-
scaffold['AGENTS.md'] = `${CUSTOMER_GUIDE}\nSee HEXIS.md.\n`;
|
|
913
|
-
await seedUpstream(scaffold);
|
|
914
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
915
|
-
|
|
916
|
-
const text = norm(
|
|
917
|
-
await fs.readFile(path.join(await checkout(DEFAULT_BRANCH), '.bevelignore'), 'utf8'),
|
|
918
|
-
);
|
|
919
|
-
expect(text).toContain('# ours\n.gitattributes\nAGENTS.md\nMyStuff/');
|
|
920
|
-
expect(text.split('\n').map((l) => l.trim())).toContain('HEXIS.md');
|
|
921
|
-
});
|
|
922
|
-
|
|
923
|
-
it("drops the bare rule an earlier release seeded in the template's hygiene block", async () => {
|
|
924
|
-
kbContext.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: 'HEXIS.md' });
|
|
925
|
-
const scaffold = await scaffoldWithoutGuide();
|
|
926
|
-
// The `.bevelignore` of a knowledge base seeded before the rule had a
|
|
927
|
-
// comment above it: bare, at the end of the template's own block.
|
|
928
|
-
scaffold['.bevelignore'] =
|
|
929
|
-
'# Repo hygiene files that clutter the tree without being node content.\n' +
|
|
930
|
-
'.gitignore\n.gitattributes\nAGENTS.md\nroles.yaml\n';
|
|
931
|
-
scaffold['AGENTS.md'] = `${CUSTOMER_GUIDE}\nSee HEXIS.md.\n`;
|
|
932
|
-
await seedUpstream(scaffold);
|
|
933
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
934
|
-
|
|
935
|
-
const lines = norm(
|
|
936
|
-
await fs.readFile(path.join(await checkout(DEFAULT_BRANCH), '.bevelignore'), 'utf8'),
|
|
937
|
-
)
|
|
938
|
-
.split('\n')
|
|
939
|
-
.map((l) => l.trim());
|
|
940
|
-
// The platform's line goes; the block above it is content and stays.
|
|
655
|
+
for (const branch of PROTECTED) {
|
|
656
|
+
const dir = await checkout(branch);
|
|
657
|
+
expect(await exists(dir, 'AGENTS.md'), branch).toBe(false);
|
|
658
|
+
const lines = await ignoreLines(dir);
|
|
941
659
|
expect(lines).not.toContain('AGENTS.md');
|
|
660
|
+
expect(lines).not.toContain('CLAUDE.md');
|
|
661
|
+
expect(lines).not.toContain("# The platform's agent guide.");
|
|
662
|
+
expect(lines).not.toContain('# The pre-rename name. Listed so a knowledge base carrying both files hides');
|
|
663
|
+
// Everything else in the file is as it was.
|
|
942
664
|
expect(lines).toContain('.gitattributes');
|
|
943
|
-
expect(lines).toContain('.
|
|
944
|
-
expect(lines).toContain('
|
|
945
|
-
|
|
665
|
+
expect(lines).toContain('/mcp-description.md');
|
|
666
|
+
expect(lines).toContain('roles.yaml');
|
|
667
|
+
expect(await git(dir, ['log', '--format=%B', '-1']), branch).toContain(
|
|
668
|
+
'Remove the platform-written AGENTS.md — the agent guide is served by the platform now',
|
|
669
|
+
);
|
|
670
|
+
}
|
|
946
671
|
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
if (theirs !== null) scaffold['AGENTS.md'] = theirs;
|
|
953
|
-
await seedUpstream(scaffold);
|
|
954
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext, [], () => link)]).runAll();
|
|
955
|
-
return checkout(DEFAULT_BRANCH);
|
|
956
|
-
}
|
|
672
|
+
// The boot after finds nothing to do.
|
|
673
|
+
const head = (await git(await checkout(DEFAULT_BRANCH), ['rev-parse', 'HEAD'])).trim();
|
|
674
|
+
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
675
|
+
expect((await git(await checkout(DEFAULT_BRANCH), ['rev-parse', 'HEAD'])).trim()).toBe(head);
|
|
676
|
+
});
|
|
957
677
|
|
|
958
|
-
|
|
678
|
+
it("leaves the organisation's own AGENTS.md byte for byte, and stops hiding it", async () => {
|
|
679
|
+
await seedUpstream({ ...(await fullScaffold()), 'AGENTS.md': CUSTOMER_GUIDE, '.bevelignore': OLD_RELEASE_IGNORE });
|
|
680
|
+
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
959
681
|
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
expect(await git(dir, ['log', '--format=%B', '-1'])).toContain(
|
|
966
|
-
'Add a pointer to HEXIS.md at the end of AGENTS.md',
|
|
967
|
-
);
|
|
968
|
-
});
|
|
682
|
+
const dir = await checkout(DEFAULT_BRANCH);
|
|
683
|
+
expect(norm(await fs.readFile(path.join(dir, 'AGENTS.md'), 'utf8'))).toBe(CUSTOMER_GUIDE);
|
|
684
|
+
expect(await ignoreLines(dir)).not.toContain('AGENTS.md');
|
|
685
|
+
expect(await git(dir, ['log', '--format=%s', '-1'])).toContain('.bevelignore');
|
|
686
|
+
});
|
|
969
687
|
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
);
|
|
987
|
-
|
|
988
|
-
const head = (await git(await checkout(DEFAULT_BRANCH), ['rev-parse', 'HEAD'])).trim();
|
|
989
|
-
await boot();
|
|
990
|
-
const after = await checkout(DEFAULT_BRANCH);
|
|
991
|
-
expect(norm(await fs.readFile(path.join(after, 'AGENTS.md'), 'utf8'))).toBe(once);
|
|
992
|
-
// And the second boot committed nothing at all.
|
|
993
|
-
expect((await git(after, ['rev-parse', 'HEAD'])).trim()).toBe(head);
|
|
994
|
-
});
|
|
688
|
+
it("stops hiding the organisation's own file under a name a deployment once gave the guide, with no copy left to find it by", async () => {
|
|
689
|
+
// A deployment saved `HEXIS.md` for the guide; the organisation then made
|
|
690
|
+
// that file its own (no platform header left), and the rule the platform
|
|
691
|
+
// appended for the name is still hiding it. The saved name is not read
|
|
692
|
+
// any more, and no managed copy names it either: the rule is known by the
|
|
693
|
+
// comment the platform wrote above it, under either of its two spellings.
|
|
694
|
+
const scaffold = await fullScaffold();
|
|
695
|
+
scaffold['HEXIS.md'] = CUSTOMER_GUIDE;
|
|
696
|
+
scaffold['Guide.md'] = CUSTOMER_GUIDE;
|
|
697
|
+
scaffold['.bevelignore'] =
|
|
698
|
+
`${OLD_RELEASE_IGNORE}\n# The platform's agent guide.\nHEXIS.md\n` +
|
|
699
|
+
'\n# Added by the platform: the conventions doc is not node content.\nGuide.md\n' +
|
|
700
|
+
// A negation and a hand-written rule under neither comment stay.
|
|
701
|
+
'!Notes.md\n# mine\nPrivate.md\n';
|
|
702
|
+
await seedUpstream(scaffold);
|
|
703
|
+
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
995
704
|
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
`${CUSTOMER_GUIDE.replace(/\n+$/, '')}\n\n${agentsFilePointerSentence('GUIDE.md')}\n`,
|
|
1019
|
-
);
|
|
1020
|
-
expect(text).not.toContain('HEXIS.md');
|
|
1021
|
-
expect(await git(dir, ['log', '--format=%B', '-1'])).toContain(
|
|
1022
|
-
'Point the sentence in AGENTS.md at GUIDE.md',
|
|
1023
|
-
);
|
|
1024
|
-
});
|
|
705
|
+
const dir = await checkout(DEFAULT_BRANCH);
|
|
706
|
+
expect(norm(await fs.readFile(path.join(dir, 'HEXIS.md'), 'utf8'))).toBe(CUSTOMER_GUIDE);
|
|
707
|
+
expect(norm(await fs.readFile(path.join(dir, 'Guide.md'), 'utf8'))).toBe(CUSTOMER_GUIDE);
|
|
708
|
+
const lines = await ignoreLines(dir);
|
|
709
|
+
expect(lines).not.toContain('HEXIS.md');
|
|
710
|
+
expect(lines).not.toContain('Guide.md');
|
|
711
|
+
expect(lines).not.toContain("# The platform's agent guide.");
|
|
712
|
+
expect(lines).not.toContain('# Added by the platform: the conventions doc is not node content.');
|
|
713
|
+
expect(lines).toContain('!Notes.md');
|
|
714
|
+
expect(lines).toContain('# mine');
|
|
715
|
+
expect(lines).toContain('Private.md');
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
it("keeps a rule the operator wrote by hand — provenance is the platform's comment or its template slot", async () => {
|
|
719
|
+
const scaffold = await fullScaffold();
|
|
720
|
+
scaffold['.bevelignore'] = '# mine\nAGENTS.md\nMyStuff/\n';
|
|
721
|
+
scaffold['AGENTS.md'] = CUSTOMER_GUIDE;
|
|
722
|
+
await seedUpstream(scaffold);
|
|
723
|
+
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
724
|
+
const text = norm(await fs.readFile(path.join(await checkout(DEFAULT_BRANCH), '.bevelignore'), 'utf8'));
|
|
725
|
+
expect(text).toContain('# mine\nAGENTS.md\nMyStuff/');
|
|
726
|
+
});
|
|
1025
727
|
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
728
|
+
it('removes a copy under the name a deployment saved for the guide, its escaped rule, and a CLAUDE.md copy', async () => {
|
|
729
|
+
kbContext.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: '#Guide[1].md' });
|
|
730
|
+
const scaffold = await fullScaffold();
|
|
731
|
+
scaffold['#Guide[1].md'] = MANAGED_GUIDE_COPY;
|
|
732
|
+
scaffold['CLAUDE.md'] = MANAGED_GUIDE_COPY;
|
|
733
|
+
// The rule the release that wrote the guide under that name appended.
|
|
734
|
+
scaffold['.bevelignore'] = `${OLD_RELEASE_IGNORE}\n# The platform's agent guide.\n${String.raw`\#Guide\[1\].md`}\n`;
|
|
735
|
+
await seedUpstream(scaffold);
|
|
736
|
+
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
1031
737
|
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
738
|
+
const dir = await checkout(DEFAULT_BRANCH);
|
|
739
|
+
expect(await exists(dir, '#Guide[1].md')).toBe(false);
|
|
740
|
+
expect(await exists(dir, 'CLAUDE.md')).toBe(false);
|
|
741
|
+
const lines = await ignoreLines(dir);
|
|
742
|
+
expect(lines).not.toContain(String.raw`\#Guide\[1\].md`);
|
|
743
|
+
expect(lines).not.toContain('AGENTS.md');
|
|
744
|
+
expect(lines).not.toContain('CLAUDE.md');
|
|
745
|
+
expect(await git(dir, ['log', '--format=%B', '-1'])).toContain('Remove the platform-written #Guide[1].md and CLAUDE.md');
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
it('finds a copy under a name the deployment no longer uses, and leaves a root note of the organisation\'s own', async () => {
|
|
749
|
+
// Renamed twice while the guide was a file: a copy under the first name
|
|
750
|
+
// is still there, hidden by the rule that release appended, and nothing
|
|
751
|
+
// in today's settings remembers the name. The header does.
|
|
752
|
+
const scaffold = await fullScaffold();
|
|
753
|
+
scaffold['OLD-GUIDE.md'] = MANAGED_GUIDE_COPY;
|
|
754
|
+
scaffold['Welcome.md'] = '# Welcome\n\nStart with the handbook.\n';
|
|
755
|
+
scaffold['.bevelignore'] = `${OLD_RELEASE_IGNORE}\n# The platform's agent guide.\nOLD-GUIDE.md\n`;
|
|
756
|
+
await seedUpstream(scaffold);
|
|
757
|
+
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
1036
758
|
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
759
|
+
const dir = await checkout(DEFAULT_BRANCH);
|
|
760
|
+
expect(await exists(dir, 'OLD-GUIDE.md')).toBe(false);
|
|
761
|
+
expect(norm(await fs.readFile(path.join(dir, 'Welcome.md'), 'utf8'))).toBe('# Welcome\n\nStart with the handbook.\n');
|
|
762
|
+
const lines = await ignoreLines(dir);
|
|
763
|
+
expect(lines).not.toContain('OLD-GUIDE.md');
|
|
764
|
+
expect(lines).not.toContain('AGENTS.md');
|
|
765
|
+
expect(await git(dir, ['log', '--format=%B', '-1'])).toContain('Remove the platform-written OLD-GUIDE.md');
|
|
766
|
+
});
|
|
1042
767
|
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
768
|
+
it('leaves a root AGENTS.md that is a symbolic link exactly where it points', async () => {
|
|
769
|
+
// Following the link would read the managed header at the other end and
|
|
770
|
+
// delete the organisation's entry.
|
|
771
|
+
const scaffold = await fullScaffold();
|
|
772
|
+
scaffold['conventions/ours.md'] = MANAGED_GUIDE_COPY;
|
|
773
|
+
await seedUpstream(scaffold);
|
|
774
|
+
const seeding = await checkout(DEFAULT_BRANCH);
|
|
775
|
+
await fs.symlink('conventions/ours.md', path.join(seeding, 'AGENTS.md'));
|
|
776
|
+
await git(seeding, ['add', '-A']);
|
|
777
|
+
await git(seeding, ['commit', '-m', 'link AGENTS.md at our own file']);
|
|
778
|
+
await git(seeding, ['push', 'origin', DEFAULT_BRANCH]);
|
|
1047
779
|
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
const dir = await checkout(DEFAULT_BRANCH);
|
|
1055
|
-
const text = norm(await fs.readFile(path.join(dir, 'AGENTS.md'), 'utf8'));
|
|
1056
|
-
expect(text).toBe(norm(await template('AGENTS.md')));
|
|
1057
|
-
expect(text).not.toContain(agentsFilePointerSentence('AGENTS.md'));
|
|
1058
|
-
});
|
|
1059
|
-
});
|
|
780
|
+
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
781
|
+
|
|
782
|
+
const dir = await checkout(DEFAULT_BRANCH);
|
|
783
|
+
expect((await fs.lstat(path.join(dir, 'AGENTS.md'))).isSymbolicLink()).toBe(true);
|
|
784
|
+
expect(await fs.readlink(path.join(dir, 'AGENTS.md'))).toBe('conventions/ours.md');
|
|
785
|
+
expect(norm(await fs.readFile(path.join(dir, 'conventions/ours.md'), 'utf8'))).toBe(MANAGED_GUIDE_COPY);
|
|
1060
786
|
});
|
|
1061
787
|
});
|
|
1062
788
|
|
|
@@ -1160,47 +886,46 @@ describe('buildSeedTree', () => {
|
|
|
1160
886
|
expect(generated.sort()).toEqual(['Docs/.gitkeep', 'Plugins/.gitkeep', 'roles.yaml', 'skills/.gitkeep']);
|
|
1161
887
|
});
|
|
1162
888
|
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
* SEED rather than left to the top-up step, which would otherwise lay down
|
|
1166
|
-
* `AGENTS.md` and delete it one commit later — two commits saying opposite
|
|
1167
|
-
* things about a knowledge base nobody has used yet.
|
|
1168
|
-
*/
|
|
1169
|
-
it('seeds the packaged guide under the configured name, and no AGENTS.md beside it', async () => {
|
|
1170
|
-
kbContext.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: 'HEXIS.md' });
|
|
1171
|
-
const dest = path.join(root, 'seed-dest-guide');
|
|
889
|
+
it('seeds no guide, and no rule hiding one: the platform serves the guide', async () => {
|
|
890
|
+
const dest = path.join(root, 'seed-dest-no-guide');
|
|
1172
891
|
await fs.mkdir(dest, { recursive: true });
|
|
1173
892
|
await buildSeedTree(new NodeFs(), TEMPLATE_DIR, [], ['admin@example.com'], kbContext)(dest);
|
|
1174
893
|
expect(await exists(dest, 'AGENTS.md')).toBe(false);
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
expect(guide).not.toContain('{{');
|
|
1178
|
-
// And the ignore file hides the name it actually seeded.
|
|
1179
|
-
const ignore = norm(await fs.readFile(path.join(dest, '.bevelignore'), 'utf8'))
|
|
1180
|
-
.split('\n')
|
|
1181
|
-
.map((l) => l.trim());
|
|
1182
|
-
expect(ignore).toContain('HEXIS.md');
|
|
894
|
+
expect(await exists(dest, 'CLAUDE.md')).toBe(false);
|
|
895
|
+
const ignore = norm(await fs.readFile(path.join(dest, '.bevelignore'), 'utf8')).split('\n').map((l) => l.trim());
|
|
1183
896
|
expect(ignore).not.toContain('AGENTS.md');
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
//
|
|
1190
|
-
//
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
await fs.
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
await fs.
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
const
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
expect(await exists(
|
|
897
|
+
expect(ignore).not.toContain('CLAUDE.md');
|
|
898
|
+
expect(ignore).toContain('/mcp-description.md');
|
|
899
|
+
});
|
|
900
|
+
|
|
901
|
+
it("skips a distribution template's root AGENTS.md that is the platform's old guide, and seeds one that is the organisation's own", async () => {
|
|
902
|
+
// A KB_TEMPLATE_DIR forked while the guide was a file still ships one. Seeded,
|
|
903
|
+
// the first start would remove it one commit later — two commits saying
|
|
904
|
+
// opposite things about a knowledge base nobody has used yet.
|
|
905
|
+
const stale = path.join(root, 'custom-template-stale-guide');
|
|
906
|
+
await fs.cp(TEMPLATE_DIR, stale, { recursive: true });
|
|
907
|
+
await fs.writeFile(path.join(stale, 'AGENTS.md'), MANAGED_GUIDE_COPY, 'utf8');
|
|
908
|
+
// Under a name a deployment once gave the guide, too: the copy is known
|
|
909
|
+
// by its header, under any root Markdown name, as the first start knows it.
|
|
910
|
+
await fs.writeFile(path.join(stale, 'OLD-GUIDE.md'), MANAGED_GUIDE_COPY, 'utf8');
|
|
911
|
+
// And whatever case the extension was saved in, as the first start judges it.
|
|
912
|
+
await fs.writeFile(path.join(stale, 'LEGACY-GUIDE.MD'), MANAGED_GUIDE_COPY, 'utf8');
|
|
913
|
+
const staleDest = path.join(root, 'seed-dest-stale-guide');
|
|
914
|
+
await fs.mkdir(staleDest, { recursive: true });
|
|
915
|
+
await buildSeedTree(new NodeFs(), stale, [], ['admin@example.com'], kbContext)(staleDest);
|
|
916
|
+
expect(await exists(staleDest, 'AGENTS.md')).toBe(false);
|
|
917
|
+
expect(await exists(staleDest, 'OLD-GUIDE.md')).toBe(false);
|
|
918
|
+
expect(await exists(staleDest, 'LEGACY-GUIDE.MD')).toBe(false);
|
|
919
|
+
|
|
920
|
+
// A template whose root AGENTS.md is the organisation's own text is content,
|
|
921
|
+
// and is seeded as the content it is.
|
|
922
|
+
const own = path.join(root, 'custom-template-own-guide');
|
|
923
|
+
await fs.cp(TEMPLATE_DIR, own, { recursive: true });
|
|
924
|
+
await fs.writeFile(path.join(own, 'AGENTS.md'), '# Acme conventions\n', 'utf8');
|
|
925
|
+
const ownDest = path.join(root, 'seed-dest-own-guide');
|
|
926
|
+
await fs.mkdir(ownDest, { recursive: true });
|
|
927
|
+
await buildSeedTree(new NodeFs(), own, [], ['admin@example.com'], kbContext)(ownDest);
|
|
928
|
+
expect(norm(await fs.readFile(path.join(ownDest, 'AGENTS.md'), 'utf8'))).toBe('# Acme conventions\n');
|
|
1204
929
|
});
|
|
1205
930
|
|
|
1206
931
|
it('names a template that is not there — a missing directory is a broken build, not an empty seed', async () => {
|
|
@@ -1974,26 +1699,3 @@ describe('GroupsToPluginsStep — migration edge cases', () => {
|
|
|
1974
1699
|
});
|
|
1975
1700
|
});
|
|
1976
1701
|
});
|
|
1977
|
-
|
|
1978
|
-
/**
|
|
1979
|
-
* The guide's rule in `.bevelignore` is a gitignore PATTERN, and the name rules
|
|
1980
|
-
* admit characters gitignore reads as syntax: written bare, `#Guide.md` is a
|
|
1981
|
-
* comment and hides nothing. Rendered escaped, the rule names exactly the file.
|
|
1982
|
-
*/
|
|
1983
|
-
describe('TemplateFilesStep: a guide named with gitignore syntax', () => {
|
|
1984
|
-
it('escapes the name in the ignore rule it writes, and keeps it escaped on the next boot', async () => {
|
|
1985
|
-
kbContext.applyLayout({ ...DEFAULT_KB_LAYOUT, agentsFile: '#Guide[1].md' });
|
|
1986
|
-
await seedUpstream({ 'marker.txt': 'seeded' });
|
|
1987
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
1988
|
-
const dir = await checkout(DEFAULT_BRANCH);
|
|
1989
|
-
const ignore = norm(await fs.readFile(path.join(dir, '.bevelignore'), 'utf8')).split('\n').map((l) => l.trim());
|
|
1990
|
-
const escaped = String.raw`\#Guide\[1\].md`;
|
|
1991
|
-
expect(ignore).toContain(escaped);
|
|
1992
|
-
expect(ignore).not.toContain('#Guide[1].md');
|
|
1993
|
-
expect(await exists(dir, '#Guide[1].md')).toBe(true);
|
|
1994
|
-
// A second boot sees the escaped rule as present and adds no second line.
|
|
1995
|
-
await makeRunner([new TemplateFilesStep(new NodeFs(), kbContext)]).runAll();
|
|
1996
|
-
const again = norm(await fs.readFile(path.join(await checkout(DEFAULT_BRANCH), '.bevelignore'), 'utf8'));
|
|
1997
|
-
expect(again.split('\n').filter((l) => l.trim() === escaped)).toHaveLength(1);
|
|
1998
|
-
});
|
|
1999
|
-
});
|