feat(install): validate agent CLI runtime registries
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { existsSync, mkdirSync, rmSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { fakePrompt, makeFakePlugin } from './helpers/fake-plugin.js';
|
||||
import { tmpRoot } from './helpers/run-script.js';
|
||||
|
||||
const PROMPTS = {
|
||||
'sdlc-analyze': fakePrompt('sdlc-analyze'),
|
||||
'sdlc-plan': fakePrompt('sdlc-plan'),
|
||||
};
|
||||
|
||||
function homeWith(t, platform) {
|
||||
mkdirSync(tmpRoot, { recursive: true });
|
||||
const home = join(tmpRoot, `runtime-home-${platform}`);
|
||||
rmSync(home, { recursive: true, force: true });
|
||||
mkdirSync(join(home, 'work'), { recursive: true });
|
||||
const roots = {
|
||||
'oh-my-pi': ['.omp'],
|
||||
claude: ['.claude'],
|
||||
codex: ['.codex'],
|
||||
kiro: ['.kiro'],
|
||||
};
|
||||
mkdirSync(join(home, ...roots[platform]), { recursive: true });
|
||||
t.after(() => rmSync(home, { recursive: true, force: true }));
|
||||
return home;
|
||||
}
|
||||
|
||||
const runInHome = (plugin, home) => (args) =>
|
||||
plugin.run(args, { env: { HOME: home }, cwd: join(home, 'work') });
|
||||
|
||||
test('sdlc-version 回報版本、實際 tea-sdlc executable 與六個流程', async (t) => {
|
||||
const plugin = makeFakePlugin(t, { prompts: PROMPTS });
|
||||
const { json } = await plugin.run(['sdlc-version']);
|
||||
|
||||
assert.equal(json.ok, true);
|
||||
assert.equal(json.data.name, 'tea-sdlc');
|
||||
assert.equal(json.data.version, '0.0.1');
|
||||
assert.equal(json.data.executable, join(plugin.shim, 'tea-sdlc'));
|
||||
assert.deepEqual(json.data.commands, ['sdlc-analyze', 'sdlc-plan']);
|
||||
});
|
||||
|
||||
test('OMP 使用 ~/.omp/agent/commands 作為 runtime registry,六個 command 全部找到才 pass', async (t) => {
|
||||
const plugin = makeFakePlugin(t, { prompts: PROMPTS });
|
||||
const home = homeWith(t, 'oh-my-pi');
|
||||
const run = runInHome(plugin, home);
|
||||
const installed = await run(['install']);
|
||||
|
||||
assert.equal(installed.code, 0);
|
||||
assert.ok(existsSync(join(home, '.omp', 'agent', 'commands', 'sdlc-analyze.md')));
|
||||
assert.equal(installed.json.data.verify.platforms[0].runtime.status, 'pass');
|
||||
assert.deepEqual(installed.json.data.verify.platforms[0].runtime.commands, ['sdlc-analyze', 'sdlc-plan']);
|
||||
});
|
||||
|
||||
test('runtime registry 缺少 command 時 verify exit 1 並列出 missing', async (t) => {
|
||||
const plugin = makeFakePlugin(t, { prompts: PROMPTS });
|
||||
const home = homeWith(t, 'claude');
|
||||
const run = runInHome(plugin, home);
|
||||
await run(['install']);
|
||||
rmSync(join(home, '.claude', 'commands', 'sdlc-plan.md'));
|
||||
|
||||
const result = await run(['verify', '--platform', 'claude']);
|
||||
assert.equal(result.code, 1);
|
||||
assert.equal(result.json.error.code, 'RUNTIME_VERIFY_FAILED');
|
||||
assert.deepEqual(result.json.data.platforms[0].runtime.missing, ['sdlc-plan']);
|
||||
assert.equal(result.json.data.platforms[0].runtime.status, 'fail');
|
||||
});
|
||||
|
||||
test('沒有安全 registry probe 的平台回報 not-supported 而不阻止 install', async (t) => {
|
||||
const plugin = makeFakePlugin(t, { prompts: PROMPTS });
|
||||
const home = homeWith(t, 'kiro');
|
||||
const result = await runInHome(plugin, home)(['install']);
|
||||
|
||||
assert.equal(result.code, 0);
|
||||
assert.equal(result.json.data.verify.platforms[0].runtime.status, 'not-supported');
|
||||
assert.deepEqual(result.json.data.verify.platforms[0].runtime.failures, []);
|
||||
});
|
||||
Reference in New Issue
Block a user