Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions .repo-updates-log

This file was deleted.

7 changes: 7 additions & 0 deletions openspec/specs/cli-init/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,13 @@ The init command SHALL generate slash command files for supported editors using
- **AND** wrap the shared template body with OpenSpec markers so `openspec update` can refresh the content
- **AND** each template includes instructions for the relevant OpenSpec workflow stage

#### Scenario: Generating slash commands for Gemini CLI
- **WHEN** the user selects Gemini CLI during initialization
- **THEN** create `.gemini/commands/openspec/proposal.toml`, `.gemini/commands/openspec/apply.toml`, and `.gemini/commands/openspec/archive.toml`
- **AND** populate each file as TOML that sets a stage-specific `description = "<summary>"` and a multi-line `prompt = """` block with the shared OpenSpec template
- **AND** wrap the OpenSpec managed markers (`<!-- OPENSPEC:START -->` / `<!-- OPENSPEC:END -->`) inside the `prompt` value so `openspec update` can safely refresh the body between markers without touching the TOML framing
- **AND** ensure the slash-command copy matches the existing proposal/apply/archive templates used by other tools

### Requirement: Non-Interactive Mode
The command SHALL support non-interactive operation through command-line options for automation and CI/CD use cases.

Expand Down
6 changes: 6 additions & 0 deletions openspec/specs/cli-update/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ The update command SHALL refresh existing slash command files for configured too
- **AND** update only the OpenSpec-managed block between markers
- **AND** ensure templates include instructions for the relevant workflow stage

#### Scenario: Updating slash commands for Gemini CLI
- **WHEN** `.gemini/commands/openspec/` contains `proposal.toml`, `apply.toml`, and `archive.toml`
- **THEN** refresh the body of each file using the shared proposal/apply/archive templates
- **AND** replace only the content between `<!-- OPENSPEC:START -->` and `<!-- OPENSPEC:END -->` markers inside the `prompt = """` block so the TOML framing (`description`, `prompt`) stays intact
- **AND** skip creating any missing `.toml` files during update; only pre-existing Gemini commands are refreshed

#### Scenario: Missing slash command file
- **WHEN** a tool lacks a slash command file
- **THEN** do not create a new file during update
Expand Down
48 changes: 48 additions & 0 deletions test/core/update.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,54 @@ Old body
await expect(FileSystemUtils.fileExists(ghArchive)).resolves.toBe(false);
});

it('should refresh existing Gemini CLI TOML files without creating new ones', async () => {
const geminiProposal = path.join(
testDir,
'.gemini/commands/openspec/proposal.toml'
);
await fs.mkdir(path.dirname(geminiProposal), { recursive: true });
const initialContent = `description = "Scaffold a new OpenSpec change and validate strictly."

prompt = """
<!-- OPENSPEC:START -->
Old Gemini body
<!-- OPENSPEC:END -->
"""
`;
await fs.writeFile(geminiProposal, initialContent);

const consoleSpy = vi.spyOn(console, 'log');

await updateCommand.execute(testDir);

const updated = await fs.readFile(geminiProposal, 'utf-8');
expect(updated).toContain('description = "Scaffold a new OpenSpec change and validate strictly."');
expect(updated).toContain('prompt = """');
expect(updated).toContain('<!-- OPENSPEC:START -->');
expect(updated).toContain('**Guardrails**');
expect(updated).toContain('<!-- OPENSPEC:END -->');
expect(updated).not.toContain('Old Gemini body');

const geminiApply = path.join(
testDir,
'.gemini/commands/openspec/apply.toml'
);
const geminiArchive = path.join(
testDir,
'.gemini/commands/openspec/archive.toml'
);

await expect(FileSystemUtils.fileExists(geminiApply)).resolves.toBe(false);
await expect(FileSystemUtils.fileExists(geminiArchive)).resolves.toBe(false);

const [logMessage] = consoleSpy.mock.calls[0];
expect(logMessage).toContain(
'Updated slash commands: .gemini/commands/openspec/proposal.toml'
);

consoleSpy.mockRestore();
});

it('should refresh existing Factory slash commands', async () => {
const factoryPath = path.join(
testDir,
Expand Down
Loading