mirror of
https://github.com/github/spec-kit.git
synced 2026-07-06 05:53:12 +08:00
feat: add forge to PowerShell script and fix test whitespace
1. PowerShell script (create-release-packages.ps1):
- Added forge agent support for Windows users
- Enables `specify init --ai forge --offline` on Windows
- Enhanced Generate-Commands with ExtraStripKey parameter
- Added frontmatter stripping for handoffs key
- Added $ARGUMENTS replacement for {{parameters}}
- Implemented forge case with name field injection
- Complete parity with bash script
2. Test file (test_core_pack_scaffold.py):
- Removed trailing whitespace from blank lines
- Cleaner diffs and no linter warnings
Addresses Copilot PR feedback on both issues.
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
|
||||
.PARAMETER Agents
|
||||
Comma or space separated subset of agents to build (default: all)
|
||||
Valid agents: claude, gemini, copilot, cursor-agent, qwen, opencode, windsurf, junie, codex, kilocode, auggie, roo, codebuddy, amp, kiro-cli, bob, qodercli, shai, tabnine, agy, vibe, kimi, trae, pi, iflow, generic
|
||||
Valid agents: claude, gemini, copilot, cursor-agent, qwen, opencode, windsurf, junie, codex, kilocode, auggie, roo, codebuddy, amp, kiro-cli, bob, qodercli, shai, tabnine, agy, vibe, kimi, trae, pi, iflow, forge, generic
|
||||
|
||||
.PARAMETER Scripts
|
||||
Comma or space separated subset of script types to build (default: both)
|
||||
@@ -73,7 +73,8 @@ function Generate-Commands {
|
||||
[string]$Extension,
|
||||
[string]$ArgFormat,
|
||||
[string]$OutputDir,
|
||||
[string]$ScriptVariant
|
||||
[string]$ScriptVariant,
|
||||
[string]$ExtraStripKey = ""
|
||||
)
|
||||
|
||||
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
|
||||
@@ -137,7 +138,16 @@ function Generate-Commands {
|
||||
}
|
||||
|
||||
if ($inFrontmatter) {
|
||||
# Check for scripts/agent_scripts or extra strip key
|
||||
$shouldSkip = $false
|
||||
if ($line -match '^(scripts|agent_scripts):$') {
|
||||
$shouldSkip = $true
|
||||
}
|
||||
if (-not [string]::IsNullOrEmpty($ExtraStripKey) -and $line -match "^${ExtraStripKey}:") {
|
||||
$shouldSkip = $true
|
||||
}
|
||||
|
||||
if ($shouldSkip) {
|
||||
$skipScripts = $true
|
||||
continue
|
||||
}
|
||||
@@ -156,6 +166,7 @@ function Generate-Commands {
|
||||
|
||||
# Apply other substitutions
|
||||
$body = $body -replace '\{ARGS\}', $ArgFormat
|
||||
$body = $body -replace '\$ARGUMENTS', $ArgFormat
|
||||
$body = $body -replace '__AGENT__', $Agent
|
||||
$body = Rewrite-Paths -Content $body
|
||||
|
||||
@@ -477,6 +488,22 @@ function Build-Variant {
|
||||
$cmdDir = Join-Path $baseDir ".iflow/commands"
|
||||
Generate-Commands -Agent 'iflow' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
||||
}
|
||||
'forge' {
|
||||
$cmdDir = Join-Path $baseDir ".forge/commands"
|
||||
Generate-Commands -Agent 'forge' -Extension 'md' -ArgFormat '{{parameters}}' -OutputDir $cmdDir -ScriptVariant $Script -ExtraStripKey 'handoffs'
|
||||
|
||||
# Inject name field into frontmatter (forge requires name + description)
|
||||
$cmdFiles = Get-ChildItem -Path "$cmdDir/*.md" -File -ErrorAction SilentlyContinue
|
||||
foreach ($cmdFile in $cmdFiles) {
|
||||
$cmdName = [System.IO.Path]::GetFileNameWithoutExtension($cmdFile.Name)
|
||||
$content = Get-Content -Path $cmdFile.FullName -Raw
|
||||
|
||||
# Inject name field after first ---
|
||||
$content = $content -replace '(?m)^---$', "---`nname: $cmdName", 1
|
||||
|
||||
Set-Content -Path $cmdFile.FullName -Value $content -NoNewline
|
||||
}
|
||||
}
|
||||
'generic' {
|
||||
$cmdDir = Join-Path $baseDir ".speckit/commands"
|
||||
Generate-Commands -Agent 'generic' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
||||
@@ -493,7 +520,7 @@ function Build-Variant {
|
||||
}
|
||||
|
||||
# Define all agents and scripts
|
||||
$AllAgents = @('claude', 'gemini', 'copilot', 'cursor-agent', 'qwen', 'opencode', 'windsurf', 'junie', 'codex', 'kilocode', 'auggie', 'roo', 'codebuddy', 'amp', 'kiro-cli', 'bob', 'qodercli', 'shai', 'tabnine', 'agy', 'vibe', 'kimi', 'trae', 'pi', 'iflow', 'generic')
|
||||
$AllAgents = @('claude', 'gemini', 'copilot', 'cursor-agent', 'qwen', 'opencode', 'windsurf', 'junie', 'codex', 'kilocode', 'auggie', 'roo', 'codebuddy', 'amp', 'kiro-cli', 'bob', 'qodercli', 'shai', 'tabnine', 'agy', 'vibe', 'kimi', 'trae', 'pi', 'iflow', 'forge', 'generic')
|
||||
$AllScripts = @('sh', 'ps')
|
||||
|
||||
function Normalize-List {
|
||||
|
||||
@@ -466,12 +466,12 @@ def test_markdown_has_frontmatter(agent, scaffolded_sh):
|
||||
|
||||
def test_forge_name_field_in_frontmatter(scaffolded_sh):
|
||||
"""Forge: every command file must have a 'name' field in frontmatter that matches the filename.
|
||||
|
||||
|
||||
Forge requires both 'name' and 'description' fields in command frontmatter.
|
||||
This test ensures the release script's name injection is working correctly.
|
||||
"""
|
||||
project = scaffolded_sh("forge")
|
||||
|
||||
|
||||
cmd_dir = _expected_cmd_dir(project, "forge")
|
||||
for f in _list_command_files(cmd_dir, "forge"):
|
||||
content = f.read_text(encoding="utf-8")
|
||||
@@ -482,13 +482,13 @@ def test_forge_name_field_in_frontmatter(scaffolded_sh):
|
||||
assert len(parts) >= 3, f"Incomplete frontmatter in '{f.name}'"
|
||||
fm = yaml.safe_load(parts[1])
|
||||
assert fm is not None, f"Empty frontmatter in '{f.name}'"
|
||||
|
||||
|
||||
# Check that 'name' field exists
|
||||
assert "name" in fm, (
|
||||
f"'name' key missing from frontmatter in '{f.name}' - "
|
||||
f"Forge requires both 'name' and 'description' fields"
|
||||
)
|
||||
|
||||
|
||||
# Check that name matches the filename (without extension)
|
||||
expected_name = f.name.removesuffix(".md")
|
||||
actual_name = fm["name"]
|
||||
|
||||
Reference in New Issue
Block a user