@danmoisan/drm-copilot-mcp 1.1.17 → 1.1.19
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.
- package/out/mcp-server.js +1405 -684
- package/package.json +6 -4
- package/resources/claude-customizations/.claude/agents/atomic-executor.md +11 -0
- package/resources/claude-customizations/.claude/agents/atomic-planner.md +10 -0
- package/resources/claude-customizations/.claude/agents/epic-orchestrator.md +12 -4
- package/resources/claude-customizations/.claude/agents/epic-planner.md +5 -4
- package/resources/claude-customizations/.claude/agents/feature-review.md +16 -5
- package/resources/claude-customizations/.claude/agents/orchestrator.md +21 -7
- package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +37 -13
- package/resources/claude-customizations/.claude/agents/parallel-planner.md +9 -6
- package/resources/claude-customizations/.claude/agents/pr-author.md +15 -2
- package/resources/claude-customizations/.claude/agents/prd-feature.md +1 -1
- package/resources/claude-customizations/.claude/hooks/check-powershell-test-purity.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/check-python-test-purity.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/enforce-checkpoint-monotonic.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/enforce-completion-consistency.ps1 +111 -46
- package/resources/claude-customizations/.claude/hooks/enforce-completion-helpers.ps1 +105 -0
- package/resources/claude-customizations/.claude/hooks/enforce-discovery-artifact-gate.ps1 +8 -1
- package/resources/claude-customizations/.claude/hooks/enforce-epic-invocation-origin.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-resolution.ps1 +116 -59
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +55 -23
- package/resources/claude-customizations/.claude/hooks/enforce-epic-wave-barrier.ps1 +74 -75
- package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate-resolution.ps1 +127 -35
- package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate.ps1 +61 -57
- package/resources/claude-customizations/.claude/hooks/enforce-evidence-locations.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/enforce-feature-folder-order.ps1 +129 -39
- package/resources/claude-customizations/.claude/hooks/enforce-mermaid-validation.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +9 -3
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +39 -51
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +31 -58
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +63 -47
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-targets.ps1 +433 -0
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +17 -12
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-abandon-gate.ps1 +9 -3
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-cohort-barrier.ps1 +65 -50
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-drift-gate.ps1 +49 -42
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +54 -72
- package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +8 -2
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-command-allowlist.ps1 +279 -0
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +129 -75
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.artifact-root.ps1 +233 -0
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.docs-only.ps1 +224 -0
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.ps1 +69 -24
- package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner-helpers.ps1 +29 -18
- package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner.ps1 +10 -4
- package/resources/claude-customizations/.claude/hooks/enforce-promotion-mcp-only.ps1 +14 -5
- package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +8 -2
- package/resources/claude-customizations/.claude/hooks/feature-folder-resolution.ps1 +373 -0
- package/resources/claude-customizations/.claude/hooks/feature-review-coverage-thresholds.ps1 +85 -0
- package/resources/claude-customizations/.claude/hooks/hook-command-heredoc.ps1 +119 -0
- package/resources/claude-customizations/.claude/hooks/hook-command-invocation-operands.ps1 +198 -0
- package/resources/claude-customizations/.claude/hooks/hook-command-invocation.ps1 +254 -255
- package/resources/claude-customizations/.claude/hooks/hook-command-payload-powershell.ps1 +201 -0
- package/resources/claude-customizations/.claude/hooks/hook-command-payload.ps1 +484 -0
- package/resources/claude-customizations/.claude/hooks/hook-command-scanner.ps1 +27 -110
- package/resources/claude-customizations/.claude/hooks/hook-dependency-guard.ps1 +114 -0
- package/resources/claude-customizations/.claude/hooks/hook-docs-only-diff.ps1 +493 -0
- package/resources/claude-customizations/.claude/hooks/subagentstop-envelope.ps1 +192 -0
- package/resources/claude-customizations/.claude/hooks/validate-bash.ps1 +9 -3
- package/resources/claude-customizations/.claude/hooks/validate-discovery-artifact-gate.ps1 +40 -42
- package/resources/claude-customizations/.claude/hooks/validate-executor-output.ps1 +66 -38
- package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage-metrics.ps1 +180 -0
- package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage-rules.ps1 +195 -0
- package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage.ps1 +141 -395
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-resolution.ps1 +311 -0
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-routing.ps1 +170 -0
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +115 -190
- package/resources/claude-customizations/.claude/hooks/validate-planner-output.ps1 +64 -32
- package/resources/claude-customizations/.claude/hooks/validate-pr-author-output.ps1 +39 -44
- package/resources/claude-customizations/.claude/hooks/validate-prd-feature-output.ps1 +43 -14
- package/resources/claude-customizations/.claude/hooks/validate-required-artifact-output.ps1 +66 -36
- package/resources/claude-customizations/.claude/hooks/validate-task-researcher-output.ps1 +31 -34
- package/resources/claude-customizations/.claude/lib/bash/mutate-parallel-run.sh +191 -0
- package/resources/claude-customizations/.claude/lib/bash/parallel-cohorts.sh +13 -3
- package/resources/claude-customizations/.claude/lib/bash/parallel-lane-assertion.sh +4 -2
- package/resources/claude-customizations/.claude/lib/bash/parallel-mutation-cli.sh +152 -0
- package/resources/claude-customizations/.claude/lib/bash/parallel-mutation-ops.sh +193 -0
- package/resources/claude-customizations/.claude/lib/bash/parallel-mutation.sh +322 -0
- package/resources/claude-customizations/.claude/lib/bash/remove-parallel-item.sh +146 -0
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusExtraction.psm1 +23 -33
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusTokenShape.psm1 +86 -6
- package/resources/claude-customizations/.claude/lib/ci-gate/Invoke-CiGateParser.ps1 +91 -19
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorState.psm1 +6 -13
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateEpicWaveBarrier.psm1 +346 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateIssueAdoption.psm1 +396 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateReceipts.psm1 +22 -15
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRemediationAccounting.psm1 +337 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRoutingContract.psm1 +9 -1
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeItemResolution.psm1 +79 -2
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeRunResolution.psm1 +3 -3
- package/resources/claude-customizations/.claude/rules/architecture-boundaries.md +5 -5
- package/resources/claude-customizations/.claude/rules/csharp.md +2 -2
- package/resources/claude-customizations/.claude/rules/general-code-change.md +1 -1
- package/resources/claude-customizations/.claude/rules/general-unit-test.md +3 -2
- package/resources/claude-customizations/.claude/rules/orchestrator-state.md +153 -4
- package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +50 -5
- package/resources/claude-customizations/.claude/rules/plan-acceptance-gates.md +47 -8
- package/resources/claude-customizations/.claude/rules/quality-tiers.md +11 -7
- package/resources/claude-customizations/.claude/rules/shell.md +10 -8
- package/resources/claude-customizations/.claude/rules/typescript.md +1 -1
- package/resources/claude-customizations/.claude/settings.json +3 -4
- package/resources/claude-customizations/.claude/skills/acceptance-criteria-tracking/SKILL.md +9 -1
- package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +7 -1
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +11 -3
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup-worktrees.sh +11 -2
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_detached_lib.sh +1 -1
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_enumerate_lib.sh +171 -5
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_lib.sh +1 -1
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_report_records_lib.sh +6 -43
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_scan_helper.sh +6 -15
- package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +45 -11
- package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +1 -1
- package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
- package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +10 -0
- package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +7 -4
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +42 -16
- package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +52 -14
- package/resources/claude-customizations/.claude/skills/parallel-close/SKILL.md +22 -9
- package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +97 -19
- package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +63 -7
- package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +35 -12
- package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +3 -1
- package/resources/claude-customizations/.claude/skills/quota-throttling/SKILL.md +1 -1
- package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +7 -3
- package/resources/claude-customizations/pack-manifests/core.json +25 -0
- package/resources/codex-and-agents-customizations/.agents/skills/acceptance-criteria-tracking/SKILL.md +9 -1
- package/resources/codex-and-agents-customizations/.agents/skills/architecture-boundaries/SKILL.md +5 -5
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-executor/SKILL.md +11 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-plan-contract/SKILL.md +4 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +10 -0
- package/resources/codex-and-agents-customizations/.agents/skills/csharp/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.agents/skills/csharp-qa-gate/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.agents/skills/epic-orchestrate/SKILL.md +13 -3
- package/resources/codex-and-agents-customizations/.agents/skills/epic-plan/SKILL.md +17 -1
- package/resources/codex-and-agents-customizations/.agents/skills/epic-run/SKILL.md +2 -1
- package/resources/codex-and-agents-customizations/.agents/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
- package/resources/codex-and-agents-customizations/.agents/skills/feature-promotion-lifecycle/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/feature-review/SKILL.md +30 -6
- package/resources/codex-and-agents-customizations/.agents/skills/feature-review-workflow/SKILL.md +16 -6
- package/resources/codex-and-agents-customizations/.agents/skills/general-code-change/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/general-unit-test/SKILL.md +3 -2
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +43 -11
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-state/SKILL.md +41 -2
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +19 -4
- package/resources/codex-and-agents-customizations/.agents/skills/quality-tiers/SKILL.md +11 -7
- package/resources/codex-and-agents-customizations/.agents/skills/remediation-handoff-atomic-planner/SKILL.md +2 -0
- package/resources/codex-and-agents-customizations/.agents/skills/translate-claude-to-codex/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c1.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c2.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3-elevated.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c4.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c1.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c2.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3-elevated.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c4.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/epic-orchestrator.toml +2 -1
- package/resources/codex-and-agents-customizations/.codex/agents/feature-review.toml +6 -6
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c1.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c2.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3-elevated.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c4.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c1.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c2.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3-elevated.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c4.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/codex-web-setup.sh +318 -273
- package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/check-powershell-test-purity.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/check-python-test-purity.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/codex-epic-child-launch-attestation.ps1 +1 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-checkpoint-monotonic.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-codex-model-routing.ps1 +8 -2
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-consistency.ps1 +97 -44
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-helpers.ps1 +105 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-child-worktree-binding.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate.ps1 +37 -5
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-planning-only.ps1 +6 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-root-invocation.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-wave-barrier.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-worktree-removal-gate.ps1 +54 -41
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-evidence-locations.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +35 -14
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +31 -58
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +63 -47
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-targets.ps1 +433 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +24 -11
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +8 -2
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-promotion-mcp-only.ps1 +13 -4
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +8 -2
- package/resources/codex-and-agents-customizations/.codex/hooks/feature-folder-resolution.ps1 +373 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/feature-review-coverage-thresholds.ps1 +85 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-heredoc.ps1 +119 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-invocation-operands.ps1 +198 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-invocation.ps1 +254 -255
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-payload-powershell.ps1 +201 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-payload.ps1 +484 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-scanner.ps1 +27 -110
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-dependency-guard.ps1 +114 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-docs-only-diff.ps1 +493 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-bash.ps1 +8 -2
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-codex-subagent-routing.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-feature-review-coverage.ps1 +24 -8
- package/resources/codex-and-agents-customizations/pack-manifests/core.json +9 -0
- package/resources/customizations/.github/agents/csharp-typed-engineer.agent.md +2 -2
- package/resources/customizations/.github/instructions/csharp-code-change.instructions.md +4 -4
- package/resources/customizations/.github/instructions/csharp-unit-test.instructions.md +2 -2
- package/resources/customizations/.github/skills/acceptance-criteria-tracking/SKILL.md +9 -1
- package/resources/customizations/.github/skills/atomic-plan-contract/SKILL.md +4 -0
- package/resources/customizations/.github/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
- package/resources/customizations/.github/skills/feature-review-workflow/SKILL.md +1 -1
- package/resources/powershell/PoshQC/PoshQC.Coverage.psm1 +314 -0
- package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +25 -28
- package/resources/powershell/PoshQC/PoshQC.psm1 +1 -0
- package/resources/powershell/PoshQC/README.md +8 -2
- package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +2 -315
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
PowerShell port of the epic wave-barrier Layer 2 ordering check (issue #840).
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Ports validate_wave_barrier_ordering (scripts/dev_tools/_epic_orchestrator_state_wave_barrier.py)
|
|
7
|
+
as reached through validate_epic_orchestrator_state_text: feature extraction, the union
|
|
8
|
+
index with lifecycle-prefix normalization, the start guard, and the status and timing
|
|
9
|
+
checks with status-before-timing precedence. For in-parity inputs the violation strings
|
|
10
|
+
are byte-identical to the Python authority.
|
|
11
|
+
|
|
12
|
+
The checkpoint is parsed with System.Text.Json (JsonDocument), not ConvertFrom-Json:
|
|
13
|
+
ConvertFrom-Json coerces ISO-8601 strings to DateTime and reads property names
|
|
14
|
+
case-insensitively, and either behavior would break parity. Properties are read through
|
|
15
|
+
an ordinal, last-definition-wins enumeration, which matches Python json semantics for a
|
|
16
|
+
duplicate key.
|
|
17
|
+
|
|
18
|
+
An input this port does not evaluate fails closed with an error whose message starts
|
|
19
|
+
with EPIC_WAVE_BARRIER_UNEVALUABLE:. The declared divergence classes are listed in
|
|
20
|
+
tests/scripts/claude-lib/orchestrator-state/OrchestratorStateEpicWaveBarrier.Parity.Tests.ps1.
|
|
21
|
+
|
|
22
|
+
.NOTES
|
|
23
|
+
PowerShell 7+. Reads no file and starts no process: the caller supplies checkpoint text
|
|
24
|
+
it has already read. Mirrored byte-identically into the bundled extension payload.
|
|
25
|
+
CONVENTION: this module fails fast at module scope and imports its siblings with -ErrorAction Stop.
|
|
26
|
+
#>
|
|
27
|
+
|
|
28
|
+
Set-StrictMode -Version Latest
|
|
29
|
+
$ErrorActionPreference = 'Stop'
|
|
30
|
+
|
|
31
|
+
# Lifecycle prefixes a folder hint may carry, tested in this order; the first match is stripped.
|
|
32
|
+
$script:LifecyclePrefixes = @('docs/features/active/', 'docs/features/completed/', 'active/', 'completed/')
|
|
33
|
+
|
|
34
|
+
# The merge statuses that durably confirm a dependency edge, and the literal not-started status.
|
|
35
|
+
$script:MergedStatuses = @('merged', 'worktree_removed')
|
|
36
|
+
$script:NotStartedStatus = 'not_started'
|
|
37
|
+
|
|
38
|
+
# A JSON number token that Python reads as an int; any other number token is not compared.
|
|
39
|
+
$script:IntegerTokenPattern = '^-?(0|[1-9][0-9]*)$'
|
|
40
|
+
|
|
41
|
+
# The fail-closed token and the two violation formats of the Python authority.
|
|
42
|
+
$script:UnevaluableToken = 'EPIC_WAVE_BARRIER_UNEVALUABLE:'
|
|
43
|
+
$script:StatusViolationFormat = 'EPIC_WAVE_BARRIER_VIOLATION: {0} is treated as started while dependency {1} is not merged'
|
|
44
|
+
$script:TimingViolationFormat = 'EPIC_WAVE_BARRIER_VIOLATION: {0} worktree_created_at precedes dependency {1} merge_confirmed_at'
|
|
45
|
+
|
|
46
|
+
# Private: the last property of an object element whose name equals Name (ordinal), so a
|
|
47
|
+
# duplicate key resolves the way Python json does. Found is $false when there is none.
|
|
48
|
+
function Get-EpicWaveBarrierProperty {
|
|
49
|
+
[CmdletBinding()]
|
|
50
|
+
[OutputType([pscustomobject])]
|
|
51
|
+
param(
|
|
52
|
+
[Parameter(Mandatory = $true)] [System.Text.Json.JsonElement] $Element,
|
|
53
|
+
[Parameter(Mandatory = $true)] [string] $Name
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
$found = $false
|
|
57
|
+
$value = $null
|
|
58
|
+
foreach ($property in $Element.EnumerateObject()) {
|
|
59
|
+
if ([string]::Equals($property.Name, $Name, [System.StringComparison]::Ordinal)) {
|
|
60
|
+
$found = $true
|
|
61
|
+
$value = $property.Value
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return [pscustomobject]@{ Found = $found; Value = $value }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# Private: the string value of a named property, or $null when it is absent or not a string.
|
|
68
|
+
function Get-EpicWaveBarrierString {
|
|
69
|
+
[CmdletBinding()]
|
|
70
|
+
[OutputType([string])]
|
|
71
|
+
param(
|
|
72
|
+
[Parameter(Mandatory = $true)] [System.Text.Json.JsonElement] $Element,
|
|
73
|
+
[Parameter(Mandatory = $true)] [string] $Name
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
$property = Get-EpicWaveBarrierProperty -Element $Element -Name $Name
|
|
77
|
+
if ($property.Found -and $property.Value.ValueKind -eq [System.Text.Json.JsonValueKind]::String) {
|
|
78
|
+
return $property.Value.GetString()
|
|
79
|
+
}
|
|
80
|
+
return $null
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# Private: strip the first matching lifecycle prefix (ordinal), as _normalize_folder_hint does.
|
|
84
|
+
function ConvertTo-EpicWaveBarrierFolderHint {
|
|
85
|
+
[CmdletBinding()]
|
|
86
|
+
[OutputType([string])]
|
|
87
|
+
param(
|
|
88
|
+
[Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $Value
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
foreach ($prefix in $script:LifecyclePrefixes) {
|
|
92
|
+
if ($Value.StartsWith($prefix, [System.StringComparison]::Ordinal)) {
|
|
93
|
+
return $Value.Substring($prefix.Length)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return $Value
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
# Private: the canonical decimal text of an integer token; BigInteger keeps values beyond
|
|
100
|
+
# 64 bits exact and renders -0 as 0, as Python str(int) does.
|
|
101
|
+
function ConvertTo-EpicWaveBarrierIntegerText {
|
|
102
|
+
[CmdletBinding()]
|
|
103
|
+
[OutputType([string])]
|
|
104
|
+
param(
|
|
105
|
+
[Parameter(Mandatory = $true)] [string] $RawToken
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
$invariant = [System.Globalization.CultureInfo]::InvariantCulture
|
|
109
|
+
return [System.Numerics.BigInteger]::Parse($RawToken, $invariant).ToString($invariant)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
# Private: the union-index key of a JSON number. Python indexes an int by value; a
|
|
113
|
+
# non-integer token is outside parity, so it fails closed rather than being compared.
|
|
114
|
+
function Get-EpicWaveBarrierNumberKey {
|
|
115
|
+
[CmdletBinding()]
|
|
116
|
+
[OutputType([string])]
|
|
117
|
+
param(
|
|
118
|
+
[Parameter(Mandatory = $true)] [System.Text.Json.JsonElement] $Element,
|
|
119
|
+
[Parameter(Mandatory = $true)] [string] $Role,
|
|
120
|
+
[Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $Folder
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
$raw = $Element.GetRawText()
|
|
124
|
+
if ($raw -cnotmatch $script:IntegerTokenPattern) {
|
|
125
|
+
throw ("{0} feature '{1}' has a non-integer numeric {2} token '{3}', which this port does not compare" -f
|
|
126
|
+
$script:UnevaluableToken, $Folder, $Role, $raw)
|
|
127
|
+
}
|
|
128
|
+
return 'n:' + (ConvertTo-EpicWaveBarrierIntegerText -RawToken $raw)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
# Private: render a resolved dependency reference as Python str() renders the raw value.
|
|
132
|
+
# Only strings, booleans, and integer numbers resolve, so no other kind reaches this point.
|
|
133
|
+
function Format-EpicWaveBarrierReference {
|
|
134
|
+
[CmdletBinding()]
|
|
135
|
+
[OutputType([string])]
|
|
136
|
+
param(
|
|
137
|
+
[Parameter(Mandatory = $true)] [System.Text.Json.JsonElement] $Element
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
$kind = $Element.ValueKind
|
|
141
|
+
if ($kind -eq [System.Text.Json.JsonValueKind]::String) { return $Element.GetString() }
|
|
142
|
+
if ($kind -eq [System.Text.Json.JsonValueKind]::True) { return 'True' }
|
|
143
|
+
if ($kind -eq [System.Text.Json.JsonValueKind]::False) { return 'False' }
|
|
144
|
+
return (ConvertTo-EpicWaveBarrierIntegerText -RawToken $Element.GetRawText())
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
# Private: the start guard of feature_has_started. A string worktree_created_at (empty
|
|
148
|
+
# included) starts a feature; otherwise only the exact string not_started leaves it unstarted.
|
|
149
|
+
function Test-EpicWaveBarrierFeatureStarted {
|
|
150
|
+
[CmdletBinding()]
|
|
151
|
+
[OutputType([bool])]
|
|
152
|
+
param(
|
|
153
|
+
[Parameter(Mandatory = $true)] [System.Text.Json.JsonElement] $Feature
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
if ($null -ne (Get-EpicWaveBarrierString -Element $Feature -Name 'worktree_created_at')) { return $true }
|
|
157
|
+
$status = Get-EpicWaveBarrierProperty -Element $Feature -Name 'merge_status'
|
|
158
|
+
if (-not $status.Found) { return $true }
|
|
159
|
+
$isNotStarted = ($status.Value.ValueKind -eq [System.Text.Json.JsonValueKind]::String) -and
|
|
160
|
+
[string]::Equals($status.Value.GetString(), $script:NotStartedStatus, [System.StringComparison]::Ordinal)
|
|
161
|
+
return (-not $isNotStarted)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
# Private: whether a dependency's merge_status is a string equal (ordinal) to a merged status.
|
|
165
|
+
# An absent or non-string status arrives as $null, which the [string] binding turns into an
|
|
166
|
+
# empty string, and an empty string is not a merged status.
|
|
167
|
+
function Test-EpicWaveBarrierMerged {
|
|
168
|
+
[CmdletBinding()]
|
|
169
|
+
[OutputType([bool])]
|
|
170
|
+
param(
|
|
171
|
+
[Parameter(Mandatory = $true)] [AllowNull()] [AllowEmptyString()] [string] $Status
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
foreach ($merged in $script:MergedStatuses) {
|
|
175
|
+
if ([string]::Equals($Status, $merged, [System.StringComparison]::Ordinal)) { return $true }
|
|
176
|
+
}
|
|
177
|
+
return $false
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
# Private: the union-index key of a feature's issue_num, or $null when it is absent, null,
|
|
181
|
+
# or a string (a string issue_num is never matched by a non-string reference).
|
|
182
|
+
function Get-EpicWaveBarrierIssueKey {
|
|
183
|
+
[CmdletBinding()]
|
|
184
|
+
[OutputType([string])]
|
|
185
|
+
param(
|
|
186
|
+
[Parameter(Mandatory = $true)] [System.Text.Json.JsonElement] $Feature,
|
|
187
|
+
[Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $Folder
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
$issue = Get-EpicWaveBarrierProperty -Element $Feature -Name 'issue_num'
|
|
191
|
+
if (-not $issue.Found) { return $null }
|
|
192
|
+
$kind = $issue.Value.ValueKind
|
|
193
|
+
# Routing table: an array or object cannot be hashed by the authority (fail closed);
|
|
194
|
+
# booleans key as 1 and 0 because Python treats True == 1; numbers key by value.
|
|
195
|
+
if ($kind -eq [System.Text.Json.JsonValueKind]::Array -or $kind -eq [System.Text.Json.JsonValueKind]::Object) {
|
|
196
|
+
throw ("{0} feature '{1}' has an issue_num that is an array or object, which the Python authority cannot index" -f
|
|
197
|
+
$script:UnevaluableToken, $Folder)
|
|
198
|
+
}
|
|
199
|
+
if ($kind -eq [System.Text.Json.JsonValueKind]::True) { return 'n:1' }
|
|
200
|
+
if ($kind -eq [System.Text.Json.JsonValueKind]::False) { return 'n:0' }
|
|
201
|
+
if ($kind -eq [System.Text.Json.JsonValueKind]::Number) {
|
|
202
|
+
return (Get-EpicWaveBarrierNumberKey -Element $issue.Value -Role 'issue_num' -Folder $Folder)
|
|
203
|
+
}
|
|
204
|
+
return $null
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
# Private: the object entries of a list-valued features property, in order; empty when the
|
|
208
|
+
# root is not an object or features is absent or not a list.
|
|
209
|
+
function Get-EpicWaveBarrierFeatureEntry {
|
|
210
|
+
[CmdletBinding()]
|
|
211
|
+
[OutputType([System.Text.Json.JsonElement[]], [object[]])]
|
|
212
|
+
param(
|
|
213
|
+
[Parameter(Mandatory = $true)] [System.Text.Json.JsonElement] $Root
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
$entries = [System.Collections.Generic.List[System.Text.Json.JsonElement]]::new()
|
|
217
|
+
if ($Root.ValueKind -ne [System.Text.Json.JsonValueKind]::Object) { return , $entries.ToArray() }
|
|
218
|
+
$features = Get-EpicWaveBarrierProperty -Element $Root -Name 'features'
|
|
219
|
+
if (-not $features.Found -or $features.Value.ValueKind -ne [System.Text.Json.JsonValueKind]::Array) {
|
|
220
|
+
return , $entries.ToArray()
|
|
221
|
+
}
|
|
222
|
+
# Keep only object-shaped entries, as _extract_features does.
|
|
223
|
+
foreach ($item in $features.Value.EnumerateArray()) {
|
|
224
|
+
if ($item.ValueKind -eq [System.Text.Json.JsonValueKind]::Object) { $entries.Add($item) }
|
|
225
|
+
}
|
|
226
|
+
return , $entries.ToArray()
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
# Private: resolve one depends_on element to a feature folder through the union index, or
|
|
230
|
+
# $null. A string consults the folder hints only; a boolean or number consults issue_num only.
|
|
231
|
+
function Resolve-EpicWaveBarrierReference {
|
|
232
|
+
[CmdletBinding()]
|
|
233
|
+
[OutputType([string])]
|
|
234
|
+
param(
|
|
235
|
+
[Parameter(Mandatory = $true)] [System.Text.Json.JsonElement] $Dependency,
|
|
236
|
+
[Parameter(Mandatory = $true)] [System.Collections.Generic.Dictionary[string, string]] $ByHint,
|
|
237
|
+
[Parameter(Mandatory = $true)] [System.Collections.Generic.Dictionary[string, string]] $ByIssue,
|
|
238
|
+
[Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $Folder
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
$kind = $Dependency.ValueKind
|
|
242
|
+
$key = $null
|
|
243
|
+
$map = $ByIssue
|
|
244
|
+
if ($kind -eq [System.Text.Json.JsonValueKind]::String) {
|
|
245
|
+
$key = ConvertTo-EpicWaveBarrierFolderHint -Value $Dependency.GetString()
|
|
246
|
+
$map = $ByHint
|
|
247
|
+
}
|
|
248
|
+
elseif ($kind -eq [System.Text.Json.JsonValueKind]::True) { $key = 'n:1' }
|
|
249
|
+
elseif ($kind -eq [System.Text.Json.JsonValueKind]::False) { $key = 'n:0' }
|
|
250
|
+
elseif ($kind -eq [System.Text.Json.JsonValueKind]::Number) {
|
|
251
|
+
$key = Get-EpicWaveBarrierNumberKey -Element $Dependency -Role 'depends_on reference' -Folder $Folder
|
|
252
|
+
}
|
|
253
|
+
if ($null -eq $key -or -not $map.ContainsKey($key)) { return $null }
|
|
254
|
+
return $map[$key]
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
# Private: the violation lines for the object entries, in feature and depends_on order.
|
|
258
|
+
function Get-EpicWaveBarrierViolation {
|
|
259
|
+
[CmdletBinding()]
|
|
260
|
+
[OutputType([string])]
|
|
261
|
+
param(
|
|
262
|
+
[Parameter(Mandatory = $true)] [AllowEmptyCollection()] [System.Text.Json.JsonElement[]] $Entry
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
$ordinal = [System.StringComparer]::Ordinal
|
|
266
|
+
$byFolder = [System.Collections.Generic.Dictionary[string, System.Text.Json.JsonElement]]::new($ordinal)
|
|
267
|
+
$byHint = [System.Collections.Generic.Dictionary[string, string]]::new($ordinal)
|
|
268
|
+
$byIssue = [System.Collections.Generic.Dictionary[string, string]]::new($ordinal)
|
|
269
|
+
|
|
270
|
+
# Build the lookups: every string folder by name, and every non-empty string folder by
|
|
271
|
+
# its normalized hint and its issue_num. A later duplicate replaces an earlier one.
|
|
272
|
+
foreach ($feature in $Entry) {
|
|
273
|
+
$folder = Get-EpicWaveBarrierString -Element $feature -Name 'feature_folder'
|
|
274
|
+
if ($null -eq $folder) { continue }
|
|
275
|
+
$byFolder[$folder] = $feature
|
|
276
|
+
if ($folder.Length -eq 0) { continue }
|
|
277
|
+
$byHint[(ConvertTo-EpicWaveBarrierFolderHint -Value $folder)] = $folder
|
|
278
|
+
$issueKey = Get-EpicWaveBarrierIssueKey -Feature $feature -Folder $folder
|
|
279
|
+
if ($null -ne $issueKey) { $byIssue[$issueKey] = $folder }
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
# Check every started feature with a list depends_on; each edge yields at most one line,
|
|
283
|
+
# and the status violation takes precedence over the timing violation.
|
|
284
|
+
foreach ($feature in $Entry) {
|
|
285
|
+
$folder = Get-EpicWaveBarrierString -Element $feature -Name 'feature_folder'
|
|
286
|
+
$dependsOn = Get-EpicWaveBarrierProperty -Element $feature -Name 'depends_on'
|
|
287
|
+
if ($null -eq $folder -or -not $dependsOn.Found -or $dependsOn.Value.ValueKind -ne [System.Text.Json.JsonValueKind]::Array) { continue }
|
|
288
|
+
if (-not (Test-EpicWaveBarrierFeatureStarted -Feature $feature)) { continue }
|
|
289
|
+
$created = Get-EpicWaveBarrierString -Element $feature -Name 'worktree_created_at'
|
|
290
|
+
foreach ($dependency in $dependsOn.Value.EnumerateArray()) {
|
|
291
|
+
$resolved = Resolve-EpicWaveBarrierReference -Dependency $dependency -ByHint $byHint -ByIssue $byIssue -Folder $folder
|
|
292
|
+
if ($null -eq $resolved -or -not $byFolder.ContainsKey($resolved)) { continue }
|
|
293
|
+
$target = $byFolder[$resolved]
|
|
294
|
+
$reference = Format-EpicWaveBarrierReference -Element $dependency
|
|
295
|
+
if (-not (Test-EpicWaveBarrierMerged -Status (Get-EpicWaveBarrierString -Element $target -Name 'merge_status'))) {
|
|
296
|
+
$script:StatusViolationFormat -f $folder, $reference
|
|
297
|
+
continue
|
|
298
|
+
}
|
|
299
|
+
$confirmed = Get-EpicWaveBarrierString -Element $target -Name 'merge_confirmed_at'
|
|
300
|
+
if ($null -ne $confirmed -and $null -ne $created -and [string]::CompareOrdinal($confirmed, $created) -gt 0) {
|
|
301
|
+
$script:TimingViolationFormat -f $folder, $reference
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function Get-OrchestratorStateEpicWaveBarrierError {
|
|
308
|
+
<#
|
|
309
|
+
.SYNOPSIS
|
|
310
|
+
Return the EPIC_WAVE_BARRIER_VIOLATION lines for an epic checkpoint's text.
|
|
311
|
+
.DESCRIPTION
|
|
312
|
+
Parses the text with System.Text.Json default options and applies the Layer 2
|
|
313
|
+
ordering check. Returns an empty array when there is no violation, when the root is
|
|
314
|
+
not an object, or when features is absent or not a list. Throws an error whose
|
|
315
|
+
message starts with EPIC_WAVE_BARRIER_UNEVALUABLE: for text System.Text.Json does
|
|
316
|
+
not parse (including NaN or Infinity literals and nesting deeper than 64 levels), an
|
|
317
|
+
array or object issue_num, and a non-integer number token that the check consults.
|
|
318
|
+
.PARAMETER CheckpointText
|
|
319
|
+
The raw epic checkpoint JSON text.
|
|
320
|
+
.OUTPUTS
|
|
321
|
+
System.String[]
|
|
322
|
+
#>
|
|
323
|
+
[CmdletBinding()]
|
|
324
|
+
[OutputType([string[]], [object[]])]
|
|
325
|
+
param(
|
|
326
|
+
[Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $CheckpointText
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
$document = $null
|
|
330
|
+
try {
|
|
331
|
+
$document = [System.Text.Json.JsonDocument]::Parse($CheckpointText, [System.Text.Json.JsonDocumentOptions]::new())
|
|
332
|
+
}
|
|
333
|
+
catch {
|
|
334
|
+
throw ('{0} the checkpoint is not parseable by System.Text.Json with default options (a non-standard literal such as NaN or Infinity, or nesting deeper than 64 levels): {1}' -f
|
|
335
|
+
$script:UnevaluableToken, $_.Exception.Message)
|
|
336
|
+
}
|
|
337
|
+
try {
|
|
338
|
+
$entries = Get-EpicWaveBarrierFeatureEntry -Root $document.RootElement
|
|
339
|
+
return , [string[]] @(Get-EpicWaveBarrierViolation -Entry $entries)
|
|
340
|
+
}
|
|
341
|
+
finally {
|
|
342
|
+
$document.Dispose()
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
Export-ModuleMember -Function Get-OrchestratorStateEpicWaveBarrierError
|