@bevel-software/platform-shared 0.15.1 → 0.20.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.
Files changed (73) hide show
  1. package/dist/auth/types.d.ts +12 -0
  2. package/dist/auth/types.d.ts.map +1 -1
  3. package/dist/git/pr.types.d.ts +75 -11
  4. package/dist/git/pr.types.d.ts.map +1 -1
  5. package/dist/git/types.d.ts +28 -1
  6. package/dist/git/types.d.ts.map +1 -1
  7. package/dist/index.d.ts +6 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +6 -0
  10. package/dist/index.js.map +1 -1
  11. package/dist/workflow/events.d.ts +32 -4
  12. package/dist/workflow/events.d.ts.map +1 -1
  13. package/dist/workflow/events.js.map +1 -1
  14. package/dist/workflow/interface.d.ts +103 -4
  15. package/dist/workflow/interface.d.ts.map +1 -1
  16. package/dist/workflow/types.d.ts +49 -0
  17. package/dist/workflow/types.d.ts.map +1 -1
  18. package/dist/workspace/access-verbs.d.ts +83 -0
  19. package/dist/workspace/access-verbs.d.ts.map +1 -0
  20. package/dist/workspace/access-verbs.js +110 -0
  21. package/dist/workspace/access-verbs.js.map +1 -0
  22. package/dist/workspace/agent-preamble.d.ts +33 -0
  23. package/dist/workspace/agent-preamble.d.ts.map +1 -0
  24. package/dist/workspace/agent-preamble.js +45 -0
  25. package/dist/workspace/agent-preamble.js.map +1 -0
  26. package/dist/workspace/entry-exists.d.ts +27 -0
  27. package/dist/workspace/entry-exists.d.ts.map +1 -0
  28. package/dist/workspace/entry-exists.js +33 -0
  29. package/dist/workspace/entry-exists.js.map +1 -0
  30. package/dist/workspace/filename.d.ts +15 -0
  31. package/dist/workspace/filename.d.ts.map +1 -1
  32. package/dist/workspace/filename.js +30 -0
  33. package/dist/workspace/filename.js.map +1 -1
  34. package/dist/workspace/frontmatter-carriers.d.ts +44 -0
  35. package/dist/workspace/frontmatter-carriers.d.ts.map +1 -0
  36. package/dist/workspace/frontmatter-carriers.js +52 -0
  37. package/dist/workspace/frontmatter-carriers.js.map +1 -0
  38. package/dist/workspace/frontmatter.d.ts +23 -4
  39. package/dist/workspace/frontmatter.d.ts.map +1 -1
  40. package/dist/workspace/frontmatter.js +59 -9
  41. package/dist/workspace/frontmatter.js.map +1 -1
  42. package/dist/workspace/kb-layout.d.ts +226 -19
  43. package/dist/workspace/kb-layout.d.ts.map +1 -1
  44. package/dist/workspace/kb-layout.js +353 -23
  45. package/dist/workspace/kb-layout.js.map +1 -1
  46. package/dist/workspace/placeholder.d.ts +21 -0
  47. package/dist/workspace/placeholder.d.ts.map +1 -0
  48. package/dist/workspace/placeholder.js +28 -0
  49. package/dist/workspace/placeholder.js.map +1 -0
  50. package/dist/workspace/platform-files.d.ts +105 -0
  51. package/dist/workspace/platform-files.d.ts.map +1 -0
  52. package/dist/workspace/platform-files.js +147 -0
  53. package/dist/workspace/platform-files.js.map +1 -0
  54. package/dist/workspace/types.d.ts +8 -0
  55. package/dist/workspace/types.d.ts.map +1 -1
  56. package/package.json +2 -2
  57. package/src/auth/types.ts +12 -0
  58. package/src/git/pr.types.ts +77 -11
  59. package/src/git/types.ts +35 -1
  60. package/src/index.ts +6 -0
  61. package/src/workflow/events.ts +33 -3
  62. package/src/workflow/interface.ts +127 -4
  63. package/src/workflow/types.ts +43 -0
  64. package/src/workspace/access-verbs.ts +124 -0
  65. package/src/workspace/agent-preamble.ts +47 -0
  66. package/src/workspace/entry-exists.ts +36 -0
  67. package/src/workspace/filename.ts +31 -0
  68. package/src/workspace/frontmatter-carriers.ts +57 -0
  69. package/src/workspace/frontmatter.ts +57 -8
  70. package/src/workspace/kb-layout.ts +388 -25
  71. package/src/workspace/placeholder.ts +29 -0
  72. package/src/workspace/platform-files.ts +188 -0
  73. package/src/workspace/types.ts +8 -0
