@squads-sh/validator 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 (53) hide show
  1. package/dist/adapters/filesystem.d.ts +11 -0
  2. package/dist/adapters/filesystem.d.ts.map +1 -0
  3. package/dist/adapters/filesystem.js +37 -0
  4. package/dist/adapters/filesystem.js.map +1 -0
  5. package/dist/categories/agents.d.ts +21 -0
  6. package/dist/categories/agents.d.ts.map +1 -0
  7. package/dist/categories/agents.js +214 -0
  8. package/dist/categories/agents.js.map +1 -0
  9. package/dist/categories/cross-refs.d.ts +13 -0
  10. package/dist/categories/cross-refs.d.ts.map +1 -0
  11. package/dist/categories/cross-refs.js +88 -0
  12. package/dist/categories/cross-refs.js.map +1 -0
  13. package/dist/categories/manifest.d.ts +19 -0
  14. package/dist/categories/manifest.d.ts.map +1 -0
  15. package/dist/categories/manifest.js +150 -0
  16. package/dist/categories/manifest.js.map +1 -0
  17. package/dist/categories/structure.d.ts +14 -0
  18. package/dist/categories/structure.d.ts.map +1 -0
  19. package/dist/categories/structure.js +76 -0
  20. package/dist/categories/structure.js.map +1 -0
  21. package/dist/categories/tasks.d.ts +20 -0
  22. package/dist/categories/tasks.d.ts.map +1 -0
  23. package/dist/categories/tasks.js +195 -0
  24. package/dist/categories/tasks.js.map +1 -0
  25. package/dist/categories/workflows.d.ts +17 -0
  26. package/dist/categories/workflows.d.ts.map +1 -0
  27. package/dist/categories/workflows.js +125 -0
  28. package/dist/categories/workflows.js.map +1 -0
  29. package/dist/index.d.ts +14 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +62 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/parser.d.ts +20 -0
  34. package/dist/parser.d.ts.map +1 -0
  35. package/dist/parser.js +58 -0
  36. package/dist/parser.js.map +1 -0
  37. package/dist/scoring.d.ts +22 -0
  38. package/dist/scoring.d.ts.map +1 -0
  39. package/dist/scoring.js +57 -0
  40. package/dist/scoring.js.map +1 -0
  41. package/dist/types.d.ts +101 -0
  42. package/dist/types.d.ts.map +1 -0
  43. package/dist/types.js +19 -0
  44. package/dist/types.js.map +1 -0
  45. package/dist/utils/enums.d.ts +9 -0
  46. package/dist/utils/enums.d.ts.map +1 -0
  47. package/dist/utils/enums.js +37 -0
  48. package/dist/utils/enums.js.map +1 -0
  49. package/dist/utils/patterns.d.ts +11 -0
  50. package/dist/utils/patterns.d.ts.map +1 -0
  51. package/dist/utils/patterns.js +11 -0
  52. package/dist/utils/patterns.js.map +1 -0
  53. package/package.json +34 -0
