@clawmasons/shared 0.1.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 (47) hide show
  1. package/dist/index.d.ts +8 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +11 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/role/adapter.d.ts +29 -0
  6. package/dist/role/adapter.d.ts.map +1 -0
  7. package/dist/role/adapter.js +149 -0
  8. package/dist/role/adapter.js.map +1 -0
  9. package/dist/role/discovery.d.ts +38 -0
  10. package/dist/role/discovery.d.ts.map +1 -0
  11. package/dist/role/discovery.js +209 -0
  12. package/dist/role/discovery.js.map +1 -0
  13. package/dist/role/index.d.ts.map +1 -0
  14. package/dist/role/index.js +13 -0
  15. package/dist/role/index.js.map +1 -0
  16. package/dist/role/package-reader.d.ts +30 -0
  17. package/dist/role/package-reader.d.ts.map +1 -0
  18. package/dist/role/package-reader.js +223 -0
  19. package/dist/role/package-reader.js.map +1 -0
  20. package/dist/role/parser.d.ts +45 -0
  21. package/dist/role/parser.d.ts.map +1 -0
  22. package/dist/role/parser.js +241 -0
  23. package/dist/role/parser.js.map +1 -0
  24. package/dist/role/resource-scanner.d.ts +16 -0
  25. package/dist/role/resource-scanner.d.ts.map +1 -0
  26. package/dist/role/resource-scanner.js +43 -0
  27. package/dist/role/resource-scanner.js.map +1 -0
  28. package/dist/schemas/index.d.ts +7 -0
  29. package/dist/schemas/index.d.ts.map +1 -0
  30. package/dist/schemas/index.js +8 -0
  31. package/dist/schemas/index.js.map +1 -0
  32. package/dist/schemas/role-types.d.ts +564 -0
  33. package/dist/schemas/role-types.d.ts.map +1 -0
  34. package/dist/schemas/role-types.js +93 -0
  35. package/dist/schemas/role-types.js.map +1 -0
  36. package/dist/toolfilter.d.ts.map +1 -0
  37. package/dist/toolfilter.js +55 -0
  38. package/dist/toolfilter.js.map +1 -0
  39. package/dist/types/role.d.ts +14 -0
  40. package/dist/types/role.d.ts.map +1 -0
  41. package/dist/types/role.js +2 -0
  42. package/dist/types/role.js.map +1 -0
  43. package/dist/types.d.ts +106 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +2 -0
  46. package/dist/types.js.map +1 -0
  47. package/package.json +29 -0
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Package Reader — reads an NPM role package and produces a Role object.
3
+ *
4
+ * Steps:
5
+ * 1. Read package.json and verify chapter.type === "role"
6
+ * 2. Read the bundled ROLE.md from the package directory
7
+ * 3. Parse frontmatter and body (reuses parseFrontmatter from parser.ts)
8
+ * 4. Normalize fields using dialect mapping if chapter.dialect is specified,
9
+ * otherwise use generic ROLE_TYPES field names directly
10
+ * 5. Resolve all paths relative to the package directory
11
+ * 6. Set source.type = 'package' and source.packageName
12
+ * 7. Validate through roleSchema
13
+ */
14
+ import { readFile } from "node:fs/promises";
15
+ import { join, basename, resolve } from "node:path";
16
+ import { roleSchema } from "../schemas/role-types.js";
17
+ import { parseFrontmatter } from "./parser.js";
18
+ import { scanBundledResources } from "./resource-scanner.js";
19
+ import { getDialect } from "./dialect-registry.js";
20
+ /**
21
+ * Error thrown when a role NPM package cannot be read.
22
+ */
23
+ export class PackageReadError extends Error {
24
+ packagePath;
25
+ constructor(message, packagePath) {
26
+ super(`${message} (at ${packagePath})`);
27
+ this.packagePath = packagePath;
28
+ this.name = "PackageReadError";
29
+ }
30
+ }
31
+ /**
32
+ * Generic field mapping — packaged roles use ROLE_TYPES generic names directly.
33
+ */
34
+ const GENERIC_FIELD_MAPPING = {
35
+ name: "generic",
36
+ directory: "",
37
+ fieldMapping: {
38
+ tasks: "tasks",
39
+ apps: "apps",
40
+ skills: "skills",
41
+ },
42
+ };
43
+ /**
44
+ * Read an NPM role package and produce a validated Role object.
45
+ *
46
+ * @param packagePath - Absolute path to the package directory (e.g., node_modules/@acme/role-create-prd)
47
+ * @returns Validated Role with source.type = 'package'
48
+ * @throws PackageReadError if the package is missing required files or has wrong chapter.type
49
+ */
50
+ export async function readPackagedRole(packagePath) {
51
+ // 1. Read and validate package.json
52
+ const pkgJson = await readPackageJson(packagePath);
53
+ if (!pkgJson.chapter || pkgJson.chapter.type !== "role") {
54
+ throw new PackageReadError(`Package "${pkgJson.name}" does not have chapter.type = "role" (got: ${pkgJson.chapter?.type ?? "undefined"})`, packagePath);
55
+ }
56
+ // 2. Read ROLE.md
57
+ const roleMdPath = join(packagePath, "ROLE.md");
58
+ let roleMdContent;
59
+ try {
60
+ roleMdContent = await readFile(roleMdPath, "utf-8");
61
+ }
62
+ catch {
63
+ throw new PackageReadError(`Package "${pkgJson.name}" is missing ROLE.md`, packagePath);
64
+ }
65
+ // 3. Parse frontmatter and body
66
+ const { frontmatter, body } = parseFrontmatter(roleMdContent, roleMdPath);
67
+ // 4. Determine field mapping
68
+ const dialect = resolveDialect(pkgJson, packagePath);
69
+ // 5. Extract metadata
70
+ const roleName = frontmatter.name ?? pkgJson.name;
71
+ const metadata = {
72
+ name: roleName,
73
+ description: frontmatter.description,
74
+ version: frontmatter.version ?? pkgJson.version,
75
+ scope: frontmatter.scope,
76
+ };
77
+ if (!metadata.description) {
78
+ throw new PackageReadError(`Package "${pkgJson.name}" ROLE.md is missing required field: description`, packagePath);
79
+ }
80
+ // 6. Normalize fields using dialect mapping
81
+ const tasks = normalizeField(frontmatter, dialect.fieldMapping.tasks);
82
+ const apps = normalizeApps(frontmatter, dialect.fieldMapping.apps);
83
+ const skills = normalizeSkills(frontmatter, dialect.fieldMapping.skills, packagePath);
84
+ // 7. Container requirements (pass-through)
85
+ const container = frontmatter.container ?? {};
86
+ // 8. Governance (assembled from top-level fields)
87
+ const governance = {};
88
+ if (frontmatter.risk !== undefined)
89
+ governance.risk = frontmatter.risk;
90
+ if (frontmatter.credentials !== undefined)
91
+ governance.credentials = frontmatter.credentials;
92
+ if (frontmatter.constraints !== undefined)
93
+ governance.constraints = frontmatter.constraints;
94
+ // 9. Scan bundled resources
95
+ const resources = await scanBundledResources(packagePath);
96
+ // 10. Build and validate
97
+ const roleData = {
98
+ metadata,
99
+ instructions: body,
100
+ type: frontmatter.type,
101
+ tasks,
102
+ apps,
103
+ skills,
104
+ container,
105
+ governance,
106
+ resources,
107
+ source: {
108
+ type: "package",
109
+ packageName: pkgJson.name,
110
+ },
111
+ };
112
+ return roleSchema.parse(roleData);
113
+ }
114
+ // ---------------------------------------------------------------------------
115
+ // Helpers
116
+ // ---------------------------------------------------------------------------
117
+ /**
118
+ * Read and parse package.json from a package directory.
119
+ */
120
+ async function readPackageJson(packagePath) {
121
+ const pkgJsonPath = join(packagePath, "package.json");
122
+ let raw;
123
+ try {
124
+ raw = await readFile(pkgJsonPath, "utf-8");
125
+ }
126
+ catch {
127
+ throw new PackageReadError("Missing package.json", packagePath);
128
+ }
129
+ try {
130
+ const parsed = JSON.parse(raw);
131
+ if (!parsed.name) {
132
+ throw new PackageReadError("package.json is missing required field: name", packagePath);
133
+ }
134
+ return parsed;
135
+ }
136
+ catch (err) {
137
+ if (err instanceof PackageReadError)
138
+ throw err;
139
+ const msg = err instanceof Error ? err.message : String(err);
140
+ throw new PackageReadError(`Invalid package.json: ${msg}`, packagePath);
141
+ }
142
+ }
143
+ /**
144
+ * Resolve the dialect to use for field normalization.
145
+ * If chapter.dialect is specified, use that dialect's mapping.
146
+ * Otherwise, use generic ROLE_TYPES field names.
147
+ */
148
+ function resolveDialect(pkgJson, packagePath) {
149
+ const dialectName = pkgJson.chapter?.dialect;
150
+ if (!dialectName)
151
+ return GENERIC_FIELD_MAPPING;
152
+ const dialect = getDialect(dialectName);
153
+ if (!dialect) {
154
+ throw new PackageReadError(`Unknown dialect "${dialectName}" specified in chapter.dialect`, packagePath);
155
+ }
156
+ return dialect;
157
+ }
158
+ /**
159
+ * Normalize a simple list field (tasks).
160
+ */
161
+ function normalizeField(frontmatter, fieldName) {
162
+ const raw = frontmatter[fieldName];
163
+ if (!raw)
164
+ return [];
165
+ if (!Array.isArray(raw)) {
166
+ return [{ name: String(raw) }];
167
+ }
168
+ return raw.map((item) => {
169
+ if (typeof item === "string") {
170
+ return { name: item };
171
+ }
172
+ if (typeof item === "object" && item !== null && "name" in item) {
173
+ return item;
174
+ }
175
+ return { name: String(item) };
176
+ });
177
+ }
178
+ /**
179
+ * Normalize apps field.
180
+ */
181
+ function normalizeApps(frontmatter, fieldName) {
182
+ const raw = frontmatter[fieldName];
183
+ if (!raw)
184
+ return [];
185
+ if (!Array.isArray(raw))
186
+ return [];
187
+ return raw.map((item) => {
188
+ if (typeof item === "object" && item !== null) {
189
+ return item;
190
+ }
191
+ return { name: String(item) };
192
+ });
193
+ }
194
+ /**
195
+ * Normalize skills field with path resolution relative to package directory.
196
+ */
197
+ function normalizeSkills(frontmatter, fieldName, packageDir) {
198
+ const raw = frontmatter[fieldName];
199
+ if (!raw)
200
+ return [];
201
+ if (!Array.isArray(raw))
202
+ return [];
203
+ return raw.map((item) => {
204
+ if (typeof item === "string") {
205
+ // Local path reference — resolve relative to package directory
206
+ if (item.startsWith("./") || item.startsWith("../")) {
207
+ const resolvedPath = resolve(packageDir, item);
208
+ const name = basename(resolvedPath);
209
+ return { name, ref: resolvedPath };
210
+ }
211
+ // Package reference — extract short name
212
+ const name = item.startsWith("@")
213
+ ? item.split("/").pop() ?? item
214
+ : item;
215
+ return { name, ref: item };
216
+ }
217
+ if (typeof item === "object" && item !== null && "name" in item) {
218
+ return item;
219
+ }
220
+ return { name: String(item) };
221
+ });
222
+ }
223
+ //# sourceMappingURL=package-reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-reader.js","sourceRoot":"","sources":["../../src/role/package-reader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * ROLE.md Parser — reads a local ROLE.md file and produces a Role object.
3
+ *
4
+ * Steps:
5
+ * 1. Detect the agent dialect from the parent directory structure
6
+ * 2. Parse YAML frontmatter and extract markdown body as instructions
7
+ * 3. Normalize agent-specific field names to generic ROLE_TYPES names
8
+ * 4. Resolve bundled resource paths
9
+ * 5. Resolve dependency references
10
+ * 6. Validate through roleSchema
11
+ */
12
+ import type { Role } from "../types/role.js";
13
+ import { type DialectEntry } from "./dialect-registry.js";
14
+ /**
15
+ * Parse error thrown when ROLE.md is malformed.
16
+ */
17
+ export declare class RoleParseError extends Error {
18
+ readonly rolePath: string;
19
+ constructor(message: string, rolePath: string);
20
+ }
21
+ /**
22
+ * Read a local ROLE.md file and produce a validated Role object.
23
+ *
24
+ * @param rolePath - Absolute path to the ROLE.md file
25
+ * @returns Validated Role
26
+ * @throws RoleParseError if the file is malformed or dialect cannot be detected
27
+ */
28
+ export declare function readMaterializedRole(rolePath: string): Promise<Role>;
29
+ interface ParsedFrontmatter {
30
+ frontmatter: Record<string, unknown>;
31
+ body: string;
32
+ }
33
+ /**
34
+ * Parse YAML frontmatter delimited by `---` markers.
35
+ */
36
+ export declare function parseFrontmatter(content: string, rolePath: string): ParsedFrontmatter;
37
+ /**
38
+ * Detect the agent dialect from the role's directory structure.
39
+ *
40
+ * Expected pattern: `<project>/.<agent>/roles/<role-name>/`
41
+ * We walk up from the role directory looking for a known agent directory.
42
+ */
43
+ export declare function detectDialect(roleDir: string, rolePath: string): DialectEntry;
44
+ export {};
45
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/role/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAG/B;;GAEG;AACH,qBAAa,cAAe,SAAQ,KAAK;aACM,QAAQ,EAAE,MAAM;gBAAjD,OAAO,EAAE,MAAM,EAAkB,QAAQ,EAAE,MAAM;CAI9D;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkE1E;AAMD,UAAU,iBAAiB;IACzB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,iBAAiB,CAyCrF;AAMD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAiC7E"}
@@ -0,0 +1,241 @@
1
+ /**
2
+ * ROLE.md Parser — reads a local ROLE.md file and produces a Role object.
3
+ *
4
+ * Steps:
5
+ * 1. Detect the agent dialect from the parent directory structure
6
+ * 2. Parse YAML frontmatter and extract markdown body as instructions
7
+ * 3. Normalize agent-specific field names to generic ROLE_TYPES names
8
+ * 4. Resolve bundled resource paths
9
+ * 5. Resolve dependency references
10
+ * 6. Validate through roleSchema
11
+ */
12
+ import { readFile } from "node:fs/promises";
13
+ import { dirname, basename, resolve } from "node:path";
14
+ import { load as yamlLoad } from "js-yaml";
15
+ import { roleSchema } from "../schemas/role-types.js";
16
+ import { getDialectByDirectory, getKnownDirectories, } from "./dialect-registry.js";
17
+ import { scanBundledResources } from "./resource-scanner.js";
18
+ /**
19
+ * Parse error thrown when ROLE.md is malformed.
20
+ */
21
+ export class RoleParseError extends Error {
22
+ rolePath;
23
+ constructor(message, rolePath) {
24
+ super(`${message} (at ${rolePath})`);
25
+ this.rolePath = rolePath;
26
+ this.name = "RoleParseError";
27
+ }
28
+ }
29
+ /**
30
+ * Read a local ROLE.md file and produce a validated Role object.
31
+ *
32
+ * @param rolePath - Absolute path to the ROLE.md file
33
+ * @returns Validated Role
34
+ * @throws RoleParseError if the file is malformed or dialect cannot be detected
35
+ */
36
+ export async function readMaterializedRole(rolePath) {
37
+ // Read the file
38
+ const content = await readFile(rolePath, "utf-8");
39
+ // Parse frontmatter and body
40
+ const { frontmatter, body } = parseFrontmatter(content, rolePath);
41
+ // Detect dialect from directory structure
42
+ const roleDir = dirname(rolePath);
43
+ const dialect = detectDialect(roleDir, rolePath);
44
+ // Extract metadata
45
+ const roleName = frontmatter.name ?? basename(roleDir);
46
+ const metadata = {
47
+ name: roleName,
48
+ description: frontmatter.description,
49
+ version: frontmatter.version,
50
+ scope: frontmatter.scope,
51
+ };
52
+ if (!metadata.description) {
53
+ throw new RoleParseError("Missing required field: description", rolePath);
54
+ }
55
+ // Normalize fields using dialect mapping
56
+ const tasks = normalizeTasks(frontmatter, dialect);
57
+ const apps = normalizeApps(frontmatter, dialect);
58
+ const skills = normalizeSkills(frontmatter, dialect, roleDir);
59
+ // Container requirements (pass-through, no normalization needed)
60
+ const container = frontmatter.container ?? {};
61
+ // Governance (assembled from top-level fields)
62
+ const governance = {};
63
+ if (frontmatter.risk !== undefined)
64
+ governance.risk = frontmatter.risk;
65
+ if (frontmatter.credentials !== undefined)
66
+ governance.credentials = frontmatter.credentials;
67
+ if (frontmatter.constraints !== undefined)
68
+ governance.constraints = frontmatter.constraints;
69
+ // Scan bundled resources
70
+ const resources = await scanBundledResources(roleDir);
71
+ // Extract sources (canonical mason field)
72
+ const sources = Array.isArray(frontmatter.sources)
73
+ ? frontmatter.sources
74
+ : [];
75
+ // Build the role object and validate through Zod
76
+ const roleData = {
77
+ metadata,
78
+ instructions: body,
79
+ type: frontmatter.type,
80
+ tasks,
81
+ apps,
82
+ skills,
83
+ sources,
84
+ container,
85
+ governance,
86
+ resources,
87
+ source: {
88
+ type: "local",
89
+ agentDialect: dialect.name,
90
+ path: roleDir,
91
+ },
92
+ };
93
+ return roleSchema.parse(roleData);
94
+ }
95
+ /**
96
+ * Parse YAML frontmatter delimited by `---` markers.
97
+ */
98
+ export function parseFrontmatter(content, rolePath) {
99
+ const trimmed = content.trimStart();
100
+ if (!trimmed.startsWith("---")) {
101
+ throw new RoleParseError("ROLE.md must start with YAML frontmatter (---)", rolePath);
102
+ }
103
+ // Find the closing ---
104
+ const endIndex = trimmed.indexOf("\n---", 3);
105
+ if (endIndex === -1) {
106
+ throw new RoleParseError("ROLE.md frontmatter is not closed (missing closing ---)", rolePath);
107
+ }
108
+ const yamlStr = trimmed.substring(3, endIndex).trim();
109
+ const body = trimmed.substring(endIndex + 4).trim(); // skip \n---
110
+ let frontmatter;
111
+ try {
112
+ frontmatter = yamlLoad(yamlStr);
113
+ }
114
+ catch (err) {
115
+ const msg = err instanceof Error ? err.message : String(err);
116
+ throw new RoleParseError(`Invalid YAML in frontmatter: ${msg}`, rolePath);
117
+ }
118
+ if (typeof frontmatter !== "object" || frontmatter === null || Array.isArray(frontmatter)) {
119
+ throw new RoleParseError("Frontmatter must be a YAML mapping (key-value pairs)", rolePath);
120
+ }
121
+ return {
122
+ frontmatter: frontmatter,
123
+ body,
124
+ };
125
+ }
126
+ // ---------------------------------------------------------------------------
127
+ // Dialect detection
128
+ // ---------------------------------------------------------------------------
129
+ /**
130
+ * Detect the agent dialect from the role's directory structure.
131
+ *
132
+ * Expected pattern: `<project>/.<agent>/roles/<role-name>/`
133
+ * We walk up from the role directory looking for a known agent directory.
134
+ */
135
+ export function detectDialect(roleDir, rolePath) {
136
+ // roleDir = /path/to/project/.claude/roles/my-role
137
+ // We expect the parent of "roles" to be the agent directory
138
+ const rolesParent = dirname(roleDir); // .../roles
139
+ const agentDir = dirname(rolesParent); // .../.claude
140
+ // Check that we're inside a "roles" directory
141
+ if (basename(rolesParent) !== "roles") {
142
+ throw new RoleParseError(`ROLE.md must be inside a roles/ directory (expected <project>/.<agent>/roles/<role-name>/ROLE.md)`, rolePath);
143
+ }
144
+ // Get the agent directory name (e.g., ".claude" → "claude")
145
+ const agentDirName = basename(agentDir);
146
+ if (!agentDirName.startsWith(".")) {
147
+ throw new RoleParseError(`Agent directory must start with a dot (got "${agentDirName}")`, rolePath);
148
+ }
149
+ const directoryKey = agentDirName.substring(1); // strip the dot
150
+ const dialect = getDialectByDirectory(directoryKey);
151
+ if (!dialect) {
152
+ throw new RoleParseError(`Unknown agent dialect for directory "${agentDirName}". Known directories: ${getKnownDirsForError()}`, rolePath);
153
+ }
154
+ return dialect;
155
+ }
156
+ function getKnownDirsForError() {
157
+ return getKnownDirectories()
158
+ .map((d) => `.${d}/`)
159
+ .join(", ");
160
+ }
161
+ // ---------------------------------------------------------------------------
162
+ // Field normalization
163
+ // ---------------------------------------------------------------------------
164
+ /**
165
+ * Normalize the dialect-specific tasks field.
166
+ * Claude: commands, Codex: instructions, Aider: conventions
167
+ * Returns raw objects — Zod validates and applies defaults.
168
+ */
169
+ function normalizeTasks(frontmatter, dialect) {
170
+ const fieldName = dialect.fieldMapping.tasks;
171
+ const raw = frontmatter[fieldName];
172
+ if (!raw)
173
+ return [];
174
+ if (!Array.isArray(raw)) {
175
+ return [{ name: String(raw) }];
176
+ }
177
+ return raw.map((item) => {
178
+ if (typeof item === "string") {
179
+ return { name: item };
180
+ }
181
+ if (typeof item === "object" && item !== null && "name" in item) {
182
+ return item;
183
+ }
184
+ return { name: String(item) };
185
+ });
186
+ }
187
+ /**
188
+ * Normalize the dialect-specific apps field.
189
+ * All dialects currently use mcp_servers.
190
+ * Returns raw objects — Zod validates and applies defaults.
191
+ */
192
+ function normalizeApps(frontmatter, dialect) {
193
+ const fieldName = dialect.fieldMapping.apps;
194
+ const raw = frontmatter[fieldName];
195
+ if (!raw)
196
+ return [];
197
+ if (!Array.isArray(raw))
198
+ return [];
199
+ return raw.map((item) => {
200
+ if (typeof item === "object" && item !== null) {
201
+ return item;
202
+ }
203
+ // String shorthand — just a server name
204
+ return { name: String(item) };
205
+ });
206
+ }
207
+ /**
208
+ * Normalize the dialect-specific skills field.
209
+ * All dialects currently use "skills".
210
+ * Returns raw objects — Zod validates and applies defaults.
211
+ */
212
+ function normalizeSkills(frontmatter, dialect, roleDir) {
213
+ const fieldName = dialect.fieldMapping.skills;
214
+ const raw = frontmatter[fieldName];
215
+ if (!raw)
216
+ return [];
217
+ if (!Array.isArray(raw))
218
+ return [];
219
+ // Find the project root (parent of the agent directory)
220
+ const projectRoot = resolve(roleDir, "..", "..", "..");
221
+ return raw.map((item) => {
222
+ if (typeof item === "string") {
223
+ // Local path reference — resolve relative to project root
224
+ if (item.startsWith("./") || item.startsWith("../")) {
225
+ const resolvedPath = resolve(projectRoot, item);
226
+ const name = basename(resolvedPath);
227
+ return { name, ref: resolvedPath };
228
+ }
229
+ // Package reference — extract short name
230
+ const name = item.startsWith("@")
231
+ ? item.split("/").pop() ?? item
232
+ : item;
233
+ return { name, ref: item };
234
+ }
235
+ if (typeof item === "object" && item !== null && "name" in item) {
236
+ return item;
237
+ }
238
+ return { name: String(item) };
239
+ });
240
+ }
241
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/role/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Resource Scanner — discover bundled resources in a role directory.
3
+ *
4
+ * Recursively walks the role directory and returns ResourceFile entries for
5
+ * all files except ROLE.md itself. Only paths are stored — file content is
6
+ * never loaded into memory (per PRD §5.1).
7
+ */
8
+ import type { ResourceFile } from "../types/role.js";
9
+ /**
10
+ * Recursively scan a role directory for bundled resources.
11
+ *
12
+ * @param roleDir - Absolute path to the role directory (contains ROLE.md)
13
+ * @returns Array of ResourceFile entries with relative and absolute paths
14
+ */
15
+ export declare function scanBundledResources(roleDir: string): Promise<ResourceFile[]>;
16
+ //# sourceMappingURL=resource-scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource-scanner.d.ts","sourceRoot":"","sources":["../../src/role/resource-scanner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAInF"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Resource Scanner — discover bundled resources in a role directory.
3
+ *
4
+ * Recursively walks the role directory and returns ResourceFile entries for
5
+ * all files except ROLE.md itself. Only paths are stored — file content is
6
+ * never loaded into memory (per PRD §5.1).
7
+ */
8
+ import { readdir, stat } from "node:fs/promises";
9
+ import { join, relative } from "node:path";
10
+ /**
11
+ * Recursively scan a role directory for bundled resources.
12
+ *
13
+ * @param roleDir - Absolute path to the role directory (contains ROLE.md)
14
+ * @returns Array of ResourceFile entries with relative and absolute paths
15
+ */
16
+ export async function scanBundledResources(roleDir) {
17
+ const resources = [];
18
+ await walkDirectory(roleDir, roleDir, resources);
19
+ return resources;
20
+ }
21
+ async function walkDirectory(baseDir, currentDir, results) {
22
+ const entries = await readdir(currentDir, { withFileTypes: true });
23
+ for (const entry of entries) {
24
+ const absolutePath = join(currentDir, entry.name);
25
+ const relativePath = relative(baseDir, absolutePath);
26
+ if (entry.isDirectory()) {
27
+ await walkDirectory(baseDir, absolutePath, results);
28
+ }
29
+ else if (entry.isFile()) {
30
+ // Skip ROLE.md itself
31
+ if (entry.name === "ROLE.md" && currentDir === baseDir) {
32
+ continue;
33
+ }
34
+ const fileStat = await stat(absolutePath);
35
+ results.push({
36
+ relativePath,
37
+ absolutePath,
38
+ permissions: fileStat.mode,
39
+ });
40
+ }
41
+ }
42
+ }
43
+ //# sourceMappingURL=resource-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource-scanner.js","sourceRoot":"","sources":["../../src/role/resource-scanner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG3C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAAe;IACxD,MAAM,SAAS,GAAmB,EAAE,CAAC;IACrC,MAAM,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IACjD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,OAAe,EACf,UAAkB,EAClB,OAAuB;IAEvB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAEnE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAClD,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAErD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,aAAa,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;QACtD,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1B,sBAAsB;YACtB,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;gBACvD,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,CAAC;YAC1C,OAAO,CAAC,IAAI,CAAC;gBACX,YAAY;gBACZ,YAAY;gBACZ,WAAW,EAAE,QAAQ,CAAC,IAAI;aAC3B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { appChapterFieldSchema, type AppChapterField } from "./app.js";
2
+ export { skillChapterFieldSchema, type SkillChapterField } from "./skill.js";
3
+ export { taskChapterFieldSchema, type TaskChapterField } from "./task.js";
4
+ export { roleChapterFieldSchema, type RoleChapterField } from "./role.js";
5
+ export { parseChapterField, type ChapterField } from "./chapter-field.js";
6
+ export { toolPermissionsSchema, roleMetadataSchema, taskRefSchema, skillRefSchema, appConfigSchema, mountConfigSchema, containerRequirementsSchema, governanceConfigSchema, resourceFileSchema, roleSourceSchema, roleSchema, } from "./role-types.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,KAAK,eAAe,EAAE,MAAM,UAAU,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG1E,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,2BAA2B,EAC3B,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,EAChB,UAAU,GACX,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { appChapterFieldSchema } from "./app.js";
2
+ export { skillChapterFieldSchema } from "./skill.js";
3
+ export { taskChapterFieldSchema } from "./task.js";
4
+ export { roleChapterFieldSchema } from "./role.js";
5
+ export { parseChapterField } from "./chapter-field.js";
6
+ // ROLE_TYPES schemas
7
+ export { toolPermissionsSchema, roleMetadataSchema, taskRefSchema, skillRefSchema, appConfigSchema, mountConfigSchema, containerRequirementsSchema, governanceConfigSchema, resourceFileSchema, roleSourceSchema, roleSchema, } from "./role-types.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAwB,MAAM,UAAU,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAA0B,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAyB,MAAM,WAAW,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAyB,MAAM,WAAW,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAqB,MAAM,oBAAoB,CAAC;AAE1E,qBAAqB;AACrB,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,2BAA2B,EAC3B,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,EAChB,UAAU,GACX,MAAM,iBAAiB,CAAC"}