feat(#1925): add ZCode (Z.ai) as a pluggable runtime descriptor

Add ZCode as a first-party runtime via a declarative capability descriptor
(capabilities/zcode/capability.json) with zero hardcoded runtime === 'zcode'
branches — exercising the de-hardcoded, data-driven runtime path that 1.7.0
(ADR-1016 / ADR-1239) enables.

Descriptor (all axes sourced verbatim from zcode.z.ai docs):
- configHome ~/.zcode; nested skills + flat commands/agents; profile-marker install
- Claude-shaped skill format reuses convertClaudeCommandToClaudeSkill (no new converter)
- hostIntegration: declarative / slash-file / mcp / electron; dispatch background=false
  (foreground-only per docs); nested+maxDepth undocumented; passive model mode

Installer registration (data, not branches): --zcode flag, allRuntimes, runtimeMap,
interactive menu, --all list. getGlobalConfigDir + resolveRuntimeArtifactLayout +
ALLOWED_CONFIG_RUNTIMES + resolveInstallPlan all derive from the descriptor.

Revamped the brittle per-runtime golden-master tests to be count-agnostic,
descriptor-derived property tests (1.7.0 makes runtimes pluggable data, so pinning
frozen '15 runtime' snapshots is the wrong invariant): getdirname, label-policy,
config-adapter-registry (intent + install-plan golden master), capability-registry,
host-integration-descriptors (counts derive from curated maps). Adding a runtime
descriptor now extends coverage with zero edits to those suites.

Welcome banner, --zcode help, supported-runtimes how-to, and the host-integration
capability matrix (every axis cited) updated.
This commit is contained in:
Tom Boucher
2026-07-05 22:47:56 -04:00
parent 84fc9d6365
commit 69b309e4e0
18 changed files with 747 additions and 572 deletions

View File

@@ -3186,11 +3186,9 @@ const {
// file is an installed artifact captured by golden-install-parity (#1943).
const VALID_EXTENSION_EVENTS = capValidatorModule.VALID_EXTENSION_EVENTS;
const RUNTIME_IDS = [
'claude', 'codex', 'antigravity', 'cursor', 'opencode',
'kilo', 'copilot', 'augment', 'trae', 'qwen', 'hermes',
'codebuddy', 'cline', 'kimi', 'windsurf',
];
// Runtime ids are derived from the built registry (the single source of truth)
// so this file stays fluid when a runtime descriptor is added or removed.
const RUNTIME_IDS = Object.keys(buildRegistry(loadAndValidate(new Set()).capMap).runtimes);
// Helper: build a minimal valid runtime capability object for fixture-based tests
function makeRuntimeCap(overrides) {
@@ -3232,18 +3230,31 @@ function makeRuntimeCap(overrides) {
};
}
// ── 24a. All 15 runtime ids appear in the runtimes index ─────────────────────
// ── 24a. Every role:runtime capability appears in the runtimes index ─────────
// Count-agnostic: the built registry's runtime set must exactly equal the set
// of capability folders whose descriptor declares role:"runtime". Adding a
// runtime descriptor extends coverage with zero edits here.
describe('ADR-1016 phase 5a: all 15 runtimes in registry index', () => {
describe('ADR-1016 phase 5a: every role:runtime capability is in the registry index', () => {
let registry;
test('loadAndValidate + buildRegistry produces runtimes index with 15 entries', () => {
test('loadAndValidate + buildRegistry indexes exactly the role:runtime capabilities on disk', () => {
const { capMap, errors } = loadAndValidate(new Set());
const hardErrors = errors.filter((e) => !e.includes('pending-migration'));
assert.deepEqual(hardErrors, [], 'Expected no hard errors: ' + JSON.stringify(hardErrors));
registry = buildRegistry(capMap);
// Derive the expected runtime id set from the loaded capability map — not a
// hand-pinned count. This is the contract: every role:runtime descriptor on
// disk becomes a runtimes-index entry, no more, no less.
const expectedRuntimeIds = [...capMap.entries()]
.filter(([, cap]) => cap && cap.role === 'runtime')
.map(([id]) => id)
.sort();
const runtimeKeys = Object.keys(registry.runtimes).sort();
assert.strictEqual(runtimeKeys.length, 15, 'Expected 15 runtime entries, got: ' + runtimeKeys.join(', '));
assert.ok(expectedRuntimeIds.length > 0, 'expected at least one role:runtime capability on disk');
assert.deepEqual(runtimeKeys, expectedRuntimeIds,
'runtimes index must exactly equal the role:runtime capabilities on disk. got: ' + runtimeKeys.join(', '));
for (const id of RUNTIME_IDS) {
assert.ok(
Object.prototype.hasOwnProperty.call(registry.runtimes, id),
@@ -4072,17 +4083,17 @@ describe('ADR-857 phase 5e: validateArtifactKindEntry — ConverterName enum (FA
assert.deepEqual(converterErrors, [], 'converter: null must always be accepted, got: ' + JSON.stringify(converterErrors));
});
// Parity: all 15 runtime descriptors must have converters in the valid set (or null)
test('all 15 real runtime descriptors have converters in VALID_CONVERTER_NAMES or null', () => {
// Parity: every role:runtime descriptor's converters must be in the valid set (or null).
// Count-agnostic: iterates the real capability map rather than a hand-pinned runtime list.
test('every real runtime descriptor has converters in VALID_CONVERTER_NAMES or null', () => {
const { capMap, errors } = loadAndValidate(new Set());
const hardErrors = errors.filter((e) => !e.includes('pending-migration'));
assert.deepEqual(hardErrors, [], 'Expected no hard errors from real capabilities, got: ' + JSON.stringify(hardErrors));
const runtimeIds = [
'claude', 'codex', 'antigravity', 'cursor', 'opencode',
'kilo', 'copilot', 'augment', 'trae', 'qwen', 'hermes',
'codebuddy', 'cline', 'kimi', 'windsurf',
];
const runtimeIds = [...capMap.entries()]
.filter(([, cap]) => cap && cap.role === 'runtime')
.map(([id]) => id);
assert.ok(runtimeIds.length > 0, 'expected at least one role:runtime capability');
for (const id of runtimeIds) {
const cap = capMap.get(id);
assert.ok(cap, 'capMap must contain "' + id + '"');
@@ -6406,45 +6417,43 @@ const {
resolveRuntimeConfigIntent,
ALLOWED_CONFIG_RUNTIMES,
} = require(path.join(ROOT, 'gsd-core', 'bin', 'lib', 'runtime-config-adapter-registry.cjs'));
const enh1055Registry = require(path.join(ROOT, 'gsd-core', 'bin', 'lib', 'capability-registry.cjs'));
// ---------------------------------------------------------------------------
// Frozen expected table (pre-change behavior — the contract being pinned)
// Expected table — DERIVED from the capability registry descriptors. The
// contract being pinned is the PROJECTION (descriptor fields → intent), not a
// frozen per-runtime value snapshot. Adding a runtime descriptor extends
// coverage with zero edits here.
// ---------------------------------------------------------------------------
const EXPECTED = [
{ runtime: 'claude', installSurface: 'settings-json', writesSharedSettings: true, finishPermissionWriter: null },
{ runtime: 'antigravity', installSurface: 'settings-json', writesSharedSettings: true, finishPermissionWriter: null },
{ runtime: 'augment', installSurface: 'settings-json', writesSharedSettings: true, finishPermissionWriter: null },
{ runtime: 'qwen', installSurface: 'settings-json', writesSharedSettings: true, finishPermissionWriter: null },
{ runtime: 'hermes', installSurface: 'settings-json', writesSharedSettings: true, finishPermissionWriter: null },
{ runtime: 'codebuddy', installSurface: 'settings-json', writesSharedSettings: true, finishPermissionWriter: null },
{ runtime: 'opencode', installSurface: 'settings-json', writesSharedSettings: true, finishPermissionWriter: 'opencode' },
{ runtime: 'kilo', installSurface: 'settings-json', writesSharedSettings: false, finishPermissionWriter: 'kilo' },
{ runtime: 'codex', installSurface: 'codex-toml', writesSharedSettings: false, finishPermissionWriter: null },
{ runtime: 'copilot', installSurface: 'copilot-instructions', writesSharedSettings: false, finishPermissionWriter: null },
{ runtime: 'cline', installSurface: 'cline-rules', writesSharedSettings: false, finishPermissionWriter: null },
{ runtime: 'cursor', installSurface: 'cursor-hooks-json', writesSharedSettings: false, finishPermissionWriter: null },
{ runtime: 'windsurf', installSurface: 'profile-marker-only', writesSharedSettings: false, finishPermissionWriter: null },
{ runtime: 'trae', installSurface: 'profile-marker-only', writesSharedSettings: false, finishPermissionWriter: null },
{ runtime: 'kimi', installSurface: 'profile-marker-only', writesSharedSettings: false, finishPermissionWriter: null },
];
const EXPECTED = Object.keys(enh1055Registry.runtimes).map((id) => {
const r = enh1055Registry.runtimes[id].runtime;
const pw = r.permissionWriter;
return {
runtime: id,
installSurface: r.installSurface,
writesSharedSettings: r.writesSharedSettings,
finishPermissionWriter: pw == null ? null : pw,
};
});
// ---------------------------------------------------------------------------
// Test 1: Golden master — all 15 runtimes resolve to expected values
// Test 1: Projection contract — every registry runtime resolves to its
// descriptor-derived intent (count-agnostic).
// ---------------------------------------------------------------------------
describe('enh-1055 descriptor-drive: resolveRuntimeConfigIntent golden master', () => {
for (const row of EXPECTED) {
test(`${row.runtime} resolves to expected intent`, () => {
const intent = resolveRuntimeConfigIntent(row.runtime);
assert.deepStrictEqual(intent, {
runtime: row.runtime,
installSurface: row.installSurface,
writesSharedSettings: row.writesSharedSettings,
describe('enh-1055 descriptor-drive: resolveRuntimeConfigIntent projection contract', () => {
test('every registry runtime resolves to its descriptor-derived intent', () => {
assert.ok(EXPECTED.length > 0, 'registry must contain at least one runtime');
for (const row of EXPECTED) {
assert.deepStrictEqual(resolveRuntimeConfigIntent(row.runtime), {
runtime: row.runtime,
installSurface: row.installSurface,
writesSharedSettings: row.writesSharedSettings,
finishPermissionWriter: row.finishPermissionWriter,
});
});
}
}, `resolveRuntimeConfigIntent('${row.runtime}') must match the descriptor projection`);
}
});
});
// ---------------------------------------------------------------------------
@@ -6470,21 +6479,18 @@ describe('enh-1055 descriptor-drive: unknown runtime throws TypeError', () => {
});
// ---------------------------------------------------------------------------
// Test 4: ALLOWED_CONFIG_RUNTIMES contains all 15 expected runtimes
// Test 4: ALLOWED_CONFIG_RUNTIMES equals the registry runtimes that declare an
// installSurface (count-agnostic; derived from the same source as production).
// ---------------------------------------------------------------------------
describe('enh-1055 descriptor-drive: ALLOWED_CONFIG_RUNTIMES completeness', () => {
const EXPECTED_15 = new Set([
'claude', 'antigravity', 'augment', 'qwen', 'hermes', 'codebuddy',
'opencode', 'kilo', 'codex', 'copilot', 'cline', 'cursor', 'windsurf', 'trae', 'kimi',
]);
test('contains exactly the 15 expected runtimes', () => {
assert.deepStrictEqual(new Set(ALLOWED_CONFIG_RUNTIMES), EXPECTED_15);
});
test('has exactly 15 entries', () => {
assert.strictEqual([...ALLOWED_CONFIG_RUNTIMES].length, 15);
test('equals the registry runtimes that declare an installSurface', () => {
const descriptorAllowed = new Set(
Object.entries(enh1055Registry.runtimes)
.filter(([, cap]) => cap && cap.runtime && typeof cap.runtime.installSurface === 'string')
.map(([id]) => id),
);
assert.deepStrictEqual(new Set(ALLOWED_CONFIG_RUNTIMES), descriptorAllowed);
});
});