@@ -1,4 +1,5 @@
1
1
  import { branchSegment } from '../git/branchAuthor.js';
2
+ import { PREAMBLE_FILE } from './agent-preamble.js';
2
3
  import { validateFilename } from './filename.js';
3
4
  /**
4
5
  * Top-level layout of the KB repo (inside the `KB_DIR_NAME` clone).
@@ -98,12 +99,186 @@ export let SKILLS_DIR = 'Skills';
98
99
  * manifest's `name` field.
99
100
  */
100
101
  export let PLUGINS_DIR = 'Plugins';
102
+ /**
103
+ * The file name of the platform's MANAGED agent guide at the repository root —
104
+ * the document every connected agent is told to read first, written and
105
+ * refreshed from the packaged template on every start.
106
+ *
107
+ * Configurable for one reason: `AGENTS.md` is the name coding agents look for
108
+ * by convention, so a customer arriving with a repository of their own very
109
+ * often already HAS one, and under the default name the platform would
110
+ * overwrite it on the first boot and on every boot after. Renaming the managed
111
+ * guide (`HEXIS.md`, say) hands that name back: `AGENTS.md` becomes ordinary
112
+ * content the platform never writes, never refreshes and never hides, and the
113
+ * customer's file is the one that points at ours (see
114
+ * {@link agentsFilePointerSentence}).
115
+ *
116
+ * A live binding like the three roots above — read it inside a function body,
117
+ * never capture it at module scope.
118
+ */
119
+ export let AGENTS_FILE = 'AGENTS.md';
120
+ /**
121
+ * The name the managed guide had when it was the only name it could have.
122
+ *
123
+ * Referenced ONLY by the code that has to tell OUR file from THEIRS — the
124
+ * boot-time removal of a platform-written `AGENTS.md`, the ignore rule that
125
+ * stops hiding it, the instruction telling an agent to read the customer's
126
+ * file too. In the spirit of {@link LEGACY_GROUPS_DIR}: a second live spelling
127
+ * of the CURRENT name is how two layouts start being supported by accident, so
128
+ * this one is a constant and means exactly one thing.
129
+ */
130
+ export const LEGACY_AGENTS_FILE = 'AGENTS.md';
131
+ /**
132
+ * The platform files whose names are FIXED — the ones no deployment renames.
133
+ * The guide is the fourth platform file and is deliberately absent here: its
134
+ * name is {@link AGENTS_FILE}, and `platform-files.ts` composes the two into
135
+ * the set every gate reads.
136
+ *
137
+ * It lives in this module rather than beside that composition because the
138
+ * LAYOUT has to validate against it (a guide may not be called `access.md`),
139
+ * and `platform-files.ts` already reads this module — the other direction
140
+ * would be a cycle.
141
+ */
142
+ export const FIXED_PLATFORM_FILE_NAMES = Object.freeze([
143
+ 'access.md',
144
+ 'roles.yaml',
145
+ '.bevelignore',
146
+ ]);
101
147
  /** The layout a deployment gets when it names nothing. */
102
148
  export const DEFAULT_KB_LAYOUT = Object.freeze({
103
149
  knowledgeBaseDir: 'KnowledgeBase',
104
150
  skillsDir: 'Skills',
105
151
  pluginsDir: 'Plugins',
152
+ agentsFile: 'AGENTS.md',
106
153
  });
