mirror of
https://github.com/affaan-m/ECC.git
synced 2026-08-17 21:15:40 +02:00
Make Antigravity 2.0 installs native and safely migrate legacy state. Ensure doctor, repair, status projection, repeat installs, legacy Codex sync, and uninstall converge without losing user files. Exclude Python bytecode and harden repo-scan bootstrap guidance. Gate publishing and pull-request merges on one exact packed artifact completing install, repeat, drift, repair, status, and uninstall across Linux, macOS, and Windows. Co-authored-by: lorencifernando-coder <lorenci.fernando@gmail.com> Co-authored-by: Suliman Abdulrazzaq <suliman9000a@gmail.com> Co-authored-by: Wu Shuwen <mikewushuwen@outlook.com>
187 lines
7.4 KiB
JavaScript
187 lines
7.4 KiB
JavaScript
/**
|
|
* Tests for scripts/lib/harness-capabilities.js
|
|
*/
|
|
|
|
const assert = require('assert');
|
|
|
|
const { SUPPORTED_INSTALL_TARGETS } = require('../../scripts/lib/install-manifests');
|
|
const { listInstallTargetAdapters } = require('../../scripts/lib/install-targets/registry');
|
|
const {
|
|
GUIDED_HARNESS_IDS,
|
|
HARNESS_CAPABILITIES,
|
|
getHarnessCapability,
|
|
listGuidedHarnesses,
|
|
listHarnessCapabilities,
|
|
normalizeHarnessSelection,
|
|
} = require('../../scripts/lib/harness-capabilities');
|
|
|
|
function test(name, fn) {
|
|
try {
|
|
fn();
|
|
console.log(` \u2713 ${name}`);
|
|
return true;
|
|
} catch (error) {
|
|
console.log(` \u2717 ${name}`);
|
|
console.log(` Error: ${error.message}`);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function runTests() {
|
|
console.log('\n=== Testing harness capability catalog ===\n');
|
|
|
|
let passed = 0;
|
|
let failed = 0;
|
|
|
|
if (test('represents all 14 registered targets exactly once across 13 harnesses', () => {
|
|
const catalogTargetIds = HARNESS_CAPABILITIES.flatMap(harness => harness.targetIds);
|
|
const adapterTargetIds = listInstallTargetAdapters().map(adapter => adapter.target);
|
|
|
|
assert.strictEqual(HARNESS_CAPABILITIES.length, 13);
|
|
assert.strictEqual(new Set(catalogTargetIds).size, 14);
|
|
assert.deepStrictEqual([...catalogTargetIds].sort(), [...SUPPORTED_INSTALL_TARGETS].sort());
|
|
assert.deepStrictEqual([...catalogTargetIds].sort(), [...adapterTargetIds].sort());
|
|
})) passed++; else failed++;
|
|
|
|
if (test('only Claude, Codex, and Kimi are guided-ready', () => {
|
|
assert.deepStrictEqual(GUIDED_HARNESS_IDS, ['claude', 'codex', 'kimi']);
|
|
assert.deepStrictEqual(
|
|
listGuidedHarnesses().map(harness => harness.id),
|
|
['claude', 'codex', 'kimi']
|
|
);
|
|
assert.ok(HARNESS_CAPABILITIES
|
|
.filter(harness => !harness.guidedReady)
|
|
.every(harness => harness.availability === 'advanced'));
|
|
})) passed++; else failed++;
|
|
|
|
if (test('models reviewed guided install modes, roots, and scopes', () => {
|
|
const claude = getHarnessCapability('claude');
|
|
assert.deepStrictEqual(claude.targetIds, ['claude', 'claude-project']);
|
|
assert.strictEqual(claude.channel, 'native-plugin');
|
|
assert.strictEqual(claude.installMode, 'native-plugin');
|
|
assert.match(claude.destination, /selected Claude plugin scope/i);
|
|
assert.deepStrictEqual(claude.scopes, [
|
|
{ id: 'user', targetId: 'claude', root: '~/.claude' },
|
|
{ id: 'project', targetId: 'claude-project', root: './.claude' },
|
|
{ id: 'local', targetId: 'claude-project', root: './.claude' },
|
|
]);
|
|
|
|
const codex = getHarnessCapability('codex');
|
|
assert.deepStrictEqual(codex.targetIds, ['codex']);
|
|
assert.strictEqual(codex.channel, 'native-plugin');
|
|
assert.strictEqual(codex.installMode, 'native-plugin');
|
|
assert.match(codex.destination, /~\/\.codex/);
|
|
assert.deepStrictEqual(codex.scopes, [
|
|
{ id: 'native', targetId: 'codex', root: '~/.codex' },
|
|
]);
|
|
|
|
const kimi = getHarnessCapability('kimi');
|
|
assert.deepStrictEqual(kimi.targetIds, ['kimi']);
|
|
assert.strictEqual(kimi.channel, 'managed-project');
|
|
assert.strictEqual(kimi.installMode, 'managed-project');
|
|
assert.strictEqual(kimi.destination, './.kimi-code');
|
|
assert.deepStrictEqual(kimi.scopes, [
|
|
{ id: 'project', targetId: 'kimi', root: './.kimi-code' },
|
|
]);
|
|
})) passed++; else failed++;
|
|
|
|
if (test('keeps every advanced target attached to its registered root and scope', () => {
|
|
const expected = {
|
|
cursor: ['project', './.cursor'],
|
|
antigravity: ['project', './.agents'],
|
|
gemini: ['project', './.gemini'],
|
|
opencode: ['home', '~/.opencode'],
|
|
codebuddy: ['project', './.codebuddy'],
|
|
joycode: ['project', './.joycode'],
|
|
qwen: ['home', '~/.qwen'],
|
|
zed: ['project', './.zed'],
|
|
hermes: ['home', '~/.hermes'],
|
|
openclaw: ['home', '~/.openclaw'],
|
|
};
|
|
|
|
for (const [id, [scopeId, root]] of Object.entries(expected)) {
|
|
const harness = getHarnessCapability(id);
|
|
assert.strictEqual(harness.guidedReady, false, id);
|
|
assert.strictEqual(harness.availability, 'advanced', id);
|
|
assert.strictEqual(harness.destination, root, id);
|
|
assert.deepStrictEqual(harness.scopes, [
|
|
{ id: scopeId, targetId: id, root },
|
|
], id);
|
|
}
|
|
})) passed++; else failed++;
|
|
|
|
if (test('describes hook capability without claiming Kimi provider support is absent', () => {
|
|
assert.strictEqual(getHarnessCapability('claude').hooks.mode, 'profile-selection');
|
|
assert.strictEqual(getHarnessCapability('codex').hooks.mode, 'native-trust');
|
|
|
|
const kimiHooks = getHarnessCapability('kimi').hooks;
|
|
assert.strictEqual(kimiHooks.mode, 'not-configured');
|
|
assert.strictEqual(kimiHooks.eccConfigured, false);
|
|
assert.match(kimiHooks.note, /ECC hooks are not configured/i);
|
|
assert.strictEqual(kimiHooks.summary, kimiHooks.note);
|
|
assert.doesNotMatch(kimiHooks.note, /provider.*unsupported|Kimi.*unsupported/i);
|
|
})) passed++; else failed++;
|
|
|
|
if (test('does not advertise unregistered Copilot, Kiro, or Pi harnesses', () => {
|
|
for (const id of ['copilot', 'kiro', 'pi']) {
|
|
assert.strictEqual(getHarnessCapability(id), null);
|
|
assert.throws(
|
|
() => normalizeHarnessSelection(id),
|
|
/Unknown guided harness selection/
|
|
);
|
|
}
|
|
})) passed++; else failed++;
|
|
|
|
if (test('normalizes wizard selections into canonical guided order', () => {
|
|
assert.deepStrictEqual(
|
|
normalizeHarnessSelection(' KIMI CODE, Claude Code, kimi '),
|
|
['claude', 'kimi']
|
|
);
|
|
assert.deepStrictEqual(
|
|
normalizeHarnessSelection(['3', 'claude-project', 'Codex']),
|
|
['claude', 'codex', 'kimi']
|
|
);
|
|
assert.deepStrictEqual(normalizeHarnessSelection('all'), ['claude', 'codex', 'kimi']);
|
|
assert.deepStrictEqual(normalizeHarnessSelection('*'), ['claude', 'codex', 'kimi']);
|
|
})) passed++; else failed++;
|
|
|
|
if (test('rejects empty, ambiguous, advanced, and unknown wizard selections clearly', () => {
|
|
assert.throws(() => normalizeHarnessSelection(''), /At least one guided harness/);
|
|
assert.throws(() => normalizeHarnessSelection([]), /At least one guided harness/);
|
|
assert.throws(() => normalizeHarnessSelection('none'), /At least one guided harness/);
|
|
assert.throws(() => normalizeHarnessSelection('all,codex'), /cannot be combined/i);
|
|
assert.throws(() => normalizeHarnessSelection('cursor'), /advanced.*not guided-ready/i);
|
|
assert.throws(() => normalizeHarnessSelection('grok'), /Unknown guided harness selection/);
|
|
})) passed++; else failed++;
|
|
|
|
if (test('exports deeply frozen records while list helpers return safe array copies', () => {
|
|
assert.ok(Object.isFrozen(HARNESS_CAPABILITIES));
|
|
assert.ok(Object.isFrozen(HARNESS_CAPABILITIES[0]));
|
|
assert.ok(Object.isFrozen(HARNESS_CAPABILITIES[0].targetIds));
|
|
assert.ok(Object.isFrozen(HARNESS_CAPABILITIES[0].scopes));
|
|
assert.ok(Object.isFrozen(HARNESS_CAPABILITIES[0].scopes[0]));
|
|
assert.ok(Object.isFrozen(HARNESS_CAPABILITIES[0].hooks));
|
|
assert.ok(Object.isFrozen(GUIDED_HARNESS_IDS));
|
|
|
|
const first = listHarnessCapabilities();
|
|
first.pop();
|
|
assert.strictEqual(listHarnessCapabilities().length, 13);
|
|
|
|
const guided = listGuidedHarnesses();
|
|
guided.reverse();
|
|
assert.deepStrictEqual(
|
|
listGuidedHarnesses().map(harness => harness.id),
|
|
['claude', 'codex', 'kimi']
|
|
);
|
|
})) passed++; else failed++;
|
|
|
|
console.log(`\n${passed} passed, ${failed} failed\n`);
|
|
return failed === 0;
|
|
}
|
|
|
|
if (require.main === module) {
|
|
process.exit(runTests() ? 0 : 1);
|
|
}
|
|
|
|
module.exports = { runTests };
|