@danmoisan/drm-copilot-mcp 1.1.25 → 1.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/out/mcp-server.js +170 -52
  2. package/package.json +1 -1
  3. package/resources/claude-customizations/.claude/agents/atomic-executor.md +3 -3
  4. package/resources/claude-customizations/.claude/agents/atomic-planner.md +2 -2
  5. package/resources/claude-customizations/.claude/agents/csharp-typed-engineer.md +7 -7
  6. package/resources/claude-customizations/.claude/agents/feature-review.md +6 -3
  7. package/resources/claude-customizations/.claude/agents/orchestrator.md +11 -7
  8. package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +7 -3
  9. package/resources/claude-customizations/.claude/agents/parallel-planner.md +6 -2
  10. package/resources/claude-customizations/.claude/agents/powershell-typed-engineer.md +7 -7
  11. package/resources/claude-customizations/.claude/agents/python-typed-engineer.md +6 -6
  12. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-review.ps1 +699 -0
  13. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +16 -1
  14. package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +41 -0
  15. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-cleanup.ps1 +481 -0
  16. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +3 -1
  17. package/resources/claude-customizations/.claude/hooks/enforce-parallel-cohort-barrier-helpers.ps1 +69 -3
  18. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +2 -2
  19. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.cleanup.ps1 +246 -0
  20. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.docs-only.ps1 +1 -0
  21. package/resources/claude-customizations/.claude/hooks/hook-cleanup-context.ps1 +343 -0
  22. package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage-rules.ps1 +50 -16
  23. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorState.psm1 +6 -1
  24. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCompletion.psm1 +4 -2
  25. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCompletionChecks.psm1 +51 -2
  26. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateReceipts.psm1 +5 -2
  27. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRemediationAccounting.psm1 +116 -4
  28. package/resources/claude-customizations/.claude/lib/parallel-admission/Invoke-ParallelAdmission.ps1 +626 -0
  29. package/resources/claude-customizations/.claude/lib/parallel-admission/ParallelAdmission.psm1 +508 -0
  30. package/resources/claude-customizations/.claude/lib/parallel-admission/ParallelAdmissionJson.psm1 +141 -0
  31. package/resources/claude-customizations/.claude/lib/parallel-admission/ParallelAdmissionPrecedence.psm1 +508 -0
  32. package/resources/claude-customizations/.claude/rules/csharp.md +8 -8
  33. package/resources/claude-customizations/.claude/rules/orchestrator-state.md +28 -2
  34. package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +17 -1
  35. package/resources/claude-customizations/.claude/rules/powershell.md +2 -2
  36. package/resources/claude-customizations/.claude/settings.json +1 -0
  37. package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +9 -13
  38. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +93 -14
  39. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup-worktrees.sh +23 -10
  40. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_lib.sh +54 -46
  41. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_merge_lib.sh +234 -0
  42. package/resources/claude-customizations/.claude/skills/csharp-qa-gate/SKILL.md +14 -15
  43. package/resources/claude-customizations/.claude/skills/epic-progress-report/SKILL.md +338 -0
  44. package/resources/claude-customizations/.claude/skills/epic-progress-report/scripts/Get-EpicProgressReport.Logic.ps1 +248 -0
  45. package/resources/claude-customizations/.claude/skills/epic-progress-report/scripts/Get-EpicProgressReport.Metrics.ps1 +232 -0
  46. package/resources/claude-customizations/.claude/skills/epic-progress-report/scripts/Get-EpicProgressReport.Render.ps1 +196 -0
  47. package/resources/claude-customizations/.claude/skills/epic-progress-report/scripts/Get-EpicProgressReport.State.ps1 +286 -0
  48. package/resources/claude-customizations/.claude/skills/epic-progress-report/scripts/Get-EpicProgressReport.ps1 +475 -0
  49. package/resources/claude-customizations/.claude/skills/execution-environment/SKILL.md +31 -16
  50. package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +21 -9
  51. package/resources/claude-customizations/.claude/skills/invoke-csharp-engineer/SKILL.md +5 -5
  52. package/resources/claude-customizations/.claude/skills/invoke-powershell-engineer/SKILL.md +4 -4
  53. package/resources/claude-customizations/.claude/skills/invoke-python-engineer/SKILL.md +4 -4
  54. package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +24 -2
  55. package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +71 -7
  56. package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +34 -2
  57. package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +82 -12
  58. package/resources/claude-customizations/.claude/skills/powershell-qa-gate/SKILL.md +16 -17
  59. package/resources/claude-customizations/.claude/skills/python-qa-gate/SKILL.md +15 -16
  60. package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +1 -1
  61. package/resources/claude-customizations/.claude-variants/csharp-legacy/agents/csharp-typed-engineer.md +6 -6
  62. package/resources/claude-customizations/.claude-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +13 -14
  63. package/resources/claude-customizations/.claude-variants/csharp-legacy/skills/invoke-csharp-engineer/SKILL.md +4 -4
  64. package/resources/claude-customizations/pack-manifests/core.json +15 -0
  65. package/resources/codex-and-agents-customizations/.agents/skills/atomic-plan-contract/SKILL.md +8 -12
  66. package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +1 -1
  67. package/resources/codex-and-agents-customizations/.agents/skills/csharp-qa-gate/SKILL.md +13 -14
  68. package/resources/codex-and-agents-customizations/.agents/skills/execution-environment/SKILL.md +31 -16
  69. package/resources/codex-and-agents-customizations/.agents/skills/feature-review/SKILL.md +5 -1
  70. package/resources/codex-and-agents-customizations/.agents/skills/feature-review-workflow/SKILL.md +18 -5
  71. package/resources/codex-and-agents-customizations/.agents/skills/invoke-csharp-engineer/SKILL.md +4 -4
  72. package/resources/codex-and-agents-customizations/.agents/skills/invoke-powershell-engineer/SKILL.md +4 -4
  73. package/resources/codex-and-agents-customizations/.agents/skills/invoke-python-engineer/SKILL.md +4 -4
  74. package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +24 -2
  75. package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-state/SKILL.md +16 -1
  76. package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +3 -3
  77. package/resources/codex-and-agents-customizations/.agents/skills/powershell/SKILL.md +2 -2
  78. package/resources/codex-and-agents-customizations/.agents/skills/powershell-qa-gate/SKILL.md +15 -16
  79. package/resources/codex-and-agents-customizations/.agents/skills/python-qa-gate/SKILL.md +14 -15
  80. package/resources/codex-and-agents-customizations/.agents/skills/repo-automation-adapter/SKILL.md +2 -0
  81. package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +13 -14
  82. package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/invoke-csharp-engineer/SKILL.md +4 -4
  83. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c1.toml +3 -3
  84. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c2.toml +3 -3
  85. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3-elevated.toml +3 -3
  86. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3.toml +3 -3
  87. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c4.toml +3 -3
  88. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor.toml +3 -3
  89. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c1.toml +2 -2
  90. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c2.toml +2 -2
  91. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3-elevated.toml +2 -2
  92. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3.toml +2 -2
  93. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c4.toml +2 -2
  94. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner.toml +2 -2
  95. package/resources/codex-and-agents-customizations/.codex/agents/csharp-atomic-executor.toml +2 -2
  96. package/resources/codex-and-agents-customizations/.codex/agents/csharp-atomic-planning.toml +1 -1
  97. package/resources/codex-and-agents-customizations/.codex/agents/csharp-orchestrator.toml +1 -1
  98. package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c1.toml +6 -6
  99. package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c2.toml +6 -6
  100. package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c3-elevated.toml +6 -6
  101. package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c3.toml +6 -6
  102. package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c4.toml +6 -6
  103. package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer.toml +6 -6
  104. package/resources/codex-and-agents-customizations/.codex/agents/feature-review.toml +2 -2
  105. package/resources/codex-and-agents-customizations/.codex/agents/powershell-atomic-executor.toml +2 -2
  106. package/resources/codex-and-agents-customizations/.codex/agents/powershell-atomic-planning.toml +1 -1
  107. package/resources/codex-and-agents-customizations/.codex/agents/powershell-di-unit-test-engineer.toml +1 -1
  108. package/resources/codex-and-agents-customizations/.codex/agents/powershell-orchestrator.toml +1 -1
  109. package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c1.toml +7 -7
  110. package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c2.toml +7 -7
  111. package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c3-elevated.toml +7 -7
  112. package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c3.toml +7 -7
  113. package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c4.toml +7 -7
  114. package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer.toml +7 -7
  115. package/resources/codex-and-agents-customizations/.codex/agents/pytest-unit-test-coding.toml +1 -1
  116. package/resources/codex-and-agents-customizations/.codex/agents/python-atomic-executor.toml +2 -2
  117. package/resources/codex-and-agents-customizations/.codex/agents/python-atomic-planning.toml +1 -1
  118. package/resources/codex-and-agents-customizations/.codex/agents/python-execution-only-typed.toml +1 -1
  119. package/resources/codex-and-agents-customizations/.codex/agents/python-orchestrator.toml +1 -1
  120. package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c1.toml +6 -6
  121. package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c2.toml +6 -6
  122. package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c3-elevated.toml +6 -6
  123. package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c3.toml +6 -6
  124. package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c4.toml +6 -6
  125. package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer.toml +6 -6
  126. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
  127. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate-review.ps1 +699 -0
  128. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate.ps1 +29 -2
  129. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-cleanup.ps1 +481 -0
  130. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +4 -2
  131. package/resources/codex-and-agents-customizations/.codex/hooks/hook-cleanup-context.ps1 +343 -0
  132. package/resources/codex-and-agents-customizations/.codex/hooks/validate-feature-review-coverage.ps1 +51 -4
  133. package/resources/codex-and-agents-customizations/.codex-variants/csharp-legacy/agents/csharp-typed-engineer.toml +6 -6
  134. package/resources/codex-and-agents-customizations/pack-manifests/core.json +3 -0
  135. package/resources/customizations/.github/agents/5.1-Beast-adjusted.agent.md +1 -1
  136. package/resources/customizations/.github/agents/Powershell DI Unit Test Engineer.agent.md +20 -26
  137. package/resources/customizations/.github/agents/atomic_executor.agent.md +4 -4
  138. package/resources/customizations/.github/agents/atomic_planning.agent.md +4 -4
  139. package/resources/customizations/.github/agents/commentary-remediation.agent.md +1 -1
  140. package/resources/customizations/.github/agents/commit-steward.agent.md +1 -1
  141. package/resources/customizations/.github/agents/csharp-atomic-executor.agent.md +14 -14
  142. package/resources/customizations/.github/agents/csharp-atomic-planning.agent.md +2 -2
  143. package/resources/customizations/.github/agents/csharp-orchestrator.agent.md +4 -4
  144. package/resources/customizations/.github/agents/csharp-typed-engineer.agent.md +19 -22
  145. package/resources/customizations/.github/agents/epic-review.agent.md +1 -1
  146. package/resources/customizations/.github/agents/gpt-5-beast-mode.agent.md +3 -3
  147. package/resources/customizations/.github/agents/orchestrator.agent.md +8 -8
  148. package/resources/customizations/.github/agents/powershell-atomic-executor.agent.md +12 -12
  149. package/resources/customizations/.github/agents/powershell-atomic-planning.agent.md +4 -4
  150. package/resources/customizations/.github/agents/powershell-orchestrator.agent.md +6 -6
  151. package/resources/customizations/.github/agents/powershell-typed-engineer.agent.md +21 -24
  152. package/resources/customizations/.github/agents/pytest-unit-test-coding.agent.md +13 -17
  153. package/resources/customizations/.github/agents/python-atomic-executor.agent.md +11 -11
  154. package/resources/customizations/.github/agents/python-atomic-planning.agent.md +2 -2
  155. package/resources/customizations/.github/agents/python-execution-only-typed.agent.md +14 -17
  156. package/resources/customizations/.github/agents/python-orchestrator.agent.md +7 -7
  157. package/resources/customizations/.github/agents/python-typed-engineer.agent.md +17 -20
  158. package/resources/customizations/.github/agents/staged-review.agent.md +2 -2
  159. package/resources/customizations/.github/agents/tdd-green.agent.md +1 -1
  160. package/resources/customizations/.github/agents/tdd-red.agent.md +3 -3
  161. package/resources/customizations/.github/agents/tdd-refactor.agent.md +2 -2
  162. package/resources/customizations/.github/agents/typescript-engineer.agent.md +3 -3
  163. package/resources/customizations/.github/codex/execute-hard-lock.prompt.md +3 -3
  164. package/resources/customizations/.github/instructions/general-code-change.instructions.md +1 -1
  165. package/resources/customizations/.github/instructions/powershell-unit-test.instructions.md +1 -1
  166. package/resources/customizations/.github/instructions/python-code-change.instructions.md +5 -5
  167. package/resources/customizations/.github/instructions/python-suppressions.instructions.md +3 -3
  168. package/resources/customizations/.github/instructions/python-unit-test.instructions.md +1 -1
  169. package/resources/customizations/.github/prompts/execute-hard-lock.prompt.md +2 -2
  170. package/resources/customizations/.github/prompts/generate-commit-message-repo.prompt.md +2 -2
  171. package/resources/customizations/.github/prompts/remediate-comments.prompt.md +2 -2
  172. package/resources/customizations/.github/prompts/review-feature.prompt.md +1 -1
  173. package/resources/customizations/.github/skills/atomic-plan-contract/SKILL.md +8 -12
  174. package/resources/customizations/.github/skills/execution-environment/SKILL.md +31 -16
  175. package/resources/customizations/.github/skills/feature-review-workflow/SKILL.md +15 -2
  176. package/resources/feature-templates/bug/plan.yyyy-MM-ddTHH-mm.md +4 -4
  177. package/resources/feature-templates/feature/plan.yyyy-MM-ddTHH-mm.md +3 -3
  178. package/resources/feature-templates/refactor/plan.yyyy-MM-ddTHH-mm.md +2 -2
  179. package/resources/powershell/PoshQC/PoshQC.ScanConfig.psm1 +3 -1
  180. package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +14 -12
  181. package/resources/powershell/PoshQC/PoshQC.psm1 +3 -3
  182. package/resources/powershell/PoshQC/README.md +8 -8
  183. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +2 -2
  184. package/resources/templates/policy_audit/AGENTS.md +9 -10
  185. package/resources/templates/policy_audit/policy-audit.yyyy-MM-ddTHH-mm.md +19 -20
