feat(skills): support install preflight-only mode
This commit is contained in:
+11
-2
@@ -1379,6 +1379,15 @@
|
|||||||
"src/cli/skills.test.ts"
|
"src/cli/skills.test.ts"
|
||||||
],
|
],
|
||||||
"test_status": "pnpm typecheck + pnpm test:run src/cli/skills.test.ts + pnpm test:run + pnpm lint (warnings only, 0 errors) + pnpm build passing"
|
"test_status": "pnpm typecheck + pnpm test:run src/cli/skills.test.ts + pnpm test:run + pnpm lint (warnings only, 0 errors) + pnpm build passing"
|
||||||
|
},
|
||||||
|
"install_preflight_only_mode": {
|
||||||
|
"status": "completed",
|
||||||
|
"description": "Added --preflight-only mode to skills install for plan-only previews without performing installation, including JSON output path",
|
||||||
|
"files_modified": [
|
||||||
|
"src/cli/skills.ts",
|
||||||
|
"src/cli/skills.test.ts"
|
||||||
|
],
|
||||||
|
"test_status": "pnpm typecheck + pnpm test:run src/cli/skills.test.ts + pnpm test:run + pnpm lint (warnings only, 0 errors) + pnpm build passing"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1407,7 +1416,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"overall_progress": {
|
"overall_progress": {
|
||||||
"total_test_count": 1528,
|
"total_test_count": 1529,
|
||||||
"all_tests_passing": true,
|
"all_tests_passing": true,
|
||||||
"p0_completion": "3/3 (100%)",
|
"p0_completion": "3/3 (100%)",
|
||||||
"p1_completion": "4/4 (100%)",
|
"p1_completion": "4/4 (100%)",
|
||||||
@@ -1427,7 +1436,7 @@
|
|||||||
"gmail_auth_cli": "flynn gmail-auth command implemented with OAuth2 flow, doctor check, config routed to Telegram",
|
"gmail_auth_cli": "flynn gmail-auth command implemented with OAuth2 flow, doctor check, config routed to Telegram",
|
||||||
"native_audio_support": "completed — smart routing for native audio (Gemini/OpenAI/GitHub) vs Whisper transcription fallback",
|
"native_audio_support": "completed — smart routing for native audio (Gemini/OpenAI/GitHub) vs Whisper transcription fallback",
|
||||||
"remaining_phases_completion": "Phase 1: 3/3 (100%) — context levels, command registry, memory structure. Phase 2: 2/2 (100%) — component registry, confidence routing. Phase 3: 2/2 (100%) — adaptive memory/compaction, truthfulness/autonomy hardening",
|
"remaining_phases_completion": "Phase 1: 3/3 (100%) — context levels, command registry, memory structure. Phase 2: 2/2 (100%) — component registry, confidence routing. Phase 3: 2/2 (100%) — adaptive memory/compaction, truthfulness/autonomy hardening",
|
||||||
"next_up": "Skills infrastructure Phase 3: add install preflight-only mode to print plan without performing install"
|
"next_up": "Skills infrastructure Phase 3: add installer execution stub command that consumes plan output but does not run package manager commands yet"
|
||||||
},
|
},
|
||||||
"soul_md_and_cron_create": {
|
"soul_md_and_cron_create": {
|
||||||
"date": "2026-02-11",
|
"date": "2026-02-11",
|
||||||
|
|||||||
@@ -187,6 +187,17 @@ describe('skills CLI helpers', () => {
|
|||||||
rmSync(root, { recursive: true, force: true });
|
rmSync(root, { recursive: true, force: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns null install preflight view when source is invalid', () => {
|
||||||
|
const root = mkdtempSync(join(tmpdir(), 'flynn-skills-cli-'));
|
||||||
|
const sourceDir = join(root, 'invalid-source-skill');
|
||||||
|
mkdirSync(sourceDir, { recursive: true });
|
||||||
|
|
||||||
|
const view = toSkillInstallPreflightView(sourceDir);
|
||||||
|
|
||||||
|
expect(view).toBeNull();
|
||||||
|
rmSync(root, { recursive: true, force: true });
|
||||||
|
});
|
||||||
|
|
||||||
it('renders install preflight output text', () => {
|
it('renders install preflight output text', () => {
|
||||||
const output = renderSkillInstallPreflight({
|
const output = renderSkillInstallPreflight({
|
||||||
sourcePath: '/tmp/source-skill',
|
sourcePath: '/tmp/source-skill',
|
||||||
|
|||||||
+18
-1
@@ -340,8 +340,9 @@ export function registerSkillsCommand(program: Command): void {
|
|||||||
.command('install <path>')
|
.command('install <path>')
|
||||||
.description('Install a skill from a local directory')
|
.description('Install a skill from a local directory')
|
||||||
.option('--json', 'Output preflight and install result as JSON')
|
.option('--json', 'Output preflight and install result as JSON')
|
||||||
|
.option('--preflight-only', 'Show installer preflight without performing install')
|
||||||
.option('-c, --config <path>', 'Config file path')
|
.option('-c, --config <path>', 'Config file path')
|
||||||
.action((pathArg: string, opts: { json?: boolean; config?: string }) => {
|
.action((pathArg: string, opts: { json?: boolean; preflightOnly?: boolean; config?: string }) => {
|
||||||
const loaded = loadConfigSafe(opts.config);
|
const loaded = loadConfigSafe(opts.config);
|
||||||
if (loaded.error || !loaded.config) {
|
if (loaded.error || !loaded.config) {
|
||||||
console.error(loaded.error ?? 'Failed to load config');
|
console.error(loaded.error ?? 'Failed to load config');
|
||||||
@@ -353,6 +354,22 @@ export function registerSkillsCommand(program: Command): void {
|
|||||||
const installer = new SkillInstaller(loaded.config.skills.managed_dir ?? defaultManagedDir);
|
const installer = new SkillInstaller(loaded.config.skills.managed_dir ?? defaultManagedDir);
|
||||||
const preflight = toSkillInstallPreflightView(pathArg);
|
const preflight = toSkillInstallPreflightView(pathArg);
|
||||||
|
|
||||||
|
if (opts.preflightOnly) {
|
||||||
|
if (!preflight) {
|
||||||
|
console.error(`Failed to generate install preflight from '${resolve(pathArg)}'.`);
|
||||||
|
process.exitCode = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.json) {
|
||||||
|
console.log(JSON.stringify({ preflight }, null, 2));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(renderSkillInstallPreflight(preflight));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (preflight) {
|
if (preflight) {
|
||||||
if (opts.json) {
|
if (opts.json) {
|
||||||
console.log(JSON.stringify({ preflight }, null, 2));
|
console.log(JSON.stringify({ preflight }, null, 2));
|
||||||
|
|||||||
Reference in New Issue
Block a user