* fix(#4132): verify durable runtime surface sources * chore(#4132): record PR number in changeset * test(#4132): cover rejected commands source alias * fix(#4132): reject aliased package fallback * test(#4132): cover rejected agents source alias * test(#4132): cover partially aliased marker provider * fix(#4132): reject partially aliased source providers * test(#4132): cover routed source identity probes * fix(#4132): route installed source identity probes * refactor(#4132): tighten installer source metadata * test(#4132): cover corpus trust boundary attacks * fix(#4132): close installed corpus trust gaps * refactor(#4132): keep installer authority private * fix(#4132): preserve private installer fallback * test(#4132): preserve fixture source authority * fix(#4132): reject overlapping source fallback * fix(#4132): avoid redundant installed corpus reads * refactor(#4132): simplify provider resolution * test(#4132): sync install tree fixtures after rebase --------- Co-authored-by: Tom Boucher <trekkie@nomorestars.com>
This commit is contained in:
@@ -143,6 +143,10 @@ function buildSourceTree(agentFiles) {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-agent-parity-src-'));
|
||||
const commandsGsd = path.join(root, 'commands', 'gsd');
|
||||
fs.mkdirSync(commandsGsd, { recursive: true });
|
||||
// Runtime Surface source providers are atomic across every source class a
|
||||
// layout needs. Keep this marker fixture complete for commands + agents so
|
||||
// the installer resolver does not correctly fall back to the package tree.
|
||||
fs.writeFileSync(path.join(commandsGsd, 'fixture-command.md'), '# Fixture command\n');
|
||||
const agentsDir = path.join(root, 'agents');
|
||||
fs.mkdirSync(agentsDir, { recursive: true });
|
||||
for (const [name, content] of Object.entries(agentFiles)) {
|
||||
|
||||
@@ -136,14 +136,16 @@ function spawnInstall(repoRoot, runtime, scope) {
|
||||
}
|
||||
|
||||
/** Emitted files under `root` that are derived from the probe agent AND contain
|
||||
* `token`. The `derivedOnly` filter is what keeps shipped library sources —
|
||||
* which legitimately carry the marker grammar — out of the leak set. */
|
||||
* `token`. The `derivedOnly` filter keeps shipped library sources and the
|
||||
* installation-owned raw re-staging corpus — both of which legitimately
|
||||
* preserve canonical marker grammar — out of the emitted-artifact leak set. */
|
||||
function filesContaining(root, token, derivedOnly = true) {
|
||||
if (!fs.existsSync(root)) return [];
|
||||
const hits = [];
|
||||
for (const abs of walk(root)) {
|
||||
const rel = path.relative(root, abs).replace(/\\/g, '/');
|
||||
if (derivedOnly && !rel.includes(PROBE_STEM)) continue;
|
||||
if (derivedOnly && (rel.startsWith('gsd-core/agents/') || rel.includes('/gsd-core/agents/'))) continue;
|
||||
let buf;
|
||||
try {
|
||||
buf = fs.readFileSync(abs);
|
||||
|
||||
@@ -253,7 +253,8 @@ test('Kimi neutralizes ~/.claude/gsd-core references instead of leaking a repoin
|
||||
// to see the ORIGINAL `~/.claude/gsd-core` text; kimi/kimi-code capability.json
|
||||
// now opt out via hostBehaviors.noPathRewrite so that still holds.
|
||||
const install = installRuntime(t, 'kimi', { scope: 'global' });
|
||||
const artifacts = emittedAgentArtifacts(install, 'gsd-executor');
|
||||
// Inspect generated prompts, not the installation-owned raw source corpus.
|
||||
const artifacts = emittedAgentArtifacts(install, 'gsd-executor', path.join(install.configDir, 'agents'));
|
||||
assert.ok(artifacts.some((artifact) => artifact.includes('GSD core')),
|
||||
'a ~/.claude/gsd-core reference must neutralize to prose, not a repointed Kimi path');
|
||||
assert.ok(artifacts.every((artifact) =>
|
||||
|
||||
@@ -1145,6 +1145,10 @@ describe('issue-2322: capability set --runtime materializes an installed third-p
|
||||
|
||||
// Step 3 of the issue repro: capability set my-thing --runtime claude --scope global
|
||||
const rcd = tmpDir('cap-cli-rcd-');
|
||||
// A global materialization needs one complete Runtime Surface provider.
|
||||
// This fixture exercises the supported legacy compatibility-marker path;
|
||||
// source-less global trees now fail closed and must be upgraded first.
|
||||
fs.writeFileSync(path.join(rcd, '.gsd-source'), path.join(__dirname, '..', 'commands', 'gsd') + '\n');
|
||||
const setResult = runGsdTools(
|
||||
['capability', 'set', 'my-thing', '--runtime', 'claude', '--scope', 'global', '--config-dir', rcd, '--raw'],
|
||||
cwd,
|
||||
|
||||
@@ -447,6 +447,11 @@ describe('capability-writer: setCapabilityState', () => {
|
||||
const materialiseWarning = result.warnings.find((w) => w.includes('materialize failed'));
|
||||
assert.equal(materialiseWarning, undefined,
|
||||
`materialise failure must not appear in warnings, got: ${JSON.stringify(result.warnings)}`);
|
||||
assert.equal(
|
||||
readSurface(rcd),
|
||||
null,
|
||||
'a failed materialization must not publish the computed surface state',
|
||||
);
|
||||
} finally {
|
||||
cleanup(rcd);
|
||||
cleanup(cwd);
|
||||
|
||||
@@ -40,6 +40,18 @@ const {
|
||||
const _manifest = loadSkillsManifest();
|
||||
const resolvedProfileFull = resolveProfile({ modes: [], manifest: _manifest });
|
||||
|
||||
function installFromFixture(configDir) {
|
||||
return installRuntimeArtifacts(
|
||||
'claude',
|
||||
configDir,
|
||||
'global',
|
||||
resolvedProfileFull,
|
||||
undefined,
|
||||
undefined,
|
||||
{ fs },
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up a configDir backed by a custom srcDir via .gsd-source marker.
|
||||
* Returns { configDir, srcDir } both under tmpDir.
|
||||
@@ -50,6 +62,12 @@ function setupConfigDir(tmpDir, commandFiles) {
|
||||
for (const [name, content] of Object.entries(commandFiles)) {
|
||||
fs.writeFileSync(path.join(srcDir, name), content);
|
||||
}
|
||||
// Claude's layout consumes commands and agents from one atomic provider.
|
||||
// Keep the marker fixture complete so these tests exercise their custom
|
||||
// command bytes instead of correctly falling back to the package corpus.
|
||||
const agentsDir = path.join(tmpDir, 'agents');
|
||||
fs.mkdirSync(agentsDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(agentsDir, 'gsd-fixture-agent.md'), '---\nname: gsd-fixture-agent\n---\n');
|
||||
const configDir = path.join(tmpDir, 'config');
|
||||
fs.mkdirSync(configDir, { recursive: true });
|
||||
// .gsd-source marker tells findInstallSourceRoot to use our custom srcDir
|
||||
@@ -212,7 +230,7 @@ describe('installRuntimeArtifacts (claude global) — skill layout', () => {
|
||||
'health.md': '---\nname: gsd:health\ndescription: Check health\n---\n\nHealth body.',
|
||||
});
|
||||
|
||||
installRuntimeArtifacts('claude', configDir, 'global', resolvedProfileFull);
|
||||
installFromFixture(configDir);
|
||||
|
||||
const skillsDir = path.join(configDir, 'skills');
|
||||
assert.ok(
|
||||
@@ -238,7 +256,7 @@ describe('installRuntimeArtifacts (claude global) — skill layout', () => {
|
||||
|
||||
// Production sequence: uninstall wipes gsd-* entries, install writes fresh ones
|
||||
uninstallRuntimeArtifacts('claude', configDir, 'global');
|
||||
installRuntimeArtifacts('claude', configDir, 'global', resolvedProfileFull);
|
||||
installFromFixture(configDir);
|
||||
|
||||
// Stale skill removed by uninstall
|
||||
assert.ok(
|
||||
@@ -264,7 +282,7 @@ describe('installRuntimeArtifacts (claude global) — skill layout', () => {
|
||||
fs.writeFileSync(path.join(otherDir, 'SKILL.md'), 'custom content');
|
||||
|
||||
// Install (no pre-uninstall: uninstall only removes gsd-* prefixed entries)
|
||||
installRuntimeArtifacts('claude', configDir, 'global', resolvedProfileFull);
|
||||
installFromFixture(configDir);
|
||||
|
||||
// Non-GSD skill preserved
|
||||
assert.ok(
|
||||
@@ -291,15 +309,19 @@ describe('installRuntimeArtifacts (claude global) — skill layout', () => {
|
||||
// an empty dir — _copyStaged then copies nothing into skills/.
|
||||
const emptySrc = path.join(tmpDir, 'empty-commands', 'gsd');
|
||||
fs.mkdirSync(emptySrc, { recursive: true });
|
||||
fs.writeFileSync(path.join(emptySrc, 'README.txt'), 'fixture only\n');
|
||||
const agentsDir = path.join(tmpDir, 'agents');
|
||||
fs.mkdirSync(agentsDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(agentsDir, 'gsd-fixture-agent.md'), '---\nname: gsd-fixture-agent\n---\n');
|
||||
|
||||
const configDir = path.join(tmpDir, 'config-empty');
|
||||
fs.mkdirSync(configDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(configDir, '.gsd-source'), emptySrc + '\n');
|
||||
|
||||
// Should not throw
|
||||
installRuntimeArtifacts('claude', configDir, 'global', resolvedProfileFull);
|
||||
// Use the existing installer fs seam to supply this fixture corpus and
|
||||
// skip production provisioning, which would intentionally replace it.
|
||||
installFromFixture(configDir);
|
||||
const skillsDir = path.join(configDir, 'skills');
|
||||
// If skills dir was created it must contain no gsd-* entries
|
||||
if (fs.existsSync(skillsDir)) {
|
||||
const gsdEntries = fs.readdirSync(skillsDir).filter(n => n.startsWith('gsd-'));
|
||||
assert.strictEqual(gsdEntries.length, 0, 'no gsd-* skills created when src has no .md files');
|
||||
@@ -339,7 +361,7 @@ describe('installRuntimeArtifacts path replacement in Claude global skills (#165
|
||||
].join('\n'),
|
||||
});
|
||||
|
||||
installRuntimeArtifacts('claude', configDir, 'global', resolvedProfileFull);
|
||||
installFromFixture(configDir);
|
||||
|
||||
const content = fs.readFileSync(
|
||||
path.join(configDir, 'skills', 'gsd-manager', 'SKILL.md'), 'utf8'
|
||||
@@ -363,7 +385,7 @@ describe('installRuntimeArtifacts path replacement in Claude global skills (#165
|
||||
'debug.md': '---\nname: gsd:debug\ndescription: Debug\n---\n\n@$HOME/.claude/gsd-core/workflows/debug.md',
|
||||
});
|
||||
|
||||
installRuntimeArtifacts('claude', configDir, 'global', resolvedProfileFull);
|
||||
installFromFixture(configDir);
|
||||
|
||||
const content = fs.readFileSync(
|
||||
path.join(configDir, 'skills', 'gsd-debug', 'SKILL.md'), 'utf8'
|
||||
@@ -383,7 +405,7 @@ describe('installRuntimeArtifacts path replacement in Claude global skills (#165
|
||||
'next.md': '---\nname: gsd:next\ndescription: Next\n---\n\n@~/.claude/gsd-core/workflows/next.md',
|
||||
});
|
||||
|
||||
installRuntimeArtifacts('claude', configDir, 'global', resolvedProfileFull);
|
||||
installFromFixture(configDir);
|
||||
|
||||
const content = fs.readFileSync(
|
||||
path.join(configDir, 'skills', 'gsd-next', 'SKILL.md'), 'utf8'
|
||||
@@ -422,7 +444,7 @@ describe('Legacy commands/gsd/ cleanup', () => {
|
||||
|
||||
// installRuntimeArtifacts calls _runLegacyInstallMigrations which removes
|
||||
// commands/gsd/ for claude runtime (it's the legacy location for global).
|
||||
installRuntimeArtifacts('claude', configDir, 'global', resolvedProfileFull);
|
||||
installFromFixture(configDir);
|
||||
|
||||
assert.ok(!fs.existsSync(legacyDir), 'legacy commands/gsd/ removed');
|
||||
assert.ok(
|
||||
|
||||
@@ -47,6 +47,7 @@ const commandRoster = require('../gsd-core/bin/lib/command-roster.cjs');
|
||||
const slashCommandTransformer = require('../scripts/fix-slash-commands.cjs');
|
||||
|
||||
const REAL_COMMANDS_DIR = path.join(__dirname, '..', 'commands', 'gsd');
|
||||
const REAL_PACKAGE_ROOT = path.resolve(__dirname, '..');
|
||||
const MANIFEST = loadSkillsManifest(REAL_COMMANDS_DIR);
|
||||
const RESOLVED_CORE = resolveProfile({ modes: ['core'], manifest: MANIFEST });
|
||||
const RESOLVED_FULL = resolveProfile({ modes: ['full'], manifest: MANIFEST });
|
||||
@@ -149,13 +150,11 @@ const REAL_FS_WRITE_SURFACE = [
|
||||
'mkdtempSync', 'openSync', 'readSync', 'closeSync',
|
||||
];
|
||||
|
||||
// Package-source roots a correct install is expected to read for real, even
|
||||
// while a fake DESTINATION adapter is injected (40-design.md "Known limits":
|
||||
// this seam makes destination IO fake-able; package-source IO stays real by
|
||||
// design). Mirrors findInstallSourceRoot's/findAgentsSourceRoot's/
|
||||
// readGsdCommandNames's own targets (commands/gsd/, agents/), all resolved
|
||||
// the same way REAL_COMMANDS_DIR is above.
|
||||
const PACKAGE_SOURCE_ROOTS = [REAL_COMMANDS_DIR, path.join(__dirname, '..', 'agents')];
|
||||
// The provider resolver probes upward through the executing package before it
|
||||
// reaches commands/gsd and agents. All read-only package-tree probes are valid
|
||||
// real IO while a fake DESTINATION adapter is active; destination paths remain
|
||||
// poisoned below.
|
||||
const PACKAGE_SOURCE_ROOTS = [path.resolve(__dirname, '..')];
|
||||
|
||||
function isPackageSourcePath(resolvedPath) {
|
||||
return PACKAGE_SOURCE_ROOTS.some(
|
||||
@@ -390,6 +389,29 @@ function sha256Hex(content) {
|
||||
return crypto.createHash('sha256').update(content).digest('hex');
|
||||
}
|
||||
|
||||
function fakeInstalledCorpusSeed(configDir) {
|
||||
const coreDir = path.join(configDir, 'gsd-core');
|
||||
const commandsDir = path.join(coreDir, 'commands');
|
||||
const commandsGsdDir = path.join(commandsDir, 'gsd');
|
||||
const agentsDir = path.join(coreDir, 'agents');
|
||||
return [
|
||||
[configDir, { type: 'dir' }],
|
||||
[coreDir, { type: 'dir' }],
|
||||
[commandsDir, { type: 'dir' }],
|
||||
[commandsGsdDir, { type: 'dir' }],
|
||||
[path.join(commandsGsdDir, 'fixture.md'), { type: 'file', content: '# Fixture command\n' }],
|
||||
[agentsDir, { type: 'dir' }],
|
||||
[path.join(agentsDir, 'fixture-agent.md'), { type: 'file', content: '# Fixture agent\n' }],
|
||||
];
|
||||
}
|
||||
|
||||
function fakeInstalledCorpusManifestFiles() {
|
||||
return {
|
||||
'gsd-core/commands/gsd/fixture.md': sha256Hex('# Fixture command\n'),
|
||||
'gsd-core/agents/fixture-agent.md': sha256Hex('# Fixture agent\n'),
|
||||
};
|
||||
}
|
||||
|
||||
describe('installRuntimeArtifacts — F2: fake-adapter install touches no real filesystem', () => {
|
||||
test('fake-adapter install touches no real filesystem (claude, skills-only)', (t) => {
|
||||
// Every real fs method this call tree could reach is poisoned BY PATH
|
||||
@@ -399,15 +421,16 @@ describe('installRuntimeArtifacts — F2: fake-adapter install touches no real f
|
||||
// try/finally inside test bodies").
|
||||
const packageSourceHits = poisonRealFsAgainstDestination(t, '');
|
||||
|
||||
const fakeFs = createFakeInstallFs();
|
||||
|
||||
// configDir deliberately never created for real — F2 asserts nothing
|
||||
// real ever gets written under it.
|
||||
const configDir = path.join(os.tmpdir(), `gsd-f2-must-not-exist-${crypto.randomUUID()}`);
|
||||
const fakeFs = createFakeInstallFs(fakeInstalledCorpusSeed(configDir));
|
||||
|
||||
// configDir exists only in the fake store — F2 asserts nothing real ever
|
||||
// gets written under it. The installed corpus seed is the new provider
|
||||
// contract, not destination setup on the host filesystem.
|
||||
|
||||
const result = installRuntimeArtifacts(
|
||||
'claude', configDir, 'global', RESOLVED_CORE, undefined, undefined,
|
||||
{ fs: fakeFs },
|
||||
{ fs: fakeFs, packageRoot: REAL_PACKAGE_ROOT },
|
||||
);
|
||||
|
||||
assert.notStrictEqual(
|
||||
@@ -436,10 +459,13 @@ describe('installRuntimeArtifacts — F2: fake-adapter install touches no real f
|
||||
const legacyFile = path.join(legacyDir, 'gsd-old-cmd.md');
|
||||
const content = '# stale legacy command\n';
|
||||
const manifestPath = path.join(configDir, 'gsd-file-manifest.json');
|
||||
const manifestJson = JSON.stringify({ files: { 'command/gsd-old-cmd.md': sha256Hex(content) } });
|
||||
const manifestJson = JSON.stringify({ files: {
|
||||
...fakeInstalledCorpusManifestFiles(),
|
||||
'command/gsd-old-cmd.md': sha256Hex(content),
|
||||
} });
|
||||
|
||||
const fakeFs = createFakeInstallFs([
|
||||
[configDir, { type: 'dir' }],
|
||||
...fakeInstalledCorpusSeed(configDir),
|
||||
[legacyDir, { type: 'dir' }],
|
||||
[legacyFile, { type: 'file', content }],
|
||||
[manifestPath, { type: 'file', content: manifestJson }],
|
||||
@@ -447,7 +473,7 @@ describe('installRuntimeArtifacts — F2: fake-adapter install touches no real f
|
||||
|
||||
const result = installRuntimeArtifacts(
|
||||
'opencode', configDir, 'global', RESOLVED_CORE, undefined, undefined,
|
||||
{ fs: fakeFs },
|
||||
{ fs: fakeFs, packageRoot: REAL_PACKAGE_ROOT },
|
||||
);
|
||||
|
||||
assert.notStrictEqual(result, undefined, 'F2 (opencode legacy migration): must still return a plan');
|
||||
@@ -476,7 +502,7 @@ describe('installRuntimeArtifacts — F2: fake-adapter install touches no real f
|
||||
// the poisoned list (see install-fs-adapter.cts's module doc — it is
|
||||
// deliberately unrouted, real-fs-only, package-source introspection), so
|
||||
// resolving this here is safe even after poisoning existsSync et al.
|
||||
const commandsGsdDir = runtimeArtifactLayout.findInstallSourceRoot();
|
||||
const commandsGsdDir = REAL_COMMANDS_DIR;
|
||||
const repoRoot = path.dirname(path.dirname(commandsGsdDir));
|
||||
const nativePlugin = registry.runtimes.pi.runtime.hostBehaviors.nativePlugin;
|
||||
assert.ok(nativePlugin && nativePlugin.source, 'pi must declare hostBehaviors.nativePlugin.source (registry drifted)');
|
||||
@@ -489,7 +515,7 @@ describe('installRuntimeArtifacts — F2: fake-adapter install touches no real f
|
||||
|
||||
const result = installRuntimeArtifacts(
|
||||
'pi', configDir, 'global', RESOLVED_CORE, undefined, undefined,
|
||||
{ fs: fakeFs },
|
||||
{ fs: fakeFs, packageRoot: REAL_PACKAGE_ROOT },
|
||||
);
|
||||
|
||||
assert.notStrictEqual(result, undefined, 'F2 (nativePlugin): must still return a plan');
|
||||
@@ -522,10 +548,13 @@ describe('installRuntimeArtifacts — F2: fake-adapter install touches no real f
|
||||
const content = '# stale retired artifact\n';
|
||||
const relPath = `${destSubpath.replace(/\\/g, '/')}/${staleName}`;
|
||||
const manifestPath = path.join(configDir, 'gsd-file-manifest.json');
|
||||
const manifestJson = JSON.stringify({ files: { [relPath]: sha256Hex(content) } });
|
||||
const manifestJson = JSON.stringify({ files: {
|
||||
...fakeInstalledCorpusManifestFiles(),
|
||||
[relPath]: sha256Hex(content),
|
||||
} });
|
||||
|
||||
const fakeFs = createFakeInstallFs([
|
||||
[configDir, { type: 'dir' }],
|
||||
...fakeInstalledCorpusSeed(configDir),
|
||||
[destDir, { type: 'dir' }],
|
||||
[staleFile, { type: 'file', content }],
|
||||
[manifestPath, { type: 'file', content: manifestJson }],
|
||||
@@ -1196,6 +1225,19 @@ describe('installRuntimeArtifacts — K3: real install before/after, full recurs
|
||||
`K3 (${runtime}): the file sets written by two independent installs must match`,
|
||||
);
|
||||
for (const [relPath, contentA] of filesA) {
|
||||
if (relPath === '.gsd-source') {
|
||||
assert.strictEqual(
|
||||
contentA.toString('utf8'),
|
||||
`${path.join(dirA, 'gsd-core', 'commands', 'gsd')}\n`,
|
||||
`K3 (${runtime}): first marker must target its own installed corpus`,
|
||||
);
|
||||
assert.strictEqual(
|
||||
filesB.get(relPath).toString('utf8'),
|
||||
`${path.join(dirB, 'gsd-core', 'commands', 'gsd')}\n`,
|
||||
`K3 (${runtime}): second marker must target its own installed corpus`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
assert.ok(
|
||||
contentA.equals(filesB.get(relPath)),
|
||||
`K3 (${runtime}): ${relPath} content drifted between two independent installs`,
|
||||
|
||||
107
tests/fixtures/install-tree/antigravity.json
vendored
107
tests/fixtures/install-tree/antigravity.json
vendored
@@ -37,6 +37,41 @@
|
||||
"agents/gsd-verifier.md",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
@@ -48,6 +83,78 @@
|
||||
"gsd-core/bin/shared/model-catalog.json",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs",
|
||||
"gsd-core/commands/gsd/add-tests.md",
|
||||
"gsd-core/commands/gsd/ai-integration-phase.md",
|
||||
"gsd-core/commands/gsd/audit-fix.md",
|
||||
"gsd-core/commands/gsd/audit-milestone.md",
|
||||
"gsd-core/commands/gsd/audit-uat.md",
|
||||
"gsd-core/commands/gsd/autonomous.md",
|
||||
"gsd-core/commands/gsd/capture.md",
|
||||
"gsd-core/commands/gsd/cleanup.md",
|
||||
"gsd-core/commands/gsd/code-review.md",
|
||||
"gsd-core/commands/gsd/complete-milestone.md",
|
||||
"gsd-core/commands/gsd/config.md",
|
||||
"gsd-core/commands/gsd/debug.md",
|
||||
"gsd-core/commands/gsd/discuss-phase.md",
|
||||
"gsd-core/commands/gsd/docs-update.md",
|
||||
"gsd-core/commands/gsd/eval-review.md",
|
||||
"gsd-core/commands/gsd/execute-phase.md",
|
||||
"gsd-core/commands/gsd/explore.md",
|
||||
"gsd-core/commands/gsd/extract-learnings.md",
|
||||
"gsd-core/commands/gsd/fast.md",
|
||||
"gsd-core/commands/gsd/forensics.md",
|
||||
"gsd-core/commands/gsd/graphify.md",
|
||||
"gsd-core/commands/gsd/health.md",
|
||||
"gsd-core/commands/gsd/help.md",
|
||||
"gsd-core/commands/gsd/import.md",
|
||||
"gsd-core/commands/gsd/inbox.md",
|
||||
"gsd-core/commands/gsd/ingest-docs.md",
|
||||
"gsd-core/commands/gsd/manager.md",
|
||||
"gsd-core/commands/gsd/map-codebase.md",
|
||||
"gsd-core/commands/gsd/mempalace-capture.md",
|
||||
"gsd-core/commands/gsd/mempalace-recall.md",
|
||||
"gsd-core/commands/gsd/milestone-summary.md",
|
||||
"gsd-core/commands/gsd/mvp-phase.md",
|
||||
"gsd-core/commands/gsd/new-milestone.md",
|
||||
"gsd-core/commands/gsd/new-project.md",
|
||||
"gsd-core/commands/gsd/next.md",
|
||||
"gsd-core/commands/gsd/ns-context.md",
|
||||
"gsd-core/commands/gsd/ns-ideate.md",
|
||||
"gsd-core/commands/gsd/ns-manage.md",
|
||||
"gsd-core/commands/gsd/ns-project.md",
|
||||
"gsd-core/commands/gsd/ns-review.md",
|
||||
"gsd-core/commands/gsd/ns-workflow.md",
|
||||
"gsd-core/commands/gsd/onboard.md",
|
||||
"gsd-core/commands/gsd/pause-work.md",
|
||||
"gsd-core/commands/gsd/phase.md",
|
||||
"gsd-core/commands/gsd/plan-phase.md",
|
||||
"gsd-core/commands/gsd/plan-review-convergence.md",
|
||||
"gsd-core/commands/gsd/pr-branch.md",
|
||||
"gsd-core/commands/gsd/profile-user.md",
|
||||
"gsd-core/commands/gsd/progress.md",
|
||||
"gsd-core/commands/gsd/quick-batch.md",
|
||||
"gsd-core/commands/gsd/quick.md",
|
||||
"gsd-core/commands/gsd/resume-work.md",
|
||||
"gsd-core/commands/gsd/review-backlog.md",
|
||||
"gsd-core/commands/gsd/review.md",
|
||||
"gsd-core/commands/gsd/secure-phase.md",
|
||||
"gsd-core/commands/gsd/settings.md",
|
||||
"gsd-core/commands/gsd/ship.md",
|
||||
"gsd-core/commands/gsd/sketch.md",
|
||||
"gsd-core/commands/gsd/spec-phase.md",
|
||||
"gsd-core/commands/gsd/spike.md",
|
||||
"gsd-core/commands/gsd/stats.md",
|
||||
"gsd-core/commands/gsd/surface.md",
|
||||
"gsd-core/commands/gsd/thread.md",
|
||||
"gsd-core/commands/gsd/ui-phase.md",
|
||||
"gsd-core/commands/gsd/ui-review.md",
|
||||
"gsd-core/commands/gsd/ultraplan-phase.md",
|
||||
"gsd-core/commands/gsd/undo.md",
|
||||
"gsd-core/commands/gsd/update.md",
|
||||
"gsd-core/commands/gsd/validate-phase.md",
|
||||
"gsd-core/commands/gsd/verify-work.md",
|
||||
"gsd-core/commands/gsd/workspace.md",
|
||||
"gsd-core/commands/gsd/workstreams.md",
|
||||
"gsd-core/contexts/dev.md",
|
||||
"gsd-core/contexts/research.md",
|
||||
"gsd-core/contexts/review.md",
|
||||
|
||||
107
tests/fixtures/install-tree/augment.json
vendored
107
tests/fixtures/install-tree/augment.json
vendored
@@ -109,6 +109,41 @@
|
||||
"commands/gsd-workstreams.md",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
@@ -120,6 +155,78 @@
|
||||
"gsd-core/bin/shared/model-catalog.json",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs",
|
||||
"gsd-core/commands/gsd/add-tests.md",
|
||||
"gsd-core/commands/gsd/ai-integration-phase.md",
|
||||
"gsd-core/commands/gsd/audit-fix.md",
|
||||
"gsd-core/commands/gsd/audit-milestone.md",
|
||||
"gsd-core/commands/gsd/audit-uat.md",
|
||||
"gsd-core/commands/gsd/autonomous.md",
|
||||
"gsd-core/commands/gsd/capture.md",
|
||||
"gsd-core/commands/gsd/cleanup.md",
|
||||
"gsd-core/commands/gsd/code-review.md",
|
||||
"gsd-core/commands/gsd/complete-milestone.md",
|
||||
"gsd-core/commands/gsd/config.md",
|
||||
"gsd-core/commands/gsd/debug.md",
|
||||
"gsd-core/commands/gsd/discuss-phase.md",
|
||||
"gsd-core/commands/gsd/docs-update.md",
|
||||
"gsd-core/commands/gsd/eval-review.md",
|
||||
"gsd-core/commands/gsd/execute-phase.md",
|
||||
"gsd-core/commands/gsd/explore.md",
|
||||
"gsd-core/commands/gsd/extract-learnings.md",
|
||||
"gsd-core/commands/gsd/fast.md",
|
||||
"gsd-core/commands/gsd/forensics.md",
|
||||
"gsd-core/commands/gsd/graphify.md",
|
||||
"gsd-core/commands/gsd/health.md",
|
||||
"gsd-core/commands/gsd/help.md",
|
||||
"gsd-core/commands/gsd/import.md",
|
||||
"gsd-core/commands/gsd/inbox.md",
|
||||
"gsd-core/commands/gsd/ingest-docs.md",
|
||||
"gsd-core/commands/gsd/manager.md",
|
||||
"gsd-core/commands/gsd/map-codebase.md",
|
||||
"gsd-core/commands/gsd/mempalace-capture.md",
|
||||
"gsd-core/commands/gsd/mempalace-recall.md",
|
||||
"gsd-core/commands/gsd/milestone-summary.md",
|
||||
"gsd-core/commands/gsd/mvp-phase.md",
|
||||
"gsd-core/commands/gsd/new-milestone.md",
|
||||
"gsd-core/commands/gsd/new-project.md",
|
||||
"gsd-core/commands/gsd/next.md",
|
||||
"gsd-core/commands/gsd/ns-context.md",
|
||||
"gsd-core/commands/gsd/ns-ideate.md",
|
||||
"gsd-core/commands/gsd/ns-manage.md",
|
||||
"gsd-core/commands/gsd/ns-project.md",
|
||||
"gsd-core/commands/gsd/ns-review.md",
|
||||
"gsd-core/commands/gsd/ns-workflow.md",
|
||||
"gsd-core/commands/gsd/onboard.md",
|
||||
"gsd-core/commands/gsd/pause-work.md",
|
||||
"gsd-core/commands/gsd/phase.md",
|
||||
"gsd-core/commands/gsd/plan-phase.md",
|
||||
"gsd-core/commands/gsd/plan-review-convergence.md",
|
||||
"gsd-core/commands/gsd/pr-branch.md",
|
||||
"gsd-core/commands/gsd/profile-user.md",
|
||||
"gsd-core/commands/gsd/progress.md",
|
||||
"gsd-core/commands/gsd/quick-batch.md",
|
||||
"gsd-core/commands/gsd/quick.md",
|
||||
"gsd-core/commands/gsd/resume-work.md",
|
||||
"gsd-core/commands/gsd/review-backlog.md",
|
||||
"gsd-core/commands/gsd/review.md",
|
||||
"gsd-core/commands/gsd/secure-phase.md",
|
||||
"gsd-core/commands/gsd/settings.md",
|
||||
"gsd-core/commands/gsd/ship.md",
|
||||
"gsd-core/commands/gsd/sketch.md",
|
||||
"gsd-core/commands/gsd/spec-phase.md",
|
||||
"gsd-core/commands/gsd/spike.md",
|
||||
"gsd-core/commands/gsd/stats.md",
|
||||
"gsd-core/commands/gsd/surface.md",
|
||||
"gsd-core/commands/gsd/thread.md",
|
||||
"gsd-core/commands/gsd/ui-phase.md",
|
||||
"gsd-core/commands/gsd/ui-review.md",
|
||||
"gsd-core/commands/gsd/ultraplan-phase.md",
|
||||
"gsd-core/commands/gsd/undo.md",
|
||||
"gsd-core/commands/gsd/update.md",
|
||||
"gsd-core/commands/gsd/validate-phase.md",
|
||||
"gsd-core/commands/gsd/verify-work.md",
|
||||
"gsd-core/commands/gsd/workspace.md",
|
||||
"gsd-core/commands/gsd/workstreams.md",
|
||||
"gsd-core/contexts/dev.md",
|
||||
"gsd-core/contexts/research.md",
|
||||
"gsd-core/contexts/review.md",
|
||||
|
||||
107
tests/fixtures/install-tree/claude.json
vendored
107
tests/fixtures/install-tree/claude.json
vendored
@@ -37,6 +37,41 @@
|
||||
"agents/gsd-verifier.md",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
@@ -48,6 +83,78 @@
|
||||
"gsd-core/bin/shared/model-catalog.json",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs",
|
||||
"gsd-core/commands/gsd/add-tests.md",
|
||||
"gsd-core/commands/gsd/ai-integration-phase.md",
|
||||
"gsd-core/commands/gsd/audit-fix.md",
|
||||
"gsd-core/commands/gsd/audit-milestone.md",
|
||||
"gsd-core/commands/gsd/audit-uat.md",
|
||||
"gsd-core/commands/gsd/autonomous.md",
|
||||
"gsd-core/commands/gsd/capture.md",
|
||||
"gsd-core/commands/gsd/cleanup.md",
|
||||
"gsd-core/commands/gsd/code-review.md",
|
||||
"gsd-core/commands/gsd/complete-milestone.md",
|
||||
"gsd-core/commands/gsd/config.md",
|
||||
"gsd-core/commands/gsd/debug.md",
|
||||
"gsd-core/commands/gsd/discuss-phase.md",
|
||||
"gsd-core/commands/gsd/docs-update.md",
|
||||
"gsd-core/commands/gsd/eval-review.md",
|
||||
"gsd-core/commands/gsd/execute-phase.md",
|
||||
"gsd-core/commands/gsd/explore.md",
|
||||
"gsd-core/commands/gsd/extract-learnings.md",
|
||||
"gsd-core/commands/gsd/fast.md",
|
||||
"gsd-core/commands/gsd/forensics.md",
|
||||
"gsd-core/commands/gsd/graphify.md",
|
||||
"gsd-core/commands/gsd/health.md",
|
||||
"gsd-core/commands/gsd/help.md",
|
||||
"gsd-core/commands/gsd/import.md",
|
||||
"gsd-core/commands/gsd/inbox.md",
|
||||
"gsd-core/commands/gsd/ingest-docs.md",
|
||||
"gsd-core/commands/gsd/manager.md",
|
||||
"gsd-core/commands/gsd/map-codebase.md",
|
||||
"gsd-core/commands/gsd/mempalace-capture.md",
|
||||
"gsd-core/commands/gsd/mempalace-recall.md",
|
||||
"gsd-core/commands/gsd/milestone-summary.md",
|
||||
"gsd-core/commands/gsd/mvp-phase.md",
|
||||
"gsd-core/commands/gsd/new-milestone.md",
|
||||
"gsd-core/commands/gsd/new-project.md",
|
||||
"gsd-core/commands/gsd/next.md",
|
||||
"gsd-core/commands/gsd/ns-context.md",
|
||||
"gsd-core/commands/gsd/ns-ideate.md",
|
||||
"gsd-core/commands/gsd/ns-manage.md",
|
||||
"gsd-core/commands/gsd/ns-project.md",
|
||||
"gsd-core/commands/gsd/ns-review.md",
|
||||
"gsd-core/commands/gsd/ns-workflow.md",
|
||||
"gsd-core/commands/gsd/onboard.md",
|
||||
"gsd-core/commands/gsd/pause-work.md",
|
||||
"gsd-core/commands/gsd/phase.md",
|
||||
"gsd-core/commands/gsd/plan-phase.md",
|
||||
"gsd-core/commands/gsd/plan-review-convergence.md",
|
||||
"gsd-core/commands/gsd/pr-branch.md",
|
||||
"gsd-core/commands/gsd/profile-user.md",
|
||||
"gsd-core/commands/gsd/progress.md",
|
||||
"gsd-core/commands/gsd/quick-batch.md",
|
||||
"gsd-core/commands/gsd/quick.md",
|
||||
"gsd-core/commands/gsd/resume-work.md",
|
||||
"gsd-core/commands/gsd/review-backlog.md",
|
||||
"gsd-core/commands/gsd/review.md",
|
||||
"gsd-core/commands/gsd/secure-phase.md",
|
||||
"gsd-core/commands/gsd/settings.md",
|
||||
"gsd-core/commands/gsd/ship.md",
|
||||
"gsd-core/commands/gsd/sketch.md",
|
||||
"gsd-core/commands/gsd/spec-phase.md",
|
||||
"gsd-core/commands/gsd/spike.md",
|
||||
"gsd-core/commands/gsd/stats.md",
|
||||
"gsd-core/commands/gsd/surface.md",
|
||||
"gsd-core/commands/gsd/thread.md",
|
||||
"gsd-core/commands/gsd/ui-phase.md",
|
||||
"gsd-core/commands/gsd/ui-review.md",
|
||||
"gsd-core/commands/gsd/ultraplan-phase.md",
|
||||
"gsd-core/commands/gsd/undo.md",
|
||||
"gsd-core/commands/gsd/update.md",
|
||||
"gsd-core/commands/gsd/validate-phase.md",
|
||||
"gsd-core/commands/gsd/verify-work.md",
|
||||
"gsd-core/commands/gsd/workspace.md",
|
||||
"gsd-core/commands/gsd/workstreams.md",
|
||||
"gsd-core/contexts/dev.md",
|
||||
"gsd-core/contexts/research.md",
|
||||
"gsd-core/contexts/review.md",
|
||||
|
||||
107
tests/fixtures/install-tree/cline.json
vendored
107
tests/fixtures/install-tree/cline.json
vendored
@@ -39,6 +39,41 @@
|
||||
"agents/gsd-verifier.md",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
@@ -50,6 +85,78 @@
|
||||
"gsd-core/bin/shared/model-catalog.json",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs",
|
||||
"gsd-core/commands/gsd/add-tests.md",
|
||||
"gsd-core/commands/gsd/ai-integration-phase.md",
|
||||
"gsd-core/commands/gsd/audit-fix.md",
|
||||
"gsd-core/commands/gsd/audit-milestone.md",
|
||||
"gsd-core/commands/gsd/audit-uat.md",
|
||||
"gsd-core/commands/gsd/autonomous.md",
|
||||
"gsd-core/commands/gsd/capture.md",
|
||||
"gsd-core/commands/gsd/cleanup.md",
|
||||
"gsd-core/commands/gsd/code-review.md",
|
||||
"gsd-core/commands/gsd/complete-milestone.md",
|
||||
"gsd-core/commands/gsd/config.md",
|
||||
"gsd-core/commands/gsd/debug.md",
|
||||
"gsd-core/commands/gsd/discuss-phase.md",
|
||||
"gsd-core/commands/gsd/docs-update.md",
|
||||
"gsd-core/commands/gsd/eval-review.md",
|
||||
"gsd-core/commands/gsd/execute-phase.md",
|
||||
"gsd-core/commands/gsd/explore.md",
|
||||
"gsd-core/commands/gsd/extract-learnings.md",
|
||||
"gsd-core/commands/gsd/fast.md",
|
||||
"gsd-core/commands/gsd/forensics.md",
|
||||
"gsd-core/commands/gsd/graphify.md",
|
||||
"gsd-core/commands/gsd/health.md",
|
||||
"gsd-core/commands/gsd/help.md",
|
||||
"gsd-core/commands/gsd/import.md",
|
||||
"gsd-core/commands/gsd/inbox.md",
|
||||
"gsd-core/commands/gsd/ingest-docs.md",
|
||||
"gsd-core/commands/gsd/manager.md",
|
||||
"gsd-core/commands/gsd/map-codebase.md",
|
||||
"gsd-core/commands/gsd/mempalace-capture.md",
|
||||
"gsd-core/commands/gsd/mempalace-recall.md",
|
||||
"gsd-core/commands/gsd/milestone-summary.md",
|
||||
"gsd-core/commands/gsd/mvp-phase.md",
|
||||
"gsd-core/commands/gsd/new-milestone.md",
|
||||
"gsd-core/commands/gsd/new-project.md",
|
||||
"gsd-core/commands/gsd/next.md",
|
||||
"gsd-core/commands/gsd/ns-context.md",
|
||||
"gsd-core/commands/gsd/ns-ideate.md",
|
||||
"gsd-core/commands/gsd/ns-manage.md",
|
||||
"gsd-core/commands/gsd/ns-project.md",
|
||||
"gsd-core/commands/gsd/ns-review.md",
|
||||
"gsd-core/commands/gsd/ns-workflow.md",
|
||||
"gsd-core/commands/gsd/onboard.md",
|
||||
"gsd-core/commands/gsd/pause-work.md",
|
||||
"gsd-core/commands/gsd/phase.md",
|
||||
"gsd-core/commands/gsd/plan-phase.md",
|
||||
"gsd-core/commands/gsd/plan-review-convergence.md",
|
||||
"gsd-core/commands/gsd/pr-branch.md",
|
||||
"gsd-core/commands/gsd/profile-user.md",
|
||||
"gsd-core/commands/gsd/progress.md",
|
||||
"gsd-core/commands/gsd/quick-batch.md",
|
||||
"gsd-core/commands/gsd/quick.md",
|
||||
"gsd-core/commands/gsd/resume-work.md",
|
||||
"gsd-core/commands/gsd/review-backlog.md",
|
||||
"gsd-core/commands/gsd/review.md",
|
||||
"gsd-core/commands/gsd/secure-phase.md",
|
||||
"gsd-core/commands/gsd/settings.md",
|
||||
"gsd-core/commands/gsd/ship.md",
|
||||
"gsd-core/commands/gsd/sketch.md",
|
||||
"gsd-core/commands/gsd/spec-phase.md",
|
||||
"gsd-core/commands/gsd/spike.md",
|
||||
"gsd-core/commands/gsd/stats.md",
|
||||
"gsd-core/commands/gsd/surface.md",
|
||||
"gsd-core/commands/gsd/thread.md",
|
||||
"gsd-core/commands/gsd/ui-phase.md",
|
||||
"gsd-core/commands/gsd/ui-review.md",
|
||||
"gsd-core/commands/gsd/ultraplan-phase.md",
|
||||
"gsd-core/commands/gsd/undo.md",
|
||||
"gsd-core/commands/gsd/update.md",
|
||||
"gsd-core/commands/gsd/validate-phase.md",
|
||||
"gsd-core/commands/gsd/verify-work.md",
|
||||
"gsd-core/commands/gsd/workspace.md",
|
||||
"gsd-core/commands/gsd/workstreams.md",
|
||||
"gsd-core/contexts/dev.md",
|
||||
"gsd-core/contexts/research.md",
|
||||
"gsd-core/contexts/review.md",
|
||||
|
||||
107
tests/fixtures/install-tree/codebuddy.json
vendored
107
tests/fixtures/install-tree/codebuddy.json
vendored
@@ -109,6 +109,41 @@
|
||||
"commands/gsd-workstreams.md",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
@@ -120,6 +155,78 @@
|
||||
"gsd-core/bin/shared/model-catalog.json",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs",
|
||||
"gsd-core/commands/gsd/add-tests.md",
|
||||
"gsd-core/commands/gsd/ai-integration-phase.md",
|
||||
"gsd-core/commands/gsd/audit-fix.md",
|
||||
"gsd-core/commands/gsd/audit-milestone.md",
|
||||
"gsd-core/commands/gsd/audit-uat.md",
|
||||
"gsd-core/commands/gsd/autonomous.md",
|
||||
"gsd-core/commands/gsd/capture.md",
|
||||
"gsd-core/commands/gsd/cleanup.md",
|
||||
"gsd-core/commands/gsd/code-review.md",
|
||||
"gsd-core/commands/gsd/complete-milestone.md",
|
||||
"gsd-core/commands/gsd/config.md",
|
||||
"gsd-core/commands/gsd/debug.md",
|
||||
"gsd-core/commands/gsd/discuss-phase.md",
|
||||
"gsd-core/commands/gsd/docs-update.md",
|
||||
"gsd-core/commands/gsd/eval-review.md",
|
||||
"gsd-core/commands/gsd/execute-phase.md",
|
||||
"gsd-core/commands/gsd/explore.md",
|
||||
"gsd-core/commands/gsd/extract-learnings.md",
|
||||
"gsd-core/commands/gsd/fast.md",
|
||||
"gsd-core/commands/gsd/forensics.md",
|
||||
"gsd-core/commands/gsd/graphify.md",
|
||||
"gsd-core/commands/gsd/health.md",
|
||||
"gsd-core/commands/gsd/help.md",
|
||||
"gsd-core/commands/gsd/import.md",
|
||||
"gsd-core/commands/gsd/inbox.md",
|
||||
"gsd-core/commands/gsd/ingest-docs.md",
|
||||
"gsd-core/commands/gsd/manager.md",
|
||||
"gsd-core/commands/gsd/map-codebase.md",
|
||||
"gsd-core/commands/gsd/mempalace-capture.md",
|
||||
"gsd-core/commands/gsd/mempalace-recall.md",
|
||||
"gsd-core/commands/gsd/milestone-summary.md",
|
||||
"gsd-core/commands/gsd/mvp-phase.md",
|
||||
"gsd-core/commands/gsd/new-milestone.md",
|
||||
"gsd-core/commands/gsd/new-project.md",
|
||||
"gsd-core/commands/gsd/next.md",
|
||||
"gsd-core/commands/gsd/ns-context.md",
|
||||
"gsd-core/commands/gsd/ns-ideate.md",
|
||||
"gsd-core/commands/gsd/ns-manage.md",
|
||||
"gsd-core/commands/gsd/ns-project.md",
|
||||
"gsd-core/commands/gsd/ns-review.md",
|
||||
"gsd-core/commands/gsd/ns-workflow.md",
|
||||
"gsd-core/commands/gsd/onboard.md",
|
||||
"gsd-core/commands/gsd/pause-work.md",
|
||||
"gsd-core/commands/gsd/phase.md",
|
||||
"gsd-core/commands/gsd/plan-phase.md",
|
||||
"gsd-core/commands/gsd/plan-review-convergence.md",
|
||||
"gsd-core/commands/gsd/pr-branch.md",
|
||||
"gsd-core/commands/gsd/profile-user.md",
|
||||
"gsd-core/commands/gsd/progress.md",
|
||||
"gsd-core/commands/gsd/quick-batch.md",
|
||||
"gsd-core/commands/gsd/quick.md",
|
||||
"gsd-core/commands/gsd/resume-work.md",
|
||||
"gsd-core/commands/gsd/review-backlog.md",
|
||||
"gsd-core/commands/gsd/review.md",
|
||||
"gsd-core/commands/gsd/secure-phase.md",
|
||||
"gsd-core/commands/gsd/settings.md",
|
||||
"gsd-core/commands/gsd/ship.md",
|
||||
"gsd-core/commands/gsd/sketch.md",
|
||||
"gsd-core/commands/gsd/spec-phase.md",
|
||||
"gsd-core/commands/gsd/spike.md",
|
||||
"gsd-core/commands/gsd/stats.md",
|
||||
"gsd-core/commands/gsd/surface.md",
|
||||
"gsd-core/commands/gsd/thread.md",
|
||||
"gsd-core/commands/gsd/ui-phase.md",
|
||||
"gsd-core/commands/gsd/ui-review.md",
|
||||
"gsd-core/commands/gsd/ultraplan-phase.md",
|
||||
"gsd-core/commands/gsd/undo.md",
|
||||
"gsd-core/commands/gsd/update.md",
|
||||
"gsd-core/commands/gsd/validate-phase.md",
|
||||
"gsd-core/commands/gsd/verify-work.md",
|
||||
"gsd-core/commands/gsd/workspace.md",
|
||||
"gsd-core/commands/gsd/workstreams.md",
|
||||
"gsd-core/contexts/dev.md",
|
||||
"gsd-core/contexts/research.md",
|
||||
"gsd-core/contexts/review.md",
|
||||
|
||||
107
tests/fixtures/install-tree/codex.json
vendored
107
tests/fixtures/install-tree/codex.json
vendored
@@ -73,6 +73,41 @@
|
||||
"config.toml",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
@@ -84,6 +119,78 @@
|
||||
"gsd-core/bin/shared/model-catalog.json",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs",
|
||||
"gsd-core/commands/gsd/add-tests.md",
|
||||
"gsd-core/commands/gsd/ai-integration-phase.md",
|
||||
"gsd-core/commands/gsd/audit-fix.md",
|
||||
"gsd-core/commands/gsd/audit-milestone.md",
|
||||
"gsd-core/commands/gsd/audit-uat.md",
|
||||
"gsd-core/commands/gsd/autonomous.md",
|
||||
"gsd-core/commands/gsd/capture.md",
|
||||
"gsd-core/commands/gsd/cleanup.md",
|
||||
"gsd-core/commands/gsd/code-review.md",
|
||||
"gsd-core/commands/gsd/complete-milestone.md",
|
||||
"gsd-core/commands/gsd/config.md",
|
||||
"gsd-core/commands/gsd/debug.md",
|
||||
"gsd-core/commands/gsd/discuss-phase.md",
|
||||
"gsd-core/commands/gsd/docs-update.md",
|
||||
"gsd-core/commands/gsd/eval-review.md",
|
||||
"gsd-core/commands/gsd/execute-phase.md",
|
||||
"gsd-core/commands/gsd/explore.md",
|
||||
"gsd-core/commands/gsd/extract-learnings.md",
|
||||
"gsd-core/commands/gsd/fast.md",
|
||||
"gsd-core/commands/gsd/forensics.md",
|
||||
"gsd-core/commands/gsd/graphify.md",
|
||||
"gsd-core/commands/gsd/health.md",
|
||||
"gsd-core/commands/gsd/help.md",
|
||||
"gsd-core/commands/gsd/import.md",
|
||||
"gsd-core/commands/gsd/inbox.md",
|
||||
"gsd-core/commands/gsd/ingest-docs.md",
|
||||
"gsd-core/commands/gsd/manager.md",
|
||||
"gsd-core/commands/gsd/map-codebase.md",
|
||||
"gsd-core/commands/gsd/mempalace-capture.md",
|
||||
"gsd-core/commands/gsd/mempalace-recall.md",
|
||||
"gsd-core/commands/gsd/milestone-summary.md",
|
||||
"gsd-core/commands/gsd/mvp-phase.md",
|
||||
"gsd-core/commands/gsd/new-milestone.md",
|
||||
"gsd-core/commands/gsd/new-project.md",
|
||||
"gsd-core/commands/gsd/next.md",
|
||||
"gsd-core/commands/gsd/ns-context.md",
|
||||
"gsd-core/commands/gsd/ns-ideate.md",
|
||||
"gsd-core/commands/gsd/ns-manage.md",
|
||||
"gsd-core/commands/gsd/ns-project.md",
|
||||
"gsd-core/commands/gsd/ns-review.md",
|
||||
"gsd-core/commands/gsd/ns-workflow.md",
|
||||
"gsd-core/commands/gsd/onboard.md",
|
||||
"gsd-core/commands/gsd/pause-work.md",
|
||||
"gsd-core/commands/gsd/phase.md",
|
||||
"gsd-core/commands/gsd/plan-phase.md",
|
||||
"gsd-core/commands/gsd/plan-review-convergence.md",
|
||||
"gsd-core/commands/gsd/pr-branch.md",
|
||||
"gsd-core/commands/gsd/profile-user.md",
|
||||
"gsd-core/commands/gsd/progress.md",
|
||||
"gsd-core/commands/gsd/quick-batch.md",
|
||||
"gsd-core/commands/gsd/quick.md",
|
||||
"gsd-core/commands/gsd/resume-work.md",
|
||||
"gsd-core/commands/gsd/review-backlog.md",
|
||||
"gsd-core/commands/gsd/review.md",
|
||||
"gsd-core/commands/gsd/secure-phase.md",
|
||||
"gsd-core/commands/gsd/settings.md",
|
||||
"gsd-core/commands/gsd/ship.md",
|
||||
"gsd-core/commands/gsd/sketch.md",
|
||||
"gsd-core/commands/gsd/spec-phase.md",
|
||||
"gsd-core/commands/gsd/spike.md",
|
||||
"gsd-core/commands/gsd/stats.md",
|
||||
"gsd-core/commands/gsd/surface.md",
|
||||
"gsd-core/commands/gsd/thread.md",
|
||||
"gsd-core/commands/gsd/ui-phase.md",
|
||||
"gsd-core/commands/gsd/ui-review.md",
|
||||
"gsd-core/commands/gsd/ultraplan-phase.md",
|
||||
"gsd-core/commands/gsd/undo.md",
|
||||
"gsd-core/commands/gsd/update.md",
|
||||
"gsd-core/commands/gsd/validate-phase.md",
|
||||
"gsd-core/commands/gsd/verify-work.md",
|
||||
"gsd-core/commands/gsd/workspace.md",
|
||||
"gsd-core/commands/gsd/workstreams.md",
|
||||
"gsd-core/contexts/dev.md",
|
||||
"gsd-core/contexts/research.md",
|
||||
"gsd-core/contexts/review.md",
|
||||
|
||||
107
tests/fixtures/install-tree/copilot.json
vendored
107
tests/fixtures/install-tree/copilot.json
vendored
@@ -38,6 +38,41 @@
|
||||
"copilot-instructions.md",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
@@ -49,6 +84,78 @@
|
||||
"gsd-core/bin/shared/model-catalog.json",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs",
|
||||
"gsd-core/commands/gsd/add-tests.md",
|
||||
"gsd-core/commands/gsd/ai-integration-phase.md",
|
||||
"gsd-core/commands/gsd/audit-fix.md",
|
||||
"gsd-core/commands/gsd/audit-milestone.md",
|
||||
"gsd-core/commands/gsd/audit-uat.md",
|
||||
"gsd-core/commands/gsd/autonomous.md",
|
||||
"gsd-core/commands/gsd/capture.md",
|
||||
"gsd-core/commands/gsd/cleanup.md",
|
||||
"gsd-core/commands/gsd/code-review.md",
|
||||
"gsd-core/commands/gsd/complete-milestone.md",
|
||||
"gsd-core/commands/gsd/config.md",
|
||||
"gsd-core/commands/gsd/debug.md",
|
||||
"gsd-core/commands/gsd/discuss-phase.md",
|
||||
"gsd-core/commands/gsd/docs-update.md",
|
||||
"gsd-core/commands/gsd/eval-review.md",
|
||||
"gsd-core/commands/gsd/execute-phase.md",
|
||||
"gsd-core/commands/gsd/explore.md",
|
||||
"gsd-core/commands/gsd/extract-learnings.md",
|
||||
"gsd-core/commands/gsd/fast.md",
|
||||
"gsd-core/commands/gsd/forensics.md",
|
||||
"gsd-core/commands/gsd/graphify.md",
|
||||
"gsd-core/commands/gsd/health.md",
|
||||
"gsd-core/commands/gsd/help.md",
|
||||
"gsd-core/commands/gsd/import.md",
|
||||
"gsd-core/commands/gsd/inbox.md",
|
||||
"gsd-core/commands/gsd/ingest-docs.md",
|
||||
"gsd-core/commands/gsd/manager.md",
|
||||
"gsd-core/commands/gsd/map-codebase.md",
|
||||
"gsd-core/commands/gsd/mempalace-capture.md",
|
||||
"gsd-core/commands/gsd/mempalace-recall.md",
|
||||
"gsd-core/commands/gsd/milestone-summary.md",
|
||||
"gsd-core/commands/gsd/mvp-phase.md",
|
||||
"gsd-core/commands/gsd/new-milestone.md",
|
||||
"gsd-core/commands/gsd/new-project.md",
|
||||
"gsd-core/commands/gsd/next.md",
|
||||
"gsd-core/commands/gsd/ns-context.md",
|
||||
"gsd-core/commands/gsd/ns-ideate.md",
|
||||
"gsd-core/commands/gsd/ns-manage.md",
|
||||
"gsd-core/commands/gsd/ns-project.md",
|
||||
"gsd-core/commands/gsd/ns-review.md",
|
||||
"gsd-core/commands/gsd/ns-workflow.md",
|
||||
"gsd-core/commands/gsd/onboard.md",
|
||||
"gsd-core/commands/gsd/pause-work.md",
|
||||
"gsd-core/commands/gsd/phase.md",
|
||||
"gsd-core/commands/gsd/plan-phase.md",
|
||||
"gsd-core/commands/gsd/plan-review-convergence.md",
|
||||
"gsd-core/commands/gsd/pr-branch.md",
|
||||
"gsd-core/commands/gsd/profile-user.md",
|
||||
"gsd-core/commands/gsd/progress.md",
|
||||
"gsd-core/commands/gsd/quick-batch.md",
|
||||
"gsd-core/commands/gsd/quick.md",
|
||||
"gsd-core/commands/gsd/resume-work.md",
|
||||
"gsd-core/commands/gsd/review-backlog.md",
|
||||
"gsd-core/commands/gsd/review.md",
|
||||
"gsd-core/commands/gsd/secure-phase.md",
|
||||
"gsd-core/commands/gsd/settings.md",
|
||||
"gsd-core/commands/gsd/ship.md",
|
||||
"gsd-core/commands/gsd/sketch.md",
|
||||
"gsd-core/commands/gsd/spec-phase.md",
|
||||
"gsd-core/commands/gsd/spike.md",
|
||||
"gsd-core/commands/gsd/stats.md",
|
||||
"gsd-core/commands/gsd/surface.md",
|
||||
"gsd-core/commands/gsd/thread.md",
|
||||
"gsd-core/commands/gsd/ui-phase.md",
|
||||
"gsd-core/commands/gsd/ui-review.md",
|
||||
"gsd-core/commands/gsd/ultraplan-phase.md",
|
||||
"gsd-core/commands/gsd/undo.md",
|
||||
"gsd-core/commands/gsd/update.md",
|
||||
"gsd-core/commands/gsd/validate-phase.md",
|
||||
"gsd-core/commands/gsd/verify-work.md",
|
||||
"gsd-core/commands/gsd/workspace.md",
|
||||
"gsd-core/commands/gsd/workstreams.md",
|
||||
"gsd-core/contexts/dev.md",
|
||||
"gsd-core/contexts/research.md",
|
||||
"gsd-core/contexts/review.md",
|
||||
|
||||
107
tests/fixtures/install-tree/cursor.json
vendored
107
tests/fixtures/install-tree/cursor.json
vendored
@@ -37,6 +37,41 @@
|
||||
"agents/gsd-verifier.md",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
@@ -48,6 +83,78 @@
|
||||
"gsd-core/bin/shared/model-catalog.json",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs",
|
||||
"gsd-core/commands/gsd/add-tests.md",
|
||||
"gsd-core/commands/gsd/ai-integration-phase.md",
|
||||
"gsd-core/commands/gsd/audit-fix.md",
|
||||
"gsd-core/commands/gsd/audit-milestone.md",
|
||||
"gsd-core/commands/gsd/audit-uat.md",
|
||||
"gsd-core/commands/gsd/autonomous.md",
|
||||
"gsd-core/commands/gsd/capture.md",
|
||||
"gsd-core/commands/gsd/cleanup.md",
|
||||
"gsd-core/commands/gsd/code-review.md",
|
||||
"gsd-core/commands/gsd/complete-milestone.md",
|
||||
"gsd-core/commands/gsd/config.md",
|
||||
"gsd-core/commands/gsd/debug.md",
|
||||
"gsd-core/commands/gsd/discuss-phase.md",
|
||||
"gsd-core/commands/gsd/docs-update.md",
|
||||
"gsd-core/commands/gsd/eval-review.md",
|
||||
"gsd-core/commands/gsd/execute-phase.md",
|
||||
"gsd-core/commands/gsd/explore.md",
|
||||
"gsd-core/commands/gsd/extract-learnings.md",
|
||||
"gsd-core/commands/gsd/fast.md",
|
||||
"gsd-core/commands/gsd/forensics.md",
|
||||
"gsd-core/commands/gsd/graphify.md",
|
||||
"gsd-core/commands/gsd/health.md",
|
||||
"gsd-core/commands/gsd/help.md",
|
||||
"gsd-core/commands/gsd/import.md",
|
||||
"gsd-core/commands/gsd/inbox.md",
|
||||
"gsd-core/commands/gsd/ingest-docs.md",
|
||||
"gsd-core/commands/gsd/manager.md",
|
||||
"gsd-core/commands/gsd/map-codebase.md",
|
||||
"gsd-core/commands/gsd/mempalace-capture.md",
|
||||
"gsd-core/commands/gsd/mempalace-recall.md",
|
||||
"gsd-core/commands/gsd/milestone-summary.md",
|
||||
"gsd-core/commands/gsd/mvp-phase.md",
|
||||
"gsd-core/commands/gsd/new-milestone.md",
|
||||
"gsd-core/commands/gsd/new-project.md",
|
||||
"gsd-core/commands/gsd/next.md",
|
||||
"gsd-core/commands/gsd/ns-context.md",
|
||||
"gsd-core/commands/gsd/ns-ideate.md",
|
||||
"gsd-core/commands/gsd/ns-manage.md",
|
||||
"gsd-core/commands/gsd/ns-project.md",
|
||||
"gsd-core/commands/gsd/ns-review.md",
|
||||
"gsd-core/commands/gsd/ns-workflow.md",
|
||||
"gsd-core/commands/gsd/onboard.md",
|
||||
"gsd-core/commands/gsd/pause-work.md",
|
||||
"gsd-core/commands/gsd/phase.md",
|
||||
"gsd-core/commands/gsd/plan-phase.md",
|
||||
"gsd-core/commands/gsd/plan-review-convergence.md",
|
||||
"gsd-core/commands/gsd/pr-branch.md",
|
||||
"gsd-core/commands/gsd/profile-user.md",
|
||||
"gsd-core/commands/gsd/progress.md",
|
||||
"gsd-core/commands/gsd/quick-batch.md",
|
||||
"gsd-core/commands/gsd/quick.md",
|
||||
"gsd-core/commands/gsd/resume-work.md",
|
||||
"gsd-core/commands/gsd/review-backlog.md",
|
||||
"gsd-core/commands/gsd/review.md",
|
||||
"gsd-core/commands/gsd/secure-phase.md",
|
||||
"gsd-core/commands/gsd/settings.md",
|
||||
"gsd-core/commands/gsd/ship.md",
|
||||
"gsd-core/commands/gsd/sketch.md",
|
||||
"gsd-core/commands/gsd/spec-phase.md",
|
||||
"gsd-core/commands/gsd/spike.md",
|
||||
"gsd-core/commands/gsd/stats.md",
|
||||
"gsd-core/commands/gsd/surface.md",
|
||||
"gsd-core/commands/gsd/thread.md",
|
||||
"gsd-core/commands/gsd/ui-phase.md",
|
||||
"gsd-core/commands/gsd/ui-review.md",
|
||||
"gsd-core/commands/gsd/ultraplan-phase.md",
|
||||
"gsd-core/commands/gsd/undo.md",
|
||||
"gsd-core/commands/gsd/update.md",
|
||||
"gsd-core/commands/gsd/validate-phase.md",
|
||||
"gsd-core/commands/gsd/verify-work.md",
|
||||
"gsd-core/commands/gsd/workspace.md",
|
||||
"gsd-core/commands/gsd/workstreams.md",
|
||||
"gsd-core/contexts/dev.md",
|
||||
"gsd-core/contexts/research.md",
|
||||
"gsd-core/contexts/review.md",
|
||||
|
||||
107
tests/fixtures/install-tree/hermes.json
vendored
107
tests/fixtures/install-tree/hermes.json
vendored
@@ -37,6 +37,41 @@
|
||||
"agents/gsd-verifier.md",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
@@ -48,6 +83,78 @@
|
||||
"gsd-core/bin/shared/model-catalog.json",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs",
|
||||
"gsd-core/commands/gsd/add-tests.md",
|
||||
"gsd-core/commands/gsd/ai-integration-phase.md",
|
||||
"gsd-core/commands/gsd/audit-fix.md",
|
||||
"gsd-core/commands/gsd/audit-milestone.md",
|
||||
"gsd-core/commands/gsd/audit-uat.md",
|
||||
"gsd-core/commands/gsd/autonomous.md",
|
||||
"gsd-core/commands/gsd/capture.md",
|
||||
"gsd-core/commands/gsd/cleanup.md",
|
||||
"gsd-core/commands/gsd/code-review.md",
|
||||
"gsd-core/commands/gsd/complete-milestone.md",
|
||||
"gsd-core/commands/gsd/config.md",
|
||||
"gsd-core/commands/gsd/debug.md",
|
||||
"gsd-core/commands/gsd/discuss-phase.md",
|
||||
"gsd-core/commands/gsd/docs-update.md",
|
||||
"gsd-core/commands/gsd/eval-review.md",
|
||||
"gsd-core/commands/gsd/execute-phase.md",
|
||||
"gsd-core/commands/gsd/explore.md",
|
||||
"gsd-core/commands/gsd/extract-learnings.md",
|
||||
"gsd-core/commands/gsd/fast.md",
|
||||
"gsd-core/commands/gsd/forensics.md",
|
||||
"gsd-core/commands/gsd/graphify.md",
|
||||
"gsd-core/commands/gsd/health.md",
|
||||
"gsd-core/commands/gsd/help.md",
|
||||
"gsd-core/commands/gsd/import.md",
|
||||
"gsd-core/commands/gsd/inbox.md",
|
||||
"gsd-core/commands/gsd/ingest-docs.md",
|
||||
"gsd-core/commands/gsd/manager.md",
|
||||
"gsd-core/commands/gsd/map-codebase.md",
|
||||
"gsd-core/commands/gsd/mempalace-capture.md",
|
||||
"gsd-core/commands/gsd/mempalace-recall.md",
|
||||
"gsd-core/commands/gsd/milestone-summary.md",
|
||||
"gsd-core/commands/gsd/mvp-phase.md",
|
||||
"gsd-core/commands/gsd/new-milestone.md",
|
||||
"gsd-core/commands/gsd/new-project.md",
|
||||
"gsd-core/commands/gsd/next.md",
|
||||
"gsd-core/commands/gsd/ns-context.md",
|
||||
"gsd-core/commands/gsd/ns-ideate.md",
|
||||
"gsd-core/commands/gsd/ns-manage.md",
|
||||
"gsd-core/commands/gsd/ns-project.md",
|
||||
"gsd-core/commands/gsd/ns-review.md",
|
||||
"gsd-core/commands/gsd/ns-workflow.md",
|
||||
"gsd-core/commands/gsd/onboard.md",
|
||||
"gsd-core/commands/gsd/pause-work.md",
|
||||
"gsd-core/commands/gsd/phase.md",
|
||||
"gsd-core/commands/gsd/plan-phase.md",
|
||||
"gsd-core/commands/gsd/plan-review-convergence.md",
|
||||
"gsd-core/commands/gsd/pr-branch.md",
|
||||
"gsd-core/commands/gsd/profile-user.md",
|
||||
"gsd-core/commands/gsd/progress.md",
|
||||
"gsd-core/commands/gsd/quick-batch.md",
|
||||
"gsd-core/commands/gsd/quick.md",
|
||||
"gsd-core/commands/gsd/resume-work.md",
|
||||
"gsd-core/commands/gsd/review-backlog.md",
|
||||
"gsd-core/commands/gsd/review.md",
|
||||
"gsd-core/commands/gsd/secure-phase.md",
|
||||
"gsd-core/commands/gsd/settings.md",
|
||||
"gsd-core/commands/gsd/ship.md",
|
||||
"gsd-core/commands/gsd/sketch.md",
|
||||
"gsd-core/commands/gsd/spec-phase.md",
|
||||
"gsd-core/commands/gsd/spike.md",
|
||||
"gsd-core/commands/gsd/stats.md",
|
||||
"gsd-core/commands/gsd/surface.md",
|
||||
"gsd-core/commands/gsd/thread.md",
|
||||
"gsd-core/commands/gsd/ui-phase.md",
|
||||
"gsd-core/commands/gsd/ui-review.md",
|
||||
"gsd-core/commands/gsd/ultraplan-phase.md",
|
||||
"gsd-core/commands/gsd/undo.md",
|
||||
"gsd-core/commands/gsd/update.md",
|
||||
"gsd-core/commands/gsd/validate-phase.md",
|
||||
"gsd-core/commands/gsd/verify-work.md",
|
||||
"gsd-core/commands/gsd/workspace.md",
|
||||
"gsd-core/commands/gsd/workstreams.md",
|
||||
"gsd-core/contexts/dev.md",
|
||||
"gsd-core/contexts/research.md",
|
||||
"gsd-core/contexts/review.md",
|
||||
|
||||
107
tests/fixtures/install-tree/kilo.json
vendored
107
tests/fixtures/install-tree/kilo.json
vendored
@@ -109,6 +109,41 @@
|
||||
"command/gsd-workstreams.md",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
@@ -120,6 +155,78 @@
|
||||
"gsd-core/bin/shared/model-catalog.json",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs",
|
||||
"gsd-core/commands/gsd/add-tests.md",
|
||||
"gsd-core/commands/gsd/ai-integration-phase.md",
|
||||
"gsd-core/commands/gsd/audit-fix.md",
|
||||
"gsd-core/commands/gsd/audit-milestone.md",
|
||||
"gsd-core/commands/gsd/audit-uat.md",
|
||||
"gsd-core/commands/gsd/autonomous.md",
|
||||
"gsd-core/commands/gsd/capture.md",
|
||||
"gsd-core/commands/gsd/cleanup.md",
|
||||
"gsd-core/commands/gsd/code-review.md",
|
||||
"gsd-core/commands/gsd/complete-milestone.md",
|
||||
"gsd-core/commands/gsd/config.md",
|
||||
"gsd-core/commands/gsd/debug.md",
|
||||
"gsd-core/commands/gsd/discuss-phase.md",
|
||||
"gsd-core/commands/gsd/docs-update.md",
|
||||
"gsd-core/commands/gsd/eval-review.md",
|
||||
"gsd-core/commands/gsd/execute-phase.md",
|
||||
"gsd-core/commands/gsd/explore.md",
|
||||
"gsd-core/commands/gsd/extract-learnings.md",
|
||||
"gsd-core/commands/gsd/fast.md",
|
||||
"gsd-core/commands/gsd/forensics.md",
|
||||
"gsd-core/commands/gsd/graphify.md",
|
||||
"gsd-core/commands/gsd/health.md",
|
||||
"gsd-core/commands/gsd/help.md",
|
||||
"gsd-core/commands/gsd/import.md",
|
||||
"gsd-core/commands/gsd/inbox.md",
|
||||
"gsd-core/commands/gsd/ingest-docs.md",
|
||||
"gsd-core/commands/gsd/manager.md",
|
||||
"gsd-core/commands/gsd/map-codebase.md",
|
||||
"gsd-core/commands/gsd/mempalace-capture.md",
|
||||
"gsd-core/commands/gsd/mempalace-recall.md",
|
||||
"gsd-core/commands/gsd/milestone-summary.md",
|
||||
"gsd-core/commands/gsd/mvp-phase.md",
|
||||
"gsd-core/commands/gsd/new-milestone.md",
|
||||
"gsd-core/commands/gsd/new-project.md",
|
||||
"gsd-core/commands/gsd/next.md",
|
||||
"gsd-core/commands/gsd/ns-context.md",
|
||||
"gsd-core/commands/gsd/ns-ideate.md",
|
||||
"gsd-core/commands/gsd/ns-manage.md",
|
||||
"gsd-core/commands/gsd/ns-project.md",
|
||||
"gsd-core/commands/gsd/ns-review.md",
|
||||
"gsd-core/commands/gsd/ns-workflow.md",
|
||||
"gsd-core/commands/gsd/onboard.md",
|
||||
"gsd-core/commands/gsd/pause-work.md",
|
||||
"gsd-core/commands/gsd/phase.md",
|
||||
"gsd-core/commands/gsd/plan-phase.md",
|
||||
"gsd-core/commands/gsd/plan-review-convergence.md",
|
||||
"gsd-core/commands/gsd/pr-branch.md",
|
||||
"gsd-core/commands/gsd/profile-user.md",
|
||||
"gsd-core/commands/gsd/progress.md",
|
||||
"gsd-core/commands/gsd/quick-batch.md",
|
||||
"gsd-core/commands/gsd/quick.md",
|
||||
"gsd-core/commands/gsd/resume-work.md",
|
||||
"gsd-core/commands/gsd/review-backlog.md",
|
||||
"gsd-core/commands/gsd/review.md",
|
||||
"gsd-core/commands/gsd/secure-phase.md",
|
||||
"gsd-core/commands/gsd/settings.md",
|
||||
"gsd-core/commands/gsd/ship.md",
|
||||
"gsd-core/commands/gsd/sketch.md",
|
||||
"gsd-core/commands/gsd/spec-phase.md",
|
||||
"gsd-core/commands/gsd/spike.md",
|
||||
"gsd-core/commands/gsd/stats.md",
|
||||
"gsd-core/commands/gsd/surface.md",
|
||||
"gsd-core/commands/gsd/thread.md",
|
||||
"gsd-core/commands/gsd/ui-phase.md",
|
||||
"gsd-core/commands/gsd/ui-review.md",
|
||||
"gsd-core/commands/gsd/ultraplan-phase.md",
|
||||
"gsd-core/commands/gsd/undo.md",
|
||||
"gsd-core/commands/gsd/update.md",
|
||||
"gsd-core/commands/gsd/validate-phase.md",
|
||||
"gsd-core/commands/gsd/verify-work.md",
|
||||
"gsd-core/commands/gsd/workspace.md",
|
||||
"gsd-core/commands/gsd/workstreams.md",
|
||||
"gsd-core/contexts/dev.md",
|
||||
"gsd-core/contexts/research.md",
|
||||
"gsd-core/contexts/review.md",
|
||||
|
||||
107
tests/fixtures/install-tree/kimi-code.json
vendored
107
tests/fixtures/install-tree/kimi-code.json
vendored
@@ -38,6 +38,41 @@
|
||||
"config.toml",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
@@ -49,6 +84,78 @@
|
||||
"gsd-core/bin/shared/model-catalog.json",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs",
|
||||
"gsd-core/commands/gsd/add-tests.md",
|
||||
"gsd-core/commands/gsd/ai-integration-phase.md",
|
||||
"gsd-core/commands/gsd/audit-fix.md",
|
||||
"gsd-core/commands/gsd/audit-milestone.md",
|
||||
"gsd-core/commands/gsd/audit-uat.md",
|
||||
"gsd-core/commands/gsd/autonomous.md",
|
||||
"gsd-core/commands/gsd/capture.md",
|
||||
"gsd-core/commands/gsd/cleanup.md",
|
||||
"gsd-core/commands/gsd/code-review.md",
|
||||
"gsd-core/commands/gsd/complete-milestone.md",
|
||||
"gsd-core/commands/gsd/config.md",
|
||||
"gsd-core/commands/gsd/debug.md",
|
||||
"gsd-core/commands/gsd/discuss-phase.md",
|
||||
"gsd-core/commands/gsd/docs-update.md",
|
||||
"gsd-core/commands/gsd/eval-review.md",
|
||||
"gsd-core/commands/gsd/execute-phase.md",
|
||||
"gsd-core/commands/gsd/explore.md",
|
||||
"gsd-core/commands/gsd/extract-learnings.md",
|
||||
"gsd-core/commands/gsd/fast.md",
|
||||
"gsd-core/commands/gsd/forensics.md",
|
||||
"gsd-core/commands/gsd/graphify.md",
|
||||
"gsd-core/commands/gsd/health.md",
|
||||
"gsd-core/commands/gsd/help.md",
|
||||
"gsd-core/commands/gsd/import.md",
|
||||
"gsd-core/commands/gsd/inbox.md",
|
||||
"gsd-core/commands/gsd/ingest-docs.md",
|
||||
"gsd-core/commands/gsd/manager.md",
|
||||
"gsd-core/commands/gsd/map-codebase.md",
|
||||
"gsd-core/commands/gsd/mempalace-capture.md",
|
||||
"gsd-core/commands/gsd/mempalace-recall.md",
|
||||
"gsd-core/commands/gsd/milestone-summary.md",
|
||||
"gsd-core/commands/gsd/mvp-phase.md",
|
||||
"gsd-core/commands/gsd/new-milestone.md",
|
||||
"gsd-core/commands/gsd/new-project.md",
|
||||
"gsd-core/commands/gsd/next.md",
|
||||
"gsd-core/commands/gsd/ns-context.md",
|
||||
"gsd-core/commands/gsd/ns-ideate.md",
|
||||
"gsd-core/commands/gsd/ns-manage.md",
|
||||
"gsd-core/commands/gsd/ns-project.md",
|
||||
"gsd-core/commands/gsd/ns-review.md",
|
||||
"gsd-core/commands/gsd/ns-workflow.md",
|
||||
"gsd-core/commands/gsd/onboard.md",
|
||||
"gsd-core/commands/gsd/pause-work.md",
|
||||
"gsd-core/commands/gsd/phase.md",
|
||||
"gsd-core/commands/gsd/plan-phase.md",
|
||||
"gsd-core/commands/gsd/plan-review-convergence.md",
|
||||
"gsd-core/commands/gsd/pr-branch.md",
|
||||
"gsd-core/commands/gsd/profile-user.md",
|
||||
"gsd-core/commands/gsd/progress.md",
|
||||
"gsd-core/commands/gsd/quick-batch.md",
|
||||
"gsd-core/commands/gsd/quick.md",
|
||||
"gsd-core/commands/gsd/resume-work.md",
|
||||
"gsd-core/commands/gsd/review-backlog.md",
|
||||
"gsd-core/commands/gsd/review.md",
|
||||
"gsd-core/commands/gsd/secure-phase.md",
|
||||
"gsd-core/commands/gsd/settings.md",
|
||||
"gsd-core/commands/gsd/ship.md",
|
||||
"gsd-core/commands/gsd/sketch.md",
|
||||
"gsd-core/commands/gsd/spec-phase.md",
|
||||
"gsd-core/commands/gsd/spike.md",
|
||||
"gsd-core/commands/gsd/stats.md",
|
||||
"gsd-core/commands/gsd/surface.md",
|
||||
"gsd-core/commands/gsd/thread.md",
|
||||
"gsd-core/commands/gsd/ui-phase.md",
|
||||
"gsd-core/commands/gsd/ui-review.md",
|
||||
"gsd-core/commands/gsd/ultraplan-phase.md",
|
||||
"gsd-core/commands/gsd/undo.md",
|
||||
"gsd-core/commands/gsd/update.md",
|
||||
"gsd-core/commands/gsd/validate-phase.md",
|
||||
"gsd-core/commands/gsd/verify-work.md",
|
||||
"gsd-core/commands/gsd/workspace.md",
|
||||
"gsd-core/commands/gsd/workstreams.md",
|
||||
"gsd-core/contexts/dev.md",
|
||||
"gsd-core/contexts/research.md",
|
||||
"gsd-core/contexts/review.md",
|
||||
|
||||
107
tests/fixtures/install-tree/kimi.json
vendored
107
tests/fixtures/install-tree/kimi.json
vendored
@@ -74,6 +74,41 @@
|
||||
"agents/subagents/gsd-verifier.yaml",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
@@ -85,6 +120,78 @@
|
||||
"gsd-core/bin/shared/model-catalog.json",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs",
|
||||
"gsd-core/commands/gsd/add-tests.md",
|
||||
"gsd-core/commands/gsd/ai-integration-phase.md",
|
||||
"gsd-core/commands/gsd/audit-fix.md",
|
||||
"gsd-core/commands/gsd/audit-milestone.md",
|
||||
"gsd-core/commands/gsd/audit-uat.md",
|
||||
"gsd-core/commands/gsd/autonomous.md",
|
||||
"gsd-core/commands/gsd/capture.md",
|
||||
"gsd-core/commands/gsd/cleanup.md",
|
||||
"gsd-core/commands/gsd/code-review.md",
|
||||
"gsd-core/commands/gsd/complete-milestone.md",
|
||||
"gsd-core/commands/gsd/config.md",
|
||||
"gsd-core/commands/gsd/debug.md",
|
||||
"gsd-core/commands/gsd/discuss-phase.md",
|
||||
"gsd-core/commands/gsd/docs-update.md",
|
||||
"gsd-core/commands/gsd/eval-review.md",
|
||||
"gsd-core/commands/gsd/execute-phase.md",
|
||||
"gsd-core/commands/gsd/explore.md",
|
||||
"gsd-core/commands/gsd/extract-learnings.md",
|
||||
"gsd-core/commands/gsd/fast.md",
|
||||
"gsd-core/commands/gsd/forensics.md",
|
||||
"gsd-core/commands/gsd/graphify.md",
|
||||
"gsd-core/commands/gsd/health.md",
|
||||
"gsd-core/commands/gsd/help.md",
|
||||
"gsd-core/commands/gsd/import.md",
|
||||
"gsd-core/commands/gsd/inbox.md",
|
||||
"gsd-core/commands/gsd/ingest-docs.md",
|
||||
"gsd-core/commands/gsd/manager.md",
|
||||
"gsd-core/commands/gsd/map-codebase.md",
|
||||
"gsd-core/commands/gsd/mempalace-capture.md",
|
||||
"gsd-core/commands/gsd/mempalace-recall.md",
|
||||
"gsd-core/commands/gsd/milestone-summary.md",
|
||||
"gsd-core/commands/gsd/mvp-phase.md",
|
||||
"gsd-core/commands/gsd/new-milestone.md",
|
||||
"gsd-core/commands/gsd/new-project.md",
|
||||
"gsd-core/commands/gsd/next.md",
|
||||
"gsd-core/commands/gsd/ns-context.md",
|
||||
"gsd-core/commands/gsd/ns-ideate.md",
|
||||
"gsd-core/commands/gsd/ns-manage.md",
|
||||
"gsd-core/commands/gsd/ns-project.md",
|
||||
"gsd-core/commands/gsd/ns-review.md",
|
||||
"gsd-core/commands/gsd/ns-workflow.md",
|
||||
"gsd-core/commands/gsd/onboard.md",
|
||||
"gsd-core/commands/gsd/pause-work.md",
|
||||
"gsd-core/commands/gsd/phase.md",
|
||||
"gsd-core/commands/gsd/plan-phase.md",
|
||||
"gsd-core/commands/gsd/plan-review-convergence.md",
|
||||
"gsd-core/commands/gsd/pr-branch.md",
|
||||
"gsd-core/commands/gsd/profile-user.md",
|
||||
"gsd-core/commands/gsd/progress.md",
|
||||
"gsd-core/commands/gsd/quick-batch.md",
|
||||
"gsd-core/commands/gsd/quick.md",
|
||||
"gsd-core/commands/gsd/resume-work.md",
|
||||
"gsd-core/commands/gsd/review-backlog.md",
|
||||
"gsd-core/commands/gsd/review.md",
|
||||
"gsd-core/commands/gsd/secure-phase.md",
|
||||
"gsd-core/commands/gsd/settings.md",
|
||||
"gsd-core/commands/gsd/ship.md",
|
||||
"gsd-core/commands/gsd/sketch.md",
|
||||
"gsd-core/commands/gsd/spec-phase.md",
|
||||
"gsd-core/commands/gsd/spike.md",
|
||||
"gsd-core/commands/gsd/stats.md",
|
||||
"gsd-core/commands/gsd/surface.md",
|
||||
"gsd-core/commands/gsd/thread.md",
|
||||
"gsd-core/commands/gsd/ui-phase.md",
|
||||
"gsd-core/commands/gsd/ui-review.md",
|
||||
"gsd-core/commands/gsd/ultraplan-phase.md",
|
||||
"gsd-core/commands/gsd/undo.md",
|
||||
"gsd-core/commands/gsd/update.md",
|
||||
"gsd-core/commands/gsd/validate-phase.md",
|
||||
"gsd-core/commands/gsd/verify-work.md",
|
||||
"gsd-core/commands/gsd/workspace.md",
|
||||
"gsd-core/commands/gsd/workstreams.md",
|
||||
"gsd-core/contexts/dev.md",
|
||||
"gsd-core/contexts/research.md",
|
||||
"gsd-core/contexts/review.md",
|
||||
|
||||
107
tests/fixtures/install-tree/opencode.json
vendored
107
tests/fixtures/install-tree/opencode.json
vendored
@@ -109,6 +109,41 @@
|
||||
"commands/gsd-workstreams.md",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
@@ -120,6 +155,78 @@
|
||||
"gsd-core/bin/shared/model-catalog.json",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs",
|
||||
"gsd-core/commands/gsd/add-tests.md",
|
||||
"gsd-core/commands/gsd/ai-integration-phase.md",
|
||||
"gsd-core/commands/gsd/audit-fix.md",
|
||||
"gsd-core/commands/gsd/audit-milestone.md",
|
||||
"gsd-core/commands/gsd/audit-uat.md",
|
||||
"gsd-core/commands/gsd/autonomous.md",
|
||||
"gsd-core/commands/gsd/capture.md",
|
||||
"gsd-core/commands/gsd/cleanup.md",
|
||||
"gsd-core/commands/gsd/code-review.md",
|
||||
"gsd-core/commands/gsd/complete-milestone.md",
|
||||
"gsd-core/commands/gsd/config.md",
|
||||
"gsd-core/commands/gsd/debug.md",
|
||||
"gsd-core/commands/gsd/discuss-phase.md",
|
||||
"gsd-core/commands/gsd/docs-update.md",
|
||||
"gsd-core/commands/gsd/eval-review.md",
|
||||
"gsd-core/commands/gsd/execute-phase.md",
|
||||
"gsd-core/commands/gsd/explore.md",
|
||||
"gsd-core/commands/gsd/extract-learnings.md",
|
||||
"gsd-core/commands/gsd/fast.md",
|
||||
"gsd-core/commands/gsd/forensics.md",
|
||||
"gsd-core/commands/gsd/graphify.md",
|
||||
"gsd-core/commands/gsd/health.md",
|
||||
"gsd-core/commands/gsd/help.md",
|
||||
"gsd-core/commands/gsd/import.md",
|
||||
"gsd-core/commands/gsd/inbox.md",
|
||||
"gsd-core/commands/gsd/ingest-docs.md",
|
||||
"gsd-core/commands/gsd/manager.md",
|
||||
"gsd-core/commands/gsd/map-codebase.md",
|
||||
"gsd-core/commands/gsd/mempalace-capture.md",
|
||||
"gsd-core/commands/gsd/mempalace-recall.md",
|
||||
"gsd-core/commands/gsd/milestone-summary.md",
|
||||
"gsd-core/commands/gsd/mvp-phase.md",
|
||||
"gsd-core/commands/gsd/new-milestone.md",
|
||||
"gsd-core/commands/gsd/new-project.md",
|
||||
"gsd-core/commands/gsd/next.md",
|
||||
"gsd-core/commands/gsd/ns-context.md",
|
||||
"gsd-core/commands/gsd/ns-ideate.md",
|
||||
"gsd-core/commands/gsd/ns-manage.md",
|
||||
"gsd-core/commands/gsd/ns-project.md",
|
||||
"gsd-core/commands/gsd/ns-review.md",
|
||||
"gsd-core/commands/gsd/ns-workflow.md",
|
||||
"gsd-core/commands/gsd/onboard.md",
|
||||
"gsd-core/commands/gsd/pause-work.md",
|
||||
"gsd-core/commands/gsd/phase.md",
|
||||
"gsd-core/commands/gsd/plan-phase.md",
|
||||
"gsd-core/commands/gsd/plan-review-convergence.md",
|
||||
"gsd-core/commands/gsd/pr-branch.md",
|
||||
"gsd-core/commands/gsd/profile-user.md",
|
||||
"gsd-core/commands/gsd/progress.md",
|
||||
"gsd-core/commands/gsd/quick-batch.md",
|
||||
"gsd-core/commands/gsd/quick.md",
|
||||
"gsd-core/commands/gsd/resume-work.md",
|
||||
"gsd-core/commands/gsd/review-backlog.md",
|
||||
"gsd-core/commands/gsd/review.md",
|
||||
"gsd-core/commands/gsd/secure-phase.md",
|
||||
"gsd-core/commands/gsd/settings.md",
|
||||
"gsd-core/commands/gsd/ship.md",
|
||||
"gsd-core/commands/gsd/sketch.md",
|
||||
"gsd-core/commands/gsd/spec-phase.md",
|
||||
"gsd-core/commands/gsd/spike.md",
|
||||
"gsd-core/commands/gsd/stats.md",
|
||||
"gsd-core/commands/gsd/surface.md",
|
||||
"gsd-core/commands/gsd/thread.md",
|
||||
"gsd-core/commands/gsd/ui-phase.md",
|
||||
"gsd-core/commands/gsd/ui-review.md",
|
||||
"gsd-core/commands/gsd/ultraplan-phase.md",
|
||||
"gsd-core/commands/gsd/undo.md",
|
||||
"gsd-core/commands/gsd/update.md",
|
||||
"gsd-core/commands/gsd/validate-phase.md",
|
||||
"gsd-core/commands/gsd/verify-work.md",
|
||||
"gsd-core/commands/gsd/workspace.md",
|
||||
"gsd-core/commands/gsd/workstreams.md",
|
||||
"gsd-core/contexts/dev.md",
|
||||
"gsd-core/contexts/research.md",
|
||||
"gsd-core/contexts/review.md",
|
||||
|
||||
107
tests/fixtures/install-tree/qwen.json
vendored
107
tests/fixtures/install-tree/qwen.json
vendored
@@ -37,6 +37,41 @@
|
||||
"agents/gsd-verifier.md",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
@@ -48,6 +83,78 @@
|
||||
"gsd-core/bin/shared/model-catalog.json",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs",
|
||||
"gsd-core/commands/gsd/add-tests.md",
|
||||
"gsd-core/commands/gsd/ai-integration-phase.md",
|
||||
"gsd-core/commands/gsd/audit-fix.md",
|
||||
"gsd-core/commands/gsd/audit-milestone.md",
|
||||
"gsd-core/commands/gsd/audit-uat.md",
|
||||
"gsd-core/commands/gsd/autonomous.md",
|
||||
"gsd-core/commands/gsd/capture.md",
|
||||
"gsd-core/commands/gsd/cleanup.md",
|
||||
"gsd-core/commands/gsd/code-review.md",
|
||||
"gsd-core/commands/gsd/complete-milestone.md",
|
||||
"gsd-core/commands/gsd/config.md",
|
||||
"gsd-core/commands/gsd/debug.md",
|
||||
"gsd-core/commands/gsd/discuss-phase.md",
|
||||
"gsd-core/commands/gsd/docs-update.md",
|
||||
"gsd-core/commands/gsd/eval-review.md",
|
||||
"gsd-core/commands/gsd/execute-phase.md",
|
||||
"gsd-core/commands/gsd/explore.md",
|
||||
"gsd-core/commands/gsd/extract-learnings.md",
|
||||
"gsd-core/commands/gsd/fast.md",
|
||||
"gsd-core/commands/gsd/forensics.md",
|
||||
"gsd-core/commands/gsd/graphify.md",
|
||||
"gsd-core/commands/gsd/health.md",
|
||||
"gsd-core/commands/gsd/help.md",
|
||||
"gsd-core/commands/gsd/import.md",
|
||||
"gsd-core/commands/gsd/inbox.md",
|
||||
"gsd-core/commands/gsd/ingest-docs.md",
|
||||
"gsd-core/commands/gsd/manager.md",
|
||||
"gsd-core/commands/gsd/map-codebase.md",
|
||||
"gsd-core/commands/gsd/mempalace-capture.md",
|
||||
"gsd-core/commands/gsd/mempalace-recall.md",
|
||||
"gsd-core/commands/gsd/milestone-summary.md",
|
||||
"gsd-core/commands/gsd/mvp-phase.md",
|
||||
"gsd-core/commands/gsd/new-milestone.md",
|
||||
"gsd-core/commands/gsd/new-project.md",
|
||||
"gsd-core/commands/gsd/next.md",
|
||||
"gsd-core/commands/gsd/ns-context.md",
|
||||
"gsd-core/commands/gsd/ns-ideate.md",
|
||||
"gsd-core/commands/gsd/ns-manage.md",
|
||||
"gsd-core/commands/gsd/ns-project.md",
|
||||
"gsd-core/commands/gsd/ns-review.md",
|
||||
"gsd-core/commands/gsd/ns-workflow.md",
|
||||
"gsd-core/commands/gsd/onboard.md",
|
||||
"gsd-core/commands/gsd/pause-work.md",
|
||||
"gsd-core/commands/gsd/phase.md",
|
||||
"gsd-core/commands/gsd/plan-phase.md",
|
||||
"gsd-core/commands/gsd/plan-review-convergence.md",
|
||||
"gsd-core/commands/gsd/pr-branch.md",
|
||||
"gsd-core/commands/gsd/profile-user.md",
|
||||
"gsd-core/commands/gsd/progress.md",
|
||||
"gsd-core/commands/gsd/quick-batch.md",
|
||||
"gsd-core/commands/gsd/quick.md",
|
||||
"gsd-core/commands/gsd/resume-work.md",
|
||||
"gsd-core/commands/gsd/review-backlog.md",
|
||||
"gsd-core/commands/gsd/review.md",
|
||||
"gsd-core/commands/gsd/secure-phase.md",
|
||||
"gsd-core/commands/gsd/settings.md",
|
||||
"gsd-core/commands/gsd/ship.md",
|
||||
"gsd-core/commands/gsd/sketch.md",
|
||||
"gsd-core/commands/gsd/spec-phase.md",
|
||||
"gsd-core/commands/gsd/spike.md",
|
||||
"gsd-core/commands/gsd/stats.md",
|
||||
"gsd-core/commands/gsd/surface.md",
|
||||
"gsd-core/commands/gsd/thread.md",
|
||||
"gsd-core/commands/gsd/ui-phase.md",
|
||||
"gsd-core/commands/gsd/ui-review.md",
|
||||
"gsd-core/commands/gsd/ultraplan-phase.md",
|
||||
"gsd-core/commands/gsd/undo.md",
|
||||
"gsd-core/commands/gsd/update.md",
|
||||
"gsd-core/commands/gsd/validate-phase.md",
|
||||
"gsd-core/commands/gsd/verify-work.md",
|
||||
"gsd-core/commands/gsd/workspace.md",
|
||||
"gsd-core/commands/gsd/workstreams.md",
|
||||
"gsd-core/contexts/dev.md",
|
||||
"gsd-core/contexts/research.md",
|
||||
"gsd-core/contexts/review.md",
|
||||
|
||||
107
tests/fixtures/install-tree/trae.json
vendored
107
tests/fixtures/install-tree/trae.json
vendored
@@ -37,6 +37,41 @@
|
||||
"agents/gsd-verifier.md",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
@@ -48,6 +83,78 @@
|
||||
"gsd-core/bin/shared/model-catalog.json",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs",
|
||||
"gsd-core/commands/gsd/add-tests.md",
|
||||
"gsd-core/commands/gsd/ai-integration-phase.md",
|
||||
"gsd-core/commands/gsd/audit-fix.md",
|
||||
"gsd-core/commands/gsd/audit-milestone.md",
|
||||
"gsd-core/commands/gsd/audit-uat.md",
|
||||
"gsd-core/commands/gsd/autonomous.md",
|
||||
"gsd-core/commands/gsd/capture.md",
|
||||
"gsd-core/commands/gsd/cleanup.md",
|
||||
"gsd-core/commands/gsd/code-review.md",
|
||||
"gsd-core/commands/gsd/complete-milestone.md",
|
||||
"gsd-core/commands/gsd/config.md",
|
||||
"gsd-core/commands/gsd/debug.md",
|
||||
"gsd-core/commands/gsd/discuss-phase.md",
|
||||
"gsd-core/commands/gsd/docs-update.md",
|
||||
"gsd-core/commands/gsd/eval-review.md",
|
||||
"gsd-core/commands/gsd/execute-phase.md",
|
||||
"gsd-core/commands/gsd/explore.md",
|
||||
"gsd-core/commands/gsd/extract-learnings.md",
|
||||
"gsd-core/commands/gsd/fast.md",
|
||||
"gsd-core/commands/gsd/forensics.md",
|
||||
"gsd-core/commands/gsd/graphify.md",
|
||||
"gsd-core/commands/gsd/health.md",
|
||||
"gsd-core/commands/gsd/help.md",
|
||||
"gsd-core/commands/gsd/import.md",
|
||||
"gsd-core/commands/gsd/inbox.md",
|
||||
"gsd-core/commands/gsd/ingest-docs.md",
|
||||
"gsd-core/commands/gsd/manager.md",
|
||||
"gsd-core/commands/gsd/map-codebase.md",
|
||||
"gsd-core/commands/gsd/mempalace-capture.md",
|
||||
"gsd-core/commands/gsd/mempalace-recall.md",
|
||||
"gsd-core/commands/gsd/milestone-summary.md",
|
||||
"gsd-core/commands/gsd/mvp-phase.md",
|
||||
"gsd-core/commands/gsd/new-milestone.md",
|
||||
"gsd-core/commands/gsd/new-project.md",
|
||||
"gsd-core/commands/gsd/next.md",
|
||||
"gsd-core/commands/gsd/ns-context.md",
|
||||
"gsd-core/commands/gsd/ns-ideate.md",
|
||||
"gsd-core/commands/gsd/ns-manage.md",
|
||||
"gsd-core/commands/gsd/ns-project.md",
|
||||
"gsd-core/commands/gsd/ns-review.md",
|
||||
"gsd-core/commands/gsd/ns-workflow.md",
|
||||
"gsd-core/commands/gsd/onboard.md",
|
||||
"gsd-core/commands/gsd/pause-work.md",
|
||||
"gsd-core/commands/gsd/phase.md",
|
||||
"gsd-core/commands/gsd/plan-phase.md",
|
||||
"gsd-core/commands/gsd/plan-review-convergence.md",
|
||||
"gsd-core/commands/gsd/pr-branch.md",
|
||||
"gsd-core/commands/gsd/profile-user.md",
|
||||
"gsd-core/commands/gsd/progress.md",
|
||||
"gsd-core/commands/gsd/quick-batch.md",
|
||||
"gsd-core/commands/gsd/quick.md",
|
||||
"gsd-core/commands/gsd/resume-work.md",
|
||||
"gsd-core/commands/gsd/review-backlog.md",
|
||||
"gsd-core/commands/gsd/review.md",
|
||||
"gsd-core/commands/gsd/secure-phase.md",
|
||||
"gsd-core/commands/gsd/settings.md",
|
||||
"gsd-core/commands/gsd/ship.md",
|
||||
"gsd-core/commands/gsd/sketch.md",
|
||||
"gsd-core/commands/gsd/spec-phase.md",
|
||||
"gsd-core/commands/gsd/spike.md",
|
||||
"gsd-core/commands/gsd/stats.md",
|
||||
"gsd-core/commands/gsd/surface.md",
|
||||
"gsd-core/commands/gsd/thread.md",
|
||||
"gsd-core/commands/gsd/ui-phase.md",
|
||||
"gsd-core/commands/gsd/ui-review.md",
|
||||
"gsd-core/commands/gsd/ultraplan-phase.md",
|
||||
"gsd-core/commands/gsd/undo.md",
|
||||
"gsd-core/commands/gsd/update.md",
|
||||
"gsd-core/commands/gsd/validate-phase.md",
|
||||
"gsd-core/commands/gsd/verify-work.md",
|
||||
"gsd-core/commands/gsd/workspace.md",
|
||||
"gsd-core/commands/gsd/workstreams.md",
|
||||
"gsd-core/contexts/dev.md",
|
||||
"gsd-core/contexts/research.md",
|
||||
"gsd-core/contexts/review.md",
|
||||
|
||||
35
tests/fixtures/install-tree/windsurf.json
vendored
35
tests/fixtures/install-tree/windsurf.json
vendored
@@ -37,6 +37,41 @@
|
||||
"agents/gsd-verifier.md",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
|
||||
107
tests/fixtures/install-tree/zcode.json
vendored
107
tests/fixtures/install-tree/zcode.json
vendored
@@ -109,6 +109,41 @@
|
||||
"commands/gsd-workstreams.md",
|
||||
"gsd-core/.gsd-runtime",
|
||||
"gsd-core/VERSION",
|
||||
"gsd-core/agents/gsd-advisor-researcher.md",
|
||||
"gsd-core/agents/gsd-ai-researcher.md",
|
||||
"gsd-core/agents/gsd-assumptions-analyzer.md",
|
||||
"gsd-core/agents/gsd-code-fixer.md",
|
||||
"gsd-core/agents/gsd-code-reviewer.md",
|
||||
"gsd-core/agents/gsd-codebase-mapper.md",
|
||||
"gsd-core/agents/gsd-debug-session-manager.md",
|
||||
"gsd-core/agents/gsd-debugger.md",
|
||||
"gsd-core/agents/gsd-doc-classifier.md",
|
||||
"gsd-core/agents/gsd-doc-synthesizer.md",
|
||||
"gsd-core/agents/gsd-doc-verifier.md",
|
||||
"gsd-core/agents/gsd-doc-writer.md",
|
||||
"gsd-core/agents/gsd-dom-verifier.md",
|
||||
"gsd-core/agents/gsd-domain-researcher.md",
|
||||
"gsd-core/agents/gsd-eval-auditor.md",
|
||||
"gsd-core/agents/gsd-eval-planner.md",
|
||||
"gsd-core/agents/gsd-executor.md",
|
||||
"gsd-core/agents/gsd-framework-selector.md",
|
||||
"gsd-core/agents/gsd-integration-checker.md",
|
||||
"gsd-core/agents/gsd-intel-updater.md",
|
||||
"gsd-core/agents/gsd-mempalace-curator.md",
|
||||
"gsd-core/agents/gsd-nyquist-auditor.md",
|
||||
"gsd-core/agents/gsd-pattern-mapper.md",
|
||||
"gsd-core/agents/gsd-phase-researcher.md",
|
||||
"gsd-core/agents/gsd-plan-checker.md",
|
||||
"gsd-core/agents/gsd-planner.md",
|
||||
"gsd-core/agents/gsd-project-researcher.md",
|
||||
"gsd-core/agents/gsd-research-synthesizer.md",
|
||||
"gsd-core/agents/gsd-roadmapper.md",
|
||||
"gsd-core/agents/gsd-security-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-auditor.md",
|
||||
"gsd-core/agents/gsd-ui-checker.md",
|
||||
"gsd-core/agents/gsd-ui-researcher.md",
|
||||
"gsd-core/agents/gsd-user-profiler.md",
|
||||
"gsd-core/agents/gsd-verifier.md",
|
||||
"gsd-core/bin/check-latest-version.cjs",
|
||||
"gsd-core/bin/ensure-runtime-build.cjs",
|
||||
"gsd-core/bin/gsd-tools.cjs",
|
||||
@@ -120,6 +155,78 @@
|
||||
"gsd-core/bin/shared/model-catalog.json",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs",
|
||||
"gsd-core/commands/gsd/add-tests.md",
|
||||
"gsd-core/commands/gsd/ai-integration-phase.md",
|
||||
"gsd-core/commands/gsd/audit-fix.md",
|
||||
"gsd-core/commands/gsd/audit-milestone.md",
|
||||
"gsd-core/commands/gsd/audit-uat.md",
|
||||
"gsd-core/commands/gsd/autonomous.md",
|
||||
"gsd-core/commands/gsd/capture.md",
|
||||
"gsd-core/commands/gsd/cleanup.md",
|
||||
"gsd-core/commands/gsd/code-review.md",
|
||||
"gsd-core/commands/gsd/complete-milestone.md",
|
||||
"gsd-core/commands/gsd/config.md",
|
||||
"gsd-core/commands/gsd/debug.md",
|
||||
"gsd-core/commands/gsd/discuss-phase.md",
|
||||
"gsd-core/commands/gsd/docs-update.md",
|
||||
"gsd-core/commands/gsd/eval-review.md",
|
||||
"gsd-core/commands/gsd/execute-phase.md",
|
||||
"gsd-core/commands/gsd/explore.md",
|
||||
"gsd-core/commands/gsd/extract-learnings.md",
|
||||
"gsd-core/commands/gsd/fast.md",
|
||||
"gsd-core/commands/gsd/forensics.md",
|
||||
"gsd-core/commands/gsd/graphify.md",
|
||||
"gsd-core/commands/gsd/health.md",
|
||||
"gsd-core/commands/gsd/help.md",
|
||||
"gsd-core/commands/gsd/import.md",
|
||||
"gsd-core/commands/gsd/inbox.md",
|
||||
"gsd-core/commands/gsd/ingest-docs.md",
|
||||
"gsd-core/commands/gsd/manager.md",
|
||||
"gsd-core/commands/gsd/map-codebase.md",
|
||||
"gsd-core/commands/gsd/mempalace-capture.md",
|
||||
"gsd-core/commands/gsd/mempalace-recall.md",
|
||||
"gsd-core/commands/gsd/milestone-summary.md",
|
||||
"gsd-core/commands/gsd/mvp-phase.md",
|
||||
"gsd-core/commands/gsd/new-milestone.md",
|
||||
"gsd-core/commands/gsd/new-project.md",
|
||||
"gsd-core/commands/gsd/next.md",
|
||||
"gsd-core/commands/gsd/ns-context.md",
|
||||
"gsd-core/commands/gsd/ns-ideate.md",
|
||||
"gsd-core/commands/gsd/ns-manage.md",
|
||||
"gsd-core/commands/gsd/ns-project.md",
|
||||
"gsd-core/commands/gsd/ns-review.md",
|
||||
"gsd-core/commands/gsd/ns-workflow.md",
|
||||
"gsd-core/commands/gsd/onboard.md",
|
||||
"gsd-core/commands/gsd/pause-work.md",
|
||||
"gsd-core/commands/gsd/phase.md",
|
||||
"gsd-core/commands/gsd/plan-phase.md",
|
||||
"gsd-core/commands/gsd/plan-review-convergence.md",
|
||||
"gsd-core/commands/gsd/pr-branch.md",
|
||||
"gsd-core/commands/gsd/profile-user.md",
|
||||
"gsd-core/commands/gsd/progress.md",
|
||||
"gsd-core/commands/gsd/quick-batch.md",
|
||||
"gsd-core/commands/gsd/quick.md",
|
||||
"gsd-core/commands/gsd/resume-work.md",
|
||||
"gsd-core/commands/gsd/review-backlog.md",
|
||||
"gsd-core/commands/gsd/review.md",
|
||||
"gsd-core/commands/gsd/secure-phase.md",
|
||||
"gsd-core/commands/gsd/settings.md",
|
||||
"gsd-core/commands/gsd/ship.md",
|
||||
"gsd-core/commands/gsd/sketch.md",
|
||||
"gsd-core/commands/gsd/spec-phase.md",
|
||||
"gsd-core/commands/gsd/spike.md",
|
||||
"gsd-core/commands/gsd/stats.md",
|
||||
"gsd-core/commands/gsd/surface.md",
|
||||
"gsd-core/commands/gsd/thread.md",
|
||||
"gsd-core/commands/gsd/ui-phase.md",
|
||||
"gsd-core/commands/gsd/ui-review.md",
|
||||
"gsd-core/commands/gsd/ultraplan-phase.md",
|
||||
"gsd-core/commands/gsd/undo.md",
|
||||
"gsd-core/commands/gsd/update.md",
|
||||
"gsd-core/commands/gsd/validate-phase.md",
|
||||
"gsd-core/commands/gsd/verify-work.md",
|
||||
"gsd-core/commands/gsd/workspace.md",
|
||||
"gsd-core/commands/gsd/workstreams.md",
|
||||
"gsd-core/contexts/dev.md",
|
||||
"gsd-core/contexts/research.md",
|
||||
"gsd-core/contexts/review.md",
|
||||
|
||||
@@ -133,6 +133,7 @@ const { applySurface } = require('../gsd-core/bin/lib/surface.cjs');
|
||||
const { loadSkillsManifest, resolveProfile } = require('../gsd-core/bin/lib/install-profiles.cjs');
|
||||
const { resolveRuntimeArtifactLayout } = require('../gsd-core/bin/lib/runtime-artifact-layout.cjs');
|
||||
const { cleanup, sandboxHome } = require('./helpers.cjs');
|
||||
const { runMinimalInstall } = require('./helpers/install-shared.cjs');
|
||||
|
||||
const COMMANDS_GSD = path.join(ROOT, 'commands', 'gsd');
|
||||
|
||||
@@ -169,13 +170,14 @@ describe('#1575 — golden-parity: surface path matches install path for descrip
|
||||
|
||||
for (const runtime of DESCRIPTOR_RUNTIMES) {
|
||||
test(`${runtime}: surface agents byte-identical to install agents`, (t) => {
|
||||
const configDir = fs.mkdtempSync(path.join(os.tmpdir(), `gsd-1575-${runtime}-`));
|
||||
t.after(() => { try { cleanup(configDir); } catch { /* best-effort */ } });
|
||||
const installed = runMinimalInstall({ runtime, scope: 'global' });
|
||||
const { configDir, root } = installed;
|
||||
t.after(() => { try { cleanup(root); } catch { /* best-effort */ } });
|
||||
// #3738: antigravity's skills/agents kinds declare a global `home`
|
||||
// override resolved from os.homedir() — sandbox HOME to the configDir
|
||||
// override resolved from os.homedir() — sandbox HOME to the install root
|
||||
// (the #3712 marker real-home-guard needs) so the override resolves
|
||||
// inside the sandbox instead of the runner's real home.
|
||||
sandboxHome(t, configDir);
|
||||
sandboxHome(t, root);
|
||||
|
||||
// Step 1: install path writes agents
|
||||
installRuntimeArtifacts(runtime, configDir, 'global', parity1575Profile, resolveAttribution1575);
|
||||
@@ -224,8 +226,10 @@ describe('#1575 — golden-parity: surface path matches install path for descrip
|
||||
// is a no-op (it replaces existing lines, doesn't add new ones). But this test
|
||||
// proves the agentCtx threading is correct for both paths regardless.
|
||||
const attrResolver = () => 'Test Bot <test@example.com>';
|
||||
const configDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-1575-attr-'));
|
||||
t.after(() => { try { cleanup(configDir); } catch { /* best-effort */ } });
|
||||
const installed = runMinimalInstall({ runtime: 'cursor', scope: 'global' });
|
||||
const { configDir, root } = installed;
|
||||
t.after(() => { try { cleanup(root); } catch { /* best-effort */ } });
|
||||
sandboxHome(t, root);
|
||||
|
||||
installRuntimeArtifacts('cursor', configDir, 'global', parity1575Profile, attrResolver);
|
||||
|
||||
@@ -262,8 +266,9 @@ describe('#1575 — golden-parity: surface path matches install path for descrip
|
||||
|
||||
describe('#1575 — surface path: no prune data-loss over pre-existing legacy agents', () => {
|
||||
test('pre-existing gsd-* agents not in staged set are pruned; user agents preserved', (t) => {
|
||||
const configDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-1575-prune-'));
|
||||
t.after(() => { try { cleanup(configDir); } catch { /* best-effort */ } });
|
||||
const installed = runMinimalInstall({ runtime: 'copilot', scope: 'global' });
|
||||
const { configDir, root } = installed;
|
||||
t.after(() => { try { cleanup(root); } catch { /* best-effort */ } });
|
||||
|
||||
// Seed a pre-existing legacy .agent.md (simulating a prior install)
|
||||
const agentsDir = path.join(configDir, 'agents');
|
||||
|
||||
@@ -1173,7 +1173,16 @@ function sandboxHome(t, dir) {
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { runGsdTools, createTempDir, createTempProject, createTempGitProject, cleanup, tmpRootCandidates, readFileNormalized, readWorkflowCombined, parseFrontmatter, isUsageOutput, captureConsole, toPosixPath, absPlanningPath, runNpm, isolatedNpmEnv, withIsolatedProcessState, delay, waitFor, resetRuntimeWarningCaches, SESSION_ENV_KEYS, saveSessionEnv, restoreSessionEnv, clearSessionEnv, isolateWorkstreamEnv, restoreWorkstreamEnv, TOOLS_PATH, SESSION_IDENTITY_ENV_KEYS, scrubConfigLocationEnv, installSpawnEnv, installSpawnHome, sandboxHome, TEST_HOME_SANDBOX_MARKER, mockPartialWriteThenThrow, captureFdSync };
|
||||
function writePackageSourceMarkerFixture(configDir) {
|
||||
fs.mkdirSync(configDir, { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(configDir, '.gsd-source'),
|
||||
path.join(__dirname, '..', 'commands', 'gsd') + '\n',
|
||||
);
|
||||
return configDir;
|
||||
}
|
||||
|
||||
module.exports = { runGsdTools, createTempDir, createTempProject, createTempGitProject, cleanup, tmpRootCandidates, readFileNormalized, readWorkflowCombined, parseFrontmatter, isUsageOutput, captureConsole, toPosixPath, absPlanningPath, runNpm, isolatedNpmEnv, withIsolatedProcessState, delay, waitFor, resetRuntimeWarningCaches, SESSION_ENV_KEYS, saveSessionEnv, restoreSessionEnv, clearSessionEnv, isolateWorkstreamEnv, restoreWorkstreamEnv, TOOLS_PATH, SESSION_IDENTITY_ENV_KEYS, scrubConfigLocationEnv, installSpawnEnv, installSpawnHome, sandboxHome, writePackageSourceMarkerFixture, TEST_HOME_SANDBOX_MARKER, mockPartialWriteThenThrow, captureFdSync };
|
||||
|
||||
// Lazy, for the reason builtLib() is lazy: reading either of these is what
|
||||
// forces the built-lib require, so a test file that needs neither can still
|
||||
|
||||
@@ -274,6 +274,22 @@ const PROVENANCE_RULES = [
|
||||
pattern: /^(workflows|references|templates|contexts|bin)\/.+$/,
|
||||
sources: (m) => [`gsd-core/${m[0]}`],
|
||||
},
|
||||
{
|
||||
id: 'gsd-core-commands-corpus',
|
||||
kind: 'rewrite',
|
||||
roots: ['gsd-core'],
|
||||
pattern: /^commands\/gsd\/(.+)$/,
|
||||
sources: (m) => [`commands/gsd/${m[1]}`],
|
||||
transforms: [INSTALL_ENGINE_SRC, INSTALLER_SRC],
|
||||
},
|
||||
{
|
||||
id: 'gsd-core-agents-corpus',
|
||||
kind: 'rewrite',
|
||||
roots: ['gsd-core'],
|
||||
pattern: /^agents\/(.+)$/,
|
||||
sources: (m) => [`agents/${m[1]}`],
|
||||
transforms: [INSTALL_ENGINE_SRC, INSTALLER_SRC],
|
||||
},
|
||||
{
|
||||
id: 'scripts-verbatim',
|
||||
kind: 'identity',
|
||||
|
||||
@@ -182,6 +182,12 @@ describe('Hermes Agent: installRuntimeArtifacts', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-hermes-test-'));
|
||||
// Hermes consumes commands and agents from one source provider. Keep the
|
||||
// compatibility-marker fixture complete even when an assertion exercises
|
||||
// only its command-to-skill output.
|
||||
const agentsDir = path.join(tmpDir, 'src', 'agents');
|
||||
fs.mkdirSync(agentsDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(agentsDir, 'fixture-agent.md'), '# Fixture agent\n');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -944,7 +950,7 @@ describe('#2284 fail-closed role resolution', () => {
|
||||
|
||||
assert.throws(
|
||||
() => install(true, 'hermes'),
|
||||
/could not resolve|refusing to install/i,
|
||||
/could not resolve|refusing to install|source is unavailable or incomplete/i,
|
||||
'a real hermes install must fail closed, never silently install workflows with unverifiable role references',
|
||||
);
|
||||
});
|
||||
|
||||
@@ -37,6 +37,10 @@ const commandRoster = require('../gsd-core/bin/lib/command-roster.cjs');
|
||||
const {
|
||||
withInstallFs,
|
||||
} = require('../gsd-core/bin/lib/install-fs-adapter.cjs');
|
||||
const {
|
||||
findInstallSourceRoot,
|
||||
resolveRuntimeArtifactLayout,
|
||||
} = require('../gsd-core/bin/lib/runtime-artifact-layout.cjs');
|
||||
const {
|
||||
stageSkillsForRuntimeAsSkills,
|
||||
cleanupStagedSkills,
|
||||
@@ -155,6 +159,141 @@ describe('command-roster readGsdCommandNames — package-source read stays unrou
|
||||
});
|
||||
});
|
||||
|
||||
describe('runtime artifact source identity — destination probes stay routed', () => {
|
||||
test('#4132: installed provider admission streams hashes before reading corpus content', (t) => {
|
||||
const configDir = createTempDir('gsd-installed-provider-');
|
||||
t.after(() => cleanup(configDir));
|
||||
const installedCommands = path.join(configDir, 'gsd-core', 'commands', 'gsd');
|
||||
const installedAgents = path.join(configDir, 'gsd-core', 'agents');
|
||||
const commandPath = path.join(installedCommands, 'help.md');
|
||||
const agentPath = path.join(installedAgents, 'gsd-planner.md');
|
||||
const manifestPath = path.join(configDir, 'gsd-file-manifest.json');
|
||||
fs.mkdirSync(installedCommands, { recursive: true });
|
||||
fs.mkdirSync(installedAgents, { recursive: true });
|
||||
fs.writeFileSync(commandPath, '# installed command\n');
|
||||
fs.writeFileSync(agentPath, '# installed agent\n');
|
||||
fs.writeFileSync(manifestPath, JSON.stringify({ files: {
|
||||
'gsd-core/commands/gsd/help.md': crypto.createHash('sha256').update(fs.readFileSync(commandPath)).digest('hex'),
|
||||
'gsd-core/agents/gsd-planner.md': crypto.createHash('sha256').update(fs.readFileSync(agentPath)).digest('hex'),
|
||||
} }));
|
||||
|
||||
const corpusPaths = new Set([commandPath, agentPath].map((candidate) => path.resolve(candidate)));
|
||||
const hashingDescriptors = new Map();
|
||||
const streamedHashes = new Set();
|
||||
const hashedBeforeRead = new Set();
|
||||
const corpusReadsBeforeHash = [];
|
||||
const readCalls = [];
|
||||
const recordingFs = {
|
||||
...fs,
|
||||
readFileSync: (candidate, ...args) => {
|
||||
const resolved = path.resolve(String(candidate));
|
||||
readCalls.push(resolved);
|
||||
if (corpusPaths.has(resolved) && !hashedBeforeRead.has(resolved)) {
|
||||
corpusReadsBeforeHash.push(resolved);
|
||||
}
|
||||
return fs.readFileSync(candidate, ...args);
|
||||
},
|
||||
openSync: (candidate, ...args) => {
|
||||
const fd = fs.openSync(candidate, ...args);
|
||||
const resolved = path.resolve(String(candidate));
|
||||
if (corpusPaths.has(resolved)) hashingDescriptors.set(fd, resolved);
|
||||
return fd;
|
||||
},
|
||||
readSync: (fd, ...args) => {
|
||||
const resolved = hashingDescriptors.get(fd);
|
||||
if (resolved) streamedHashes.add(resolved);
|
||||
return fs.readSync(fd, ...args);
|
||||
},
|
||||
closeSync: (fd) => {
|
||||
fs.closeSync(fd);
|
||||
const resolved = hashingDescriptors.get(fd);
|
||||
if (resolved) hashedBeforeRead.add(resolved);
|
||||
},
|
||||
};
|
||||
|
||||
const layout = resolveRuntimeArtifactLayout('claude', configDir, 'global');
|
||||
let stagedSkills;
|
||||
let stagedAgents;
|
||||
t.after(() => {
|
||||
if (stagedSkills) cleanup(stagedSkills);
|
||||
if (stagedAgents) cleanup(stagedAgents);
|
||||
});
|
||||
withInstallFs(recordingFs, () => {
|
||||
stagedSkills = layout.kinds.find((kind) => kind.kind === 'skills').stage({ skills: '*', agents: '*' });
|
||||
stagedAgents = layout.kinds.find((kind) => kind.kind === 'agents').stage({ skills: '*', agents: '*' });
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(corpusReadsBeforeHash, [], 'installed corpus files must not be pre-read before manifest hashing');
|
||||
assert.deepStrictEqual(streamedHashes, corpusPaths, 'commands and agents hashes must stream through readSync');
|
||||
assert.deepStrictEqual(hashedBeforeRead, corpusPaths, 'commands and agents hashes must use the streaming fd path');
|
||||
assert.ok(readCalls.includes(path.resolve(manifestPath)), 'provider admission must still read the install manifest');
|
||||
assert.match(fs.readFileSync(path.join(stagedSkills, 'gsd-help', 'SKILL.md'), 'utf8'), /installed command/);
|
||||
assert.match(fs.readFileSync(path.join(stagedAgents, 'gsd-planner.md'), 'utf8'), /installed agent/);
|
||||
});
|
||||
|
||||
test('#4132: an installed-root alias is resolved through installFs without routing the package root', () => {
|
||||
const configDir = path.join(os.tmpdir(), `gsd-fake-config-${crypto.randomUUID()}`);
|
||||
const installedCommands = path.join(configDir, 'gsd-core', 'commands', 'gsd');
|
||||
const probes = [];
|
||||
const missing = (p) => {
|
||||
const error = new Error(`ENOENT: no such file or directory, '${p}'`);
|
||||
error.code = 'ENOENT';
|
||||
throw error;
|
||||
};
|
||||
const fakeFs = {
|
||||
existsSync: () => false,
|
||||
lstatSync: missing,
|
||||
realpathSync: (p) => {
|
||||
probes.push(path.normalize(String(p)));
|
||||
return path.normalize(String(p)) === path.normalize(installedCommands)
|
||||
? fs.realpathSync(REAL_COMMANDS_DIR)
|
||||
: path.normalize(String(p));
|
||||
},
|
||||
};
|
||||
|
||||
assert.throws(
|
||||
() => withInstallFs(fakeFs, () => findInstallSourceRoot(configDir)),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
assert.deepStrictEqual(
|
||||
probes,
|
||||
[path.normalize(installedCommands)],
|
||||
'installed destination identity must use installFs, while package-source identity stays on raw fs',
|
||||
);
|
||||
});
|
||||
|
||||
test('#4132: an unreadable physical root cannot prove a marker is independent', () => {
|
||||
const configDir = path.join(os.tmpdir(), `gsd-fake-config-${crypto.randomUUID()}`);
|
||||
const installedCommands = path.join(configDir, 'gsd-core', 'commands', 'gsd');
|
||||
const markerCommands = path.join(configDir, 'independent', 'commands', 'gsd');
|
||||
const fakeFs = createFakeFs([
|
||||
[configDir, { type: 'dir' }],
|
||||
[path.join(configDir, 'gsd-core'), { type: 'dir' }],
|
||||
[path.join(configDir, 'gsd-core', 'commands'), { type: 'dir' }],
|
||||
[installedCommands, { type: 'dir' }],
|
||||
[path.join(installedCommands, 'help.md'), { type: 'file', content: '# unverified installed command\n' }],
|
||||
[path.join(configDir, 'independent'), { type: 'dir' }],
|
||||
[path.join(configDir, 'independent', 'commands'), { type: 'dir' }],
|
||||
[markerCommands, { type: 'dir' }],
|
||||
[path.join(markerCommands, 'help.md'), { type: 'file', content: '# marker command\n' }],
|
||||
[path.join(configDir, '.gsd-source'), { type: 'file', content: markerCommands + '\n' }],
|
||||
]);
|
||||
fakeFs.realpathSync = (p) => {
|
||||
if ([installedCommands, markerCommands].includes(path.normalize(String(p)))) {
|
||||
const error = new Error(`EACCES: permission denied, realpath '${p}'`);
|
||||
error.code = 'EACCES';
|
||||
throw error;
|
||||
}
|
||||
return path.normalize(String(p));
|
||||
};
|
||||
|
||||
assert.throws(
|
||||
() => withInstallFs(fakeFs, () => findInstallSourceRoot(configDir)),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── (b) cleanupStagedSkills must not perform real IO on fake-staged dirs ──
|
||||
|
||||
describe('install-profiles cleanupStagedSkills — deferred cleanup does not leak past the restore', () => {
|
||||
|
||||
@@ -29,7 +29,7 @@ const os = require('node:os');
|
||||
const espree = require('espree');
|
||||
const { splitLines, joinLines } = require('../gsd-core/bin/lib/text-lines.cjs');
|
||||
|
||||
const { createTempDir, cleanup } = require('./helpers.cjs');
|
||||
const { createTempDir, cleanup, writePackageSourceMarkerFixture } = require('./helpers.cjs');
|
||||
const { runNode } = require('./helpers/process-seam.cjs');
|
||||
const { INSTALL_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
||||
const {
|
||||
@@ -172,6 +172,299 @@ describe('installRuntimeArtifacts — consumes Runtime Artifact Install Plan Mod
|
||||
});
|
||||
});
|
||||
|
||||
describe('installRuntimeArtifacts — durable Runtime Surface corpus (#4132)', () => {
|
||||
test('#4132: provisioning refuses a gsd-core ancestor symlink that escapes configDir', (t) => {
|
||||
const root = createTempDir('gsd-corpus-parent-symlink-');
|
||||
const configDir = path.join(root, 'config');
|
||||
const outside = path.join(root, 'outside');
|
||||
fs.mkdirSync(configDir);
|
||||
fs.mkdirSync(outside);
|
||||
t.after(() => cleanup(root));
|
||||
try {
|
||||
fs.symlinkSync(outside, path.join(configDir, 'gsd-core'), process.platform === 'win32' ? 'junction' : 'dir');
|
||||
} catch (error) {
|
||||
t.skip(`directory symlink creation unavailable: ${error.code || error.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
assert.throws(
|
||||
() => installRuntimeArtifacts('codex', configDir, 'global', RESOLVED_CORE),
|
||||
/symlink|refusing/i,
|
||||
);
|
||||
assert.equal(fs.existsSync(path.join(outside, 'commands')), false, 'commands must not escape configDir');
|
||||
assert.equal(fs.existsSync(path.join(outside, 'agents')), false, 'agents must not escape configDir');
|
||||
});
|
||||
|
||||
test('#4132: provisioning does not follow a compatibility-marker symlink outside configDir', (t) => {
|
||||
const root = createTempDir('gsd-corpus-marker-symlink-');
|
||||
const configDir = path.join(root, '.claude');
|
||||
const outsideMarker = path.join(root, 'outside-marker');
|
||||
const outsideCheckout = path.join(root, 'outside-checkout');
|
||||
fs.mkdirSync(configDir);
|
||||
fs.cpSync(path.join(__dirname, '..', 'commands'), path.join(outsideCheckout, 'commands'), { recursive: true });
|
||||
fs.cpSync(path.join(__dirname, '..', 'agents'), path.join(outsideCheckout, 'agents'), { recursive: true });
|
||||
fs.appendFileSync(path.join(outsideCheckout, 'commands', 'gsd', 'help.md'), '\nMARKER_SYMLINK_SOURCE\n');
|
||||
const outsideMarkerBytes = path.join(outsideCheckout, 'commands', 'gsd') + '\n';
|
||||
fs.writeFileSync(outsideMarker, outsideMarkerBytes);
|
||||
t.after(() => cleanup(root));
|
||||
try {
|
||||
fs.symlinkSync(outsideMarker, path.join(configDir, '.gsd-source'), 'file');
|
||||
} catch (error) {
|
||||
t.skip(`file symlink creation unavailable: ${error.code || error.message}`);
|
||||
return;
|
||||
}
|
||||
runMinimalInstall({ runtime: 'claude', scope: 'global', root });
|
||||
|
||||
assert.equal(
|
||||
fs.readFileSync(outsideMarker, 'utf8'),
|
||||
outsideMarkerBytes,
|
||||
'the compatibility marker write must remain confined to configDir',
|
||||
);
|
||||
assert.doesNotMatch(
|
||||
fs.readFileSync(path.join(configDir, 'skills', 'gsd-help', 'SKILL.md'), 'utf8'),
|
||||
/MARKER_SYMLINK_SOURCE/,
|
||||
'the installer must not read a source provider through a symlinked marker file',
|
||||
);
|
||||
});
|
||||
|
||||
test('global Codex owns the canonical commands and agents corpus', (t) => {
|
||||
const configDir = createTempDir('gsd-codex-surface-corpus-');
|
||||
t.after(() => cleanup(configDir));
|
||||
sandboxHome(t, configDir);
|
||||
|
||||
installRuntimeArtifacts('codex', configDir, 'global', RESOLVED_CORE);
|
||||
|
||||
assert.deepStrictEqual(
|
||||
snapshot2362Dir(path.join(configDir, 'gsd-core', 'commands', 'gsd')),
|
||||
snapshot2362Dir(path.join(__dirname, '..', 'commands', 'gsd')),
|
||||
'installed commands corpus must match the package source tree',
|
||||
);
|
||||
assert.deepStrictEqual(
|
||||
snapshot2362Dir(path.join(configDir, 'gsd-core', 'agents')),
|
||||
snapshot2362Dir(path.join(__dirname, '..', 'agents')),
|
||||
'installed agents corpus must match the package source tree',
|
||||
);
|
||||
});
|
||||
|
||||
test('agents-only and empty layouts derive corpus needs from layout kinds', (t) => {
|
||||
const windsurfDir = createTempDir('gsd-windsurf-surface-corpus-');
|
||||
const piDir = createTempDir('gsd-pi-surface-corpus-');
|
||||
const vscodeDir = createTempDir('gsd-vscode-surface-corpus-');
|
||||
t.after(() => { cleanup(windsurfDir); cleanup(piDir); cleanup(vscodeDir); });
|
||||
|
||||
installRuntimeArtifacts('windsurf', windsurfDir, 'global', RESOLVED_CORE);
|
||||
assert.ok(fs.existsSync(path.join(windsurfDir, 'gsd-core', 'agents')));
|
||||
assert.ok(!fs.existsSync(path.join(windsurfDir, 'gsd-core', 'commands', 'gsd')));
|
||||
|
||||
installRuntimeArtifacts('pi', piDir, 'global', RESOLVED_CORE);
|
||||
installRuntimeArtifacts('vscode', vscodeDir, 'global', RESOLVED_CORE);
|
||||
assert.ok(!fs.existsSync(path.join(piDir, 'gsd-core', 'commands')));
|
||||
assert.ok(!fs.existsSync(path.join(piDir, 'gsd-core', 'agents')));
|
||||
assert.ok(!fs.existsSync(path.join(vscodeDir, 'gsd-core', 'commands')));
|
||||
assert.ok(!fs.existsSync(path.join(vscodeDir, 'gsd-core', 'agents')));
|
||||
});
|
||||
|
||||
test('local Claude and Codex installs do not gain the global corpus', (t) => {
|
||||
const claudeDir = createTempDir('gsd-claude-local-no-corpus-');
|
||||
const codexDir = createTempDir('gsd-codex-local-no-corpus-');
|
||||
t.after(() => { cleanup(claudeDir); cleanup(codexDir); });
|
||||
|
||||
installRuntimeArtifacts('claude', claudeDir, 'local', RESOLVED_CORE);
|
||||
installRuntimeArtifacts('codex', codexDir, 'local', RESOLVED_CORE);
|
||||
for (const configDir of [claudeDir, codexDir]) {
|
||||
assert.ok(!fs.existsSync(path.join(configDir, 'gsd-core', 'commands')));
|
||||
assert.ok(!fs.existsSync(path.join(configDir, 'gsd-core', 'agents')));
|
||||
}
|
||||
});
|
||||
|
||||
test('refresh restores canonical bytes and removes only manifest-proven stale corpus files', (t) => {
|
||||
const configDir = createTempDir('gsd-corpus-refresh-');
|
||||
t.after(() => cleanup(configDir));
|
||||
sandboxHome(t, configDir);
|
||||
installRuntimeArtifacts('codex', configDir, 'global', RESOLVED_CORE);
|
||||
|
||||
const commandsDir = path.join(configDir, 'gsd-core', 'commands', 'gsd');
|
||||
const canonicalName = fs.readdirSync(commandsDir).find((name) => name.endsWith('.md'));
|
||||
assert.ok(canonicalName);
|
||||
fs.writeFileSync(path.join(commandsDir, canonicalName), '# corrupted\n');
|
||||
fs.writeFileSync(path.join(commandsDir, 'stale-owned.md'), '# stale\n');
|
||||
fs.writeFileSync(path.join(commandsDir, 'unknown-neighbour.md'), '# preserve\n');
|
||||
fs.writeFileSync(path.join(configDir, 'gsd-file-manifest.json'), JSON.stringify({
|
||||
files: { 'gsd-core/commands/gsd/stale-owned.md': '0'.repeat(64) },
|
||||
}));
|
||||
|
||||
installRuntimeArtifacts('codex', configDir, 'global', RESOLVED_CORE);
|
||||
assert.strictEqual(
|
||||
fs.readFileSync(path.join(commandsDir, canonicalName), 'utf8'),
|
||||
fs.readFileSync(path.join(__dirname, '..', 'commands', 'gsd', canonicalName), 'utf8'),
|
||||
);
|
||||
assert.ok(!fs.existsSync(path.join(commandsDir, 'stale-owned.md')));
|
||||
assert.strictEqual(fs.readFileSync(path.join(commandsDir, 'unknown-neighbour.md'), 'utf8'), '# preserve\n');
|
||||
});
|
||||
|
||||
test('a partial corpus copy failure is rejected until a later install repairs it', (t) => {
|
||||
const configDir = createTempDir('gsd-corpus-copy-failure-');
|
||||
t.after(() => cleanup(configDir));
|
||||
sandboxHome(t, configDir);
|
||||
const agentsDestination = path.join(configDir, 'gsd-core', 'agents');
|
||||
const originalCpSync = fs.cpSync;
|
||||
t.mock.method(fs, 'cpSync', (source, destination, options) => {
|
||||
if (destination === agentsDestination) {
|
||||
fs.mkdirSync(destination, { recursive: true });
|
||||
fs.writeFileSync(path.join(destination, 'gsd-planner.md'), '# partial agent\n');
|
||||
throw new Error('injected corpus copy failure');
|
||||
}
|
||||
return originalCpSync(source, destination, options);
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() => installRuntimeArtifacts('codex', configDir, 'global', RESOLVED_CORE),
|
||||
/injected corpus copy failure/,
|
||||
);
|
||||
const incompleteLayout = resolveRuntimeArtifactLayout('codex', configDir, 'global');
|
||||
assert.throws(
|
||||
() => incompleteLayout.kinds.find((kind) => kind.kind === 'skills').stage(RESOLVED_CORE),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
|
||||
t.mock.restoreAll();
|
||||
installRuntimeArtifacts('codex', configDir, 'global', RESOLVED_CORE);
|
||||
assert.deepStrictEqual(
|
||||
snapshot2362Dir(agentsDestination),
|
||||
snapshot2362Dir(path.join(__dirname, '..', 'agents')),
|
||||
'a later install must heal the partial agents corpus',
|
||||
);
|
||||
});
|
||||
|
||||
test('an unreadable prior manifest preserves unproven neighbours while refreshing canonical bytes', (t) => {
|
||||
const configDir = createTempDir('gsd-corpus-manifest-read-failure-');
|
||||
t.after(() => cleanup(configDir));
|
||||
sandboxHome(t, configDir);
|
||||
const commandsDir = path.join(configDir, 'gsd-core', 'commands', 'gsd');
|
||||
fs.mkdirSync(commandsDir, { recursive: true });
|
||||
const canonicalName = fs.readdirSync(path.join(__dirname, '..', 'commands', 'gsd'))
|
||||
.find((name) => name.endsWith('.md'));
|
||||
assert.ok(canonicalName);
|
||||
fs.writeFileSync(path.join(commandsDir, canonicalName), '# corrupted\n');
|
||||
fs.writeFileSync(path.join(commandsDir, 'unproven-neighbour.md'), '# preserve\n');
|
||||
const manifestPath = path.join(configDir, 'gsd-file-manifest.json');
|
||||
fs.writeFileSync(manifestPath, JSON.stringify({ files: {
|
||||
'gsd-core/commands/gsd/unproven-neighbour.md': '0'.repeat(64),
|
||||
} }));
|
||||
|
||||
const originalReadFileSync = fs.readFileSync;
|
||||
t.mock.method(fs, 'readFileSync', (filePath, ...args) => {
|
||||
if (filePath === manifestPath) throw new Error('injected manifest read failure');
|
||||
return originalReadFileSync(filePath, ...args);
|
||||
});
|
||||
|
||||
installRuntimeArtifacts('codex', configDir, 'global', RESOLVED_CORE);
|
||||
assert.equal(
|
||||
fs.readFileSync(path.join(commandsDir, canonicalName), 'utf8'),
|
||||
fs.readFileSync(path.join(__dirname, '..', 'commands', 'gsd', canonicalName), 'utf8'),
|
||||
);
|
||||
assert.equal(
|
||||
fs.readFileSync(path.join(commandsDir, 'unproven-neighbour.md'), 'utf8'),
|
||||
'# preserve\n',
|
||||
'an unreadable manifest provides no ownership proof for deletion',
|
||||
);
|
||||
});
|
||||
|
||||
test('a stale corpus removal failure leaves a resolver-rejected corpus', (t) => {
|
||||
const configDir = createTempDir('gsd-corpus-remove-failure-');
|
||||
t.after(() => cleanup(configDir));
|
||||
sandboxHome(t, configDir);
|
||||
const commandsDir = path.join(configDir, 'gsd-core', 'commands', 'gsd');
|
||||
const agentsDir = path.join(configDir, 'gsd-core', 'agents');
|
||||
fs.mkdirSync(commandsDir, { recursive: true });
|
||||
fs.mkdirSync(agentsDir, { recursive: true });
|
||||
const stalePath = path.join(commandsDir, 'removed-by-4132-test.md');
|
||||
fs.writeFileSync(stalePath, '# stale\n');
|
||||
fs.writeFileSync(path.join(agentsDir, 'gsd-planner.md'), '# stale agent\n');
|
||||
const manifestPath = path.join(configDir, 'gsd-file-manifest.json');
|
||||
const manifestBytes = JSON.stringify({ files: {
|
||||
'gsd-core/commands/gsd/removed-by-4132-test.md': '0'.repeat(64),
|
||||
'gsd-core/agents/gsd-planner.md': '0'.repeat(64),
|
||||
} });
|
||||
fs.writeFileSync(manifestPath, manifestBytes);
|
||||
|
||||
const originalRmSync = fs.rmSync;
|
||||
t.mock.method(fs, 'rmSync', (target, options) => {
|
||||
if (target === stalePath) throw new Error('injected stale corpus removal failure');
|
||||
// eslint-disable-next-line local/no-raw-rmsync-in-tests -- delegate non-target production writes; fixture cleanup still uses cleanup().
|
||||
return originalRmSync(target, options);
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() => installRuntimeArtifacts('codex', configDir, 'global', RESOLVED_CORE),
|
||||
/injected stale corpus removal failure/,
|
||||
);
|
||||
assert.equal(fs.readFileSync(manifestPath, 'utf8'), manifestBytes, 'failed provisioning must not claim a new manifest');
|
||||
const incompleteLayout = resolveRuntimeArtifactLayout('codex', configDir, 'global');
|
||||
assert.throws(
|
||||
() => incompleteLayout.kinds.find((kind) => kind.kind === 'skills').stage(RESOLVED_CORE),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
});
|
||||
|
||||
test('an empty-parent prune failure leaves a resolver-rejected corpus', (t) => {
|
||||
const configDir = createTempDir('gsd-corpus-prune-failure-');
|
||||
t.after(() => cleanup(configDir));
|
||||
sandboxHome(t, configDir);
|
||||
const commandsDir = path.join(configDir, 'gsd-core', 'commands', 'gsd');
|
||||
const agentsDir = path.join(configDir, 'gsd-core', 'agents');
|
||||
const staleParent = path.join(commandsDir, 'retired');
|
||||
const stalePath = path.join(staleParent, 'removed-by-4132-test.md');
|
||||
fs.mkdirSync(staleParent, { recursive: true });
|
||||
fs.mkdirSync(agentsDir, { recursive: true });
|
||||
fs.writeFileSync(stalePath, '# stale\n');
|
||||
fs.writeFileSync(path.join(agentsDir, 'gsd-planner.md'), '# stale agent\n');
|
||||
const manifestPath = path.join(configDir, 'gsd-file-manifest.json');
|
||||
const manifestBytes = JSON.stringify({ files: {
|
||||
'gsd-core/commands/gsd/retired/removed-by-4132-test.md': '0'.repeat(64),
|
||||
'gsd-core/agents/gsd-planner.md': '0'.repeat(64),
|
||||
} });
|
||||
fs.writeFileSync(manifestPath, manifestBytes);
|
||||
|
||||
const originalRmdirSync = fs.rmdirSync;
|
||||
t.mock.method(fs, 'rmdirSync', (target, options) => {
|
||||
if (target === staleParent) throw new Error('injected corpus parent prune failure');
|
||||
return originalRmdirSync(target, options);
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() => installRuntimeArtifacts('codex', configDir, 'global', RESOLVED_CORE),
|
||||
/injected corpus parent prune failure/,
|
||||
);
|
||||
assert.equal(fs.existsSync(stalePath), false, 'owned stale file was removed before parent pruning failed');
|
||||
assert.equal(fs.existsSync(staleParent), true, 'failed empty parent removal must leave the directory in place');
|
||||
assert.equal(fs.readFileSync(manifestPath, 'utf8'), manifestBytes, 'failed provisioning must not claim a new manifest');
|
||||
const incompleteLayout = resolveRuntimeArtifactLayout('codex', configDir, 'global');
|
||||
assert.throws(
|
||||
() => incompleteLayout.kinds.find((kind) => kind.kind === 'skills').stage(RESOLVED_CORE),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
});
|
||||
|
||||
for (const runtime of ['codex', 'claude']) {
|
||||
test(`full global ${runtime} manifest covers every installed corpus file with its hash`, (t) => {
|
||||
const installed = runMinimalInstall({ runtime, scope: 'global' });
|
||||
t.after(() => cleanup(installed.root));
|
||||
const corpusRoots = [
|
||||
['gsd-core/commands/gsd/', path.join(installed.configDir, 'gsd-core', 'commands', 'gsd')],
|
||||
['gsd-core/agents/', path.join(installed.configDir, 'gsd-core', 'agents')],
|
||||
];
|
||||
for (const [prefix, root] of corpusRoots) {
|
||||
for (const file of walk(root)) {
|
||||
const key = prefix + path.relative(root, file).replace(/\\/g, '/');
|
||||
const hash = crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex');
|
||||
assert.strictEqual(installed.manifest.files[key], hash, `${key} must be manifest-owned with the installed hash`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const SKILLS_RUNTIMES_LAYOUT = [
|
||||
'claude', 'cursor', 'codex', 'copilot', 'antigravity',
|
||||
'augment', 'trae', 'qwen', 'kimi', 'codebuddy',
|
||||
@@ -415,6 +708,7 @@ describe('installOpencodeFamilySkills — emits skills/<name>/SKILL.md (#784)',
|
||||
test(`${runtime}: writes gsd-help/SKILL.md with name + description`, (t) => {
|
||||
const configDir = createTempDir(`gsd-ocs-${runtime}-`);
|
||||
t.after(() => cleanup(configDir));
|
||||
writePackageSourceMarkerFixture(configDir);
|
||||
|
||||
const raw = stageRawCommands(runtime, configDir);
|
||||
const count = installOpencodeFamilySkills(runtime, configDir, raw, `${configDir}/`);
|
||||
@@ -431,6 +725,7 @@ describe('installOpencodeFamilySkills — emits skills/<name>/SKILL.md (#784)',
|
||||
test(`${runtime}: rewrites body paths to the actual install target (#784 path fix)`, (t) => {
|
||||
const configDir = createTempDir(`gsd-ocp-${runtime}-`);
|
||||
t.after(() => cleanup(configDir));
|
||||
writePackageSourceMarkerFixture(configDir);
|
||||
|
||||
// Simulate a custom/local install: pathPrefix points at configDir, NOT the
|
||||
// runtime's default global config dir. Body refs must use pathPrefix.
|
||||
@@ -461,6 +756,7 @@ describe('installOpencodeFamilySkills — emits skills/<name>/SKILL.md (#784)',
|
||||
test(`${runtime}: preserves user-owned gsd-dev-preferences across reinstall (#784)`, (t) => {
|
||||
const configDir = createTempDir(`gsd-ocd-${runtime}-`);
|
||||
t.after(() => cleanup(configDir));
|
||||
writePackageSourceMarkerFixture(configDir);
|
||||
|
||||
const userSkill = path.join(configDir, 'skills', 'gsd-dev-preferences');
|
||||
fs.mkdirSync(userSkill, { recursive: true });
|
||||
@@ -2656,6 +2952,7 @@ describe('fix-2644 — Cursor has one menu entry per GSD workflow', () => {
|
||||
version: '1.8.0', timestamp: '2026-07-28T00:00:00.000Z', mode: 'core',
|
||||
files: { 'commands/gsd-help.md': crypto.createHash('sha256').update(content).digest('hex') },
|
||||
}));
|
||||
writePackageSourceMarkerFixture(configDir);
|
||||
|
||||
const layout = resolveRuntimeArtifactLayout('cursor', configDir, 'global');
|
||||
applySurface(configDir, layout, MANIFEST);
|
||||
@@ -5582,7 +5879,13 @@ const {
|
||||
*/
|
||||
function writeMinimalSourceTree(baseDir, stems) {
|
||||
const srcDir = path.join(baseDir, 'src', 'commands', 'gsd');
|
||||
const agentsDir = path.join(baseDir, 'src', 'agents');
|
||||
fs.mkdirSync(srcDir, { recursive: true });
|
||||
fs.mkdirSync(agentsDir, { recursive: true });
|
||||
// Hermes resolves one complete provider for its skills+agents layout. Keep
|
||||
// this legacy-marker fixture complete so it exercises marker compatibility
|
||||
// without relying on forbidden per-kind provider mixing (#4132).
|
||||
fs.writeFileSync(path.join(agentsDir, 'gsd-test-agent.md'), '# test agent\n');
|
||||
for (const stem of stems) {
|
||||
fs.writeFileSync(path.join(srcDir, `${stem}.md`), [
|
||||
'---',
|
||||
@@ -7583,6 +7886,11 @@ describe('#3719: real global Claude install — agents/*.md @-refs must resolve
|
||||
const failures = [];
|
||||
for (const file of walk(rootDir)) {
|
||||
if (!file.endsWith('.md')) continue;
|
||||
const relative = path.relative(claudeGlobal.configDir, file).replace(/\\/g, '/');
|
||||
// The installation-owned Runtime Surface corpus is raw package input,
|
||||
// not an emitted runtime artifact. It must remain byte-identical to the
|
||||
// package and is validated separately by the corpus parity matrix.
|
||||
if (relative.startsWith('gsd-core/commands/gsd/') || relative.startsWith('gsd-core/agents/')) continue;
|
||||
const content = fs.readFileSync(file, 'utf8');
|
||||
for (const line of splitLines(content)) {
|
||||
if (/@\$HOME\//.test(line.replace(INLINE_CODE_SPAN_RE, ''))) failures.push({ file, line });
|
||||
|
||||
@@ -738,6 +738,13 @@ describe('#3544: spawned installer — gsd-core/ spec tree @-refs resolve on til
|
||||
const walk = (dir) => {
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
const full = path.join(dir, entry.name);
|
||||
const rel = path.relative(rootDir, full);
|
||||
const topLevel = rel.split(path.sep)[0];
|
||||
// The durable Runtime Surface corpus is intentionally raw canonical
|
||||
// input, not an emitted/runtime-rewritten spec tree. Its paths are
|
||||
// validated when staged, so exclude only these two known corpus roots
|
||||
// from this legacy emitted-content oracle.
|
||||
if (topLevel === 'commands' || topLevel === 'agents') continue;
|
||||
if (entry.isDirectory()) walk(full);
|
||||
else if (entry.name.endsWith('.md')) {
|
||||
const content = fs.readFileSync(full, 'utf8');
|
||||
|
||||
@@ -136,6 +136,12 @@ describe('Qwen Code: installRuntimeArtifacts', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-qwen-test-'));
|
||||
// Qwen's global layout consumes commands and agents from one provider.
|
||||
// Keep this legacy-marker fixture complete even though these assertions
|
||||
// exercise only the command-to-skill half of the install.
|
||||
const agentsDir = path.join(tmpDir, 'src', 'agents');
|
||||
fs.mkdirSync(agentsDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(agentsDir, 'fixture-agent.md'), '# Fixture agent\n');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -11,6 +11,8 @@ const { describe, test, before, after } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const crypto = require('node:crypto');
|
||||
const { spawnSync } = require('node:child_process');
|
||||
|
||||
const { cleanup, createTempDir, runNpm, isolatedNpmEnv } = require('./helpers.cjs');
|
||||
const { SMOKE, runSmoke, CHILD_TIMEOUT_MS } = require('../scripts/release-tarball-smoke.cjs');
|
||||
@@ -21,6 +23,31 @@ const smokeMsg = (label, result) =>
|
||||
const PKG_PATH = path.join(__dirname, '..', 'package.json');
|
||||
const pkg = JSON.parse(fs.readFileSync(PKG_PATH, 'utf-8'));
|
||||
|
||||
function installedPackageRoot(prefix) {
|
||||
const parts = pkg.name.split('/');
|
||||
const posix = path.join(prefix, 'lib', 'node_modules', ...parts);
|
||||
const windows = path.join(prefix, 'node_modules', ...parts);
|
||||
return fs.existsSync(posix) ? posix : windows;
|
||||
}
|
||||
|
||||
function hashTree(root) {
|
||||
const result = new Map();
|
||||
const visit = (dir) => {
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
const absolute = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) visit(absolute);
|
||||
else if (entry.isFile()) {
|
||||
result.set(
|
||||
path.relative(root, absolute).replace(/\\/g, '/'),
|
||||
crypto.createHash('sha256').update(fs.readFileSync(absolute)).digest('hex'),
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
visit(root);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ─── runSmoke install timeout must clear a slow-host cold install (#2335) ────
|
||||
// Regression: runSmoke()'s internal `npm install -g` used CHILD_TIMEOUT_MS,
|
||||
// which was 120 s on non-Windows while before()'s pack+install used 600 s. A
|
||||
@@ -207,6 +234,208 @@ describe('release-tarball-smoke', () => {
|
||||
smokeMsg('E', result),
|
||||
);
|
||||
});
|
||||
|
||||
test('F: packed package carries the complete canonical Runtime Surface corpus', () => {
|
||||
const packageRoot = installedPackageRoot(installPrefix);
|
||||
assert.deepStrictEqual(
|
||||
hashTree(path.join(packageRoot, 'commands', 'gsd')),
|
||||
hashTree(path.join(__dirname, '..', 'commands', 'gsd')),
|
||||
);
|
||||
assert.deepStrictEqual(
|
||||
hashTree(path.join(packageRoot, 'agents')),
|
||||
hashTree(path.join(__dirname, '..', 'agents')),
|
||||
);
|
||||
});
|
||||
|
||||
test('G: deployed Codex and Claude modules materially change a surface after package source is unreachable', (t) => {
|
||||
const runtimeRoot = createTempDir('gsd-smoke-offline-runtime-');
|
||||
const packageRoot = installedPackageRoot(installPrefix);
|
||||
const hiddenPackageRoot = `${packageRoot}.offline-${process.pid}`;
|
||||
t.after(() => {
|
||||
if (fs.existsSync(hiddenPackageRoot) && !fs.existsSync(packageRoot)) fs.renameSync(hiddenPackageRoot, packageRoot);
|
||||
cleanup(runtimeRoot);
|
||||
});
|
||||
const installs = [];
|
||||
for (const runtime of ['codex', 'claude']) {
|
||||
const configDir = path.join(runtimeRoot, `.${runtime}`);
|
||||
const result = spawnSync(process.execPath, [
|
||||
path.join(packageRoot, 'bin', 'install.js'),
|
||||
`--${runtime}`,
|
||||
'--global',
|
||||
'--config-dir',
|
||||
configDir,
|
||||
], {
|
||||
cwd: runtimeRoot,
|
||||
env: {
|
||||
...process.env,
|
||||
...isolatedNpmEnv(),
|
||||
HOME: runtimeRoot,
|
||||
USERPROFILE: runtimeRoot,
|
||||
GSD_TEST_MODE: '',
|
||||
NO_UPDATE_NOTIFIER: '1',
|
||||
npm_config_update_notifier: 'false',
|
||||
},
|
||||
encoding: 'utf8',
|
||||
timeout: CHILD_TIMEOUT_MS,
|
||||
});
|
||||
assert.equal(result.status, 0, `${runtime} packed install failed:\n${result.stdout}\n${result.stderr}`);
|
||||
installs.push({ runtime, configDir });
|
||||
}
|
||||
|
||||
// Synthetic untouched 1.12-style deployed tree: converted outputs and a
|
||||
// hash manifest exist, but the raw corpus/marker do not. It must not use
|
||||
// those outputs as source when the executing package disappears.
|
||||
const legacyConfigDir = path.join(runtimeRoot, '.legacy-codex');
|
||||
fs.cpSync(installs.find((entry) => entry.runtime === 'codex').configDir, legacyConfigDir, { recursive: true });
|
||||
cleanup(path.join(legacyConfigDir, 'gsd-core', 'commands'));
|
||||
cleanup(path.join(legacyConfigDir, 'gsd-core', 'agents'));
|
||||
const legacyMarker = path.join(legacyConfigDir, '.gsd-source');
|
||||
if (fs.existsSync(legacyMarker)) fs.unlinkSync(legacyMarker);
|
||||
|
||||
// S04: upgrade a synthetic source-less legacy tree while the fixed
|
||||
// package is available. Preserve its exact committed selection and an
|
||||
// unrelated file, converge artifacts to that selection, and later prove
|
||||
// an offline expansion works from the provisioned corpus alone.
|
||||
const upgradedHome = path.join(runtimeRoot, 'legacy-codex-upgrade-home');
|
||||
const upgradeCwd = path.join(runtimeRoot, 'legacy-codex-upgrade-worktree');
|
||||
const upgradedConfigDir = path.join(upgradedHome, '.codex');
|
||||
fs.mkdirSync(upgradeCwd, { recursive: true });
|
||||
fs.cpSync(installs.find((entry) => entry.runtime === 'codex').configDir, upgradedConfigDir, { recursive: true });
|
||||
fs.cpSync(path.join(runtimeRoot, '.agents', 'skills'), path.join(upgradedHome, '.agents', 'skills'), { recursive: true });
|
||||
fs.mkdirSync(path.join(upgradedHome, '.agents', 'skills', 'user-owned-skill'), { recursive: true });
|
||||
fs.writeFileSync(path.join(upgradedHome, '.agents', 'skills', 'user-owned-skill', 'SKILL.md'), '# preserve me\n');
|
||||
cleanup(path.join(upgradedConfigDir, 'gsd-core', 'commands'));
|
||||
cleanup(path.join(upgradedConfigDir, 'gsd-core', 'agents'));
|
||||
const upgradedMarker = path.join(upgradedConfigDir, '.gsd-source');
|
||||
if (fs.existsSync(upgradedMarker)) fs.unlinkSync(upgradedMarker);
|
||||
const selectedState = JSON.stringify({ baseProfile: 'core', disabledClusters: [], explicitAdds: [], explicitRemoves: [] }, null, 2) + '\n';
|
||||
const priorGates = JSON.stringify({ workflow: { code_review: false, research: true } }, null, 2) + '\n';
|
||||
fs.writeFileSync(path.join(upgradedConfigDir, '.gsd-surface.json'), selectedState);
|
||||
fs.writeFileSync(path.join(upgradedConfigDir, 'user-owned.txt'), 'preserve me\n');
|
||||
fs.mkdirSync(path.join(upgradeCwd, '.planning'), { recursive: true });
|
||||
fs.writeFileSync(path.join(upgradeCwd, '.planning', 'config.json'), priorGates);
|
||||
const upgradeResult = spawnSync(process.execPath, [
|
||||
path.join(packageRoot, 'bin', 'install.js'),
|
||||
'--codex',
|
||||
'--global',
|
||||
'--config-dir',
|
||||
upgradedConfigDir,
|
||||
], {
|
||||
cwd: upgradeCwd,
|
||||
env: {
|
||||
...process.env,
|
||||
...isolatedNpmEnv(),
|
||||
HOME: upgradedHome,
|
||||
USERPROFILE: upgradedHome,
|
||||
GSD_TEST_MODE: '',
|
||||
NO_UPDATE_NOTIFIER: '1',
|
||||
npm_config_update_notifier: 'false',
|
||||
},
|
||||
encoding: 'utf8',
|
||||
timeout: CHILD_TIMEOUT_MS,
|
||||
});
|
||||
assert.equal(upgradeResult.status, 0, `legacy upgrade failed:\n${upgradeResult.stdout}\n${upgradeResult.stderr}`);
|
||||
assert.equal(fs.readFileSync(path.join(upgradedConfigDir, '.gsd-surface.json'), 'utf8'), selectedState);
|
||||
assert.equal(fs.readFileSync(path.join(upgradedConfigDir, 'user-owned.txt'), 'utf8'), 'preserve me\n');
|
||||
assert.equal(fs.readFileSync(path.join(upgradeCwd, '.planning', 'config.json'), 'utf8'), priorGates);
|
||||
assert.deepStrictEqual(
|
||||
hashTree(path.join(upgradedConfigDir, 'gsd-core', 'commands', 'gsd')),
|
||||
hashTree(path.join(packageRoot, 'commands', 'gsd')),
|
||||
);
|
||||
assert.deepStrictEqual(
|
||||
hashTree(path.join(upgradedConfigDir, 'gsd-core', 'agents')),
|
||||
hashTree(path.join(packageRoot, 'agents')),
|
||||
);
|
||||
const upgradedSkillRoot = path.join(upgradedHome, '.agents', 'skills');
|
||||
const upgradedSkillCount = fs.readdirSync(upgradedSkillRoot).filter((name) => name.startsWith('gsd-')).length;
|
||||
assert.ok(upgradedSkillCount > 0 && upgradedSkillCount < 71, `upgrade must converge the selected core surface, got ${upgradedSkillCount}`);
|
||||
assert.equal(fs.readFileSync(path.join(upgradedSkillRoot, 'user-owned-skill', 'SKILL.md'), 'utf8'), '# preserve me\n');
|
||||
|
||||
fs.renameSync(packageRoot, hiddenPackageRoot);
|
||||
|
||||
const upgradedOfflineScript = [
|
||||
"const fs=require('node:fs'),path=require('node:path');",
|
||||
`const configDir=${JSON.stringify(upgradedConfigDir)};`,
|
||||
"const lib=path.join(configDir,'gsd-core','bin','lib');",
|
||||
"const surface=require(path.join(lib,'surface.cjs'));",
|
||||
"const layoutModule=require(path.join(lib,'runtime-artifact-layout.cjs'));",
|
||||
"const profiles=require(path.join(lib,'install-profiles.cjs'));",
|
||||
"const clusters=require(path.join(lib,'clusters.cjs'));",
|
||||
"const manifest=profiles.loadSkillsManifest(path.join(configDir,'gsd-core','commands','gsd'));",
|
||||
"const layout=layoutModule.resolveRuntimeArtifactLayout('codex',configDir,'global');",
|
||||
"const skillKind=layout.kinds.find(kind=>kind.kind==='skills');",
|
||||
"const skillRoot=path.join(skillKind.home||configDir,skillKind.destSubpath);",
|
||||
"const before=fs.readdirSync(skillRoot).filter(n=>n.startsWith('gsd-')).length;",
|
||||
"surface.applySurface(configDir,layout,manifest,clusters.CLUSTERS,undefined,{surfaceState:{baseProfile:'full',disabledClusters:[],explicitAdds:[],explicitRemoves:[]}});",
|
||||
"const after=fs.readdirSync(skillRoot).filter(n=>n.startsWith('gsd-')).length;",
|
||||
"if(!(after>before))throw new Error(`offline upgraded expansion failed: ${before} -> ${after}`);",
|
||||
].join('');
|
||||
const upgradedOfflineResult = spawnSync(process.execPath, ['-e', upgradedOfflineScript], {
|
||||
cwd: runtimeRoot,
|
||||
env: { ...process.env, HOME: upgradedHome, USERPROFILE: upgradedHome, GSD_TEST_MODE: '' },
|
||||
encoding: 'utf8',
|
||||
timeout: CHILD_TIMEOUT_MS,
|
||||
});
|
||||
assert.equal(upgradedOfflineResult.status, 0, `upgraded offline surface failed:\n${upgradedOfflineResult.stdout}\n${upgradedOfflineResult.stderr}`);
|
||||
|
||||
const legacyChildScript = [
|
||||
"const fs=require('node:fs'),path=require('node:path');",
|
||||
`const configDir=${JSON.stringify(legacyConfigDir)};`,
|
||||
"const lib=path.join(configDir,'gsd-core','bin','lib');",
|
||||
"const surface=require(path.join(lib,'surface.cjs'));",
|
||||
"const layoutModule=require(path.join(lib,'runtime-artifact-layout.cjs'));",
|
||||
"const profiles=require(path.join(lib,'install-profiles.cjs'));",
|
||||
"const clusters=require(path.join(lib,'clusters.cjs'));",
|
||||
"const surfacePath=path.join(configDir,'.gsd-surface.json');",
|
||||
"const agentPath=path.join(configDir,'agents','gsd-planner.md');",
|
||||
"const beforeSurface=fs.existsSync(surfacePath)?fs.readFileSync(surfacePath):null;",
|
||||
"const beforeAgent=fs.readFileSync(agentPath);",
|
||||
"const layout=layoutModule.resolveRuntimeArtifactLayout('codex',configDir,'global');",
|
||||
"let error=null;try{surface.applySurface(configDir,layout,new Map(),clusters.CLUSTERS,undefined,{surfaceState:{baseProfile:'core',disabledClusters:[],explicitAdds:[],explicitRemoves:[]}})}catch(value){error=value}",
|
||||
"if(!error||!/install or upgrade gsd-core/.test(error.message))throw new Error(`expected actionable source failure, got ${error&&error.message}`);",
|
||||
"const afterSurface=fs.existsSync(surfacePath)?fs.readFileSync(surfacePath):null;",
|
||||
"if(!Buffer.isBuffer(beforeAgent)||!beforeAgent.equals(fs.readFileSync(agentPath)))throw new Error('legacy output changed');",
|
||||
"if(beforeSurface===null?afterSurface!==null:!beforeSurface.equals(afterSurface))throw new Error('legacy surface state changed');",
|
||||
].join('');
|
||||
const legacyResult = spawnSync(process.execPath, ['-e', legacyChildScript], {
|
||||
cwd: runtimeRoot,
|
||||
env: { ...process.env, HOME: runtimeRoot, USERPROFILE: runtimeRoot, GSD_TEST_MODE: '' },
|
||||
encoding: 'utf8',
|
||||
timeout: CHILD_TIMEOUT_MS,
|
||||
});
|
||||
assert.equal(legacyResult.status, 0, `legacy source-less refusal failed:\n${legacyResult.stdout}\n${legacyResult.stderr}`);
|
||||
|
||||
for (const { runtime, configDir } of installs) {
|
||||
const childScript = [
|
||||
"const path=require('node:path');",
|
||||
`const configDir=${JSON.stringify(configDir)};`,
|
||||
`const runtime=${JSON.stringify(runtime)};`,
|
||||
"const lib=path.join(configDir,'gsd-core','bin','lib');",
|
||||
"const surface=require(path.join(lib,'surface.cjs'));",
|
||||
"const layoutModule=require(path.join(lib,'runtime-artifact-layout.cjs'));",
|
||||
"const profiles=require(path.join(lib,'install-profiles.cjs'));",
|
||||
"const clusters=require(path.join(lib,'clusters.cjs'));",
|
||||
"const corpus=path.join(configDir,'gsd-core','commands','gsd');",
|
||||
"const manifest=profiles.loadSkillsManifest(corpus);",
|
||||
"const layout=layoutModule.resolveRuntimeArtifactLayout(runtime,configDir,'global');",
|
||||
"const before=layout.kinds.map(k=>{const root=path.join(k.home||configDir,k.destSubpath);try{return require('node:fs').readdirSync(root).length}catch{return 0}}).reduce((a,b)=>a+b,0);",
|
||||
"const state={baseProfile:'core',disabledClusters:[],explicitAdds:[],explicitRemoves:[]};",
|
||||
"surface.applySurface(configDir,layout,manifest,clusters.CLUSTERS,undefined,{surfaceState:state});",
|
||||
"const after=layout.kinds.map(k=>{const root=path.join(k.home||configDir,k.destSubpath);try{return require('node:fs').readdirSync(root).length}catch{return 0}}).reduce((a,b)=>a+b,0);",
|
||||
"if(!(after>0&&after<before))throw new Error(`surface did not materially shrink: ${before} -> ${after}`);",
|
||||
"process.stdout.write(JSON.stringify({before,after}));",
|
||||
].join('');
|
||||
const result = spawnSync(process.execPath, ['-e', childScript], {
|
||||
cwd: runtimeRoot,
|
||||
env: { ...process.env, HOME: runtimeRoot, USERPROFILE: runtimeRoot, GSD_TEST_MODE: '' },
|
||||
encoding: 'utf8',
|
||||
timeout: CHILD_TIMEOUT_MS,
|
||||
});
|
||||
assert.equal(result.status, 0, `${runtime} offline materialization failed:\n${result.stdout}\n${result.stderr}`);
|
||||
const counts = JSON.parse(result.stdout);
|
||||
assert.ok(counts.after > 0 && counts.after < counts.before);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,8 @@ const {
|
||||
capabilityClusterStems,
|
||||
CAPABILITY_SKILL_MARKER,
|
||||
} = require('../gsd-core/bin/lib/install-profiles.cjs');
|
||||
const { createTempDir, cleanup } = require('./helpers.cjs');
|
||||
const { createTempDir, cleanup, writePackageSourceMarkerFixture } = require('./helpers.cjs');
|
||||
const { resolveRuntimeArtifactLayout: resolveLayout } = require('../gsd-core/bin/lib/runtime-artifact-layout.cjs');
|
||||
|
||||
const REAL_COMMANDS_DIR = path.join(__dirname, '..', 'commands', 'gsd');
|
||||
const REAL_AGENTS_DIR = path.join(__dirname, '..', 'agents');
|
||||
@@ -738,6 +739,7 @@ function createFixture() {
|
||||
const configDir = createTempDir('gsd-bug3659-');
|
||||
const skillsDir = path.join(configDir, 'skills');
|
||||
fs.mkdirSync(skillsDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(configDir, '.gsd-source'), REAL_COMMANDS_DIR + '\n');
|
||||
|
||||
const gsdExplore = path.join(skillsDir, 'gsd-explore');
|
||||
const gsdHelp = path.join(skillsDir, 'gsd-help');
|
||||
@@ -953,7 +955,7 @@ describe('bug-3659: applySurface prunes ~/.claude/skills/gsd-*/ on cluster disab
|
||||
const { describe: __issueDescribe, test: __issueTest } = require('node:test');
|
||||
const surfaceMod = require('../gsd-core/bin/lib/surface.cjs');
|
||||
const { writeSurface: __writeSurface, applySurface: __applySurface } = surfaceMod;
|
||||
const { resolveRuntimeArtifactLayout: __resolveRuntimeArtifactLayout } = require('../gsd-core/bin/lib/runtime-artifact-layout.cjs');
|
||||
const __resolveRuntimeArtifactLayout = resolveLayout;
|
||||
|
||||
/** Install a fake already-installed third-party capability skill under a sandboxed GSD_HOME. */
|
||||
function __installCapSkill(gsdHome, capId, stem, content) {
|
||||
@@ -1005,7 +1007,7 @@ describe('bug-3659: applySurface prunes ~/.claude/skills/gsd-*/ on cluster disab
|
||||
__issueDescribe('issue-2322: applySurface materializes installed third-party capability skills', () => {
|
||||
__issueTest('(1) primary: installed capability skill materializes at <prefix><stem>/SKILL.md and IS subject to the same runtime body rewrites as first-party content', () => {
|
||||
const gsdHome = createTempDir('gsd-2322-home-');
|
||||
const configDir = createTempDir('gsd-2322-cfg-');
|
||||
const configDir = writePackageSourceMarkerFixture(createTempDir('gsd-2322-cfg-'));
|
||||
const savedHome = process.env.GSD_HOME;
|
||||
try {
|
||||
// #2322 MEDIUM-4: a fixture with NO rewrite-triggering content passes
|
||||
@@ -1048,7 +1050,7 @@ describe('bug-3659: applySurface prunes ~/.claude/skills/gsd-*/ on cluster disab
|
||||
|
||||
__issueTest('(2) collision: a first-party stem always wins over a same-named third-party capability skill', () => {
|
||||
const gsdHome = createTempDir('gsd-2322-home-');
|
||||
const configDir = createTempDir('gsd-2322-cfg-');
|
||||
const configDir = writePackageSourceMarkerFixture(createTempDir('gsd-2322-cfg-'));
|
||||
const savedHome = process.env.GSD_HOME;
|
||||
try {
|
||||
const EVIL = '---\nname: phase\n---\n\n# EVIL PHASE — must never win over the first-party gsd-phase skill\n';
|
||||
@@ -1094,7 +1096,7 @@ describe('bug-3659: applySurface prunes ~/.claude/skills/gsd-*/ on cluster disab
|
||||
|
||||
__issueTest('(3) profile filter: a third-party skill outside the resolved profile is not staged; sibling first-party skills are unaffected', () => {
|
||||
const gsdHome = createTempDir('gsd-2322-home-');
|
||||
const configDir = createTempDir('gsd-2322-cfg-');
|
||||
const configDir = writePackageSourceMarkerFixture(createTempDir('gsd-2322-cfg-'));
|
||||
const savedHome = process.env.GSD_HOME;
|
||||
try {
|
||||
__installCapSkill(gsdHome, 'my-thing', 'my-thing', '# my-thing\n');
|
||||
@@ -1129,7 +1131,7 @@ describe('bug-3659: applySurface prunes ~/.claude/skills/gsd-*/ on cluster disab
|
||||
|
||||
__issueTest('(4) control: a nested-router (doNest) runtime layout is unperturbed by an installed capability skill', () => {
|
||||
const gsdHome = createTempDir('gsd-2322-home-');
|
||||
const configDir = createTempDir('gsd-2322-cfg-');
|
||||
const configDir = writePackageSourceMarkerFixture(createTempDir('gsd-2322-cfg-'));
|
||||
const savedHome = process.env.GSD_HOME;
|
||||
try {
|
||||
__installCapSkill(gsdHome, 'my-thing', 'my-thing', '# my-thing\n');
|
||||
@@ -1170,8 +1172,8 @@ describe('bug-3659: applySurface prunes ~/.claude/skills/gsd-*/ on cluster disab
|
||||
|
||||
__issueTest('(5) absent/malformed: a registry-referenced capability skill missing on disk must not throw and must not affect first-party output', () => {
|
||||
const gsdHome = createTempDir('gsd-2322-home-');
|
||||
const configDirGhost = createTempDir('gsd-2322-cfg-ghost-');
|
||||
const configDirPartial = createTempDir('gsd-2322-cfg-partial-');
|
||||
const configDirGhost = writePackageSourceMarkerFixture(createTempDir('gsd-2322-cfg-ghost-'));
|
||||
const configDirPartial = writePackageSourceMarkerFixture(createTempDir('gsd-2322-cfg-partial-'));
|
||||
const savedHome = process.env.GSD_HOME;
|
||||
try {
|
||||
// Partial case: the capability dir exists but the declared stem's
|
||||
@@ -1215,7 +1217,7 @@ describe('bug-3659: applySurface prunes ~/.claude/skills/gsd-*/ on cluster disab
|
||||
__issueDescribe('issue-2322 BLOCKER 1: capability skill stem hijack via an undeclared/unregistered directory', () => {
|
||||
__issueTest('an UNDECLARED skills/<stem>/ directory shipped by one capability must never supply another capability\'s declared+registered stem', () => {
|
||||
const gsdHome = createTempDir('gsd-2322-home-');
|
||||
const configDir = createTempDir('gsd-2322-cfg-');
|
||||
const configDir = writePackageSourceMarkerFixture(createTempDir('gsd-2322-cfg-'));
|
||||
const savedHome = process.env.GSD_HOME;
|
||||
try {
|
||||
const EVIL = '---\nname: deploy\n---\n\n# EVIL deploy — planted by aaa-utils, which never declared this skill\n';
|
||||
@@ -1282,7 +1284,7 @@ describe('bug-3659: applySurface prunes ~/.claude/skills/gsd-*/ on cluster disab
|
||||
__issueDescribe('issue-2322 BLOCKER 2: mode=full (the "*" sentinel) must still stage registered third-party capability skills', () => {
|
||||
__issueTest('resolveProfile({modes:["full"]})\'s "*" sentinel, passed straight to stageSkillsForRuntimeAsSkills, still materializes a registered capability skill', () => {
|
||||
const gsdHome = createTempDir('gsd-2322-home-');
|
||||
const configDir = createTempDir('gsd-2322-cfg-');
|
||||
const configDir = writePackageSourceMarkerFixture(createTempDir('gsd-2322-cfg-'));
|
||||
const savedHome = process.env.GSD_HOME;
|
||||
let unitStaged;
|
||||
let e2eStaged;
|
||||
@@ -1354,7 +1356,7 @@ describe('bug-3659: applySurface prunes ~/.claude/skills/gsd-*/ on cluster disab
|
||||
__issueDescribe('issue-2322 HIGH-3: an orphaned (uninstalled/unsurfaced) capability skill is pruned; a genuinely unknown gsd-* dir is still preserved', () => {
|
||||
__issueTest('uninstalling the capability + re-applying removes its staged skill; an unrelated hand-made gsd-* dir survives with a warning', () => {
|
||||
const gsdHome = createTempDir('gsd-2322-home-');
|
||||
const configDir = createTempDir('gsd-2322-cfg-');
|
||||
const configDir = writePackageSourceMarkerFixture(createTempDir('gsd-2322-cfg-'));
|
||||
const savedHome = process.env.GSD_HOME;
|
||||
try {
|
||||
__installCapSkill(gsdHome, 'my-thing', 'my-thing', '# my-thing\n');
|
||||
@@ -1521,7 +1523,7 @@ const {
|
||||
resolveProfile,
|
||||
} = require('../gsd-core/bin/lib/install-profiles.cjs');
|
||||
const { applySurface } = require('../gsd-core/bin/lib/surface.cjs');
|
||||
const { resolveRuntimeArtifactLayout } = require('../gsd-core/bin/lib/runtime-artifact-layout.cjs');
|
||||
const resolveRuntimeArtifactLayout = resolveLayout;
|
||||
|
||||
const MANIFEST = loadSkillsManifest(COMMANDS_GSD);
|
||||
const RESOLVED_FULL = resolveProfile({ modes: ['full'], manifest: MANIFEST });
|
||||
@@ -1627,6 +1629,7 @@ describe('bug-924: applySurface on claude preserves flat layout (no re-nesting)'
|
||||
before(() => {
|
||||
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-924-surface-'));
|
||||
installRuntimeArtifacts('claude', tmpDir, 'global', RESOLVED_FULL);
|
||||
writePackageSourceMarkerFixture(tmpDir);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
|
||||
@@ -16,7 +16,8 @@ const { writeSurface, readSurface, resolveSurface, listSurface, applySurface } =
|
||||
const { loadSkillsManifest, writeActiveProfile, resolveProfile } = require('../gsd-core/bin/lib/install-profiles.cjs');
|
||||
const { resolveRuntimeArtifactLayout } = require('../gsd-core/bin/lib/runtime-artifact-layout.cjs');
|
||||
const { CLUSTERS, allClusteredSkills } = require('../gsd-core/bin/lib/clusters.cjs');
|
||||
const { createTempDir, cleanup, sandboxHome } = require('./helpers.cjs');
|
||||
const { createTempDir, cleanup, sandboxHome, writePackageSourceMarkerFixture } = require('./helpers.cjs');
|
||||
const { runMinimalInstall } = require('./helpers/install-shared.cjs');
|
||||
|
||||
const REAL_COMMANDS_DIR = path.join(__dirname, '..', 'commands', 'gsd');
|
||||
|
||||
@@ -34,6 +35,7 @@ function createFixtureRuntime() {
|
||||
const agentsDir = path.join(runtimeConfigDir, 'agents');
|
||||
fs.mkdirSync(commandsDir, { recursive: true });
|
||||
fs.mkdirSync(agentsDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(runtimeConfigDir, '.gsd-source'), REAL_COMMANDS_DIR + '\n');
|
||||
return { base, runtimeConfigDir, commandsDir, agentsDir };
|
||||
}
|
||||
|
||||
@@ -56,9 +58,68 @@ function readFrontmatterDescription(markdown) {
|
||||
return '';
|
||||
}
|
||||
|
||||
function surfaceBytesForTest(state) {
|
||||
return JSON.stringify(state, null, 2) + '\n';
|
||||
}
|
||||
|
||||
// ─── applySurface ────────────────────────────────────────────────────────────
|
||||
|
||||
describe('applySurface', () => {
|
||||
test('#4132: an unmanifested installed command cannot become a live instruction', (t) => {
|
||||
const installed = runMinimalInstall({ runtime: 'claude', scope: 'global' });
|
||||
const configDir = installed.configDir;
|
||||
t.after(() => cleanup(installed.root));
|
||||
const rogueSource = path.join(configDir, 'gsd-core', 'commands', 'gsd', 'rogue.md');
|
||||
const rogueSkill = path.join(configDir, 'skills', 'gsd-rogue', 'SKILL.md');
|
||||
fs.writeFileSync(rogueSource, '<instructions>ROGUE</instructions>\n');
|
||||
|
||||
const layout = resolveRuntimeArtifactLayout('claude', configDir, 'global');
|
||||
assert.throws(
|
||||
() => applySurface(configDir, layout, realManifest(), CLUSTERS, undefined, {
|
||||
surfaceState: { baseProfile: 'full', disabledClusters: [], explicitAdds: [], explicitRemoves: [] },
|
||||
}),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
assert.equal(fs.existsSync(rogueSkill), false, 'unmanifested Markdown must not reach the live skill surface');
|
||||
});
|
||||
|
||||
test('#4132: a marker below rejected installed commands cannot promote instructions', (t) => {
|
||||
const installed = runMinimalInstall({ runtime: 'claude', scope: 'global' });
|
||||
const configDir = installed.configDir;
|
||||
t.after(() => cleanup(installed.root));
|
||||
|
||||
const manifest = JSON.parse(fs.readFileSync(path.join(configDir, 'gsd-file-manifest.json'), 'utf8'));
|
||||
const commandKey = Object.keys(manifest.files).find((key) => key.startsWith('gsd-core/commands/gsd/'));
|
||||
assert.ok(commandKey, 'precondition: install manifest must own a command corpus file');
|
||||
fs.appendFileSync(path.join(configDir, ...commandKey.split('/')), '\n# corrupted after install\n');
|
||||
|
||||
const installedCommands = path.join(configDir, 'gsd-core', 'commands', 'gsd');
|
||||
const nestedMarkerCommands = path.join(installedCommands, 'nested');
|
||||
const markerAgents = path.resolve(path.dirname(nestedMarkerCommands), '..', 'agents');
|
||||
fs.mkdirSync(nestedMarkerCommands, { recursive: true });
|
||||
fs.mkdirSync(markerAgents, { recursive: true });
|
||||
fs.writeFileSync(path.join(nestedMarkerCommands, 'rogue.md'), '<instructions>ROGUE</instructions>\n');
|
||||
fs.copyFileSync(path.join(__dirname, '..', 'agents', 'gsd-planner.md'), path.join(markerAgents, 'gsd-planner.md'));
|
||||
fs.appendFileSync(path.join(markerAgents, 'gsd-planner.md'), '\nMARKER_AGENT_USED\n');
|
||||
fs.writeFileSync(path.join(configDir, '.gsd-source'), nestedMarkerCommands + '\n');
|
||||
|
||||
const rogueSkill = path.join(configDir, 'skills', 'gsd-rogue', 'SKILL.md');
|
||||
const liveAgent = path.join(configDir, 'agents', 'gsd-planner.md');
|
||||
const oldAgent = fs.readFileSync(liveAgent);
|
||||
const oldState = { baseProfile: 'full', disabledClusters: [], explicitAdds: [], explicitRemoves: [] };
|
||||
writeSurface(configDir, oldState);
|
||||
const oldSurface = fs.readFileSync(path.join(configDir, '.gsd-surface.json'));
|
||||
|
||||
const layout = resolveRuntimeArtifactLayout('claude', configDir, 'global');
|
||||
assert.throws(
|
||||
() => applySurface(configDir, layout, realManifest(), CLUSTERS, undefined, { surfaceState: oldState }),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
assert.equal(fs.existsSync(rogueSkill), false, 'nested marker Markdown must not reach the live skill surface');
|
||||
assert.deepEqual(fs.readFileSync(liveAgent), oldAgent, 'marker agents must not replace live agents');
|
||||
assert.deepEqual(fs.readFileSync(path.join(configDir, '.gsd-surface.json')), oldSurface);
|
||||
});
|
||||
|
||||
test('core profile: only core skills appear in commandsDir', (t) => {
|
||||
// #1367: claude local uses flat gsd-<stem>.md files at commands/ (not commands/gsd/<stem>.md).
|
||||
const { base, runtimeConfigDir, commandsDir } = createFixtureRuntime();
|
||||
@@ -324,6 +385,7 @@ describe('applySurface', () => {
|
||||
test('applySurface writes gsd-prefixed command files matching install and preserves user commands (#816)', (t) => {
|
||||
const configDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-surface-816-'));
|
||||
t.after(() => cleanup(configDir));
|
||||
writePackageSourceMarkerFixture(configDir);
|
||||
|
||||
writeActiveProfile(configDir, 'standard');
|
||||
writeSurface(configDir, {
|
||||
@@ -406,6 +468,7 @@ describe('applySurface', () => {
|
||||
const installDir = fs.mkdtempSync(path.join(os.tmpdir(), `gsd-816-install-${runtime}-`));
|
||||
const surfaceDir = fs.mkdtempSync(path.join(os.tmpdir(), `gsd-816-surface-${runtime}-`));
|
||||
t.after(() => { cleanup(installDir); cleanup(surfaceDir); });
|
||||
writePackageSourceMarkerFixture(surfaceDir);
|
||||
|
||||
// --- Install path ---
|
||||
installRuntimeArtifacts(runtime, installDir, 'global', resolvedProfile);
|
||||
@@ -531,6 +594,118 @@ describe('applySurface', () => {
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
test('#4132: a later kind staging failure leaves exact all-old state and artifacts', (t) => {
|
||||
const root = createTempDir('gsd-surface-stage-failure-');
|
||||
t.after(() => cleanup(root));
|
||||
const firstDest = path.join(root, 'first');
|
||||
const secondDest = path.join(root, 'second');
|
||||
fs.mkdirSync(firstDest, { recursive: true });
|
||||
fs.mkdirSync(secondDest, { recursive: true });
|
||||
fs.writeFileSync(path.join(firstDest, 'gsd-alpha.md'), 'old alpha\n');
|
||||
fs.writeFileSync(path.join(secondDest, 'gsd-beta.md'), 'old beta\n');
|
||||
const stagedFirst = path.join(root, 'staged-first');
|
||||
fs.mkdirSync(stagedFirst);
|
||||
fs.writeFileSync(path.join(stagedFirst, 'alpha.md'), 'new alpha\n');
|
||||
const oldSurface = surfaceBytesForTest({ baseProfile: 'full', disabledClusters: [], explicitAdds: [], explicitRemoves: [] });
|
||||
fs.writeFileSync(path.join(root, '.gsd-surface.json'), oldSurface);
|
||||
const layout = {
|
||||
runtime: 'claude', configDir: root, scope: 'local', kinds: [
|
||||
{ kind: 'commands', destSubpath: 'first', prefix: 'gsd-', stage: () => stagedFirst },
|
||||
{ kind: 'commands', destSubpath: 'second', prefix: 'gsd-', stage: () => { throw new Error('later stage failed'); } },
|
||||
],
|
||||
};
|
||||
|
||||
assert.throws(() => applySurface(root, layout, new Map([['alpha', []], ['beta', []]])), /later stage failed/);
|
||||
assert.equal(fs.readFileSync(path.join(firstDest, 'gsd-alpha.md'), 'utf8'), 'old alpha\n');
|
||||
assert.equal(fs.readFileSync(path.join(secondDest, 'gsd-beta.md'), 'utf8'), 'old beta\n');
|
||||
assert.equal(fs.readFileSync(path.join(root, '.gsd-surface.json'), 'utf8'), oldSurface);
|
||||
});
|
||||
|
||||
test('#4132: a hash-mismatched installed corpus leaves exact all-old state and artifacts', (t) => {
|
||||
const root = createTempDir('gsd-surface-corrupt-corpus-');
|
||||
t.after(() => cleanup(root));
|
||||
const installedCommands = path.join(root, 'gsd-core', 'commands', 'gsd');
|
||||
const installedAgents = path.join(root, 'gsd-core', 'agents');
|
||||
fs.mkdirSync(installedCommands, { recursive: true });
|
||||
fs.mkdirSync(installedAgents, { recursive: true });
|
||||
fs.writeFileSync(path.join(installedCommands, 'help.md'), '# corrupted command\n');
|
||||
fs.writeFileSync(path.join(installedAgents, 'gsd-planner.md'), '# corrupted agent\n');
|
||||
fs.writeFileSync(path.join(root, 'gsd-file-manifest.json'), JSON.stringify({ files: {
|
||||
'gsd-core/commands/gsd/help.md': '0'.repeat(64),
|
||||
'gsd-core/agents/gsd-planner.md': '0'.repeat(64),
|
||||
} }));
|
||||
|
||||
const skillPath = path.join(root, 'skills', 'gsd-help', 'SKILL.md');
|
||||
const agentPath = path.join(root, 'agents', 'gsd-planner.md');
|
||||
fs.mkdirSync(path.dirname(skillPath), { recursive: true });
|
||||
fs.mkdirSync(path.dirname(agentPath), { recursive: true });
|
||||
fs.writeFileSync(skillPath, 'old skill\n');
|
||||
fs.writeFileSync(agentPath, 'old agent\n');
|
||||
const oldState = { baseProfile: 'full', disabledClusters: [], explicitAdds: [], explicitRemoves: [] };
|
||||
const candidate = { ...oldState, explicitRemoves: ['help'] };
|
||||
const oldSurface = surfaceBytesForTest(oldState);
|
||||
fs.writeFileSync(path.join(root, '.gsd-surface.json'), oldSurface);
|
||||
|
||||
const layout = resolveRuntimeArtifactLayout('claude', root, 'global');
|
||||
assert.throws(
|
||||
() => applySurface(root, layout, realManifest(), CLUSTERS, undefined, { surfaceState: candidate }),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
assert.equal(fs.readFileSync(skillPath, 'utf8'), 'old skill\n');
|
||||
assert.equal(fs.readFileSync(agentPath, 'utf8'), 'old agent\n');
|
||||
assert.equal(fs.readFileSync(path.join(root, '.gsd-surface.json'), 'utf8'), oldSurface);
|
||||
});
|
||||
|
||||
test('#4132: candidate surface state is published after materialization', (t) => {
|
||||
const root = createTempDir('gsd-surface-state-last-');
|
||||
t.after(() => cleanup(root));
|
||||
const dest = path.join(root, 'commands');
|
||||
const staged = path.join(root, 'staged');
|
||||
fs.mkdirSync(dest, { recursive: true });
|
||||
fs.mkdirSync(staged);
|
||||
fs.writeFileSync(path.join(dest, 'gsd-alpha.md'), 'old alpha\n');
|
||||
fs.writeFileSync(path.join(staged, 'alpha.md'), 'new alpha\n');
|
||||
const oldState = { baseProfile: 'full', disabledClusters: [], explicitAdds: [], explicitRemoves: [] };
|
||||
const newState = { ...oldState, disabledClusters: ['ui'] };
|
||||
writeSurface(root, oldState);
|
||||
const layout = {
|
||||
runtime: 'claude', configDir: root, scope: 'local', kinds: [
|
||||
{ kind: 'commands', destSubpath: 'commands', prefix: 'gsd-', stage: () => {
|
||||
assert.deepEqual(readSurface(root), oldState, 'candidate must not be visible while staging');
|
||||
return staged;
|
||||
} },
|
||||
],
|
||||
};
|
||||
|
||||
applySurface(root, layout, new Map([['alpha', []]]), undefined, undefined, { surfaceState: newState });
|
||||
|
||||
assert.equal(fs.readFileSync(path.join(dest, 'gsd-alpha.md'), 'utf8'), 'new alpha\n');
|
||||
assert.deepEqual(readSurface(root), newState);
|
||||
});
|
||||
|
||||
test('#4132: reset removes surface state after materialization', (t) => {
|
||||
const root = createTempDir('gsd-surface-reset-state-last-');
|
||||
t.after(() => cleanup(root));
|
||||
const dest = path.join(root, 'commands');
|
||||
const staged = path.join(root, 'staged');
|
||||
fs.mkdirSync(dest, { recursive: true });
|
||||
fs.mkdirSync(staged);
|
||||
fs.writeFileSync(path.join(staged, 'alpha.md'), 'reset alpha\n');
|
||||
writeActiveProfile(root, 'full');
|
||||
writeSurface(root, { baseProfile: 'core', disabledClusters: ['ui'], explicitAdds: [], explicitRemoves: [] });
|
||||
const layout = {
|
||||
runtime: 'claude', configDir: root, scope: 'local', kinds: [
|
||||
{ kind: 'commands', destSubpath: 'commands', prefix: 'gsd-', stage: () => staged },
|
||||
],
|
||||
};
|
||||
|
||||
applySurface(root, layout, new Map([['alpha', []]]), undefined, undefined, { surfaceState: null });
|
||||
|
||||
assert.equal(fs.existsSync(path.join(root, '.gsd-surface.json')), false);
|
||||
assert.equal(fs.readFileSync(path.join(dest, 'gsd-alpha.md'), 'utf8'), 'reset alpha\n');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// ─── resolveSurface ──────────────────────────────────────────────────────────
|
||||
@@ -1201,6 +1376,7 @@ describe('skills-kind destination parity: installer vs surface-apply (#2911)', (
|
||||
for (const runtime of RUNTIME_IDS) {
|
||||
const configDir = fs.mkdtempSync(path.join(os.tmpdir(), `gsd-2911-parity-${runtime}-${scope}-`));
|
||||
t.after(() => cleanup(configDir));
|
||||
writePackageSourceMarkerFixture(configDir);
|
||||
|
||||
withFakeHome(fakeHome, () => {
|
||||
let layout;
|
||||
@@ -1295,6 +1471,7 @@ describe('codex skills-kind destination: home override (#2911)', () => {
|
||||
t.after(() => cleanup(fakeHome));
|
||||
const codexHome = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-2911-codex-home-dir-'));
|
||||
t.after(() => cleanup(codexHome));
|
||||
writePackageSourceMarkerFixture(codexHome);
|
||||
|
||||
withFakeHome(fakeHome, () => {
|
||||
const manifest = loadSkillsManifest(REAL_COMMANDS_DIR);
|
||||
@@ -1387,6 +1564,7 @@ describe('installOpencodeFamilySkills destination parity (#2911 sibling coverage
|
||||
const configDir = fs.mkdtempSync(path.join(os.tmpdir(), `gsd-2911-ocfs-${runtime}-`));
|
||||
const fakeHomeOverride = fs.mkdtempSync(path.join(os.tmpdir(), `gsd-2911-ocfs-home-${runtime}-`));
|
||||
t.after(() => { cleanup(configDir); cleanup(fakeHomeOverride); });
|
||||
writePackageSourceMarkerFixture(configDir);
|
||||
// #3712 — this row drives a skills-kind `home` override on purpose, which is
|
||||
// exactly what the test-home guard exists to police, so it has to declare the
|
||||
// sandbox rather than rely on the destination happening to sit outside the
|
||||
@@ -1458,15 +1636,12 @@ describe('installOpencodeFamilySkills destination parity (#2911 sibling coverage
|
||||
// flat layout is preserved (not re-nested) rather than a nested one.
|
||||
describe('issue-69: applySurface preserves nested skill layout (no re-flatten)', () => {
|
||||
test('cline global full: applySurface keeps 6 router dirs and nested gsd-ns-manage/skills/help/SKILL.md', (t) => {
|
||||
process.env.GSD_TEST_MODE = '1';
|
||||
const { installRuntimeArtifacts } = require('../gsd-core/bin/lib/install-engine.cjs');
|
||||
const dir = tmpDir('gsd-69-surface-');
|
||||
t.after(() => { try { cleanup(dir); } catch { /* best-effort */ } });
|
||||
const installed = runMinimalInstall({ runtime: 'cline', scope: 'global' });
|
||||
const dir = installed.configDir;
|
||||
t.after(() => { try { cleanup(installed.root); } catch { /* best-effort */ } });
|
||||
|
||||
// Step 1: full install
|
||||
const manifest = loadSkillsManifest(REAL_COMMANDS_DIR);
|
||||
const resolved = resolveProfile({ modes: ['full'], manifest });
|
||||
installRuntimeArtifacts('cline', dir, 'global', resolved);
|
||||
|
||||
const skillsDir = path.join(dir, 'skills');
|
||||
|
||||
@@ -1510,14 +1685,11 @@ describe('issue-69: applySurface preserves nested skill layout (no re-flatten)',
|
||||
|
||||
// #924 companion: Claude must use FLAT layout and applySurface must NOT re-nest it.
|
||||
test('claude global full: install produces flat layout and applySurface preserves it (#924)', (t) => {
|
||||
process.env.GSD_TEST_MODE = '1';
|
||||
const { installRuntimeArtifacts } = require('../gsd-core/bin/lib/install-engine.cjs');
|
||||
const dir = tmpDir('gsd-924-69-');
|
||||
t.after(() => { try { cleanup(dir); } catch { /* best-effort */ } });
|
||||
const installed = runMinimalInstall({ runtime: 'claude', scope: 'global' });
|
||||
const dir = installed.configDir;
|
||||
t.after(() => { try { cleanup(installed.root); } catch { /* best-effort */ } });
|
||||
|
||||
const manifest = loadSkillsManifest(REAL_COMMANDS_DIR);
|
||||
const resolved = resolveProfile({ modes: ['full'], manifest });
|
||||
installRuntimeArtifacts('claude', dir, 'global', resolved);
|
||||
|
||||
const skillsDir = path.join(dir, 'skills');
|
||||
|
||||
|
||||
@@ -21,12 +21,14 @@ const { test, describe, beforeEach, afterEach, mock } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const crypto = require('node:crypto');
|
||||
|
||||
const { resolveRuntimeArtifactLayout, findInstallSourceRoot } = require('../gsd-core/bin/lib/runtime-artifact-layout.cjs');
|
||||
const capabilityRegistry = require('../gsd-core/bin/lib/capability-registry.cjs');
|
||||
const installProfiles = require('../gsd-core/bin/lib/install-profiles.cjs');
|
||||
const { withInstallFs } = require('../gsd-core/bin/lib/install-fs-adapter.cjs');
|
||||
const { install } = require('../bin/install.js');
|
||||
const { createTempDir, cleanup, scrubConfigLocationEnv } = require('./helpers.cjs');
|
||||
const { createTempDir, cleanup, scrubConfigLocationEnv, writePackageSourceMarkerFixture } = require('./helpers.cjs');
|
||||
|
||||
const REPO_ROOT = path.join(__dirname, '..');
|
||||
|
||||
@@ -533,11 +535,16 @@ const CORE_SKILLS = new Set(['help', 'phase', 'new-project']);
|
||||
const CORE_AGENTS = new Set(['gsd-planner']);
|
||||
const PROFILE_CORE = { skills: CORE_SKILLS, agents: CORE_AGENTS };
|
||||
const PROFILE_FULL = { skills: '*', agents: new Set() };
|
||||
const FAKE_STAGE_DIR = '/tmp/fake-config-dir-stage';
|
||||
|
||||
function createStageConfigDir(t) {
|
||||
const configDir = writePackageSourceMarkerFixture(createTempDir('gsd-layout-stage-'));
|
||||
t.after(() => cleanup(configDir));
|
||||
return configDir;
|
||||
}
|
||||
|
||||
describe('stage — agents kind (claude local)', () => {
|
||||
test('stage returns a valid directory for the agents kind', () => {
|
||||
const layout = resolveRuntimeArtifactLayout('claude', FAKE_STAGE_DIR, 'local');
|
||||
test('stage returns a valid directory for the agents kind', (t) => {
|
||||
const layout = resolveRuntimeArtifactLayout('claude', createStageConfigDir(t), 'local');
|
||||
const agentsKind = layout.kinds.find(k => k.kind === 'agents');
|
||||
assert.ok(agentsKind, 'should have an agents kind');
|
||||
|
||||
@@ -548,8 +555,40 @@ describe('stage — agents kind (claude local)', () => {
|
||||
});
|
||||
|
||||
describe('stage — skills kind (claude global)', () => {
|
||||
test('stage returns a directory containing gsd-<stem>/SKILL.md entries', () => {
|
||||
const layout = resolveRuntimeArtifactLayout('claude', FAKE_STAGE_DIR, 'global');
|
||||
test('#4132: an independent source checkout can replace an invalid installed corpus', (t) => {
|
||||
const configDir = createTempDir('gsd-4132-installer-source-');
|
||||
t.after(() => cleanup(configDir));
|
||||
const installedCommands = path.join(configDir, 'gsd-core', 'commands', 'gsd');
|
||||
const installedAgents = path.join(configDir, 'gsd-core', 'agents');
|
||||
fs.mkdirSync(installedCommands, { recursive: true });
|
||||
fs.mkdirSync(installedAgents, { recursive: true });
|
||||
fs.writeFileSync(path.join(installedCommands, 'help.md'), 'OLD INSTALLED COMMAND\n');
|
||||
fs.writeFileSync(path.join(installedAgents, 'gsd-planner.md'), 'OLD INSTALLED AGENT\n');
|
||||
fs.writeFileSync(path.join(configDir, '.gsd-source'), path.join(REPO_ROOT, 'commands', 'gsd') + '\n');
|
||||
|
||||
const layout = resolveRuntimeArtifactLayout('claude', configDir, 'global');
|
||||
const skillsKind = layout.kinds.find(k => k.kind === 'skills');
|
||||
const agentsKind = layout.kinds.find(k => k.kind === 'agents');
|
||||
assert.ok(skillsKind);
|
||||
assert.ok(agentsKind);
|
||||
|
||||
const stagedSkills = skillsKind.stage(PROFILE_CORE);
|
||||
const stagedAgents = agentsKind.stage(PROFILE_CORE);
|
||||
t.after(() => cleanup(stagedSkills));
|
||||
t.after(() => cleanup(stagedAgents));
|
||||
|
||||
assert.match(
|
||||
fs.readFileSync(path.join(stagedSkills, 'gsd-help', 'SKILL.md'), 'utf8'),
|
||||
/Show available GSD commands and usage guide/,
|
||||
);
|
||||
assert.doesNotMatch(
|
||||
fs.readFileSync(path.join(stagedAgents, 'gsd-planner.md'), 'utf8'),
|
||||
/OLD INSTALLED AGENT/,
|
||||
);
|
||||
});
|
||||
|
||||
test('stage returns a directory containing gsd-<stem>/SKILL.md entries', (t) => {
|
||||
const layout = resolveRuntimeArtifactLayout('claude', createStageConfigDir(t), 'global');
|
||||
const skillsKind = layout.kinds.find(k => k.kind === 'skills');
|
||||
assert.ok(skillsKind, 'should have a skills kind');
|
||||
|
||||
@@ -564,8 +603,8 @@ describe('stage — skills kind (claude global)', () => {
|
||||
assert.ok(entries.length >= 1, 'at least one skill dir should be staged');
|
||||
});
|
||||
|
||||
test('stage with skills="*" produces flat layout for claude (#924: reverted from nested)', () => {
|
||||
const layout = resolveRuntimeArtifactLayout('claude', FAKE_STAGE_DIR, 'global');
|
||||
test('stage with skills="*" produces flat layout for claude (#924: reverted from nested)', (t) => {
|
||||
const layout = resolveRuntimeArtifactLayout('claude', createStageConfigDir(t), 'global');
|
||||
const skillsKind = layout.kinds.find(k => k.kind === 'skills');
|
||||
assert.ok(skillsKind, 'should have a skills kind');
|
||||
|
||||
@@ -592,8 +631,8 @@ describe('stage — skills kind (claude global)', () => {
|
||||
});
|
||||
|
||||
describe('stage — skills kind (kimi global)', () => {
|
||||
test('stage returns Kimi SKILL.md dirs and agent YAML/prompt artifacts', () => {
|
||||
const layout = resolveRuntimeArtifactLayout('kimi', FAKE_STAGE_DIR, 'global');
|
||||
test('stage returns Kimi SKILL.md dirs and agent YAML/prompt artifacts', (t) => {
|
||||
const layout = resolveRuntimeArtifactLayout('kimi', createStageConfigDir(t), 'global');
|
||||
const skillsKind = layout.kinds.find(k => k.kind === 'skills');
|
||||
assert.ok(skillsKind, 'should have a skills kind');
|
||||
|
||||
@@ -635,8 +674,8 @@ describe('stage — skills kind (kimi global)', () => {
|
||||
assert.doesNotMatch(executorYaml, /mcp__/);
|
||||
});
|
||||
|
||||
test('tracks Kimi agent staging dir before writing artifacts', () => {
|
||||
const layout = resolveRuntimeArtifactLayout('kimi', FAKE_STAGE_DIR, 'global');
|
||||
test('tracks Kimi agent staging dir before writing artifacts', (t) => {
|
||||
const layout = resolveRuntimeArtifactLayout('kimi', createStageConfigDir(t), 'global');
|
||||
const agentsKind = layout.kinds.find(k => k.kind === 'kimi-agents');
|
||||
assert.ok(agentsKind, 'should have a kimi-agents kind');
|
||||
|
||||
@@ -673,8 +712,8 @@ describe('stage — skills kind (kimi global)', () => {
|
||||
});
|
||||
|
||||
describe('stage — opencode commands kind', () => {
|
||||
test('opencode stage returns directory with .md files for selected skills', () => {
|
||||
const layout = resolveRuntimeArtifactLayout('opencode', FAKE_STAGE_DIR);
|
||||
test('opencode stage returns directory with .md files for selected skills', (t) => {
|
||||
const layout = resolveRuntimeArtifactLayout('opencode', createStageConfigDir(t));
|
||||
const commandsKind = layout.kinds.find(k => k.kind === 'commands');
|
||||
assert.ok(commandsKind, 'should have a commands kind');
|
||||
|
||||
@@ -690,8 +729,8 @@ describe('stage — opencode commands kind', () => {
|
||||
|
||||
describe('stage — opencode/kilo skills kind (#784)', () => {
|
||||
for (const runtime of ['opencode', 'kilo']) {
|
||||
test(`${runtime} skills stage writes gsd-<stem>/SKILL.md with name + description`, () => {
|
||||
const layout = resolveRuntimeArtifactLayout(runtime, FAKE_STAGE_DIR);
|
||||
test(`${runtime} skills stage writes gsd-<stem>/SKILL.md with name + description`, (t) => {
|
||||
const layout = resolveRuntimeArtifactLayout(runtime, createStageConfigDir(t));
|
||||
const skillsKind = layout.kinds.find(k => k.kind === 'skills');
|
||||
assert.ok(skillsKind, 'should have a skills kind');
|
||||
|
||||
@@ -717,7 +756,7 @@ describe('stage — opencode/kilo skills kind (#784)', () => {
|
||||
|
||||
describe('stage — cursor retired commands kind (#2644)', () => {
|
||||
test('cursor layout exposes no commands staging surface', () => {
|
||||
const layout = resolveRuntimeArtifactLayout('cursor', FAKE_STAGE_DIR);
|
||||
const layout = resolveRuntimeArtifactLayout('cursor', FAKE_DIR);
|
||||
const commandsKind = layout.kinds.find(k => k.kind === 'commands');
|
||||
assert.equal(commandsKind, undefined);
|
||||
});
|
||||
@@ -921,9 +960,10 @@ describe('#1477 .gsd-source marker provisioning', () => {
|
||||
});
|
||||
|
||||
// ── Failure 1 end-to-end: resolution succeeds FROM the deployed tree ─────────
|
||||
// The deployed module's __dirname is <claudeDir>/gsd-core/bin/lib, which has no
|
||||
// commands/gsd ancestor (global skills layout). Only the marker rescues it.
|
||||
test('deployed global layout resolves the source root via the marker', () => {
|
||||
// Fixed installs own a raw corpus below the deployed gsd-core tree. The
|
||||
// marker remains compatible, but offline resolution no longer depends on
|
||||
// the executing package path surviving.
|
||||
test('deployed global layout resolves its installation-owned source corpus', () => {
|
||||
const claudeDir = path.join(tmpRoot, '.claude');
|
||||
fs.mkdirSync(claudeDir, { recursive: true });
|
||||
runInstall(true /* isGlobal */, 'claude');
|
||||
@@ -939,21 +979,93 @@ describe('#1477 .gsd-source marker provisioning', () => {
|
||||
delete require.cache[deployedLayoutPath];
|
||||
const deployed = require(deployedLayoutPath);
|
||||
|
||||
// Negative proof that the bug condition exists: WITHOUT consulting the marker
|
||||
// (no configDir argument), walk-up from the deployed tree has nothing to find.
|
||||
assert.throws(
|
||||
() => deployed.findInstallSourceRoot(),
|
||||
/could not locate commands\/gsd/,
|
||||
'deployed walk-up must fail without the marker — this is the regression condition',
|
||||
);
|
||||
const installedCorpus = path.join(claudeDir, 'gsd-core', 'commands', 'gsd');
|
||||
assert.ok(fs.existsSync(installedCorpus), 'fixed install must own commands/gsd below gsd-core');
|
||||
assert.equal(fs.realpathSync(deployed.findInstallSourceRoot()), fs.realpathSync(installedCorpus));
|
||||
|
||||
// With the marker (configDir provided), list/status resolution succeeds.
|
||||
let resolved;
|
||||
assert.doesNotThrow(() => {
|
||||
resolved = deployed.findInstallSourceRoot(claudeDir);
|
||||
}, 'findInstallSourceRoot must resolve via the .gsd-source marker');
|
||||
assert.equal(path.basename(resolved), 'gsd');
|
||||
assert.ok(fs.existsSync(resolved));
|
||||
assert.equal(fs.realpathSync(resolved), fs.realpathSync(installedCorpus));
|
||||
});
|
||||
|
||||
test('#4132: deployed findInstallSourceRoot rejects an installed commands corpus whose hash changed', () => {
|
||||
const claudeDir = path.join(tmpRoot, '.claude');
|
||||
fs.mkdirSync(claudeDir, { recursive: true });
|
||||
runInstall(true /* isGlobal */, 'claude');
|
||||
|
||||
const manifest = JSON.parse(fs.readFileSync(path.join(claudeDir, 'gsd-file-manifest.json'), 'utf8'));
|
||||
const commandKey = Object.keys(manifest.files).find((key) => key.startsWith('gsd-core/commands/gsd/'));
|
||||
assert.ok(commandKey, 'precondition: install manifest must own at least one command corpus file');
|
||||
const commandPath = path.join(claudeDir, ...commandKey.split('/'));
|
||||
fs.appendFileSync(commandPath, '\n# corrupted after install\n');
|
||||
|
||||
const deployedLayoutPath = path.join(claudeDir, 'gsd-core', 'bin', 'lib', 'runtime-artifact-layout.cjs');
|
||||
delete require.cache[deployedLayoutPath];
|
||||
const deployed = require(deployedLayoutPath);
|
||||
|
||||
assert.throws(
|
||||
() => deployed.findInstallSourceRoot(claudeDir),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
});
|
||||
|
||||
test('#4132: deployed finder rejects an installed corpus reached through an ancestor symlink', (t) => {
|
||||
const claudeDir = path.join(tmpRoot, '.claude');
|
||||
fs.mkdirSync(claudeDir, { recursive: true });
|
||||
runInstall(true /* isGlobal */, 'claude');
|
||||
|
||||
const commandsParent = path.join(claudeDir, 'gsd-core', 'commands');
|
||||
const outsideParent = path.join(tmpRoot, 'outside-commands');
|
||||
fs.renameSync(commandsParent, outsideParent);
|
||||
try {
|
||||
fs.symlinkSync(outsideParent, commandsParent, process.platform === 'win32' ? 'junction' : 'dir');
|
||||
} catch (error) {
|
||||
fs.renameSync(outsideParent, commandsParent);
|
||||
if (['EPERM', 'EACCES', 'ENOSYS'].includes(error.code)) {
|
||||
t.skip(`directory symlink creation unavailable: ${error.code || error.message}`);
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
const deployedLayoutPath = path.join(claudeDir, 'gsd-core', 'bin', 'lib', 'runtime-artifact-layout.cjs');
|
||||
delete require.cache[deployedLayoutPath];
|
||||
const deployed = require(deployedLayoutPath);
|
||||
const priorOptIn = process.env.GSD_ALLOW_SYMLINKED_DEST;
|
||||
process.env.GSD_ALLOW_SYMLINKED_DEST = '1';
|
||||
t.after(() => {
|
||||
if (priorOptIn === undefined) delete process.env.GSD_ALLOW_SYMLINKED_DEST;
|
||||
else process.env.GSD_ALLOW_SYMLINKED_DEST = priorOptIn;
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() => deployed.findInstallSourceRoot(claudeDir),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
});
|
||||
|
||||
test('#4132: deployed agents layout rejects an installed agents corpus whose hash changed', () => {
|
||||
const claudeDir = path.join(tmpRoot, '.claude');
|
||||
fs.mkdirSync(claudeDir, { recursive: true });
|
||||
runInstall(true /* isGlobal */, 'claude');
|
||||
|
||||
const manifest = JSON.parse(fs.readFileSync(path.join(claudeDir, 'gsd-file-manifest.json'), 'utf8'));
|
||||
const agentKey = Object.keys(manifest.files).find((key) => key.startsWith('gsd-core/agents/'));
|
||||
assert.ok(agentKey, 'precondition: install manifest must own at least one agent corpus file');
|
||||
fs.appendFileSync(path.join(claudeDir, ...agentKey.split('/')), '\n# corrupted after install\n');
|
||||
|
||||
const deployedLayoutPath = path.join(claudeDir, 'gsd-core', 'bin', 'lib', 'runtime-artifact-layout.cjs');
|
||||
delete require.cache[deployedLayoutPath];
|
||||
const deployed = require(deployedLayoutPath);
|
||||
|
||||
assert.throws(
|
||||
() => deployed.resolveRuntimeArtifactLayout('claude', claudeDir, 'global')
|
||||
.kinds.find((kind) => kind.kind === 'agents').stage(PROFILE_CORE),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
});
|
||||
|
||||
// ── Adversarial marker-reader cases (no full install needed) ─────────────────
|
||||
@@ -965,6 +1077,7 @@ describe('#1477 .gsd-source marker provisioning', () => {
|
||||
test('marker pointing at a valid commands/gsd takes precedence over walk-up', () => {
|
||||
const fakeSrc = path.join(cfgDir, 'pkg', 'commands', 'gsd');
|
||||
fs.mkdirSync(fakeSrc, { recursive: true });
|
||||
fs.writeFileSync(path.join(fakeSrc, 'gsd-test.md'), '# marker source\n');
|
||||
fs.writeFileSync(path.join(cfgDir, '.gsd-source'), fakeSrc + '\n', 'utf8');
|
||||
|
||||
const resolved = findInstallSourceRoot(cfgDir);
|
||||
@@ -981,11 +1094,335 @@ describe('#1477 .gsd-source marker provisioning', () => {
|
||||
assert.equal(path.resolve(resolved), path.resolve(REPO_ROOT, 'commands', 'gsd'));
|
||||
});
|
||||
|
||||
test('#4132: a missing installed leaf still rejects a marker containing it through a symlinked ancestor', (t) => {
|
||||
const outsideCore = path.join(cfgDir, 'outside-core');
|
||||
const markerCommands = path.join(outsideCore, 'commands');
|
||||
const markerAgents = path.join(cfgDir, 'agents');
|
||||
fs.mkdirSync(markerCommands, { recursive: true });
|
||||
fs.mkdirSync(markerAgents, { recursive: true });
|
||||
fs.writeFileSync(path.join(markerCommands, 'help.md'), '# marker command\n');
|
||||
fs.writeFileSync(path.join(markerAgents, 'gsd-planner.md'), '# marker agent\n');
|
||||
try {
|
||||
fs.symlinkSync(
|
||||
outsideCore,
|
||||
path.join(cfgDir, 'gsd-core'),
|
||||
process.platform === 'win32' ? 'junction' : 'dir',
|
||||
);
|
||||
} catch (error) {
|
||||
t.skip(`directory symlink creation unavailable: ${error.code || error.message}`);
|
||||
return;
|
||||
}
|
||||
fs.writeFileSync(path.join(cfgDir, '.gsd-source'), markerCommands + '\n');
|
||||
|
||||
assert.throws(
|
||||
() => resolveRuntimeArtifactLayout('claude', cfgDir, 'global')
|
||||
.kinds.find((kind) => kind.kind === 'skills').stage(PROFILE_CORE),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
});
|
||||
|
||||
test('empty / whitespace-only marker is ignored', () => {
|
||||
fs.writeFileSync(path.join(cfgDir, '.gsd-source'), ' \n', 'utf8');
|
||||
const resolved = findInstallSourceRoot(cfgDir);
|
||||
assert.equal(path.resolve(resolved), path.resolve(REPO_ROOT, 'commands', 'gsd'));
|
||||
});
|
||||
|
||||
test('one complete installed provider wins over a different complete marker provider', (t) => {
|
||||
const installedCommands = path.join(cfgDir, 'gsd-core', 'commands', 'gsd');
|
||||
const installedAgents = path.join(cfgDir, 'gsd-core', 'agents');
|
||||
fs.mkdirSync(installedCommands, { recursive: true });
|
||||
fs.mkdirSync(installedAgents, { recursive: true });
|
||||
const installedCommandPath = path.join(installedCommands, 'help.md');
|
||||
const installedAgentPath = path.join(installedAgents, 'gsd-planner.md');
|
||||
fs.writeFileSync(installedCommandPath, '# installed command\n');
|
||||
fs.writeFileSync(installedAgentPath, '# installed agent\n');
|
||||
fs.writeFileSync(path.join(cfgDir, 'gsd-file-manifest.json'), JSON.stringify({ files: {
|
||||
'gsd-core/commands/gsd/help.md': crypto.createHash('sha256').update(fs.readFileSync(installedCommandPath)).digest('hex'),
|
||||
'gsd-core/agents/gsd-planner.md': crypto.createHash('sha256').update(fs.readFileSync(installedAgentPath)).digest('hex'),
|
||||
} }));
|
||||
|
||||
const markerCommands = path.join(cfgDir, 'legacy-package', 'commands', 'gsd');
|
||||
const markerAgents = path.join(cfgDir, 'legacy-package', 'agents');
|
||||
fs.mkdirSync(markerCommands, { recursive: true });
|
||||
fs.mkdirSync(markerAgents, { recursive: true });
|
||||
fs.writeFileSync(path.join(markerCommands, 'help.md'), '# marker command\n');
|
||||
fs.writeFileSync(path.join(markerAgents, 'gsd-planner.md'), '# marker agent\n');
|
||||
fs.writeFileSync(path.join(cfgDir, '.gsd-source'), markerCommands + '\n');
|
||||
|
||||
const layout = resolveRuntimeArtifactLayout('claude', cfgDir, 'global');
|
||||
const stagedSkills = layout.kinds.find((kind) => kind.kind === 'skills').stage(PROFILE_CORE);
|
||||
const stagedAgents = layout.kinds.find((kind) => kind.kind === 'agents').stage(PROFILE_CORE);
|
||||
t.after(() => cleanup(stagedSkills));
|
||||
t.after(() => cleanup(stagedAgents));
|
||||
assert.match(fs.readFileSync(path.join(stagedSkills, 'gsd-help', 'SKILL.md'), 'utf8'), /installed command/);
|
||||
assert.match(fs.readFileSync(path.join(stagedAgents, 'gsd-planner.md'), 'utf8'), /installed agent/);
|
||||
});
|
||||
|
||||
test('a partial installed corpus is not mixed with a complete marker provider', (t) => {
|
||||
const installedCommands = path.join(cfgDir, 'gsd-core', 'commands', 'gsd');
|
||||
fs.mkdirSync(installedCommands, { recursive: true });
|
||||
fs.writeFileSync(path.join(installedCommands, 'help.md'), '# installed command\n');
|
||||
const markerCommands = path.join(cfgDir, 'legacy-package', 'commands', 'gsd');
|
||||
const markerAgents = path.join(cfgDir, 'legacy-package', 'agents');
|
||||
fs.mkdirSync(markerCommands, { recursive: true });
|
||||
fs.mkdirSync(markerAgents, { recursive: true });
|
||||
fs.writeFileSync(path.join(markerCommands, 'help.md'), '# marker command\n');
|
||||
fs.writeFileSync(path.join(markerAgents, 'gsd-planner.md'), '# marker agent\n');
|
||||
fs.writeFileSync(path.join(cfgDir, '.gsd-source'), markerCommands + '\n');
|
||||
|
||||
const layout = resolveRuntimeArtifactLayout('claude', cfgDir, 'global');
|
||||
const stagedSkills = layout.kinds.find((kind) => kind.kind === 'skills').stage(PROFILE_CORE);
|
||||
const stagedAgents = layout.kinds.find((kind) => kind.kind === 'agents').stage(PROFILE_CORE);
|
||||
t.after(() => cleanup(stagedSkills));
|
||||
t.after(() => cleanup(stagedAgents));
|
||||
assert.match(fs.readFileSync(path.join(stagedSkills, 'gsd-help', 'SKILL.md'), 'utf8'), /marker command/);
|
||||
assert.match(fs.readFileSync(path.join(stagedAgents, 'gsd-planner.md'), 'utf8'), /marker agent/);
|
||||
});
|
||||
|
||||
test('partial providers are not mixed when package fallback is disabled', () => {
|
||||
const installedCommands = path.join(cfgDir, 'gsd-core', 'commands', 'gsd');
|
||||
fs.mkdirSync(installedCommands, { recursive: true });
|
||||
fs.writeFileSync(path.join(installedCommands, 'gsd-test.md'), '# installed command\n');
|
||||
|
||||
const markerCommands = path.join(cfgDir, 'legacy-package', 'commands', 'gsd');
|
||||
fs.mkdirSync(markerCommands, { recursive: true });
|
||||
fs.writeFileSync(path.join(markerCommands, 'gsd-test.md'), '# marker command\n');
|
||||
fs.writeFileSync(path.join(cfgDir, '.gsd-source'), markerCommands + '\n');
|
||||
|
||||
const layout = resolveRuntimeArtifactLayout('claude', cfgDir, 'global');
|
||||
assert.throws(() => layout.kinds.find((kind) => kind.kind === 'skills').stage(PROFILE_CORE), /install or upgrade gsd-core/);
|
||||
});
|
||||
|
||||
test('ordinary Runtime Surface staging never falls back to the source checkout package', () => {
|
||||
const layout = resolveRuntimeArtifactLayout('claude', cfgDir, 'global');
|
||||
const skills = layout.kinds.find((kind) => kind.kind === 'skills');
|
||||
assert.ok(skills);
|
||||
assert.throws(
|
||||
() => skills.stage(PROFILE_CORE),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
});
|
||||
|
||||
test('#4132: caller-supplied stage context cannot select installer source authority', () => {
|
||||
const layout = resolveRuntimeArtifactLayout('claude', cfgDir, 'global');
|
||||
const skills = layout.kinds.find((kind) => kind.kind === 'skills');
|
||||
assert.throws(
|
||||
() => skills.stage(PROFILE_CORE, {
|
||||
[Symbol.for('@open-gsd/runtime-artifact-installer-source-authority')]: true,
|
||||
}),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
assert.throws(
|
||||
() => withInstallFs(undefined, () => skills.stage(PROFILE_CORE)),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
});
|
||||
|
||||
test('an installed corpus without a manifest is not a working fallback', () => {
|
||||
const installedCommands = path.join(cfgDir, 'gsd-core', 'commands', 'gsd');
|
||||
const installedAgents = path.join(cfgDir, 'gsd-core', 'agents');
|
||||
fs.mkdirSync(installedCommands, { recursive: true });
|
||||
fs.mkdirSync(installedAgents, { recursive: true });
|
||||
fs.writeFileSync(path.join(installedCommands, 'help.md'), '# unverified command\n');
|
||||
fs.writeFileSync(path.join(installedAgents, 'gsd-planner.md'), '# unverified agent\n');
|
||||
|
||||
const layout = resolveRuntimeArtifactLayout('claude', cfgDir, 'global');
|
||||
assert.throws(
|
||||
() => layout.kinds.find((kind) => kind.kind === 'skills').stage(PROFILE_CORE),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
});
|
||||
|
||||
test('an installed corpus whose bytes do not match its manifest is not a working fallback', () => {
|
||||
const installedCommands = path.join(cfgDir, 'gsd-core', 'commands', 'gsd');
|
||||
const installedAgents = path.join(cfgDir, 'gsd-core', 'agents');
|
||||
fs.mkdirSync(installedCommands, { recursive: true });
|
||||
fs.mkdirSync(installedAgents, { recursive: true });
|
||||
fs.writeFileSync(path.join(installedCommands, 'help.md'), '# corrupted command\n');
|
||||
fs.writeFileSync(path.join(installedAgents, 'gsd-planner.md'), '# corrupted agent\n');
|
||||
fs.writeFileSync(path.join(cfgDir, 'gsd-file-manifest.json'), JSON.stringify({ files: {
|
||||
'gsd-core/commands/gsd/help.md': '0'.repeat(64),
|
||||
'gsd-core/agents/gsd-planner.md': '0'.repeat(64),
|
||||
} }));
|
||||
|
||||
const layout = resolveRuntimeArtifactLayout('claude', cfgDir, 'global');
|
||||
assert.throws(
|
||||
() => layout.kinds.find((kind) => kind.kind === 'skills').stage(PROFILE_CORE),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
});
|
||||
|
||||
test('a hash-mismatched installed corpus falls back to an independent complete marker provider', (t) => {
|
||||
const installedCommands = path.join(cfgDir, 'gsd-core', 'commands', 'gsd');
|
||||
const installedAgents = path.join(cfgDir, 'gsd-core', 'agents');
|
||||
fs.mkdirSync(installedCommands, { recursive: true });
|
||||
fs.mkdirSync(installedAgents, { recursive: true });
|
||||
fs.writeFileSync(path.join(installedCommands, 'help.md'), '# corrupted command\n');
|
||||
fs.writeFileSync(path.join(installedAgents, 'gsd-planner.md'), '# corrupted agent\n');
|
||||
fs.writeFileSync(path.join(cfgDir, 'gsd-file-manifest.json'), JSON.stringify({ files: {
|
||||
'gsd-core/commands/gsd/help.md': '0'.repeat(64),
|
||||
'gsd-core/agents/gsd-planner.md': '0'.repeat(64),
|
||||
} }));
|
||||
|
||||
const markerCommands = path.join(cfgDir, 'legacy-package', 'commands', 'gsd');
|
||||
const markerAgents = path.join(cfgDir, 'legacy-package', 'agents');
|
||||
fs.mkdirSync(markerCommands, { recursive: true });
|
||||
fs.mkdirSync(markerAgents, { recursive: true });
|
||||
fs.writeFileSync(path.join(markerCommands, 'help.md'), '# marker command\n');
|
||||
fs.writeFileSync(path.join(markerAgents, 'gsd-planner.md'), '# marker agent\n');
|
||||
fs.writeFileSync(path.join(cfgDir, '.gsd-source'), markerCommands + '\n');
|
||||
|
||||
const layout = resolveRuntimeArtifactLayout('claude', cfgDir, 'global');
|
||||
const stagedSkills = layout.kinds.find((kind) => kind.kind === 'skills').stage(PROFILE_CORE);
|
||||
const stagedAgents = layout.kinds.find((kind) => kind.kind === 'agents').stage(PROFILE_CORE);
|
||||
t.after(() => cleanup(stagedSkills));
|
||||
t.after(() => cleanup(stagedAgents));
|
||||
assert.match(fs.readFileSync(path.join(stagedSkills, 'gsd-help', 'SKILL.md'), 'utf8'), /marker command/);
|
||||
assert.match(fs.readFileSync(path.join(stagedAgents, 'gsd-planner.md'), 'utf8'), /marker agent/);
|
||||
});
|
||||
|
||||
test('#4132: a marker aliasing any rejected installed root is not an independent provider', (t) => {
|
||||
const installedCommandsParent = path.join(cfgDir, 'gsd-core', 'commands');
|
||||
const installedCommands = path.join(installedCommandsParent, 'gsd');
|
||||
const installedAgents = path.join(cfgDir, 'gsd-core', 'agents');
|
||||
fs.mkdirSync(installedCommands, { recursive: true });
|
||||
fs.mkdirSync(installedAgents, { recursive: true });
|
||||
fs.writeFileSync(path.join(installedCommands, 'help.md'), '# corrupted installed command\n');
|
||||
const installedAgentPath = path.join(installedAgents, 'gsd-planner.md');
|
||||
fs.writeFileSync(installedAgentPath, '# installed agent\n');
|
||||
fs.writeFileSync(path.join(cfgDir, 'gsd-file-manifest.json'), JSON.stringify({ files: {
|
||||
'gsd-core/commands/gsd/help.md': '0'.repeat(64),
|
||||
'gsd-core/agents/gsd-planner.md': crypto.createHash('sha256').update(fs.readFileSync(installedAgentPath)).digest('hex'),
|
||||
} }));
|
||||
|
||||
const markerRoot = path.join(cfgDir, 'hybrid-marker');
|
||||
fs.mkdirSync(markerRoot, { recursive: true });
|
||||
try {
|
||||
fs.symlinkSync(
|
||||
installedCommandsParent,
|
||||
path.join(markerRoot, 'commands'),
|
||||
process.platform === 'win32' ? 'junction' : 'dir',
|
||||
);
|
||||
} catch (error) {
|
||||
t.skip(`directory symlink creation unavailable: ${error.code || error.message}`);
|
||||
return;
|
||||
}
|
||||
const markerCommands = path.join(markerRoot, 'commands', 'gsd');
|
||||
const markerAgents = path.join(markerRoot, 'agents');
|
||||
fs.mkdirSync(markerAgents, { recursive: true });
|
||||
fs.writeFileSync(path.join(markerAgents, 'gsd-planner.md'), '# independent marker agent\n');
|
||||
fs.writeFileSync(path.join(cfgDir, '.gsd-source'), markerCommands + '\n');
|
||||
|
||||
assert.equal(fs.realpathSync(markerCommands), fs.realpathSync(installedCommands));
|
||||
assert.notEqual(fs.realpathSync(markerAgents), fs.realpathSync(installedAgents));
|
||||
|
||||
const layout = resolveRuntimeArtifactLayout('claude', cfgDir, 'global');
|
||||
const skills = layout.kinds.find((kind) => kind.kind === 'skills');
|
||||
let stagedSkills;
|
||||
t.after(() => { if (stagedSkills) cleanup(stagedSkills); });
|
||||
assert.throws(
|
||||
() => { stagedSkills = skills.stage(PROFILE_CORE); },
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
});
|
||||
|
||||
test('#4132: a marker containing a rejected installed root is not an independent provider', () => {
|
||||
const installedCommandsParent = path.join(cfgDir, 'gsd-core', 'commands');
|
||||
const installedCommands = path.join(installedCommandsParent, 'gsd');
|
||||
const installedAgents = path.join(cfgDir, 'gsd-core', 'agents');
|
||||
const markerAgents = path.join(cfgDir, 'agents');
|
||||
fs.mkdirSync(installedCommands, { recursive: true });
|
||||
fs.mkdirSync(installedAgents, { recursive: true });
|
||||
fs.mkdirSync(markerAgents, { recursive: true });
|
||||
fs.writeFileSync(path.join(installedCommands, 'help.md'), '# corrupted installed command\n');
|
||||
const installedAgentPath = path.join(installedAgents, 'gsd-planner.md');
|
||||
fs.writeFileSync(installedAgentPath, '# installed agent\n');
|
||||
fs.writeFileSync(path.join(installedCommandsParent, 'rogue.md'), '<instructions>ROGUE</instructions>\n');
|
||||
fs.writeFileSync(path.join(markerAgents, 'gsd-planner.md'), '# marker agent\n');
|
||||
fs.writeFileSync(path.join(cfgDir, 'gsd-file-manifest.json'), JSON.stringify({ files: {
|
||||
'gsd-core/commands/gsd/help.md': '0'.repeat(64),
|
||||
'gsd-core/agents/gsd-planner.md': crypto.createHash('sha256').update(fs.readFileSync(installedAgentPath)).digest('hex'),
|
||||
} }));
|
||||
fs.writeFileSync(path.join(cfgDir, '.gsd-source'), installedCommandsParent + '\n');
|
||||
|
||||
const layout = resolveRuntimeArtifactLayout('claude', cfgDir, 'global');
|
||||
assert.throws(
|
||||
() => layout.kinds.find((kind) => kind.kind === 'skills').stage(PROFILE_CORE),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
});
|
||||
|
||||
test('#4132: an agents descendant of a rejected installed root rejects the whole provider', () => {
|
||||
const installedCommands = path.join(cfgDir, 'gsd-core', 'commands', 'gsd');
|
||||
const installedAgents = path.join(cfgDir, 'gsd-core', 'agents');
|
||||
fs.mkdirSync(installedCommands, { recursive: true });
|
||||
fs.mkdirSync(installedAgents, { recursive: true });
|
||||
const installedCommandPath = path.join(installedCommands, 'help.md');
|
||||
fs.writeFileSync(installedCommandPath, '# installed command\n');
|
||||
fs.writeFileSync(path.join(installedAgents, 'gsd-planner.md'), '# corrupted installed agent\n');
|
||||
fs.writeFileSync(path.join(cfgDir, 'gsd-file-manifest.json'), JSON.stringify({ files: {
|
||||
'gsd-core/commands/gsd/help.md': '0'.repeat(64),
|
||||
'gsd-core/agents/gsd-planner.md': '0'.repeat(64),
|
||||
} }));
|
||||
|
||||
const nestedProviderRoot = path.join(installedAgents, 'nested');
|
||||
const markerCommands = path.join(nestedProviderRoot, 'commands', 'gsd');
|
||||
const markerAgents = path.join(nestedProviderRoot, 'agents');
|
||||
fs.mkdirSync(markerCommands, { recursive: true });
|
||||
fs.mkdirSync(markerAgents, { recursive: true });
|
||||
fs.writeFileSync(path.join(markerCommands, 'help.md'), '# marker command\n');
|
||||
fs.writeFileSync(path.join(markerAgents, 'gsd-planner.md'), '# marker agent\n');
|
||||
fs.writeFileSync(path.join(cfgDir, '.gsd-source'), markerCommands + '\n');
|
||||
|
||||
assert.equal(
|
||||
fs.realpathSync(findInstallSourceRoot(cfgDir)),
|
||||
fs.realpathSync(markerCommands),
|
||||
'commands-only resolution must ignore overlap in the non-required agents class',
|
||||
);
|
||||
const layout = resolveRuntimeArtifactLayout('claude', cfgDir, 'global');
|
||||
assert.throws(
|
||||
() => layout.kinds.find((kind) => kind.kind === 'skills').stage(PROFILE_CORE),
|
||||
/install or upgrade gsd-core/,
|
||||
);
|
||||
});
|
||||
|
||||
test('manifest-expected missing corpus file fails closed without reusing its marker alias', () => {
|
||||
const installedCommands = path.join(cfgDir, 'gsd-core', 'commands', 'gsd');
|
||||
const installedAgents = path.join(cfgDir, 'gsd-core', 'agents');
|
||||
fs.mkdirSync(installedCommands, { recursive: true });
|
||||
fs.mkdirSync(installedAgents, { recursive: true });
|
||||
fs.writeFileSync(path.join(installedCommands, 'gsd-test.md'), '# installed command\n');
|
||||
fs.writeFileSync(path.join(installedAgents, 'gsd-test-agent.md'), '# installed agent\n');
|
||||
fs.writeFileSync(path.join(cfgDir, 'gsd-file-manifest.json'), JSON.stringify({ files: {
|
||||
'gsd-core/commands/gsd/gsd-test.md': '0'.repeat(64),
|
||||
'gsd-core/agents/gsd-test-agent.md': '0'.repeat(64),
|
||||
'gsd-core/agents/removed.md': '0'.repeat(64),
|
||||
} }));
|
||||
fs.writeFileSync(path.join(cfgDir, '.gsd-source'), installedCommands + '\n');
|
||||
|
||||
const layout = resolveRuntimeArtifactLayout('claude', cfgDir, 'global');
|
||||
assert.throws(() => layout.kinds.find((kind) => kind.kind === 'skills').stage(PROFILE_CORE), /install or upgrade gsd-core/);
|
||||
});
|
||||
|
||||
test('a symlink inside the installed corpus is not a confined source', (t) => {
|
||||
const installedCommands = path.join(cfgDir, 'gsd-core', 'commands', 'gsd');
|
||||
const installedAgents = path.join(cfgDir, 'gsd-core', 'agents');
|
||||
fs.mkdirSync(installedCommands, { recursive: true });
|
||||
fs.mkdirSync(installedAgents, { recursive: true });
|
||||
fs.writeFileSync(path.join(installedCommands, 'gsd-test.md'), '# installed command\n');
|
||||
const outside = path.join(cfgDir, 'outside.md');
|
||||
fs.writeFileSync(outside, '# outside\n');
|
||||
try {
|
||||
fs.symlinkSync(outside, path.join(installedAgents, 'gsd-test-agent.md'));
|
||||
} catch (error) {
|
||||
t.skip(`symlink creation unavailable: ${error.code || error.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const layout = resolveRuntimeArtifactLayout('claude', cfgDir, 'global');
|
||||
assert.throws(() => layout.kinds.find((kind) => kind.kind === 'skills').stage(PROFILE_CORE), /install or upgrade gsd-core/);
|
||||
assert.strictEqual(fs.readFileSync(outside, 'utf8'), '# outside\n');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1054,8 +1491,7 @@ describe('#2624 .gsd-source marker is rewritten before staging reads it', () =>
|
||||
cleanup(tmpRoot);
|
||||
});
|
||||
|
||||
// The current package's commands/gsd — what the marker MUST point at after install.
|
||||
const CURRENT_SOURCE = path.join(REPO_ROOT, 'commands', 'gsd');
|
||||
const installedSource = (claudeDir) => path.join(claudeDir, 'gsd-core', 'commands', 'gsd');
|
||||
|
||||
test('claude-global install overwrites a stale .gsd-source marker before staging reads it', (t) => {
|
||||
const claudeDir = path.join(tmpRoot, '.claude');
|
||||
@@ -1090,8 +1526,8 @@ describe('#2624 .gsd-source marker is rewritten before staging reads it', () =>
|
||||
const markerPath = path.join(claudeDir, '.gsd-source');
|
||||
assert.ok(fs.existsSync(markerPath), 'marker must exist after install');
|
||||
const finalMarker = path.resolve(fs.readFileSync(markerPath, 'utf8').trim());
|
||||
assert.equal(finalMarker, path.resolve(CURRENT_SOURCE),
|
||||
`final marker must point at the current package source, not ${finalMarker}`);
|
||||
assert.equal(finalMarker, path.resolve(installedSource(claudeDir)),
|
||||
`final marker must point at the installed current-version corpus, not ${finalMarker}`);
|
||||
|
||||
// The decisive assertion: staging must NEVER have resolved the stale source. Before the
|
||||
// fix, at least one staging resolution returned the stale path (read before rewrite).
|
||||
@@ -1112,8 +1548,8 @@ describe('#2624 .gsd-source marker is rewritten before staging reads it', () =>
|
||||
const resolved = fs.readFileSync(markerPath, 'utf8').trim();
|
||||
assert.equal(
|
||||
path.resolve(resolved),
|
||||
path.resolve(CURRENT_SOURCE),
|
||||
'fresh install marker must point at the current package source',
|
||||
path.resolve(installedSource(claudeDir)),
|
||||
'fresh install marker must point at the installed corpus',
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1132,8 +1568,8 @@ describe('#2624 .gsd-source marker is rewritten before staging reads it', () =>
|
||||
const resolved = fs.readFileSync(markerPath, 'utf8').trim();
|
||||
assert.equal(
|
||||
path.resolve(resolved),
|
||||
path.resolve(CURRENT_SOURCE),
|
||||
'ghost marker must be rewritten to the current package source',
|
||||
path.resolve(installedSource(claudeDir)),
|
||||
'ghost marker must be rewritten to the installed corpus',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2508,6 +2508,7 @@ describe('#3706: the layout seam actually threads the variant', () => {
|
||||
fs.mkdirSync(commandsDir, { recursive: true });
|
||||
fs.mkdirSync(agentsDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(configDir, '.gsd-source'), commandsDir + '\n', 'utf8');
|
||||
fs.writeFileSync(path.join(commandsDir, 'gsd-help.md'), '# complete marker provider\n', 'utf8');
|
||||
fs.writeFileSync(path.join(agentsDir, 'gsd-executor.md'), agentContent, 'utf8');
|
||||
return configDir;
|
||||
}
|
||||
@@ -2587,4 +2588,3 @@ describe('#3706: the layout seam actually threads the variant', () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -39,3 +39,18 @@ describe('#2116 regression: surface.md resolvable require + correct package', ()
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#4132 regression: surface.md uses the state-last public contract', () => {
|
||||
// allow-test-rule: source-text-is-the-product (#4132)
|
||||
const content = fs.readFileSync(SURFACE_MD, 'utf-8');
|
||||
|
||||
test('mutations pass an in-memory candidate without an eager state write', () => {
|
||||
assert.match(content, /surfaceState/);
|
||||
assert.match(content, /publishes the candidate state only after/);
|
||||
assert.doesNotMatch(content, /writeSurface\(runtimeConfigDir, surfaceState\)/);
|
||||
});
|
||||
|
||||
test('reset is represented as an absent-state candidate, not an eager delete', () => {
|
||||
assert.match(content, /surfaceState: null/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"adr857-predicate-boundary.test.cjs": 113,
|
||||
"affected-tests-lib.test.cjs": 240,
|
||||
"agent-classification-parity.test.cjs": 49,
|
||||
"agent-fragments-emission.install.test.cjs": 79456,
|
||||
"agent-fragments-emission.install.test.cjs": 228000,
|
||||
"agent-frontmatter.test.cjs": 1076,
|
||||
"agent-install-check.test.cjs": 274,
|
||||
"agent-install-validation.test.cjs": 12405,
|
||||
@@ -282,7 +282,7 @@
|
||||
"fixture-builder.test.cjs": 324,
|
||||
"forensics.test.cjs": 164,
|
||||
"format-github-release-notes.test.cjs": 69,
|
||||
"fragment-single-edit-propagation.install.test.cjs": 229914,
|
||||
"fragment-single-edit-propagation.install.test.cjs": 575000,
|
||||
"frontmatter-cli.test.cjs": 25728,
|
||||
"frontmatter.property.test.cjs": 2551,
|
||||
"frontmatter.test.cjs": 10565,
|
||||
|
||||
Reference in New Issue
Block a user