refactor: make ForgeIntegration extend MarkdownIntegration

- Change base class from IntegrationBase to MarkdownIntegration
- Eliminates ~30 lines of duplicated validation/setup boilerplate
- Aligns with the pattern used by 20+ other markdown agents (Bob, Claude, Windsurf, etc.)
- Update AGENTS.md to reflect new inheritance hierarchy
- All Forge-specific processing retained ({{parameters}}, handoffs stripping, name injection)
- All 535 integration tests pass

This addresses reviewer feedback about using the MarkdownIntegration convenience base class.
This commit is contained in:
ericnoam
2026-04-02 15:56:16 +02:00
parent 1294d43c24
commit 7d06021989
2 changed files with 21 additions and 18 deletions

View File

@@ -449,11 +449,12 @@ Forge has special frontmatter and argument requirements:
- Strips `handoffs` frontmatter key (Forge-specific collaboration feature)
- Injects `name` field into frontmatter when missing
Implementation: Extends `IntegrationBase` with custom `setup()` method that:
1. Processes templates with `process_template()` using `{{parameters}}`
2. Applies Forge-specific transformations via `_apply_forge_transformations()`
3. Strips unwanted frontmatter keys
4. Injects missing `name` fields
Implementation: Extends `MarkdownIntegration` with custom `setup()` method that:
1. Inherits standard template processing from `MarkdownIntegration`
2. Adds extra `$ARGUMENTS``{{parameters}}` replacement after template processing
3. Applies Forge-specific transformations via `_apply_forge_transformations()`
4. Strips `handoffs` frontmatter key
5. Injects missing `name` fields
### Standard Markdown Agents

View File

@@ -11,12 +11,18 @@ from __future__ import annotations
from pathlib import Path
from typing import Any
from ..base import IntegrationBase
from ..base import MarkdownIntegration
from ..manifest import IntegrationManifest
class ForgeIntegration(IntegrationBase):
"""Integration for Forge (forgecode.dev)."""
class ForgeIntegration(MarkdownIntegration):
"""Integration for Forge (forgecode.dev).
Extends MarkdownIntegration to add Forge-specific processing:
- Replaces $ARGUMENTS with {{parameters}}
- Strips 'handoffs' frontmatter key
- Injects 'name' field into frontmatter when missing
"""
key = "forge"
config = {
@@ -45,12 +51,8 @@ class ForgeIntegration(IntegrationBase):
) -> list[Path]:
"""Install Forge commands with custom processing.
Processes command templates similarly to MarkdownIntegration but with
Forge-specific transformations:
1. Replaces {SCRIPT} and {ARGS} placeholders
2. Strips 'handoffs' frontmatter key
3. Injects 'name' field into frontmatter
4. Uses {{parameters}} instead of $ARGUMENTS
Extends MarkdownIntegration.setup() to inject Forge-specific transformations
after standard template processing.
"""
templates = self.list_command_templates()
if not templates:
@@ -79,14 +81,14 @@ class ForgeIntegration(IntegrationBase):
for src_file in templates:
raw = src_file.read_text(encoding="utf-8")
# Process template with Forge-specific argument placeholder
# Process template with standard MarkdownIntegration logic
processed = self.process_template(raw, self.key, script_type, arg_placeholder)
# Ensure any remaining $ARGUMENTS placeholders are converted to the
# Forge argument placeholder ({{parameters}} by default)
# FORGE-SPECIFIC: Ensure any remaining $ARGUMENTS placeholders are
# converted to {{parameters}}
processed = processed.replace("$ARGUMENTS", arg_placeholder)
# Apply Forge-specific transformations
# FORGE-SPECIFIC: Apply frontmatter transformations
processed = self._apply_forge_transformations(processed, src_file.stem)
dst_name = self.command_filename(src_file.stem)