@@ -0,0 +1,286 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Setting, state-file, baseline, and sample functions for Get-EpicProgressReport.ps1.
4
+
5
+ .DESCRIPTION
6
+ Pure functions: each takes data in and returns data, and none reads a file, starts a
7
+ process, calls the network, or reads the clock. The entry script reads and writes the
8
+ state file through its I/O seams. Get-EpicProgressReport.Logic.ps1 dot-sources this file,
9
+ so a consumer dot-sources the Logic hub, not this file.
10
+ #>
11
+
12
+ function Select-EpicProgressSample {
13
+ <#
14
+ .SYNOPSIS
15
+ Apply the sample-retention rule for one check-in; return Sample and Changed.
16
+ .DESCRIPTION
17
+ A sample (ts, done) is added only when there is no previous sample, the previous
18
+ sample has no 'ts', or it is at least 90 seconds older than now. On add, samples
19
+ without 'ts' are dropped and only the last SampleCap samples are kept.
20
+ .PARAMETER Sample
21
+ The samples read from the state file.
22
+ .PARAMETER NowUnixSeconds
23
+ The current instant in Unix seconds.
24
+ .PARAMETER Done
25
+ The checked task count now.
26
+ .PARAMETER SampleCap
27
+ The maximum number of samples kept.
28
+ #>
29
+ [CmdletBinding()]
30
+ [OutputType([pscustomobject])]
31
+ param(
32
+ [Parameter(Mandatory = $true)] [AllowEmptyCollection()] [object[]] $Sample,
33
+ [Parameter(Mandatory = $true)] [long] $NowUnixSeconds,
34
+ [Parameter(Mandatory = $true)] [int] $Done,
35
+ [Parameter(Mandatory = $true)] [ValidateRange(1, 100000)] [int] $SampleCap
36
+ )
37
+
38
+ $last = $null
39
+ if ($Sample.Count -gt 0) { $last = $Sample[$Sample.Count - 1] }
40
+ $add = ($null -eq $last) -or -not ($last.PSObject.Properties.Name -contains 'ts') -or (($NowUnixSeconds - [long] $last.ts) -ge 90)
41
+ if (-not $add) { return [pscustomobject]@{ Sample = $Sample; Changed = $false } }
42
+ $kept = [System.Collections.Generic.List[object]]::new()
43
+ foreach ($entry in $Sample) {
44
+ if ($null -ne $entry -and $entry.PSObject.Properties.Name -contains 'ts') { $kept.Add($entry) }
45
+ }
46
+ $kept.Add([pscustomobject]@{ ts = $NowUnixSeconds; done = $Done })
47
+ $retained = [object[]] @($kept | Select-Object -Skip ([math]::Max(0, $kept.Count - $SampleCap)))
48
+ return [pscustomobject]@{ Sample = $retained; Changed = $true }
49
+ }
50
+
51
+ function Resolve-EpicProgressSetting {
52
+ <#
53
+ .SYNOPSIS
54
+ Apply the parameter defaults of the report; pure, with the current location passed in.
55
+ .DESCRIPTION
56
+ A blank value takes its default and an explicit value is kept. The kickoff path is a
57
+ git object path with '/' separators; filesystem paths are built with Join-Path. The
58
+ default state file is .claude/state/epic-progress-<EpicFolder>.json under the
59
+ repository root, which is gitignored and survives a container stop with the checkout.
60
+ .PARAMETER EpicFolder
61
+ The epic folder name.
62
+ .PARAMETER EpicIssue
63
+ The explicit epic issue number, or blank.
64
+ .PARAMETER IntegrationBranch
65
+ The explicit integration branch, or blank.
66
+ .PARAMETER KickoffPath
67
+ The explicit kickoff path, or blank.
68
+ .PARAMETER RepositoryRoot
69
+ The explicit repository root, or blank.
70
+ .PARAMETER CheckpointPath
71
+ The explicit checkpoint path, or blank.
72
+ .PARAMETER StatePath
73
+ The explicit state file path, or blank.
74
+ .PARAMETER CurrentLocation
75
+ The current location.
76
+ #>
77
+ [CmdletBinding()]
78
+ [OutputType([pscustomobject])]
79
+ param(
80
+ [Parameter(Mandatory = $true)] [string] $EpicFolder,
81
+ [AllowEmptyString()] [string] $EpicIssue = '',
82
+ [AllowEmptyString()] [string] $IntegrationBranch = '',
83
+ [AllowEmptyString()] [string] $KickoffPath = '',
84
+ [AllowEmptyString()] [string] $RepositoryRoot = '',
85
+ [AllowEmptyString()] [string] $CheckpointPath = '',
86
+ [AllowEmptyString()] [string] $StatePath = '',
87
+ [Parameter(Mandatory = $true)] [string] $CurrentLocation
88
+ )
89
+
90
+ $root = $RepositoryRoot
91
+ if ([string]::IsNullOrWhiteSpace($root)) { $root = $CurrentLocation }
92
+ $branch = $IntegrationBranch
93
+ if ([string]::IsNullOrWhiteSpace($branch)) { $branch = "origin/epic/$EpicFolder-integration" }
94
+ $kickoff = $KickoffPath
95
+ if ([string]::IsNullOrWhiteSpace($kickoff)) { $kickoff = "docs/features/epics/$EpicFolder/epic-kickoff.md" }
96
+ $checkpoint = $CheckpointPath
97
+ if ([string]::IsNullOrWhiteSpace($checkpoint)) {
98
+ $checkpoint = Join-Path -Path $root -ChildPath 'artifacts' -AdditionalChildPath 'orchestration', 'epic-orchestrator-state.json'
99
+ }
100
+ $state = $StatePath
101
+ if ([string]::IsNullOrWhiteSpace($state)) {
102
+ $state = Join-Path -Path $root -ChildPath '.claude' -AdditionalChildPath 'state', "epic-progress-$EpicFolder.json"
103
+ }
104
+
105
+ return [pscustomobject]@{
106
+ EpicIssue = $EpicIssue
107
+ IntegrationBranch = $branch
108
+ KickoffPath = $kickoff.Replace('\', '/')
109
+ RepositoryRoot = $root
110
+ CheckpointPath = $checkpoint
111
+ StatePath = $state
112
+ }
113
+ }
114
+
115
+ function ConvertFrom-EpicProgressStateText {
116
+ <#
117
+ .SYNOPSIS
118
+ Parse the state file text into StartUnixSeconds, BaselineDone, BaselineWeeklyPct, and Samples.
119
+ .DESCRIPTION
120
+ Accepts the version-1 object written by ConvertTo-EpicProgressStateJson and the legacy
121
+ JSON array of samples written by the issue #1080 tool (samples only, no baseline).
122
+ Blank text, unparseable text, any other JSON value, and an object whose version is
123
+ not 1 give the empty state. A version-1 field that is missing, null, or not a number
124
+ is absent: its value is $null. Samples is always an array.
125
+ .PARAMETER Text
126
+ The raw state file text; blank or null for no state file.
127
+ #>
128
+ [CmdletBinding()]
129
+ [OutputType([pscustomobject])]
130
+ param([Parameter(Mandatory = $true)] [AllowEmptyString()] [AllowNull()] [string] $Text)
131
+
132
+ $state = [pscustomobject]@{ StartUnixSeconds = $null; BaselineDone = $null; BaselineWeeklyPct = $null; Samples = [object[]] @() }
133
+ if (-not (Test-EpicProgressJsonText -Json $Text)) { return $state }
134
+ $parsed = ConvertFrom-Json -InputObject $Text -NoEnumerate
135
+ if ($parsed -is [array]) {
136
+ $state.Samples = [object[]] @($parsed | Where-Object { $null -ne $_ })
137
+ return $state
138
+ }
139
+ if ($parsed -isnot [System.Management.Automation.PSCustomObject]) { return $state }
140
+ $names = $parsed.PSObject.Properties.Name
141
+ if (-not ($names -contains 'version') -or [string] $parsed.version -ne '1') { return $state }
142
+ if ($names -contains 'startUnixSeconds' -and $null -ne $parsed.startUnixSeconds) { $state.StartUnixSeconds = $parsed.startUnixSeconds -as [long] }
143
+ if ($names -contains 'baselineDone' -and $null -ne $parsed.baselineDone) { $state.BaselineDone = $parsed.baselineDone -as [int] }
144
+ if ($names -contains 'baselineWeeklyPct' -and $null -ne $parsed.baselineWeeklyPct) { $state.BaselineWeeklyPct = $parsed.baselineWeeklyPct -as [double] }
145
+ if ($names -contains 'samples' -and $null -ne $parsed.samples) {
146
+ $state.Samples = [object[]] @($parsed.samples | Where-Object { $null -ne $_ })
147
+ }
148
+ return $state
149
+ }
150
+
151
+ function ConvertTo-EpicProgressStateJson {
152
+ <#
153
+ .SYNOPSIS
154
+ Return the version-1 state document as JSON text.
155
+ .DESCRIPTION
156
+ The document holds version 1, startUnixSeconds, baselineDone, baselineWeeklyPct, and
157
+ samples, each sample with an integer 'ts' (Unix epoch seconds) and a 'done' count.
158
+ A sample without 'ts' is not written. Epoch seconds are used because ConvertFrom-Json
159
+ converts ISO date strings into local-time DateTime values.
160
+ .PARAMETER StartUnixSeconds
161
+ The start instant in Unix epoch seconds.
162
+ .PARAMETER BaselineDone
163
+ The checked task count at the start instant.
164
+ .PARAMETER BaselineWeeklyPct
165
+ The weekly quota percentage at the start instant.
166
+ .PARAMETER Sample
167
+ The retained samples (ts, done).
168
+ #>
169
+ [CmdletBinding()]
170
+ [OutputType([string])]
171
+ param(
172
+ [Parameter(Mandatory = $true)] [long] $StartUnixSeconds,
173
+ [Parameter(Mandatory = $true)] [int] $BaselineDone,
174
+ [Parameter(Mandatory = $true)] [double] $BaselineWeeklyPct,
175
+ [Parameter(Mandatory = $true)] [AllowEmptyCollection()] [object[]] $Sample
176
+ )
177
+
178
+ $written = [System.Collections.Generic.List[object]]::new()
179
+ foreach ($entry in $Sample) {
180
+ if ($null -eq $entry -or -not ($entry.PSObject.Properties.Name -contains 'ts')) { continue }
181
+ $written.Add([ordered]@{ ts = [long] $entry.ts; done = [int] $entry.done })
182
+ }
183
+ $document = [ordered]@{
184
+ version = 1
185
+ startUnixSeconds = $StartUnixSeconds
186
+ baselineDone = $BaselineDone
187
+ baselineWeeklyPct = $BaselineWeeklyPct
188
+ samples = [object[]] $written.ToArray()
189
+ }
190
+ return ConvertTo-Json -InputObject $document -Depth 4
191
+ }
192
+
193
+ function Resolve-EpicProgressBaseline {
194
+ <#
195
+ .SYNOPSIS
196
+ Resolve the start instant and the baseline values from the passed values, the stored state, and the reset switch.
197
+ .DESCRIPTION
198
+ Start: the passed value, else (with ResetBaseline) NowUtc, else the stored value; with
199
+ none of these a terminating error names -StartUtc and -ResetBaseline. Baseline done:
200
+ the passed value, else (with ResetBaseline) the current done count, else the stored
201
+ value, else 0. Weekly baseline: the passed value, else the stored value, else 0; a
202
+ reset does not capture it. The current done count is not known before the git calls,
203
+ so UseCurrentDone is $true when the caller must substitute it for BaselineDone.
204
+ .PARAMETER StartUtc
205
+ The passed start instant; read only when StartUtcPassed is set.
206
+ .PARAMETER StartUtcPassed
207
+ Whether -StartUtc was passed to the report.
208
+ .PARAMETER BaselineDone
209
+ The passed baseline done count; read only when BaselineDonePassed is set.
210
+ .PARAMETER BaselineDonePassed
211
+ Whether -BaselineDone was passed to the report.
212
+ .PARAMETER BaselineWeeklyPct
213
+ The passed weekly baseline; read only when BaselineWeeklyPctPassed is set.
214
+ .PARAMETER BaselineWeeklyPctPassed
215
+ Whether -BaselineWeeklyPct was passed to the report.
216
+ .PARAMETER State
217
+ The parsed state from ConvertFrom-EpicProgressStateText.
218
+ .PARAMETER ResetBaseline
219
+ Whether the run resets the baseline.
220
+ .PARAMETER NowUtc
221
+ The current instant (UTC).
222
+ #>
223
+ [CmdletBinding()]
224
+ [OutputType([pscustomobject])]
225
+ param(
226
+ [datetime] $StartUtc,
227
+ [switch] $StartUtcPassed,
228
+ [int] $BaselineDone,
229
+ [switch] $BaselineDonePassed,
230
+ [double] $BaselineWeeklyPct,
231
+ [switch] $BaselineWeeklyPctPassed,
232
+ [Parameter(Mandatory = $true)] [pscustomobject] $State,
233
+ [switch] $ResetBaseline,
234
+ [Parameter(Mandatory = $true)] [datetime] $NowUtc
235
+ )
236
+
237
+ if ($StartUtcPassed) {
238
+ $start = $StartUtc.ToUniversalTime()
239
+ } elseif ($ResetBaseline) {
240
+ $start = $NowUtc.ToUniversalTime()
241
+ } elseif ($null -ne $State.StartUnixSeconds) {
242
+ $start = [DateTimeOffset]::FromUnixTimeSeconds([long] $State.StartUnixSeconds).UtcDateTime
243
+ } else {
244
+ throw 'The start instant could not be resolved: pass -StartUtc, or pass -ResetBaseline to start the measurement now; the state file holds no start.'
245
+ }
246
+
247
+ $useCurrentDone = $false
248
+ $done = 0
249
+ if ($BaselineDonePassed) {
250
+ $done = $BaselineDone
251
+ } elseif ($ResetBaseline) {
252
+ $useCurrentDone = $true
253
+ } elseif ($null -ne $State.BaselineDone) {
254
+ $done = [int] $State.BaselineDone
255
+ }
256
+
257
+ $weekly = 0.0
258
+ if ($BaselineWeeklyPctPassed) {
259
+ $weekly = $BaselineWeeklyPct
260
+ } elseif ($null -ne $State.BaselineWeeklyPct) {
261
+ $weekly = [double] $State.BaselineWeeklyPct
262
+ }
263
+
264
+ return [pscustomobject]@{ StartUtc = $start; BaselineDone = $done; BaselineWeeklyPct = $weekly; UseCurrentDone = $useCurrentDone }
265
+ }
266
+
267
+ function Merge-EpicProgressSamplePair {
268
+ <#
269
+ .SYNOPSIS
270
+ Keep the newest sample and every second older sample (indices n-1, n-3, ...), in chronological order.
271
+ .DESCRIPTION
272
+ With k intervals the result has floor(k/2) intervals, each spanning two original
273
+ intervals; when k is odd the oldest interval is discarded. 14 samples become 7, 13
274
+ become 7, 2 become 1, and 1 or 0 samples are returned unchanged. Each application
275
+ doubles the spacing again, so the function is not idempotent.
276
+ .PARAMETER Sample
277
+ The samples in chronological order.
278
+ #>
279
+ [CmdletBinding()]
280
+ [OutputType([object[]])]
281
+ param([Parameter(Mandatory = $true)] [AllowEmptyCollection()] [object[]] $Sample)
282
+
283
+ $kept = [System.Collections.Generic.List[object]]::new()
284
+ for ($index = $Sample.Count - 1; $index -ge 0; $index -= 2) { $kept.Insert(0, $Sample[$index]) }
285
+ return [object[]] $kept.ToArray()
286
+ }