mirror of
https://github.com/Fission-AI/OpenSpec.git
synced 2026-10-15 05:30:21 +08:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
300d020529 | ||
|
|
f036fbeeae | ||
|
|
499241b525 | ||
|
|
01fded8c75 |
+24
-1
@@ -428,9 +428,11 @@ export class InitCommand {
|
||||
} else {
|
||||
ora({ stream: process.stdout }).info(
|
||||
PALETTE.midGray(
|
||||
'ℹ OpenSpec already initialized. Skipping base scaffolding.'
|
||||
'ℹ OpenSpec already initialized. Checking for missing files...'
|
||||
)
|
||||
);
|
||||
await this.createDirectoryStructure(openspecPath);
|
||||
await this.ensureTemplateFiles(openspecPath, config);
|
||||
}
|
||||
|
||||
// Step 2: Configure AI tools
|
||||
@@ -719,6 +721,21 @@ export class InitCommand {
|
||||
private async generateFiles(
|
||||
openspecPath: string,
|
||||
config: OpenSpecConfig
|
||||
): Promise<void> {
|
||||
await this.writeTemplateFiles(openspecPath, config, false);
|
||||
}
|
||||
|
||||
private async ensureTemplateFiles(
|
||||
openspecPath: string,
|
||||
config: OpenSpecConfig
|
||||
): Promise<void> {
|
||||
await this.writeTemplateFiles(openspecPath, config, true);
|
||||
}
|
||||
|
||||
private async writeTemplateFiles(
|
||||
openspecPath: string,
|
||||
config: OpenSpecConfig,
|
||||
skipExisting: boolean
|
||||
): Promise<void> {
|
||||
const context: ProjectContext = {
|
||||
// Could be enhanced with prompts for project details
|
||||
@@ -728,6 +745,12 @@ export class InitCommand {
|
||||
|
||||
for (const template of templates) {
|
||||
const filePath = path.join(openspecPath, template.path);
|
||||
|
||||
// Skip if file exists and we're in skipExisting mode
|
||||
if (skipExisting && (await FileSystemUtils.fileExists(filePath))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const content =
|
||||
typeof template.content === 'function'
|
||||
? template.content(context)
|
||||
|
||||
@@ -579,6 +579,44 @@ describe('InitCommand', () => {
|
||||
await expect(initCommand.execute(testDir)).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('should recreate deleted openspec/AGENTS.md in extend mode', async () => {
|
||||
await testFileRecreationInExtendMode(
|
||||
testDir,
|
||||
initCommand,
|
||||
'openspec/AGENTS.md',
|
||||
'OpenSpec Instructions'
|
||||
);
|
||||
});
|
||||
|
||||
it('should recreate deleted openspec/project.md in extend mode', async () => {
|
||||
await testFileRecreationInExtendMode(
|
||||
testDir,
|
||||
initCommand,
|
||||
'openspec/project.md',
|
||||
'Project Context'
|
||||
);
|
||||
});
|
||||
|
||||
it('should preserve existing template files in extend mode', async () => {
|
||||
queueSelections('claude', DONE, DONE);
|
||||
|
||||
// First init
|
||||
await initCommand.execute(testDir);
|
||||
|
||||
const agentsPath = path.join(testDir, 'openspec', 'AGENTS.md');
|
||||
const customContent = '# My Custom AGENTS Content\nDo not overwrite this!';
|
||||
|
||||
// Modify the file with custom content
|
||||
await fs.writeFile(agentsPath, customContent);
|
||||
|
||||
// Run init again - should NOT overwrite
|
||||
await initCommand.execute(testDir);
|
||||
|
||||
const content = await fs.readFile(agentsPath, 'utf-8');
|
||||
expect(content).toBe(customContent);
|
||||
expect(content).not.toContain('OpenSpec Instructions');
|
||||
});
|
||||
|
||||
it('should handle non-existent target directory', async () => {
|
||||
queueSelections('claude', DONE);
|
||||
|
||||
@@ -1160,6 +1198,32 @@ describe('InitCommand', () => {
|
||||
});
|
||||
});
|
||||
|
||||
async function testFileRecreationInExtendMode(
|
||||
testDir: string,
|
||||
initCommand: InitCommand,
|
||||
relativePath: string,
|
||||
expectedContent: string
|
||||
): Promise<void> {
|
||||
queueSelections('claude', DONE, DONE);
|
||||
|
||||
// First init
|
||||
await initCommand.execute(testDir);
|
||||
|
||||
const filePath = path.join(testDir, relativePath);
|
||||
expect(await fileExists(filePath)).toBe(true);
|
||||
|
||||
// Delete the file
|
||||
await fs.unlink(filePath);
|
||||
expect(await fileExists(filePath)).toBe(false);
|
||||
|
||||
// Run init again - should recreate the file
|
||||
await initCommand.execute(testDir);
|
||||
expect(await fileExists(filePath)).toBe(true);
|
||||
|
||||
const content = await fs.readFile(filePath, 'utf-8');
|
||||
expect(content).toContain(expectedContent);
|
||||
}
|
||||
|
||||
async function fileExists(filePath: string): Promise<boolean> {
|
||||
try {
|
||||
await fs.access(filePath);
|
||||
|
||||
Reference in New Issue
Block a user