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
|
@@ -93,4 +93,33 @@ const run = (args) => catch_errors('Uninstall failed', async () => {
|
|
|
93
93
|
}
|
|
94
94
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
const schema = {
|
|
97
|
+
name: 'uninstall',
|
|
98
|
+
audience: 'consumer',
|
|
99
|
+
purpose: 'Remove one or more skills and prune their orphaned dependencies.',
|
|
100
|
+
mutation: true,
|
|
101
|
+
interactive_in_text_mode: false,
|
|
102
|
+
input: {
|
|
103
|
+
positional: [ { name: 'skills', required: true, type: 'string[]', pattern: '<owner>/<name>' } ],
|
|
104
|
+
flags: [
|
|
105
|
+
{ name: 'global', alias: 'g', type: 'boolean', default: false, description: 'Remove from global scope' },
|
|
106
|
+
{ name: 'agents', type: 'string', default: undefined, description: 'Target specific agents (comma-separated)' },
|
|
107
|
+
{ name: 'yes', alias: 'y', type: 'boolean', default: false, description: 'Skip confirmation prompts' },
|
|
108
|
+
{ name: 'json', type: 'boolean', default: false, description: 'Output as JSON' },
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
output: {
|
|
112
|
+
data_shape: {
|
|
113
|
+
results: 'array<{ skill: string, status: string, removed: string[], orphans_pruned: string[] } | { skill: string, status: "failed", error: { code: string, message: string } }>',
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
errors: [
|
|
117
|
+
{ code: 'USAGE_ERROR', next_step: { kind: 'routing', action: 'discover_schema' } },
|
|
118
|
+
],
|
|
119
|
+
examples: [
|
|
120
|
+
'happyskills uninstall acme/deploy-aws',
|
|
121
|
+
'happyskills uninstall acme/deploy-aws acme/monitor acme/logging',
|
|
122
|
+
],
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
module.exports = { run, schema }
|
package/src/commands/update.js
CHANGED
|
@@ -333,4 +333,43 @@ const run = (args) => catch_errors('Update failed', async () => {
|
|
|
333
333
|
}
|
|
334
334
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
335
335
|
|
|
336
|
-
|
|
336
|
+
const schema = {
|
|
337
|
+
name: 'update',
|
|
338
|
+
audience: 'consumer',
|
|
339
|
+
purpose: 'Bring installed skills up to date by batch-checking the registry and re-installing only outdated skills.',
|
|
340
|
+
mutation: true,
|
|
341
|
+
interactive_in_text_mode: true,
|
|
342
|
+
input: {
|
|
343
|
+
positional: [{ name: 'skill', required: false, type: 'string', pattern: '<owner>/<name>' }],
|
|
344
|
+
flags: [
|
|
345
|
+
{ name: 'all', type: 'boolean', default: false },
|
|
346
|
+
{ name: 'force', type: 'boolean', default: false },
|
|
347
|
+
{ name: 'global', type: 'boolean', default: false },
|
|
348
|
+
{ name: 'yes', type: 'boolean', default: false },
|
|
349
|
+
{ name: 'agents', type: 'string', default: null },
|
|
350
|
+
{ name: 'json', type: 'boolean', default: false }
|
|
351
|
+
]
|
|
352
|
+
},
|
|
353
|
+
output: {
|
|
354
|
+
data_shape: {
|
|
355
|
+
results: 'array<{ skill: string, installed: string, latest: string, status: string }>',
|
|
356
|
+
outdated_count: 'number',
|
|
357
|
+
up_to_date_count: 'number',
|
|
358
|
+
drift_count: 'number',
|
|
359
|
+
updated: 'array<{ skill: string, from: string, to: string }>',
|
|
360
|
+
skipped: 'array<{ skill: string, reason: string, suggestion: string }>',
|
|
361
|
+
already_up_to_date: 'array<{ skill: string, version: string }>',
|
|
362
|
+
symlink_repairs: 'array',
|
|
363
|
+
errors: 'array<{ skill: string, message: string }>'
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
errors: [
|
|
367
|
+
{ code: 'USAGE_ERROR', next_step: { kind: 'routing', action: 'discover_schema' } }
|
|
368
|
+
],
|
|
369
|
+
examples: [
|
|
370
|
+
'happyskills update acme/deploy-aws',
|
|
371
|
+
'happyskills up --all -y --json'
|
|
372
|
+
]
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
module.exports = { run, schema }
|
package/src/commands/validate.js
CHANGED
|
@@ -232,4 +232,40 @@ const run = (args) => catch_errors('Validate failed', async () => {
|
|
|
232
232
|
process.exit(has_errors ? EXIT_CODES.ERROR : EXIT_CODES.SUCCESS)
|
|
233
233
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
234
234
|
|
|
235
|
-
|
|
235
|
+
const schema = {
|
|
236
|
+
name: 'validate',
|
|
237
|
+
audience: 'author',
|
|
238
|
+
purpose: 'Validate a local skill against all agentskills.io spec rules (structure, cross-file, file sizes, changelog, dependencies).',
|
|
239
|
+
mutation: true,
|
|
240
|
+
interactive_in_text_mode: false,
|
|
241
|
+
input: {
|
|
242
|
+
positional: [
|
|
243
|
+
{ name: 'skill-name', required: true, type: 'string', pattern: '<skill-name>' },
|
|
244
|
+
],
|
|
245
|
+
flags: [
|
|
246
|
+
{ name: 'global', short: 'g', type: 'boolean', default: false },
|
|
247
|
+
{ name: 'json', type: 'boolean', default: false },
|
|
248
|
+
],
|
|
249
|
+
},
|
|
250
|
+
output: {
|
|
251
|
+
data_shape: {
|
|
252
|
+
skill: 'string',
|
|
253
|
+
valid: 'boolean',
|
|
254
|
+
errors: 'array',
|
|
255
|
+
warnings: 'array',
|
|
256
|
+
checks_passed: 'number',
|
|
257
|
+
checks_failed: 'number',
|
|
258
|
+
checks_warned: 'number',
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
errors: [
|
|
262
|
+
{ code: 'USAGE_ERROR', next_step: { kind: 'routing', action: 'discover_schema' } },
|
|
263
|
+
{ code: 'VALIDATION_FAILED', next_step: { kind: 'recovery', action: 'fix_validation_errors' } },
|
|
264
|
+
],
|
|
265
|
+
examples: [
|
|
266
|
+
'happyskills validate my-skill',
|
|
267
|
+
'happyskills v my-skill --json',
|
|
268
|
+
],
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
module.exports = { run, schema }
|
package/src/commands/versions.js
CHANGED
|
@@ -89,4 +89,37 @@ const run = (args) => catch_errors('Versions failed', async () => {
|
|
|
89
89
|
print_table(['VERSION', 'PUBLISHED', 'COMMIT', 'MESSAGE'], rows)
|
|
90
90
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
const schema = {
|
|
93
|
+
name: 'versions',
|
|
94
|
+
audience: 'consumer',
|
|
95
|
+
purpose: 'List all published versions of a skill from the registry, newest first.',
|
|
96
|
+
mutation: false,
|
|
97
|
+
interactive_in_text_mode: false,
|
|
98
|
+
input: {
|
|
99
|
+
positional: [
|
|
100
|
+
{ name: 'skill', required: true, type: 'string', pattern: '<owner>/<name>' },
|
|
101
|
+
],
|
|
102
|
+
flags: [
|
|
103
|
+
{ name: 'limit', type: 'number', default: null },
|
|
104
|
+
{ name: 'json', type: 'boolean', default: false },
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
output: {
|
|
108
|
+
data_shape: {
|
|
109
|
+
skill: 'string',
|
|
110
|
+
count: 'number',
|
|
111
|
+
versions: 'array<{ version: string, ref: string, commit: string, message: string, published_at: string|null }>',
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
errors: [
|
|
115
|
+
{ code: 'USAGE_ERROR', next_step: { kind: 'routing', action: 'discover_schema' } },
|
|
116
|
+
{ code: 'NOT_FOUND' },
|
|
117
|
+
{ code: 'NETWORK_ERROR', next_step: { kind: 'recovery', action: 'retry' } },
|
|
118
|
+
],
|
|
119
|
+
examples: [
|
|
120
|
+
'happyskills versions acme/deploy-aws',
|
|
121
|
+
'happyskills versions acme/deploy-aws --limit 20 --json',
|
|
122
|
+
],
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
module.exports = { run, extract_version, sort_refs, schema }
|
|
@@ -76,4 +76,36 @@ const run = (args) => catch_errors('Visibility failed', async () => {
|
|
|
76
76
|
}
|
|
77
77
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
const schema = {
|
|
80
|
+
name: 'visibility',
|
|
81
|
+
audience: 'author',
|
|
82
|
+
purpose: 'Check or set a skill\'s visibility (public, private, workspace) in the registry.',
|
|
83
|
+
mutation: true,
|
|
84
|
+
interactive_in_text_mode: false,
|
|
85
|
+
input: {
|
|
86
|
+
positional: [
|
|
87
|
+
{ name: 'skill', required: true, type: 'string', pattern: '<owner>/<name>' },
|
|
88
|
+
{ name: 'visibility', required: false, type: 'string', pattern: 'public|private|workspace' },
|
|
89
|
+
],
|
|
90
|
+
flags: [
|
|
91
|
+
{ name: 'json', type: 'boolean', default: false },
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
output: {
|
|
95
|
+
data_shape: {
|
|
96
|
+
skill: 'string',
|
|
97
|
+
visibility: 'string',
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
errors: [
|
|
101
|
+
{ code: 'USAGE_ERROR', next_step: { kind: 'routing', action: 'discover_schema' } },
|
|
102
|
+
{ code: 'AUTH_REQUIRED', next_step: { kind: 'recovery', action: 'login' } },
|
|
103
|
+
{ code: 'NOT_FOUND' },
|
|
104
|
+
],
|
|
105
|
+
examples: [
|
|
106
|
+
'happyskills visibility acme/deploy-aws',
|
|
107
|
+
'happyskills visibility acme/deploy-aws public',
|
|
108
|
+
],
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
module.exports = { run, schema }
|
package/src/commands/whoami.js
CHANGED
|
@@ -67,4 +67,33 @@ const run = (args) => catch_errors('Whoami failed', async () => {
|
|
|
67
67
|
}
|
|
68
68
|
}).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
const schema = {
|
|
71
|
+
name: 'whoami',
|
|
72
|
+
audience: 'account',
|
|
73
|
+
purpose: 'Show the currently authenticated user and their workspaces.',
|
|
74
|
+
mutation: false,
|
|
75
|
+
interactive_in_text_mode: false,
|
|
76
|
+
input: {
|
|
77
|
+
positional: [],
|
|
78
|
+
flags: [
|
|
79
|
+
{ name: 'json', type: 'boolean', default: false }
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
output: {
|
|
83
|
+
data_shape: {
|
|
84
|
+
username: 'string',
|
|
85
|
+
email: 'string',
|
|
86
|
+
workspaces: 'array'
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
errors: [
|
|
90
|
+
{ code: 'AUTH_REQUIRED', next_step: { kind: 'recovery', action: 'login' } },
|
|
91
|
+
{ code: 'NETWORK_ERROR', next_step: { kind: 'recovery', action: 'retry' } }
|
|
92
|
+
],
|
|
93
|
+
examples: [
|
|
94
|
+
'happyskills whoami',
|
|
95
|
+
'happyskills whoami --json'
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = { run, schema }
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
// Auth & permission ────────────────────────────────────────────────────────
|
|
15
15
|
const AUTH_REQUIRED = 'AUTH_REQUIRED'
|
|
16
16
|
const INVALID_CREDENTIALS = 'INVALID_CREDENTIALS'
|
|
17
|
+
const AUTH_FAILED = 'AUTH_FAILED'
|
|
17
18
|
const EXPIRED_TOKEN = 'EXPIRED_TOKEN'
|
|
18
19
|
const INTERACTIVE_REQUIRED = 'INTERACTIVE_REQUIRED'
|
|
19
20
|
const FORBIDDEN = 'FORBIDDEN'
|
|
@@ -109,6 +110,13 @@ const WRITE_FAILED = 'WRITE_FAILED'
|
|
|
109
110
|
const PUBLISH_FAILED = 'PUBLISH_FAILED'
|
|
110
111
|
const RANKING_SCHEMA_MISMATCH = 'RANKING_SCHEMA_MISMATCH'
|
|
111
112
|
|
|
113
|
+
// pull --rebase pipeline (client-side, spec 260523-02) ──────────────────────
|
|
114
|
+
const COMPARE_FAILED = 'COMPARE_FAILED'
|
|
115
|
+
const CLONE_BASE_FAILED = 'CLONE_BASE_FAILED'
|
|
116
|
+
const CLONE_REMOTE_FAILED = 'CLONE_REMOTE_FAILED'
|
|
117
|
+
const READ_LOCAL_FAILED = 'READ_LOCAL_FAILED'
|
|
118
|
+
const SWAP_FAILED = 'SWAP_FAILED'
|
|
119
|
+
|
|
112
120
|
// Internal ─────────────────────────────────────────────────────────────────
|
|
113
121
|
const INTERNAL_ERROR = 'INTERNAL_ERROR'
|
|
114
122
|
const PERSIST_FAILED = 'PERSIST_FAILED'
|
|
@@ -147,7 +155,8 @@ const NOT_COMMUNITY_LISTED = 'NOT_COMMUNITY_LISTED'
|
|
|
147
155
|
const UNKNOWN_CODE = 'UNKNOWN_CODE'
|
|
148
156
|
|
|
149
157
|
const ERROR_CODES = Object.freeze({
|
|
150
|
-
AUTH_REQUIRED, INVALID_CREDENTIALS,
|
|
158
|
+
AUTH_REQUIRED, INVALID_CREDENTIALS, AUTH_FAILED, EXPIRED_TOKEN,
|
|
159
|
+
INTERACTIVE_REQUIRED,
|
|
151
160
|
FORBIDDEN, INSUFFICIENT_ACCESS, LAST_OWNER, ORG_RESTRICTED,
|
|
152
161
|
NETWORK_ERROR, RATE_LIMITED, DB_UNAVAILABLE, GITHUB_UNAVAILABLE,
|
|
153
162
|
EMBEDDING_UNAVAILABLE, REGISTRY_UNAVAILABLE,
|
|
@@ -172,6 +181,8 @@ const ERROR_CODES = Object.freeze({
|
|
|
172
181
|
AUTHORIZATION_PENDING,
|
|
173
182
|
COMMAND_NOT_FOUND, MIN_CLI_VERSION, SNAPSHOT_FAILED, WRITE_FAILED,
|
|
174
183
|
PUBLISH_FAILED, RANKING_SCHEMA_MISMATCH,
|
|
184
|
+
COMPARE_FAILED, CLONE_BASE_FAILED, CLONE_REMOTE_FAILED, READ_LOCAL_FAILED,
|
|
185
|
+
SWAP_FAILED,
|
|
175
186
|
INTERNAL_ERROR, PERSIST_FAILED, VERIFICATION_FAILED,
|
|
176
187
|
NO_COGNITO_USER, COGNITO_SYNC_FAILED, COGNITO_UNLINK_FAILED,
|
|
177
188
|
ALREADY_HAS_PASSWORD, EMAIL_ALIAS_CONFLICT, ALREADY_APPROVED,
|
|
@@ -31,6 +31,8 @@ const PROVIDE_CHANGELOG = 'provide_changelog'
|
|
|
31
31
|
const SELF_UPDATE = 'self_update'
|
|
32
32
|
const SHOW_FORMAT = 'show_format'
|
|
33
33
|
const RETRY_RANK = 'retry_rank'
|
|
34
|
+
const RETRY_OR_ABANDON = 'retry_or_abandon'
|
|
35
|
+
const REVIEW_PUBLISH_ERROR = 'review_publish_error'
|
|
34
36
|
|
|
35
37
|
// kind: clarification
|
|
36
38
|
const CLARIFY_QUERY = 'clarify_query'
|
|
@@ -45,6 +47,7 @@ const SPECIFY_WORKSPACE = 'specify_workspace'
|
|
|
45
47
|
const SPECIFY_BUMP_TYPE = 'specify_bump_type'
|
|
46
48
|
const RESOLVE_BUMP_DISAGREEMENT = 'resolve_bump_disagreement'
|
|
47
49
|
const PICK_VERSION = 'pick_version'
|
|
50
|
+
const RESOLVE_UNKNOWN_DRIFT = 'resolve_unknown_drift'
|
|
48
51
|
|
|
49
52
|
// kind: confirmation
|
|
50
53
|
const CONFIRM_DISCARD_OR_SNAPSHOT_FIRST = 'confirm_discard_or_snapshot_first'
|
|
@@ -72,6 +75,8 @@ const ACTION_KIND = Object.freeze({
|
|
|
72
75
|
[SELF_UPDATE]: RECOVERY,
|
|
73
76
|
[SHOW_FORMAT]: RECOVERY,
|
|
74
77
|
[RETRY_RANK]: RECOVERY,
|
|
78
|
+
[RETRY_OR_ABANDON]: RECOVERY,
|
|
79
|
+
[REVIEW_PUBLISH_ERROR]: RECOVERY,
|
|
75
80
|
|
|
76
81
|
[CLARIFY_QUERY]: CLARIFICATION,
|
|
77
82
|
|
|
@@ -84,6 +89,7 @@ const ACTION_KIND = Object.freeze({
|
|
|
84
89
|
[SPECIFY_BUMP_TYPE]: DECISION,
|
|
85
90
|
[RESOLVE_BUMP_DISAGREEMENT]: DECISION,
|
|
86
91
|
[PICK_VERSION]: DECISION,
|
|
92
|
+
[RESOLVE_UNKNOWN_DRIFT]: DECISION,
|
|
87
93
|
|
|
88
94
|
[CONFIRM_DISCARD_OR_SNAPSHOT_FIRST]: CONFIRMATION,
|
|
89
95
|
[CONFIRM_CASCADE]: CONFIRMATION,
|
|
@@ -101,10 +107,12 @@ const ACTION_KIND = Object.freeze({
|
|
|
101
107
|
const NEXT_STEP_ACTIONS = Object.freeze({
|
|
102
108
|
LOGIN, RETRY, RECONCILE_FIRST, PULL_REBASE_FIRST, FIX_VALIDATION_ERRORS,
|
|
103
109
|
PROVIDE_CHANGELOG, SELF_UPDATE, SHOW_FORMAT, RETRY_RANK,
|
|
110
|
+
RETRY_OR_ABANDON, REVIEW_PUBLISH_ERROR,
|
|
104
111
|
CLARIFY_QUERY,
|
|
105
112
|
RESOLVE_REGRESSION, RESOLVE_MISSING_SKILL_JSON, RESOLVE_MISSING_DIR,
|
|
106
113
|
RESOLVE_CONFLICTS, RESOLVE_PATCH_REJECTIONS, SPECIFY_WORKSPACE,
|
|
107
114
|
SPECIFY_BUMP_TYPE, RESOLVE_BUMP_DISAGREEMENT, PICK_VERSION,
|
|
115
|
+
RESOLVE_UNKNOWN_DRIFT,
|
|
108
116
|
CONFIRM_DISCARD_OR_SNAPSHOT_FIRST, CONFIRM_CASCADE, CONFIRM_DESTRUCTIVE,
|
|
109
117
|
PASS_YES_FLAG,
|
|
110
118
|
RANK_DIGESTS_INLINE, PRESENT_TO_USER, ATTACH_SCREENSHOT,
|
|
@@ -59,6 +59,11 @@ const NEXT_STEP_BY_ERROR_CODE = Object.freeze({
|
|
|
59
59
|
'Sign in to HappySkills, then re-run the command.',
|
|
60
60
|
{ commands: ['npx happyskills login --browser --json'] }
|
|
61
61
|
),
|
|
62
|
+
AUTH_FAILED: () => recovery(
|
|
63
|
+
LOGIN,
|
|
64
|
+
'The sign-in attempt did not complete. Start the login flow again, then re-run the command.',
|
|
65
|
+
{ commands: ['npx happyskills login --browser --json'] }
|
|
66
|
+
),
|
|
62
67
|
EXPIRED_TOKEN: () => recovery(
|
|
63
68
|
LOGIN,
|
|
64
69
|
'Your session has expired. Sign in again, then re-run the command.',
|
|
@@ -94,6 +94,37 @@ describe('happyskills schema --json', () => {
|
|
|
94
94
|
}
|
|
95
95
|
})
|
|
96
96
|
|
|
97
|
+
it('no command returns the stub purpose (anti-stub guard — spec 260602-01)', () => {
|
|
98
|
+
const { stdout } = run(['schema', '--json'])
|
|
99
|
+
const env = parse_envelope(stdout, 'schema --json anti-stub')
|
|
100
|
+
const stubbed = env.data.commands.filter(c => /no curated purpose/i.test(c.purpose))
|
|
101
|
+
assert.deepStrictEqual(
|
|
102
|
+
stubbed.map(c => c.name),
|
|
103
|
+
[],
|
|
104
|
+
`these commands still return the stub purpose and need a curated schema export: ${stubbed.map(c => c.name).join(', ')}`
|
|
105
|
+
)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('every command carries a non-empty examples array of strings', () => {
|
|
109
|
+
const { stdout } = run(['schema', '--json'])
|
|
110
|
+
const env = parse_envelope(stdout, 'schema --json examples')
|
|
111
|
+
for (const cmd of env.data.commands) {
|
|
112
|
+
assert.ok(Array.isArray(cmd.examples) && cmd.examples.length > 0, `command.examples must be a non-empty array for ${cmd.name}`)
|
|
113
|
+
for (const ex of cmd.examples) {
|
|
114
|
+
assert.ok(typeof ex === 'string' && ex.length > 0, `command.examples[] entries must be non-empty strings for ${cmd.name}`)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it('every command.input exposes positional and flags arrays', () => {
|
|
120
|
+
const { stdout } = run(['schema', '--json'])
|
|
121
|
+
const env = parse_envelope(stdout, 'schema --json input shape')
|
|
122
|
+
for (const cmd of env.data.commands) {
|
|
123
|
+
assert.ok(Array.isArray(cmd.input.positional), `command.input.positional must be an array for ${cmd.name}`)
|
|
124
|
+
assert.ok(Array.isArray(cmd.input.flags), `command.input.flags must be an array for ${cmd.name}`)
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
|
|
97
128
|
it('every command.errors[].code is in the closed enum, and the kind/action pair is valid', () => {
|
|
98
129
|
const { stdout } = run(['schema', '--json'])
|
|
99
130
|
const env = parse_envelope(stdout, 'schema --json error refs')
|