happyskills 1.1.0 → 1.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.
- package/CHANGELOG.md +9 -0
- package/package.json +1 -1
- package/src/commands/access.js +41 -1
- package/src/commands/agents.js +30 -1
- package/src/commands/bump.js +33 -1
- package/src/commands/changelog.js +37 -1
- package/src/commands/check.js +30 -1
- package/src/commands/config.js +34 -1
- package/src/commands/convert.js +38 -1
- package/src/commands/delete.js +33 -1
- package/src/commands/diff.js +33 -1
- package/src/commands/disable.js +31 -1
- package/src/commands/enable.js +31 -1
- package/src/commands/feedback.js +41 -1
- package/src/commands/fork.js +35 -1
- package/src/commands/groups.js +40 -1
- package/src/commands/init.js +35 -1
- package/src/commands/install.js +35 -1
- package/src/commands/list.js +29 -1
- package/src/commands/login.js +34 -1
- package/src/commands/logout.js +20 -1
- package/src/commands/people.js +37 -1
- package/src/commands/postlex.js +38 -0
- package/src/commands/publish.js +40 -1
- package/src/commands/pull.js +47 -1
- package/src/commands/reconcile.js +36 -1
- package/src/commands/release.js +51 -1
- package/src/commands/schema.js +5 -0
- package/src/commands/search.js +46 -1
- package/src/commands/self-update.js +27 -1
- package/src/commands/setup.js +32 -1
- package/src/commands/snapshot.js +38 -1
- package/src/commands/status.js +26 -1
- package/src/commands/uninstall.js +30 -1
- package/src/commands/update.js +40 -1
- package/src/commands/validate.js +37 -1
- package/src/commands/versions.js +34 -1
- package/src/commands/visibility.js +33 -1
- package/src/commands/whoami.js +30 -1
- package/src/constants/error_codes.js +12 -1
- package/src/constants/next_step_actions.js +8 -0
- package/src/constants/next_step_by_error_code.js +5 -0
- package/src/integration/schema.test.js +31 -0
package/src/commands/install.js
CHANGED
|
@@ -260,4 +260,38 @@ const run = (args) => catch_errors('Install failed', async () => {
|
|
|
260
260
|
print_hint(`See what's installed: ${code('happyskills list')}`)
|
|
261
261
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
262
262
|
|
|
263
|
-
|
|
263
|
+
const schema = {
|
|
264
|
+
name: 'install',
|
|
265
|
+
audience: 'consumer',
|
|
266
|
+
purpose: 'Install one or more skills and their dependencies; without arguments installs all dependencies from skill.json or skills-lock.json.',
|
|
267
|
+
mutation: true,
|
|
268
|
+
interactive_in_text_mode: false,
|
|
269
|
+
input: {
|
|
270
|
+
positional: [ { name: 'skills', required: false, type: 'string[]', pattern: '<owner>/<name>[@<version>]' } ],
|
|
271
|
+
flags: [
|
|
272
|
+
{ name: 'global', alias: 'g', type: 'boolean', default: false, description: 'Install globally (~/.agents/skills/)' },
|
|
273
|
+
{ name: 'version', type: 'string', default: undefined, description: 'Pin to specific version (single skill only)' },
|
|
274
|
+
{ name: 'force', type: 'boolean', default: false, description: 'Force install on dependency conflicts' },
|
|
275
|
+
{ name: 'fresh', type: 'boolean', default: false, description: 'Ignore lock file, re-resolve from scratch' },
|
|
276
|
+
{ name: 'agents', type: 'string', default: undefined, description: 'Target specific agents (comma-separated)' },
|
|
277
|
+
{ name: 'yes', alias: 'y', type: 'boolean', default: false, description: 'Skip confirmation prompts' },
|
|
278
|
+
{ name: 'json', type: 'boolean', default: false, description: 'Output as JSON' },
|
|
279
|
+
],
|
|
280
|
+
},
|
|
281
|
+
output: {
|
|
282
|
+
data_shape: {
|
|
283
|
+
results: 'array<{ skill: string, status: string, version: string, installed: string[], skipped: string[], skipped_deps: string[], warnings: string[], forced: string[], snapshot_id?: string } | { skill: string, status: "failed", error: { code: string, message: string } }>',
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
errors: [
|
|
287
|
+
{ code: 'USAGE_ERROR', next_step: { kind: 'routing', action: 'discover_schema' } },
|
|
288
|
+
{ code: 'LOCAL_EDITS_PRESENT', next_step: { kind: 'confirmation', action: 'confirm_discard_or_snapshot_first' } },
|
|
289
|
+
{ code: 'VERSION_NOT_FOUND', next_step: { kind: 'decision', action: 'pick_version' } },
|
|
290
|
+
],
|
|
291
|
+
examples: [
|
|
292
|
+
'happyskills install acme/deploy-aws',
|
|
293
|
+
'happyskills install acme/deploy-aws@1.2.0 acme/monitor@latest',
|
|
294
|
+
],
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
module.exports = { run, schema }
|
package/src/commands/list.js
CHANGED
|
@@ -199,4 +199,32 @@ const run = (args) => catch_errors('List failed', async () => {
|
|
|
199
199
|
}
|
|
200
200
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
201
201
|
|
|
202
|
-
|
|
202
|
+
const schema = {
|
|
203
|
+
name: 'list',
|
|
204
|
+
audience: 'consumer',
|
|
205
|
+
purpose: 'List installed skills, showing version, source, drift/ahead status, and agent-enabled state.',
|
|
206
|
+
mutation: false,
|
|
207
|
+
interactive_in_text_mode: false,
|
|
208
|
+
input: {
|
|
209
|
+
positional: [],
|
|
210
|
+
flags: [
|
|
211
|
+
{ name: 'global', alias: 'g', type: 'boolean', default: false, description: 'List globally installed skills' },
|
|
212
|
+
{ name: 'json', type: 'boolean', default: false, description: 'Output as JSON' },
|
|
213
|
+
],
|
|
214
|
+
},
|
|
215
|
+
output: {
|
|
216
|
+
data_shape: {
|
|
217
|
+
skills: 'object<string, { version: string, type: string, source: string, status: string, enabled: boolean, drift?: object, ahead?: object }>',
|
|
218
|
+
drafts: 'array<{ name: string, description: string, version: string|null, type: string }>',
|
|
219
|
+
external: 'array<{ name: string, description: string }>',
|
|
220
|
+
agent_orphans: 'array<{ name: string, description: string, agents: string[] }>',
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
errors: [],
|
|
224
|
+
examples: [
|
|
225
|
+
'happyskills list',
|
|
226
|
+
'happyskills ls --json',
|
|
227
|
+
],
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
module.exports = { run, schema }
|
package/src/commands/login.js
CHANGED
|
@@ -218,4 +218,37 @@ const run = (args) => catch_errors('Login failed', async () => {
|
|
|
218
218
|
print_hint(`Verify your identity: ${code('happyskills whoami')}`)
|
|
219
219
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
220
220
|
|
|
221
|
-
|
|
221
|
+
const schema = {
|
|
222
|
+
name: 'login',
|
|
223
|
+
audience: 'account',
|
|
224
|
+
purpose: 'Authenticate with the HappySkills registry via browser (device flow) or password; returns current auth status when already logged in.',
|
|
225
|
+
mutation: true,
|
|
226
|
+
interactive_in_text_mode: true,
|
|
227
|
+
input: {
|
|
228
|
+
positional: [],
|
|
229
|
+
flags: [
|
|
230
|
+
{ name: 'browser', type: 'boolean', default: false },
|
|
231
|
+
{ name: 'password', type: 'boolean', default: false },
|
|
232
|
+
{ name: 'json', type: 'boolean', default: false },
|
|
233
|
+
],
|
|
234
|
+
},
|
|
235
|
+
output: {
|
|
236
|
+
data_shape: {
|
|
237
|
+
status: 'string',
|
|
238
|
+
username: 'string',
|
|
239
|
+
email: 'string',
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
errors: [
|
|
243
|
+
{ code: 'INTERACTIVE_REQUIRED' },
|
|
244
|
+
{ code: 'INVALID_CREDENTIALS' },
|
|
245
|
+
{ code: 'AUTH_FAILED', next_step: { kind: 'recovery', action: 'login' } },
|
|
246
|
+
{ code: 'NETWORK_ERROR', next_step: { kind: 'recovery', action: 'retry' } },
|
|
247
|
+
],
|
|
248
|
+
examples: [
|
|
249
|
+
'happyskills login',
|
|
250
|
+
'happyskills login --json --browser',
|
|
251
|
+
],
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
module.exports = { run, schema }
|
package/src/commands/logout.js
CHANGED
|
@@ -30,4 +30,23 @@ const run = (args) => catch_errors('Logout failed', async () => {
|
|
|
30
30
|
print_hint(`Log back in: ${code('happyskills login')}`)
|
|
31
31
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
const schema = {
|
|
34
|
+
name: 'logout',
|
|
35
|
+
audience: 'account',
|
|
36
|
+
purpose: 'Clear stored authentication credentials from disk.',
|
|
37
|
+
mutation: true,
|
|
38
|
+
interactive_in_text_mode: false,
|
|
39
|
+
input: {
|
|
40
|
+
positional: [],
|
|
41
|
+
flags: [
|
|
42
|
+
{ name: 'json', type: 'boolean', default: false }
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
output: { data_shape: { status: 'string' } },
|
|
46
|
+
errors: [],
|
|
47
|
+
examples: [
|
|
48
|
+
'happyskills logout'
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = { run, schema }
|
package/src/commands/people.js
CHANGED
|
@@ -159,4 +159,40 @@ const run = (args) => catch_errors('People command failed', async () => {
|
|
|
159
159
|
throw new UsageError(`Unknown subcommand: ${sub}. Run happyskills people --help`)
|
|
160
160
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
161
161
|
|
|
162
|
-
|
|
162
|
+
const schema = {
|
|
163
|
+
name: 'people',
|
|
164
|
+
audience: 'account',
|
|
165
|
+
purpose: 'Manage workspace membership: list, add, remove, change roles, and search users.',
|
|
166
|
+
mutation: true,
|
|
167
|
+
interactive_in_text_mode: true,
|
|
168
|
+
input: {
|
|
169
|
+
positional: [
|
|
170
|
+
{ name: 'subcommand', required: true, type: 'string', enum: ['list', 'add', 'remove', 'role', 'search'] }
|
|
171
|
+
],
|
|
172
|
+
flags: [
|
|
173
|
+
{ name: 'workspace', alias: 'w', type: 'string' },
|
|
174
|
+
{ name: 'role', type: 'string' },
|
|
175
|
+
{ name: 'limit', type: 'number' },
|
|
176
|
+
{ name: 'yes', alias: 'y', type: 'boolean' },
|
|
177
|
+
{ name: 'json', type: 'boolean' }
|
|
178
|
+
]
|
|
179
|
+
},
|
|
180
|
+
output: {
|
|
181
|
+
data_shape: {
|
|
182
|
+
results: 'array<{ username: string, email: string, role: string, created_at: string }>'
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
errors: [
|
|
186
|
+
{ code: 'AUTH_REQUIRED', next_step: { kind: 'recovery', action: 'login' } },
|
|
187
|
+
{ code: 'USAGE_ERROR', next_step: { kind: 'routing', action: 'discover_schema' } },
|
|
188
|
+
{ code: 'NOT_FOUND' },
|
|
189
|
+
{ code: 'FORBIDDEN' },
|
|
190
|
+
{ code: 'NETWORK_ERROR', next_step: { kind: 'recovery', action: 'retry' } }
|
|
191
|
+
],
|
|
192
|
+
examples: [
|
|
193
|
+
'happyskills people list -w acme',
|
|
194
|
+
'happyskills people add -w acme alice --role admin'
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
module.exports = { run, schema }
|
package/src/commands/postlex.js
CHANGED
|
@@ -518,8 +518,46 @@ const run = (args) => catch_errors('Postlex failed', async () => {
|
|
|
518
518
|
console.log(`\n${gray(`Showing ${final_ordering.length} result${final_ordering.length === 1 ? '' : 's'}.`)}\n`)
|
|
519
519
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
520
520
|
|
|
521
|
+
const schema = {
|
|
522
|
+
name: 'postlex',
|
|
523
|
+
audience: 'consumer',
|
|
524
|
+
purpose: 'Apply deterministic slug-overlap promotion to an LLM-emitted ranking and emit a next_step envelope; the finalization step of the rerank discovery protocol.',
|
|
525
|
+
mutation: false,
|
|
526
|
+
interactive_in_text_mode: false,
|
|
527
|
+
input: {
|
|
528
|
+
positional: [],
|
|
529
|
+
flags: [
|
|
530
|
+
{ name: 'query', type: 'string', required: true, description: 'The original search query (used for slug-overlap scoring)' },
|
|
531
|
+
{ name: 'ranking', type: 'string', required: true, description: 'Path to ranking JSON, or `-` for stdin' },
|
|
532
|
+
{ name: 'search-output', type: 'string', default: undefined, description: 'Path to full search --with-rerank --json response envelope (recommended)' },
|
|
533
|
+
{ name: 'data', type: 'string', default: undefined, description: 'Legacy: separate data file when --ranking does not embed it' },
|
|
534
|
+
{ name: 'clarification-turns-used', type: 'number', default: 0, description: 'Clarification budget already spent (0-2)' },
|
|
535
|
+
{ name: 'original-query', type: 'string', default: undefined, description: 'Original user query (opaque context from prior step)' },
|
|
536
|
+
{ name: 'json', type: 'boolean', default: false, description: 'Output as JSON' },
|
|
537
|
+
],
|
|
538
|
+
},
|
|
539
|
+
output: {
|
|
540
|
+
data_shape: {
|
|
541
|
+
final_ordering: 'array<{ rank: number, candidate_id: number, slug: string, name: string, workspace_slug: string|null, description: string, version: string, match_quality: string|null, quality_score: number|null, star_count: number, rationale: string }>',
|
|
542
|
+
postlex_promoted: 'boolean',
|
|
543
|
+
promoted_from_rank: 'number|null',
|
|
544
|
+
exact_match_count_in_window: 'number',
|
|
545
|
+
formulated_query: 'string',
|
|
546
|
+
},
|
|
547
|
+
},
|
|
548
|
+
errors: [
|
|
549
|
+
{ code: 'USAGE_ERROR', next_step: { kind: 'routing', action: 'discover_schema' } },
|
|
550
|
+
{ code: 'RANKING_SCHEMA_MISMATCH', next_step: { kind: 'recovery', action: 'retry_rank' } },
|
|
551
|
+
],
|
|
552
|
+
examples: [
|
|
553
|
+
'happyskills postlex --query "deploy aws" --ranking - --search-output /tmp/search-out.json',
|
|
554
|
+
'happyskills postlex --query "deploy aws" --ranking r.json --data d.json --json',
|
|
555
|
+
],
|
|
556
|
+
}
|
|
557
|
+
|
|
521
558
|
module.exports = {
|
|
522
559
|
run,
|
|
560
|
+
schema,
|
|
523
561
|
// Exported for unit testing — pure functions only.
|
|
524
562
|
validate_ranking,
|
|
525
563
|
apply_postlex,
|
package/src/commands/publish.js
CHANGED
|
@@ -339,4 +339,43 @@ const run = (args) => catch_errors('Publish failed', async () => {
|
|
|
339
339
|
print_hint(`Check versions: ${code('happyskills check')}`)
|
|
340
340
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
341
341
|
|
|
342
|
-
|
|
342
|
+
const schema = {
|
|
343
|
+
name: 'publish',
|
|
344
|
+
audience: 'author',
|
|
345
|
+
purpose: 'Push a skill to the registry, resolving the owner workspace from skills-lock.json; optionally bumps the version before publishing.',
|
|
346
|
+
mutation: true,
|
|
347
|
+
interactive_in_text_mode: false,
|
|
348
|
+
input: {
|
|
349
|
+
positional: [ { name: 'skill', required: true, type: 'string', description: 'Name of the installed skill' } ],
|
|
350
|
+
flags: [
|
|
351
|
+
{ name: 'bump', type: 'string', default: undefined, description: 'Auto-bump version before publishing (patch, minor, major)' },
|
|
352
|
+
{ name: 'workspace', type: 'string', default: undefined, description: 'Target workspace (overrides lock file owner)' },
|
|
353
|
+
{ name: 'public', type: 'boolean', default: false, description: 'Publish as public (default is private)' },
|
|
354
|
+
{ name: 'force', type: 'boolean', default: false, description: 'Bypass divergence check (may overwrite remote changes)' },
|
|
355
|
+
{ name: 'json', type: 'boolean', default: false, description: 'Output as JSON' },
|
|
356
|
+
],
|
|
357
|
+
},
|
|
358
|
+
output: {
|
|
359
|
+
data_shape: {
|
|
360
|
+
skill: 'string',
|
|
361
|
+
version: 'string',
|
|
362
|
+
ref: 'string',
|
|
363
|
+
commit: 'string | null',
|
|
364
|
+
bumped_from: 'string | null',
|
|
365
|
+
warnings: 'string[] | undefined',
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
errors: [
|
|
369
|
+
{ code: 'AUTH_REQUIRED', next_step: { kind: 'recovery', action: 'login' } },
|
|
370
|
+
{ code: 'VALIDATION_FAILED', next_step: { kind: 'recovery', action: 'fix_validation_errors' } },
|
|
371
|
+
{ code: 'DEPENDENCY_VALIDATION_FAILED', next_step: { kind: 'recovery', action: 'fix_validation_errors' } },
|
|
372
|
+
{ code: 'USAGE_ERROR', next_step: { kind: 'routing', action: 'discover_schema' } },
|
|
373
|
+
{ code: 'NETWORK_ERROR', next_step: { kind: 'recovery', action: 'retry' } },
|
|
374
|
+
],
|
|
375
|
+
examples: [
|
|
376
|
+
'happyskills publish my-skill',
|
|
377
|
+
'happyskills publish deploy-aws --bump patch',
|
|
378
|
+
],
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
module.exports = { run, schema }
|
package/src/commands/pull.js
CHANGED
|
@@ -611,4 +611,50 @@ const reconcile_dependencies = (skill_dir, skill_name, lock_data, is_global, pro
|
|
|
611
611
|
}
|
|
612
612
|
})
|
|
613
613
|
|
|
614
|
-
|
|
614
|
+
const schema = {
|
|
615
|
+
name: 'pull',
|
|
616
|
+
audience: 'consumer',
|
|
617
|
+
purpose: 'Pull remote changes for an installed skill and merge with local files, with optional rebase or conflict-resolution strategies.',
|
|
618
|
+
mutation: true,
|
|
619
|
+
interactive_in_text_mode: false,
|
|
620
|
+
input: {
|
|
621
|
+
positional: [{ name: 'skill', required: true, type: 'string', pattern: '<owner>/<name>' }],
|
|
622
|
+
flags: [
|
|
623
|
+
{ name: 'theirs', type: 'string|boolean', default: false },
|
|
624
|
+
{ name: 'ours', type: 'string|boolean', default: false },
|
|
625
|
+
{ name: 'force', type: 'boolean', default: false },
|
|
626
|
+
{ name: 'rebase', type: 'boolean', default: false },
|
|
627
|
+
{ name: 'global', type: 'boolean', default: false },
|
|
628
|
+
{ name: 'strict', type: 'boolean', default: false },
|
|
629
|
+
{ name: 'json', type: 'boolean', default: false },
|
|
630
|
+
{ name: 'full-report', type: 'boolean', default: false }
|
|
631
|
+
]
|
|
632
|
+
},
|
|
633
|
+
output: {
|
|
634
|
+
data_shape: {
|
|
635
|
+
status: 'string',
|
|
636
|
+
skill: 'string',
|
|
637
|
+
version: 'string|null',
|
|
638
|
+
report: 'object',
|
|
639
|
+
conflict_files: 'array<string>',
|
|
640
|
+
json_conflicts: 'array<object>',
|
|
641
|
+
drift: 'object|null',
|
|
642
|
+
resolution_steps: 'array|null'
|
|
643
|
+
}
|
|
644
|
+
},
|
|
645
|
+
errors: [
|
|
646
|
+
{ code: 'USAGE_ERROR', next_step: { kind: 'routing', action: 'discover_schema' } },
|
|
647
|
+
// --rebase pipeline failures — recover by retrying or abandoning to the snapshot
|
|
648
|
+
{ code: 'COMPARE_FAILED', next_step: { kind: 'recovery', action: 'retry_or_abandon' } },
|
|
649
|
+
{ code: 'CLONE_BASE_FAILED', next_step: { kind: 'recovery', action: 'retry_or_abandon' } },
|
|
650
|
+
{ code: 'CLONE_REMOTE_FAILED', next_step: { kind: 'recovery', action: 'retry_or_abandon' } },
|
|
651
|
+
{ code: 'READ_LOCAL_FAILED', next_step: { kind: 'recovery', action: 'retry_or_abandon' } },
|
|
652
|
+
{ code: 'SWAP_FAILED', next_step: { kind: 'recovery', action: 'retry_or_abandon' } }
|
|
653
|
+
],
|
|
654
|
+
examples: [
|
|
655
|
+
'happyskills pull acme/deploy-aws',
|
|
656
|
+
'happyskills pull acme/deploy-aws --rebase --json'
|
|
657
|
+
]
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
module.exports = { run, schema }
|
|
@@ -274,4 +274,39 @@ const run = (args) => catch_errors('Reconcile failed', async () => {
|
|
|
274
274
|
}
|
|
275
275
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
276
276
|
|
|
277
|
-
|
|
277
|
+
const schema = {
|
|
278
|
+
name: 'reconcile',
|
|
279
|
+
audience: 'consumer',
|
|
280
|
+
purpose: 'Diagnose and repair genuine drift between the lock file and disk (regression, missing files, or unparseable skill.json); the ahead state is not drift and is reported as a non-event.',
|
|
281
|
+
mutation: true,
|
|
282
|
+
interactive_in_text_mode: false,
|
|
283
|
+
input: {
|
|
284
|
+
positional: [ { name: 'skill', required: true, type: 'string', pattern: '<owner>/<name>' } ],
|
|
285
|
+
flags: [
|
|
286
|
+
{ name: 'apply', type: 'string', default: undefined, description: 'Execute one of the recommended options directly (skips the next_step round-trip)' },
|
|
287
|
+
{ name: 'global', alias: 'g', type: 'boolean', default: false, description: 'Operate on globally-installed skills' },
|
|
288
|
+
{ name: 'json', type: 'boolean', default: false, description: 'Output as JSON' },
|
|
289
|
+
],
|
|
290
|
+
},
|
|
291
|
+
output: {
|
|
292
|
+
data_shape: {
|
|
293
|
+
skill: 'string',
|
|
294
|
+
no_drift: 'boolean',
|
|
295
|
+
status: 'string',
|
|
296
|
+
drift_state: 'string',
|
|
297
|
+
applied: '{ applied: string, new_disk_version: string } | undefined',
|
|
298
|
+
lock_version: 'string | undefined',
|
|
299
|
+
disk_version: 'string | undefined',
|
|
300
|
+
ahead: '{ lock_version: string, disk_version: string, has_changelog_entry: boolean, changelog_version: string | null } | undefined',
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
errors: [
|
|
304
|
+
{ code: 'USAGE_ERROR', next_step: { kind: 'routing', action: 'discover_schema' } },
|
|
305
|
+
],
|
|
306
|
+
examples: [
|
|
307
|
+
'happyskills reconcile acme/deploy-aws --json',
|
|
308
|
+
'happyskills reconcile acme/deploy-aws --apply restore_from_lock_version --json',
|
|
309
|
+
],
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
module.exports = { run, reconcile_one, SUBTYPE_OPTIONS, ACTION_NEXT_STEPS, schema }
|
package/src/commands/release.js
CHANGED
|
@@ -481,4 +481,54 @@ const run = (args) => catch_errors('Release wrapper failed', async () => {
|
|
|
481
481
|
}
|
|
482
482
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
483
483
|
|
|
484
|
-
|
|
484
|
+
const schema = {
|
|
485
|
+
name: 'release',
|
|
486
|
+
audience: 'author',
|
|
487
|
+
purpose: 'Atomic release pipeline: snapshot, validate, bump version, verify CHANGELOG, and publish in one deterministic command; restores the snapshot on any failure.',
|
|
488
|
+
mutation: true,
|
|
489
|
+
interactive_in_text_mode: false,
|
|
490
|
+
input: {
|
|
491
|
+
positional: [ { name: 'skill', required: true, type: 'string', description: 'Name of the skill to release' } ],
|
|
492
|
+
flags: [
|
|
493
|
+
{ name: 'bump', type: 'string', default: undefined, description: 'patch | minor | major | explicit semver' },
|
|
494
|
+
{ name: 'no-bump', type: 'boolean', default: false, description: 'Refuse to bump; require disk to already be ahead' },
|
|
495
|
+
{ name: 'changelog-from', type: 'string', default: undefined, description: 'Source for the new CHANGELOG entry (auto or file path)' },
|
|
496
|
+
{ name: 'workspace', type: 'string', default: undefined, description: 'Target workspace slug' },
|
|
497
|
+
{ name: 'public', type: 'boolean', default: false, description: 'Publish as public on first publish' },
|
|
498
|
+
{ name: 'dry-run', type: 'boolean', default: false, description: 'Validate and check status without mutating' },
|
|
499
|
+
{ name: 'json', type: 'boolean', default: false, description: 'Output as JSON' },
|
|
500
|
+
],
|
|
501
|
+
},
|
|
502
|
+
output: {
|
|
503
|
+
data_shape: {
|
|
504
|
+
published: 'boolean',
|
|
505
|
+
skill: 'string',
|
|
506
|
+
version: 'string',
|
|
507
|
+
workspace: 'string',
|
|
508
|
+
commit: 'string | null',
|
|
509
|
+
ref: 'string',
|
|
510
|
+
ahead_recognized: 'boolean',
|
|
511
|
+
bump_applied: 'boolean',
|
|
512
|
+
warnings: 'string[]',
|
|
513
|
+
snapshot_id_preserved: 'boolean',
|
|
514
|
+
},
|
|
515
|
+
},
|
|
516
|
+
errors: [
|
|
517
|
+
{ code: 'VALIDATION_FAILED', next_step: { kind: 'recovery', action: 'fix_validation_errors' } },
|
|
518
|
+
{ code: 'DRIFT_DETECTED', next_step: { kind: 'recovery', action: 'reconcile_first' } },
|
|
519
|
+
{ code: 'MISSING_VERSION', next_step: { kind: 'decision', action: 'specify_bump_type' } },
|
|
520
|
+
{ code: 'INVALID_BUMP', next_step: { kind: 'decision', action: 'specify_bump_type' } },
|
|
521
|
+
{ code: 'BUMP_DISAGREEMENT', next_step: { kind: 'decision', action: 'resolve_bump_disagreement' } },
|
|
522
|
+
{ code: 'CHANGELOG_SOURCE_UNREADABLE', next_step: { kind: 'recovery', action: 'provide_changelog' } },
|
|
523
|
+
{ code: 'MISSING_CHANGELOG_ENTRY', next_step: { kind: 'recovery', action: 'provide_changelog' } },
|
|
524
|
+
{ code: 'WORKSPACE_UNRESOLVED', next_step: { kind: 'decision', action: 'specify_workspace' } },
|
|
525
|
+
{ code: 'WRITE_FAILED', next_step: { kind: 'recovery', action: 'retry' } },
|
|
526
|
+
{ code: 'PUBLISH_FAILED', next_step: { kind: 'recovery', action: 'review_publish_error' } },
|
|
527
|
+
],
|
|
528
|
+
examples: [
|
|
529
|
+
'happyskills release my-skill --workspace acme --json',
|
|
530
|
+
'happyskills release my-skill --bump patch --workspace acme --json',
|
|
531
|
+
],
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
module.exports = { run, orchestrate, determine_target_version, compute_bump, schema }
|
package/src/commands/schema.js
CHANGED
|
@@ -84,6 +84,7 @@ const default_schema = (name) => ({
|
|
|
84
84
|
input: { positional: [], flags: [] },
|
|
85
85
|
output: { data_shape: {} },
|
|
86
86
|
errors: [],
|
|
87
|
+
examples: [],
|
|
87
88
|
})
|
|
88
89
|
|
|
89
90
|
// Load the per-command schema export. Misses fall back to default_schema.
|
|
@@ -174,6 +175,10 @@ const schema = {
|
|
|
174
175
|
next_step_kinds: 'array<string>',
|
|
175
176
|
} },
|
|
176
177
|
errors: [],
|
|
178
|
+
examples: [
|
|
179
|
+
'happyskills schema --json',
|
|
180
|
+
'happyskills schema --text',
|
|
181
|
+
],
|
|
177
182
|
}
|
|
178
183
|
|
|
179
184
|
module.exports = { run, schema, build_schema_payload }
|
package/src/commands/search.js
CHANGED
|
@@ -435,4 +435,49 @@ const run = (args) => catch_errors('Search failed', async () => {
|
|
|
435
435
|
}
|
|
436
436
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
437
437
|
|
|
438
|
-
|
|
438
|
+
const schema = {
|
|
439
|
+
name: 'search',
|
|
440
|
+
audience: 'consumer',
|
|
441
|
+
purpose: 'Search the skill registry using smart semantic dispatch (natural-language, fuzzy-slug, or fuzzy-scoped); use --with-rerank to get the rerank-protocol envelope for agentic discovery.',
|
|
442
|
+
mutation: false,
|
|
443
|
+
interactive_in_text_mode: false,
|
|
444
|
+
input: {
|
|
445
|
+
positional: [ { name: 'query', required: false, type: 'string', description: 'Search term (optional with --mine/--personal/--workspace)' } ],
|
|
446
|
+
flags: [
|
|
447
|
+
{ name: 'workspace', alias: 'w', type: 'string', default: undefined, description: 'Search within specific workspace(s) (comma-separated)' },
|
|
448
|
+
{ name: 'mine', type: 'boolean', default: false, description: 'Search across all your workspaces' },
|
|
449
|
+
{ name: 'personal', type: 'boolean', default: false, description: 'Search only your personal workspace' },
|
|
450
|
+
{ name: 'tags', type: 'string', default: undefined, description: 'Filter by tags (comma-separated)' },
|
|
451
|
+
{ name: 'type', type: 'string', default: undefined, description: 'Filter by type: skill, kit' },
|
|
452
|
+
{ name: 'exact', type: 'boolean', default: false, description: 'Force keyword-only FTS matching' },
|
|
453
|
+
{ name: 'with-rerank', type: 'boolean', default: false, description: 'Include rerank digests + next_step envelope (agentic discovery protocol)' },
|
|
454
|
+
{ name: 'clarification-turns-used', type: 'number', default: 0, description: 'Clarification budget already spent (0-2)' },
|
|
455
|
+
{ name: 'limit', type: 'number', required: true, description: 'Max results (1-50)' },
|
|
456
|
+
{ name: 'min-quality', type: 'number', default: undefined, description: 'Minimum quality score 0-100' },
|
|
457
|
+
{ name: 'json', type: 'boolean', default: false, description: 'Output as JSON' },
|
|
458
|
+
],
|
|
459
|
+
},
|
|
460
|
+
output: {
|
|
461
|
+
data_shape: {
|
|
462
|
+
query: 'string',
|
|
463
|
+
formulated_query: 'string',
|
|
464
|
+
mode: 'string',
|
|
465
|
+
results: 'array<{ skill: string, name: string, type: string, description: string, version: string, visibility: string, workspace_slug: string, stars: number, quality_score: number|null, quality_tier: string|null, relevance_score: number|null, match_quality: string|null, tags: string[], download_count: number, created_at: string, updated_at: string, similar_count: number, similar_repos: array }>',
|
|
466
|
+
count: 'number',
|
|
467
|
+
rerank_digests: 'array (present when --with-rerank)',
|
|
468
|
+
rerank_system_prompt: 'string|null (present when --with-rerank)',
|
|
469
|
+
rerank_response_schema: 'object|null (present when --with-rerank)',
|
|
470
|
+
},
|
|
471
|
+
},
|
|
472
|
+
errors: [
|
|
473
|
+
{ code: 'USAGE_ERROR', next_step: { kind: 'routing', action: 'discover_schema' } },
|
|
474
|
+
{ code: 'AUTH_REQUIRED', next_step: { kind: 'recovery', action: 'login' } },
|
|
475
|
+
{ code: 'NETWORK_ERROR', next_step: { kind: 'recovery', action: 'retry' } },
|
|
476
|
+
],
|
|
477
|
+
examples: [
|
|
478
|
+
'happyskills search "deploy infra to AWS" --limit 10',
|
|
479
|
+
'happyskills search "deploy infra to AWS" --with-rerank --json --limit 50',
|
|
480
|
+
],
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
module.exports = { run, build_search_next_step, schema }
|
|
@@ -80,4 +80,30 @@ const run = (args) => catch_errors('Self-update failed', async () => {
|
|
|
80
80
|
print_hint(`Run ${code('happyskills --version')} to confirm.`)
|
|
81
81
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
const schema = {
|
|
84
|
+
name: 'self-update',
|
|
85
|
+
audience: 'account',
|
|
86
|
+
purpose: 'Upgrade the happyskills CLI to the latest version published on npm.',
|
|
87
|
+
mutation: true,
|
|
88
|
+
interactive_in_text_mode: false,
|
|
89
|
+
input: {
|
|
90
|
+
positional: [],
|
|
91
|
+
flags: [
|
|
92
|
+
{ name: 'json', type: 'boolean', default: false }
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
output: {
|
|
96
|
+
data_shape: {
|
|
97
|
+
status: 'string',
|
|
98
|
+
version: 'string'
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
errors: [
|
|
102
|
+
{ code: 'NETWORK_ERROR', next_step: { kind: 'recovery', action: 'retry' } }
|
|
103
|
+
],
|
|
104
|
+
examples: [
|
|
105
|
+
'happyskills self-update'
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports = { run, schema }
|
package/src/commands/setup.js
CHANGED
|
@@ -55,4 +55,35 @@ const run = (args) => catch_errors('Setup failed', async () => {
|
|
|
55
55
|
}
|
|
56
56
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
const schema = {
|
|
59
|
+
name: 'setup',
|
|
60
|
+
audience: 'account',
|
|
61
|
+
purpose: 'Install (or update) the official HappySkills CLI skill into the local or global agent skills directory.',
|
|
62
|
+
mutation: true,
|
|
63
|
+
interactive_in_text_mode: false,
|
|
64
|
+
input: {
|
|
65
|
+
positional: [],
|
|
66
|
+
flags: [
|
|
67
|
+
{ name: 'global', type: 'boolean', default: false },
|
|
68
|
+
{ name: 'agents', type: 'string', default: null },
|
|
69
|
+
{ name: 'json', type: 'boolean', default: false }
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
output: {
|
|
73
|
+
data_shape: {
|
|
74
|
+
skill: 'string',
|
|
75
|
+
version: 'string',
|
|
76
|
+
status: 'string'
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
errors: [
|
|
80
|
+
{ code: 'NETWORK_ERROR', next_step: { kind: 'recovery', action: 'retry' } },
|
|
81
|
+
{ code: 'REGISTRY_UNAVAILABLE', next_step: { kind: 'recovery', action: 'retry' } }
|
|
82
|
+
],
|
|
83
|
+
examples: [
|
|
84
|
+
'happyskills setup',
|
|
85
|
+
'happyskills setup -g'
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
module.exports = { run, schema }
|
package/src/commands/snapshot.js
CHANGED
|
@@ -249,4 +249,41 @@ const run = (args) => catch_errors('Snapshot failed', async () => {
|
|
|
249
249
|
if (err) throw err
|
|
250
250
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
251
251
|
|
|
252
|
-
|
|
252
|
+
const schema = {
|
|
253
|
+
name: 'snapshot',
|
|
254
|
+
audience: 'consumer',
|
|
255
|
+
purpose: 'Capture and restore skill state — create, list, restore, delete, or prune snapshots as a safety net for every mutation.',
|
|
256
|
+
mutation: true,
|
|
257
|
+
interactive_in_text_mode: false,
|
|
258
|
+
input: {
|
|
259
|
+
positional: [
|
|
260
|
+
{ name: 'subcommand', required: true, type: 'string', enum: ['create', 'list', 'restore', 'delete', 'prune'] },
|
|
261
|
+
{ name: 'target', required: true, type: 'string', description: '<owner/skill> for create/list/prune; <snapshot-id> for restore/delete' },
|
|
262
|
+
],
|
|
263
|
+
flags: [
|
|
264
|
+
{ name: 'note', type: 'string', default: undefined, description: 'Attach a note to a new snapshot (create only)' },
|
|
265
|
+
{ name: 'keep', type: 'number', default: 10, description: 'Retention count for prune' },
|
|
266
|
+
{ name: 'global', alias: 'g', type: 'boolean', default: false, description: 'Operate on the global snapshot store' },
|
|
267
|
+
{ name: 'json', type: 'boolean', default: false, description: 'Output as JSON' },
|
|
268
|
+
],
|
|
269
|
+
},
|
|
270
|
+
output: {
|
|
271
|
+
data_shape: {
|
|
272
|
+
'create': '{ snapshot_id: string, path: string, note?: string, pruned?: string[] }',
|
|
273
|
+
'list': '{ workspace: string, skill: string, snapshots: array<{ snapshot_id: string, timestamp: string, note: string }> }',
|
|
274
|
+
'restore': '{ workspace: string, skill: string, snapshot_id: string }',
|
|
275
|
+
'delete': '{ deleted: boolean, snapshot_id: string, reason?: string }',
|
|
276
|
+
'prune': '{ kept: number, deleted: number }',
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
errors: [
|
|
280
|
+
{ code: 'USAGE_ERROR', next_step: { kind: 'routing', action: 'discover_schema' } },
|
|
281
|
+
{ code: 'SNAPSHOT_FAILED' },
|
|
282
|
+
],
|
|
283
|
+
examples: [
|
|
284
|
+
'happyskills snapshot create acme/deploy-aws --note "pre-release" --json',
|
|
285
|
+
'happyskills snapshot restore snap_20260523T103045Z_abc123 --json',
|
|
286
|
+
],
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
module.exports = { run, schema }
|
package/src/commands/status.js
CHANGED
|
@@ -224,4 +224,29 @@ const run = (args) => catch_errors('Status failed', async () => {
|
|
|
224
224
|
}
|
|
225
225
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
226
226
|
|
|
227
|
-
|
|
227
|
+
const schema = {
|
|
228
|
+
name: 'status',
|
|
229
|
+
audience: 'consumer',
|
|
230
|
+
purpose: 'Show divergence status for installed skills — drift, ahead, modified, outdated, conflicts, or clean.',
|
|
231
|
+
mutation: false,
|
|
232
|
+
interactive_in_text_mode: false,
|
|
233
|
+
input: {
|
|
234
|
+
positional: [{ name: 'skill', required: false, type: 'string', pattern: '<owner>/<name>' }],
|
|
235
|
+
flags: [
|
|
236
|
+
{ name: 'global', type: 'boolean', default: false },
|
|
237
|
+
{ name: 'json', type: 'boolean', default: false }
|
|
238
|
+
]
|
|
239
|
+
},
|
|
240
|
+
output: {
|
|
241
|
+
data_shape: {
|
|
242
|
+
results: 'array<{ skill: string, base_version: string|null, base_commit: string|null, local_modified: boolean, modified_files: array|null, remote_updated: boolean, remote_version: string|null, remote_commit: string|null, conflict_files: array, drift: object|null, ahead: object|null, status: string }>'
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
errors: [],
|
|
246
|
+
examples: [
|
|
247
|
+
'happyskills status',
|
|
248
|
+
'happyskills status acme/deploy-aws'
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
module.exports = { run, schema }
|