@@ -0,0 +1,11 @@
1
+ import type { FileTree } from "../types.js";
2
+ /**
3
+ * Build a FileTree from a local filesystem directory.
4
+ * Recursively reads all files and returns a Map<relativePath, content>.
5
+ * Only reads text files (.yaml, .yml, .md, .json).
6
+ *
7
+ * @param dirPath Absolute path to the squad directory
8
+ * @returns FileTree ready for validateSquad()
9
+ */
10
+ export declare function buildFileTreeFromFS(dirPath: string): Promise<FileTree>;
11
+ //# sourceMappingURL=filesystem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../src/adapters/filesystem.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAI5E"}
@@ -0,0 +1,37 @@
1
+ import { readFile, readdir } from "node:fs/promises";
2
+ import { join, relative } from "node:path";
3
+ /**
4
+ * Build a FileTree from a local filesystem directory.
5
+ * Recursively reads all files and returns a Map<relativePath, content>.
6
+ * Only reads text files (.yaml, .yml, .md, .json).
7
+ *
8
+ * @param dirPath Absolute path to the squad directory
9
+ * @returns FileTree ready for validateSquad()
10
+ */
11
+ export async function buildFileTreeFromFS(dirPath) {
12
+ const fileTree = new Map();
13
+ await walkDir(dirPath, dirPath, fileTree);
14
+ return fileTree;
15
+ }
16
+ const TEXT_EXTENSIONS = new Set([".yaml", ".yml", ".md", ".json", ".txt"]);
17
+ async function walkDir(basePath, currentPath, fileTree) {
18
+ const entries = await readdir(currentPath, { withFileTypes: true });
19
+ for (const entry of entries) {
20
+ const fullPath = join(currentPath, entry.name);
21
+ if (entry.isDirectory()) {
22
+ // Skip hidden directories and node_modules
23
+ if (entry.name.startsWith(".") || entry.name === "node_modules")
24
+ continue;
25
+ await walkDir(basePath, fullPath, fileTree);
26
+ }
27
+ else if (entry.isFile()) {
28
+ const ext = entry.name.substring(entry.name.lastIndexOf("."));
29
+ if (!TEXT_EXTENSIONS.has(ext))
30
+ continue;
31
+ const relativePath = relative(basePath, fullPath);
32
+ const content = await readFile(fullPath, "utf-8");
33
+ fileTree.set(relativePath, content);
34
+ }
35
+ }
36
+ }
37
+ //# sourceMappingURL=filesystem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.js","sourceRoot":"","sources":["../../src/adapters/filesystem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAQ,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG3C;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,OAAe;IACvD,MAAM,QAAQ,GAAa,IAAI,GAAG,EAAE,CAAC;IACrC,MAAM,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC1C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AAE3E,KAAK,UAAU,OAAO,CACpB,QAAgB,EAChB,WAAmB,EACnB,QAAkB;IAElB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAEpE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAE/C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,2CAA2C;YAC3C,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc;gBAAE,SAAS;YAC1E,MAAM,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC9C,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1B,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9D,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YAExC,MAAM,YAAY,GAAG,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAClD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAClD,QAAQ,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { FileTree, ValidationFinding, ParsedAgent } from "../types.js";
2
+ /**
3
+ * Category 3: Agents validation
4
+ * Weight: 20%
5
+ *
6
+ * Validates:
7
+ * - YAML frontmatter exists
8
+ * - agent.id (kebab-case)
9
+ * - agent.name (non-empty)
10
+ * - agent.title (non-empty)
11
+ * - agent.icon (non-empty)
12
+ * - agent.whenToUse (non-empty)
13
+ * - persona_profile.archetype in {Builder, Guardian, Balancer, Flow_Master}
14
+ * - persona_profile.communication.tone (non-empty, known value)
15
+ * - greeting_levels has at least 3 keys
16
+ */
17
+ export declare function validateAgents(fileTree: FileTree): {
18
+ findings: ValidationFinding[];
19
+ agents: ParsedAgent[];
20
+ };
21
+ //# sourceMappingURL=agents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/categories/agents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO5E;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,QAAQ,GACjB;IAAE,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAAC,MAAM,EAAE,WAAW,EAAE,CAAA;CAAE,CAoN1D"}
@@ -0,0 +1,214 @@
1
+ import { extractFrontmatter, hasFrontmatter } from "../parser.js";
2
+ import { KEBAB_CASE } from "../utils/patterns.js";
3
+ import { ARCHETYPES, TONES } from "../utils/enums.js";
4
+ const CAT = "agents";
5
+ /**
6
+ * Category 3: Agents validation
7
+ * Weight: 20%
8
+ *
9
+ * Validates:
10
+ * - YAML frontmatter exists
11
+ * - agent.id (kebab-case)
12
+ * - agent.name (non-empty)
13
+ * - agent.title (non-empty)
14
+ * - agent.icon (non-empty)
15
+ * - agent.whenToUse (non-empty)
16
+ * - persona_profile.archetype in {Builder, Guardian, Balancer, Flow_Master}
17
+ * - persona_profile.communication.tone (non-empty, known value)
18
+ * - greeting_levels has at least 3 keys
19
+ */
20
+ export function validateAgents(fileTree) {
21
+ const findings = [];
22
+ const agents = [];
23
+ const agentFiles = [...fileTree.keys()].filter((p) => p.startsWith("agents/") && p.endsWith(".md"));
24
+ if (agentFiles.length === 0) {
25
+ return { findings, agents };
26
+ }
27
+ for (const file of agentFiles) {
28
+ const content = fileTree.get(file);
29
+ if (!hasFrontmatter(content)) {
30
+ findings.push({
31
+ severity: "error",
32
+ category: CAT,
33
+ message: "Agent file missing YAML frontmatter block (--- ... ---)",
34
+ file,
35
+ });
36
+ agents.push({ file });
37
+ continue;
38
+ }
39
+ const fm = extractFrontmatter(content);
40
+ if (!fm) {
41
+ findings.push({
42
+ severity: "error",
43
+ category: CAT,
44
+ message: "Agent file has invalid YAML in frontmatter",
45
+ file,
46
+ });
47
+ agents.push({ file });
48
+ continue;
49
+ }
50
+ const agentBlock = fm["agent"];
51
+ const personaBlock = fm["persona_profile"];
52
+ // Support greeting_levels as top-level OR nested inside persona_profile.communication
53
+ const greetingBlock = (fm["greeting_levels"]
54
+ ?? personaBlock?.["communication"]?.["greeting_levels"]);
55
+ const parsed = {
56
+ file,
57
+ agent: agentBlock
58
+ ? {
59
+ name: agentBlock["name"],
60
+ id: agentBlock["id"],
61
+ title: agentBlock["title"],
62
+ icon: agentBlock["icon"],
63
+ whenToUse: agentBlock["whenToUse"],
64
+ }
65
+ : undefined,
66
+ persona_profile: personaBlock
67
+ ? {
68
+ archetype: personaBlock["archetype"],
69
+ communication: personaBlock["communication"]
70
+ ? {
71
+ tone: personaBlock["communication"]["tone"],
72
+ }
73
+ : undefined,
74
+ }
75
+ : undefined,
76
+ greeting_levels: greetingBlock,
77
+ };
78
+ agents.push(parsed);
79
+ // Validate agent block
80
+ if (!agentBlock) {
81
+ findings.push({
82
+ severity: "error",
83
+ category: CAT,
84
+ message: "Missing 'agent' block in frontmatter",
85
+ file,
86
+ });
87
+ }
88
+ else {
89
+ // agent.id
90
+ if (!agentBlock["id"]) {
91
+ findings.push({
92
+ severity: "error",
93
+ category: CAT,
94
+ message: "Missing 'agent.id'",
95
+ file,
96
+ });
97
+ }
98
+ else if (typeof agentBlock["id"] === "string" &&
99
+ !KEBAB_CASE.test(agentBlock["id"])) {
100
+ findings.push({
101
+ severity: "error",
102
+ category: CAT,
103
+ message: `'agent.id' must be kebab-case, got: "${agentBlock["id"]}"`,
104
+ file,
105
+ });
106
+ }
107
+ // agent.name
108
+ if (!agentBlock["name"]) {
109
+ findings.push({
110
+ severity: "error",
111
+ category: CAT,
112
+ message: "Missing 'agent.name'",
113
+ file,
114
+ });
115
+ }
116
+ // agent.title
117
+ if (!agentBlock["title"]) {
118
+ findings.push({
119
+ severity: "error",
120
+ category: CAT,
121
+ message: "Missing 'agent.title'",
122
+ file,
123
+ });
124
+ }
125
+ // agent.icon
126
+ if (!agentBlock["icon"]) {
127
+ findings.push({
128
+ severity: "warning",
129
+ category: CAT,
130
+ message: "Missing 'agent.icon'",
131
+ file,
132
+ });
133
+ }
134
+ // agent.whenToUse
135
+ if (!agentBlock["whenToUse"]) {
136
+ findings.push({
137
+ severity: "warning",
138
+ category: CAT,
139
+ message: "Missing 'agent.whenToUse'",
140
+ file,
141
+ });
142
+ }
143
+ }
144
+ // Validate persona_profile
145
+ if (!personaBlock) {
146
+ findings.push({
147
+ severity: "error",
148
+ category: CAT,
149
+ message: "Missing 'persona_profile' block in frontmatter",
150
+ file,
151
+ });
152
+ }
153
+ else {
154
+ // archetype
155
+ const archetype = personaBlock["archetype"];
156
+ if (!archetype) {
157
+ findings.push({
158
+ severity: "error",
159
+ category: CAT,
160
+ message: "Missing 'persona_profile.archetype'",
161
+ file,
162
+ });
163
+ }
164
+ else if (typeof archetype === "string" && !ARCHETYPES.has(archetype)) {
165
+ findings.push({
166
+ severity: "error",
167
+ category: CAT,
168
+ message: `'persona_profile.archetype' must be one of {${[...ARCHETYPES].join(", ")}}, got: "${archetype}"`,
169
+ file,
170
+ });
171
+ }
172
+ // communication.tone
173
+ const comm = personaBlock["communication"];
174
+ if (!comm || !comm["tone"]) {
175
+ findings.push({
176
+ severity: "warning",
177
+ category: CAT,
178
+ message: "Missing 'persona_profile.communication.tone'",
179
+ file,
180
+ });
181
+ }
182
+ else if (typeof comm["tone"] === "string" && !TONES.has(comm["tone"])) {
183
+ findings.push({
184
+ severity: "warning",
185
+ category: CAT,
186
+ message: `'persona_profile.communication.tone' has unknown value: "${comm["tone"]}"`,
187
+ file,
188
+ });
189
+ }
190
+ }
191
+ // Validate greeting_levels
192
+ if (!greetingBlock) {
193
+ findings.push({
194
+ severity: "warning",
195
+ category: CAT,
196
+ message: "Missing 'greeting_levels' block",
197
+ file,
198
+ });
199
+ }
200
+ else {
201
+ const keys = Object.keys(greetingBlock);
202
+ if (keys.length < 3) {
203
+ findings.push({
204
+ severity: "warning",
205
+ category: CAT,
206
+ message: `'greeting_levels' should have at least 3 keys, found ${keys.length}`,
207
+ file,
208
+ });
209
+ }
210
+ }
211
+ }
212
+ return { findings, agents };
213
+ }
214
+ //# sourceMappingURL=agents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/categories/agents.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ValidationFinding, ParsedAgent, ParsedTask, ParsedWorkflow } from "../types.js";
2
+ /**
3
+ * Category 6: Cross-reference validation
4
+ * Weight: 15%
5
+ *
6
+ * Validates:
7
+ * - task.responsavel references an existing agent.name
8
+ * - workflow.agent_sequence entries reference existing agent.id values
9
+ * - agent IDs are unique
10
+ * - task identifiers are unique
11
+ */
12
+ export declare function validateCrossReferences(agents: ParsedAgent[], tasks: ParsedTask[], workflows: ParsedWorkflow[]): ValidationFinding[];
13
+ //# sourceMappingURL=cross-refs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-refs.d.ts","sourceRoot":"","sources":["../../src/categories/cross-refs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACX,UAAU,EACV,cAAc,EACf,MAAM,aAAa,CAAC;AAIrB;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,WAAW,EAAE,EACrB,KAAK,EAAE,UAAU,EAAE,EACnB,SAAS,EAAE,cAAc,EAAE,GAC1B,iBAAiB,EAAE,CAoFrB"}
@@ -0,0 +1,88 @@
1
+ const CAT = "cross-refs";
2
+ /**
3
+ * Category 6: Cross-reference validation
4
+ * Weight: 15%
5
+ *
6
+ * Validates:
7
+ * - task.responsavel references an existing agent.name
8
+ * - workflow.agent_sequence entries reference existing agent.id values
9
+ * - agent IDs are unique
10
+ * - task identifiers are unique
11
+ */
12
+ export function validateCrossReferences(agents, tasks, workflows) {
13
+ const findings = [];
14
+ // Build lookup sets
15
+ const agentNames = new Set();
16
+ const agentIds = new Set();
17
+ const agentIdCounts = new Map();
18
+ const taskIdCounts = new Map();
19
+ // Collect agent names and IDs, check uniqueness
20
+ for (const agent of agents) {
21
+ if (agent.agent?.name) {
22
+ agentNames.add(agent.agent.name);
23
+ }
24
+ if (agent.agent?.id) {
25
+ agentIds.add(agent.agent.id);
26
+ const files = agentIdCounts.get(agent.agent.id) || [];
27
+ files.push(agent.file);
28
+ agentIdCounts.set(agent.agent.id, files);
29
+ }
30
+ }
31
+ // Check agent ID uniqueness
32
+ for (const [id, files] of agentIdCounts) {
33
+ if (files.length > 1) {
34
+ findings.push({
35
+ severity: "error",
36
+ category: CAT,
37
+ message: `Duplicate agent ID "${id}" found in: ${files.join(", ")}`,
38
+ });
39
+ }
40
+ }
41
+ // Collect task IDs and check uniqueness
42
+ for (const task of tasks) {
43
+ if (task.task) {
44
+ const files = taskIdCounts.get(task.task) || [];
45
+ files.push(task.file);
46
+ taskIdCounts.set(task.task, files);
47
+ }
48
+ }
49
+ for (const [id, files] of taskIdCounts) {
50
+ if (files.length > 1) {
51
+ findings.push({
52
+ severity: "error",
53
+ category: CAT,
54
+ message: `Duplicate task identifier "${id}" found in: ${files.join(", ")}`,
55
+ });
56
+ }
57
+ }
58
+ // Validate task.responsavel → agent.name
59
+ for (const task of tasks) {
60
+ if (task.responsavel && agentNames.size > 0) {
61
+ if (!agentNames.has(task.responsavel)) {
62
+ findings.push({
63
+ severity: "error",
64
+ category: CAT,
65
+ message: `Task references agent "${task.responsavel}" but no agent with that name exists`,
66
+ file: task.file,
67
+ });
68
+ }
69
+ }
70
+ }
71
+ // Validate workflow.agent_sequence → agent.id
72
+ for (const wf of workflows) {
73
+ if (wf.agent_sequence && Array.isArray(wf.agent_sequence) && agentIds.size > 0) {
74
+ for (const agentId of wf.agent_sequence) {
75
+ if (typeof agentId === "string" && !agentIds.has(agentId)) {
76
+ findings.push({
77
+ severity: "error",
78
+ category: CAT,
79
+ message: `Workflow "${wf.workflow_name || wf.file}" references agent ID "${agentId}" not found in agents/`,
80
+ file: wf.file,
81
+ });
82
+ }
83
+ }
84
+ }
85
+ }
86
+ return findings;
87
+ }
88
+ //# sourceMappingURL=cross-refs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-refs.js","sourceRoot":"","sources":["../../src/categories/cross-refs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { FileTree, ValidationFinding, ParsedManifest } from "../types.js";
2
+ /**
3
+ * Category 1: Manifest validation (squad.yaml)
4
+ * Weight: 25%
5
+ *
6
+ * Validates:
7
+ * - squad.yaml exists and is valid YAML
8
+ * - name (kebab-case)
9
+ * - version (semver)
10
+ * - description (non-empty)
11
+ * - aios.minVersion (semver string)
12
+ * - aios.type == "squad"
13
+ * - components.agents has at least 1 entry
14
+ */
15
+ export declare function validateManifest(fileTree: FileTree): {
16
+ findings: ValidationFinding[];
17
+ parsed: ParsedManifest | null;
18
+ };
19
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/categories/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAM/E;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,QAAQ,GACjB;IAAE,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAA;CAAE,CAuIlE"}
@@ -0,0 +1,150 @@
1
+ import { parseYaml, getNestedValue } from "../parser.js";
2
+ import { KEBAB_CASE, SEMVER } from "../utils/patterns.js";
3
+ const CAT = "manifest";
4
+ /**
5
+ * Category 1: Manifest validation (squad.yaml)
6
+ * Weight: 25%
7
+ *
8
+ * Validates:
9
+ * - squad.yaml exists and is valid YAML
10
+ * - name (kebab-case)
11
+ * - version (semver)
12
+ * - description (non-empty)
13
+ * - aios.minVersion (semver string)
14
+ * - aios.type == "squad"
15
+ * - components.agents has at least 1 entry
16
+ */
17
+ export function validateManifest(fileTree) {
18
+ const findings = [];
19
+ const content = fileTree.get("squad.yaml");
20
+ if (!content) {
21
+ findings.push({
22
+ severity: "error",
23
+ category: CAT,
24
+ message: "squad.yaml not found",
25
+ });
26
+ return { findings, parsed: null };
27
+ }
28
+ const parsed = parseYaml(content);
29
+ if (!parsed) {
30
+ findings.push({
31
+ severity: "error",
32
+ category: CAT,
33
+ message: "squad.yaml contains invalid YAML",
34
+ file: "squad.yaml",
35
+ });
36
+ return { findings, parsed: null };
37
+ }
38
+ // name
39
+ if (!parsed.name) {
40
+ findings.push({
41
+ severity: "error",
42
+ category: CAT,
43
+ message: "squad.yaml missing required field: name",
44
+ file: "squad.yaml",
45
+ });
46
+ }
47
+ else if (typeof parsed.name !== "string" || !KEBAB_CASE.test(parsed.name)) {
48
+ findings.push({
49
+ severity: "error",
50
+ category: CAT,
51
+ message: `squad.yaml 'name' must be kebab-case, got: "${parsed.name}"`,
52
+ file: "squad.yaml",
53
+ });
54
+ }
55
+ // version
56
+ if (!parsed.version) {
57
+ findings.push({
58
+ severity: "error",
59
+ category: CAT,
60
+ message: "squad.yaml missing required field: version",
61
+ file: "squad.yaml",
62
+ });
63
+ }
64
+ else if (typeof parsed.version !== "string" || !SEMVER.test(parsed.version)) {
65
+ findings.push({
66
+ severity: "error",
67
+ category: CAT,
68
+ message: `squad.yaml 'version' must be semver (X.Y.Z), got: "${parsed.version}"`,
69
+ file: "squad.yaml",
70
+ });
71
+ }
72
+ // description
73
+ if (!parsed.description) {
74
+ findings.push({
75
+ severity: "error",
76
+ category: CAT,
77
+ message: "squad.yaml missing required field: description",
78
+ file: "squad.yaml",
79
+ });
80
+ }
81
+ // aios block
82
+ const aios = parsed.aios;
83
+ if (!aios || typeof aios !== "object") {
84
+ findings.push({
85
+ severity: "error",
86
+ category: CAT,
87
+ message: "squad.yaml missing required field: aios",
88
+ file: "squad.yaml",
89
+ });
90
+ }
91
+ else {
92
+ const minVersion = getNestedValue(parsed, "aios.minVersion");
93
+ if (!minVersion) {
94
+ findings.push({
95
+ severity: "error",
96
+ category: CAT,
97
+ message: "squad.yaml missing required field: aios.minVersion",
98
+ file: "squad.yaml",
99
+ });
100
+ }
101
+ else if (typeof minVersion === "string" && !SEMVER.test(minVersion) && !/^\d+\.\d+\.\d+/.test(minVersion)) {
102
+ findings.push({
103
+ severity: "warning",
104
+ category: CAT,
105
+ message: `squad.yaml 'aios.minVersion' should be semver, got: "${minVersion}"`,
106
+ file: "squad.yaml",
107
+ });
108
+ }
109
+ const aiosType = getNestedValue(parsed, "aios.type");
110
+ if (!aiosType) {
111
+ findings.push({
112
+ severity: "error",
113
+ category: CAT,
114
+ message: "squad.yaml missing required field: aios.type",
115
+ file: "squad.yaml",
116
+ });
117
+ }
118
+ else if (aiosType !== "squad") {
119
+ findings.push({
120
+ severity: "error",
121
+ category: CAT,
122
+ message: `squad.yaml 'aios.type' must be "squad", got: "${aiosType}"`,
123
+ file: "squad.yaml",
124
+ });
125
+ }
126
+ }
127
+ // components.agents
128
+ const components = parsed.components;
129
+ if (!components || typeof components !== "object") {
130
+ findings.push({
131
+ severity: "warning",
132
+ category: CAT,
133
+ message: "squad.yaml missing 'components' block",
134
+ file: "squad.yaml",
135
+ });
136
+ }
137
+ else {
138
+ const agents = components.agents;
139
+ if (!agents || !Array.isArray(agents) || agents.length === 0) {
140
+ findings.push({
141
+ severity: "error",
142
+ category: CAT,
143
+ message: "squad.yaml 'components.agents' must list at least 1 agent",
144
+ file: "squad.yaml",
145
+ });
146
+ }
147
+ }
148
+ return { findings, parsed };
149
+ }
150
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/categories/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { FileTree, ValidationFinding, ParsedManifest } from "../types.js";
2
+ /**
3
+ * Category 2: Structure validation
4
+ * Weight: 15%
5
+ *
6
+ * Validates:
7
+ * - agents/ directory exists with at least 1 .md file
8
+ * - tasks/ directory exists (warning if missing)
9
+ * - workflows/ directory exists (warning if missing)
10
+ * - config/ directory exists (warning if missing)
11
+ * - Each file listed in components.* exists in the FileTree
12
+ */
13
+ export declare function validateStructure(fileTree: FileTree, manifest: ParsedManifest | null): ValidationFinding[];
14
+ //# sourceMappingURL=structure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../../src/categories/structure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAI/E;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,cAAc,GAAG,IAAI,GAC9B,iBAAiB,EAAE,CAoErB"}