@bevel-software/platform-shared 0.23.0 → 0.24.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.
@@ -22,6 +22,21 @@ export declare function platformFileNames(layout: KbLayout): readonly string[];
22
22
  * {@link platformFileNames}, which knows what this deployment called its guide.
23
23
  */
24
24
  export declare const PLATFORM_FILE_NAMES: readonly string[];
25
+ /**
26
+ * The platform files split by the DEPTH they count at, which is the half of
27
+ * {@link isPlatformFile} that a name alone does not tell you: `access.md` and
28
+ * `.bevelignore` are platform files in any folder, `roles.yaml` and the agent
29
+ * guide only in the repository root.
30
+ *
31
+ * Exported because the agent-facing rules state that split in prose, and a
32
+ * prose list written by hand drifts from the predicate that actually refuses
33
+ * the move — an agent then declines a nested `roles.yaml` it may rename, or
34
+ * trusts that a nested `access.md` is ordinary content.
35
+ */
36
+ export declare function platformFilesByDepth(layout: KbLayout): {
37
+ anyDepth: readonly string[];
38
+ rootOnly: readonly string[];
39
+ };
25
40
  /**
26
41
  * Whether the repository-relative `repoRelativePath` is a platform file.
27
42
  * Exact spelling, as the platform reads it: `Access.md` is content. A caller
@@ -39,6 +54,20 @@ export declare function platformFileRefusal(pathOrName: string): string;
39
54
  * wrote as rules.
40
55
  */
41
56
  export declare function platformFileCreationRefusal(pathOrName: string): string;
57
+ /**
58
+ * The sentence an UPLOAD is refused with when one of its paths would land a
59
+ * platform file — a zip carrying an `access.md`, a `.bevelignore`, a
60
+ * `roles.yaml` or the agent guide, or a single file sent under one of those
61
+ * names.
62
+ *
63
+ * Its own sentence rather than the move's, because the thing being kept out is
64
+ * different: a move cannot CREATE a platform file, and an upload cannot land
65
+ * one at all, in either sense — the bytes arrive outside every gate that reads
66
+ * these files as configuration. What governs a folder's access and which roles
67
+ * exist has to be written where the write is checked, so the refusal names the
68
+ * two tools that check it.
69
+ */
70
+ export declare function platformFileUploadRefusal(pathOrName: string): string;
42
71
  /**
43
72
  * Whether `repoRelativeDir` is a folder the platform owns rather than content:
44
73
  * the repository root itself, or one of its reserved top-level folders
@@ -1 +1 @@
1
- {"version":3,"file":"platform-files.d.ts","sourceRoot":"","sources":["../../src/workspace/platform-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,QAAQ,EACd,MAAM,gBAAgB,CAAC;AAExB;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,MAAM,EAAE,CAErE;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAEhD,CAAC;AA2BF;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAKlF;AAED,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAInF;AAED,0EAA0E;AAC1E,wBAAgB,qBAAqB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAKrE;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAEtF;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,0BAA0B,GAClC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,0BAA0B,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpE,wBAAgB,0BAA0B,CACxC,uBAAuB,EAAE,MAAM,EAC/B,MAAM,EAAE,QAAQ,GACf,0BAA0B,GAAG,IAAI,CAUnC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,sBAAsB,CACpC,kBAAkB,EAAE,MAAM,EAC1B,uBAAuB,EAAE,MAAM,EAC/B,MAAM,EAAE,QAAQ,GACf,OAAO,CAOT"}
1
+ {"version":3,"file":"platform-files.d.ts","sourceRoot":"","sources":["../../src/workspace/platform-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,QAAQ,EACd,MAAM,gBAAgB,CAAC;AAExB;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,MAAM,EAAE,CAErE;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAEhD,CAAC;AAKF;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,QAAQ,GAAG;IAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAMnH;AAwBD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAKlF;AAED,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAKpE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAInF;AAED,0EAA0E;AAC1E,wBAAgB,qBAAqB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAKrE;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAEtF;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,0BAA0B,GAClC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,0BAA0B,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpE,wBAAgB,0BAA0B,CACxC,uBAAuB,EAAE,MAAM,EAC/B,MAAM,EAAE,QAAQ,GACf,0BAA0B,GAAG,IAAI,CAUnC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,sBAAsB,CACpC,kBAAkB,EAAE,MAAM,EAC1B,uBAAuB,EAAE,MAAM,EAC/B,MAAM,EAAE,QAAQ,GACf,OAAO,CAOT"}
@@ -26,6 +26,24 @@ export function platformFileNames(layout) {
26
26
  export const PLATFORM_FILE_NAMES = Object.freeze(platformFileNames(DEFAULT_KB_LAYOUT));
27
27
  /** The platform files that are read wherever they sit, not only at the root. */
