param(
  [string]$ProjectRoot = "",
  [switch]$AsJson
)

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

if ([string]::IsNullOrWhiteSpace($ProjectRoot)) {
  $ProjectRoot = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot "..\..\..\.."))
}

function New-Issue {
  param(
    [string]$Severity,
    [string]$File,
    [string]$Section,
    [string]$Message
  )

  [PSCustomObject]@{
    severity = $Severity
    file = $File
    section = $Section
    message = $Message
  }
}

function Get-FileContentOrNull {
  param([string]$Path)

  if (-not (Test-Path -LiteralPath $Path)) {
    return $null
  }

  Get-Content -LiteralPath $Path -Raw
}

function Resolve-FirstExistingPath {
  param([string[]]$Candidates)

  foreach ($candidate in $Candidates) {
    if (Test-Path -LiteralPath $candidate) {
      return $candidate
    }
  }

  return $null
}

function Test-ContainsAll {
  param(
    [string]$Content,
    [string[]]$Terms
  )

  foreach ($term in $Terms) {
    if ($Content -notmatch [regex]::Escape($term)) {
      return $false
    }
  }

  return $true
}

$issues = @()

$taskSchemaPath = Resolve-FirstExistingPath -Candidates @(
  (Join-Path $ProjectRoot "docs\harness\task.schema.json"),
  (Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\runtime\task.schema.json")
)
$traceSchemaPath = Resolve-FirstExistingPath -Candidates @(
  (Join-Path $ProjectRoot "docs\harness\trace.schema.json"),
  (Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\trace\trace.schema.json")
)
$featureTaskTemplatePath = Resolve-FirstExistingPath -Candidates @(
  (Join-Path $ProjectRoot "tools\harness\templates\feature-task-reference.json"),
  (Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\runtime\feature-task-reference.json")
)
$projectTaskTemplatePath = Resolve-FirstExistingPath -Candidates @(
  (Join-Path $ProjectRoot "tools\harness\templates\project-task-template.json"),
  (Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\runtime\project-task-template.json")
)
$implementPromptPath = Resolve-FirstExistingPath -Candidates @(
  (Join-Path $ProjectRoot ".codex\prompts\implement-one-task.md"),
  (Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\prompts\implement-one-task.md")
)
$stage1PromptPath = Resolve-FirstExistingPath -Candidates @(
  (Join-Path $ProjectRoot ".codex\prompts\review-stage1-spec.md"),
  (Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\prompts\review-stage1-spec.md")
)
$stage2PromptPath = Resolve-FirstExistingPath -Candidates @(
  (Join-Path $ProjectRoot ".codex\prompts\review-stage2-quality.md"),
  (Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\prompts\review-stage2-quality.md")
)
$driverPath = Resolve-FirstExistingPath -Candidates @(
  (Join-Path $ProjectRoot "tools\harness\codex-loop.ps1"),
  (Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\runtime\codex-loop.ps1")
)
$verifyPath = Resolve-FirstExistingPath -Candidates @(
  (Join-Path $ProjectRoot "tools\harness\verify.ps1"),
  (Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\runtime\verify.ps1")
)

$taskSchema = Get-FileContentOrNull -Path $taskSchemaPath
if ($null -eq $taskSchema -or -not (Test-ContainsAll -Content $taskSchema -Terms @('"implementationPlanSummary"', '"implementation_plan_summary"', '"standard"', '"deep"', '"critical"'))) {
  $issues += New-Issue -Severity "error" -File "docs/harness/task.schema.json" -Section "schema" -Message "task schema 没有把 implementation_plan_summary 做成标准深度任务的结构化合同。"
}

$traceSchema = Get-FileContentOrNull -Path $traceSchemaPath
if ($null -eq $traceSchema -or -not (Test-ContainsAll -Content $traceSchema -Terms @('"implementation_plan_summary"', '"files_to_modify"', '"documentation_update_plan"', '"out_of_scope_items"', '"implementation_plan"'))) {
  $issues += New-Issue -Severity "error" -File "docs/harness/trace.schema.json" -Section "trace" -Message "trace schema 没有记录 implementation_plan_summary 或 depth_protocol.implementation_plan。"
}

$featureTaskTemplate = Get-FileContentOrNull -Path $featureTaskTemplatePath
if ($null -eq $featureTaskTemplate -or -not (Test-ContainsAll -Content $featureTaskTemplate -Terms @('"implementation_plan_summary"', '"files_to_modify"', '"documentation_update_plan"', '"split_recommendation"', '"human_approval_requirement"', '"out_of_scope_items"', '"implementation_plan": true'))) {
  $issues += New-Issue -Severity "error" -File "tools/harness/templates/feature-task-reference.json" -Section "template" -Message "feature task 模板没有完整定义 implementation_plan_summary 或 depth_protocol.implementation_plan。"
}

$projectTaskTemplate = Get-FileContentOrNull -Path $projectTaskTemplatePath
if ($null -eq $projectTaskTemplate -or -not (Test-ContainsAll -Content $projectTaskTemplate -Terms @('"implementation_plan_summary"', '"files_to_modify"', '"documentation_update_plan"', '"out_of_scope_items"'))) {
  $issues += New-Issue -Severity "error" -File "tools/harness/templates/project-task-template.json" -Section "template" -Message "project task 模板没有为 standard/deep/critical 任务补 implementation_plan_summary。"
}

$implementPrompt = Get-FileContentOrNull -Path $implementPromptPath
if ($null -eq $implementPrompt -or -not (Test-ContainsAll -Content $implementPrompt -Terms @("### Phase 4: Implementation Plan", "Implementation Plan Summary", "documentation update plan", "split recommendation", "human approval requirement", "out-of-scope items"))) {
  $issues += New-Issue -Severity "error" -File ".codex/prompts/implement-one-task.md" -Section "prompt" -Message "implement prompt 没有把结构化 Implementation Plan 阶段做成实现前必答项。"
}

$stage1Prompt = Get-FileContentOrNull -Path $stage1PromptPath
if ($null -eq $stage1Prompt -or -not (Test-ContainsAll -Content $stage1Prompt -Terms @("implementation_plan_summary", "Implementation Plan Summary", "planning_gap"))) {
  $issues += New-Issue -Severity "error" -File ".codex/prompts/review-stage1-spec.md" -Section "prompt" -Message "Stage 1 prompt 缺少 implementation plan 合同或 planning_gap 审查。"
}

$stage2Prompt = Get-FileContentOrNull -Path $stage2PromptPath
if ($null -eq $stage2Prompt -or -not (Test-ContainsAll -Content $stage2Prompt -Terms @("Implementation Plan Summary", "changed files", "files not to modify", "human approval requirement", "implementation_plan_summary"))) {
  $issues += New-Issue -Severity "error" -File ".codex/prompts/review-stage2-quality.md" -Section "prompt" -Message "Stage 2 prompt 缺少计划与实际 diff 对齐检查。"
}

$driver = Get-FileContentOrNull -Path $driverPath
if ($null -eq $driver -or -not (Test-ContainsAll -Content $driver -Terms @('implementation_plan_summary', 'Get-MarkdownSectionBody', 'Implementation Plan Contract', 'Changed Files', 'Add-Member -InputObject $Trace -MemberType NoteProperty -Name "implementation_plan_summary"'))) {
  $issues += New-Issue -Severity "error" -File "tools/harness/codex-loop.ps1" -Section "runtime" -Message "driver 没有把 implementation plan 注入 review 或 trace。"
}

$verify = Get-FileContentOrNull -Path $verifyPath
if ($null -eq $verify -or -not (Test-ContainsAll -Content $verify -Terms @("Invoke-ImplementationPlanValidation", "implementation-plan-lint.ps1"))) {
  $issues += New-Issue -Severity "error" -File "tools/harness/verify.ps1" -Section "verify" -Message "verify 没有接入 implementation-plan-lint。"
}

$errors = @($issues | Where-Object { $_.severity -eq "error" })
$warnings = @($issues | Where-Object { $_.severity -eq "warning" })
$exitCode = if ($errors.Count -gt 0) { 1 } elseif ($warnings.Count -gt 0) { 2 } else { 0 }

if ($AsJson) {
  [PSCustomObject]@{
    ok = ($exitCode -eq 0)
    errors = $errors
    warnings = $warnings
  } | ConvertTo-Json -Depth 6
  exit $exitCode
}

if ($errors.Count -eq 0 -and $warnings.Count -eq 0) {
  Write-Output "Implementation plan lint passed."
  exit 0
}

if ($errors.Count -gt 0) {
  Write-Output "Implementation plan lint failed."
  foreach ($issue in $errors) {
    Write-Output ("- [ERROR] {0} :: {1} :: {2}" -f $issue.file, $issue.section, $issue.message)
  }
}

if ($warnings.Count -gt 0) {
  if ($errors.Count -eq 0) {
    Write-Output "Implementation plan lint passed with warnings."
  }
  foreach ($issue in $warnings) {
    Write-Output ("- [WARNING] {0} :: {1} :: {2}" -f $issue.file, $issue.section, $issue.message)
  }
}

exit $exitCode
