Skip to content

Conversation

@lifegoon
Copy link

@lifegoon lifegoon commented Jan 20, 2026

  • Add support for Lingma AI IDE

Summary by CodeRabbit

Release Notes

  • New Features
    • Integrated Lingma IDE AI as a new available AI tool option, enabling users to select Lingma as their preferred AI assistant
    • Added Lingma slash commands supporting proposal submission, content application, and archive management operations
    • Automatically configures OpenSpec rules within Lingma environments with dedicated workflow files and integration

✏️ Tip: You can customize this high-level summary in your review settings.

- 在 AI 工具配置中注册 Lingma 选项
- 创建 Lingma 配置器实现工具特定配置逻辑
- 集成 Lingma 到工具注册表中统一管理
- 添加 Lingma 命令配置器支持工作流命令
- 注册 Lingma 命令到命令注册表中
- 实现 Lingma 规则文件自动生成和更新机制
@lifegoon lifegoon requested a review from TabishB as a code owner January 20, 2026 12:31
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 20, 2026

📝 Walkthrough

Walkthrough

This PR adds Lingma, a new AI IDE tool, to OpenSpec by introducing configuration classes that handle Lingma-specific setup, registering them in tool and slash-command registries, and listing Lingma in the available AI tools.

Changes

Cohort / File(s) Summary
Core Configuration & Registry Wiring
src/core/config.ts, src/core/configurators/registry.ts, src/core/configurators/slash/registry.ts
Added Lingma entry to AI_TOOLS array; registered LingmaConfigurator and LingmaSlashCommandConfigurator in their respective registries under the 'lingma' key.
Lingma Tool Configurator
src/core/configurators/lingma.ts
New LingmaConfigurator class implements ToolConfigurator, writes OpenSpec rules to .lingma/rules/openspec-rules.md using TemplateManager and FileSystemUtils with markers, prepends trigger configuration to existing files.
Lingma Slash Command Configurator
src/core/configurators/slash/lingma.ts
New LingmaSlashCommandConfigurator class extends SlashCommandConfigurator with three slash commands (proposal, apply, archive) mapped to workflow files; provides per-command descriptions and frontmatter with manual trigger configuration.

Sequence Diagram

sequenceDiagram
    actor User
    participant Registry
    participant LingmaConfigurator
    participant TemplateManager
    participant FileSystemUtils
    
    User->>Registry: Request Lingma configuration
    Registry->>LingmaConfigurator: Instantiate & call configure()
    LingmaConfigurator->>TemplateManager: Get OpenSpec standard template
    TemplateManager-->>LingmaConfigurator: Return template content
    LingmaConfigurator->>FileSystemUtils: Update file with markers
    FileSystemUtils->>FileSystemUtils: Wrap content with OPENSPEC_MARKERS
    FileSystemUtils->>FileSystemUtils: Prepend trigger config if file exists
    FileSystemUtils-->>LingmaConfigurator: File write complete
    LingmaConfigurator-->>User: Configuration applied
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • TabishB
  • Israel-Laguan

🐰 Lingma joins the OpenSpec team,
With rules and workflows, a coding dream,
Markers wrap the template bright,
Registry wired, everything's right,
Slash commands hop—configuration's prime!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(core): Add support for Lingma AI IDE' accurately and clearly describes the main objective of the pull request, which is to introduce support for Lingma AI IDE across multiple components.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@vibe-kanban-cloud
Copy link

Review Complete

Your review story is ready!

View Story

Comment !reviewfast on this PR to re-generate the story.

@lifegoon
Copy link
Author

lifegoon commented Jan 20, 2026

TongYi Lingma AI ide official website

@greptile-apps
Copy link

greptile-apps bot commented Jan 20, 2026

Greptile Summary

This PR adds support for Lingma AI IDE by implementing configurators for the main rules file and slash commands, following established patterns from other tool integrations.

  • Added Lingma to AI_TOOLS registry and both tool registries
  • Implemented LingmaConfigurator for .lingma/rules/openspec-rules.md with YAML frontmatter
  • Implemented LingmaSlashCommandConfigurator for workflow commands (proposal, apply, archive)
  • Slash command implementation correctly follows SlashCommandConfigurator base class patterns

Critical Issue: The main configurator (lingma.ts:37-61) has a logic error that will cause file corruption. After updateFileWithMarkers writes the file, the code reads it back and prepends frontmatter again, creating duplicate frontmatter blocks on subsequent runs. The fix is to handle new file creation and updates separately, similar to how slash commands are implemented.

