@agent-facets/core 0.1.2 → 0.2.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.
@@ -2,7 +2,7 @@ import { type } from 'arktype'
2
2
 
3
3
  // --- Sub-schemas ---
4
4
 
5
- /** Skill descriptor — description is required, prompt resolved from skills/<name>.md */
5
+ /** Skill descriptor — description is required, prompt resolved from skills/<name>/SKILL.md */
6
6
  const SkillDescriptor = type({
7
7
  description: 'string',
8
8
  'platforms?': type.Record('string', 'unknown'),
@@ -37,9 +37,11 @@ const ServerReference = type('string').or({ image: 'string' })
37
37
  // --- Main schema ---
38
38
 
39
39
  /**
40
- * The structural schema for the facet manifest — validates shape only.
41
- * Custom constraints (at least one text asset, selective entry must select at least one type)
42
- * are checked post-validation by checkFacetManifestConstraints().
40
+ * The facet manifest schema — validates structure and business constraints.
41
+ *
42
+ * Structural validation covers field types and shapes. Narrow constraints enforce:
43
+ * 1. At least one text asset (skills, agents, commands, or facets) must be present
44
+ * 2. Selective facets entries must include at least one asset type selection
43
45
  */
44
46
  export const FacetManifestSchema = type({
45
47
  name: 'string',
@@ -51,63 +53,35 @@ export const FacetManifestSchema = type({
51
53
  'commands?': type.Record('string', CommandDescriptor),
52
54
  'facets?': FacetsEntry.array(),
53
55
  'servers?': type.Record('string', ServerReference),
54
- })
55
-
56
- /** Inferred TypeScript type for a validated facet manifest */
57
- export type FacetManifest = typeof FacetManifestSchema.infer
58
-
59
- // --- Custom validation ---
60
-
61
- export interface FacetManifestError {
62
- path: string
63
- message: string
64
- expected: string
65
- actual: string
66
- }
67
-
68
- /**
69
- * Checks business-rule constraints that ArkType's structural validation cannot express:
70
- * 1. At least one text asset must be present (skills, agents, commands, or facets)
71
- * 2. Selective facets entries must include at least one asset type
72
- */
73
- export function checkFacetManifestConstraints(manifest: FacetManifest): FacetManifestError[] {
74
- const errors: FacetManifestError[] = []
75
-
56
+ }).narrow((data, ctx) => {
76
57
  // Constraint 1: at least one text asset
77
- const hasSkills = manifest.skills && Object.keys(manifest.skills).length > 0
78
- const hasAgents = manifest.agents && Object.keys(manifest.agents).length > 0
79
- const hasCommands = manifest.commands && Object.keys(manifest.commands).length > 0
80
- const hasFacets = manifest.facets && manifest.facets.length > 0
58
+ const hasSkills = data.skills && Object.keys(data.skills).length > 0
59
+ const hasAgents = data.agents && Object.keys(data.agents).length > 0
60
+ const hasCommands = data.commands && Object.keys(data.commands).length > 0
61
+ const hasFacets = data.facets && data.facets.length > 0
81
62
 
82
63
  if (!hasSkills && !hasAgents && !hasCommands && !hasFacets) {
83
- errors.push({
84
- path: '',
85
- message: 'Manifest must include at least one text asset (skills, agents, commands, or facets)',
86
- expected: 'at least one of: skills, agents, commands, facets',
87
- actual: 'none present',
88
- })
64
+ ctx.mustBe('Manifest must include at least one text asset (skills, agents, commands, or facets)')
89
65
  }
90
66
 
91
67
  // Constraint 2: selective facets entries must select at least one asset type
92
- if (manifest.facets) {
93
- for (let i = 0; i < manifest.facets.length; i++) {
94
- const entry = manifest.facets[i]
68
+ if (data.facets) {
69
+ for (let i = 0; i < data.facets.length; i++) {
70
+ const entry = data.facets[i]
95
71
  if (typeof entry === 'object') {
96
72
  const hasSelectedSkills = entry.skills && entry.skills.length > 0
97
73
  const hasSelectedAgents = entry.agents && entry.agents.length > 0
98
74
  const hasSelectedCommands = entry.commands && entry.commands.length > 0
99
75
 
100
76
  if (!hasSelectedSkills && !hasSelectedAgents && !hasSelectedCommands) {
101
- errors.push({
102
- path: `facets[${i}]`,
103
- message: 'Selective facets entry must include at least one asset type (skills, agents, or commands)',
104
- expected: 'at least one of: skills, agents, commands',
105
- actual: 'none selected',
106
- })
77
+ ctx.mustBe('Selective facets entry must include at least one asset type (skills, agents, or commands)')
107
78
  }
108
79
  }
109
80
  }
110
81
  }
111
82
 
112
- return errors
113
- }
83
+ return true
84
+ })
85
+
86
+ /** Inferred TypeScript type for a validated facet manifest */
87
+ export type FacetManifest = typeof FacetManifestSchema.infer