@skhema/cli 0.5.1 → 0.6.1
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/LICENSE +21 -0
- package/README.md +7 -0
- package/dist/cli.js +14 -2
- package/dist/commands/element.d.ts +3 -2
- package/dist/commands/element.d.ts.map +1 -1
- package/dist/commands/element.js +52 -2
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +98 -1
- package/dist/lib/auth/api-key-admin.d.ts.map +1 -1
- package/dist/lib/auth/api-key-admin.js +4 -5
- package/dist/lib/config.js +4 -4
- package/dist/lib/contribute/api.d.ts +2 -2
- package/dist/lib/contribute/api.d.ts.map +1 -1
- package/dist/lib/contribute/api.js +3 -3
- package/dist/lib/contribute/types.d.ts.map +1 -1
- package/dist/lib/docs/reference-generator.js +3 -3
- package/dist/lib/skills/installer.d.ts +14 -1
- package/dist/lib/skills/installer.d.ts.map +1 -1
- package/dist/lib/skills/installer.js +40 -0
- package/dist/lib/skills/types.d.ts +6 -0
- package/dist/lib/skills/types.d.ts.map +1 -1
- package/dist/program.d.ts +13 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +34 -1
- package/package.json +11 -23
- package/skills/skhema-operate/references/author-elements.md +3 -2
- package/skills/skhema-pressure-test/references/pre-mortem.md +12 -7
- package/skills/.manifest.json +0 -13
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Skhema
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
> [!IMPORTANT]
|
|
2
|
+
> **Generated mirror of a private source repo — do not open PRs here.**
|
|
3
|
+
> This repository is an automatically generated, read-only mirror of a package
|
|
4
|
+
> built from Skhema's private monorepo. Pull requests are disabled and any change
|
|
5
|
+
> pushed here is overwritten on the next release. Questions and bug reports:
|
|
6
|
+
> support@skhema.com. Security: see [SECURITY.md](./SECURITY.md).
|
|
7
|
+
|
|
1
8
|
# @skhema/cli
|
|
2
9
|
|
|
3
10
|
The Skhema command-line interface (`skhema`). Authenticate as a human or an
|
package/dist/cli.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { CommanderError } from 'commander';
|
|
1
2
|
import { createRequire } from 'module';
|
|
2
3
|
import { isApprovedContributor } from './lib/auth/entitlements.js';
|
|
3
4
|
import { getStoredCredentials } from './lib/auth/token-store.js';
|
|
4
5
|
import { outputError } from './lib/output.js';
|
|
5
|
-
import { buildProgram } from './program.js';
|
|
6
|
+
import { buildProgram, resolveCommanderExitCode } from './program.js';
|
|
6
7
|
const require = createRequire(import.meta.url);
|
|
7
8
|
const pkg = require('../package.json');
|
|
8
9
|
const program = buildProgram(pkg.version);
|
|
@@ -35,6 +36,17 @@ async function main() {
|
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
+
try {
|
|
40
|
+
await program.parseAsync();
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
// With exitOverride set, commander throws instead of exiting for every
|
|
44
|
+
// parser-level outcome (usage error, --help, --version). Map those onto the
|
|
45
|
+
// ExitCode contract; anything else is a real failure and should propagate.
|
|
46
|
+
if (err instanceof CommanderError) {
|
|
47
|
+
process.exit(resolveCommanderExitCode(err));
|
|
48
|
+
}
|
|
49
|
+
throw err;
|
|
50
|
+
}
|
|
39
51
|
}
|
|
40
52
|
main();
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
/**
|
|
3
|
-
* Element commands — the strategic building blocks in a workspace.
|
|
4
|
-
* workspace-scoped via `--workspace` (falling back to the default workspace)
|
|
3
|
+
* Element commands — the strategic building blocks in a workspace. Most are
|
|
4
|
+
* workspace-scoped via `--workspace` (falling back to the default workspace);
|
|
5
|
+
* `types` is a local, network-free lookup of the method vocabulary.
|
|
5
6
|
*/
|
|
6
7
|
export declare function registerElementCommands(program: Command): void;
|
|
7
8
|
//# sourceMappingURL=element.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../../src/commands/element.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../../src/commands/element.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AA2EnC;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2T9D"}
|
package/dist/commands/element.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getElementDefinition, getElementsForComponent, SKHEMA_MAPPING, } from '@skhema/method';
|
|
1
2
|
import chalk from 'chalk';
|
|
2
3
|
import { resolveClient } from '../lib/api/client.js';
|
|
3
4
|
import { asRecord, buildBody, coerceList, readPayloadFile, resolveWorkspaceId, } from '../lib/api/command-helpers.js';
|
|
@@ -8,9 +9,47 @@ function summarize(content) {
|
|
|
8
9
|
const text = typeof content === 'string' ? content : '';
|
|
9
10
|
return text.length > 48 ? `${text.slice(0, 47)}…` : text || '—';
|
|
10
11
|
}
|
|
12
|
+
/** Human-friendly rendering of an expected mood (e.g. `noun_phrase` → `noun phrase`). */
|
|
13
|
+
function formatMood(mood) {
|
|
14
|
+
return mood ? mood.replace(/_/g, ' ') : '—';
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The component → allowed-element-type mapping, read straight from
|
|
18
|
+
* `@skhema/method` (SKHEMA_MAPPING) in canonical component-flow order. This is
|
|
19
|
+
* the same vocabulary the backend enforces, so agents can discover the
|
|
20
|
+
* allow-list locally instead of probing it via `bad_request` errors.
|
|
21
|
+
*/
|
|
22
|
+
function buildElementTypeMapping() {
|
|
23
|
+
return SKHEMA_MAPPING.componentFlow.map((component) => ({
|
|
24
|
+
component: component.value,
|
|
25
|
+
label: component.label,
|
|
26
|
+
acronym: component.acronym,
|
|
27
|
+
elementTypes: getElementsForComponent(component.value).map((element) => ({
|
|
28
|
+
type: element.value,
|
|
29
|
+
label: element.label,
|
|
30
|
+
acronym: element.acronym,
|
|
31
|
+
mood: getElementDefinition(element.value)?.expectedMood ?? null,
|
|
32
|
+
})),
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
/** Render the mapping as a per-component section with an element-type table. */
|
|
36
|
+
function renderElementTypeMapping(mapping) {
|
|
37
|
+
logHeader('Element types by component');
|
|
38
|
+
for (const component of mapping) {
|
|
39
|
+
log('');
|
|
40
|
+
log(chalk.bold(`${component.label} ${chalk.dim(`(${component.acronym})`)}`));
|
|
41
|
+
logTable(['acronym', 'type', 'label', 'mood'], component.elementTypes.map((element) => [
|
|
42
|
+
element.acronym,
|
|
43
|
+
element.type,
|
|
44
|
+
element.label,
|
|
45
|
+
formatMood(element.mood),
|
|
46
|
+
]));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
11
49
|
/**
|
|
12
|
-
* Element commands — the strategic building blocks in a workspace.
|
|
13
|
-
* workspace-scoped via `--workspace` (falling back to the default workspace)
|
|
50
|
+
* Element commands — the strategic building blocks in a workspace. Most are
|
|
51
|
+
* workspace-scoped via `--workspace` (falling back to the default workspace);
|
|
52
|
+
* `types` is a local, network-free lookup of the method vocabulary.
|
|
14
53
|
*/
|
|
15
54
|
export function registerElementCommands(program) {
|
|
16
55
|
const element = program.command('element').description('Element commands');
|
|
@@ -200,4 +239,15 @@ export function registerElementCommands(program) {
|
|
|
200
239
|
return data;
|
|
201
240
|
});
|
|
202
241
|
});
|
|
242
|
+
element
|
|
243
|
+
.command('types')
|
|
244
|
+
.description('List element types allowed in each component (method vocabulary, no network)')
|
|
245
|
+
.action(async () => {
|
|
246
|
+
await runCommand('element types', async () => {
|
|
247
|
+
const mapping = buildElementTypeMapping();
|
|
248
|
+
if (!getGlobalOptions().json)
|
|
249
|
+
renderElementTypeMapping(mapping);
|
|
250
|
+
return { components: mapping };
|
|
251
|
+
});
|
|
252
|
+
});
|
|
203
253
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/commands/skills.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/commands/skills.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAwCnC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6U7D"}
|
package/dist/commands/skills.js
CHANGED
|
@@ -1,10 +1,28 @@
|
|
|
1
|
+
import readline from 'readline';
|
|
1
2
|
import chalk from 'chalk';
|
|
2
3
|
import ora from 'ora';
|
|
3
4
|
import { getGlobalOptions, log, logHeader, logTable, outputError, outputSuccess, } from '../lib/output.js';
|
|
4
5
|
import { listBundledSkills, readBundledSkill } from '../lib/skills/bundled.js';
|
|
5
|
-
import { installSkills, updateSkills } from '../lib/skills/installer.js';
|
|
6
|
+
import { installSkills, pruneSkills, updateSkills, } from '../lib/skills/installer.js';
|
|
6
7
|
import { readLock } from '../lib/skills/lock.js';
|
|
7
8
|
import { detectPlatforms } from '../lib/skills/platform-detect.js';
|
|
9
|
+
function interactiveTerminal() {
|
|
10
|
+
return (Boolean(process.stdin.isTTY && process.stdout.isTTY) &&
|
|
11
|
+
!getGlobalOptions().json);
|
|
12
|
+
}
|
|
13
|
+
async function confirm(question) {
|
|
14
|
+
const rl = readline.createInterface({
|
|
15
|
+
input: process.stdin,
|
|
16
|
+
output: process.stdout,
|
|
17
|
+
});
|
|
18
|
+
const answer = await new Promise((resolve) => {
|
|
19
|
+
rl.question(`${question} [y/N]: `, (value) => {
|
|
20
|
+
rl.close();
|
|
21
|
+
resolve(value.trim().toLowerCase());
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
return answer === 'y' || answer === 'yes';
|
|
25
|
+
}
|
|
8
26
|
export function registerSkillsCommands(program) {
|
|
9
27
|
const skills = program.command('skills').description('AI skills management');
|
|
10
28
|
skills
|
|
@@ -171,4 +189,83 @@ export function registerSkillsCommands(program) {
|
|
|
171
189
|
process.exit(1);
|
|
172
190
|
}
|
|
173
191
|
});
|
|
192
|
+
skills
|
|
193
|
+
.command('prune')
|
|
194
|
+
.description('Remove installed skills that are no longer bundled with this CLI (retired or renamed)')
|
|
195
|
+
.option('--platform <id>', 'Prune a specific platform only')
|
|
196
|
+
.option('--yes', 'Actually remove; without it, only preview what would go')
|
|
197
|
+
.action(async (options) => {
|
|
198
|
+
const opts = getGlobalOptions();
|
|
199
|
+
const spinner = opts.json || opts.quiet
|
|
200
|
+
? null
|
|
201
|
+
: ora('Detecting agent platforms...').start();
|
|
202
|
+
try {
|
|
203
|
+
const platforms = detectPlatforms().filter((p) => p.detected);
|
|
204
|
+
const targets = options.platform
|
|
205
|
+
? platforms.filter((p) => p.id === options.platform)
|
|
206
|
+
: platforms;
|
|
207
|
+
if (targets.length === 0) {
|
|
208
|
+
spinner?.warn(options.platform
|
|
209
|
+
? `Platform "${options.platform}" not detected.`
|
|
210
|
+
: 'No agent platforms detected.');
|
|
211
|
+
if (opts.json)
|
|
212
|
+
outputSuccess([], 'skills prune');
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
// Preview first — this never writes.
|
|
216
|
+
const preview = await pruneSkills(targets, { apply: false });
|
|
217
|
+
if (preview.length === 0) {
|
|
218
|
+
spinner?.succeed('No retired skills to prune. Everything is current.');
|
|
219
|
+
if (opts.json)
|
|
220
|
+
outputSuccess([], 'skills prune');
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
spinner?.info(`Found ${preview.length} retired skill install(s) across ${new Set(preview.map((r) => r.platform.id)).size} platform(s).`);
|
|
224
|
+
// Mutate only with --yes, or after an interactive confirmation.
|
|
225
|
+
let apply = Boolean(options.yes);
|
|
226
|
+
if (!apply) {
|
|
227
|
+
if (interactiveTerminal()) {
|
|
228
|
+
logHeader('Would remove');
|
|
229
|
+
logTable(['Platform', 'Skill', 'Path'], preview.map((r) => [
|
|
230
|
+
r.platform.name,
|
|
231
|
+
r.skill,
|
|
232
|
+
chalk.dim(r.targetPath),
|
|
233
|
+
]));
|
|
234
|
+
apply = await confirm('Remove these skills?');
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (!apply) {
|
|
238
|
+
const results = preview;
|
|
239
|
+
if (opts.json) {
|
|
240
|
+
outputSuccess(results, 'skills prune');
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
logHeader('Prune Preview (dry run — pass --yes to remove)');
|
|
244
|
+
logTable(['Platform', 'Skill', 'Path'], results.map((r) => [
|
|
245
|
+
r.platform.name,
|
|
246
|
+
r.skill,
|
|
247
|
+
chalk.dim(r.targetPath),
|
|
248
|
+
]));
|
|
249
|
+
log('');
|
|
250
|
+
log(chalk.dim('Re-run with --yes to remove these skills.'));
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
const results = await pruneSkills(targets, { apply: true });
|
|
254
|
+
if (opts.json) {
|
|
255
|
+
outputSuccess(results, 'skills prune');
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
logHeader('Prune Results');
|
|
259
|
+
logTable(['Platform', 'Skill', 'Status'], results.map((r) => [
|
|
260
|
+
r.platform.name,
|
|
261
|
+
r.skill,
|
|
262
|
+
chalk.red(r.action),
|
|
263
|
+
]));
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
spinner?.fail('Prune failed');
|
|
267
|
+
outputError(error instanceof Error ? error.message : 'Unknown error', 'skills prune');
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
});
|
|
174
271
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-key-admin.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/api-key-admin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"api-key-admin.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/api-key-admin.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,OAAO,GAAG,YAAY,CAAA;AAC9D,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,MAAM,CAAA;AAExC,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,cAAc,EAAE,MAAM,CAAA;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,KAAK,EAAE,WAAW,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,aAAc,SAAQ,aAAa;IAClD,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,EAAE,CAAA;IACrB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CACtC;AAsDD,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE;IACL,cAAc,EAAE,MAAM,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,gBAAgB,CAAA;IAC5B,KAAK,EAAE,WAAW,CAAA;CACnB,GACA,OAAO,CAAC,aAAa,CAAC,CAKxB;AAED,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,iBAAiB,CAAC,CAK5B;AAED,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAK9C"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { SkhemaApiError } from '@skhema/sdk';
|
|
2
2
|
import { SUPABASE_PUBLISHABLE_KEY, SUPABASE_URL } from '../config.js';
|
|
3
3
|
/**
|
|
4
|
-
* Client for
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* enforced server-side and unchanged. This is NOT the public gateway.
|
|
4
|
+
* Client for creating, listing, and revoking the caller's Skhema API keys.
|
|
5
|
+
* Authenticates with the user's OAuth bearer; key-issuance authorization
|
|
6
|
+
* (org role, plan limits, one-time key display, security notifications) is
|
|
7
|
+
* enforced by the server, not the CLI.
|
|
9
8
|
*/
|
|
10
9
|
const API_KEY_MANAGE_URL = `${SUPABASE_URL}/functions/v1/api-key-manage`;
|
|
11
10
|
async function callApiKeyManage(accessToken, body) {
|
package/dist/lib/config.js
CHANGED
|
@@ -25,10 +25,10 @@ export const API_KEY_ENV_VAR = 'SKHEMA_API_KEY';
|
|
|
25
25
|
// never injects a credential here.
|
|
26
26
|
// Override via env for staging/preview environments.
|
|
27
27
|
export const MCP_SERVER_URL = process.env.SKHEMA_MCP_URL ?? 'https://mcp.skhema.com/mcp';
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
28
|
+
// Backend project configuration for the CLI's authenticated data calls.
|
|
29
|
+
// The publishable key is safe to embed in client-side code — it carries no
|
|
30
|
+
// privileged access and relies on server-side authorization. Override via env
|
|
31
|
+
// for staging/preview environments.
|
|
32
32
|
export const SUPABASE_URL = process.env.SKHEMA_SUPABASE_URL ?? 'https://uiybgpcjjrdqmdbarqlx.supabase.co';
|
|
33
33
|
export const SUPABASE_PUBLISHABLE_KEY = process.env.SKHEMA_SUPABASE_PUBLISHABLE_KEY ??
|
|
34
34
|
'sb_publishable_G9uXii5AYDLK6vUpyaqy3A_-NmdwQF1';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** Backend actions the contributor commands invoke. */
|
|
2
2
|
export type ContributeEdgeFunction = 'contributor-manage' | 'embed-manage' | 'contributor-payout';
|
|
3
3
|
/**
|
|
4
|
-
* POST a JSON action to
|
|
4
|
+
* POST a JSON action to the contributor backend with the stored OAuth session.
|
|
5
5
|
* Shared by every authenticated `contribute` subcommand so the auth headers,
|
|
6
6
|
* base URL, and error mapping live in exactly one place.
|
|
7
7
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/lib/contribute/api.ts"],"names":[],"mappings":"AAGA,
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/lib/contribute/api.ts"],"names":[],"mappings":"AAGA,uDAAuD;AACvD,MAAM,MAAM,sBAAsB,GAC9B,oBAAoB,GACpB,cAAc,GACd,oBAAoB,CAAA;AAExB;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,EAAE,EAAE,sBAAsB,EAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,CAAC,CAAC,CA+BZ"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getStoredCredentials } from '../auth/token-store.js';
|
|
2
2
|
import { SUPABASE_PUBLISHABLE_KEY, SUPABASE_URL } from '../config.js';
|
|
3
3
|
/**
|
|
4
|
-
* POST a JSON action to
|
|
4
|
+
* POST a JSON action to the contributor backend with the stored OAuth session.
|
|
5
5
|
* Shared by every authenticated `contribute` subcommand so the auth headers,
|
|
6
6
|
* base URL, and error mapping live in exactly one place.
|
|
7
7
|
*
|
|
@@ -25,8 +25,8 @@ export async function postContributeFunction(fn, body) {
|
|
|
25
25
|
body: JSON.stringify(body),
|
|
26
26
|
});
|
|
27
27
|
if (!response.ok) {
|
|
28
|
-
//
|
|
29
|
-
//
|
|
28
|
+
// The backend returns `{ message }`, while some handlers return
|
|
29
|
+
// `{ error }` — accept either before the generic fallback.
|
|
30
30
|
const detail = (await response.json().catch(() => ({})));
|
|
31
31
|
throw new Error(detail.error ||
|
|
32
32
|
detail.message ||
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/contribute/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/contribute/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,8 +7,8 @@ import { ExitCode } from '../api/run-command.js';
|
|
|
7
7
|
* options, or exit codes change — never on a plain version bump.
|
|
8
8
|
*
|
|
9
9
|
* The committed copy lives at docs/cli-reference.mdx and is drift-tested
|
|
10
|
-
* (src/__tests__/cli-reference-drift.test.ts).
|
|
11
|
-
*
|
|
10
|
+
* (src/__tests__/cli-reference-drift.test.ts). A copy is also published to the
|
|
11
|
+
* public docs site — regenerate and sync both when this file changes.
|
|
12
12
|
*/
|
|
13
13
|
/** Human meanings for the stable exit-code contract (run-command.ts). */
|
|
14
14
|
const EXIT_CODE_MEANINGS = {
|
|
@@ -137,7 +137,7 @@ export function generateCliReference() {
|
|
|
137
137
|
lines.push('---');
|
|
138
138
|
lines.push('');
|
|
139
139
|
lines.push('{/* AUTO-GENERATED from the @skhema/cli command tree — do not edit by hand.');
|
|
140
|
-
lines.push(' Regenerate with `npm run generate:cli-reference
|
|
140
|
+
lines.push(' Regenerate with `npm run generate:cli-reference`. */}');
|
|
141
141
|
lines.push('');
|
|
142
142
|
lines.push('This page is generated from the CLI itself, so it always matches the installed command surface. For a guided tour, start with [Using the CLI](/docs/guides/using-the-cli).');
|
|
143
143
|
lines.push('');
|
|
@@ -1,4 +1,17 @@
|
|
|
1
|
-
import type { DetectedPlatform, InstallResult } from './types.js';
|
|
1
|
+
import type { DetectedPlatform, InstallResult, PruneResult } from './types.js';
|
|
2
2
|
export declare function installSkills(platforms: DetectedPlatform[]): Promise<InstallResult[]>;
|
|
3
3
|
export declare function updateSkills(platforms: DetectedPlatform[]): Promise<InstallResult[]>;
|
|
4
|
+
/**
|
|
5
|
+
* Find skills we previously installed that are no longer bundled with this CLI
|
|
6
|
+
* (retired or renamed) and remove them from each platform.
|
|
7
|
+
*
|
|
8
|
+
* Attribution is anchored on the per-platform lock file: only skills recorded
|
|
9
|
+
* there by our own installer are candidates, so a skill authored by the user or
|
|
10
|
+
* another tool that happens to share the skills directory is never touched. With
|
|
11
|
+
* `apply: false` (the default), nothing is written — the returned list is a
|
|
12
|
+
* preview of what removal would do.
|
|
13
|
+
*/
|
|
14
|
+
export declare function pruneSkills(platforms: DetectedPlatform[], options?: {
|
|
15
|
+
apply: boolean;
|
|
16
|
+
}): Promise<PruneResult[]>;
|
|
4
17
|
//# sourceMappingURL=installer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../../src/lib/skills/installer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AA+
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../../src/lib/skills/installer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AA+D9E,wBAAsB,aAAa,CACjC,SAAS,EAAE,gBAAgB,EAAE,GAC5B,OAAO,CAAC,aAAa,EAAE,CAAC,CA0C1B;AAED,wBAAsB,YAAY,CAChC,SAAS,EAAE,gBAAgB,EAAE,GAC5B,OAAO,CAAC,aAAa,EAAE,CAAC,CAG1B;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,GAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAqB,GAC7C,OAAO,CAAC,WAAW,EAAE,CAAC,CAmCxB"}
|
|
@@ -83,3 +83,43 @@ export async function updateSkills(platforms) {
|
|
|
83
83
|
// Update uses the same logic as install — content comparison handles skip/update
|
|
84
84
|
return installSkills(platforms);
|
|
85
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Find skills we previously installed that are no longer bundled with this CLI
|
|
88
|
+
* (retired or renamed) and remove them from each platform.
|
|
89
|
+
*
|
|
90
|
+
* Attribution is anchored on the per-platform lock file: only skills recorded
|
|
91
|
+
* there by our own installer are candidates, so a skill authored by the user or
|
|
92
|
+
* another tool that happens to share the skills directory is never touched. With
|
|
93
|
+
* `apply: false` (the default), nothing is written — the returned list is a
|
|
94
|
+
* preview of what removal would do.
|
|
95
|
+
*/
|
|
96
|
+
export async function pruneSkills(platforms, options = { apply: false }) {
|
|
97
|
+
const bundledNames = new Set(getBundledSkills().map((skill) => skill.name));
|
|
98
|
+
const results = [];
|
|
99
|
+
for (const platform of platforms) {
|
|
100
|
+
const lock = readLock(platform);
|
|
101
|
+
const retired = Object.keys(lock.skills)
|
|
102
|
+
.filter((name) => !bundledNames.has(name))
|
|
103
|
+
.sort((a, b) => a.localeCompare(b));
|
|
104
|
+
for (const name of retired) {
|
|
105
|
+
const targetPath = path.join(platform.skillsDir, name);
|
|
106
|
+
if (options.apply) {
|
|
107
|
+
// Remove only the directory our lock attributes to this skill.
|
|
108
|
+
if (fs.existsSync(targetPath)) {
|
|
109
|
+
fs.rmSync(targetPath, { recursive: true, force: true });
|
|
110
|
+
}
|
|
111
|
+
delete lock.skills[name];
|
|
112
|
+
}
|
|
113
|
+
results.push({
|
|
114
|
+
platform,
|
|
115
|
+
skill: name,
|
|
116
|
+
action: options.apply ? 'removed' : 'would-remove',
|
|
117
|
+
targetPath,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
if (options.apply && retired.length > 0) {
|
|
121
|
+
writeLock(platform, lock);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return results;
|
|
125
|
+
}
|
|
@@ -17,6 +17,12 @@ export interface InstallResult {
|
|
|
17
17
|
action: 'installed' | 'updated' | 'skipped';
|
|
18
18
|
targetPath: string;
|
|
19
19
|
}
|
|
20
|
+
export interface PruneResult {
|
|
21
|
+
platform: DetectedPlatform;
|
|
22
|
+
skill: string;
|
|
23
|
+
action: 'removed' | 'would-remove';
|
|
24
|
+
targetPath: string;
|
|
25
|
+
}
|
|
20
26
|
export interface SkillLock {
|
|
21
27
|
version: string;
|
|
22
28
|
installedAt: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/skills/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,SAAS,CAAA;IAC3C,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CACZ,MAAM,EACN;QACE,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,MAAM,CAAA;QAChB,WAAW,EAAE,MAAM,CAAA;KACpB,CACF,CAAA;CACF"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/skills/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,SAAS,CAAA;IAC3C,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,SAAS,GAAG,cAAc,CAAA;IAClC,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CACZ,MAAM,EACN;QACE,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,MAAM,CAAA;QAChB,WAAW,EAAE,MAAM,CAAA;KACpB,CACF,CAAA;CACF"}
|
package/dist/program.d.ts
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
1
|
+
import { Command, CommanderError } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the process exit code for a parser-level {@link CommanderError}.
|
|
4
|
+
*
|
|
5
|
+
* Commander's own defaults are inconsistent (unknown option → 1, unknown
|
|
6
|
+
* command silently swallowed → 0, missing subcommand → 1). We collapse them
|
|
7
|
+
* onto the CLI's stable {@link ExitCode} contract: printing help or the version
|
|
8
|
+
* is an informational success (`0`), and every other parser failure — unknown
|
|
9
|
+
* option, unknown/missing command, missing or excess argument — is a usage
|
|
10
|
+
* error ({@link ExitCode.Usage}). Commander tags the informational cases with
|
|
11
|
+
* `exitCode === 0`, which is the only discriminator we need.
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveCommanderExitCode(err: CommanderError): number;
|
|
2
14
|
/**
|
|
3
15
|
* Assemble the full skhema CLI program. The runtime entry (cli.ts) and the
|
|
4
16
|
* docs reference generator both build from here, so every registered command
|
package/dist/program.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAsBnD;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAEpE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAqErD"}
|
package/dist/program.js
CHANGED
|
@@ -16,8 +16,23 @@ import { registerStrategyCommands } from './commands/strategy.js';
|
|
|
16
16
|
import { registerWebhookCommands } from './commands/webhook.js';
|
|
17
17
|
import { registerWorkspaceCommands } from './commands/workspace.js';
|
|
18
18
|
import { setApiKeyFlag } from './lib/api/credential-context.js';
|
|
19
|
+
import { ExitCode } from './lib/api/run-command.js';
|
|
19
20
|
import { showBanner } from './lib/banner.js';
|
|
20
21
|
import { setGlobalOptions } from './lib/output.js';
|
|
22
|
+
/**
|
|
23
|
+
* Resolve the process exit code for a parser-level {@link CommanderError}.
|
|
24
|
+
*
|
|
25
|
+
* Commander's own defaults are inconsistent (unknown option → 1, unknown
|
|
26
|
+
* command silently swallowed → 0, missing subcommand → 1). We collapse them
|
|
27
|
+
* onto the CLI's stable {@link ExitCode} contract: printing help or the version
|
|
28
|
+
* is an informational success (`0`), and every other parser failure — unknown
|
|
29
|
+
* option, unknown/missing command, missing or excess argument — is a usage
|
|
30
|
+
* error ({@link ExitCode.Usage}). Commander tags the informational cases with
|
|
31
|
+
* `exitCode === 0`, which is the only discriminator we need.
|
|
32
|
+
*/
|
|
33
|
+
export function resolveCommanderExitCode(err) {
|
|
34
|
+
return err.exitCode === 0 ? ExitCode.Ok : ExitCode.Usage;
|
|
35
|
+
}
|
|
21
36
|
/**
|
|
22
37
|
* Assemble the full skhema CLI program. The runtime entry (cli.ts) and the
|
|
23
38
|
* docs reference generator both build from here, so every registered command
|
|
@@ -25,6 +40,15 @@ import { setGlobalOptions } from './lib/output.js';
|
|
|
25
40
|
*/
|
|
26
41
|
export function buildProgram(version) {
|
|
27
42
|
const program = new Command();
|
|
43
|
+
// Throw a CommanderError instead of calling process.exit directly, so the
|
|
44
|
+
// entry point can map every parser-level failure onto the ExitCode taxonomy.
|
|
45
|
+
// Set before registering subcommands: commander copies the exit callback into
|
|
46
|
+
// each child at `.command()` time, so this one call covers the whole tree.
|
|
47
|
+
program.exitOverride();
|
|
48
|
+
// The default `.action()` below (banner on bare invocation) otherwise
|
|
49
|
+
// suppresses commander's implicit `help` command, so `skhema help [command]`
|
|
50
|
+
// would fall through to the unknown-command guard. Re-enable it explicitly.
|
|
51
|
+
program.helpCommand(true);
|
|
28
52
|
program
|
|
29
53
|
.name('skhema')
|
|
30
54
|
.description('Skhema CLI — drive the Skhema Public API from your terminal, CI, or agent')
|
|
@@ -43,7 +67,16 @@ export function buildProgram(version) {
|
|
|
43
67
|
setApiKeyFlag(opts.apiKey);
|
|
44
68
|
})
|
|
45
69
|
.action(() => {
|
|
46
|
-
//
|
|
70
|
+
// A bare `skhema` invocation shows the banner. Any leftover operand means
|
|
71
|
+
// an unknown command was given: commander routes it here (the default
|
|
72
|
+
// action) instead of erroring, so we must reject it ourselves — otherwise
|
|
73
|
+
// the banner prints and the process exits 0, hiding the mistake.
|
|
74
|
+
if (program.args.length > 0) {
|
|
75
|
+
program.error(`unknown command '${program.args[0]}'`, {
|
|
76
|
+
code: 'commander.unknownCommand',
|
|
77
|
+
exitCode: ExitCode.Usage,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
47
80
|
showBanner(version);
|
|
48
81
|
program.help();
|
|
49
82
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skhema/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Skhema CLI - Authentication and AI skills management for agent platforms",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,29 +20,12 @@
|
|
|
20
20
|
"skills"
|
|
21
21
|
],
|
|
22
22
|
"scripts": {
|
|
23
|
-
"dev": "tsc --watch",
|
|
24
23
|
"build": "tsc",
|
|
25
|
-
"
|
|
26
|
-
"lint:fix": "eslint . --fix",
|
|
27
|
-
"format": "prettier --write .",
|
|
28
|
-
"format:check": "prettier --check .",
|
|
29
|
-
"typecheck": "tsc --noEmit",
|
|
30
|
-
"test": "vitest run",
|
|
31
|
-
"test:watch": "vitest",
|
|
32
|
-
"clean": "rm -rf dist node_modules skills",
|
|
33
|
-
"clean:dist": "rm -rf dist",
|
|
34
|
-
"sync-skills": "tsx scripts/sync-skills.ts",
|
|
35
|
-
"prebuild": "npm run clean:dist && npm run sync-skills",
|
|
36
|
-
"prepack": "npm run sync-skills",
|
|
37
|
-
"check": "npm run typecheck && npm run lint && npm run format:check",
|
|
38
|
-
"check:fix": "npm run format && npm run lint:fix",
|
|
39
|
-
"prepublishOnly": "npm run build",
|
|
40
|
-
"postinstall": "node dist/postinstall.js || true",
|
|
41
|
-
"generate:cli-reference": "tsx scripts/generate-cli-reference.ts"
|
|
24
|
+
"prebuild": "rm -rf dist"
|
|
42
25
|
},
|
|
43
26
|
"dependencies": {
|
|
44
27
|
"@skhema/agent-sdk": "0.1.4",
|
|
45
|
-
"@skhema/method": "0.
|
|
28
|
+
"@skhema/method": "0.4.1",
|
|
46
29
|
"@skhema/sdk": "0.2.4",
|
|
47
30
|
"chalk": "^5.3.0",
|
|
48
31
|
"commander": "^12.0.0",
|
|
@@ -50,8 +33,6 @@
|
|
|
50
33
|
},
|
|
51
34
|
"devDependencies": {
|
|
52
35
|
"@mdx-js/mdx": "3.1.1",
|
|
53
|
-
"@skhema/linter": "2.3.0",
|
|
54
|
-
"@skhema/prettier-config": "1.0.0",
|
|
55
36
|
"@types/node": "^22.0.0",
|
|
56
37
|
"eslint": "^9.0.0",
|
|
57
38
|
"prettier": "^3.0.0",
|
|
@@ -67,5 +48,12 @@
|
|
|
67
48
|
"publishConfig": {
|
|
68
49
|
"access": "public"
|
|
69
50
|
},
|
|
70
|
-
"homepage": "https://skhema.com/docs/
|
|
51
|
+
"homepage": "https://skhema.com/docs/cli",
|
|
52
|
+
"repository": {
|
|
53
|
+
"type": "git",
|
|
54
|
+
"url": "git+https://github.com/skhema/cli.git"
|
|
55
|
+
},
|
|
56
|
+
"bugs": {
|
|
57
|
+
"url": "https://github.com/skhema/cli/issues"
|
|
58
|
+
}
|
|
71
59
|
}
|
|
@@ -38,8 +38,9 @@ to *write* the element — indicative for a judgment, imperative for a command,
|
|
|
38
38
|
a noun phrase for a thing. It is a check on the sentence. **Placement** tells
|
|
39
39
|
you *where the element is allowed to live*, and the platform enforces a strict
|
|
40
40
|
type→component allow-list that does NOT follow mood. Put a type in the wrong
|
|
41
|
-
component and `element create` rejects it.
|
|
42
|
-
|
|
41
|
+
component and `element create` rejects it. Discover it locally (no network)
|
|
42
|
+
with `skhema element types` (add `--json` for machine-readable output); the
|
|
43
|
+
allow-list is:
|
|
43
44
|
|
|
44
45
|
| Component | Element types it accepts |
|
|
45
46
|
|---|---|
|
|
@@ -83,13 +83,18 @@ thing we've decided is true" and "a thing we've decided to do about a danger" is
|
|
|
83
83
|
the whole discipline — an assumption you never test and a risk you never watch
|
|
84
84
|
are the same landmine wearing two hats.
|
|
85
85
|
|
|
86
|
-
**Encoding this in Skhema.** There is no `risk` element type in the taxonomy
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
86
|
+
**Encoding this in Skhema.** There is no `risk` element type in the taxonomy —
|
|
87
|
+
a deliberate decision (2026-07-20), not a gap. Encode both halves with the
|
|
88
|
+
types that exist. A belief is the bet stated as a claim: an
|
|
89
|
+
`assumption_hypothesis`. A risk is *also* an `assumption_hypothesis` — the bet
|
|
90
|
+
that the danger stays away — paired with a linked `experiment` or `action` that
|
|
91
|
+
carries the tripwire: the signal you'll watch and what you'll do when it fires.
|
|
92
|
+
The tripwire condition goes in the element's `reasoning` field. One refinement:
|
|
93
|
+
when the risk is really "this quantity must hold for the solution to stay
|
|
94
|
+
valid" — a threshold, a rate, a level — encode it as a `performance_variable`
|
|
95
|
+
(in Measures) instead; that is exactly what the type means, and it gives the
|
|
96
|
+
tripwire a measurable home. Don't reach for a `risk` type; it doesn't exist,
|
|
97
|
+
and won't unless a feature ever needs to query risks as first-class objects.
|
|
93
98
|
|
|
94
99
|
```
|
|
95
100
|
CAUSE 1 → ASSUMPTION: Sales team can sell upmarket.
|
package/skills/.manifest.json
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"syncedAt": "2026-07-09T17:15:20.908Z",
|
|
3
|
-
"source": "/Users/michaellovell/Desktop/GitHub/skhema-skills",
|
|
4
|
-
"sourceSha": "2a3abbb24f2fb2539608102eabc90de10fc9984b",
|
|
5
|
-
"skills": [
|
|
6
|
-
"skhema-frame",
|
|
7
|
-
"skhema-compose",
|
|
8
|
-
"skhema-calibrate",
|
|
9
|
-
"skhema-pressure-test",
|
|
10
|
-
"skhema-communicate",
|
|
11
|
-
"skhema-operate"
|
|
12
|
-
]
|
|
13
|
-
}
|