Confidence Score: 1/5

  • This PR has a critical bug that will corrupt configuration files on updates
  • The main configurator has a fundamental logic error in lines 53-60 that causes file corruption. On first run, it works, but on subsequent updates it keeps prepending duplicate frontmatter blocks. This will break Lingma's rule parsing and corrupt user configuration files.
  • The src/core/configurators/lingma.ts file must be fixed before merging - the configure method's file handling logic is broken

Important Files Changed

Filename Overview
src/core/config.ts Added Lingma to AI_TOOLS registry in alphabetical order
src/core/configurators/slash/lingma.ts Implemented slash command configurator following established patterns correctly
src/core/configurators/lingma.ts Critical bug: frontmatter only added if file exists, and file is rewritten after updateFileWithMarkers

Sequence Diagram

sequenceDiagram
    participant User
    participant CLI as OpenSpec CLI
    participant Registry as ToolRegistry
    participant Lingma as LingmaConfigurator
    participant FS as FileSystemUtils
    participant Template as TemplateManager

    User->>CLI: openspec init --tool lingma
    CLI->>Registry: getTool('lingma')
    Registry->>Lingma: new LingmaConfigurator()
    Registry-->>CLI: configurator
    CLI->>Lingma: configure(projectPath, openspecDir)
    Lingma->>Template: getAgentsStandardTemplate()
    Template-->>Lingma: template content
    Lingma->>FS: updateFileWithMarkers(filePath, content, markers)
    alt File doesn't exist
        FS->>FS: Create .lingma/rules/openspec-rules.md
        FS->>FS: Write markers + content
    else File exists
        FS->>FS: Read existing file
        FS->>FS: Update content between markers
    end
    FS-->>Lingma: void
    Note over Lingma,FS: Bug: Current code reads file again<br/>and prepends frontmatter,<br/>causing duplication
    Lingma->>FS: fileExists(filePath)
    FS-->>Lingma: true
    Lingma->>FS: readFile(filePath)
    FS-->>Lingma: existing content
    Lingma->>Lingma: Prepend frontmatter
    Lingma->>FS: writeFile(filePath, frontmatter + content)
    FS-->>Lingma: void
    Lingma-->>CLI: void
    CLI-->>User: ✓ Configured Lingma
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +53 to +60
// Create trigger configuration for Lingma rules
const lingmaRulesTrigger = `---\ntrigger: always_on\nalwaysApply: true\n---\n`;
let existingContent = '';
if (await FileSystemUtils.fileExists(filePath)) {
existingContent = await FileSystemUtils.readFile(filePath);
existingContent = lingmaRulesTrigger + existingContent;
await FileSystemUtils.writeFile(filePath, existingContent);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: This logic is backwards and will fail. The frontmatter is only added if the file already exists, but should be added when creating a new file. Additionally, the file is rewritten after updateFileWithMarkers has already written it, causing duplication or incorrect output.

Compare with other configurators like qwen.ts which simply call updateFileWithMarkers - that method already handles both creating new files and updating existing ones with proper marker placement.

Suggested change
// Create trigger configuration for Lingma rules
const lingmaRulesTrigger = `---\ntrigger: always_on\nalwaysApply: true\n---\n`;
let existingContent = '';
if (await FileSystemUtils.fileExists(filePath)) {
existingContent = await FileSystemUtils.readFile(filePath);
existingContent = lingmaRulesTrigger + existingContent;
await FileSystemUtils.writeFile(filePath, existingContent);
}
// updateFileWithMarkers handles both file creation and updates
// For new files, it creates: frontmatter + markers + content
// For existing files, it updates content between markers
const frontmatter = `---\ntrigger: always_on\nalwaysApply: true\n---\n\n`;
const fullContent = frontmatter + content;
await FileSystemUtils.updateFileWithMarkers(
filePath,
fullContent,
OPENSPEC_MARKERS.start,
OPENSPEC_MARKERS.end
);
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/core/configurators/lingma.ts
Line: 53:60

Comment:
**logic:** This logic is backwards and will fail. The frontmatter is only added if the file already exists, but should be added when creating a new file. Additionally, the file is rewritten after `updateFileWithMarkers` has already written it, causing duplication or incorrect output.

Compare with other configurators like `qwen.ts` which simply call `updateFileWithMarkers` - that method already handles both creating new files and updating existing ones with proper marker placement.

```suggestion
    // updateFileWithMarkers handles both file creation and updates
    // For new files, it creates: frontmatter + markers + content
    // For existing files, it updates content between markers
    const frontmatter = `---\ntrigger: always_on\nalwaysApply: true\n---\n\n`;
    const fullContent = frontmatter + content;
    
    await FileSystemUtils.updateFileWithMarkers(
      filePath,
      fullContent,
      OPENSPEC_MARKERS.start,
      OPENSPEC_MARKERS.end
    );
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +37 to +61
async configure(projectPath: string, openspecDir: string): Promise<void> {
// Construct full path to .lingma/rules/openspec-rules.md
const filePath = path.join(projectPath, this.configFileName);

// Combine trigger configuration with agent-standard instructions
const content = TemplateManager.getAgentsStandardTemplate();

// Write or update file with managed content between markers
// This allows future updates to refresh instructions automatically
await FileSystemUtils.updateFileWithMarkers(
filePath,
content,
OPENSPEC_MARKERS.start,
OPENSPEC_MARKERS.end
);

// Create trigger configuration for Lingma rules
const lingmaRulesTrigger = `---\ntrigger: always_on\nalwaysApply: true\n---\n`;
let existingContent = '';
if (await FileSystemUtils.fileExists(filePath)) {
existingContent = await FileSystemUtils.readFile(filePath);
existingContent = lingmaRulesTrigger + existingContent;
await FileSystemUtils.writeFile(filePath, existingContent);
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Logic error causes file corruption on updates. After updateFileWithMarkers writes the file (line 46-51), the code reads it back and prepends frontmatter again (line 56-59). On subsequent runs, this creates duplicate frontmatter blocks.

Additionally, frontmatter is only added if file exists after the initial write, which is backwards - it should be added during initial creation.

Fix: Handle new files and updates separately, like SlashCommandConfigurator does (see slash/base.ts:32-43).

Suggested change
async configure(projectPath: string, openspecDir: string): Promise<void> {
// Construct full path to .lingma/rules/openspec-rules.md
const filePath = path.join(projectPath, this.configFileName);
// Combine trigger configuration with agent-standard instructions
const content = TemplateManager.getAgentsStandardTemplate();
// Write or update file with managed content between markers
// This allows future updates to refresh instructions automatically
await FileSystemUtils.updateFileWithMarkers(
filePath,
content,
OPENSPEC_MARKERS.start,
OPENSPEC_MARKERS.end
);
// Create trigger configuration for Lingma rules
const lingmaRulesTrigger = `---\ntrigger: always_on\nalwaysApply: true\n---\n`;
let existingContent = '';
if (await FileSystemUtils.fileExists(filePath)) {
existingContent = await FileSystemUtils.readFile(filePath);
existingContent = lingmaRulesTrigger + existingContent;
await FileSystemUtils.writeFile(filePath, existingContent);
}
}
async configure(projectPath: string, openspecDir: string): Promise<void> {
const filePath = path.join(projectPath, this.configFileName);
const content = TemplateManager.getAgentsStandardTemplate();
const frontmatter = `---\ntrigger: always_on\nalwaysApply: true\n---\n`;
if (await FileSystemUtils.fileExists(filePath)) {
// Update existing file: only update content between markers
await FileSystemUtils.updateFileWithMarkers(
filePath,
content,
OPENSPEC_MARKERS.start,
OPENSPEC_MARKERS.end
);
} else {
// Create new file: frontmatter + markers + content
const fullContent = `${frontmatter}\n${OPENSPEC_MARKERS.start}\n${content}\n${OPENSPEC_MARKERS.end}\n`;
await FileSystemUtils.writeFile(filePath, fullContent);
}
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/core/configurators/lingma.ts
Line: 37:61

Comment:
**logic:** Logic error causes file corruption on updates. After `updateFileWithMarkers` writes the file (line 46-51), the code reads it back and prepends frontmatter again (line 56-59). On subsequent runs, this creates duplicate frontmatter blocks.

Additionally, frontmatter is only added if file exists after the initial write, which is backwards - it should be added during initial creation.

Fix: Handle new files and updates separately, like `SlashCommandConfigurator` does (see `slash/base.ts:32-43`).

```suggestion
  async configure(projectPath: string, openspecDir: string): Promise<void> {
    const filePath = path.join(projectPath, this.configFileName);
    const content = TemplateManager.getAgentsStandardTemplate();
    const frontmatter = `---\ntrigger: always_on\nalwaysApply: true\n---\n`;

    if (await FileSystemUtils.fileExists(filePath)) {
      // Update existing file: only update content between markers
      await FileSystemUtils.updateFileWithMarkers(
        filePath,
        content,
        OPENSPEC_MARKERS.start,
        OPENSPEC_MARKERS.end
      );
    } else {
      // Create new file: frontmatter + markers + content
      const fullContent = `${frontmatter}\n${OPENSPEC_MARKERS.start}\n${content}\n${OPENSPEC_MARKERS.end}\n`;
      await FileSystemUtils.writeFile(filePath, fullContent);
    }
  }
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/core/configurators/lingma.ts`:
- Around line 53-60: The configure() logic currently prepends the
lingmaRulesTrigger every run causing duplicate frontmatter; update the code that
uses FileSystemUtils.readFile/fileExists and filePath to first read the file (if
exists) and check whether the content already begins with or contains the exact
lingmaRulesTrigger string before prepending—only call FileSystemUtils.writeFile
to add the trigger when it is missing (i.e., make the prepend idempotent by
checking existingContent.includes(lingmaRulesTrigger) or
startsWith(lingmaRulesTrigger) and skip writing if present).

Comment on lines +53 to +60
// Create trigger configuration for Lingma rules
const lingmaRulesTrigger = `---\ntrigger: always_on\nalwaysApply: true\n---\n`;
let existingContent = '';
if (await FileSystemUtils.fileExists(filePath)) {
existingContent = await FileSystemUtils.readFile(filePath);
existingContent = lingmaRulesTrigger + existingContent;
await FileSystemUtils.writeFile(filePath, existingContent);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Prevent duplicated trigger blocks on repeat runs.
configure() prepends the YAML trigger every time, so repeated runs will stack multiple frontmatter blocks (Line 54–59). This makes the file grow and can break Lingma parsing.

🛠️ Suggested fix (idempotent trigger prepend)
-    const lingmaRulesTrigger = `---\ntrigger: always_on\nalwaysApply: true\n---\n`;
-    let existingContent = '';
-    if (await FileSystemUtils.fileExists(filePath)) {
-      existingContent = await FileSystemUtils.readFile(filePath);
-      existingContent = lingmaRulesTrigger + existingContent;
-      await FileSystemUtils.writeFile(filePath, existingContent);
-    }
+    const lingmaRulesTrigger = `---\ntrigger: always_on\nalwaysApply: true\n---\n`;
+    if (await FileSystemUtils.fileExists(filePath)) {
+      const existingContent = await FileSystemUtils.readFile(filePath);
+      if (!existingContent.startsWith(lingmaRulesTrigger)) {
+        await FileSystemUtils.writeFile(filePath, lingmaRulesTrigger + existingContent);
+      }
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Create trigger configuration for Lingma rules
const lingmaRulesTrigger = `---\ntrigger: always_on\nalwaysApply: true\n---\n`;
let existingContent = '';
if (await FileSystemUtils.fileExists(filePath)) {
existingContent = await FileSystemUtils.readFile(filePath);
existingContent = lingmaRulesTrigger + existingContent;
await FileSystemUtils.writeFile(filePath, existingContent);
}
// Create trigger configuration for Lingma rules
const lingmaRulesTrigger = `---\ntrigger: always_on\nalwaysApply: true\n---\n`;
if (await FileSystemUtils.fileExists(filePath)) {
const existingContent = await FileSystemUtils.readFile(filePath);
if (!existingContent.startsWith(lingmaRulesTrigger)) {
await FileSystemUtils.writeFile(filePath, lingmaRulesTrigger + existingContent);
}
}
🤖 Prompt for AI Agents
In `@src/core/configurators/lingma.ts` around lines 53 - 60, The configure() logic
currently prepends the lingmaRulesTrigger every run causing duplicate
frontmatter; update the code that uses FileSystemUtils.readFile/fileExists and
filePath to first read the file (if exists) and check whether the content
already begins with or contains the exact lingmaRulesTrigger string before
prepending—only call FileSystemUtils.writeFile to add the trigger when it is
missing (i.e., make the prepend idempotent by checking
existingContent.includes(lingmaRulesTrigger) or startsWith(lingmaRulesTrigger)
and skip writing if present).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant