Payload/scripts/kaden/harness/harness-record-story-ids.ps1
|
#Requires -Version 5.1 <# .SYNOPSIS Assign story ids to a slice projection; journals StoryIdsAssigned as a byproduct. .DESCRIPTION Initialize-HarnessProjectionSlice accepts -StoryIds, but every runtime caller inside HarnessGateProjection.psm1 creates slice shells with -SliceId only, so story_ids stays an empty array for every slice after the one hand-seeded at feature start. This is the recorder that closes that gap: it journals a StoryIdsAssigned event (auditable, replay-safe) and rebuilds the projection, unioning the given ids into the slice's existing story_ids instead of overwriting them. Call this once per slice, as early as convenient (at plan approval or at first harness-turn-start.ps1), using the Story Coverage assigned in slice-plan.md. The validate-review-loop.ps1 MISSING_STORY_IDS check fails -RequireReviewReady when a slice's story_ids is still empty, so this recorder (not a hand-edit of .review-loop.json) is the only sanctioned way to satisfy that gate. .EXAMPLE pwsh -File scripts/kaden/harness-invoke.ps1 harness-record-story-ids.ps1 -Feature kaden-distro-architecture -Slice repository-diagnostics -StoryIdsCsv "US-KDA-15" -ModelProvider cursor -ModelSlug claude-sonnet-5-thinking-medium #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Feature, [Parameter(Mandatory = $true)] [string]$Slice, [Parameter(Mandatory = $true)] [string]$StoryIdsCsv, [string]$FeatureRoot = '', [string]$RepoRoot = '', [ValidateSet('cursor', 'copilot', 'other')] [string]$ModelProvider = 'copilot', [string]$ModelSlug = 'unknown', [ValidateSet('primary', 'subagent')] [string]$ModelRole = 'primary', [string]$Agent = 'atdd-developer', [string]$ParentAgent = '', [ValidateSet('cursor-task', 'copilot-agent', 'chat', 'harness-script')] [string]$Tool = 'harness-script', [switch]$AllowArbitraryFeatureRoot ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' Import-Module (Join-Path $PSScriptRoot 'lib\HarnessContract.psm1') -Force Import-Module (Join-Path $PSScriptRoot 'lib\HarnessJournal.psm1') -Force Import-Module (Join-Path $PSScriptRoot 'lib\HarnessGateProjection.psm1') -Force Test-HarnessContractModuleReady if ([string]::IsNullOrWhiteSpace($RepoRoot)) { $RepoRoot = Get-HarnessRepoRoot -StartPath $PSScriptRoot } $featureRootPath = Get-HarnessFeatureRoot -RepoRoot $RepoRoot -Feature $Feature -FeatureRootOverride $FeatureRoot -AllowArbitraryFeatureRoot:$AllowArbitraryFeatureRoot $storyIds = [System.Collections.ArrayList]@() foreach ($part in ($StoryIdsCsv -split ',')) { $t = $part.Trim() if ($t) { [void]$storyIds.Add($t) } } if ($storyIds.Count -eq 0) { throw '-StoryIdsCsv must contain at least one non-empty story id.' } $resolvedSlug = Get-HarnessResolvedModelSlug -ModelSlug $ModelSlug $actor = New-HarnessJournalActor -Agent $Agent -ParentAgent $(if ($ParentAgent) { $ParentAgent } else { $null }) ` -Tool $Tool -Provider $ModelProvider -Slug $resolvedSlug -Role $ModelRole $activity = New-HarnessJournalActivity -Id (New-HarnessJournalActivityId) -Type 'other' -Name 'story-ids-assigned' -Role 'instant' $journalEvent = Add-HarnessJournalEvent -FeatureRoot $featureRootPath -Feature $Feature -Slice $Slice ` -Kind 'StoryIdsAssigned' -Activity $activity -Actor $actor -Outcome $null ` -Summary "story ids assigned for $Slice" ` -Payload ([pscustomobject]@{ story_ids = @($storyIds.ToArray()) }) ` -Refs ([pscustomobject]@{ amends_event_id = $null pair_event_id = $null artifact = $null command = '.\scripts\kaden\harness-record-story-ids.ps1' }) $result = Update-HarnessGateProjectionFromJournal -FeatureRoot $featureRootPath -Feature $Feature -RepoRoot $RepoRoot -Write $impl = Get-ImplementationPhase -LoopData $result $targetSlice = @($impl.slices) | Where-Object { $_.id -eq $Slice } | Select-Object -First 1 [pscustomobject]@{ operation = 'record-story-ids' feature = $Feature slice = $Slice story_ids = @($targetSlice.story_ids) journal_event_ids = @($journalEvent.event_id) status = 'PASS' } | ConvertTo-Json -Depth 10 |