diff --git a/scripts/grok-install.js b/scripts/grok-install.js index 09663dce4..c6fe3904c 100644 --- a/scripts/grok-install.js +++ b/scripts/grok-install.js @@ -19,13 +19,21 @@ function canonicalArgs(argv = process.argv.slice(2)) { for (let index = 0; index < argv.length; index += 1) { const argument = argv[index]; if (argument === '--target') { + const value = argv[index + 1]; + if (!value || value.startsWith('-')) { + throw new Error('Missing value for --target'); + } index += 1; continue; } args.push(argument); if (SELECTION_FLAGS.has(argument)) hasSelection = true; if (VALUE_FLAGS.has(argument)) { - if (index + 1 < argv.length) args.push(argv[index + 1]); + const value = argv[index + 1]; + if (!value || value.startsWith('-')) { + throw new Error(`Missing value for ${argument}`); + } + args.push(value); index += 1; } else if (!argument.startsWith('-')) { hasSelection = true; diff --git a/tests/lib/grok-canonical-install.test.js b/tests/lib/grok-canonical-install.test.js index 55895feb2..ee85f2028 100644 --- a/tests/lib/grok-canonical-install.test.js +++ b/tests/lib/grok-canonical-install.test.js @@ -247,11 +247,13 @@ function runTests() { const destination = path.join(parent, 'snapshot'); const calls = []; try { + const archive = Buffer.from('archive'); copyGitArchive('/source', 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', destination, (...args) => { calls.push(args); - return Buffer.alloc(0); + return archive; }); assert.deepStrictEqual(calls[1][1], ['-x', '-f', '-', '-C', destination]); + assert.deepStrictEqual(calls[1][2].input, archive); } finally { fs.rmSync(parent, { recursive: true, force: true }); } diff --git a/tests/scripts/install-apply.test.js b/tests/scripts/install-apply.test.js index db541c91a..2d0a3264e 100644 --- a/tests/scripts/install-apply.test.js +++ b/tests/scripts/install-apply.test.js @@ -165,6 +165,11 @@ function runTests() { ); })) passed++; else failed++; + if (test('Grok alias rejects option-prefixed values for value flags', () => { + assert.throws(() => canonicalArgs(['--target', '--dry-run']), /Missing value for --target/); + assert.throws(() => canonicalArgs(['--consent-mcp', '--dry-run']), /Missing value for --consent-mcp/); + })) passed++; else failed++; + if (test('plans Grok through the canonical request with a local pinned fixture', () => { const homeDir = createTempDir('install-apply-grok-home-'); const fixtureRoot = createTempDir('install-apply-grok-source-'); @@ -174,11 +179,17 @@ function runTests() { const sourceSha = execFileSync('git', ['rev-parse', 'HEAD'], { cwd: sourceRoot, encoding: 'utf8' }).trim(); const marketplacePath = path.join(sourceRoot, '.grok-plugin', 'marketplace.json'); const marketplace = readJson(marketplacePath); - marketplace.plugins[0] = { - ...marketplace.plugins[0], - source: { source: 'url', url: sourceRoot, sha: sourceSha }, + const updatedMarketplace = { + ...marketplace, + plugins: [ + { + ...marketplace.plugins[0], + source: { source: 'url', url: sourceRoot, sha: sourceSha }, + }, + ...marketplace.plugins.slice(1), + ], }; - fs.writeFileSync(marketplacePath, `${JSON.stringify(marketplace, null, 2)}\n`); + fs.writeFileSync(marketplacePath, `${JSON.stringify(updatedMarketplace, null, 2)}\n`); const result = run( ['--target', 'grok', '--profile', 'minimal', '--dry-run', '--json'],