Closing the intent-to-code chasm - specification-driven development with BDD verification chain
Overall
score
96%
Does it follow best practices?
Validation for skill structure
#!/usr/bin/env pwsh <# .SYNOPSIS Update agent context files with information from plan.md (PowerShell version)
.DESCRIPTION Mirrors the behavior of scripts/bash/update-agent-context.sh:
.PARAMETER AgentType Optional agent key to update a single agent. If omitted, updates all existing agent files (creating a default Claude file if none exist).
.EXAMPLE ./update-agent-context.ps1 -AgentType claude
.EXAMPLE ./update-agent-context.ps1 # Updates all existing agent files
.NOTES Relies on common helper functions in common.ps1 #> param( [Parameter(Position=0)] [ValidateSet('claude','gemini','codex','opencode')] [string]$AgentType )
$ErrorActionPreference = 'Stop'
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path . (Join-Path $ScriptDir 'common.ps1')
$repoRoot = Get-RepoRoot $hasGit = Test-HasGit $currentBranch = Get-CurrentBranch $branchResult = Test-FeatureBranch -Branch $currentBranch -HasGit $hasGit if ($branchResult -eq "NEEDS_SELECTION") { Write-Host "ERROR: Multiple features exist. Run: /iikit-core use <feature> to select one." -ForegroundColor Red exit 2 } elseif ($branchResult -eq "ERROR") { exit 1 }
$envData = Get-FeaturePathsEnv $REPO_ROOT = $envData.REPO_ROOT $CURRENT_BRANCH = $envData.CURRENT_BRANCH $HAS_GIT = $envData.HAS_GIT $IMPL_PLAN = $envData.IMPL_PLAN $NEW_PLAN = $IMPL_PLAN
$CLAUDE_FILE = Join-Path $REPO_ROOT 'CLAUDE.md' $GEMINI_FILE = Join-Path $REPO_ROOT 'GEMINI.md' $AGENTS_FILE = Join-Path $REPO_ROOT 'AGENTS.md'
$TEMPLATE_FILE = Join-Path $PSScriptRoot '....\templates\agent-file-template.md'
$script:NEW_LANG = '' $script:NEW_FRAMEWORK = '' $script:NEW_DB = '' $script:NEW_PROJECT_TYPE = ''
function Write-Info { param( [Parameter(Mandatory=$true)] [string]$Message ) Write-Host "INFO: $Message" }
function Write-Success { param( [Parameter(Mandatory=$true)] [string]$Message ) Write-Host "SUCCESS: $Message" }
function Write-WarningMsg { param( [Parameter(Mandatory=$true)] [string]$Message ) Write-Warning $Message }
function Write-Err { param( [Parameter(Mandatory=$true)] [string]$Message ) Write-Host "ERROR: $Message" -ForegroundColor Red }
function Validate-Environment { if (-not $CURRENT_BRANCH) { Write-Err 'Unable to determine current feature' if ($HAS_GIT) { Write-Info "Make sure you're on a feature branch" } else { Write-Info 'Run /iikit-core use <feature> or create a new feature first' } exit 1 } if (-not (Test-Path $NEW_PLAN)) { Write-Err "No plan.md found at $NEW_PLAN" Write-Info 'Ensure you are working on a feature with a corresponding spec directory' if (-not $HAS_GIT) { Write-Info 'Run /iikit-core use <feature> or create a new feature first' } exit 1 } if (-not (Test-Path $TEMPLATE_FILE)) { Write-Err "Template file not found at $TEMPLATE_FILE" Write-Info 'Run /iikit-core init to initialize intent-integrity-kit, or add agent-file-template.md to .claude/skills/iikit-core/templates/.' exit 1 } }
function Extract-PlanField { param( [Parameter(Mandatory=$true)] [string]$FieldPattern, [Parameter(Mandatory=$true)] [string]$PlanFile ) if (-not (Test-Path $PlanFile)) { return '' } # Lines like Language/Version: Python 3.12 $regex = "^**$([Regex]::Escape($FieldPattern))**: (.+)$" Get-Content -LiteralPath $PlanFile -Encoding utf8 | ForEach-Object { if ($_ -match $regex) { $val = $Matches[1].Trim() if ($val -notin @('NEEDS CLARIFICATION','N/A')) { return $val } } } | Select-Object -First 1 }
function Parse-PlanData { param( [Parameter(Mandatory=$true)] [string]$PlanFile ) if (-not (Test-Path $PlanFile)) { Write-Err "Plan file not found: $PlanFile"; return $false } Write-Info "Parsing plan data from $PlanFile" $script:NEW_LANG = Extract-PlanField -FieldPattern 'Language/Version' -PlanFile $PlanFile $script:NEW_FRAMEWORK = Extract-PlanField -FieldPattern 'Primary Dependencies' -PlanFile $PlanFile $script:NEW_DB = Extract-PlanField -FieldPattern 'Storage' -PlanFile $PlanFile $script:NEW_PROJECT_TYPE = Extract-PlanField -FieldPattern 'Project Type' -PlanFile $PlanFile
if ($NEW_LANG) { Write-Info "Found language: $NEW_LANG" } else { Write-WarningMsg 'No language information found in plan' }
if ($NEW_FRAMEWORK) { Write-Info "Found framework: $NEW_FRAMEWORK" }
if ($NEW_DB -and $NEW_DB -ne 'N/A') { Write-Info "Found database: $NEW_DB" }
if ($NEW_PROJECT_TYPE) { Write-Info "Found project type: $NEW_PROJECT_TYPE" }
return $true}
function Format-TechnologyStack { param( [Parameter(Mandatory=$false)] [string]$Lang, [Parameter(Mandatory=$false)] [string]$Framework ) $parts = @() if ($Lang -and $Lang -ne 'NEEDS CLARIFICATION') { $parts += $Lang } if ($Framework -and $Framework -notin @('NEEDS CLARIFICATION','N/A')) { $parts += $Framework } if (-not $parts) { return '' } return ($parts -join ' + ') }
function Get-ProjectStructure {
param(
[Parameter(Mandatory=$false)]
[string]$ProjectType
)
if ($ProjectType -match 'web') { return "backend/nfrontend/ntests/" } else { return "src/`ntests/" }
}
function Get-CommandsForLanguage { param( [Parameter(Mandatory=$false)] [string]$Lang ) switch -Regex ($Lang) { 'Python' { return "cd src; pytest; ruff check ." } 'Rust' { return "cargo test; cargo clippy" } 'JavaScript|TypeScript' { return "npm test; npm run lint" } default { return "# Add commands for $Lang" } } }
function New-AgentFile { param( [Parameter(Mandatory=$true)] [string]$TargetFile, [Parameter(Mandatory=$true)] [string]$ProjectName, [Parameter(Mandatory=$true)] [datetime]$Date ) if (-not (Test-Path $TEMPLATE_FILE)) { Write-Err "Template not found at $TEMPLATE_FILE"; return $false } $temp = New-TemporaryFile Copy-Item -LiteralPath $TEMPLATE_FILE -Destination $temp -Force
$projectStructure = Get-ProjectStructure -ProjectType $NEW_PROJECT_TYPE
$commands = Get-CommandsForLanguage -Lang $NEW_LANG
$escaped_lang = $NEW_LANG
$escaped_framework = $NEW_FRAMEWORK
$escaped_branch = $CURRENT_BRANCH
$content = Get-Content -LiteralPath $temp -Raw -Encoding utf8
$content = $content -replace '\[PROJECT NAME\]',$ProjectName
$content = $content -replace '\[DATE\]',$Date.ToString('yyyy-MM-dd')
# Build the technology stack string safely
$techStackForTemplate = ""
if ($escaped_lang -and $escaped_framework) {
$techStackForTemplate = "- $escaped_lang + $escaped_framework ($escaped_branch)"
} elseif ($escaped_lang) {
$techStackForTemplate = "- $escaped_lang ($escaped_branch)"
} elseif ($escaped_framework) {
$techStackForTemplate = "- $escaped_framework ($escaped_branch)"
}
$content = $content -replace '\[EXTRACTED FROM ALL PLAN.MD FILES\]',$techStackForTemplate
# For project structure we manually embed (keep newlines)
$escapedStructure = [Regex]::Escape($projectStructure)
$content = $content -replace '\[ACTUAL STRUCTURE FROM PLANS\]',$escapedStructure
# Replace escaped newlines placeholder after all replacements
$content = $content -replace '\[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]',$commands
# Build the recent changes string safely
$recentChangesForTemplate = ""
if ($escaped_lang -and $escaped_framework) {
$recentChangesForTemplate = "- ${escaped_branch}: Added ${escaped_lang} + ${escaped_framework}"
} elseif ($escaped_lang) {
$recentChangesForTemplate = "- ${escaped_branch}: Added ${escaped_lang}"
} elseif ($escaped_framework) {
$recentChangesForTemplate = "- ${escaped_branch}: Added ${escaped_framework}"
}
$content = $content -replace '\[LAST 3 FEATURES AND WHAT THEY ADDED\]',$recentChangesForTemplate
# Convert literal \n sequences introduced by Escape to real newlines
$content = $content -replace '\\n',[Environment]::NewLine
$parent = Split-Path -Parent $TargetFile
if (-not (Test-Path $parent)) { New-Item -ItemType Directory -Path $parent | Out-Null }
Set-Content -LiteralPath $TargetFile -Value $content -NoNewline -Encoding utf8
Remove-Item $temp -Force
return $true}
function Update-AgentFile { param( [Parameter(Mandatory=$true)] [string]$TargetFile, [Parameter(Mandatory=$true)] [string]$AgentName ) if (-not $TargetFile -or -not $AgentName) { Write-Err 'Update-AgentFile requires TargetFile and AgentName'; return $false } Write-Info "Updating $AgentName context file: $TargetFile" $projectName = Split-Path $REPO_ROOT -Leaf $date = Get-Date
$dir = Split-Path -Parent $TargetFile
if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir | Out-Null }
if (-not (Test-Path $TargetFile)) {
if (New-AgentFile -TargetFile $TargetFile -ProjectName $projectName -Date $date) {
Write-Success "Created new $AgentName context file"
} else {
Write-Err 'Failed to create new agent file'
return $false
}
} else {
Write-Info "Agent file already exists at $TargetFile"
Write-Success "Updated existing $AgentName context file"
}
return $true}
function Update-SpecificAgent { param( [Parameter(Mandatory=$true)] [string]$Type ) switch ($Type) { 'claude' { Update-AgentFile -TargetFile $CLAUDE_FILE -AgentName 'Claude Code' } 'gemini' { Update-AgentFile -TargetFile $GEMINI_FILE -AgentName 'Gemini CLI' } 'opencode' { Update-AgentFile -TargetFile $AGENTS_FILE -AgentName 'opencode' } 'codex' { Update-AgentFile -TargetFile $AGENTS_FILE -AgentName 'Codex CLI' } default { Write-Err "Unknown agent type '$Type'"; Write-Err 'Expected: claude|gemini|codex|opencode'; return $false } } }
function Update-AllExistingAgents { $found = $false $ok = $true if (Test-Path $CLAUDE_FILE) { if (-not (Update-AgentFile -TargetFile $CLAUDE_FILE -AgentName 'Claude Code')) { $ok = $false }; $found = $true } if (Test-Path $GEMINI_FILE) { if (-not (Update-AgentFile -TargetFile $GEMINI_FILE -AgentName 'Gemini CLI')) { $ok = $false }; $found = $true } if (Test-Path $AGENTS_FILE) { if (-not (Update-AgentFile -TargetFile $AGENTS_FILE -AgentName 'Codex/opencode')) { $ok = $false }; $found = $true } if (-not $found) { Write-Info 'No existing agent files found, creating default Claude file...' if (-not (Update-AgentFile -TargetFile $CLAUDE_FILE -AgentName 'Claude Code')) { $ok = $false } } return $ok }
function Main { Validate-Environment Write-Info "=== Updating agent context files for feature $CURRENT_BRANCH ===" if (-not (Parse-PlanData -PlanFile $NEW_PLAN)) { Write-Err 'Failed to parse plan data'; exit 1 } $success = $true if ($AgentType) { Write-Info "Updating specific agent: $AgentType" if (-not (Update-SpecificAgent -Type $AgentType)) { $success = $false } } else { Write-Info 'No agent specified, updating all existing agent files...' if (-not (Update-AllExistingAgents)) { $success = $false } } if ($success) { Write-Success 'Agent context update completed successfully'; exit 0 } else { Write-Err 'Agent context update completed with errors'; exit 1 } }
Main
Install with Tessl CLI
npx tessl i tessl-labs/intent-integrity-kit@2.3.5rules
skills
iikit-00-constitution
scripts
iikit-01-specify
iikit-02-clarify
iikit-03-plan
iikit-04-checklist
scripts
dashboard
iikit-05-testify
iikit-06-tasks
iikit-07-analyze
iikit-08-implement
iikit-09-taskstoissues
iikit-bugfix
scripts
iikit-core
scripts
bash
dashboard
powershell