28
28
  const PLATFORM_FILES_AT_ANY_DEPTH = new Set(['access.md', '.bevelignore']);
29
+ /**
30
+ * The platform files split by the DEPTH they count at, which is the half of
31
+ * {@link isPlatformFile} that a name alone does not tell you: `access.md` and
32
+ * `.bevelignore` are platform files in any folder, `roles.yaml` and the agent
33
+ * guide only in the repository root.
34
+ *
35
+ * Exported because the agent-facing rules state that split in prose, and a
36
+ * prose list written by hand drifts from the predicate that actually refuses
37
+ * the move — an agent then declines a nested `roles.yaml` it may rename, or
38
+ * trusts that a nested `access.md` is ordinary content.
39
+ */
40
+ export function platformFilesByDepth(layout) {
41
+ const names = platformFileNames(layout);
42
+ return {
43
+ anyDepth: names.filter((name) => PLATFORM_FILES_AT_ANY_DEPTH.has(name)),
44
+ rootOnly: names.filter((name) => !PLATFORM_FILES_AT_ANY_DEPTH.has(name)),
45
+ };
46
+ }
29
47
  /** The names under `layout`, as a set — rebuilt per call, because the guide's is configurable. */
30
48
  const platformFiles = (layout) => new Set(platformFileNames(layout));
31
49
  const normalize = (path) => path.replace(/^\.?\/+/, '').replace(/\/+$/, '');