154
+ /** The guide's name in a layout, with the default standing in for an absent one. */
155
+ export function agentsFileOf(layout) {
156
+ return (layout.agentsFile ?? '').trim() || DEFAULT_KB_LAYOUT.agentsFile;
157
+ }
158
+ /**
159
+ * `name` as one literal gitignore pattern. The guide's name is the
160
+ * operator's, and the name rules admit characters gitignore reads as syntax:
161
+ * a leading `#` is a comment and a leading `!` a negation (the rule would
162
+ * silently hide nothing), `[`, `]`, `*` and `?` are globs, and a backslash is
163
+ * the escape itself. Each is escaped so the pattern names exactly the file.
164
+ */
165
+ export function gitignoreLiteral(name) {
166
+ return name.replace(/[[\]*?\\]/g, '\\$&').replace(/^([#!])/, '\\$1');
167
+ }
168
+ /**
169
+ * The ONE sentence the platform offers to keep in a customer's own
170
+ * `AGENTS.md`, pointing at the managed guide beside it.
171
+ *
172
+ * Defined here, once, because two surfaces must produce the identical text:
173
+ * the deployment-settings field previews it before the admin consents, and the
174
+ * startup step appends it. A sentence written twice is a sentence that drifts,
175
+ * and a drifted one appends a SECOND copy to every customer file on the boot
176
+ * after the drift — which is the one thing this whole feature exists to stop.
177
+ *
178
+ * A guide name is a FILE NAME, not an identifier: everything `validateFilename`
179
+ * admits can appear in it — spaces, brackets, parentheses, `#`, `%` — and each
180
+ * of those means something in an inline link. So the link is BUILT rather than
181
+ * interpolated: the label backslash-escaped ({@link markdownLinkLabel}), the
182
+ * destination percent-encoded ({@link agentsFileLinkPath}). A name that only
183
+ * parenthesised would break the destination; `#` would turn the rest of the
184
+ * name into a URL fragment, and the link would point at the customer's own
185
+ * file.
186
+ *
187
+ * Neither spelling need match the name as it is on disk, so nothing may ask
188
+ * whether this sentence is present by searching for the RAW name — see
189
+ * {@link mentionsAgentsFile}, which is how the startup step asks.
190
+ */
191
+ export function agentsFilePointerSentence(agentsFile = AGENTS_FILE) {
192
+ return `Read [${markdownLinkLabel(agentsFile)}](${agentsFileLinkPath(agentsFile)})${POINTER_SENTENCE_TAIL}`;
193
+ }
194
+ /**
195
+ * Everything of the sentence that does NOT depend on the guide's name — split
196
+ * out so the one definition above can also be RECOGNISED, by the pattern below,
197
+ * when the name it was written with is no longer the name in effect.
198
+ */
199
+ const POINTER_SENTENCE_TAIL = " before working in this knowledge base — it is the platform's guide to its layout, files and rules.";
200
+ /**
201
+ * A pointer sentence the platform wrote, naming ANY guide.
202
+ *
203
+ * The label admits a backslash escape (`\[`, `\]`) because that is what
204
+ * {@link markdownLinkLabel} puts there; the destination cannot contain a `)`
205
+ * or a newline because {@link agentsFileLinkPath} encodes both. Anchored at
206
+ * both ends by text the platform fixed, so the shape is the provenance —
207
+ * a customer would have to reproduce our sentence word for word to be taken
208
+ * for us, which is the same bar the managed-guide header sets.
209
+ */
210
+ const POINTER_SENTENCE_PATTERN = new RegExp(`Read \\[(?:[^\\]\\n\\\\]|\\\\[\\s\\S])*\\]\\(\\.\\/[^)\\n]*\\)${escapeRegExp(POINTER_SENTENCE_TAIL)}`, 'g');
211
+ /** `text` as a literal inside a regular expression. */
212
+ function escapeRegExp(text) {
213
+ return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
214
+ }
215
+ /**
216
+ * `text` with every pointer sentence THE PLATFORM WROTE aimed at `agentsFile`
217
+ * — or null when it holds none of ours.
218
+ *
219
+ * This is what a SECOND rename needs. The guide's name is a setting an admin
220
+ * may change again: a knowledge base whose `AGENTS.md` was given a sentence
221
+ * pointing at `HEXIS.md` and is then renamed to `GUIDE.md` must have that
222
+ * sentence aimed at the new file, not a second one appended beneath a first
223
+ * that now points at nothing. Asking only whether the NEW name is mentioned
224
+ * cannot see that — the old sentence does not mention it.
225
+ *
226
+ * Returning the text unchanged (rather than null) when the sentence is already
227
+ * right is deliberate: "ours and correct" and "not ours at all" are different
228
+ * answers, and only the caller knows that the second one means "consider
229
+ * appending".
230
+ */
231
+ export function retargetAgentsFilePointer(text, agentsFile = AGENTS_FILE) {
232
+ let found = false;
233
+ const wanted = agentsFilePointerSentence(agentsFile);
234
+ const updated = text.replace(POINTER_SENTENCE_PATTERN, () => {
235
+ found = true;
236
+ return wanted;
237
+ });
238
+ return found ? updated : null;
239
+ }
240
+ /**
241
+ * `text` as an inline link's LABEL: the characters that would end the label or
242
+ * start emphasis or code inside it, backslash-escaped. Nothing else is touched
243
+ * — a filename is read by people, and `AGENTS\.md` helps no one.
244
+ */
245
+ function markdownLinkLabel(text) {
246
+ return text.replace(/[\\[\]`*_]/g, (c) => `\\${c}`);
247
+ }
248
+ /**
249
+ * The guide as an inline link's DESTINATION: `./` and the name, percent-encoded.
250
+ *
251
+ * `encodeURI` does most of it (a space, a bracket, and `%` itself, so an
252
+ * already-encoded-looking name is not decoded by a reader). Three more are
253
+ * encoded by hand because `encodeURI` leaves them and each one ENDS the path
254
+ * early: `#` opens a fragment, and `(`/`)` close the destination in
255
+ * CommonMark's bare form. `?` and the rest of the URL-significant set are
256
+ * already refused by {@link validateFilename}.
257
+ *
258
+ * An ordinary name has none of these and comes out exactly as it went in.
259
+ */
260
+ function agentsFileLinkPath(agentsFile) {
261
+ return `./${encodeURI(agentsFile).replace(/[#()]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`)}`;
262
+ }
263
+ /**
264
+ * Whether `text` already points at the guide — the ONE question the startup
265
+ * step asks before appending {@link agentsFilePointerSentence} to a customer's
266
+ * own `AGENTS.md`.
267
+ *
268
+ * The plain name is the answer that matters: a mention in the customer's own
269
+ * words, a heading, a link they wrote, all count, and the platform stays out
270
+ * of a file it does not own. The other two spellings are the platform's OWN,
271
+ * and they are here for idempotence: the sentence writes the name escaped in
272
+ * the label and encoded in the destination, so on a punctuated name the file
273
+ * the last boot wrote need not contain the raw name at all. Asking only for
274
+ * that one would append a second copy on the next boot, and a third on the
275
+ * one after — the exact failure this feature exists to prevent.
276
+ */
277
+ export function mentionsAgentsFile(text, agentsFile = AGENTS_FILE) {
278
+ return (text.includes(agentsFile) ||
279
+ text.includes(markdownLinkLabel(agentsFile)) ||
280
+ text.includes(agentsFileLinkPath(agentsFile)));
281
+ }
107
282
  /**
108
283
  * What is wrong with one root name, or null. A root is joined onto the repo
109
284
  * root and onto `<dir>/.gitkeep`, so a separator or `..` would write outside
@@ -127,12 +302,76 @@ export function validateKbRootName(name) {
127
302
  return 'The name can\'t start with a dot.';
128
303
  return null;
129
304
  }
305
+ /**
306
+ * What is wrong with the agent guide's file name, or null.
307
+ *
308
+ * The rules, and what each one is for:
309
+ *
310
+ * - ONE FILE NAME. The name is joined onto the repository root and read from
311
+ * there and nowhere else, so a separator would name a file the platform
312
+ * would write but never read back.
313
+ * - A MARKDOWN NAME. The guide is a markdown document that people open in the
314
+ * app and agents read as text; `.md` is also what the per-file access rules
315
+ * apply to, so a guide under any other extension would take its folder's
316
+ * rules and stop being readable by everyone.
317
+ * - NOT `CLAUDE.md`. That is the guide's own pre-rename name; knowledge bases
318
+ * seeded before the rename still carry one, and it stays legacy content
319
+ * rather than becoming a second managed file.
320
+ * - NOT ANOTHER PLATFORM FILE. Two platform roles on one path means whichever
321
+ * writer runs last wins, silently.
322
+ * - NOT A ROOT FOLDER'S NAME, compared case-insensitively like the roots are
323
+ * to each other: the workspaces live on case-insensitive filesystems, where
324
+ * a file `Docs.md` and a folder `docs.md` are one entry.
325
+ *
326
+ * `roots` is the layout the name is judged against — the names this save would
327
+ * put in effect, not necessarily the ones running now.
328
+ */
329
+ export function validateAgentsFileName(name, roots = currentKbLayout()) {
330
+ const v = name.trim();
331
+ if (!v)
332
+ return 'A file name is required.';
333
+ if (v.includes('/') || v.includes('\\'))
334
+ return 'Use a single file name — no folders.';
335
+ // The ONE rule for what a path component may be called, as everywhere else.
336
+ const asName = validateFilename(v);
337
+ if (asName)
338
+ return asName;
339
+ const lower = v.toLowerCase();
340
+ // The taken names come FIRST, so a name that is wrong for a specific reason
341
+ // is refused with that reason rather than with whichever general rule it
342
+ // happens to break as well (`roles.yaml` is not merely 'not markdown').
343
+ if (lower === 'claude.md') {
344
+ return 'CLAUDE.md is the guide\'s pre-rename name and stays reserved for it.';
345
+ }
346
+ for (const reserved of [...FIXED_PLATFORM_FILE_NAMES, PREAMBLE_FILE]) {
347
+ if (lower === reserved.toLowerCase())
348
+ return `${reserved} is a platform file name.`;
349
+ }
350
+ // A dot-prefixed name is skipped by every scanner that treats dot-entries as
351
+ // bookkeeping — including the one that would show the guide in the tree.
352
+ if (v.startsWith('.'))
353
+ return 'The name can\'t start with a dot.';
354
+ if (!v.endsWith('.md'))
355
+ return 'The name must end in .md.';
356
+ for (const [label, dir] of [
357
+ ['knowledge', roots.knowledgeBaseDir],
358
+ ['skills', roots.skillsDir],
359
+ ['plugins', roots.pluginsDir],
360
+ ]) {
361
+ if (lower === (dir ?? '').trim().toLowerCase()) {
362
+ return `That is already the ${label} folder's name.`;
363
+ }
364
+ }
365
+ return null;
366
+ }
130
367
  /**
131
368
  * What is wrong with a layout, or null — the same rule {@link configureKbLayout}
132
369
  * enforces, without applying anything. Separate so the setup screen can judge a
133
- * proposed layout before it is saved. The three names must differ, compared
134
- * case-insensitively: the workspaces live on case-insensitive filesystems too,
135
- * where `Skills` and `skills` are one folder.
370
+ * proposed layout before it is saved. The three folder names must differ,
371
+ * compared case-insensitively: the workspaces live on case-insensitive
372
+ * filesystems too, where `Skills` and `skills` are one folder. The guide's
373
+ * file name is judged against all three by the same rule (see
374
+ * {@link validateAgentsFileName}), which makes the four names distinct.
136
375
  */
137
376
  export function validateKbLayout(layout) {
138
377
  for (const [label, value] of [
@@ -154,8 +393,37 @@ export function validateKbLayout(layout) {
154
393
  const clash = names.find((n) => fixed.includes(n));
155
394
  if (clash)
156
395
  return `"${clash}" is a reserved folder name (${[DATA_DIR, AGENTS_DIR, PIPELINES_DIR].join(', ')}).`;
396
+ // Judged against the roots THIS layout declares, not the ones in effect: a
397
+ // save that renames the plugins folder and the guide together must be read
398
+ // as the pair it is.
399
+ const guide = validateAgentsFileName(agentsFileOf(layout), layout);
400
+ if (guide)
401
+ return `The agent guide's file name: ${guide}`;
157
402
  return null;
158
403
  }
404
+ /** Everything that has asked to hear when the layout is applied. */
405
+ const layoutListeners = new Set();
406
+ /**
407
+ * Be told when {@link configureKbLayout} runs — for the few things that cannot
408
+ * read a live binding at the moment they are used.
409
+ *
410
+ * Almost nothing needs this: the roots and the guide's name are `let` bindings
411
+ * read inside function bodies, so code that follows the rule follows the
412
+ * layout for free. The exception is a value BUILT ONCE and handed to something
413
+ * that keeps it — the tool catalog's descriptions, which are validated into
414
+ * frozen-ish defs at registration and then served to agents from a map. Boot
415
+ * applies the layout before they are built, but the save that completes
416
+ * FIRST-RUN SETUP applies it afterwards (see `setup.routes.ts`, which must, so
417
+ * the KB phase that runs in the same request scaffolds the names the admin
418
+ * just chose) — and without this the catalog would go on naming `AGENTS.md`
419
+ * until someone restarted the server.
420
+ *
421
+ * Listeners run in registration order, after the bindings are updated and only
422
+ * when the layout was accepted.
423
+ */
424
+ export function onKbLayoutApplied(listener) {
425
+ layoutListeners.add(listener);
426
+ }
159
427
  /**
160
428
  * Apply the layout. Called once during boot on each side; throws on an invalid
161
429
  * one so a bad deployment setting fails beside the rest of the wiring rather
@@ -168,18 +436,41 @@ export function configureKbLayout(layout) {
168
436
  KNOWLEDGE_BASE_DIR = layout.knowledgeBaseDir.trim();
169
437
  SKILLS_DIR = layout.skillsDir.trim();
170
438
  PLUGINS_DIR = layout.pluginsDir.trim();
439
+ AGENTS_FILE = agentsFileOf(layout);
440
+ for (const listener of layoutListeners)
441
+ listener();
171
442
  }
172
443
  /** The layout currently in effect. */
173
444
  export function currentKbLayout() {
174
- return { knowledgeBaseDir: KNOWLEDGE_BASE_DIR, skillsDir: SKILLS_DIR, pluginsDir: PLUGINS_DIR };
445
+ return {
446
+ knowledgeBaseDir: KNOWLEDGE_BASE_DIR,
447
+ skillsDir: SKILLS_DIR,
448
+ pluginsDir: PLUGINS_DIR,
449
+ agentsFile: AGENTS_FILE,
450
+ };
451
+ }
452
+ /**
453
+ * Whether a layout — the one in effect, unless one is given — is the default
454
+ * one. The setup-completing save applies the stored names while this holds,
455
+ * the same "only from none to some" rule the branch model follows — and also
456
+ * on a retry after its own failed initialization run, when the process holds
457
+ * names setup applied but the app never opened (see `setup.routes.ts`). A
458
+ * layout the process booted with is never replaced here.
459
+ */
460
+ export function isDefaultKbLayout(layout = currentKbLayout()) {
461
+ return (layout.knowledgeBaseDir === DEFAULT_KB_LAYOUT.knowledgeBaseDir &&
462
+ layout.skillsDir === DEFAULT_KB_LAYOUT.skillsDir &&
463
+ layout.pluginsDir === DEFAULT_KB_LAYOUT.pluginsDir &&
464
+ agentsFileOf(layout) === DEFAULT_KB_LAYOUT.agentsFile);
175
465
  }
176
466
  /**
177
467
  * Render the layout placeholders a managed template carries —
178
- * `{{knowledgeBaseDir}}`, `{{skillsDir}}`, `{{pluginsDir}}` — with the
179
- * names in effect. The packaged `AGENTS.md` and `.bevelignore` are written
180
- * this way so a deployment that renamed its roots hands the agent a guide
181
- * that names the folders it will actually find. Text without placeholders
182
- * passes through unchanged.
468
+ * `{{knowledgeBaseDir}}`, `{{skillsDir}}`, `{{pluginsDir}}`, `{{agentsFile}}`
469
+ * — with the names in effect. The packaged guide and `.bevelignore` are
470
+ * written this way so a deployment that renamed its roots hands the agent a
471
+ * guide that names the folders it will actually find, and a deployment that
472
+ * renamed the guide gets a guide naming the file it lives in. Text without
473
+ * placeholders passes through unchanged.
183
474
  */
184
475
  export function renderKbLayoutPlaceholders(text, layout = currentKbLayout()) {
185
476
  // Replacer FUNCTIONS: a string replacement would interpret `$&`, `$$` and
@@ -187,7 +478,8 @@ export function renderKbLayoutPlaceholders(text, layout = currentKbLayout()) {
187
478
  return text
188
479
  .replaceAll('{{knowledgeBaseDir}}', () => layout.knowledgeBaseDir)
189
480
  .replaceAll('{{skillsDir}}', () => layout.skillsDir)
190
- .replaceAll('{{pluginsDir}}', () => layout.pluginsDir);
481
+ .replaceAll('{{pluginsDir}}', () => layout.pluginsDir)
482
+ .replaceAll('{{agentsFile}}', () => agentsFileOf(layout));
191
483
  }
192
484
  /**
193
485
  * The pre-rename name of {@link PLUGINS_DIR}. Referenced ONLY by the migration
@@ -362,27 +654,53 @@ export function pluginIdentityOf(manifest, folderName) {
362
654
  /**
363
655
  * What a person sees the plugin called: the manifest's `displayName` (the
364
656
  * vendor field Claude Code shows in its picker; any casing, spaces allowed),
365
- * else the folder name — which is what every plugin made before this field
366
- * existed was called, so nothing renames itself on upgrade.
657
+ * else the manifest's `name`.
658
+ *
659
+ * THE MANIFEST IS THE ONLY SOURCE — there is no folder argument, on purpose.
660
+ * The folder's spelling used to stand in here, which made where a plugin
661
+ * happens to live a hidden input to what everyone sees it called: the API
662
+ * always answered with a display name while the file sometimes omitted the
663
+ * field, and moving or re-casing a folder silently renamed the plugin. Every
664
+ * write path now persists the field (see {@link renderPluginManifest} and
665
+ * the rename service), and one startup step backfilled the folder's spelling
666
+ * into the manifests written before that, so nothing renames itself.
667
+ *
668
+ * Empty only for a manifest that names nothing at all — the shape discovery
669
+ * already warns about and stands the folder in as the IDENTITY for; its
670
+ * display name then follows that identity, never the folder directly.
367
671
  */
368
- export function pluginDisplayNameOf(manifest, folderName) {
672
+ export function pluginDisplayNameOf(manifest) {
369
673
  const declared = manifest?.displayName;
370
- return typeof declared === 'string' && declared.trim() ? declared.trim() : folderName;
674
+ if (typeof declared === 'string' && declared.trim())
675
+ return declared.trim();
676
+ const name = manifest?.name;
677
+ return typeof name === 'string' ? name.trim() : '';
371
678
  }
372
679
  /**
373
680
  * A minimal, valid `plugin.json` for a plugin folder: the identifier the
374
- * folder name folds into, and — when the folder is spelled differently — the
375
- * folder's spelling as `displayName`, so a client's picker shows "Sales
376
- * Team" for `sales-team`. Nothing else: `version`, `license` and the rest
377
- * are metadata about a DISTRIBUTED package, and inventing values for a
378
- * folder someone just made in the app would be asserting things nobody said.
681
+ * folder name folds into, and the name a person sees it by — `displayName`,
682
+ * ALWAYS written, so a client's picker shows "Sales Team" for `sales-team`
683
+ * and every reader has the one field to read.
684
+ *
685
+ * ONE argument, deliberately: `folderName` is the folder's own leaf, and on
686
+ * the creation path that leaf IS the name its creator typed, trimmed — the
687
+ * dialog's route and the `create_plugin` tool make the folder out of the
688
+ * typed name and hand the same string to both. A second `displayName`
689
+ * parameter would be a way for the two to disagree that no caller needs.
690
+ * The field is written even when it equals the identifier: a manifest that
691
+ * omits it when the two agree is a manifest whose readers need a second rule.
692
+ *
693
+ * Nothing else: `version`, `license` and the rest are metadata about a
694
+ * DISTRIBUTED package, and inventing values for a folder someone just made
695
+ * in the app would be asserting things nobody said.
379
696
  */
380
697
  export function renderPluginManifest(folderName) {
381
698
  const name = pluginManifestName(folderName);
382
- const manifest = { $schema: PLUGIN_MANIFEST_SCHEMA, name };
383
- if (folderName !== name)
384
- manifest.displayName = folderName;
385
- return `${JSON.stringify(manifest, null, 2)}\n`;
699
+ // Always a non-blank, trimmed answer: the spelling asked for, else the
700
+ // identifier — a `displayName` of spaces would be a field present and
701
+ // saying nothing, which is the shape every reader here exists to avoid.
702
+ const shown = folderName.trim() || name;
703
+ return `${JSON.stringify({ $schema: PLUGIN_MANIFEST_SCHEMA, name, displayName: shown }, null, 2)}\n`;
386
704
  }
387
705
  /**
388
706
  * The reserved name prefix marking a personal folder under `Plugins/` —
@@ -470,6 +788,18 @@ export function ontologyRoots() {
470
788
  export function reservedRootDirNames() {
471
789
  return new Set([KNOWLEDGE_BASE_DIR, SKILLS_DIR, PLUGINS_DIR, DATA_DIR, AGENTS_DIR, PIPELINES_DIR]);
472
790
  }
791
+ /**
792
+ * The roots anyone may start a new folder in — knowledge, skills and plugins
793
+ * — whatever the root's own `access.md` grants them. Everywhere else a change
794
+ * needs read access to where it lands (the "read before write" rule); a new
795
+ * folder directly under one of these three is the one place that rule does
796
+ * not apply, because the new folder carries its creator's own grant. A
797
+ * function, like {@link reservedRootDirNames}, because the names are
798
+ * configurable.
799
+ */
800
+ export function creatableRootDirNames() {
801
+ return new Set([KNOWLEDGE_BASE_DIR, SKILLS_DIR, PLUGINS_DIR]);
802
+ }
473
803
  /** The `Knowledge/` marker subfolder of an ontology (holds the graph nodes). */
474
804
  export const KNOWLEDGE_DIR = 'Knowledge';
475
805
  /** The `NodeTypes/` marker subfolder of an ontology (holds the type definitions). */
@@ -1 +1 @@
1
- {"version":3,"file":"kb-layout.js","sourceRoot":"","sources":["../../src/workspace/kb-layout.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"kb-layout.js","sourceRoot":"","sources":["../../src/workspace/kb-layout.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The empty-folder placeholder. Git tracks files, not folders, so a folder
3
+ * with nothing in it is kept alive by one empty file. That file is how a
4
+ * folder survives a clone and nothing more: it is never content, so every
5
+ * listing, tree, stat, search and change-request view hides it.
6
+ *
7
+ * The rule it serves: a folder exists until someone deletes it explicitly.
8
+ * Creating one (UI, `mkdir`, a nested write) and emptying one (deleting or
9
+ * moving out its last file) both leave a folder that lists as a folder; only
10
+ * an explicit folder delete removes it, placeholder included.
11
+ */
12
+ export declare const FOLDER_PLACEHOLDER = ".gitkeep";
13
+ /**
14
+ * True when `nameOrPath` (a bare name or any `/`-separated path, trailing
15
+ * slashes allowed as the other basename helpers here allow them) is the
16
+ * placeholder.
17
+ */
18
+ export declare function isFolderPlaceholder(nameOrPath: string): boolean;
19
+ /** The placeholder's path inside `dir` (`''` for a root-level placeholder). */
20
+ export declare function folderPlaceholderPath(dir: string): string;
21
+ //# sourceMappingURL=placeholder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placeholder.d.ts","sourceRoot":"","sources":["../../src/workspace/placeholder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,aAAa,CAAC;AAE7C;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAI/D;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGzD"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The empty-folder placeholder. Git tracks files, not folders, so a folder
3
+ * with nothing in it is kept alive by one empty file. That file is how a
4
+ * folder survives a clone and nothing more: it is never content, so every
5
+ * listing, tree, stat, search and change-request view hides it.
6
+ *
7
+ * The rule it serves: a folder exists until someone deletes it explicitly.
8
+ * Creating one (UI, `mkdir`, a nested write) and emptying one (deleting or
9
+ * moving out its last file) both leave a folder that lists as a folder; only
10
+ * an explicit folder delete removes it, placeholder included.
11
+ */
12
+ export const FOLDER_PLACEHOLDER = '.gitkeep';
13
+ /**
14
+ * True when `nameOrPath` (a bare name or any `/`-separated path, trailing
15
+ * slashes allowed as the other basename helpers here allow them) is the
16
+ * placeholder.
17
+ */
18
+ export function isFolderPlaceholder(nameOrPath) {
19
+ const trimmed = nameOrPath.replace(/\/+$/, '');
20
+ const slash = trimmed.lastIndexOf('/');
21
+ return (slash === -1 ? trimmed : trimmed.slice(slash + 1)) === FOLDER_PLACEHOLDER;
22
+ }
23
+ /** The placeholder's path inside `dir` (`''` for a root-level placeholder). */
24
+ export function folderPlaceholderPath(dir) {
25
+ const trimmed = dir.replace(/\/+$/, '');
26
+ return trimmed ? `${trimmed}/${FOLDER_PLACEHOLDER}` : FOLDER_PLACEHOLDER;
27
+ }
28
+ //# sourceMappingURL=placeholder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placeholder.js","sourceRoot":"","sources":["../../src/workspace/placeholder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,CAAC;AAE7C;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACpD,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACvC,OAAO,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,kBAAkB,CAAC;AACpF,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACxC,OAAO,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,kBAAkB,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC;AAC3E,CAAC"}