@bevel-software/platform-core-backend 0.25.0 → 0.26.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 +234 -0
- package/agent-guide/conventions.md +27 -0
- package/agent-guide/directory-structure.md +145 -0
- package/agent-guide/finding-things.md +7 -0
- package/agent-guide/introduction.md +27 -0
- package/agent-guide/skills.md +47 -0
- package/agent-guide/tool-manuals.md +217 -0
- package/agent-guide/where-a-new-file-goes.md +36 -0
- package/dist/assets.d.ts +7 -0
- package/dist/assets.d.ts.map +1 -1
- package/dist/assets.js +9 -0
- package/dist/assets.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.map +1 -1
- package/dist/core/create-core-server.js +13 -2
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +9 -0
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +14 -4
- package/dist/core/create-core-services.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 +9 -0
- package/dist/modules/access/access-control.interface.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +1 -0
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +16 -0
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/agent-guide/agent-guide.d.ts +139 -0
- package/dist/modules/agent-guide/agent-guide.d.ts.map +1 -0
- package/dist/modules/agent-guide/agent-guide.js +191 -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 +9 -6
- package/dist/modules/agent-instructions/compose.d.ts.map +1 -1
- package/dist/modules/agent-instructions/compose.js +9 -6
- 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 +32 -85
- package/dist/modules/agent-instructions/shared-file-rules.js.map +1 -1
- package/dist/modules/mcp/mcp.service.d.ts +29 -2
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.service.js +113 -16
- package/dist/modules/mcp/mcp.service.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/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 +0 -7
- package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
- package/dist/modules/settings/deployment-settings.service.js +14 -53
- package/dist/modules/settings/deployment-settings.service.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 +58 -16
- package/dist/modules/skills/skills.tools.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 +66 -36
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
- package/dist/modules/tool-registry/description-length.d.ts +14 -14
- package/dist/modules/tool-registry/description-length.d.ts.map +1 -1
- package/dist/modules/tool-registry/description-length.js +24 -26
- package/dist/modules/tool-registry/description-length.js.map +1 -1
- package/dist/modules/tool-registry/guide-first.d.ts +23 -0
- package/dist/modules/tool-registry/guide-first.d.ts.map +1 -0
- package/dist/modules/tool-registry/guide-first.js +32 -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 +73 -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 +582 -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.map +1 -1
- package/dist/modules/workflow/agent-tools/workflow.tools.js +9 -0
- package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
- package/dist/modules/workflow/git/git.service.d.ts +210 -13
- package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
- package/dist/modules/workflow/git/git.service.js +456 -91
- 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/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/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 +178 -12
- package/dist/modules/workflow/review-workflow/review-workflow.service.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 +4 -0
- package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
- package/dist/modules/workflow/workflow.service.js +3 -0
- package/dist/modules/workflow/workflow.service.js.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts +70 -0
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
- package/dist/modules/workspace/startup/kb-startup-runner.js +213 -20
- package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
- package/dist/modules/workspace/startup/steps/seed-tree.js +22 -27
- 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.tools.d.ts +10 -1
- package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.tools.js +211 -18
- package/dist/modules/workspace/workspace.tools.js.map +1 -1
- package/dist/shared/domain-errors.d.ts +11 -0
- package/dist/shared/domain-errors.d.ts.map +1 -1
- package/dist/shared/domain-errors.js +14 -0
- package/dist/shared/domain-errors.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/kb-template/.bevelignore +0 -5
- package/package.json +4 -3
- package/src/__tests__/kb-layout-config.test.ts +10 -100
- package/src/__tests__/packaged-assets-ship.test.ts +54 -0
- package/src/assets.ts +10 -0
- package/src/core/core-ports.ts +11 -0
- package/src/core/create-core-server.ts +13 -2
- package/src/core/create-core-services.ts +28 -4
- 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-personal-plugin.test.ts +1 -18
- package/src/modules/access/access-control.interface.ts +15 -0
- package/src/modules/access/access-control.service.ts +21 -0
- package/src/modules/agent-guide/__tests__/agent-guide.test.ts +328 -0
- package/src/modules/agent-guide/__tests__/agent-guide.tools.test.ts +189 -0
- package/src/modules/agent-guide/agent-guide.tools.ts +122 -0
- package/src/modules/agent-guide/agent-guide.ts +291 -0
- package/src/modules/agent-guide/index.ts +21 -0
- package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +28 -121
- package/src/modules/agent-instructions/agent-instructions.routes.ts +3 -2
- package/src/modules/agent-instructions/compose.ts +9 -6
- package/src/modules/agent-instructions/index.ts +0 -3
- package/src/modules/agent-instructions/shared-file-rules.ts +31 -93
- package/src/modules/mcp/__tests__/fake-downstream-mcp-server.ts +14 -3
- package/src/modules/mcp/__tests__/mcp.e2e.test.ts +250 -0
- package/src/modules/mcp/__tests__/mcp.service.test.ts +31 -23
- package/src/modules/mcp/__tests__/tool-schema-guard.test.ts +266 -0
- package/src/modules/mcp/mcp.service.ts +137 -19
- package/src/modules/mcp/tool-schema-guard.ts +196 -0
- package/src/modules/plugins/__tests__/plugins.tools.test.ts +154 -4
- package/src/modules/plugins/plugins.tools.ts +75 -15
- package/src/modules/settings/__tests__/deployment-settings.service.test.ts +26 -55
- package/src/modules/settings/deployment-settings.service.ts +13 -54
- package/src/modules/settings/setup.routes.ts +3 -6
- package/src/modules/skills/__tests__/skills.tools.description.test.ts +91 -0
- package/src/modules/skills/skills.tools.ts +62 -16
- 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 +74 -36
- package/src/modules/tool-registry/__tests__/own-tool-schemas.test.ts +160 -0
- package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +61 -59
- package/src/modules/tool-registry/description-length.ts +24 -26
- package/src/modules/tool-registry/guide-first.ts +34 -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/agent-tools/__tests__/change-request-read-shape.test.ts +705 -0
- package/src/modules/workflow/agent-tools/__tests__/change-request-read.tools.test.ts +1518 -0
- package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +23 -2
- package/src/modules/workflow/agent-tools/change-request-read-shape.ts +712 -0
- package/src/modules/workflow/agent-tools/change-request-read.tools.ts +724 -0
- package/src/modules/workflow/agent-tools/change-request-summary.ts +5 -1
- package/src/modules/workflow/agent-tools/workflow.tools.ts +8 -0
- 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.mergeChangeRequest.test.ts +334 -0
- 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 +537 -94
- package/src/modules/workflow/git/merge-commit.ts +88 -0
- package/src/modules/workflow/git/pull-request.service.ts +380 -54
- 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 +189 -11
- package/src/modules/workflow/workflow.routes.ts +7 -2
- package/src/modules/workflow/workflow.service.ts +7 -0
- package/src/modules/workspace/__tests__/escape-sequences.routes.test.ts +4 -3
- package/src/modules/workspace/__tests__/workspace.routes.move-platform-files.test.ts +21 -10
- package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +33 -55
- package/src/modules/workspace/__tests__/workspace.tools.test.ts +255 -22
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +231 -1
- package/src/modules/workspace/startup/kb-startup-runner.ts +216 -19
- package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +191 -489
- package/src/modules/workspace/startup/steps/seed-tree.ts +21 -27
- 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.tools.ts +226 -16
- package/src/shared/domain-errors.ts +15 -0
- package/src/shared/hidden-tools.ts +45 -0
- package/kb-template/AGENTS.md +0 -730
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
## Access control
|
|
2
|
+
|
|
3
|
+
Access to any path — reading it as much as writing it — is governed by
|
|
4
|
+
`roles.yaml` (who has which role), `groups.yaml` (who is in which group) and
|
|
5
|
+
`access.md` files (who may do what, where).
|
|
6
|
+
|
|
7
|
+
- **Roles** in `roles.yaml` map a role name to a list of members: emails, and
|
|
8
|
+
`group:<Name>` entries that give the role to a whole group (see *Giving a
|
|
9
|
+
role to a group* below). Role names are
|
|
10
|
+
case- and whitespace-insensitive (`Admin` = `admin` = `ADMIN`; `Product Team`
|
|
11
|
+
= `product team`). The reserved names `deny` and `everyone` cannot be used, and neither can
|
|
12
|
+
names starting with `role/` or `plugin/` — those spellings are tokens in
|
|
13
|
+
access entries (below). One exception to the file's authority: the
|
|
14
|
+
**deployment admin** — the address the server configuration sets as
|
|
15
|
+
`ADMIN_EMAIL` — is **always an Admin**, whether or not `roles.yaml` lists
|
|
16
|
+
it, and taking it out of the file does not change that. It is the rescue
|
|
17
|
+
path for a `roles.yaml` that has lost its last Admin. The App roles page
|
|
18
|
+
shows that account under Admin as a fixed member that cannot be added or
|
|
19
|
+
removed there; every other Admin membership is exactly what the file says,
|
|
20
|
+
and removing one takes effect on that person's next request.
|
|
21
|
+
- **Plugins are grantable principals.** `plugin/<name>/read`,
|
|
22
|
+
`plugin/<name>/write` and `plugin/<name>/owner` in any access file mean
|
|
23
|
+
everyone who currently holds that verb on the plugin whose manifest `name`
|
|
24
|
+
is `<name>`, derived live from the plugin's own `access.md`. Any spelling
|
|
25
|
+
folds to the identifier (`plugin/GTM/read` and `plugin/gtm/read` are one
|
|
26
|
+
principal). This is how a shared skill is made visible to a plugin's
|
|
27
|
+
members: `read: plugin/gtm/read` on the skill's folder.
|
|
28
|
+
Adding or removing someone on the plugin changes what they can read
|
|
29
|
+
everywhere the token is granted, with no copying.
|
|
30
|
+
- **Access rules** live in `access.md` files, which carry **two blocks with two
|
|
31
|
+
scopes**: the BODY (below the closing `---`) declares the rules for the
|
|
32
|
+
folder the file sits in, and the FRONTMATTER declares who may read and
|
|
33
|
+
write that `access.md` itself. Each block names verbs (`read`, `write`,
|
|
34
|
+
`download`, `owner`) whose entries are either grants (a bare principal) or
|
|
35
|
+
denials (the lowercase word `deny`, a space, then the principal).
|
|
36
|
+
Capitalised forms like `Deny` are *not* triggers; they are treated as part
|
|
37
|
+
of a name.
|
|
38
|
+
- **Principals** are a role name from `roles.yaml`, a group name from
|
|
39
|
+
`groups.yaml`, a person as `Name <email>`, a plugin token (above), or
|
|
40
|
+
**`everyone`** — the built-in org-wide principal: every signed-in person and
|
|
41
|
+
their agents. `read: everyone` in a folder's BODY opens that folder to the
|
|
42
|
+
whole organisation; it is how an organisation-wide skill or plugin is
|
|
43
|
+
shared. The same line in a file's FRONTMATTER only makes that one file
|
|
44
|
+
visible — a plugin's `access.md` ships with `read: everyone` in its
|
|
45
|
+
frontmatter so the plugin can be found and joined, and that admits nobody
|
|
46
|
+
to the plugin itself. A person's personal plugin
|
|
47
|
+
(`{{pluginsDir}}/personal-<id>/`) grants its owner access and denies
|
|
48
|
+
`everyone` outright, so opening a parent folder never opens it.
|
|
49
|
+
When a group and a role share a name, the bare name means the GROUP;
|
|
50
|
+
`role/<Name>` (for example `deny role/Reviewer`) always means the role.
|
|
51
|
+
- **Keep an `access.md` body pure YAML**, with any explanation in `#` comments.
|
|
52
|
+
A body that does not parse as YAML naming at least one verb is read in the
|
|
53
|
+
older format instead, where the FRONTMATTER carried the folder's rules — so a
|
|
54
|
+
stray line of prose silently changes which block governs the folder.
|
|
55
|
+
- **The verbs nest.** `owner` sits over `write` and `download`; `write` and
|
|
56
|
+
`download` each sit over `read` — anyone who may edit a node, or save a copy
|
|
57
|
+
of it, may also view it. `write` and `download` say nothing about each other.
|
|
58
|
+
The nesting is GRANT-ONLY: a grant of a higher verb confers the lower ones,
|
|
59
|
+
but `deny write` or `deny download` says nothing about `read` and never
|
|
60
|
+
strips a separate read grant. So `download: Ana <ana@x.io>` alone lets Ana
|
|
61
|
+
open the node as well as download it, and a `deny download` beside an
|
|
62
|
+
inherited read leaves her able to open it but not save it.
|
|
63
|
+
- **You can only change what you can read.** Nothing is created, changed,
|
|
64
|
+
moved into or removed from a place the caller cannot read — on every
|
|
65
|
+
branch, drafts included, whatever `write:` rules say. A write tool refused
|
|
66
|
+
for this says so (`write-denied`, naming the unreadable folder), and
|
|
67
|
+
proposing is not offered either: a proposal into a folder its author cannot
|
|
68
|
+
see would vanish from them the moment it landed. Two exceptions. A NEW
|
|
69
|
+
FOLDER directly under `{{knowledgeBaseDir}}/`, `{{skillsDir}}/` or
|
|
70
|
+
`{{pluginsDir}}/`: anyone may start one, whatever the root's rules grant
|
|
71
|
+
them, and the new folder's `access.md` is seeded with the creator's own
|
|
72
|
+
`read:` grant so what they put there is visible to them (a loose FILE
|
|
73
|
+
directly at a root has no folder to carry that grant and is not excepted).
|
|
74
|
+
And an Admin — or the deployment owner — may change the files directly in
|
|
75
|
+
the repository root (`roles.yaml`, `access.md`, `groups.yaml`, …) even when
|
|
76
|
+
the root grants read to nobody: the same rescue the write
|
|
77
|
+
floor gives them, so a tree whose root rules lock everyone out stays
|
|
78
|
+
repairable from inside the app. That rescue stops at the root; a subfolder
|
|
79
|
+
an admin cannot read is closed to them like to anyone else.
|
|
80
|
+
- **Resolution** walks repo root → file directory, accumulating per-principal
|
|
81
|
+
state. User-level entries trump role-level entries. A role denial removes
|
|
82
|
+
only that role's contribution; it does not undo grants from other roles.
|
|
83
|
+
- **`roles.yaml` is editable only by Admin** — hard-coded in the resolver,
|
|
84
|
+
never overridable by an `access.md`.
|
|
85
|
+
- **`access.md` files are picked up at any depth**, so a folder can tighten or
|
|
86
|
+
widen what it inherited from its parent.
|
|
87
|
+
- **Per-file rules exist for Markdown notes and `.tool` definitions.** A note
|
|
88
|
+
(`.md`, lowercase) may name verbs in its own frontmatter, and those rules
|
|
89
|
+
apply to that one note; a `.tool` definition keeps the access verbs in its
|
|
90
|
+
own YAML the same way; a distribution may register further file kinds
|
|
91
|
+
that carry their own rules. Any other file (a PDF, a presentation, a
|
|
92
|
+
spreadsheet, an image, any binary, a `.markdown` or `.MD` file, or binary
|
|
93
|
+
content saved as `.md`) takes its folder's rules: sharing it on its own is refused with
|
|
94
|
+
`folder-governs-access`, naming the folder. To change who
|
|
95
|
+
can open such a file, change its folder's `access.md`, or move the file to a
|
|
96
|
+
folder whose rules fit.
|
|
97
|
+
|
|
98
|
+
Rules are enforced at runtime; a malformed `roles.yaml` or `access.md` surfaces
|
|
99
|
+
when access is resolved.
|
|
100
|
+
|
|
101
|
+
### Roles are pre-set — a "new role" is usually a group
|
|
102
|
+
|
|
103
|
+
**What a role is.** A role in `roles.yaml` is an app role: a capability the
|
|
104
|
+
platform defines and acts on (`Admin` is one), listed with the people who hold
|
|
105
|
+
it. The set of roles is pre-set by the platform. A role is not a way to name a
|
|
106
|
+
team.
|
|
107
|
+
|
|
108
|
+
**Agents never create roles.** Add people to a role that already exists, or
|
|
109
|
+
remove them, and nothing more: never add a role name to `roles.yaml`, and never
|
|
110
|
+
rename one — a rename is a delete plus a create. Such a write is refused with a
|
|
111
|
+
422 that names the role and says: app roles are pre-set — add people to
|
|
112
|
+
existing roles, and use a GROUP for a task- or team-scoped set of people.
|
|
113
|
+
Relay that refusal to your user as it stands; do not look for another way to
|
|
114
|
+
write the file.
|
|
115
|
+
|
|
116
|
+
**Is it really a group?** When someone asks for a "new role", it almost always
|
|
117
|
+
is. It is a group when any of these hold:
|
|
118
|
+
|
|
119
|
+
- the name says who the people are — a team, a project, a customer, a
|
|
120
|
+
committee — rather than a capability the platform already has;
|
|
121
|
+
- it would change or disappear when the project ends or the team reshuffles;
|
|
122
|
+
- its purpose is to give those people access to some folders or files.
|
|
123
|
+
|
|
124
|
+
A request that matches a role that already exists is membership, not a new
|
|
125
|
+
role.
|
|
126
|
+
|
|
127
|
+
**What to do instead.**
|
|
128
|
+
|
|
129
|
+
1. If an existing role already carries the capability, add the people to it.
|
|
130
|
+
2. Otherwise make it a group: add or extend the group in `groups.yaml` (or
|
|
131
|
+
point your user at the app's Groups page), then grant the group in the
|
|
132
|
+
`access.md` of the folders it should reach.
|
|
133
|
+
3. If your user still needs a role the platform does not have, that is not an
|
|
134
|
+
edit you can make — say so, and leave the decision to an admin.
|
|
135
|
+
|
|
136
|
+
### Giving a role to a group
|
|
137
|
+
|
|
138
|
+
A role's member list takes a group as well as individual emails. Write the
|
|
139
|
+
entry as `- group:<Name>`, where `<Name>` is a group in the active group
|
|
140
|
+
source — `synced-groups.yaml` when the deployment syncs groups from an
|
|
141
|
+
identity provider, `groups.yaml` otherwise. Here a `Reviewer` role the
|
|
142
|
+
deployment already has goes to a whole group:
|
|
143
|
+
|
|
144
|
+
```yaml
|
|
145
|
+
roles:
|
|
146
|
+
Admin:
|
|
147
|
+
- dana@example.com
|
|
148
|
+
Reviewer:
|
|
149
|
+
- lee@example.com
|
|
150
|
+
- group:Platform Team
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
- **Matching.** The name is matched case- and whitespace-insensitively against
|
|
154
|
+
the active group source, like role names: `group:platform team` and
|
|
155
|
+
`group:Platform Team` are the same entry as `group:Platform Team`.
|
|
156
|
+
- **Unknown groups are refused.** An entry naming a group the active source
|
|
157
|
+
does not declare is a validation error: the write is refused with a 422
|
|
158
|
+
that names the entry and its role (`'- group:Platfrom Team' under role
|
|
159
|
+
'Reviewer'`), and nothing is saved. Create the group first, or fix the name.
|
|
160
|
+
- **A group under `Admin` makes every member a full admin** — including anyone
|
|
161
|
+
added to the group later, and including the right to edit `roles.yaml`
|
|
162
|
+
itself. Only make that edit when your user is an Admin and explicitly asks
|
|
163
|
+
for exactly that, and say so in the commit summary; for anyone else, tell
|
|
164
|
+
them what it would mean and who can do it (below). `Admin` must also always keep at least one
|
|
165
|
+
direct email member; a group entry alone is not enough, so a broken
|
|
166
|
+
directory can never leave the deployment without an admin.
|
|
167
|
+
- **With direct emails.** Group entries and emails add up: the role's members
|
|
168
|
+
are everyone listed by email plus everyone currently in each listed group.
|
|
169
|
+
A person in both is simply a member; adding or removing someone from the
|
|
170
|
+
group changes the role with no edit to `roles.yaml`.
|
|
171
|
+
- **With denials.** Group members hold the role's grants exactly as if they
|
|
172
|
+
were listed by email. A denial of the role in an `access.md`
|
|
173
|
+
(`deny role/Reviewer`) therefore removes the role's contribution for
|
|
174
|
+
everyone in the group, as it does for the emails. Write the `role/` form:
|
|
175
|
+
a bare `deny Reviewer` would deny a group named `Reviewer` instead, if one
|
|
176
|
+
exists. The nearest `access.md` that says
|
|
177
|
+
anything about the person decides: a person granted by name
|
|
178
|
+
(`Name <email>`) in the SAME `access.md` as the denial keeps that access,
|
|
179
|
+
because within one file a person's own entry beats a role entry. A grant by
|
|
180
|
+
name in a folder further up does not survive a role denial closer to the
|
|
181
|
+
file.
|
|
182
|
+
|
|
183
|
+
**Only an Admin changes `roles.yaml`, and only on the default branch.** A
|
|
184
|
+
change request cannot carry the edit: when a request is merged, `roles.yaml`
|
|
185
|
+
is restored to what the default branch has, so a role edit drafted on a
|
|
186
|
+
branch is dropped at the merge without a word. Do not propose one. If your
|
|
187
|
+
user is an Admin, `edit_file` the file on the default branch directly — for
|
|
188
|
+
example, to give the Reviewer role to a group, add the entry under the
|
|
189
|
+
existing role:
|
|
190
|
+
|
|
191
|
+
```yaml
|
|
192
|
+
roles:
|
|
193
|
+
Admin:
|
|
194
|
+
- dana@example.com
|
|
195
|
+
Reviewer:
|
|
196
|
+
- lee@example.com
|
|
197
|
+
- group:Platform Team # added
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
If your user is not an Admin, tell them who is (the `Admin` entries in
|
|
201
|
+
`roles.yaml`) and that the change is made in the app's Roles page or by an
|
|
202
|
+
admin editing the file; do not open a change request for it.
|
|
203
|
+
|
|
204
|
+
### Direct writes vs change requests
|
|
205
|
+
|
|
206
|
+
File-level write access decides how a change lands on the default branch:
|
|
207
|
+
|
|
208
|
+
- A user — or an agent acting as that user — whose access resolution grants
|
|
209
|
+
**write or owner on every file the change touches** may commit **directly**
|
|
210
|
+
to the default branch.
|
|
211
|
+
- Without that access, the change goes through a **branch + change request**,
|
|
212
|
+
approved by an owner / write-access holder of the affected files — every
|
|
213
|
+
affected file with an eligible approver needs that approval, whatever its
|
|
214
|
+
type (notes, binary files, files without an extension).
|
|
215
|
+
- Agents carry exactly their user's access, never more. Before writing to the
|
|
216
|
+
default branch, **ask the user** whether to write directly or go through the
|
|
217
|
+
review flow — and prefer a change request when in doubt, when the change is
|
|
218
|
+
large, or when it touches content the user does not own.
|
|
219
|
+
|
|
220
|
+
### An agent proposes and syncs; a person merges
|
|
221
|
+
|
|
222
|
+
- **Propose** with `open_change_request`, then give the user the request's
|
|
223
|
+
`url`. Reviewing, approving and merging a change request happen in the app,
|
|
224
|
+
by a person — no agent tool approves a file, bypasses approval, or merges a
|
|
225
|
+
request. `merge_change_request` no longer exists.
|
|
226
|
+
- **Sync** a draft with `merge_branch`, `source` = the branch the request
|
|
227
|
+
targets, `target` = the draft. This is allowed while the draft's request is
|
|
228
|
+
open, and is how you bring it up to date or surface conflicts to resolve on
|
|
229
|
+
the draft.
|
|
230
|
+
- `merge_branch` refuses to merge a draft into the branch its open change
|
|
231
|
+
request targets — it names the request; ask the user to review it in the
|
|
232
|
+
app. Into a protected branch it merges only what you could commit there
|
|
233
|
+
directly, under the rule above — and never a change to `roles.yaml`, whoever
|
|
234
|
+
you are: roles are changed in the app, not merged in from a draft.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
## Conventions
|
|
2
|
+
|
|
3
|
+
These are conventions, not validations — nothing rejects a file for breaking
|
|
4
|
+
them. They exist because a knowledge base people can navigate beats one that is
|
|
5
|
+
merely correct.
|
|
6
|
+
|
|
7
|
+
1. **Descriptive file names.** `Weekly-Sync-2026-03-14.md` beats `notes3.md`.
|
|
8
|
+
Avoid spaces; they survive git fine but make links noisier to read.
|
|
9
|
+
|
|
10
|
+
2. **Markdown links between documents.** Use
|
|
11
|
+
`[Page Name](relative/path/to/Page.md)`, relative to the LINKING file's
|
|
12
|
+
directory rather than the repo root, so links resolve both in the app and on
|
|
13
|
+
the git host.
|
|
14
|
+
|
|
15
|
+
3. **Absolute dates.** `YYYY-MM-DD`, never "last Tuesday" — a saved file
|
|
16
|
+
outlives the moment it was written.
|
|
17
|
+
|
|
18
|
+
4. **Search before creating.** If a document on the subject exists, extend it
|
|
19
|
+
rather than starting a rival.
|
|
20
|
+
|
|
21
|
+
5. **Preserve what is there.** Append or edit sections; do not overwrite a file
|
|
22
|
+
wholesale unless asked to.
|
|
23
|
+
|
|
24
|
+
6. **Say where it came from.** When a claim rests on a specific source — a
|
|
25
|
+
person, a ticket, a document, a URL — name it inline near the claim, with
|
|
26
|
+
the date it was true. The next reader's first question is "says who, and is
|
|
27
|
+
it still true?".
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
## Directory Structure
|
|
2
|
+
|
|
3
|
+
```text
|
|
4
|
+
{{kbDirName}}/
|
|
5
|
+
├── {{knowledgeBaseDir}}/ ← the knowledge itself; organise it however suits you
|
|
6
|
+
├── {{skillsDir}}/ ← shared skills, organised by who owns them
|
|
7
|
+
├── {{pluginsDir}}/ ← one folder per plugin: its tools, and links to skills
|
|
8
|
+
├── roles.yaml ← identity → role mapping (Admin-only edits)
|
|
9
|
+
└── access.md ← repo-root access-control rules
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
(The three root names above are this deployment's own — a deployment may
|
|
13
|
+
rename them in its setup screen, and this guide is rendered with the names in
|
|
14
|
+
effect each time it is composed.)
|
|
15
|
+
|
|
16
|
+
Tool paths are workspace-relative, and the workspace root holds this
|
|
17
|
+
repository as the `{{kbDirName}}/` folder (this deployment's own name for its
|
|
18
|
+
checkout): a file in it is `{{kbDirName}}/{{knowledgeBaseDir}}/Foo.md`. Write
|
|
19
|
+
the prefix where you can — it is the path every tool reports back — but a
|
|
20
|
+
path without it is PLACED under `{{kbDirName}}/` rather than refused, so
|
|
21
|
+
`{{knowledgeBaseDir}}/Foo.md` names that same file, and so does the
|
|
22
|
+
root-anchored `/{{kbDirName}}/{{knowledgeBaseDir}}/Foo.md` the app's Copy
|
|
23
|
+
path gives you. Nothing you send can land beside the repository,
|
|
24
|
+
where git would never see it. `.` or `..` segments, backslashes and every other
|
|
25
|
+
absolute path are refused.
|
|
26
|
+
|
|
27
|
+
Only those three folders are structural. `{{skillsDir}}/` holds shared skills at any
|
|
28
|
+
depth — the folder that holds a `SKILL.md` is the skill, and everything above
|
|
29
|
+
it is ownership (`{{skillsDir}}/<scope>/…/<skill>/SKILL.md`, with an `access.md` in
|
|
30
|
+
any scope folder that needs its own rules). `{{pluginsDir}}/` has a layout the
|
|
31
|
+
platform reads:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
{{pluginsDir}}/<Plugin>/plugin.json the manifest (Agent Plugins) — what makes the folder a plugin; its `name` is the plugin's identity
|
|
35
|
+
{{pluginsDir}}/<Plugin>/skills/<skill>/SKILL.md a skill that lives inside the plugin
|
|
36
|
+
{{pluginsDir}}/<Plugin>/mcp.json MCP servers (authoritative)
|
|
37
|
+
{{pluginsDir}}/<Plugin>/software.bevel.hexis/tools/ `.tool` manuals
|
|
38
|
+
{{pluginsDir}}/<Plugin>/access.md who can read/write the plugin
|
|
39
|
+
{{pluginsDir}}/personal-<user-id>/… one per person: private
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**The manifest's `name` is the plugin.** It is a kebab-case identifier
|
|
43
|
+
(`sales-team`), and it is what every grant spells (`plugin/sales-team/read`),
|
|
44
|
+
what the URLs and the catalog key on, and what the compiled marketplace
|
|
45
|
+
publishes the plugin as. `displayName` is what people see it called ("Sales
|
|
46
|
+
Team"); absent, the folder name is shown. Rename a plugin from its page in the
|
|
47
|
+
app: an identifier change rewrites every grant that names it, in one commit —
|
|
48
|
+
editing `name` by hand leaves those grants pointing at a plugin that no longer
|
|
49
|
+
exists.
|
|
50
|
+
|
|
51
|
+
**A plugin LINKS shared skills rather than containing them.** Its manifest
|
|
52
|
+
lists skill paths under `extensions["software.bevel.hexis"].skills` — each
|
|
53
|
+
entry is one skill folder or a folder of skills under `{{skillsDir}}/`:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{ "extensions": { "software.bevel.hexis": { "skills": ["{{skillsDir}}/Engineering/deploy", "{{skillsDir}}/Sales"] } } }
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
One skill, stored once, can be listed by many plugins. A plugin's effective
|
|
60
|
+
skills are the ones inside its folder plus everything its links resolve to.
|
|
61
|
+
Do not edit that list by hand: linking is done from the plugin's page in the
|
|
62
|
+
app, because it is two edits at once — the manifest entry AND a grant on the
|
|
63
|
+
skill (see *Access control* below). A manifest entry without the grant lists
|
|
64
|
+
a skill the plugin's members cannot read; the app shows such a link as
|
|
65
|
+
needing setup and offers Repair.
|
|
66
|
+
|
|
67
|
+
**Ownership decides who may read a skill, never the plugin.** A shared
|
|
68
|
+
skill's readability comes from the `access.md` rules on its own folder and
|
|
69
|
+
the scopes above it. A plugin that links a skill someone cannot read simply
|
|
70
|
+
does not show it to them.
|
|
71
|
+
|
|
72
|
+
**Symlinks are not supported anywhere under `{{pluginsDir}}/`.** Access control
|
|
73
|
+
resolves rules by path, and a symlink is a second path to the same content —
|
|
74
|
+
the two can disagree about who may read what. The platform never creates
|
|
75
|
+
them and ignores any it finds (they can only arrive via a direct git push).
|
|
76
|
+
|
|
77
|
+
**A plugin follows the [Agent Plugins](https://agent-plugins.org) specification**
|
|
78
|
+
(v1.0.0), so another conformant client can load one: it reads `plugin.json`, the
|
|
79
|
+
skills under `skills/`, and the servers in `mcp.json`, and ignores everything
|
|
80
|
+
else. Two things here are ours and sit outside that portable core. `access.md`
|
|
81
|
+
stays at the plugin root because access resolution walks root → file, so the
|
|
82
|
+
same rules one level down would govern only that subtree. And `http`/`inline` `.tool`
|
|
83
|
+
manuals live under the reverse-DNS `software.bevel.hexis/` namespace, because
|
|
84
|
+
the specification describes MCP servers only and has no way to express them.
|
|
85
|
+
|
|
86
|
+
**MCP servers belong in `mcp.json` — do not write `.tool` files for them.**
|
|
87
|
+
Each `mcpServers` key is the server's identity: it is the namespace its vault
|
|
88
|
+
secrets bind to (`<name>_<VAR>`), so renaming a key unbinds every configured
|
|
89
|
+
secret and sign-in. The portable entry carries only where the server is
|
|
90
|
+
(`type`, `url`, literal headers). Anything this platform needs beyond that —
|
|
91
|
+
auth headers carrying `${VAR}` vault references, `variables` declarations,
|
|
92
|
+
a `description`, or `local: true` for a server only reachable from a user's
|
|
93
|
+
machine — goes in `plugin.json` under
|
|
94
|
+
`extensions["software.bevel.hexis"].mcpServers[<name>]`, which other clients
|
|
95
|
+
ignore by design. A `type: "stdio"` entry (a command run on the user's own
|
|
96
|
+
machine) is always local: the hosted endpoint never spawns it; the local
|
|
97
|
+
`hexis-mcp` server fetches the plugin's files to a local directory and runs it
|
|
98
|
+
per the Agent Plugins runtime contract (`PLUGIN_ROOT`/`PLUGIN_DATA`, `./`
|
|
99
|
+
commands contained to the plugin). A stdio server SHOULD exit when its stdin
|
|
100
|
+
reaches EOF — the client also terminates it on shutdown, but a server that
|
|
101
|
+
ignores EOF outlives crashes as an orphan whose working directory blocks the
|
|
102
|
+
plugin folder from ever refreshing.
|
|
103
|
+
|
|
104
|
+
**Secrets are never written into a plugin's portable files.** The specification
|
|
105
|
+
defines no portable credential mechanism on purpose: authorization and
|
|
106
|
+
credential storage are the client's business, header and `env` values are
|
|
107
|
+
"visible package data", and a client must not expand anything except
|
|
108
|
+
`${PLUGIN_ROOT}` and `${PLUGIN_DATA}`. So the Secrets Vault IS this platform's
|
|
109
|
+
answer to that — and `mcp.json` carries only where a server is, never a
|
|
110
|
+
`${VAR}` reference to how to authenticate with it. Those live in `plugin.json`
|
|
111
|
+
under `extensions["software.bevel.hexis"].mcpServers[<name>]`, which is ours
|
|
112
|
+
to interpret and which other clients ignore by design.
|
|
113
|
+
|
|
114
|
+
**Plugin folders are made through the platform, not by writing files.** A
|
|
115
|
+
folder is a plugin exactly when it carries a `plugin.json` (the platform
|
|
116
|
+
writes one into every legacy plugin folder at startup), and it is LISTED only
|
|
117
|
+
when it also carries an `access.md` — a bare directory under `{{pluginsDir}}/` is
|
|
118
|
+
neither. Plugins may sit at any depth under `{{pluginsDir}}/`; a folder that holds
|
|
119
|
+
plugins deeper down is a grouping folder, not a plugin. A new plugin needs an
|
|
120
|
+
`access.md` naming who runs it, and the write gate refuses a plain write
|
|
121
|
+
into an unused name there — so do not try to create a plugin by writing a
|
|
122
|
+
skill into `{{pluginsDir}}/<new-name>/…`; it will be denied. Use the two tools
|
|
123
|
+
instead:
|
|
124
|
+
|
|
125
|
+
- `my_plugin` — your user's personal plugin, holding their own skills and
|
|
126
|
+
tools, created on first use: `{{pluginsDir}}/personal-<id>/`. Readable only
|
|
127
|
+
by its owner — not even admins — and never listed as a plugin. Their personal
|
|
128
|
+
skills go under its `skills/`, each in its own folder with a `SKILL.md`;
|
|
129
|
+
write there with the file tools. A note or any other document goes under
|
|
130
|
+
`{{knowledgeBaseDir}}/` instead — see **Where a new file goes**.
|
|
131
|
+
- `create_plugin` — a shared plugin, named, optionally inside a grouping
|
|
132
|
+
folder under `{{pluginsDir}}/` (`parent`). The caller runs it; others join
|
|
133
|
+
through the app or are granted in its `access.md`.
|
|
134
|
+
|
|
135
|
+
The app's **New plugin** button and `POST /api/plugins` do the same. A skill
|
|
136
|
+
moves from a personal plugin into a shared plugin by moving its folder.
|
|
137
|
+
|
|
138
|
+
Everything under `{{knowledgeBaseDir}}/` is yours to arrange. Subfolders, naming,
|
|
139
|
+
whether a topic is one file or twenty — all of it is a judgement call about
|
|
140
|
+
what the next reader needs, not a rule the platform enforces.
|
|
141
|
+
|
|
142
|
+
A deployment may reserve further root folders of its own — `Data/`, `Agents/`
|
|
143
|
+
and `Pipelines/` scaffold an agentic execution layer in some installations.
|
|
144
|
+
They are not part of this template and are not created here; where they exist,
|
|
145
|
+
each carries its own `README.md` describing what belongs in it.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
## Finding things
|
|
2
|
+
|
|
3
|
+
- `grep` for keywords across `{{knowledgeBaseDir}}/`.
|
|
4
|
+
- Follow markdown links: when you read `[Some Page](relative/path/Some Page.md)`,
|
|
5
|
+
that path is relative to the file you are reading.
|
|
6
|
+
- `list_files` to see the shape of a folder before assuming where something
|
|
7
|
+
lives.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Knowledge base
|
|
2
|
+
|
|
3
|
+
This is a git-backed knowledge base. You are the primary agent responsible for
|
|
4
|
+
maintaining it.
|
|
5
|
+
|
|
6
|
+
> **This guide is served by the platform.** It is not a file in the
|
|
7
|
+
> repository: `get_agent_guide` returns it, whole or one section at a time,
|
|
8
|
+
> and so does `read_file` on `AGENTS.md` at the repository root — after the
|
|
9
|
+
> knowledge base's own `AGENTS.md`, when it has one; `grep` searches it there
|
|
10
|
+
> too. An `AGENTS.md` you find on disk is the organisation's own conventions
|
|
11
|
+
> file, written by its people; follow it, and never write this text into it.
|
|
12
|
+
> Deployment- or team-specific conventions belong there, or in files of your
|
|
13
|
+
> own anywhere under `{{knowledgeBaseDir}}/`, linked from wherever they are
|
|
14
|
+
> needed.
|
|
15
|
+
|
|
16
|
+
**Read `mcp-description.md` at the repository root first.** It says what this
|
|
17
|
+
knowledge base contains and when to consult it. Agents connected over MCP
|
|
18
|
+
receive the default branch's copy inline at the start of every session; a
|
|
19
|
+
clone reads the copy on its own branch.
|
|
20
|
+
|
|
21
|
+
**There is no required format for knowledge.** Write markdown the way the
|
|
22
|
+
subject wants to be written: prose, tables, checklists, diagrams, whatever
|
|
23
|
+
serves the reader. Nothing here parses your files into a schema or rejects a
|
|
24
|
+
document for having the wrong shape. If a deployment layers a structured
|
|
25
|
+
knowledge graph on top, it brings its own conventions, in sections of this
|
|
26
|
+
guide of its own; what follows describes the platform underneath, which stores
|
|
27
|
+
files and controls who may change them.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
## Skills (`{{skillsDir}}/<scope>/…/<skill>/SKILL.md`, or `{{pluginsDir}}/<Plugin>/skills/<skill>/SKILL.md`)
|
|
2
|
+
|
|
3
|
+
A skill is a folder holding a `SKILL.md` and whatever files it needs. Shared
|
|
4
|
+
skills live under `{{skillsDir}}/`, organised by ownership; a skill that belongs to
|
|
5
|
+
exactly one plugin may live inside that plugin's `skills/` folder instead.
|
|
6
|
+
Skill names are unique across the whole catalog, whichever home they have.
|
|
7
|
+
The frontmatter names it, declares which tools it may use, and may carry a
|
|
8
|
+
version:
|
|
9
|
+
|
|
10
|
+
```yaml
|
|
11
|
+
---
|
|
12
|
+
name: weekly-newsletter
|
|
13
|
+
description: Drafts the Friday newsletter for review.
|
|
14
|
+
allowed-tools: [slack_post_message]
|
|
15
|
+
metadata:
|
|
16
|
+
version: "1.4.0"
|
|
17
|
+
---
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The body is the instructions, in plain markdown. `allowed-tools` entries are
|
|
21
|
+
tool names from the `.tool` manuals and MCP servers of the plugins that hold
|
|
22
|
+
the skill, and the agent client's own tools beside them (`Bash`, `Read`,
|
|
23
|
+
`Bash(git:*)` and the like, which the platform leaves to the client).
|
|
24
|
+
`metadata.version` is semver; `list_skills` reports it, and
|
|
25
|
+
`get_skill` with a `version` loads the skill as it was when it last declared
|
|
26
|
+
that version (omit `version` for the latest). Any other `metadata` keys are
|
|
27
|
+
the author's own notes — the catalog carries the file as it is and acts on
|
|
28
|
+
none of them.
|
|
29
|
+
|
|
30
|
+
A `SKILL.md` committed on the default branch is listed and loadable from the
|
|
31
|
+
very next `list_skills` or `get_skill`, on the connection you already have:
|
|
32
|
+
the released catalog is cached briefly and dropped the moment the default
|
|
33
|
+
branch changes, so the next request reads the workspace again.
|
|
34
|
+
See *A released tool or skill is live within ten seconds* under **Tool
|
|
35
|
+
Manuals** for the one caveat (an MCP client that caches the prompt list it
|
|
36
|
+
was given at connect time must re-list — the prompt-list-changed notification
|
|
37
|
+
that tells it to arrives with the connection's next catalog check, which is
|
|
38
|
+
within ten seconds on a connection in use and at its next use on an idle
|
|
39
|
+
one).
|
|
40
|
+
|
|
41
|
+
**How skills reach agents.** Through the MCP server (`list_skills`,
|
|
42
|
+
`get_skill`), or as native plugins: every user can clone a git remote from
|
|
43
|
+
the app's external-agent page that holds a plugin marketplace compiled from
|
|
44
|
+
exactly the skills they may read — one plugin per plugin here, a
|
|
45
|
+
`skills-and-knowledge` plugin for the rest plus this knowledge base's MCP
|
|
46
|
+
server, and `hexis-all`, one plugin holding every skill they may read and
|
|
47
|
+
the MCP server, for a single install.
|