@djordje-stojanovic/sigmaskills 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +77 -0
- package/LICENSE +21 -0
- package/README.md +342 -0
- package/bin/sigmaskills.js +7 -0
- package/manifest.json +28 -0
- package/package.json +42 -0
- package/registry/agent-hosts.json +2404 -0
- package/registry/schema.json +110 -0
- package/registry/skill-baselines.json +4 -0
- package/registry/source.json +6 -0
- package/sigmabrief/SKILL.md +56 -0
- package/sigmabrief/agents/openai.yaml +12 -0
- package/sigmabrief/references/brief-method.md +73 -0
- package/sigmabrief/references/prompt-contract.md +174 -0
- package/sigmaperformance/SKILL.md +118 -0
- package/sigmaperformance/agents/openai.yaml +12 -0
- package/sigmaperformance/references/audit-method.md +112 -0
- package/sigmaperformance/references/calibration.md +45 -0
- package/sigmaperformance/references/report-contract.md +103 -0
- package/sigmareview/SKILL.md +133 -0
- package/sigmareview/agents/openai.yaml +12 -0
- package/sigmareview/references/report-contract.md +217 -0
- package/sigmareview/references/review-method.md +233 -0
- package/sigmawrite/SKILL.md +45 -0
- package/sigmawrite/agents/openai.yaml +12 -0
- package/src/adoption.js +370 -0
- package/src/backup.js +398 -0
- package/src/catalog.js +211 -0
- package/src/cli.js +657 -0
- package/src/customization.js +344 -0
- package/src/destinations.js +491 -0
- package/src/interactive.js +959 -0
- package/src/links.js +157 -0
- package/src/plan.js +429 -0
- package/src/prepack.js +10 -0
- package/src/project-lock.js +169 -0
- package/src/purge.js +477 -0
- package/src/registry/automation-ci.js +411 -0
- package/src/registry/automation.js +554 -0
- package/src/registry/diff.js +149 -0
- package/src/registry/normalize.js +67 -0
- package/src/registry/parse.js +184 -0
- package/src/registry/sync.js +230 -0
- package/src/registry/validate.js +223 -0
- package/src/release-ci.js +12 -0
- package/src/release.js +837 -0
- package/src/restore.js +518 -0
- package/src/revision.js +82 -0
- package/src/state.js +480 -0
- package/src/status.js +469 -0
- package/src/transaction.js +636 -0
- package/src/uninstall.js +647 -0
- package/src/update.js +815 -0
package/src/cli.js
ADDED
|
@@ -0,0 +1,657 @@
|
|
|
1
|
+
import { getCatalog, findPackageRoot } from './catalog.js';
|
|
2
|
+
import { formatPlanHuman, formatPlanJson } from './plan.js';
|
|
3
|
+
import { runProjectInstaller } from './interactive.js';
|
|
4
|
+
import { collectStatus, formatStatusHuman, formatStatusJson } from './status.js';
|
|
5
|
+
import { executeUpdate, formatUpdateHuman, formatUpdateJson } from './update.js';
|
|
6
|
+
import { executeRestore, formatRestoreHuman, formatRestoreJson } from './restore.js';
|
|
7
|
+
import { executeUninstall, formatUninstallHuman, formatUninstallJson } from './uninstall.js';
|
|
8
|
+
import {
|
|
9
|
+
PURGE_CONFIRMATION_PHRASE,
|
|
10
|
+
executePurge,
|
|
11
|
+
formatPurgeHuman,
|
|
12
|
+
formatPurgeJson,
|
|
13
|
+
} from './purge.js';
|
|
14
|
+
import {
|
|
15
|
+
executeRelease,
|
|
16
|
+
formatReleaseHuman,
|
|
17
|
+
formatReleaseJson,
|
|
18
|
+
} from './release.js';
|
|
19
|
+
import { executeProjectInstall } from './transaction.js';
|
|
20
|
+
import { resolveHomeDir } from './destinations.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Format and print help message.
|
|
24
|
+
*
|
|
25
|
+
* @param {object} catalog
|
|
26
|
+
* @returns {string}
|
|
27
|
+
*/
|
|
28
|
+
export function buildHelpText(catalog) {
|
|
29
|
+
const version = catalog.manifest.version;
|
|
30
|
+
const skillsList = catalog.skills
|
|
31
|
+
.map((s) => ` - ${s.id.padEnd(18)} ${s.title.padEnd(20)} (${s.revision.slice(0, 8)}…)`)
|
|
32
|
+
.join('\n');
|
|
33
|
+
|
|
34
|
+
return `sigmaskills v${version}
|
|
35
|
+
Portable Agent Skills monorepo and first-party Sigma Installer
|
|
36
|
+
|
|
37
|
+
Usage:
|
|
38
|
+
sigmaskills [options] [command]
|
|
39
|
+
|
|
40
|
+
Commands:
|
|
41
|
+
install <skill> Install a skill into the project (.agents/skills/<skill>)
|
|
42
|
+
add <skill> Alias for install
|
|
43
|
+
update Update selected whole skills to the running CLI Release
|
|
44
|
+
restore Restore the latest retained backup for a skill
|
|
45
|
+
uninstall Uninstall selected skills or every recorded skill in one scope after Uninstall Review
|
|
46
|
+
purge Remove all Sigma-owned content in one scope after the typed confirmation phrase
|
|
47
|
+
release Prepare or dispatch an owner-triggered GitHub and npm Release
|
|
48
|
+
status Report managed Project or Global Installation state and drift
|
|
49
|
+
list List all shipped skills and their Skill Revisions
|
|
50
|
+
verify Validate manifest, skill resources, and compute revisions
|
|
51
|
+
|
|
52
|
+
Options:
|
|
53
|
+
-v, --version Show version number
|
|
54
|
+
-h, --help Show help
|
|
55
|
+
--skill <name> Skill identifier to install, update, restore, or uninstall (repeatable)
|
|
56
|
+
--all Uninstall every recorded Sigma skill in the chosen Project or Global scope
|
|
57
|
+
--dry-run Preview install, update, restore, uninstall, purge, or release without writing files
|
|
58
|
+
--confirm-purge <phrase>
|
|
59
|
+
Exact typed confirmation for purge; --yes, CI, non-TTY, and JSON are not enough
|
|
60
|
+
--write-identities
|
|
61
|
+
Write package, manifest, and changelog version identities for the calculated Release
|
|
62
|
+
--expected-commit <sha>
|
|
63
|
+
Approved source commit for release dispatch
|
|
64
|
+
--expected-version <version>
|
|
65
|
+
Approved Release version for release dispatch
|
|
66
|
+
--expected-digest <sha256>
|
|
67
|
+
Approved tarball SHA-256 digest for release dispatch
|
|
68
|
+
--json Output in versioned JSON format
|
|
69
|
+
--project <path> Target project root directory (defaults to current directory)
|
|
70
|
+
--global User-level Global Installation (requires --yes to write)
|
|
71
|
+
--state-dir <dir> Custom state directory for private machine state
|
|
72
|
+
--destination <dir> Project destination root (repeatable; default .agents/skills)
|
|
73
|
+
--link Recommended links: Windows junctions, macOS/Linux symbolic links
|
|
74
|
+
--copy Independent managed copy at every selected destination
|
|
75
|
+
--adopt-changed <replace|skip|export>
|
|
76
|
+
Resolve changed owned or drifted trees
|
|
77
|
+
--adopt-legacy <replace|skip|export>
|
|
78
|
+
Resolve trees that match a bundled historical baseline
|
|
79
|
+
--adopt-unverified <replace|skip|export>
|
|
80
|
+
Resolve Sigma-looking trees without a baseline
|
|
81
|
+
--adopt-malformed <replace|skip|export>
|
|
82
|
+
Resolve trees with malformed customization markers
|
|
83
|
+
--outside-edit <replace|skip|export>
|
|
84
|
+
Resolve outside-customization edits during update
|
|
85
|
+
--malformed-markers <skip|repair|replace>
|
|
86
|
+
Resolve malformed customization markers during update
|
|
87
|
+
--clean <remove|keep>
|
|
88
|
+
Uninstall Review choice for a clean skill
|
|
89
|
+
--changed <backup|keep|export|delete>
|
|
90
|
+
Uninstall Review choice for a changed, customized, or malformed skill
|
|
91
|
+
--export-dir <dir>
|
|
92
|
+
Collision-safe destination root for export resolutions
|
|
93
|
+
--no-color Disable color and reveal animation
|
|
94
|
+
--static Disable animation and screen repainting
|
|
95
|
+
--narrow Use the narrow-terminal layout
|
|
96
|
+
-y, --yes Skip interactive confirmations
|
|
97
|
+
|
|
98
|
+
Run without a command to start the interactive Project Installation.
|
|
99
|
+
|
|
100
|
+
Available Skills:
|
|
101
|
+
${skillsList}
|
|
102
|
+
`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Parse CLI arguments into structured options.
|
|
107
|
+
*
|
|
108
|
+
* @param {string[]} args
|
|
109
|
+
* @returns {object}
|
|
110
|
+
*/
|
|
111
|
+
export function parseCliArgs(args) {
|
|
112
|
+
const parsed = {
|
|
113
|
+
command: null,
|
|
114
|
+
skillId: null,
|
|
115
|
+
skillIds: [],
|
|
116
|
+
projectRoot: null,
|
|
117
|
+
stateDir: null,
|
|
118
|
+
dryRun: false,
|
|
119
|
+
json: false,
|
|
120
|
+
help: false,
|
|
121
|
+
version: false,
|
|
122
|
+
yes: false,
|
|
123
|
+
global: false,
|
|
124
|
+
noColor: false,
|
|
125
|
+
static: false,
|
|
126
|
+
narrow: false,
|
|
127
|
+
method: null,
|
|
128
|
+
destinations: [],
|
|
129
|
+
adoptChanged: null,
|
|
130
|
+
adoptLegacy: null,
|
|
131
|
+
adoptUnverified: null,
|
|
132
|
+
adoptMalformed: null,
|
|
133
|
+
outsideEdit: null,
|
|
134
|
+
malformedMarkers: null,
|
|
135
|
+
clean: null,
|
|
136
|
+
changed: null,
|
|
137
|
+
exportDir: null,
|
|
138
|
+
all: false,
|
|
139
|
+
confirmPurge: undefined,
|
|
140
|
+
writeIdentities: false,
|
|
141
|
+
expectedCommit: null,
|
|
142
|
+
expectedVersion: null,
|
|
143
|
+
expectedDigest: null,
|
|
144
|
+
unknown: [],
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
for (let i = 0; i < args.length; i++) {
|
|
148
|
+
const arg = args[i];
|
|
149
|
+
if (arg === '-h' || arg === '--help') {
|
|
150
|
+
parsed.help = true;
|
|
151
|
+
} else if (arg === '-v' || arg === '--version') {
|
|
152
|
+
parsed.version = true;
|
|
153
|
+
} else if (arg === '--all') {
|
|
154
|
+
parsed.all = true;
|
|
155
|
+
} else if (arg === '--dry-run') {
|
|
156
|
+
parsed.dryRun = true;
|
|
157
|
+
} else if (arg === '--json') {
|
|
158
|
+
parsed.json = true;
|
|
159
|
+
} else if (arg === '-y' || arg === '--yes') {
|
|
160
|
+
parsed.yes = true;
|
|
161
|
+
} else if (arg === '-g' || arg === '--global') {
|
|
162
|
+
parsed.global = true;
|
|
163
|
+
} else if (arg === '--no-color') {
|
|
164
|
+
parsed.noColor = true;
|
|
165
|
+
} else if (arg === '--static') {
|
|
166
|
+
parsed.static = true;
|
|
167
|
+
} else if (arg === '--narrow') {
|
|
168
|
+
parsed.narrow = true;
|
|
169
|
+
} else if (arg === '--copy') {
|
|
170
|
+
parsed.method = parsed.method && parsed.method !== 'copy' ? 'conflict' : 'copy';
|
|
171
|
+
} else if (arg === '--link') {
|
|
172
|
+
parsed.method = parsed.method && parsed.method !== 'link' ? 'conflict' : 'link';
|
|
173
|
+
} else if (arg === '--adopt-changed') {
|
|
174
|
+
parsed.adoptChanged = args[++i];
|
|
175
|
+
} else if (arg.startsWith('--adopt-changed=')) {
|
|
176
|
+
parsed.adoptChanged = arg.slice('--adopt-changed='.length);
|
|
177
|
+
} else if (arg === '--adopt-legacy') {
|
|
178
|
+
parsed.adoptLegacy = args[++i];
|
|
179
|
+
} else if (arg.startsWith('--adopt-legacy=')) {
|
|
180
|
+
parsed.adoptLegacy = arg.slice('--adopt-legacy='.length);
|
|
181
|
+
} else if (arg === '--adopt-unverified') {
|
|
182
|
+
parsed.adoptUnverified = args[++i];
|
|
183
|
+
} else if (arg.startsWith('--adopt-unverified=')) {
|
|
184
|
+
parsed.adoptUnverified = arg.slice('--adopt-unverified='.length);
|
|
185
|
+
} else if (arg === '--adopt-malformed') {
|
|
186
|
+
parsed.adoptMalformed = args[++i];
|
|
187
|
+
} else if (arg.startsWith('--adopt-malformed=')) {
|
|
188
|
+
parsed.adoptMalformed = arg.slice('--adopt-malformed='.length);
|
|
189
|
+
} else if (arg === '--outside-edit') {
|
|
190
|
+
parsed.outsideEdit = args[++i];
|
|
191
|
+
} else if (arg.startsWith('--outside-edit=')) {
|
|
192
|
+
parsed.outsideEdit = arg.slice('--outside-edit='.length);
|
|
193
|
+
} else if (arg === '--malformed-markers') {
|
|
194
|
+
parsed.malformedMarkers = args[++i];
|
|
195
|
+
} else if (arg.startsWith('--malformed-markers=')) {
|
|
196
|
+
parsed.malformedMarkers = arg.slice('--malformed-markers='.length);
|
|
197
|
+
} else if (arg === '--clean') {
|
|
198
|
+
parsed.clean = args[++i];
|
|
199
|
+
} else if (arg.startsWith('--clean=')) {
|
|
200
|
+
parsed.clean = arg.slice('--clean='.length);
|
|
201
|
+
} else if (arg === '--changed') {
|
|
202
|
+
parsed.changed = args[++i];
|
|
203
|
+
} else if (arg.startsWith('--changed=')) {
|
|
204
|
+
parsed.changed = arg.slice('--changed='.length);
|
|
205
|
+
} else if (arg === '--export-dir') {
|
|
206
|
+
parsed.exportDir = args[++i];
|
|
207
|
+
} else if (arg.startsWith('--export-dir=')) {
|
|
208
|
+
parsed.exportDir = arg.slice('--export-dir='.length);
|
|
209
|
+
} else if (arg === '--write-identities') {
|
|
210
|
+
parsed.writeIdentities = true;
|
|
211
|
+
} else if (arg === '--expected-commit') {
|
|
212
|
+
parsed.expectedCommit = args[++i];
|
|
213
|
+
} else if (arg.startsWith('--expected-commit=')) {
|
|
214
|
+
parsed.expectedCommit = arg.slice('--expected-commit='.length);
|
|
215
|
+
} else if (arg === '--expected-version') {
|
|
216
|
+
parsed.expectedVersion = args[++i];
|
|
217
|
+
} else if (arg.startsWith('--expected-version=')) {
|
|
218
|
+
parsed.expectedVersion = arg.slice('--expected-version='.length);
|
|
219
|
+
} else if (arg === '--expected-digest') {
|
|
220
|
+
parsed.expectedDigest = args[++i];
|
|
221
|
+
} else if (arg.startsWith('--expected-digest=')) {
|
|
222
|
+
parsed.expectedDigest = arg.slice('--expected-digest='.length);
|
|
223
|
+
} else if (arg === '--confirm-purge') {
|
|
224
|
+
parsed.confirmPurge = args[++i] ?? '';
|
|
225
|
+
} else if (arg.startsWith('--confirm-purge=')) {
|
|
226
|
+
parsed.confirmPurge = arg.slice('--confirm-purge='.length);
|
|
227
|
+
} else if (arg === '--destination') {
|
|
228
|
+
parsed.destinations.push(args[++i]);
|
|
229
|
+
} else if (arg.startsWith('--destination=')) {
|
|
230
|
+
parsed.destinations.push(arg.slice('--destination='.length));
|
|
231
|
+
} else if (arg === '--skill') {
|
|
232
|
+
parsed.skillId = args[++i];
|
|
233
|
+
if (parsed.skillId) parsed.skillIds.push(parsed.skillId);
|
|
234
|
+
} else if (arg.startsWith('--skill=')) {
|
|
235
|
+
parsed.skillId = arg.slice('--skill='.length);
|
|
236
|
+
if (parsed.skillId) parsed.skillIds.push(parsed.skillId);
|
|
237
|
+
} else if (arg === '--project' || arg === '--cwd') {
|
|
238
|
+
parsed.projectRoot = args[++i];
|
|
239
|
+
} else if (arg.startsWith('--project=')) {
|
|
240
|
+
parsed.projectRoot = arg.slice('--project='.length);
|
|
241
|
+
} else if (arg.startsWith('--cwd=')) {
|
|
242
|
+
parsed.projectRoot = arg.slice('--cwd='.length);
|
|
243
|
+
} else if (arg === '--state-dir') {
|
|
244
|
+
parsed.stateDir = args[++i];
|
|
245
|
+
} else if (arg.startsWith('--state-dir=')) {
|
|
246
|
+
parsed.stateDir = arg.slice('--state-dir='.length);
|
|
247
|
+
} else if (
|
|
248
|
+
!parsed.command &&
|
|
249
|
+
(arg === 'list' || arg === 'verify' || arg === 'check' || arg === 'install' || arg === 'add' || arg === 'status' || arg === 'update' || arg === 'restore' || arg === 'uninstall' || arg === 'purge' || arg === 'release')
|
|
250
|
+
) {
|
|
251
|
+
parsed.command = arg;
|
|
252
|
+
} else if (!parsed.skillId && (parsed.command === 'install' || parsed.command === 'add')) {
|
|
253
|
+
parsed.skillId = arg;
|
|
254
|
+
} else if ((parsed.command === 'update' || parsed.command === 'restore' || parsed.command === 'uninstall') && !arg.startsWith('-')) {
|
|
255
|
+
parsed.skillIds.push(arg);
|
|
256
|
+
} else if (arg === '--list') {
|
|
257
|
+
parsed.command = 'list';
|
|
258
|
+
} else {
|
|
259
|
+
parsed.unknown.push(arg);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return parsed;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function readStdinLine(stdin) {
|
|
267
|
+
return new Promise((resolve) => {
|
|
268
|
+
if (!stdin) {
|
|
269
|
+
resolve('');
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
let settled = false;
|
|
273
|
+
let buffer = '';
|
|
274
|
+
const finish = () => {
|
|
275
|
+
if (settled) return;
|
|
276
|
+
settled = true;
|
|
277
|
+
stdin.off('data', onData);
|
|
278
|
+
stdin.off('end', finish);
|
|
279
|
+
if (typeof stdin.pause === 'function') stdin.pause();
|
|
280
|
+
resolve(buffer.split(/\r?\n/)[0] ?? '');
|
|
281
|
+
};
|
|
282
|
+
const onData = (chunk) => {
|
|
283
|
+
buffer += String(chunk);
|
|
284
|
+
if (buffer.includes('\n') || buffer.includes('\r')) finish();
|
|
285
|
+
};
|
|
286
|
+
stdin.on('data', onData);
|
|
287
|
+
stdin.once('end', finish);
|
|
288
|
+
if (typeof stdin.resume === 'function') stdin.resume();
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Main CLI entrypoint.
|
|
294
|
+
*
|
|
295
|
+
* @param {string[]} args Command-line arguments
|
|
296
|
+
* @param {object} [io] Optional custom stdin/stdout/stderr stream handles
|
|
297
|
+
* @returns {Promise<number>} Exit code (0 for success, 1 for failure)
|
|
298
|
+
*/
|
|
299
|
+
export async function runCli(args = process.argv.slice(2), io = { stdout: process.stdout, stderr: process.stderr }) {
|
|
300
|
+
const writeOut = (str) => io.stdout.write(str.endsWith('\n') ? str : `${str}\n`);
|
|
301
|
+
const writeErr = (str) => io.stderr.write(str.endsWith('\n') ? str : `${str}\n`);
|
|
302
|
+
|
|
303
|
+
try {
|
|
304
|
+
const opts = parseCliArgs(args);
|
|
305
|
+
const rootDir = findPackageRoot();
|
|
306
|
+
const catalog = getCatalog(rootDir);
|
|
307
|
+
|
|
308
|
+
if (opts.help) {
|
|
309
|
+
writeOut(buildHelpText(catalog));
|
|
310
|
+
return 0;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (opts.version) {
|
|
314
|
+
writeOut(catalog.manifest.version);
|
|
315
|
+
return 0;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (opts.unknown.length > 0) {
|
|
319
|
+
writeErr(`sigmaskills error: unknown option or command: ${opts.unknown[0]}`);
|
|
320
|
+
writeErr(`Run 'sigmaskills --help' for usage information.`);
|
|
321
|
+
return 1;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (opts.method === 'conflict') {
|
|
325
|
+
writeErr('sigmaskills error: use either --link or --copy, not both');
|
|
326
|
+
return 1;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const adoptFlags = [
|
|
330
|
+
['--adopt-changed', opts.adoptChanged],
|
|
331
|
+
['--adopt-legacy', opts.adoptLegacy],
|
|
332
|
+
['--adopt-unverified', opts.adoptUnverified],
|
|
333
|
+
['--adopt-malformed', opts.adoptMalformed],
|
|
334
|
+
];
|
|
335
|
+
for (const [flag, value] of adoptFlags) {
|
|
336
|
+
if (value && value !== 'replace' && value !== 'skip' && value !== 'export') {
|
|
337
|
+
writeErr(`sigmaskills error: ${flag} must be replace, skip, or export`);
|
|
338
|
+
return 1;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (opts.outsideEdit && opts.outsideEdit !== 'replace' && opts.outsideEdit !== 'skip' && opts.outsideEdit !== 'export') {
|
|
343
|
+
writeErr('sigmaskills error: --outside-edit must be replace, skip, or export');
|
|
344
|
+
return 1;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (opts.malformedMarkers && opts.malformedMarkers !== 'replace' && opts.malformedMarkers !== 'skip' && opts.malformedMarkers !== 'repair') {
|
|
348
|
+
writeErr('sigmaskills error: --malformed-markers must be skip, repair, or replace');
|
|
349
|
+
return 1;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (opts.clean && opts.clean !== 'remove' && opts.clean !== 'keep') {
|
|
353
|
+
writeErr('sigmaskills error: --clean must be remove or keep');
|
|
354
|
+
return 1;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (opts.changed && opts.changed !== 'backup' && opts.changed !== 'keep' && opts.changed !== 'export' && opts.changed !== 'delete') {
|
|
358
|
+
writeErr('sigmaskills error: --changed must be backup, keep, export, or delete');
|
|
359
|
+
return 1;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (opts.command === 'release') {
|
|
363
|
+
const adapters = io.release || {};
|
|
364
|
+
const result = executeRelease({
|
|
365
|
+
rootDir: adapters.rootDir || rootDir,
|
|
366
|
+
catalog: adapters.catalog || catalog,
|
|
367
|
+
dryRun: opts.dryRun,
|
|
368
|
+
yes: opts.yes,
|
|
369
|
+
writeIdentities: opts.writeIdentities,
|
|
370
|
+
expectedCommit: opts.expectedCommit,
|
|
371
|
+
expectedVersion: opts.expectedVersion,
|
|
372
|
+
expectedDigest: opts.expectedDigest,
|
|
373
|
+
git: adapters.git,
|
|
374
|
+
pack: adapters.pack,
|
|
375
|
+
probes: adapters.probes,
|
|
376
|
+
dispatch: adapters.dispatch,
|
|
377
|
+
workflow: adapters.workflow,
|
|
378
|
+
now: adapters.now,
|
|
379
|
+
});
|
|
380
|
+
writeOut(opts.json ? formatReleaseJson(result) : formatReleaseHuman(result));
|
|
381
|
+
return 0;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (opts.command === 'purge') {
|
|
385
|
+
const env = io.env || process.env;
|
|
386
|
+
const stdin = io.stdin || process.stdin;
|
|
387
|
+
let confirmPurge = opts.confirmPurge;
|
|
388
|
+
if (!opts.dryRun && confirmPurge === undefined) {
|
|
389
|
+
const ci = env.CI;
|
|
390
|
+
const nonInteractive = Boolean(opts.json)
|
|
391
|
+
|| (ci !== undefined && ci !== '' && ci !== '0' && String(ci).toLowerCase() !== 'false')
|
|
392
|
+
|| !stdin.isTTY;
|
|
393
|
+
if (nonInteractive) {
|
|
394
|
+
writeErr('sigmaskills error: purge requires --confirm-purge with the typed confirmation phrase; --yes, CI, non-TTY, and JSON are not authority');
|
|
395
|
+
return 1;
|
|
396
|
+
}
|
|
397
|
+
writeOut(formatPurgeHuman(executePurge({
|
|
398
|
+
catalog,
|
|
399
|
+
projectRoot: opts.projectRoot || process.cwd(),
|
|
400
|
+
homeDir: resolveHomeDir(env),
|
|
401
|
+
scope: opts.global ? 'global' : 'project',
|
|
402
|
+
customStateDir: opts.stateDir,
|
|
403
|
+
packageRoot: rootDir,
|
|
404
|
+
dryRun: true,
|
|
405
|
+
env,
|
|
406
|
+
})));
|
|
407
|
+
writeOut(`Type ${PURGE_CONFIRMATION_PHRASE} to purge, or nothing to cancel.`);
|
|
408
|
+
confirmPurge = await readStdinLine(stdin);
|
|
409
|
+
}
|
|
410
|
+
const result = executePurge({
|
|
411
|
+
catalog,
|
|
412
|
+
projectRoot: opts.projectRoot || process.cwd(),
|
|
413
|
+
homeDir: resolveHomeDir(env),
|
|
414
|
+
scope: opts.global ? 'global' : 'project',
|
|
415
|
+
customStateDir: opts.stateDir,
|
|
416
|
+
packageRoot: rootDir,
|
|
417
|
+
dryRun: opts.dryRun,
|
|
418
|
+
env,
|
|
419
|
+
confirmPurge,
|
|
420
|
+
});
|
|
421
|
+
writeOut(opts.json ? formatPurgeJson(result) : formatPurgeHuman(result));
|
|
422
|
+
return 0;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if (opts.command === 'update') {
|
|
426
|
+
const env = io.env || process.env;
|
|
427
|
+
if (opts.global && !opts.dryRun && !opts.yes) {
|
|
428
|
+
writeErr('sigmaskills error: Global Installation requires both --global and --yes; CI, TTY, JSON, and Agent Host detection never imply that authority');
|
|
429
|
+
return 1;
|
|
430
|
+
}
|
|
431
|
+
if (!opts.dryRun && !opts.yes && opts.skillIds.length === 0) {
|
|
432
|
+
writeErr('sigmaskills error: update requires --yes to apply all changed skills, or --skill <id> to select complete skills; use --dry-run to preview');
|
|
433
|
+
return 1;
|
|
434
|
+
}
|
|
435
|
+
const result = executeUpdate({
|
|
436
|
+
catalog,
|
|
437
|
+
projectRoot: opts.projectRoot || process.cwd(),
|
|
438
|
+
homeDir: resolveHomeDir(env),
|
|
439
|
+
scope: opts.global ? 'global' : 'project',
|
|
440
|
+
customStateDir: opts.stateDir,
|
|
441
|
+
packageRoot: rootDir,
|
|
442
|
+
dryRun: opts.dryRun,
|
|
443
|
+
env,
|
|
444
|
+
skillIds: opts.skillIds,
|
|
445
|
+
outsideEdit: opts.outsideEdit || undefined,
|
|
446
|
+
malformedMarkers: opts.malformedMarkers || undefined,
|
|
447
|
+
exportDir: opts.exportDir || undefined,
|
|
448
|
+
});
|
|
449
|
+
writeOut(opts.json ? formatUpdateJson(result) : formatUpdateHuman(result));
|
|
450
|
+
return 0;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (opts.command === 'uninstall') {
|
|
454
|
+
const env = io.env || process.env;
|
|
455
|
+
if (opts.global && !opts.dryRun && !opts.yes) {
|
|
456
|
+
writeErr('sigmaskills error: Global Installation requires both --global and --yes; CI, TTY, JSON, and Agent Host detection never imply that authority');
|
|
457
|
+
return 1;
|
|
458
|
+
}
|
|
459
|
+
if (opts.all && opts.skillIds.length > 0) {
|
|
460
|
+
writeErr('sigmaskills error: uninstall --all cannot be combined with --skill');
|
|
461
|
+
return 1;
|
|
462
|
+
}
|
|
463
|
+
if (opts.skillIds.length === 0 && !opts.all) {
|
|
464
|
+
writeErr('sigmaskills error: uninstall requires --skill <id> or --all');
|
|
465
|
+
return 1;
|
|
466
|
+
}
|
|
467
|
+
if (!opts.dryRun && !opts.yes) {
|
|
468
|
+
writeErr('sigmaskills error: uninstall requires --yes to apply, or --dry-run to preview');
|
|
469
|
+
return 1;
|
|
470
|
+
}
|
|
471
|
+
const result = executeUninstall({
|
|
472
|
+
catalog,
|
|
473
|
+
projectRoot: opts.projectRoot || process.cwd(),
|
|
474
|
+
homeDir: resolveHomeDir(env),
|
|
475
|
+
scope: opts.global ? 'global' : 'project',
|
|
476
|
+
customStateDir: opts.stateDir,
|
|
477
|
+
packageRoot: rootDir,
|
|
478
|
+
dryRun: opts.dryRun,
|
|
479
|
+
env,
|
|
480
|
+
skillIds: opts.skillIds,
|
|
481
|
+
all: opts.all,
|
|
482
|
+
yes: opts.yes,
|
|
483
|
+
clean: opts.clean || (opts.yes || opts.all ? 'remove' : undefined),
|
|
484
|
+
changed: opts.changed || (opts.all ? 'backup' : undefined),
|
|
485
|
+
exportDir: opts.exportDir || undefined,
|
|
486
|
+
});
|
|
487
|
+
writeOut(opts.json ? formatUninstallJson(result) : formatUninstallHuman(result));
|
|
488
|
+
if ((result.summary?.failed || []).length > 0) return 1;
|
|
489
|
+
return 0;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
if (opts.command === 'restore') {
|
|
493
|
+
const env = io.env || process.env;
|
|
494
|
+
if (opts.global && !opts.dryRun && !opts.yes) {
|
|
495
|
+
writeErr('sigmaskills error: Global Installation requires both --global and --yes; CI, TTY, JSON, and Agent Host detection never imply that authority');
|
|
496
|
+
return 1;
|
|
497
|
+
}
|
|
498
|
+
if (opts.skillIds.length === 0) {
|
|
499
|
+
writeErr('sigmaskills error: restore requires --skill <id>');
|
|
500
|
+
return 1;
|
|
501
|
+
}
|
|
502
|
+
if (!opts.dryRun && !opts.yes) {
|
|
503
|
+
writeErr('sigmaskills error: restore requires --yes to apply, or --dry-run to preview');
|
|
504
|
+
return 1;
|
|
505
|
+
}
|
|
506
|
+
const result = executeRestore({
|
|
507
|
+
catalog,
|
|
508
|
+
projectRoot: opts.projectRoot || process.cwd(),
|
|
509
|
+
homeDir: resolveHomeDir(env),
|
|
510
|
+
scope: opts.global ? 'global' : 'project',
|
|
511
|
+
customStateDir: opts.stateDir,
|
|
512
|
+
packageRoot: rootDir,
|
|
513
|
+
dryRun: opts.dryRun,
|
|
514
|
+
env,
|
|
515
|
+
skillIds: opts.skillIds,
|
|
516
|
+
yes: opts.yes,
|
|
517
|
+
});
|
|
518
|
+
writeOut(opts.json ? formatRestoreJson(result) : formatRestoreHuman(result));
|
|
519
|
+
return 0;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
if (opts.command === 'status') {
|
|
523
|
+
const env = io.env || process.env;
|
|
524
|
+
const report = collectStatus({
|
|
525
|
+
catalog,
|
|
526
|
+
projectRoot: opts.projectRoot || process.cwd(),
|
|
527
|
+
homeDir: resolveHomeDir(env),
|
|
528
|
+
scope: opts.global ? 'global' : 'project',
|
|
529
|
+
customStateDir: opts.stateDir,
|
|
530
|
+
packageRoot: rootDir,
|
|
531
|
+
env,
|
|
532
|
+
});
|
|
533
|
+
writeOut(opts.json ? formatStatusJson(report) : formatStatusHuman(report));
|
|
534
|
+
return 0;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
if (opts.command === 'list' || (!opts.command && opts.json && !opts.skillId)) {
|
|
538
|
+
if (opts.json) {
|
|
539
|
+
const payload = {
|
|
540
|
+
name: catalog.manifest.name,
|
|
541
|
+
version: catalog.manifest.version,
|
|
542
|
+
schemaVersion: catalog.manifest.schemaVersion,
|
|
543
|
+
skills: catalog.skills.map((s) => ({
|
|
544
|
+
id: s.id,
|
|
545
|
+
title: s.title,
|
|
546
|
+
description: s.description,
|
|
547
|
+
revision: s.revision,
|
|
548
|
+
files: s.files,
|
|
549
|
+
})),
|
|
550
|
+
};
|
|
551
|
+
writeOut(JSON.stringify(payload, null, 2));
|
|
552
|
+
} else {
|
|
553
|
+
writeOut(`Skill Pack: ${catalog.manifest.name} v${catalog.manifest.version}\n`);
|
|
554
|
+
for (const skill of catalog.skills) {
|
|
555
|
+
writeOut(`• ${skill.title} (${skill.id})`);
|
|
556
|
+
writeOut(` Revision: ${skill.revision}`);
|
|
557
|
+
writeOut(` Description: ${skill.description}\n`);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return 0;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
if (opts.command === 'verify' || opts.command === 'check') {
|
|
564
|
+
writeOut(`✔ Manifest verified (${catalog.manifest.name} v${catalog.manifest.version})`);
|
|
565
|
+
for (const skill of catalog.skills) {
|
|
566
|
+
const fileCount = Object.keys(skill.files).length;
|
|
567
|
+
writeOut(`✔ Skill '${skill.id}': ${fileCount} files verified (revision ${skill.revision.slice(0, 12)}…)`);
|
|
568
|
+
}
|
|
569
|
+
writeOut(`\nAll ${catalog.skills.length} skills in Skill Pack validated successfully.`);
|
|
570
|
+
return 0;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
if (opts.command === 'install' || opts.command === 'add' || opts.skillId) {
|
|
574
|
+
if (!opts.skillId) {
|
|
575
|
+
writeErr("sigmaskills error: missing required skill name for install command (e.g. 'sigmaskills install sigmawrite')");
|
|
576
|
+
return 1;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
if (opts.global && !opts.dryRun && !opts.yes) {
|
|
580
|
+
writeErr('sigmaskills error: Global Installation requires both --global and --yes; CI, TTY, JSON, and Agent Host detection never imply that authority');
|
|
581
|
+
return 1;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
const env = io.env || process.env;
|
|
585
|
+
const result = executeProjectInstall({
|
|
586
|
+
catalog,
|
|
587
|
+
skillId: opts.skillId,
|
|
588
|
+
projectRoot: opts.projectRoot,
|
|
589
|
+
homeDir: resolveHomeDir(env),
|
|
590
|
+
scope: opts.global ? 'global' : 'project',
|
|
591
|
+
customStateDir: opts.stateDir,
|
|
592
|
+
packageRoot: rootDir,
|
|
593
|
+
dryRun: opts.dryRun,
|
|
594
|
+
env,
|
|
595
|
+
selectedRoots: opts.destinations.length > 0 ? opts.destinations : undefined,
|
|
596
|
+
method: opts.method || undefined,
|
|
597
|
+
adoptChanged: opts.adoptChanged || undefined,
|
|
598
|
+
adoptLegacy: opts.adoptLegacy || undefined,
|
|
599
|
+
adoptUnverified: opts.adoptUnverified || undefined,
|
|
600
|
+
adoptMalformed: opts.adoptMalformed || undefined,
|
|
601
|
+
exportDir: opts.exportDir || undefined,
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
if (opts.json) {
|
|
605
|
+
writeOut(formatPlanJson(result.plan));
|
|
606
|
+
} else {
|
|
607
|
+
writeOut(formatPlanHuman(result.plan));
|
|
608
|
+
if (!opts.dryRun) {
|
|
609
|
+
writeOut('');
|
|
610
|
+
for (const dest of result.plan.destinations) {
|
|
611
|
+
const method = dest.method ? ` [${dest.method}]` : '';
|
|
612
|
+
writeOut(`✔ Installed ${result.plan.title} (${result.plan.skill}) to ${dest.relativeDestination}${method}`);
|
|
613
|
+
}
|
|
614
|
+
writeOut(` Revision: ${result.plan.sourceRevision}`);
|
|
615
|
+
if (result.plan.scope !== 'global') {
|
|
616
|
+
writeOut(` Project lock: skills-lock.json updated`);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
return 0;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
if (!opts.command && !opts.skillId && !opts.dryRun && !opts.yes) {
|
|
624
|
+
return await runProjectInstaller({
|
|
625
|
+
catalog,
|
|
626
|
+
packageRoot: rootDir,
|
|
627
|
+
projectRoot: opts.projectRoot || process.cwd(),
|
|
628
|
+
homeDir: resolveHomeDir(io.env || process.env),
|
|
629
|
+
customStateDir: opts.stateDir,
|
|
630
|
+
initialScope: opts.global ? 'global' : 'project',
|
|
631
|
+
io: {
|
|
632
|
+
stdin: io.stdin || process.stdin,
|
|
633
|
+
stdout: io.stdout,
|
|
634
|
+
stderr: io.stderr,
|
|
635
|
+
env: io.env || process.env,
|
|
636
|
+
},
|
|
637
|
+
options: {
|
|
638
|
+
noColor: opts.noColor,
|
|
639
|
+
static: opts.static,
|
|
640
|
+
narrow: opts.narrow,
|
|
641
|
+
json: opts.json,
|
|
642
|
+
},
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
writeErr(`sigmaskills error: unknown option or command`);
|
|
647
|
+
writeErr(`Run 'sigmaskills --help' for usage information.`);
|
|
648
|
+
return 1;
|
|
649
|
+
} catch (err) {
|
|
650
|
+
writeErr(`sigmaskills error: ${err.message}`);
|
|
651
|
+
if (err.linkFailure) {
|
|
652
|
+
writeErr(`Link failed for '${err.linkFailure.relativeDestination || err.linkFailure.destination}'.`);
|
|
653
|
+
writeErr('The installer did not change method. Re-run with --copy to install a complete managed copy at this destination.');
|
|
654
|
+
}
|
|
655
|
+
return 1;
|
|
656
|
+
}
|
|
657
|
+
}
|