happyskills 1.2.1 → 1.2.2

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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.2] - 2026-06-02
11
+
12
+ ### Changed
13
+
14
+ - `validate` no longer warns when `skill.json` `keywords` is missing or omits a canonical slug. The `keywords` field is deprecated — it is not used for search, ranking, or discovery — so the warning and the canonical-slug check were removed. The field is still accepted in the manifest.
15
+
10
16
  ## [1.2.1] - 2026-06-02
11
17
 
12
18
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "happyskills",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "Package manager for AI agent skills",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Nicolas Dao <nic@cloudlesslabs.com> (https://cloudlesslabs.com)",
@@ -6,7 +6,6 @@ const { SKILL_JSON, VALID_SKILL_TYPES, SKILL_TYPES, KIT_PREFIX } = require('../c
6
6
 
7
7
  const NAME_PATTERN = /^[a-z0-9][a-z0-9_-]*$/
8
8
  const KIT_NAME_PATTERN = /^_kit-[a-z0-9][a-z0-9-]*$/
9
- const CANONICAL_SLUGS = ['deployment', 'database', 'security', 'ai', 'api', 'monitoring', 'testing', 'devops', 'cloud', 'analytics']
10
9
  const REQUIRED_PLATFORMS = ['darwin', 'linux', 'win32']
11
10
 
12
11
  const result = (field, rule, severity, message, value) => ({
@@ -90,27 +89,6 @@ const validate_description = (manifest) => {
90
89
  return results
91
90
  }
92
91
 
93
- const validate_keywords = (manifest) => {
94
- const results = []
95
- const kw = manifest.keywords
96
-
97
- if (!kw || !Array.isArray(kw)) {
98
- results.push(result('keywords', 'recommended_field', 'warning', 'Keywords array is recommended — include at least one canonical slug'))
99
- return results
100
- }
101
-
102
- results.push(result('keywords', 'recommended_field', 'pass', `keywords: ${kw.length} entries`))
103
-
104
- const has_slug = kw.some(k => CANONICAL_SLUGS.includes(k))
105
- if (!has_slug) {
106
- results.push(result('keywords', 'canonical_slug', 'warning', `Keywords should include at least one canonical slug: ${CANONICAL_SLUGS.join(', ')}`))
107
- } else {
108
- results.push(result('keywords', 'canonical_slug', 'pass', 'Contains canonical slug'))
109
- }
110
-
111
- return results
112
- }
113
-
114
92
  const validate_type = (manifest) => {
115
93
  const results = []
116
94
  const type = manifest.type
@@ -229,7 +207,6 @@ const validate_skill_json = (skill_dir) => catch_errors('Failed to validate skil
229
207
  results.push(...validate_version(manifest))
230
208
  results.push(...validate_type(manifest))
231
209
  results.push(...validate_description(manifest))
232
- results.push(...validate_keywords(manifest))
233
210
  results.push(...validate_dependencies(manifest))
234
211
  results.push(...validate_system_dependencies(manifest))
235
212
 
@@ -121,32 +121,6 @@ describe('validate_skill_json — description', () => {
121
121
  })
122
122
  })
123
123
 
124
- describe('validate_skill_json — keywords', () => {
125
- it('warns when keywords are missing', async () => {
126
- write_json(tmp, { name: 'my-skill', version: '1.0.0' })
127
- const [err, data] = await validate_skill_json(tmp)
128
- assert.ifError(err)
129
- const check = data.results.find(r => r.field === 'keywords' && r.rule === 'recommended_field')
130
- assert.strictEqual(check.severity, 'warning')
131
- })
132
-
133
- it('warns when no canonical slug is present', async () => {
134
- write_json(tmp, { name: 'my-skill', version: '1.0.0', keywords: ['custom'] })
135
- const [err, data] = await validate_skill_json(tmp)
136
- assert.ifError(err)
137
- const check = data.results.find(r => r.rule === 'canonical_slug')
138
- assert.strictEqual(check.severity, 'warning')
139
- })
140
-
141
- it('passes when a canonical slug is present', async () => {
142
- write_json(tmp, { name: 'my-skill', version: '1.0.0', keywords: ['deployment', 'custom'] })
143
- const [err, data] = await validate_skill_json(tmp)
144
- assert.ifError(err)
145
- const check = data.results.find(r => r.rule === 'canonical_slug')
146
- assert.strictEqual(check.severity, 'pass')
147
- })
148
- })
149
-
150
124
  describe('validate_skill_json — dependencies', () => {
151
125
  it('errors when dependencies is an array', async () => {
152
126
  write_json(tmp, { name: 'my-skill', version: '1.0.0', dependencies: ['acme/deploy'] })