@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
package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-resolution.ps1
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Checkpoint resolution and Layer 2 decision helpers for validate-orchestrator-output.ps1 (issues #787, #840).
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Dot-sourced by validate-orchestrator-output.ps1. Resolves the run checkpoint that a
|
|
7
|
+
SubagentStop validation reads through the exported functions of
|
|
8
|
+
WorktreeRunResolution.psm1 and Get-WorktreeItemLiveRoot (WorktreeItemResolution.psm1)
|
|
9
|
+
only, so the hook evaluates the checkpoint of the run that stopped rather than whatever
|
|
10
|
+
file sits at a session-relative path. The payload cwd is never used as a target selector.
|
|
11
|
+
|
|
12
|
+
Per artifact type: orchestrator-state resolves the enclosing worktree of the session
|
|
13
|
+
root; epic-orchestrator-state and parallel-orchestrator-state resolve from the
|
|
14
|
+
integration_branch: or parallel_slug: literal in the agent output, and otherwise from the
|
|
15
|
+
single distinct value recorded by the live worktrees' run checkpoints. A bound
|
|
16
|
+
-CheckpointPath is a repository-relative leaf that must compose the canonical checkpoint
|
|
17
|
+
path beneath the resolved root.
|
|
18
|
+
|
|
19
|
+
Reads no file except through Get-WorktreeRunCheckpointText and the
|
|
20
|
+
Test-OrchestratorOutputRunbookFile seam. Starts no process and invokes no Python.
|
|
21
|
+
#>
|
|
22
|
+
|
|
23
|
+
# The run kind each supported artifact type resolves as.
|
|
24
|
+
$script:OrchestratorOutputRunKind = @{
|
|
25
|
+
'orchestrator-state' = 'item'
|
|
26
|
+
'epic-orchestrator-state' = 'epic'
|
|
27
|
+
'parallel-orchestrator-state' = 'parallel'
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
# Reason codes. The first two equal the WorktreeResolution.psm1 accessor values, which the
|
|
31
|
+
# sibling suite asserts, because this file calls no accessor of that module.
|
|
32
|
+
$script:OrchestratorOutputAmbiguousReasonCode = 'TARGET_WORKTREE_AMBIGUOUS'
|
|
33
|
+
$script:OrchestratorOutputNoTargetReasonCode = 'TARGET_WORKTREE_NOT_DERIVABLE'
|
|
34
|
+
$script:OrchestratorOutputMismatchReasonCode = 'CHECKPOINT_PATH_MISMATCH'
|
|
35
|
+
|
|
36
|
+
# The fixed instruction that follows Layer 2 violation lines, and the unevaluable token.
|
|
37
|
+
$script:OrchestratorOutputHaltInstruction = 'orchestrator hook: the lines above record a wave-barrier ordering violation in the epic checkpoint that this agent cannot clear. Report them to the operator and halt.'
|
|
38
|
+
$script:OrchestratorOutputUnevaluableToken = 'EPIC_WAVE_BARRIER_UNEVALUABLE:'
|
|
39
|
+
|
|
40
|
+
function ConvertTo-OrchestratorOutputResolution {
|
|
41
|
+
<#
|
|
42
|
+
.SYNOPSIS
|
|
43
|
+
Build the resolution result object.
|
|
44
|
+
.DESCRIPTION
|
|
45
|
+
Returns an object with exactly Resolved, CheckpointPath, WorktreeRoot, Status,
|
|
46
|
+
ReasonCode, and Detail; a value that is not supplied is $null.
|
|
47
|
+
#>
|
|
48
|
+
[CmdletBinding()]
|
|
49
|
+
[OutputType([pscustomobject])]
|
|
50
|
+
param(
|
|
51
|
+
[Parameter(Mandatory = $true)] [bool] $Resolved,
|
|
52
|
+
[AllowNull()] [object] $CheckpointPath = $null,
|
|
53
|
+
[AllowNull()] [object] $WorktreeRoot = $null,
|
|
54
|
+
[Parameter(Mandatory = $true)] [string] $Status,
|
|
55
|
+
[AllowNull()] [object] $ReasonCode = $null,
|
|
56
|
+
[Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $Detail
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
return [pscustomobject]@{
|
|
60
|
+
Resolved = $Resolved
|
|
61
|
+
CheckpointPath = $CheckpointPath
|
|
62
|
+
WorktreeRoot = $WorktreeRoot
|
|
63
|
+
Status = $Status
|
|
64
|
+
ReasonCode = $ReasonCode
|
|
65
|
+
Detail = $Detail
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function Test-OrchestratorOutputCheckpointLeafShape {
|
|
70
|
+
<#
|
|
71
|
+
.SYNOPSIS
|
|
72
|
+
Check that a -CheckpointPath value is a non-empty repository-relative leaf.
|
|
73
|
+
.DESCRIPTION
|
|
74
|
+
Pure. Normalizes the value (trim, forward slashes, no repeated separator, no leading
|
|
75
|
+
./) and returns @{ Ok; Leaf; Detail }. A blank, rooted, or parent-escaping value is
|
|
76
|
+
not Ok.
|
|
77
|
+
#>
|
|
78
|
+
[CmdletBinding()]
|
|
79
|
+
[OutputType([hashtable])]
|
|
80
|
+
param(
|
|
81
|
+
[Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $CheckpointPath
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
$leaf = ($CheckpointPath.Trim() -replace '\\', '/') -replace '/{2,}', '/'
|
|
85
|
+
while ($leaf.StartsWith('./')) { $leaf = $leaf.Substring(2) }
|
|
86
|
+
|
|
87
|
+
# Decision order: blank first, then rooted, then a .. segment; each names the value.
|
|
88
|
+
if ([string]::IsNullOrWhiteSpace($leaf)) {
|
|
89
|
+
return @{ Ok = $false; Leaf = $null; Detail = 'the -CheckpointPath value is empty' }
|
|
90
|
+
}
|
|
91
|
+
if ($leaf -match '^([A-Za-z]:|/)') {
|
|
92
|
+
return @{ Ok = $false; Leaf = $null; Detail = ("the -CheckpointPath value '{0}' is rooted; it must be a repository-relative path" -f $CheckpointPath) }
|
|
93
|
+
}
|
|
94
|
+
if (@($leaf -split '/') -contains '..') {
|
|
95
|
+
return @{ Ok = $false; Leaf = $null; Detail = ("the -CheckpointPath value '{0}' escapes the worktree root" -f $CheckpointPath) }
|
|
96
|
+
}
|
|
97
|
+
return @{ Ok = $true; Leaf = $leaf; Detail = $null }
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function Test-OrchestratorOutputCheckpointLeaf {
|
|
101
|
+
<#
|
|
102
|
+
.SYNOPSIS
|
|
103
|
+
Cross-check a -CheckpointPath leaf against the canonical checkpoint of a run kind.
|
|
104
|
+
.DESCRIPTION
|
|
105
|
+
Composes the leaf beneath the resolved root and requires an ordinal match with
|
|
106
|
+
Get-WorktreeRunCheckpointPath for the kind. Returns @{ Ok; CanonicalPath; Detail }.
|
|
107
|
+
#>
|
|
108
|
+
[CmdletBinding()]
|
|
109
|
+
[OutputType([hashtable])]
|
|
110
|
+
param(
|
|
111
|
+
[Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $CheckpointPath,
|
|
112
|
+
[Parameter(Mandatory = $true)] [ValidateSet('epic', 'parallel', 'item')] [string] $Kind,
|
|
113
|
+
[Parameter(Mandatory = $true)] [string] $WorktreeRoot
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
$shape = Test-OrchestratorOutputCheckpointLeafShape -CheckpointPath $CheckpointPath
|
|
117
|
+
if (-not $shape.Ok) { return @{ Ok = $false; CanonicalPath = $null; Detail = $shape.Detail } }
|
|
118
|
+
$canonical = Get-WorktreeRunCheckpointPath -Kind $Kind -WorktreeRoot $WorktreeRoot
|
|
119
|
+
$composed = (($WorktreeRoot.Trim() -replace '\\', '/').TrimEnd('/')) + '/' + $shape.Leaf
|
|
120
|
+
if ($composed -ceq $canonical) { return @{ Ok = $true; CanonicalPath = $canonical; Detail = $null } }
|
|
121
|
+
return @{
|
|
122
|
+
Ok = $false
|
|
123
|
+
CanonicalPath = $canonical
|
|
124
|
+
Detail = ("the -CheckpointPath value '{0}' composes '{1}' beneath the resolved root, which is not the canonical {2} checkpoint '{3}'" -f
|
|
125
|
+
$CheckpointPath, $composed, $Kind, $canonical)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function Find-OrchestratorOutputRunSignalValue {
|
|
130
|
+
<#
|
|
131
|
+
.SYNOPSIS
|
|
132
|
+
Collect the distinct run identity values recorded by the live worktrees' checkpoints.
|
|
133
|
+
.DESCRIPTION
|
|
134
|
+
For kind epic, the integration_branch of every checkpoint with route_id epic; for
|
|
135
|
+
kind parallel, the parallel_slug of every checkpoint with route_id parallel. Blank,
|
|
136
|
+
unparseable, non-object, and off-route checkpoints are skipped. Values are distinct
|
|
137
|
+
under ordinal comparison and kept in discovery order.
|
|
138
|
+
#>
|
|
139
|
+
[CmdletBinding()]
|
|
140
|
+
[OutputType([string[]], [object[]])]
|
|
141
|
+
param(
|
|
142
|
+
[Parameter(Mandatory = $true)] [ValidateSet('epic', 'parallel')] [string] $Kind,
|
|
143
|
+
[Parameter(Mandatory = $true)] [string] $SessionRoot
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
$field = if ($Kind -eq 'epic') { 'integration_branch' } else { 'parallel_slug' }
|
|
147
|
+
$route = if ($Kind -eq 'epic') { 'epic' } else { 'parallel' }
|
|
148
|
+
$values = [System.Collections.Generic.List[string]]::new()
|
|
149
|
+
# The seam returns its array as one object, so it is assigned before it is iterated.
|
|
150
|
+
$liveRoots = Get-WorktreeItemLiveRoot -SessionRoot $SessionRoot
|
|
151
|
+
foreach ($root in $liveRoots) {
|
|
152
|
+
if ([string]::IsNullOrWhiteSpace($root)) { continue }
|
|
153
|
+
$text = Get-WorktreeRunCheckpointText -Path (Get-WorktreeRunCheckpointPath -Kind $Kind -WorktreeRoot $root)
|
|
154
|
+
if ([string]::IsNullOrWhiteSpace($text)) { continue }
|
|
155
|
+
try { $parsed = ConvertFrom-Json -InputObject $text -NoEnumerate -ErrorAction Stop } catch { continue }
|
|
156
|
+
if ($parsed -isnot [System.Management.Automation.PSCustomObject]) { continue }
|
|
157
|
+
$names = @($parsed.PSObject.Properties.Name)
|
|
158
|
+
if (-not ($names -contains 'route_id') -or ([string]$parsed.route_id -cne $route)) { continue }
|
|
159
|
+
if (-not ($names -contains $field)) { continue }
|
|
160
|
+
$value = $parsed.$field
|
|
161
|
+
if ($value -isnot [string] -or [string]::IsNullOrWhiteSpace($value)) { continue }
|
|
162
|
+
if (-not $values.Contains($value)) { $values.Add($value) }
|
|
163
|
+
}
|
|
164
|
+
return , $values.ToArray()
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function Resolve-OrchestratorOutputCheckpointPath {
|
|
168
|
+
<#
|
|
169
|
+
.SYNOPSIS
|
|
170
|
+
Resolve the absolute run checkpoint path for a SubagentStop validation.
|
|
171
|
+
.DESCRIPTION
|
|
172
|
+
Returns the ConvertTo-OrchestratorOutputResolution object. Resolved is $true only
|
|
173
|
+
when exactly one target resolves and the -CheckpointPath leaf composes its canonical
|
|
174
|
+
checkpoint path; otherwise Status, ReasonCode, and Detail name the failure. A
|
|
175
|
+
rejected -CheckpointPath is detected before any resolver call.
|
|
176
|
+
.PARAMETER ArtifactType
|
|
177
|
+
orchestrator-state, epic-orchestrator-state, or parallel-orchestrator-state.
|
|
178
|
+
.PARAMETER CheckpointPath
|
|
179
|
+
The bound repository-relative checkpoint leaf.
|
|
180
|
+
.PARAMETER AgentOutput
|
|
181
|
+
The agent's final output text, scanned for the run identity literals.
|
|
182
|
+
.PARAMETER SessionRoot
|
|
183
|
+
The calling process's path, used only to find the repository.
|
|
184
|
+
#>
|
|
185
|
+
[CmdletBinding()]
|
|
186
|
+
[OutputType([pscustomobject])]
|
|
187
|
+
param(
|
|
188
|
+
[Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $ArtifactType,
|
|
189
|
+
[Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $CheckpointPath,
|
|
190
|
+
[Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $AgentOutput,
|
|
191
|
+
[Parameter(Mandatory = $true)] [string] $SessionRoot
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
if (-not $script:OrchestratorOutputRunKind.ContainsKey($ArtifactType)) {
|
|
195
|
+
return (ConvertTo-OrchestratorOutputResolution -Resolved $false -Status 'NoTarget' -ReasonCode $script:OrchestratorOutputNoTargetReasonCode -Detail (
|
|
196
|
+
"unsupported artifact type '{0}'; supported types: orchestrator-state, epic-orchestrator-state, parallel-orchestrator-state" -f $ArtifactType))
|
|
197
|
+
}
|
|
198
|
+
$kind = $script:OrchestratorOutputRunKind[$ArtifactType]
|
|
199
|
+
|
|
200
|
+
# A malformed leaf is rejected before any resolver call, so nothing is read for it.
|
|
201
|
+
$shape = Test-OrchestratorOutputCheckpointLeafShape -CheckpointPath $CheckpointPath
|
|
202
|
+
if (-not $shape.Ok) {
|
|
203
|
+
return (ConvertTo-OrchestratorOutputResolution -Resolved $false -Status 'Rejected' -ReasonCode $script:OrchestratorOutputMismatchReasonCode -Detail $shape.Detail)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
# Routing table: item resolves the session worktree; epic and parallel take the agent
|
|
207
|
+
# output's literal first and fall back to discovery over the live run checkpoints.
|
|
208
|
+
if ($kind -eq 'item') {
|
|
209
|
+
$target = Resolve-WorktreeOperandTarget -Path '' -SessionRoot $SessionRoot
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
$signal = Find-WorktreeRunIdentitySignal -Text $AgentOutput
|
|
213
|
+
$field = if ($kind -eq 'epic') { 'integration_branch' } else { 'parallel_slug' }
|
|
214
|
+
$identity = if ($kind -eq 'epic') { $signal.IntegrationBranch } else { $signal.ParallelSlug }
|
|
215
|
+
if ([string]::IsNullOrWhiteSpace($identity)) {
|
|
216
|
+
$discovered = [System.Collections.Generic.List[string]]::new()
|
|
217
|
+
foreach ($value in (Find-OrchestratorOutputRunSignalValue -Kind $kind -SessionRoot $SessionRoot)) { $discovered.Add([string]$value) }
|
|
218
|
+
if ($discovered.Count -gt 1) {
|
|
219
|
+
$detail = ("the {0} checkpoints of live worktrees record {1} distinct {2} values ({3}), and the agent output names no {2}: value" -f
|
|
220
|
+
$kind, $discovered.Count, $field, ($discovered -join ', '))
|
|
221
|
+
return (ConvertTo-OrchestratorOutputResolution -Resolved $false -Status 'Ambiguous' -ReasonCode $script:OrchestratorOutputAmbiguousReasonCode -Detail $detail)
|
|
222
|
+
}
|
|
223
|
+
$identity = if ($discovered.Count -eq 1) { $discovered[0] } else { '' }
|
|
224
|
+
}
|
|
225
|
+
$target = if ($kind -eq 'epic') {
|
|
226
|
+
Resolve-WorktreeEpicTarget -IntegrationBranch $identity -EpicSlug $signal.EpicSlug -SessionRoot $SessionRoot
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
Resolve-WorktreeParallelTarget -ParallelSlug $identity -SessionRoot $SessionRoot
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if ($target.Status -in @('NoTarget', 'Ambiguous')) {
|
|
234
|
+
return (ConvertTo-OrchestratorOutputResolution -Resolved $false -Status $target.Status -ReasonCode $target.ReasonCode -Detail $target.Detail)
|
|
235
|
+
}
|
|
236
|
+
$leaf = Test-OrchestratorOutputCheckpointLeaf -CheckpointPath $CheckpointPath -Kind $kind -WorktreeRoot $target.WorktreeRoot
|
|
237
|
+
if (-not $leaf.Ok) {
|
|
238
|
+
return (ConvertTo-OrchestratorOutputResolution -Resolved $false -Status 'Rejected' -ReasonCode $script:OrchestratorOutputMismatchReasonCode -Detail $leaf.Detail)
|
|
239
|
+
}
|
|
240
|
+
return (ConvertTo-OrchestratorOutputResolution -Resolved $true -CheckpointPath $leaf.CanonicalPath -WorktreeRoot $target.WorktreeRoot -Status $target.Status -Detail $target.Detail)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function Resolve-OrchestratorOutputRunbookPath {
|
|
244
|
+
<#
|
|
245
|
+
.SYNOPSIS
|
|
246
|
+
Place a runbook_path beneath the resolved worktree root.
|
|
247
|
+
.DESCRIPTION
|
|
248
|
+
Pure. A rooted value is returned with forward slashes; a relative value has any
|
|
249
|
+
leading ./ removed and is joined beneath the root.
|
|
250
|
+
#>
|
|
251
|
+
[CmdletBinding()]
|
|
252
|
+
[OutputType([string])]
|
|
253
|
+
param(
|
|
254
|
+
[Parameter(Mandatory = $true)] [string] $WorktreeRoot,
|
|
255
|
+
[Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $RunbookPath
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
$path = ([string]$RunbookPath).Trim() -replace '\\', '/'
|
|
259
|
+
if ($path -match '^([A-Za-z]:/|/)') { return $path }
|
|
260
|
+
while ($path.StartsWith('./')) { $path = $path.Substring(2) }
|
|
261
|
+
return ((($WorktreeRoot.Trim() -replace '\\', '/').TrimEnd('/')) + '/' + $path.TrimStart('/'))
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function Test-OrchestratorOutputRunbookFile {
|
|
265
|
+
<#
|
|
266
|
+
.SYNOPSIS
|
|
267
|
+
The runbook existence seam: $true when the path is an existing file.
|
|
268
|
+
#>
|
|
269
|
+
[CmdletBinding()]
|
|
270
|
+
[OutputType([bool])]
|
|
271
|
+
param(
|
|
272
|
+
[Parameter(Mandatory = $true)] [string] $Path
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
return (Test-Path -LiteralPath $Path -PathType Leaf)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function Get-OrchestratorOutputWaveBarrierDecision {
|
|
279
|
+
<#
|
|
280
|
+
.SYNOPSIS
|
|
281
|
+
Run the Layer 2 wave-barrier ordering check on epic checkpoint text.
|
|
282
|
+
.DESCRIPTION
|
|
283
|
+
Returns @{ Ok; Message } on success and @{ Ok; Repairable; Message } on a block, with
|
|
284
|
+
Repairable set to $false on every block (the agent cannot clear it, so it blocks once under
|
|
285
|
+
the re-entry policy of issue #903). Violation lines are surfaced unwrapped and followed by
|
|
286
|
+
the fixed report-and-halt instruction. A failed port import, an
|
|
287
|
+
EPIC_WAVE_BARRIER_UNEVALUABLE: error, or any other port failure blocks with a
|
|
288
|
+
message that starts with EPIC_WAVE_BARRIER_UNEVALUABLE:.
|
|
289
|
+
#>
|
|
290
|
+
[CmdletBinding()]
|
|
291
|
+
[OutputType([hashtable])]
|
|
292
|
+
param(
|
|
293
|
+
[Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $CheckpointText
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
$lines = [System.Collections.Generic.List[string]]::new()
|
|
297
|
+
try {
|
|
298
|
+
foreach ($line in (Get-OrchestratorStateEpicWaveBarrierError -CheckpointText $CheckpointText)) { $lines.Add([string]$line) }
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
$message = $_.Exception.Message
|
|
302
|
+
if ($message.StartsWith($script:OrchestratorOutputUnevaluableToken, [System.StringComparison]::Ordinal)) {
|
|
303
|
+
return @{ Ok = $false; Repairable = $false; Message = $message }
|
|
304
|
+
}
|
|
305
|
+
return @{ Ok = $false; Repairable = $false; Message = ('{0} the wave-barrier ordering check failed: {1}' -f $script:OrchestratorOutputUnevaluableToken, $message) }
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if ($lines.Count -eq 0) { return @{ Ok = $true; Message = $null } }
|
|
309
|
+
$lines.Add($script:OrchestratorOutputHaltInstruction)
|
|
310
|
+
return @{ Ok = $false; Repairable = $false; Message = ($lines -join "`n") }
|
|
311
|
+
}
|
package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-routing.ps1
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Routing-contract dispatch for the orchestrator SubagentStop hook validate-orchestrator-output.ps1 (issue #903).
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Dot-sourced by validate-orchestrator-output.ps1 through a guarded load whose catch records the
|
|
7
|
+
failure with Add-HookDependencyFailure, so a missing or broken copy of this file blocks the
|
|
8
|
+
hook instead of failing open. It defines Test-OrchestratorCheckpointStructure and
|
|
9
|
+
Invoke-RoutingContractValidation, moved unchanged from the main hook file to keep that file
|
|
10
|
+
under the 500-line cap.
|
|
11
|
+
|
|
12
|
+
The default Invoker of Invoke-RoutingContractValidation resolves
|
|
13
|
+
../lib/orchestrator-state/OrchestratorStateCompletion.psm1 from $PSScriptRoot, which is the
|
|
14
|
+
same directory for this dot-sourced file as for the main hook. The file starts no process
|
|
15
|
+
and invokes no Python.
|
|
16
|
+
#>
|
|
17
|
+
|
|
18
|
+
function Test-OrchestratorCheckpointStructure {
|
|
19
|
+
<#
|
|
20
|
+
.SYNOPSIS
|
|
21
|
+
Type-scoped structural check for the epic and parallel checkpoint types.
|
|
22
|
+
.DESCRIPTION
|
|
23
|
+
PD-3 implementation. The Python reference exposes no validation surface for
|
|
24
|
+
`epic-orchestrator-state` or `parallel-orchestrator-state` under this hook's
|
|
25
|
+
flag pair: argparse rejects the pair and exits 2 without running a single
|
|
26
|
+
check, so parity is UNDEFINED in this region. Rather than inherit an
|
|
27
|
+
undefined behavior, this hook defines it: the checkpoint must exist, parse
|
|
28
|
+
as JSON, and have an object root. That is the largest assertion that holds
|
|
29
|
+
for every checkpoint type without importing a schema this hook does not own.
|
|
30
|
+
|
|
31
|
+
Deliberately NOT applied here:
|
|
32
|
+
- the standard-checkpoint REQUIRED_STATE_KEYS presence block, whose key
|
|
33
|
+
set belongs to the standard checkpoint and would produce false
|
|
34
|
+
ROUTING_CONTRACT_BLOCKED verdicts against a well-formed epic or
|
|
35
|
+
parallel checkpoint (defect D-1),
|
|
36
|
+
- the model-routing gate, whose receipts live on the standard checkpoint.
|
|
37
|
+
|
|
38
|
+
The check fails closed: a missing file, unreadable content, invalid JSON, or
|
|
39
|
+
a non-object root all yield ExitCode 1 with the load error as Output.
|
|
40
|
+
.PARAMETER CheckpointPath
|
|
41
|
+
The path to the checkpoint JSON file.
|
|
42
|
+
.OUTPUTS
|
|
43
|
+
System.Collections.Hashtable with keys ExitCode (int, 0 or 1) and Output (string).
|
|
44
|
+
#>
|
|
45
|
+
[CmdletBinding()]
|
|
46
|
+
[OutputType([hashtable])]
|
|
47
|
+
param(
|
|
48
|
+
[Parameter(Mandatory = $true)]
|
|
49
|
+
[string] $CheckpointPath
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# Get-OrchestratorStateCheckpoint already implements exactly the three
|
|
53
|
+
# structural conditions (exists, parses, object root) and reports each as a
|
|
54
|
+
# fail-closed Error string, so the structural leg reuses it rather than
|
|
55
|
+
# duplicating the load contract.
|
|
56
|
+
$loaded = Get-OrchestratorStateCheckpoint -CheckpointPath $CheckpointPath
|
|
57
|
+
if (-not $loaded.Ok) {
|
|
58
|
+
return @{ ExitCode = 1; Output = $loaded.Error }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return @{ ExitCode = 0; Output = '' }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function Invoke-RoutingContractValidation {
|
|
65
|
+
<#
|
|
66
|
+
.SYNOPSIS
|
|
67
|
+
Runs the portable routing-contract validation against the on-disk
|
|
68
|
+
checkpoint and reports whether it emitted errors.
|
|
69
|
+
.DESCRIPTION
|
|
70
|
+
Invokes the validation through an injectable scriptblock seam. As of issue
|
|
71
|
+
#475 the default Invoker names no interpreter and starts no subprocess: the
|
|
72
|
+
portable PowerShell path is the ONLY path, so the hook behaves identically
|
|
73
|
+
in this repository and in every destination that received only the
|
|
74
|
+
pushed-down `.claude` pack. The former capability-detection probe and the
|
|
75
|
+
interpreter-subprocess leg it guarded are both gone.
|
|
76
|
+
|
|
77
|
+
The default Invoker dispatches on ArtifactType:
|
|
78
|
+
|
|
79
|
+
orchestrator-state
|
|
80
|
+
the COMPLETE-PARITY completion validation
|
|
81
|
+
(Test-OrchestratorStateCompletionReadiness), a row-by-row port of the
|
|
82
|
+
Python call surface `--require-complete --require-model-routing`.
|
|
83
|
+
|
|
84
|
+
epic-orchestrator-state, parallel-orchestrator-state
|
|
85
|
+
the type-scoped structural check
|
|
86
|
+
(Test-OrchestratorCheckpointStructure): exists, parses as JSON,
|
|
87
|
+
object root. PD-3: this is DEFINED behavior in a region where Python
|
|
88
|
+
parity is UNDEFINED (argparse exit 2, zero checks run). It is a
|
|
89
|
+
design decision, not a deferral. The standard-checkpoint
|
|
90
|
+
REQUIRED_STATE_KEYS block and the model-routing gate are deliberately
|
|
91
|
+
not applied, which is the D-1 fix.
|
|
92
|
+
|
|
93
|
+
anything else
|
|
94
|
+
fail closed, naming the unsupported type. An unrecognized type must
|
|
95
|
+
never read as a clean pass.
|
|
96
|
+
|
|
97
|
+
ArtifactType defaults to 'orchestrator-state' so every existing caller of
|
|
98
|
+
this hook keeps its current behavior.
|
|
99
|
+
|
|
100
|
+
Returns a hashtable with keys:
|
|
101
|
+
- HasErrors: $true only when the validation reported a non-zero exit
|
|
102
|
+
code; $false when it exited 0. The exit code is the sole
|
|
103
|
+
discriminator.
|
|
104
|
+
- ErrorText: the validation's output text, carried through unchanged:
|
|
105
|
+
the error lines on a failure, empty on a clean pass.
|
|
106
|
+
#>
|
|
107
|
+
[CmdletBinding()]
|
|
108
|
+
[OutputType([hashtable])]
|
|
109
|
+
param(
|
|
110
|
+
[Parameter(Mandatory = $true)]
|
|
111
|
+
[string] $CheckpointPath,
|
|
112
|
+
|
|
113
|
+
[Parameter(Mandatory = $false)]
|
|
114
|
+
[string] $ArtifactType = 'orchestrator-state',
|
|
115
|
+
|
|
116
|
+
[Parameter(Mandatory = $false)]
|
|
117
|
+
[scriptblock] $Invoker = {
|
|
118
|
+
param($Path, $Type)
|
|
119
|
+
switch ($Type) {
|
|
120
|
+
'orchestrator-state' {
|
|
121
|
+
# Import the portable completion module only when its function is not
|
|
122
|
+
# already available, so a repeated call (or a test that pre-imports and
|
|
123
|
+
# mocks the function) does not reload the module and reset the seam.
|
|
124
|
+
if (-not (Get-Command -Name Test-OrchestratorStateCompletionReadiness -ErrorAction SilentlyContinue)) {
|
|
125
|
+
Import-Module (Join-Path $PSScriptRoot '../lib/orchestrator-state/OrchestratorStateCompletion.psm1') -Force
|
|
126
|
+
}
|
|
127
|
+
$portable = Test-OrchestratorStateCompletionReadiness -CheckpointPath $Path
|
|
128
|
+
[pscustomobject]@{
|
|
129
|
+
ExitCode = $portable.ExitCode
|
|
130
|
+
Output = $portable.Output
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
{ $_ -in @('epic-orchestrator-state', 'parallel-orchestrator-state') } {
|
|
134
|
+
# PD-3: defined fail-closed structural behavior in an
|
|
135
|
+
# undefined-parity region. See Test-OrchestratorCheckpointStructure.
|
|
136
|
+
$structural = Test-OrchestratorCheckpointStructure -CheckpointPath $Path
|
|
137
|
+
[pscustomobject]@{
|
|
138
|
+
ExitCode = $structural.ExitCode
|
|
139
|
+
Output = $structural.Output
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
default {
|
|
143
|
+
# Fail closed on an unwired type: an unrecognized artifact type is
|
|
144
|
+
# not a clean pass.
|
|
145
|
+
[pscustomobject]@{
|
|
146
|
+
ExitCode = 1
|
|
147
|
+
Output = "orchestrator hook: unsupported artifact type '$Type'; no validation surface is wired for it. Supported types: orchestrator-state, epic-orchestrator-state, parallel-orchestrator-state."
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
$result = & $Invoker $CheckpointPath $ArtifactType
|
|
155
|
+
$exitCode = 0
|
|
156
|
+
if ($null -ne $result -and ($result.PSObject.Properties.Name -contains 'ExitCode')) {
|
|
157
|
+
$exitCode = [int]$result.ExitCode
|
|
158
|
+
}
|
|
159
|
+
$outputText = ''
|
|
160
|
+
if ($null -ne $result -and ($result.PSObject.Properties.Name -contains 'Output')) {
|
|
161
|
+
$outputText = ([string]$result.Output).Trim()
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
# The exit code is the complete failure discriminator: every dispatch leg
|
|
165
|
+
# returns a non-zero ExitCode with its error text on failure and ExitCode 0
|
|
166
|
+
# with empty Output on a clean pass, so output text must not influence this
|
|
167
|
+
# decision.
|
|
168
|
+
$hasErrors = ($exitCode -ne 0)
|
|
169
|
+
return @{ HasErrors = $hasErrors; ErrorText = $outputText }
|
|
170
|
+
}
|