<# .SYNOPSIS spawn-model-audit.ps1 - H23 PA-2b: spawn-model audit, resolved-vs-expected. INFORMATIONAL. .DESCRIPTION Owner-decision S119 PA-2 (runs/2026-07-15-S119-adap-6-broadcast/owner-decisions-15-07-2026.md:59-60) splits "anchor the model version" in two, because anchoring AT SPAWN is NOT possible at SE (the spawn param takes an enum alias only; SE has 0 full-id in any definition file - H8 all-inherit): PA-2a .claude/workflows/hmw.js declares TIER2_EXPECTED_FULL_ID (value lives ONLY there - single-source, do NOT copy it here; stale copy 'claude-opus-4-8' fixed S150). PA-2b THIS script compares the model actually RESOLVED at spawn against that constant. Drift => print FLAG => owner decides re-pin. NO enforcement (H23 section 2(4)). Design rules (mirror scripts/governance-detectors.ps1): (1) NO-API - reads files only. NEVER calls a model/API. (2) FLAG-only - prints FLAGs, NEVER edits files. (3) PowerShell 5.1, offline. ASCII-only script body (gotcha #30); target files read -Encoding UTF8. (4) DETECT-only. Exit code ALWAYS 0 (audit/inform, never a build gate). --------------------------------------------------------------------------- MEASURABLE vs NOT-MEASURABLE - read before trusting any line of this report --------------------------------------------------------------------------- MEASURED (this script really reads it, offline, from disk): * expected = the TIER2_EXPECTED_FULL_ID constant in hmw.js [section A] * resolved = "message":{"model":"..."} in the per-lane spawn transcripts ///subagents/workflows/wf_*/agent-*.jsonl Verified present S119: 9 lanes 'claude-opus-4-8' + 2 lanes 'claude-fable-5'. [section B] NOT MEASURABLE HERE - declared, never silently passed: (i) FORWARD drift. This audit is RETROSPECTIVE: it reads what ALREADY resolved in recorded runs. It cannot pre-verify what the NEXT spawn will resolve to. A clean report does NOT promise the next spawn stays on the expected version. This is exactly why H23 section 2(4) makes it informational, not enforcement. (ii) PRECEDENCE vs a frontmatter HARD-PIN - MEASURED at SE 2026-07-16 (S126), after S124 re-pinned all 14 agents THEN-EXISTING to 'model: opus' (ALIAS pin; roster is 17 as of S141 - this measurement was taken when N was 14 and was NOT re-run for the 3 new ones): spawn param 'fable' on agentType reviewer (pin 'opus') RESOLVED claude-fable-5 (run wf_f960dae2-fa0, 3 records); a control lane with NO override resolved claude-opus-4-8 under lead=Fable => the pin itself works at runtime AND the spawn param BEATS it. Caveats: alias-pin only (the hub form pins FULL-ID 'claude-opus-4-8' 17/17 - NOT covered by this measurement); retrospective - says nothing about future spawns. Older 'inherit' evidence: below. (iii)Whether the spawn param REJECTS a full-id (fix #8a). Per harness docs the param is an enum alias (sonnet|opus|haiku|fable); passing a full-id has NEVER been tried. Not tried here. (iv) Documentation coverage. This measures EXPLICITNESS IN TRANSCRIPTS only. A clean report must NOT be read as "the floor is fully applied" (owner-decisions:65, honesty declaration 3). PRECEDENCE - spawn-param vs frontmatter 'inherit': MEASURED 2026-07-15, no longer "never tested". Spec v2:271 recorded this as CHUA TUNG DUOC TEST, reasoning that a discriminating experiment needs lead=Fable. That reasoning only covered the tier:'opus' direction. The discriminating condition is simply spawn-param family != lead family - and the tier:'fable' direction satisfies it under lead=Opus. It ALREADY RAN, unplanned, in run wf_cb964f83-331: lead model = claude-opus-4-8 (290/290 records, session 3d9bec56, zero Fable) agentType = reviewer (.claude/agents/reviewer.md:5 = 'model: inherit') spawn param = fable (/fable-real escape-hatch, hmw.js:44 returns the alias) RESOLVED = claude-fable-5 (2/2 lanes, 39 + 42 assistant records) If frontmatter 'inherit' had won, resolved would be the lead's claude-opus-4-8. It was not. => the spawn param TAKES EFFECT on a frontmatter-'inherit' agent => the GAP#6 fix is NOT a no-op. HONEST LIMIT: this does not prove 'inherit' LOSES a precedence contest. 'inherit' may simply mean "defer to the caller", in which case there is no contest at all. Both readings give the same operative answer (the param takes effect); this data cannot separate them, and does not try. UPDATE 2026-07-16 (S126): the hard-pin contest HAS now been measured - see NOT-MEASURABLE (ii) above, which flipped to MEASURED. Param 'fable' beat frontmatter 'model: opus' on a real lane. .PARAMETER RepoRoot Repo root. Default = 2 levels up from this script (scripts/ -> repo root). Every path derives from this, so -RepoRoot makes fault-injection possible. .PARAMETER TranscriptRoot Root of the CLI project transcripts. Default derives from $env:USERPROFILE (NOT a hardcoded absolute path). The per-project folder name is derived from $RepoRoot, so a fault-inject tree resolves to a slug with no transcripts and section B reports NO-SCOPE instead of faking a number. .PARAMETER SessionId Audit one specific session folder. Default = most recent session that HAS spawn transcripts. Default-to-current is deliberate: scanning old history surfaces pre-convention runs, which is noise, not a bug storm (owner-decisions:64, honesty declaration 2). .EXAMPLE powershell.exe -ExecutionPolicy Bypass -File scripts/spawn-model-audit.ps1 #> param( [string]$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path, [string]$TranscriptRoot = (Join-Path $env:USERPROFILE '.claude\projects'), [string]$SessionId = '' ) $ErrorActionPreference = 'Continue' # --------------------------------------------------------------------------- # Owner-ratified expectation (S119 PA-2a, owner-decisions-15-07-2026.md:59). # Deliberate 2-key design: the expected version is declared TWICE - once in hmw.js (PA-2a) and # once here - so that a unilateral edit of ONE of them is FLAGGED instead of passing silently. # Cost, stated plainly: an owner re-pin must touch BOTH files. That cost IS the check. # NOT a fallback: if hmw.js has no constant, section A fails loud - it never borrows this value. # --------------------------------------------------------------------------- # 🔄 VALUE-update 2026-07-25 (broadcast model-default-opus-5-max sha 59ce1d0f + SE-owner "dam Opus 5 MAX"): # 'claude-opus-4-8' -> 'claude-opus-5'. Khoan 1.4: records cu mang 'claude-opus-4-8*' = LEGACY bucket # trong giai doan chuyen tiep — dem rieng, KHONG co drift (tranh bao canh bao gia tren ban ghi cu). # 2-key: doi DONG THOI voi TIER2_EXPECTED_FULL_ID trong .claude/workflows/hmw.js (cung commit). $OWNER_RATIFIED_TIER2_FULL_ID = 'claude-opus-5' $TIER2_LEGACY_FULL_ID = 'claude-opus-4-8' # Family that the 'opus' alias maps to. Alias locks the FAMILY, not the version (H23 section 2(2)): # same family + different version = the drift this audit exists to catch. $TIER2_FAMILY_PREFIX = 'claude-opus-' # --------------------------------------------------------------------------- # Helpers (shape mirrors scripts/governance-detectors.ps1:43-67) # --------------------------------------------------------------------------- $script:FlagCount = 0 function Write-Flag { param( [ValidateSet('HIGH', 'MED', 'LOW')] [string]$Severity, [string]$Where, [string]$Desc, [string]$Resolve ) $color = switch ($Severity) { 'HIGH' { 'Red' } 'MED' { 'Yellow' } default { 'Gray' } } Write-Host ("[SPAWN-AUDIT] {0,-4} | {1} | {2} | resolve: {3}" -f $Severity, $Where, $Desc, $Resolve) -ForegroundColor $color $script:FlagCount++ } function Write-Section($title) { Write-Host '' Write-Host ("===== $title =====") -ForegroundColor Cyan } function Rel($full) { $r = $full if ($full.StartsWith($RepoRoot, [StringComparison]::OrdinalIgnoreCase)) { $r = $full.Substring($RepoRoot.Length).TrimStart('\', '/') } return ($r -replace '\\', '/') } Write-Host '' Write-Host '########## spawn-model-audit.ps1 - H23 PA-2b (INFORMATIONAL, exit 0 always) ##########' -ForegroundColor Cyan Write-Host ("RepoRoot: {0}" -f $RepoRoot) -ForegroundColor DarkGray # =========================================================================== # SECTION A - PA-2a: the EXPECTED constant in hmw.js (STATIC, measurable) # =========================================================================== Write-Section 'A - expected constant (PA-2a, hmw.js)' $hmwPath = Join-Path $RepoRoot '.claude\workflows\hmw.js' $expected = $null if (-not (Test-Path $hmwPath)) { Write-Flag 'HIGH' (Rel $hmwPath) 'hmw.js not found - cannot resolve the expected model version' ` 'run from a repo root that contains .claude/workflows/hmw.js' } else { # STRUCTURAL anchor, NOT a loose string grep (W0.4 lesson 1 - self-reference). # Capture the VALUE of the assignment. A bare grep for the version string is NOT acceptable # evidence here: hmw.js also carries the expected literal inside COMMENT text (measured S150: # naive grep = 2 hits, both comments), so a naive grep returns >=1 hit and passes VACUOUSLY # even when the constant is absent or holds a wrong value. (Old line-pinned example # 'hmw.js:36 demote-pin' died in an edit - keep this description line-number-free, S150.) # The naive count is printed below as a counter-example only - it is never used as evidence. $RX_CONST = 'TIER2_EXPECTED_FULL_ID\s*=\s*[''"]([^''"]+)[''"]' $constHits = @(Select-String -Path $hmwPath -Pattern $RX_CONST -Encoding UTF8 -AllMatches) $naiveHits = @(Select-String -Path $hmwPath -Pattern ([regex]::Escape($OWNER_RATIFIED_TIER2_FULL_ID)) -Encoding UTF8) Write-Host (" anti-vacuous note: naive grep '{0}' in hmw.js = {1} hit(s) [comment text] -> NOT used as evidence" -f ` $OWNER_RATIFIED_TIER2_FULL_ID, $naiveHits.Count) -ForegroundColor DarkGray if ($constHits.Count -eq 0) { # FAIL-LOUD. No hardcoded default is substituted: an audit that invents the value it is # meant to verify would report a PASS about itself. Write-Flag 'HIGH' (Rel $hmwPath) ` 'expected constant missing (W2 chua land): TIER2_EXPECTED_FULL_ID not declared in hmw.js' ` ("land PA-2a: add TIER2_EXPECTED_FULL_ID = '{0}' next to resolveModel() in hmw.js" -f $OWNER_RATIFIED_TIER2_FULL_ID) Write-Host ' -> section B comparison will report SKIPPED (no expected value to compare against)' -ForegroundColor DarkGray } else { $values = @() foreach ($h in $constHits) { foreach ($m in $h.Matches) { $values += $m.Groups[1].Value } } $distinctValues = @($values | Sort-Object -Unique) Write-Host (" found {0} definition(s) of TIER2_EXPECTED_FULL_ID; distinct value(s): {1}" -f ` $values.Count, ($distinctValues -join ', ')) foreach ($h in $constHits) { Write-Host (" {0}:{1}" -f (Rel $hmwPath), $h.LineNumber) -ForegroundColor DarkGray } if ($distinctValues.Count -gt 1) { Write-Flag 'HIGH' (Rel $hmwPath) ` ("conflicting definitions: TIER2_EXPECTED_FULL_ID declared with {0} different values [{1}]" -f ` $distinctValues.Count, ($distinctValues -join ' vs ')) ` 'keep exactly ONE authoritative definition of TIER2_EXPECTED_FULL_ID' } $expected = $distinctValues[0] # PASS/FAIL is COMPUTED from the measured value (W0.4 lesson 2 - never a label pasted # next to a number that says otherwise). if ($expected -cne $OWNER_RATIFIED_TIER2_FULL_ID) { Write-Flag 'HIGH' (Rel $hmwPath) ` ("mismatch vs owner-ratified expectation: hmw.js declares '{0}' but S119 PA-2a ratified '{1}'" -f ` $expected, $OWNER_RATIFIED_TIER2_FULL_ID) ` ("set TIER2_EXPECTED_FULL_ID = '{0}', or have the owner re-ratify and update this script" -f $OWNER_RATIFIED_TIER2_FULL_ID) } else { Write-Host (" [OK] hmw.js expected = '{0}' = owner-ratified (S119 PA-2a)" -f $expected) -ForegroundColor Green } if ($expected -match '\[1m\]') { Write-Flag 'MED' (Rel $hmwPath) ` ("expected value carries a '[1m]' context-window suffix: '{0}'" -f $expected) ` 'drop the [1m] suffix - it is not part of the model id (gotcha #37)' } } } # =========================================================================== # SECTION B - PA-2b: the RESOLVED model, from spawn transcripts (MEASURED) # =========================================================================== Write-Section 'B - resolved model (PA-2b, spawn transcripts)' # Project folder name derives from $RepoRoot (path separators -> '-'), so a fault-inject tree # resolves to a slug with no transcripts -> NO-SCOPE, never a faked measurement. $slug = $RepoRoot -replace '[:\\/_]', '-' $projDir = Join-Path $TranscriptRoot $slug $dispatch = 0 # spawn lanes found (one agent-*.jsonl = one lane) $explicit = 0 # lanes where a resolved model is actually recorded $mismatch = 0 # lanes resolved to the tier-2 FAMILY but NOT the expected version = alias drift $otherFam = 0 # lanes resolved outside the tier-2 family (escape-hatch / inherited lead) $legacy = 0 # lanes resolved the PRE-FLIP default (transition bucket, Khoan 1.4 - counted, not flagged) $modelTally = @{} Write-Host (" transcript root: {0}" -f $TranscriptRoot) -ForegroundColor DarkGray Write-Host (" project slug : {0} (derived from RepoRoot)" -f $slug) -ForegroundColor DarkGray if (-not (Test-Path $projDir)) { Write-Host ' [NO-SCOPE] no transcript folder for this repo - nothing to measure, nothing claimed.' -ForegroundColor DarkGray Write-Host ' (expected when running against a fault-inject / temp tree)' -ForegroundColor DarkGray } else { $sessionDir = $null if ($SessionId -ne '') { $cand = Join-Path $projDir $SessionId if (Test-Path $cand) { $sessionDir = Get-Item $cand } else { Write-Flag 'MED' (Rel $cand) 'requested -SessionId not found' 'pass an existing session id, or omit to use the most recent' } } else { $sessionDir = Get-ChildItem -Path $projDir -Directory -ErrorAction SilentlyContinue | Where-Object { Test-Path (Join-Path $_.FullName 'subagents\workflows') } | Sort-Object LastWriteTime -Descending | Select-Object -First 1 } if ($null -eq $sessionDir) { Write-Host ' [NO-SCOPE] no session with spawn transcripts under this project - nothing measured.' -ForegroundColor DarkGray } else { Write-Host (" session scope : {0} (last write {1:yyyy-MM-dd HH:mm})" -f $sessionDir.Name, $sessionDir.LastWriteTime) Write-Host ' scope = CURRENT session only, by design (old runs predate the convention; owner-decisions:64)' -ForegroundColor DarkGray # STRUCTURAL anchor: the model key of an assistant record sits immediately inside # "message":{ ... . Anchoring on the record shape (not a bare "model": grep) keeps quoted # JSON inside message CONTENT - agents routinely paste transcript snippets - from being # counted as if it were a real dispatch. $RX_MODEL = '"message"\s*:\s*\{\s*"model"\s*:\s*"([^"]+)"' $wfRoot = Join-Path $sessionDir.FullName 'subagents\workflows' $laneFiles = @(Get-ChildItem -Path $wfRoot -Recurse -Filter 'agent-*.jsonl' -File -ErrorAction SilentlyContinue) foreach ($lane in $laneFiles) { $dispatch++ $hits = @(Select-String -Path $lane.FullName -Pattern $RX_MODEL -Encoding UTF8 -AllMatches) $models = @() foreach ($h in $hits) { foreach ($m in $h.Matches) { $models += $m.Groups[1].Value } } $distinct = @($models | Sort-Object -Unique) $wfName = Split-Path (Split-Path $lane.FullName -Parent) -Leaf $agentType = '?' $metaPath = ($lane.FullName -replace '\.jsonl$', '.meta.json') if (Test-Path $metaPath) { $metaTxt = Get-Content -Path $metaPath -Raw -Encoding UTF8 $mm = [regex]::Match($metaTxt, '"agentType"\s*:\s*"([^"]+)"') if ($mm.Success) { $agentType = $mm.Groups[1].Value } } if ($distinct.Count -eq 0) { Write-Host (" {0}/{1} [{2}] -> no model recorded (lane produced no assistant record)" -f ` $wfName, $lane.Name, $agentType) -ForegroundColor DarkGray continue } $explicit++ foreach ($d in $distinct) { if ($modelTally.ContainsKey($d)) { $modelTally[$d] = $modelTally[$d] + 1 } else { $modelTally[$d] = 1 } } $verdict = 'other-family' $inFamily = @($distinct | Where-Object { $_.StartsWith($TIER2_FAMILY_PREFIX) }) if ($null -eq $expected) { $verdict = 'SKIPPED (no expected constant)' } elseif ($inFamily.Count -eq 0) { $verdict = 'other-family (escape-hatch / inherited lead - not a drift signal)' $otherFam++ } else { $bad = @($inFamily | Where-Object { $_ -cne $expected }) # Khoan 1.4 broadcast model-default-opus-5-max (2026-07-25): records that resolved the # PREVIOUS default are a LEGACY bucket during the transition, counted separately, # NOT flagged as drift (a value-update flips the expected mid-history; old records # predate the flip - flagging them is a false alarm storm, exactly what 1.4 forbids). # A record that is neither expected NOR legacy is still a REAL mismatch. $legacyOnly = @($bad | Where-Object { $_ -cne $TIER2_LEGACY_FULL_ID }) if ($bad.Count -gt 0 -and $legacyOnly.Count -eq 0) { $legacy++ $verdict = ("legacy ({0} = pre-flip default; transition bucket Khoan 1.4, not drift)" -f ($bad -join ', ')) } elseif ($legacyOnly.Count -gt 0) { $mismatch++ $verdict = 'MISMATCH' Write-Flag 'HIGH' ("{0}/{1}" -f $wfName, $lane.Name) ` ("alias-drift: resolved '{0}' is in the tier-2 family but expected '{1}' (and not the legacy bucket)" -f ($legacyOnly -join ', '), $expected) ` 'owner decides re-pin (H23 section 2(2)); update TIER2_EXPECTED_FULL_ID once ratified' } else { $verdict = 'match' } } Write-Host (" {0}/{1} [{2}] -> {3} ({4} record(s)) : {5}" -f ` $wfName, $lane.Name, $agentType, ($distinct -join ', '), $models.Count, $verdict) } Write-Host '' Write-Host (" COUNTS: {0} dispatch | {1} explicit | {2} mismatch" -f $dispatch, $explicit, $mismatch) Write-Host ' (dispatch = lanes found | explicit = lanes with a model actually recorded | mismatch = tier-2-family lanes off the expected version)' -ForegroundColor DarkGray if ($modelTally.Count -gt 0) { Write-Host ' resolved model tally (lanes per model):' foreach ($k in ($modelTally.Keys | Sort-Object)) { Write-Host (" {0,-24} {1} lane(s)" -f $k, $modelTally[$k]) } } if ($null -eq $expected) { Write-Host ' [SKIPPED] resolved-vs-expected NOT evaluated: section A found no expected constant.' -ForegroundColor Yellow Write-Host ' This is NOT a pass. The lanes above are reported raw, uncompared.' -ForegroundColor Yellow } elseif ($dispatch -eq 0) { Write-Host ' [NO-SCOPE] 0 lanes in scope - a 0-mismatch count here would be VACUOUS, not a pass.' -ForegroundColor Yellow } elseif ($mismatch -eq 0) { Write-Host (" [OK] 0/{0} lane(s) drifted off expected '{1}' (retrospective only - says nothing about the NEXT spawn)" -f ` $explicit, $expected) -ForegroundColor Green } } } # =========================================================================== # SECTION C - canonical cross-check: docs/STATUS.md, the Sub-agents row # =========================================================================== Write-Section 'C - canonical cross-check (STATUS.md Sub-agents row)' # Row label read from the file, not guessed: docs/STATUS.md:24 = "| Sub-agents | **12** | ...". # That row is the single-owner flip-chain canonical; hmw.js:34 and agents/README point at it. $SUBAGENT_ROW_LABEL = 'Sub-agents' $FLIPCHAIN_MARKER = 'CANONICAL single-owner flip-chain' $statusPath = Join-Path $RepoRoot 'docs\STATUS.md' if (-not (Test-Path $statusPath)) { Write-Flag 'MED' (Rel $statusPath) 'docs/STATUS.md not found - cannot cross-check the roster canonical' ` 'run against a repo root that contains docs/STATUS.md' } else { $rowPat = '^\|\s*' + [regex]::Escape($SUBAGENT_ROW_LABEL) + '\s*\|\s*\*\*(\d+)' $rowHit = Select-String -Path $statusPath -Pattern $rowPat -Encoding UTF8 | Select-Object -First 1 if ($null -eq $rowHit) { Write-Flag 'MED' (Rel $statusPath) ` ("canonical row '| {0} | **N** |' not found in STATUS.md CURRENT STATE table" -f $SUBAGENT_ROW_LABEL) ` 'restore the Sub-agents row, or update this script if the canonical owner moved' } else { $canonSub = [int]$rowHit.Matches[0].Groups[1].Value Write-Host (" STATUS.md:{0} canonical {1} = {2}" -f $rowHit.LineNumber, $SUBAGENT_ROW_LABEL, $canonSub) if ($rowHit.Line -notmatch [regex]::Escape($FLIPCHAIN_MARKER)) { Write-Flag 'LOW' ("{0}:{1}" -f (Rel $statusPath), $rowHit.LineNumber) ` ("the {0} row no longer carries the '{1}' marker" -f $SUBAGENT_ROW_LABEL, $FLIPCHAIN_MARKER) ` 'restore the marker, or re-point this cross-check at the new canonical owner' } else { Write-Host (" [OK] row carries the flip-chain canonical marker") -ForegroundColor Green } # disk cross-check: the canonical count must not itself be stale. $agentDir = Join-Path $RepoRoot '.claude\agents' if (Test-Path $agentDir) { $diskAgents = @(Get-ChildItem -Path $agentDir -Filter *.md -File -ErrorAction SilentlyContinue | Where-Object { $_.Name -ne 'README.md' }) Write-Host (" disk cross-check: .claude/agents/*.md minus README = {0}" -f $diskAgents.Count) if ($diskAgents.Count -ne $canonSub) { Write-Flag 'MED' (Rel $statusPath) ` ("canonical-itself-stale: STATUS {0}=**{1}** but disk has {2} agent .md" -f ` $SUBAGENT_ROW_LABEL, $canonSub, $diskAgents.Count) ` ("re-ground the STATUS.md {0} row to {1}" -f $SUBAGENT_ROW_LABEL, $diskAgents.Count) } else { Write-Host (" [OK] canonical {0} matches disk ({1})" -f $canonSub, $diskAgents.Count) -ForegroundColor Green } } } } # =========================================================================== # SECTION D - S124 worker-tier-pin: agent frontmatter (model: opus + effort: max) # (was: H8 all-inherit - superseded by owner-decision S124 2026-07-15, adap erratum-h8) # =========================================================================== Write-Section 'D - frontmatter worker-tier-pin (S124)' # GLOB, never a hardcoded roster size: the roster moves 12 -> 14 at W2, and a hardcoded count # would self-age into a false FAIL the moment it lands (fix #9(h) / R2-M3). $agentDir = Join-Path $RepoRoot '.claude\agents' if (-not (Test-Path $agentDir)) { Write-Flag 'MED' (Rel $agentDir) '.claude/agents not found - cannot check frontmatter' ` 'run against a repo root that contains .claude/agents' } else { $agentFiles = @(Get-ChildItem -Path $agentDir -Filter *.md -File -ErrorAction SilentlyContinue | Where-Object { $_.Name -ne 'README.md' }) $pinCount = 0 $effortOkCount = 0 foreach ($a in $agentFiles) { $lines = @(Get-Content -Path $a.FullName -Encoding UTF8) # frontmatter = the block between the first '---' and the next '---' $modelVal = $null $modelLine = 0 $effortVal = $null $effortLine = 0 $inFm = $false for ($i = 0; $i -lt $lines.Count; $i++) { $t = $lines[$i].Trim() if ($t -eq '---') { if (-not $inFm) { $inFm = $true; continue } break } if ($inFm -and $t -match '^model\s*:\s*(.+?)\s*$') { $modelVal = $Matches[1].Trim() $modelLine = $i + 1 } if ($inFm -and $t -match '^effort\s*:\s*(.+?)\s*$') { $effortVal = $Matches[1].Trim() $effortLine = $i + 1 } } if ($null -eq $modelVal) { Write-Flag 'MED' (Rel $a.FullName) ` 'no "model:" key in frontmatter - the lane falls back to a harness default, NOT the worker-tier pin' ` 'add "model: opus" to the agent frontmatter (S124 worker-tier-pin)' } elseif ($modelVal -cne 'opus') { Write-Flag 'MED' ("{0}:{1}" -f (Rel $a.FullName), $modelLine) ` ("frontmatter has 'model: {0}' - S124 worker-tier-pin expects every agent pinned 'model: opus'" -f $modelVal) ` 'set "model: opus", or have the owner ratify the change and record it in STATUS.md Sub-agents' } else { $pinCount++ } if ($null -eq $effortVal) { Write-Flag 'MED' (Rel $a.FullName) ` 'no "effort:" key in frontmatter - S124 worker-tier-pin expects "effort: max" alongside the model pin' ` 'add "effort: max" to the agent frontmatter (S124 worker-tier-pin)' } elseif ($effortVal -cne 'max') { Write-Flag 'MED' ("{0}:{1}" -f (Rel $a.FullName), $effortLine) ` ("frontmatter has 'effort: {0}' - S124 worker-tier-pin expects 'effort: max'" -f $effortVal) ` 'set "effort: max", or have the owner ratify the change and record it in STATUS.md Sub-agents' } else { $effortOkCount++ } } # verdict COMPUTED from the counts, never a pasted label (W0.4 lesson 2) Write-Host (" frontmatter: {0}/{1} agent .md carry 'model: opus' and {2}/{1} carry 'effort: max' (S124 worker-tier-pin)" -f ` $pinCount, $agentFiles.Count, $effortOkCount) if ($agentFiles.Count -eq 0) { Write-Host ' [NO-SCOPE] 0 agent .md found - a clean result here would be VACUOUS.' -ForegroundColor Yellow } elseif (($pinCount -eq $agentFiles.Count) -and ($effortOkCount -eq $agentFiles.Count)) { Write-Host (" [OK] worker-tier-pin holds ({0}/{0} model + {0}/{0} effort)" -f $agentFiles.Count) -ForegroundColor Green } } # =========================================================================== # SECTION E - declared limits (printed EVERY run, so no report can over-read) # =========================================================================== Write-Section 'E - what this report does NOT say' Write-Host ' 1. SPOT-CHECK BY CONVENTION, NOT ENFORCEMENT. Nothing here blocks a spawn (H23 section 2(4)).' Write-Host ' 2. CURRENT SESSION ONLY. Older runs predate the convention; scanning them yields noise, not a bug storm.' Write-Host ' 3. NOT "the floor is applied". This measures explicitness in transcripts, never documentation coverage.' Write-Host ' 4. RETROSPECTIVE ONLY. It reads models that ALREADY resolved; it cannot pre-verify the NEXT spawn.' Write-Host ' 5. TESTED 2026-07-16 (S126) - spawn param vs frontmatter HARD-PIN: the param WON (reviewer pinned opus +' Write-Host ' spawn fable -> claude-fable-5; no-override control -> claude-opus-4-8 under lead=Fable). ALIAS-pin only;' Write-Host ' the full-id-pin form (hub) is still untested here. Inherit-case evidence: header, wf_cb964f83-331.' Write-Host ' 6. NOT TRIED - whether the spawn param rejects a full-id (fix #8a). Docs say enum alias; never attempted.' # --------------------------------------------------------------------------- # Summary # --------------------------------------------------------------------------- Write-Section 'Summary' Write-Host ("TOTAL FLAGS: {0}" -f $script:FlagCount) -ForegroundColor Cyan Write-Host 'NOTE: informational audit. Exit 0 always (never fails a build). FLAGs are advisory - owner decides re-pin.' -ForegroundColor DarkGray exit 0