@@ -70,6 +88,23 @@ export function platformFileRefusal(pathOrName) {
70
88
  export function platformFileCreationRefusal(pathOrName) {
71
89
  return `${baseName(pathOrName)} is a platform file name; a move cannot create a platform file.`;
72
90
  }
91
+ /**
92
+ * The sentence an UPLOAD is refused with when one of its paths would land a
93
+ * platform file — a zip carrying an `access.md`, a `.bevelignore`, a
94
+ * `roles.yaml` or the agent guide, or a single file sent under one of those
95
+ * names.
96
+ *
97
+ * Its own sentence rather than the move's, because the thing being kept out is
98
+ * different: a move cannot CREATE a platform file, and an upload cannot land
99
+ * one at all, in either sense — the bytes arrive outside every gate that reads
100
+ * these files as configuration. What governs a folder's access and which roles
101
+ * exist has to be written where the write is checked, so the refusal names the
102
+ * two tools that check it.
103
+ */
104
+ export function platformFileUploadRefusal(pathOrName) {
105
+ return (`${baseName(pathOrName)} is a platform file and is never landed by an upload — ` +
106
+ 'change it with edit_file or write_file, where the change is checked.');
107
+ }
73
108
  /**
74
109
  * Whether `repoRelativeDir` is a folder the platform owns rather than content:
75
110
  * the repository root itself, or one of its reserved top-level folders
@@ -1 +1 @@
1
- {"version":3,"file":"platform-files.js","sourceRoot":"","sources":["../../src/workspace/platform-files.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"platform-files.js","sourceRoot":"","sources":["../../src/workspace/platform-files.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,YAAY,EACZ,oBAAoB,GAErB,MAAM,gBAAgB,CAAC;AAExB;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAgB;IAChD,OAAO,CAAC,GAAG,yBAAyB,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAsB,MAAM,CAAC,MAAM,CACjE,iBAAiB,CAAC,iBAAiB,CAAC,CACrC,CAAC;AAEF,gFAAgF;AAChF,MAAM,2BAA2B,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC;AAE3E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAgB;IACnD,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACxC,OAAO;QACL,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,2BAA2B,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvE,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,2BAA2B,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;KACzE,CAAC;AACJ,CAAC;AAED,kGAAkG;AAClG,MAAM,aAAa,GAAG,CAAC,MAAgB,EAAuB,EAAE,CAAC,IAAI,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;AAEpG,MAAM,SAAS,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAE5F,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAU,EAAE;IACxC,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAChC,OAAO,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,YAAY,GAAG,CAAC,IAAY,EAAW,EAAE,CAC7C,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,GAAG,CAAC,CAAC;AAEpF;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,gBAAwB,EAAE,MAAgB;IACvE,MAAM,IAAI,GAAG,SAAS,CAAC,gBAAgB,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,OAAO,2BAA2B,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,IAAI,CAAC;AAChE,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACpD,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,8CAA8C,CAAC;AAC/E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,2BAA2B,CAAC,UAAkB;IAC5D,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,iEAAiE,CAAC;AAClG,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,yBAAyB,CAAC,UAAkB;IAC1D,OAAO,CACL,GAAG,QAAQ,CAAC,UAAU,CAAC,yDAAyD;QAChF,sEAAsE,CACvE,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,eAAuB,EAAE,MAAgB;IACxE,MAAM,IAAI,GAAG,SAAS,CAAC,eAAe,CAAC,CAAC;IACxC,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,oBAAoB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACvE,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,qBAAqB,CAAC,eAAuB;IAC3D,MAAM,IAAI,GAAG,SAAS,CAAC,eAAe,CAAC,CAAC;IACxC,OAAO,IAAI,KAAK,EAAE;QAChB,CAAC,CAAC,0EAA0E;QAC5E,CAAC,CAAC,GAAG,IAAI,wDAAwD,CAAC;AACtE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,gBAAwB,EAAE,MAAgB;IAC3E,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAChE,CAAC;AAqBD,MAAM,UAAU,0BAA0B,CACxC,uBAA+B,EAC/B,MAAgB;IAEhB,MAAM,IAAI,GAAG,SAAS,CAAC,uBAAuB,CAAC,CAAC;IAChD,IAAI,YAAY,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAClD,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACpC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,0BAA0B,EAAE,GAAG,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;IACnG,CAAC;IACD,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACvD,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,sBAAsB,CACpC,kBAA0B,EAC1B,uBAA+B,EAC/B,MAAgB;IAEhB,IAAI,YAAY,CAAC,kBAAkB,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,MAAM,IAAI,GAAG,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IAC1C,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,IAAI,kBAAkB,CAAC,kBAAkB,EAAE,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACjE,MAAM,MAAM,GAAG,0BAA0B,CAAC,uBAAuB,EAAE,MAAM,CAAC,CAAC;IAC3E,OAAO,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC;AACjD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bevel-software/platform-shared",
3
- "version": "0.23.0",
3
+ "version": "0.24.0",
4
4
  "description": "Shared types and pure domain utilities of the Bevel core platform (auth, workspace, git/workflow contracts, branch registry).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -38,6 +38,25 @@ export const PLATFORM_FILE_NAMES: readonly string[] = Object.freeze(
38
38
  /** The platform files that are read wherever they sit, not only at the root. */
39
39
  const PLATFORM_FILES_AT_ANY_DEPTH = new Set(['access.md', '.bevelignore']);
40
40
 
41
+ /**
42
+ * The platform files split by the DEPTH they count at, which is the half of
43
+ * {@link isPlatformFile} that a name alone does not tell you: `access.md` and
44
+ * `.bevelignore` are platform files in any folder, `roles.yaml` and the agent
45
+ * guide only in the repository root.
46
+ *
47
+ * Exported because the agent-facing rules state that split in prose, and a
48
+ * prose list written by hand drifts from the predicate that actually refuses
49
+ * the move — an agent then declines a nested `roles.yaml` it may rename, or
50
+ * trusts that a nested `access.md` is ordinary content.
51
+ */
52
+ export function platformFilesByDepth(layout: KbLayout): { anyDepth: readonly string[]; rootOnly: readonly string[] } {
53
+ const names = platformFileNames(layout);
54
+ return {
55
+ anyDepth: names.filter((name) => PLATFORM_FILES_AT_ANY_DEPTH.has(name)),
56
+ rootOnly: names.filter((name) => !PLATFORM_FILES_AT_ANY_DEPTH.has(name)),
57
+ };
58
+ }
59
+
41
60
  /** The names under `layout`, as a set — rebuilt per call, because the guide's is configurable. */
42
61
  const platformFiles = (layout: KbLayout): ReadonlySet<string> => new Set(platformFileNames(layout));
43
62
 
@@ -89,6 +108,26 @@ export function platformFileCreationRefusal(pathOrName: string): string {
89
108
  return `${baseName(pathOrName)} is a platform file name; a move cannot create a platform file.`;
90
109
  }
91
110
 
111
+ /**
112
+ * The sentence an UPLOAD is refused with when one of its paths would land a
113
+ * platform file — a zip carrying an `access.md`, a `.bevelignore`, a
114
+ * `roles.yaml` or the agent guide, or a single file sent under one of those
115
+ * names.
116
+ *
117
+ * Its own sentence rather than the move's, because the thing being kept out is
118
+ * different: a move cannot CREATE a platform file, and an upload cannot land
119
+ * one at all, in either sense — the bytes arrive outside every gate that reads
120
+ * these files as configuration. What governs a folder's access and which roles
121
+ * exist has to be written where the write is checked, so the refusal names the
122
+ * two tools that check it.
123
+ */
124
+ export function platformFileUploadRefusal(pathOrName: string): string {
125
+ return (
126
+ `${baseName(pathOrName)} is a platform file and is never landed by an upload — ` +
127
+ 'change it with edit_file or write_file, where the change is checked.'
128
+ );
129
+ }
130
+
92
131
  /**
93
132
  * Whether `repoRelativeDir` is a folder the platform owns rather than content:
94
133
  * the repository root itself, or one of its reserved top-level folders