test: pin review-voice row, helpers row and the no-Drive fallback in existing install tests

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
(cherry picked from commit 7f6c70459a)
This commit is contained in:
garrytan committed 2026-10-17 00:37:57 +00:00
1 parent 2314b6f679
commit 60da139bf8
4 files changed
+13 -7

No files matched your search

+2 -1
View File
@@ -17,6 +17,7 @@ import { afterEach, describe, expect, test } from 'bun:test';
import { spawn, spawnSync } from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import { capyBootstrapCommand } from '../lib/doctor-components';
import { RESULT_CODES } from '../lib/result-codes';
import { capyHost, type CapyHost } from './helpers/capy-host';
@@ -222,7 +223,7 @@ describe('capy skill bootstrapper (capy/skill/gstack/scripts/install.sh)', () =>
fs.rmSync(f.root, { recursive: true, force: true });
const check = f.run(['--check', '--for', 'autoplan']);
expect(check.status).toBe(1);
expect(check.last).toBe(`gstack: fail not-installed — no gstack checkout at ${f.root}; fix: bash ${BOOT} --for autoplan (installs)`);
expect(check.last).toBe(`gstack: fail not-installed — no gstack checkout at ${f.root}; fix: bash ${BOOT} --for autoplan (installs; on a machine without this skill: ${capyBootstrapCommand('autoplan', f.root)})`);
const install = f.run(['--for', 'autoplan']);
expect(install.status, install.stdout + install.stderr).toBe(0);
expect(f.git(['rev-parse', 'HEAD'])).toBe(f.b);
+8 -3
View File
@@ -10,7 +10,7 @@ import { spawnSync } from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import {
COMPONENT_IDS, CORE_IDS, DOCTOR_COMPONENTS, SKILL_REQUIREMENTS, renderDoctorComponentsSh,
COMPONENT_IDS, CORE_IDS, DOCTOR_COMPONENTS, INSTALL_PROFILES, SKILL_REQUIREMENTS, renderDoctorComponentsSh,
} from '../lib/doctor-components';
import { RESULT_CODES } from '../lib/result-codes';
import { DOCTOR_COMPONENTS_RELPATH } from '../scripts/gen-doctor-components';
@@ -33,10 +33,15 @@ describe('doctor component table', () => {
}
});
test('every skill directory in the repo is classified, and no classified skill is missing', () => {
test('every skill directory in the repo is classified, and no classified skill is missing (install profiles are the only other rows)', () => {
const skills = fs.readdirSync(ROOT).filter(d => fs.existsSync(path.join(ROOT, d, 'SKILL.md.tmpl'))).sort();
expect(skills.length).toBeGreaterThan(40);
expect(Object.keys(SKILL_REQUIREMENTS).sort()).toEqual(skills);
expect(Object.keys(SKILL_REQUIREMENTS).filter(s => !INSTALL_PROFILES.includes(s)).sort()).toEqual(skills);
expect(INSTALL_PROFILES).toEqual(['review-voice']);
for (const profile of INSTALL_PROFILES) {
expect(skills, `${profile} is an install profile, not a skill`).not.toContain(profile);
expect(SKILL_REQUIREMENTS[profile]?.requires).toEqual(['helpers']);
}
});
test('the Bash render answers the same questions as the table, and refuses unknown names', () => {
+2 -2
View File
@@ -296,9 +296,9 @@ describe('gstack-capy-install', () => {
const r = run(f, ['--root', clone], { GSTACK_CAPY_REPO: f.root });
expect(r.status, r.stdout + r.stderr).toBe(0);
expect(r.stdout).toContain(`cloning ${f.root} into ${clone}`);
expect(r.stdout).toMatch(new RegExp(`^gstack-capy-install: cloned ${f.root} at [0-9a-f]{12} \\(1\\.2\\.3\\)$`, 'm'));
expect(r.stdout).toMatch(new RegExp(`^gstack-capy-install: cloned ${f.root} into ${clone} at [0-9a-f]{12} \\(1\\.2\\.3\\)$`, 'm'));
const handed = run(f, [], { GSTACK_CAPY_CLONED: 'https://github.com/garrytan/gstack.git' });
expect(handed.stdout).toMatch(/^gstack-capy-install: cloned https:\/\/github\.com\/garrytan\/gstack\.git at [0-9a-f]{12} \(1\.2\.3\)$/m);
expect(handed.stdout).toMatch(new RegExp(`^gstack-capy-install: cloned https://github\\.com/garrytan/gstack\\.git into ${f.root} at [0-9a-f]{12} \\(1\\.2\\.3\\)$`, 'm'));
expect(handed.stdout).not.toContain('reusing');
expect(fs.existsSync(path.join(clone, 'setup'))).toBe(true);
const occupied = path.join(f.base, 'occupied');
+1 -1
View File
@@ -697,7 +697,7 @@ describe('gstack-doctor --check', () => {
expect(json.ok).toBe(false);
expect(json.failed).toEqual(['runtime']);
expect(json.required).toEqual(['claude', 'codex', 'patch', 'runtime', 'pins', 'state-root', 'privacy', 'cores', 'revision', 'wrapper']);
expect(json.rows.map((x: { id: string }) => x.id)).toEqual(['claude', 'codex', 'patch', 'codex-cli', 'browse-bundle', 'browser', 'cso', 'runtime', 'pins', 'state-root', 'privacy', 'cores', 'revision', 'wrapper']);
expect(json.rows.map((x: { id: string }) => x.id)).toEqual(['claude', 'codex', 'patch', 'codex-cli', 'browse-bundle', 'browser', 'cso', 'helpers', 'runtime', 'pins', 'state-root', 'privacy', 'cores', 'revision', 'wrapper']);
const runtime = json.rows.find((x: { id: string }) => x.id === 'runtime');
expect(runtime.status).toBe('FAIL');
expect(runtime.code).toBe('RUNTIME_BELOW_MINIMUM');