From 2a8745b21aa13f47cee5875e384ae6dec97cedc0 Mon Sep 17 00:00:00 2001 From: Viktorplus <36795799+viktorplus@users.noreply.github.com> Date: Sat, 6 Jun 2026 13:20:05 +0200 Subject: [PATCH] fix(01-03): guard Kimi global artifact writes - Keep Kimi global installs as a Phase 1 no-op skeleton - Assert no unconverted Kimi skills, agents, hooks, or payload files are written --- bin/install.js | 15 +++++--- .../bug-kimi-path-layout-local-guard.test.cjs | 35 +++++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/bin/install.js b/bin/install.js index 6664bab22..2cc6a09b2 100755 --- a/bin/install.js +++ b/bin/install.js @@ -8250,14 +8250,19 @@ function install(isGlobal, runtime = 'claude', options = {}) { const dirName = getDirName(runtime); const src = path.join(__dirname, '..'); - if (isKimi && !isGlobal) { - console.log(` ${yellow}⚠${reset} Kimi local install is deferred for Phase 1.`); - console.log(` No .kimi/skills or .agents/skills project artifacts were written.`); - console.log(` Use ${cyan}--kimi --global${reset} for the Phase 1 runtime skeleton.`); + if (isKimi) { + const scopeLabel = isGlobal ? 'global' : 'local'; + console.log(` ${yellow}⚠${reset} Kimi ${scopeLabel} install is deferred for Phase 1.`); + if (isGlobal) { + console.log(` No Kimi skills, agents, hooks, or workflow payload artifacts were written.`); + } else { + console.log(` No .kimi/skills or .agents/skills project artifacts were written.`); + } + console.log(` Phase 1 only registers Kimi selection, paths, and layout guards.`); return { runtime, skipped: true, - reason: 'kimi_local_deferred', + reason: isGlobal ? 'kimi_global_deferred' : 'kimi_local_deferred', configDir: null, settingsPath: null, settings: null, diff --git a/tests/bug-kimi-path-layout-local-guard.test.cjs b/tests/bug-kimi-path-layout-local-guard.test.cjs index db636165b..5fad93f0b 100644 --- a/tests/bug-kimi-path-layout-local-guard.test.cjs +++ b/tests/bug-kimi-path-layout-local-guard.test.cjs @@ -138,4 +138,39 @@ describe('Kimi local install guard', () => { cleanup(tmpHome); } }); + + test('--kimi --global exits successfully without writing unconverted Kimi artifacts', () => { + const tmpProject = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-kimi-global-project-')); + const tmpConfig = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-kimi-global-config-')); + const tmpHome = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-kimi-global-home-')); + try { + const result = spawnSync( + process.execPath, + [INSTALL_SCRIPT, '--kimi', '--global', '--config-dir', tmpConfig, '--no-sdk'], + { + cwd: tmpProject, + encoding: 'utf8', + env: installerEnv({ HOME: tmpHome, USERPROFILE: tmpHome }), + }, + ); + + assert.strictEqual( + result.status, + 0, + `expected --kimi --global skeleton guard to no-op successfully\nstdout: ${result.stdout}\nstderr: ${result.stderr}`, + ); + const combined = `${result.stdout}\n${result.stderr}`; + assert.match(combined, /Kimi global install/i); + assert.match(combined, /deferred/i); + + assert.ok(!fs.existsSync(path.join(tmpConfig, 'skills')), 'must not write unconverted Kimi skills'); + assert.ok(!fs.existsSync(path.join(tmpConfig, 'agents')), 'must not write unconverted Kimi agents'); + assert.ok(!fs.existsSync(path.join(tmpConfig, 'gsd-core')), 'must not write workflow payloads as Kimi artifacts'); + assert.ok(!fs.existsSync(path.join(tmpConfig, 'hooks')), 'must not write hooks under the Kimi root'); + } finally { + cleanup(tmpProject); + cleanup(tmpConfig); + cleanup(tmpHome); + } + }); });