@danmoisan/drm-copilot-mcp 1.1.22 → 1.1.24
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 +18758 -12030
- package/package.json +1 -1
- package/resources/claude-customizations/.claude/agent-memory/orchestrator/MEMORY.md +1 -1
- package/resources/claude-customizations/.claude/agent-memory/orchestrator/feedback_test_files_count_against_500_cap.md +4 -4
- package/resources/claude-customizations/.claude/agents/csharp-typed-engineer.md +1 -1
- package/resources/claude-customizations/.claude/agents/discovery-capability-sentinel.md +34 -0
- package/resources/claude-customizations/.claude/agents/feature-review.md +8 -0
- package/resources/claude-customizations/.claude/agents/legacy-parity-analyst.md +101 -43
- package/resources/claude-customizations/.claude/agents/migration-coverage-reviewer.md +107 -43
- package/resources/claude-customizations/.claude/agents/orchestrator.md +1 -1
- package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +60 -6
- package/resources/claude-customizations/.claude/agents/parallel-planner.md +21 -1
- package/resources/claude-customizations/.claude/agents/powershell-typed-engineer.md +1 -1
- package/resources/claude-customizations/.claude/agents/pr-author.md +48 -7
- package/resources/claude-customizations/.claude/agents/python-typed-engineer.md +1 -1
- package/resources/claude-customizations/.claude/agents/requirements-reconciler.md +117 -42
- package/resources/claude-customizations/.claude/agents/runtime-characterization-analyst.md +103 -43
- package/resources/claude-customizations/.claude/hooks/discovery-capability-probe.ps1 +102 -0
- package/resources/claude-customizations/.claude/hooks/enforce-discovery-artifact-gate.ps1 +69 -194
- package/resources/claude-customizations/.claude/hooks/enforce-discovery-planning-gate.ps1 +87 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-green-ci.ps1 +325 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +29 -7
- package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate-resolution.ps1 +23 -10
- package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate.ps1 +29 -21
- package/resources/claude-customizations/.claude/hooks/enforce-file-size-limit.ps1 +244 -0
- package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +51 -0
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +168 -48
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +1 -1
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +22 -11
- package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +59 -20
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-command-allowlist.ps1 +51 -4
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +72 -11
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.current-branch.ps1 +149 -0
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.epic-base-branch.ps1 +4 -2
- package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +59 -20
- package/resources/claude-customizations/.claude/hooks/record-discovery-agent-start.ps1 +132 -0
- package/resources/claude-customizations/.claude/hooks/validate-discovery-artifact-gate.ps1 +56 -212
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-feature-folder.ps1 +146 -0
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-rejection.ps1 +172 -0
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +34 -4
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadius.psm1 +9 -3
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusAggregate.psm1 +154 -0
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusCombination.psm1 +228 -0
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusExtraction.psm1 +1 -0
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusNormalization.psm1 +4 -2
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusScheduling.psm1 +63 -16
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusTokenShape.psm1 +56 -1
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusWriteIntent.psm1 +4 -1
- package/resources/claude-customizations/.claude/lib/cleanup-manifest/CleanupWorktreeManifest.psm1 +33 -6
- package/resources/claude-customizations/.claude/lib/codex-routing/CodexDeployment.psm1 +5 -1
- package/resources/claude-customizations/.claude/lib/codex-routing/CodexDiscoveryRouting.psm1 +161 -0
- package/resources/claude-customizations/.claude/lib/codex-routing/CodexTopology.psm1 +25 -2
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryAuthority.psd1 +90 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryAuthority.psm1 +493 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryAuthorization.psm1 +479 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryCapability.psm1 +468 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryEncoding.psm1 +156 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryManifest.psm1 +384 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryObservation.psm1 +217 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryPayload.psm1 +276 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryPlanning.psm1 +336 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryRootGrant.psm1 +164 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryStart.psm1 +440 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryStartRecord.psm1 +296 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryStop.psm1 +336 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryToolRouting.psm1 +228 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryValidation.psm1 +188 -341
- package/resources/claude-customizations/.claude/lib/file-size-policy/FileSizePolicy.psm1 +434 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateFeatureFolderRecord.psm1 +166 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateIssueAdoption.psm1 +8 -3
- package/resources/claude-customizations/.claude/lib/worktree-resolution/HookTargetWorktree.psm1 +391 -0
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeRunRecordPath.psm1 +185 -0
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeRunResolution.psm1 +11 -21
- package/resources/claude-customizations/.claude/rules/general-code-change.md +4 -1
- package/resources/claude-customizations/.claude/rules/orchestrator-state.md +29 -5
- package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +152 -20
- package/resources/claude-customizations/.claude/rules/powershell.md +1 -1
- package/resources/claude-customizations/.claude/rules/shell.md +1 -1
- package/resources/claude-customizations/.claude/settings.json +36 -3
- package/resources/claude-customizations/.claude/skills/adjudicate-unspecified-behavior/SKILL.md +135 -0
- package/resources/claude-customizations/.claude/skills/characterize-runtime-behavior/SKILL.md +134 -0
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +2 -2
- package/resources/claude-customizations/.claude/skills/discovery-behavior-reconciliation/SKILL.md +28 -47
- package/resources/claude-customizations/.claude/skills/discovery-coverage-ledger/SKILL.md +32 -48
- package/resources/claude-customizations/.claude/skills/discovery-parity-matrix/SKILL.md +28 -45
- package/resources/claude-customizations/.claude/skills/discovery-repo-inventory/SKILL.md +28 -62
- package/resources/claude-customizations/.claude/skills/discovery-runtime-characterization/SKILL.md +28 -45
- package/resources/claude-customizations/.claude/skills/discovery-validate-artifacts/SKILL.md +28 -61
- package/resources/claude-customizations/.claude/skills/discovery-workflow/SKILL.md +55 -139
- package/resources/claude-customizations/.claude/skills/execution-environment/SKILL.md +25 -10
- package/resources/claude-customizations/.claude/skills/extract-feature-contract/SKILL.md +133 -0
- package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +1 -0
- package/resources/claude-customizations/.claude/skills/generate-acceptance-scenarios/SKILL.md +132 -0
- package/resources/claude-customizations/.claude/skills/initialize-discovery-workspace/SKILL.md +131 -0
- package/resources/claude-customizations/.claude/skills/inventory-legacy-system/SKILL.md +131 -0
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +15 -7
- package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +25 -2
- package/resources/claude-customizations/.claude/skills/parallel-close/SKILL.md +11 -1
- package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +124 -14
- package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +72 -7
- package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +15 -0
- package/resources/claude-customizations/.claude/skills/parallel-run/SKILL.md +6 -0
- package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +56 -9
- package/resources/claude-customizations/.claude/skills/reconcile-parity-matrix/SKILL.md +131 -0
- package/resources/claude-customizations/.claude/skills/review-discovery-coverage/SKILL.md +129 -0
- package/resources/claude-customizations/.claude/skills/validate-discovery-artifacts/SKILL.md +127 -0
- package/resources/claude-customizations/.claude-variants/csharp-legacy/agents/csharp-typed-engineer.md +1 -1
- package/resources/claude-customizations/config/blast-radius.json +6 -5
- package/resources/claude-customizations/config/orchestration-routing.json +61 -1
- package/resources/claude-customizations/pack-manifests/core.json +40 -1
- package/resources/codex-and-agents-customizations/.agents/skills/adjudicate-unspecified-behavior/SKILL.md +135 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +7 -0
- package/resources/codex-and-agents-customizations/.agents/skills/characterize-runtime-behavior/SKILL.md +134 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-behavior-reconciliation/SKILL.md +46 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-coverage-ledger/SKILL.md +50 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-parity-matrix/SKILL.md +46 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-repo-inventory/SKILL.md +46 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-runtime-characterization/SKILL.md +46 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-validate-artifacts/SKILL.md +46 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-workflow/SKILL.md +62 -0
- package/resources/codex-and-agents-customizations/.agents/skills/execution-environment/SKILL.md +25 -10
- package/resources/codex-and-agents-customizations/.agents/skills/extract-feature-contract/SKILL.md +133 -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 +8 -0
- package/resources/codex-and-agents-customizations/.agents/skills/general-code-change/SKILL.md +4 -1
- package/resources/codex-and-agents-customizations/.agents/skills/generate-acceptance-scenarios/SKILL.md +132 -0
- package/resources/codex-and-agents-customizations/.agents/skills/initialize-discovery-workspace/SKILL.md +131 -0
- package/resources/codex-and-agents-customizations/.agents/skills/inventory-legacy-system/SKILL.md +131 -0
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +8 -0
- package/resources/codex-and-agents-customizations/.agents/skills/powershell/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/reconcile-parity-matrix/SKILL.md +131 -0
- package/resources/codex-and-agents-customizations/.agents/skills/review-discovery-coverage/SKILL.md +129 -0
- package/resources/codex-and-agents-customizations/.agents/skills/validate-discovery-artifacts/SKILL.md +127 -0
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c1.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c2.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c3-elevated.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c3.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c4.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/discovery-capability-sentinel.toml +51 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-review.toml +8 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c1.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c2.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c3-elevated.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c3.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c4.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c1.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c2.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c3-elevated.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c3.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c4.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c1.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c2.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c3-elevated.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c3.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c4.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c1.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c2.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c3-elevated.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c3.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c4.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c1.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c2.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c3-elevated.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c3.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c4.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c1.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c2.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c3-elevated.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c3.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c4.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/config.toml +39 -3
- package/resources/codex-and-agents-customizations/.codex/hooks/codex-agent-profile-attestation.ps1 +22 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/discovery-capability-probe.ps1 +97 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/discovery-start-attestation.ps1 +171 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-codex-model-routing.ps1 +4 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-discovery-artifact-gate.ps1 +187 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-discovery-planning-gate.ps1 +149 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-file-size-limit.ps1 +282 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +239 -2
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +6 -15
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +54 -15
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +54 -15
- package/resources/codex-and-agents-customizations/.codex/hooks/file-size-policy.ps1 +421 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-target-worktree.ps1 +369 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/record-subagent-routing-attestation.ps1 +8 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-codex-subagent-routing.ps1 +22 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-discovery-agent-output.ps1 +178 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/Resolve-CodexTopology.ps1 +11 -1
- package/resources/codex-and-agents-customizations/.codex-variants/csharp-legacy/agents/csharp-typed-engineer.toml +1 -1
- package/resources/codex-and-agents-customizations/AGENTS.md +4 -1
- package/resources/codex-and-agents-customizations/pack-manifests/core.json +65 -1
- package/resources/config/orchestration-routing.json +61 -1
- package/resources/customizations/.github/agents/commentary-remediation.agent.md +1 -1
- package/resources/customizations/.github/agents/discovery-capability-sentinel.agent.md +34 -0
- package/resources/customizations/.github/agents/legacy-parity-analyst.agent.md +122 -0
- package/resources/customizations/.github/agents/migration-coverage-reviewer.agent.md +128 -0
- package/resources/customizations/.github/agents/python-execution-only-typed.agent.md +1 -1
- package/resources/customizations/.github/agents/python-typed-engineer.agent.md +1 -1
- package/resources/customizations/.github/agents/requirements-reconciler.agent.md +138 -0
- package/resources/customizations/.github/agents/runtime-characterization-analyst.agent.md +124 -0
- package/resources/customizations/.github/hooks/discovery-agent-start.ps1 +139 -0
- package/resources/customizations/.github/hooks/discovery-agent-stop.ps1 +123 -0
- package/resources/customizations/.github/hooks/discovery-capability-probe.ps1 +98 -0
- package/resources/customizations/.github/hooks/discovery-planning.ps1 +91 -0
- package/resources/customizations/.github/hooks/discovery-pre-tool.ps1 +123 -0
- package/resources/customizations/.github/hooks/discovery.json +35 -0
- package/resources/customizations/.github/instructions/general-code-change.instructions.md +5 -2
- package/resources/customizations/.github/instructions/mermaid.instructions.md +85 -0
- package/resources/customizations/.github/instructions/powershell-code-change.instructions.md +1 -1
- package/resources/customizations/.github/prompts/execute-hard-lock.prompt.md +105 -0
- package/resources/customizations/.github/prompts/remediate-comments.prompt.md +1 -1
- package/resources/customizations/.github/skills/adjudicate-unspecified-behavior/SKILL.md +135 -0
- package/resources/customizations/.github/skills/characterize-runtime-behavior/SKILL.md +134 -0
- package/resources/customizations/.github/skills/discovery-behavior-reconciliation/SKILL.md +46 -0
- package/resources/customizations/.github/skills/discovery-coverage-ledger/SKILL.md +50 -0
- package/resources/customizations/.github/skills/discovery-parity-matrix/SKILL.md +46 -0
- package/resources/customizations/.github/skills/discovery-repo-inventory/SKILL.md +46 -0
- package/resources/customizations/.github/skills/discovery-runtime-characterization/SKILL.md +46 -0
- package/resources/customizations/.github/skills/discovery-validate-artifacts/SKILL.md +46 -0
- package/resources/customizations/.github/skills/discovery-workflow/SKILL.md +62 -0
- package/resources/customizations/.github/skills/execution-environment/SKILL.md +25 -10
- package/resources/customizations/.github/skills/extract-feature-contract/SKILL.md +133 -0
- package/resources/customizations/.github/skills/feature-review-workflow/SKILL.md +8 -0
- package/resources/customizations/.github/skills/generate-acceptance-scenarios/SKILL.md +132 -0
- package/resources/customizations/.github/skills/initialize-discovery-workspace/SKILL.md +131 -0
- package/resources/customizations/.github/skills/inventory-legacy-system/SKILL.md +131 -0
- package/resources/customizations/.github/skills/reconcile-parity-matrix/SKILL.md +131 -0
- package/resources/customizations/.github/skills/review-discovery-coverage/SKILL.md +129 -0
- package/resources/customizations/.github/skills/validate-discovery-artifacts/SKILL.md +127 -0
- package/resources/lib/codex-routing/CodexDeployment.psm1 +5 -1
- package/resources/lib/codex-routing/CodexDiscoveryRouting.psm1 +161 -0
- package/resources/lib/codex-routing/CodexTopology.psm1 +25 -2
- package/resources/lib/discovery-validation/DiscoveryAuthority.psd1 +90 -0
- package/resources/lib/discovery-validation/DiscoveryAuthority.psm1 +493 -0
- package/resources/lib/discovery-validation/DiscoveryAuthorization.psm1 +479 -0
- package/resources/lib/discovery-validation/DiscoveryCapability.psm1 +468 -0
- package/resources/lib/discovery-validation/DiscoveryEncoding.psm1 +156 -0
- package/resources/lib/discovery-validation/DiscoveryManifest.psm1 +384 -0
- package/resources/lib/discovery-validation/DiscoveryObservation.psm1 +217 -0
- package/resources/lib/discovery-validation/DiscoveryPayload.psm1 +276 -0
- package/resources/lib/discovery-validation/DiscoveryPlanning.psm1 +336 -0
- package/resources/lib/discovery-validation/DiscoveryRootGrant.psm1 +164 -0
- package/resources/lib/discovery-validation/DiscoveryStart.psm1 +440 -0
- package/resources/lib/discovery-validation/DiscoveryStartRecord.psm1 +296 -0
- package/resources/lib/discovery-validation/DiscoveryStop.psm1 +336 -0
- package/resources/lib/discovery-validation/DiscoveryToolRouting.psm1 +228 -0
- package/resources/powershell/PoshQC/PoshQC.Parallel.psm1 +452 -0
- package/resources/powershell/PoshQC/PoshQC.Shard.psm1 +106 -8
- package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +12 -0
- package/resources/powershell/PoshQC/PoshQC.psd1 +6 -1
- package/resources/powershell/PoshQC/PoshQC.psm1 +7 -1
- package/resources/powershell/PoshQC/README.md +20 -1
- package/resources/templates/policy_audit/code-review.yyyy-MM-ddTHH-mm.md +4 -4
- package/resources/templates/policy_audit/policy-audit.yyyy-MM-ddTHH-mm.md +4 -4
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Codex capability probe for discovery agents: observes registration, handler hashes and the recorded sentinel observations.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Not an event hook. The gateway doctor and the operator script
|
|
7
|
+
scripts/dev-tools/Test-DiscoveryHostCapability.ps1 run this probe to observe
|
|
8
|
+
whether this workspace's Codex host provides the required discovery controls:
|
|
9
|
+
the SubagentStart, PreToolUse and SubagentStop handlers registered in
|
|
10
|
+
.codex/config.toml for the four discovery agents and the controlled tools, their
|
|
11
|
+
current hashes, and the host observations the PreToolUse gate recorded while the
|
|
12
|
+
discovery-capability-sentinel agent ran in session SessionId. The result is a
|
|
13
|
+
capability-attestation-shaped JSON document on stdout; exit 0 when supported, 1
|
|
14
|
+
when unsupported. A session without observations, or whose sentinel observation
|
|
15
|
+
carries no agent_id, is unsupported.
|
|
16
|
+
|
|
17
|
+
.NOTES
|
|
18
|
+
Issue #980. Requires PowerShell 7+. Invokes NO external process and makes no
|
|
19
|
+
in-process sentinel decision.
|
|
20
|
+
#>
|
|
21
|
+
[CmdletBinding()]
|
|
22
|
+
param(
|
|
23
|
+
[Parameter(Mandatory = $false)][string]$WorkspaceRoot = (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent),
|
|
24
|
+
[Parameter(Mandatory = $false)][string]$SessionId = 'capability-probe',
|
|
25
|
+
[Parameter(Mandatory = $false)][AllowNull()][string]$Nonce = $null,
|
|
26
|
+
[Parameter(Mandatory = $false)][bool]$WorkspaceTrusted = $true,
|
|
27
|
+
[Parameter(Mandatory = $false)][AllowNull()][string]$RuntimeJson = $null
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
. (Join-Path $PSScriptRoot 'enforce-discovery-artifact-gate.ps1')
|
|
31
|
+
Import-Module (Get-DiscoveryHelperModulePath -ModuleName 'DiscoveryCapability.psm1') -Force -Global -ErrorAction Stop
|
|
32
|
+
|
|
33
|
+
function Get-DiscoveryProbeRuntime {
|
|
34
|
+
<#
|
|
35
|
+
.SYNOPSIS
|
|
36
|
+
Returns the runtime identity the probe records: the caller's JSON, or the local configuration digest.
|
|
37
|
+
#>
|
|
38
|
+
[CmdletBinding()]
|
|
39
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
40
|
+
param([Parameter(Mandatory = $false)][AllowNull()][string]$RuntimeJson, [Parameter(Mandatory = $true)][string]$WorkspaceRoot)
|
|
41
|
+
|
|
42
|
+
if (-not [string]::IsNullOrWhiteSpace($RuntimeJson)) {
|
|
43
|
+
$parsed = ConvertFrom-Json -InputObject $RuntimeJson -Depth 4
|
|
44
|
+
$runtime = [ordered]@{}
|
|
45
|
+
foreach ($key in @('build_sha256', 'package_version', 'policy_sha256', 'policy_version', 'schema_version')) {
|
|
46
|
+
# The runtime identity contract types policy_version as an integer; the hosts compare it canonically.
|
|
47
|
+
$runtime[$key] = $(if ($key -eq 'policy_version') { [int]$parsed.$key } else { [string]$parsed.$key })
|
|
48
|
+
}
|
|
49
|
+
return $runtime
|
|
50
|
+
}
|
|
51
|
+
# The workspace root is a host-modelled path string; Join-Path would require its drive to exist locally.
|
|
52
|
+
$configuration = "$($WorkspaceRoot.TrimEnd('/', '\'))/.codex/config.toml"
|
|
53
|
+
$digest = $(if (Test-Path -LiteralPath $configuration -PathType Leaf) { Get-DiscoveryBytesSha256Hex -Bytes ([System.IO.File]::ReadAllBytes($configuration)) } else { '0' * 64 })
|
|
54
|
+
return [ordered]@{ build_sha256 = $digest; package_version = '2.0.0'; policy_sha256 = $digest; policy_version = 2; schema_version = '2.0.0' }
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function Invoke-DiscoveryCapabilityProbe {
|
|
58
|
+
<#
|
|
59
|
+
.SYNOPSIS
|
|
60
|
+
Runs the Codex capability observation and returns the attestation-shaped document.
|
|
61
|
+
#>
|
|
62
|
+
[CmdletBinding()]
|
|
63
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
64
|
+
param(
|
|
65
|
+
[Parameter(Mandatory = $true)][string]$WorkspaceRoot,
|
|
66
|
+
[Parameter(Mandatory = $true)][string]$SessionId,
|
|
67
|
+
[Parameter(Mandatory = $false)][AllowNull()][string]$Nonce = $null,
|
|
68
|
+
[Parameter(Mandatory = $false)][bool]$WorkspaceTrusted = $true,
|
|
69
|
+
[Parameter(Mandatory = $false)][AllowNull()][string]$RuntimeJson = $null,
|
|
70
|
+
[Parameter(Mandatory = $false)][AllowNull()][hashtable]$HostEnvironment = $null,
|
|
71
|
+
[Parameter(Mandatory = $false)][AllowNull()][hashtable]$Store = $null,
|
|
72
|
+
[Parameter(Mandatory = $false)][AllowNull()][scriptblock]$ReadBytes = $null,
|
|
73
|
+
[Parameter(Mandatory = $false)][AllowNull()][nullable[datetime]]$Now = $null
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
if ([string]::IsNullOrEmpty($Nonce)) { $Nonce = Get-DiscoveryAuthorizationNonce }
|
|
77
|
+
if ($null -eq $HostEnvironment) { $HostEnvironment = Get-DiscoveryTrustedHostEnvironment }
|
|
78
|
+
if ($null -eq $Store) { $Store = Get-DiscoveryDefaultStore }
|
|
79
|
+
if ($null -eq $Now) { $Now = [datetime]::UtcNow }
|
|
80
|
+
$parameters = @{
|
|
81
|
+
HostName = 'codex'; WorkspaceRoot = $WorkspaceRoot; SessionId = $SessionId; Nonce = $Nonce; WorkspaceTrusted = $WorkspaceTrusted; Now = $Now
|
|
82
|
+
Runtime = (Get-DiscoveryProbeRuntime -RuntimeJson $RuntimeJson -WorkspaceRoot $WorkspaceRoot)
|
|
83
|
+
HostEnvironment = $HostEnvironment; Store = $Store
|
|
84
|
+
}
|
|
85
|
+
if ($null -ne $ReadBytes) { $parameters['ReadBytes'] = $ReadBytes }
|
|
86
|
+
$observation = Get-DiscoveryCapabilityObservation @parameters
|
|
87
|
+
# The doctor, the agent preparation and the start attestation read only the protected session copy.
|
|
88
|
+
[void](Write-DiscoveryCapabilityAttestation -Observation $observation -WorkspaceRoot $WorkspaceRoot -HostEnvironment $HostEnvironment -Store $Store)
|
|
89
|
+
return $observation
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if ($MyInvocation.InvocationName -eq '.') {
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
$observation = Invoke-DiscoveryCapabilityProbe -WorkspaceRoot $WorkspaceRoot -SessionId $SessionId -Nonce $Nonce -WorkspaceTrusted $WorkspaceTrusted -RuntimeJson $RuntimeJson
|
|
96
|
+
$observation | ConvertTo-Json -Depth 8 | Write-Output
|
|
97
|
+
exit $(if ($observation['status'] -eq 'supported') { 0 } else { 1 })
|
package/resources/codex-and-agents-customizations/.codex/hooks/discovery-start-attestation.ps1
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Codex SubagentStart attestation for discovery specialists through the protected discovery store.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Dot-sourced by record-subagent-routing-attestation.ps1. A Codex start whose agent
|
|
7
|
+
type names a discovery specialist is attested against the explicit
|
|
8
|
+
`discovery-invocation` receipt the root prepared in the protected store, through
|
|
9
|
+
the shared DiscoveryStart module (published under .codex/lib/discovery-validation,
|
|
10
|
+
or read from .claude/lib when this repository hosts itself). The result is
|
|
11
|
+
projected into the schema-2 routing attestation the Codex PreToolUse gates
|
|
12
|
+
already consume, with receipt_kind `discovery-invocation`, so an unattested or
|
|
13
|
+
drifted specialist is denied before its first tool use. No orchestrator
|
|
14
|
+
checkpoint, repository HEAD or epic receipt is read for a discovery start.
|
|
15
|
+
#>
|
|
16
|
+
[CmdletBinding()]
|
|
17
|
+
param()
|
|
18
|
+
|
|
19
|
+
$script:CodexDiscoveryAgentTypePattern = '^(legacy-parity-analyst|runtime-characterization-analyst|requirements-reconciler|migration-coverage-reviewer)(-c(1|2|3|4|3-elevated))?$'
|
|
20
|
+
$script:CodexDiscoveryStartPrefix = 'DISCOVERY_START_ATTESTATION_BLOCKED:'
|
|
21
|
+
$script:CodexDiscoveryStartModules = @('DiscoveryEncoding.psm1', 'DiscoveryAuthority.psm1', 'DiscoveryPayload.psm1', 'DiscoveryStartRecord.psm1', 'DiscoveryStart.psm1')
|
|
22
|
+
|
|
23
|
+
function Test-CodexDiscoveryAgentType {
|
|
24
|
+
[CmdletBinding()]
|
|
25
|
+
[OutputType([bool])]
|
|
26
|
+
param([AllowNull()][AllowEmptyString()][string] $AgentType)
|
|
27
|
+
|
|
28
|
+
return -not [string]::IsNullOrWhiteSpace($AgentType) -and $AgentType -cmatch $script:CodexDiscoveryAgentTypePattern
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function Get-CodexDiscoveryStartModulePath {
|
|
32
|
+
<#
|
|
33
|
+
.SYNOPSIS
|
|
34
|
+
Returns the published (.codex/lib) or self-hosting (.claude/lib) path of one helper module.
|
|
35
|
+
#>
|
|
36
|
+
[CmdletBinding()]
|
|
37
|
+
[OutputType([string])]
|
|
38
|
+
param(
|
|
39
|
+
[Parameter(Mandatory)][string] $ModuleName,
|
|
40
|
+
[string] $ScriptRoot = $PSScriptRoot
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
$published = Join-Path $ScriptRoot "../lib/discovery-validation/$ModuleName"
|
|
44
|
+
$selfHosted = Join-Path $ScriptRoot "../../.claude/lib/discovery-validation/$ModuleName"
|
|
45
|
+
foreach ($candidate in @($published, $selfHosted)) {
|
|
46
|
+
if (Test-Path -LiteralPath $candidate -PathType Leaf) { return $candidate }
|
|
47
|
+
}
|
|
48
|
+
return $published
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function Import-CodexDiscoveryStartModule {
|
|
52
|
+
<#
|
|
53
|
+
.SYNOPSIS
|
|
54
|
+
Loads the shared discovery modules a discovery start needs; ordinary starts never load them.
|
|
55
|
+
#>
|
|
56
|
+
[CmdletBinding()]
|
|
57
|
+
param([string] $ScriptRoot = $PSScriptRoot)
|
|
58
|
+
|
|
59
|
+
foreach ($moduleName in $script:CodexDiscoveryStartModules) {
|
|
60
|
+
Import-Module (Get-CodexDiscoveryStartModulePath -ModuleName $moduleName -ScriptRoot $ScriptRoot) -Force -Global -ErrorAction Stop
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function Get-CodexDiscoveryStartAttestation {
|
|
65
|
+
<#
|
|
66
|
+
.SYNOPSIS
|
|
67
|
+
Builds the schema-2 attestation of a Codex discovery start from the protected invocation.
|
|
68
|
+
.DESCRIPTION
|
|
69
|
+
The actual model comes from the SubagentStart payload and the actual effort and
|
|
70
|
+
profile hash from the generated Codex profile; both must equal the deployment
|
|
71
|
+
the root prepared. routing_valid is true only when the shared decision
|
|
72
|
+
attested the start; discovery_code and discovery_reason carry the decision.
|
|
73
|
+
#>
|
|
74
|
+
[CmdletBinding()]
|
|
75
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
76
|
+
param(
|
|
77
|
+
[Parameter(Mandatory)] $Payload,
|
|
78
|
+
[Parameter(Mandatory)][string] $RepositoryRoot,
|
|
79
|
+
[Parameter(Mandatory)][datetimeoffset] $Now,
|
|
80
|
+
[AllowNull()][hashtable] $HostEnvironment = $null,
|
|
81
|
+
[AllowNull()][hashtable] $Store = $null,
|
|
82
|
+
[AllowNull()][string] $Nonce = $null,
|
|
83
|
+
[AllowNull()] $AgentProfile = $null,
|
|
84
|
+
[string] $HandlerPath = (Join-Path $PSScriptRoot 'record-subagent-routing-attestation.ps1')
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
$agentId = [string]$Payload.agent_id
|
|
88
|
+
$agentType = [string]$Payload.agent_type
|
|
89
|
+
$model = [string]$Payload.model
|
|
90
|
+
if (-not $agentId -or -not $agentType -or -not $model) {
|
|
91
|
+
throw "$($script:CodexDiscoveryStartPrefix) SubagentStart requires agent_id, agent_type, and model."
|
|
92
|
+
}
|
|
93
|
+
Import-CodexDiscoveryStartModule
|
|
94
|
+
$profileValidationError = $null
|
|
95
|
+
if ($null -eq $AgentProfile) {
|
|
96
|
+
try { $AgentProfile = Get-CodexAgentProfileAttestation -RepositoryRoot $RepositoryRoot -AgentType $agentType } catch { $profileValidationError = [string]$_ }
|
|
97
|
+
}
|
|
98
|
+
$sharedProfile = $(if ($null -ne $AgentProfile) { ConvertTo-CodexSharedAgentProfile -AgentProfile $AgentProfile } else { $null })
|
|
99
|
+
# The principal comes from the payload alone: Codex supplies no parent identifier, so the parent is the literal root.
|
|
100
|
+
$normalized = [pscustomobject]@{
|
|
101
|
+
HostName = 'codex'; Event = 'SubagentStart'; SessionId = [string]$Payload.session_id; AgentId = $agentId; AgentType = $agentType; ParentAgentId = $null
|
|
102
|
+
ToolName = $null; ToolInput = $null; Cwd = $RepositoryRoot; ToolUseId = $null; Anomaly = $null
|
|
103
|
+
}
|
|
104
|
+
if ([string]::IsNullOrWhiteSpace($normalized.SessionId)) { $normalized.Anomaly = 'MissingSessionId' }
|
|
105
|
+
$handlerSha256 = $(if (Test-Path -LiteralPath $HandlerPath -PathType Leaf) { Get-DiscoveryBytesSha256Hex -Bytes ([System.IO.File]::ReadAllBytes($HandlerPath)) } else { '0' * 64 })
|
|
106
|
+
$parameters = @{ Normalized = $normalized; HandlerSha256 = $handlerSha256; Now = $Now.UtcDateTime; ActualModel = $model }
|
|
107
|
+
$parameters['HostEnvironment'] = $(if ($null -ne $HostEnvironment) { $HostEnvironment } else { Get-DiscoveryTrustedHostEnvironment })
|
|
108
|
+
if ($null -ne $Store) { $parameters['Store'] = $Store }
|
|
109
|
+
if (-not [string]::IsNullOrEmpty($Nonce)) { $parameters['Nonce'] = $Nonce }
|
|
110
|
+
if ($null -ne $sharedProfile) { $parameters['AgentProfile'] = $sharedProfile; $parameters['ActualReasoningEffort'] = $sharedProfile.ProfileReasoningEffort }
|
|
111
|
+
$outcome = $(if ($null -eq $sharedProfile) {
|
|
112
|
+
[pscustomobject]@{ Decision = 'deny'; Code = 'PROFILE'; Reason = "the agent profile could not be read: $profileValidationError"; Attestation = $null; AttestationPath = $null; Invocation = $null }
|
|
113
|
+
} else { Get-DiscoveryStartDecision @parameters })
|
|
114
|
+
$record = $outcome.Invocation
|
|
115
|
+
$attested = ($outcome.Decision -eq 'attest')
|
|
116
|
+
return [ordered]@{
|
|
117
|
+
schema_version = 2
|
|
118
|
+
receipt_kind = 'discovery-invocation'
|
|
119
|
+
session_id = [string]$Payload.session_id
|
|
120
|
+
turn_id = [string]$Payload.turn_id
|
|
121
|
+
agent_id = $agentId
|
|
122
|
+
agent_type = $agentType
|
|
123
|
+
transcript_path = [string]$Payload.transcript_path
|
|
124
|
+
attestation_key = Get-SubagentAttestationKey -TranscriptPath ([string]$Payload.transcript_path) -AgentId $agentId
|
|
125
|
+
actual_model = $model
|
|
126
|
+
expected_model = $(if ($null -ne $record) { [string]$record.deployment.model } else { '' })
|
|
127
|
+
actual_reasoning_effort = $(if ($null -ne $AgentProfile) { [string]$AgentProfile.profile_reasoning_effort } else { $null })
|
|
128
|
+
expected_reasoning_effort = $(if ($null -ne $record) { [string]$record.deployment.reasoning_effort } else { '' })
|
|
129
|
+
profile_name = $(if ($null -ne $AgentProfile) { [string]$AgentProfile.profile_name } else { $null })
|
|
130
|
+
profile_model = $(if ($null -ne $AgentProfile) { [string]$AgentProfile.profile_model } else { $null })
|
|
131
|
+
profile_path = $(if ($null -ne $AgentProfile) { [string]$AgentProfile.profile_path } else { $null })
|
|
132
|
+
profile_sha256 = $(if ($null -ne $AgentProfile) { [string]$AgentProfile.profile_sha256 } else { $null })
|
|
133
|
+
profile_validation_error = $profileValidationError
|
|
134
|
+
routing_valid = $attested
|
|
135
|
+
launch_authority_valid = $attested
|
|
136
|
+
root_authorized = $null
|
|
137
|
+
root_entry_kind = $null
|
|
138
|
+
root_epic_reference = $null
|
|
139
|
+
root_kickoff_path = $null
|
|
140
|
+
authority_repository_sha256 = Get-CodexAuthorityRepositoryKey -RepositoryRoot $RepositoryRoot
|
|
141
|
+
provenance_valid = $true
|
|
142
|
+
enforcement_marker = $(if ($attested) { $null } else { 'DISCOVERY_START_ATTESTATION_BLOCKED' })
|
|
143
|
+
invocation_id = $(if ($null -ne $record) { [string]$record.invocation_id } else { $null })
|
|
144
|
+
start_attestation_ref = $(if ($attested) { [string]$outcome.Attestation['start_attestation_ref'] } else { $null })
|
|
145
|
+
discovery_code = $outcome.Code
|
|
146
|
+
discovery_reason = $outcome.Reason
|
|
147
|
+
recorded_at = $Now.ToUniversalTime().ToString('o')
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function Get-CodexDiscoveryStartCommandOutput {
|
|
152
|
+
<#
|
|
153
|
+
.SYNOPSIS
|
|
154
|
+
Returns the SubagentStart stdout for a discovery attestation, or $null when the start was attested.
|
|
155
|
+
#>
|
|
156
|
+
[CmdletBinding()]
|
|
157
|
+
[OutputType([string])]
|
|
158
|
+
param(
|
|
159
|
+
[Parameter(Mandatory)][System.Collections.IDictionary] $Attestation,
|
|
160
|
+
[Parameter(Mandatory)][string] $AttestationPath
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
if ([bool]$Attestation.routing_valid) { return $null }
|
|
164
|
+
return [ordered]@{
|
|
165
|
+
systemMessage = "$($script:CodexDiscoveryStartPrefix) $($Attestation.discovery_reason) Attestation: $AttestationPath"
|
|
166
|
+
hookSpecificOutput = [ordered]@{
|
|
167
|
+
hookEventName = 'SubagentStart'
|
|
168
|
+
additionalContext = "$($script:CodexDiscoveryStartPrefix) no discovery tool grant is active for this agent. Do not read or mutate state; report the blocked start and stop."
|
|
169
|
+
}
|
|
170
|
+
} | ConvertTo-Json -Compress -Depth 5
|
|
171
|
+
}
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-codex-model-routing.ps1
CHANGED
|
@@ -127,7 +127,10 @@ function Test-CodexModelGateAgentType {
|
|
|
127
127
|
[OutputType([bool])]
|
|
128
128
|
param([Parameter(Mandatory)][string] $AgentType)
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
# Discovery specialists are gated by their SubagentStart attestation of the
|
|
131
|
+
# protected invocation (issue #980); a start without one denies the first tool use.
|
|
132
|
+
return $AgentType -match '-c(?:1|2|3|4|3-elevated)$' -or
|
|
133
|
+
$AgentType -cmatch '^(legacy-parity-analyst|runtime-characterization-analyst|requirements-reconciler|migration-coverage-reviewer)$' -or @(
|
|
131
134
|
'orchestrator', 'atomic-planner', 'atomic-executor', 'feature-review',
|
|
132
135
|
'feature-reviewer', 'task-researcher', 'prd-feature', 'pr-author',
|
|
133
136
|
'python-typed-engineer', 'powershell-typed-engineer',
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-discovery-artifact-gate.ps1
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Native PreToolUse authorization adapter for Codex discovery agents.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Invoked by the Codex PreToolUse hook. The hook reads the Codex envelope from
|
|
7
|
+
stdin, derives the trusted principal from the payload alone (session, the
|
|
8
|
+
host-assigned agent_id and agent_type when the payload carries them, and the
|
|
9
|
+
literal parent root), and takes its decision from the shared
|
|
10
|
+
DiscoveryAuthorization module (published under .codex/lib/discovery-validation,
|
|
11
|
+
or read from .claude/lib when this repository hosts itself):
|
|
12
|
+
|
|
13
|
+
- a root call (no agent_id) of prepare_discovery_agent, run_discovery_doctor or
|
|
14
|
+
a controlled discovery tool is allowed with a one-use root grant the MCP
|
|
15
|
+
server consumes; every other root call and every call of an agent that is
|
|
16
|
+
not a discovery specialist allows silently (no stdout), so ordinary
|
|
17
|
+
sessions keep the behavior of their other gates;
|
|
18
|
+
- a sentinel envelope is observed for the capability probe and never granted;
|
|
19
|
+
- a discovery specialist may use read-only native tools and the controlled
|
|
20
|
+
discovery MCP tools only; shell, exec and evaluation tools, generic
|
|
21
|
+
apply_patch/Write/Edit mutations, nested agents, foreign MCP servers,
|
|
22
|
+
root-only discovery operations and caller-supplied identity fields are denied
|
|
23
|
+
before execution with a PreToolUse deny decision at exit 0;
|
|
24
|
+
- every controlled call must name the specialist's started invocation through
|
|
25
|
+
invocation_ref and is recorded as one short-lived, one-use tool-authorization;
|
|
26
|
+
the Codex SubagentStart attestation binds the prepared invocation, and the
|
|
27
|
+
gate's first-call binding reports PROFILE when no start attested the agent.
|
|
28
|
+
|
|
29
|
+
An envelope the hook cannot read is a hard failure: the reason goes to stderr
|
|
30
|
+
and the hook exits 2. Dependency failures deny with the
|
|
31
|
+
DISCOVERY_ARTIFACT_GATE_BLOCKED: prefix (issue #980).
|
|
32
|
+
|
|
33
|
+
.NOTES
|
|
34
|
+
Requires PowerShell 7+. Invokes NO external process and never reads a profile,
|
|
35
|
+
locator or request field to decide identity or authority.
|
|
36
|
+
#>
|
|
37
|
+
[CmdletBinding()]
|
|
38
|
+
param()
|
|
39
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
40
|
+
|
|
41
|
+
function Get-DiscoveryHelperModulePath {
|
|
42
|
+
<#
|
|
43
|
+
.SYNOPSIS
|
|
44
|
+
Returns the published (.codex/lib) or self-hosting (.claude/lib) path of one helper module.
|
|
45
|
+
.DESCRIPTION
|
|
46
|
+
The published destination holds the helpers beside .codex/hooks under
|
|
47
|
+
.codex/lib/discovery-validation; this repository holds them under
|
|
48
|
+
.claude/lib/discovery-validation. The first existing candidate wins; when
|
|
49
|
+
neither exists the published path is returned so the import failure names it.
|
|
50
|
+
#>
|
|
51
|
+
[CmdletBinding()]
|
|
52
|
+
[OutputType([string])]
|
|
53
|
+
param(
|
|
54
|
+
[Parameter(Mandatory = $true)][string]$ModuleName,
|
|
55
|
+
[Parameter(Mandatory = $false)][string]$ScriptRoot = $PSScriptRoot
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
$published = Join-Path $ScriptRoot "../lib/discovery-validation/$ModuleName"
|
|
59
|
+
$selfHosted = Join-Path $ScriptRoot "../../.claude/lib/discovery-validation/$ModuleName"
|
|
60
|
+
# Resolution order: the destination layout first, then the repository layout.
|
|
61
|
+
foreach ($candidate in @($published, $selfHosted)) {
|
|
62
|
+
if (Test-Path -LiteralPath $candidate -PathType Leaf) { return $candidate }
|
|
63
|
+
}
|
|
64
|
+
return $published
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function Import-DiscoveryGateSelfHostedModule {
|
|
68
|
+
<#
|
|
69
|
+
.SYNOPSIS
|
|
70
|
+
Imports the shared helpers from this repository's .claude/lib layout when no published .codex/lib exists (exemption D4).
|
|
71
|
+
#>
|
|
72
|
+
[CmdletBinding()]
|
|
73
|
+
param()
|
|
74
|
+
|
|
75
|
+
$ScriptRoot = $PSScriptRoot
|
|
76
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryEncoding.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryEncoding.psm1' -ErrorRecord $_ }
|
|
77
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryAuthority.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryAuthority.psm1' -ErrorRecord $_ }
|
|
78
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryPayload.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryPayload.psm1' -ErrorRecord $_ }
|
|
79
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryToolRouting.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryToolRouting.psm1' -ErrorRecord $_ }
|
|
80
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryStartRecord.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryStartRecord.psm1' -ErrorRecord $_ }
|
|
81
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryRootGrant.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryRootGrant.psm1' -ErrorRecord $_ }
|
|
82
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryObservation.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryObservation.psm1' -ErrorRecord $_ }
|
|
83
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryStart.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryStart.psm1' -ErrorRecord $_ }
|
|
84
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryAuthorization.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryAuthorization.psm1' -ErrorRecord $_ }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
# The published destination keeps the helpers beside .codex/hooks; this repository hosts them under .claude/lib.
|
|
88
|
+
if (Test-Path -LiteralPath (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryEncoding.psm1') -PathType Leaf) {
|
|
89
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryEncoding.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryEncoding.psm1' -ErrorRecord $_ }
|
|
90
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryAuthority.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryAuthority.psm1' -ErrorRecord $_ }
|
|
91
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryPayload.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryPayload.psm1' -ErrorRecord $_ }
|
|
92
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryToolRouting.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryToolRouting.psm1' -ErrorRecord $_ }
|
|
93
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryStartRecord.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryStartRecord.psm1' -ErrorRecord $_ }
|
|
94
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryRootGrant.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryRootGrant.psm1' -ErrorRecord $_ }
|
|
95
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryObservation.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryObservation.psm1' -ErrorRecord $_ }
|
|
96
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryStart.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryStart.psm1' -ErrorRecord $_ }
|
|
97
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryAuthorization.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryAuthorization.psm1' -ErrorRecord $_ }
|
|
98
|
+
} else {
|
|
99
|
+
Import-DiscoveryGateSelfHostedModule
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
$script:DiscoveryGateReasonPrefix = 'DISCOVERY_ARTIFACT_GATE_BLOCKED:'
|
|
103
|
+
$script:DiscoveryGateHandlerPath = $PSCommandPath
|
|
104
|
+
|
|
105
|
+
function Get-DiscoveryGateHandlerSha256 {
|
|
106
|
+
<#
|
|
107
|
+
.SYNOPSIS
|
|
108
|
+
Returns the SHA-256 of this handler's own bytes for the authorization writer record.
|
|
109
|
+
#>
|
|
110
|
+
[CmdletBinding()]
|
|
111
|
+
[OutputType([string])]
|
|
112
|
+
param([Parameter(Mandatory = $false)][AllowNull()][string]$HandlerPath = $script:DiscoveryGateHandlerPath)
|
|
113
|
+
|
|
114
|
+
if ([string]::IsNullOrEmpty($HandlerPath) -or -not (Test-Path -LiteralPath $HandlerPath -PathType Leaf)) {
|
|
115
|
+
return ('0' * 64)
|
|
116
|
+
}
|
|
117
|
+
return Get-DiscoveryBytesSha256Hex -Bytes ([System.IO.File]::ReadAllBytes($HandlerPath))
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function Invoke-DiscoveryArtifactGateDecision {
|
|
121
|
+
<#
|
|
122
|
+
.SYNOPSIS
|
|
123
|
+
Parses the Codex PreToolUse envelope and returns the decision outcome.
|
|
124
|
+
.DESCRIPTION
|
|
125
|
+
Returns the shared outcome object (Decision, Code, Reason, Record,
|
|
126
|
+
RecordPath). Every seam defaults to the real host and is injectable. A
|
|
127
|
+
recorded dependency failure returns a deny outcome before the envelope is read.
|
|
128
|
+
#>
|
|
129
|
+
[CmdletBinding()]
|
|
130
|
+
[OutputType([pscustomobject])]
|
|
131
|
+
param(
|
|
132
|
+
[Parameter(Mandatory = $false)][AllowNull()][AllowEmptyString()][string]$ToolInputRaw,
|
|
133
|
+
[Parameter(Mandatory = $false)][AllowNull()][hashtable]$HostEnvironment = $null,
|
|
134
|
+
[Parameter(Mandatory = $false)][AllowNull()][hashtable]$Store = $null,
|
|
135
|
+
[Parameter(Mandatory = $false)][AllowNull()][nullable[datetime]]$Now = $null,
|
|
136
|
+
[Parameter(Mandatory = $false)][AllowNull()][string]$Nonce = $null
|
|
137
|
+
)
|
|
138
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix $script:DiscoveryGateReasonPrefix
|
|
139
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
140
|
+
|
|
141
|
+
# Seams resolve only after the dependency check so a missing module denies
|
|
142
|
+
# instead of raising while a default is evaluated.
|
|
143
|
+
if ($null -eq $HostEnvironment) { $HostEnvironment = Get-DiscoveryTrustedHostEnvironment }
|
|
144
|
+
if ($null -eq $Store) { $Store = Get-DiscoveryDefaultStore }
|
|
145
|
+
if ($null -eq $Now) { $Now = [datetime]::UtcNow }
|
|
146
|
+
if ([string]::IsNullOrEmpty($Nonce)) { $Nonce = Get-DiscoveryAuthorizationNonce }
|
|
147
|
+
|
|
148
|
+
$normalized = ConvertFrom-DiscoveryHostPayloadText -HostName 'codex' -Text $ToolInputRaw
|
|
149
|
+
return Get-DiscoveryPreToolDecision -Normalized $normalized -HostEnvironment $HostEnvironment `
|
|
150
|
+
-HandlerSha256 (Get-DiscoveryGateHandlerSha256) -Store $Store -Now $Now -Nonce $Nonce
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function Invoke-DiscoveryArtifactGateEntryPoint {
|
|
154
|
+
<#
|
|
155
|
+
.SYNOPSIS
|
|
156
|
+
Reads one Codex PreToolUse payload, writes the decision and returns the process exit code.
|
|
157
|
+
.DESCRIPTION
|
|
158
|
+
An unreadable envelope writes its reason to stderr and returns 2. A deny
|
|
159
|
+
writes the PreToolUse decision JSON to stdout and returns 0. An allow writes
|
|
160
|
+
nothing and returns 0, as the Codex gates do.
|
|
161
|
+
#>
|
|
162
|
+
[CmdletBinding()]
|
|
163
|
+
[OutputType([int])]
|
|
164
|
+
param([Parameter(Mandatory = $false)][AllowNull()][AllowEmptyString()][string]$PayloadRaw)
|
|
165
|
+
|
|
166
|
+
$outcome = Invoke-DiscoveryArtifactGateDecision -ToolInputRaw $PayloadRaw
|
|
167
|
+
# A dependency failure is already the PreToolUse deny decision.
|
|
168
|
+
if ($outcome -is [System.Collections.IDictionary]) { [Console]::Out.WriteLine(($outcome | ConvertTo-Json -Compress -Depth 5)); return 0 }
|
|
169
|
+
if ($outcome.Decision -eq 'allow') { return 0 }
|
|
170
|
+
if ($outcome.Code -eq 'ENVELOPE') {
|
|
171
|
+
[Console]::Error.WriteLine("$($script:DiscoveryGateReasonPrefix) $($outcome.Reason)")
|
|
172
|
+
return 2
|
|
173
|
+
}
|
|
174
|
+
$decision = ConvertTo-DiscoveryPreToolHookOutput -Outcome $outcome -ReasonPrefix $script:DiscoveryGateReasonPrefix
|
|
175
|
+
[Console]::Out.WriteLine(($decision | ConvertTo-Json -Compress -Depth 5))
|
|
176
|
+
return 0
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
# Guard allows dot-sourcing in tests without executing the entrypoint.
|
|
180
|
+
if ($MyInvocation.InvocationName -eq '.') {
|
|
181
|
+
return
|
|
182
|
+
}
|
|
183
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('DISCOVERY_ARTIFACT_GATE_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
184
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'DISCOVERY_ARTIFACT_GATE_BLOCKED:'
|
|
185
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
186
|
+
|
|
187
|
+
exit (Invoke-DiscoveryArtifactGateEntryPoint -PayloadRaw ([Console]::In.ReadToEnd()))
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-discovery-planning-gate.ps1
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Codex PreToolUse hook that gates planner and orchestrator launches on current configured discovery authority.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Invoked by the Codex PreToolUse hook. The hook reads the Codex envelope from
|
|
7
|
+
stdin, recognizes an atomic-planner or orchestrator launch, and takes its
|
|
8
|
+
decision from the shared DiscoveryPlanning module (published under
|
|
9
|
+
.codex/lib/discovery-validation, or read from .claude/lib when this repository
|
|
10
|
+
hosts itself):
|
|
11
|
+
|
|
12
|
+
- a call that is not a planner or orchestrator launch, and a workspace without
|
|
13
|
+
a protected discovery activation, allow silently (no stdout) so the existing
|
|
14
|
+
Codex gates keep their behavior;
|
|
15
|
+
- an active workspace must still hold the activated locator and domain profile
|
|
16
|
+
and the protected session must hold a current, passing, gateway-written
|
|
17
|
+
planning-mode receipt for this host and session; otherwise the launch is
|
|
18
|
+
denied with a PreToolUse deny decision at exit 0.
|
|
19
|
+
|
|
20
|
+
An envelope the hook cannot read is a hard failure: the reason goes to stderr
|
|
21
|
+
and the hook exits 2. Dependency failures deny with the
|
|
22
|
+
DISCOVERY_PLANNING_GATE_BLOCKED: prefix. The hook never runs Python (issue #980).
|
|
23
|
+
|
|
24
|
+
.NOTES
|
|
25
|
+
Requires PowerShell 7+. Invokes NO external process.
|
|
26
|
+
#>
|
|
27
|
+
[CmdletBinding()]
|
|
28
|
+
param()
|
|
29
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
30
|
+
|
|
31
|
+
function Get-DiscoveryPlanningHelperModulePath {
|
|
32
|
+
<#
|
|
33
|
+
.SYNOPSIS
|
|
34
|
+
Returns the published (.codex/lib) or self-hosting (.claude/lib) path of one helper module.
|
|
35
|
+
#>
|
|
36
|
+
[CmdletBinding()]
|
|
37
|
+
[OutputType([string])]
|
|
38
|
+
param(
|
|
39
|
+
[Parameter(Mandatory = $true)][string]$ModuleName,
|
|
40
|
+
[Parameter(Mandatory = $false)][string]$ScriptRoot = $PSScriptRoot
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
$published = Join-Path $ScriptRoot "../lib/discovery-validation/$ModuleName"
|
|
44
|
+
$selfHosted = Join-Path $ScriptRoot "../../.claude/lib/discovery-validation/$ModuleName"
|
|
45
|
+
foreach ($candidate in @($published, $selfHosted)) {
|
|
46
|
+
if (Test-Path -LiteralPath $candidate -PathType Leaf) { return $candidate }
|
|
47
|
+
}
|
|
48
|
+
return $published
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function Import-DiscoveryPlanningSelfHostedModule {
|
|
52
|
+
<#
|
|
53
|
+
.SYNOPSIS
|
|
54
|
+
Imports the shared helpers from this repository's .claude/lib layout when no published .codex/lib exists (exemption D4).
|
|
55
|
+
#>
|
|
56
|
+
[CmdletBinding()]
|
|
57
|
+
param()
|
|
58
|
+
|
|
59
|
+
$ScriptRoot = $PSScriptRoot
|
|
60
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryEncoding.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryEncoding.psm1' -ErrorRecord $_ }
|
|
61
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryAuthority.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryAuthority.psm1' -ErrorRecord $_ }
|
|
62
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryManifest.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryManifest.psm1' -ErrorRecord $_ }
|
|
63
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryPayload.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryPayload.psm1' -ErrorRecord $_ }
|
|
64
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryToolRouting.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryToolRouting.psm1' -ErrorRecord $_ }
|
|
65
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryAuthorization.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryAuthorization.psm1' -ErrorRecord $_ }
|
|
66
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryStartRecord.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryStartRecord.psm1' -ErrorRecord $_ }
|
|
67
|
+
try { Import-Module (Join-Path $ScriptRoot '../../.claude/lib/discovery-validation/DiscoveryPlanning.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryPlanning.psm1' -ErrorRecord $_ }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# The published destination keeps the helpers beside .codex/hooks; this repository hosts them under .claude/lib.
|
|
71
|
+
if (Test-Path -LiteralPath (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryEncoding.psm1') -PathType Leaf) {
|
|
72
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryEncoding.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryEncoding.psm1' -ErrorRecord $_ }
|
|
73
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryAuthority.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryAuthority.psm1' -ErrorRecord $_ }
|
|
74
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryManifest.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryManifest.psm1' -ErrorRecord $_ }
|
|
75
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryPayload.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryPayload.psm1' -ErrorRecord $_ }
|
|
76
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryToolRouting.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryToolRouting.psm1' -ErrorRecord $_ }
|
|
77
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryAuthorization.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryAuthorization.psm1' -ErrorRecord $_ }
|
|
78
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryStartRecord.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryStartRecord.psm1' -ErrorRecord $_ }
|
|
79
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/discovery-validation/DiscoveryPlanning.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'DiscoveryPlanning.psm1' -ErrorRecord $_ }
|
|
80
|
+
} else {
|
|
81
|
+
Import-DiscoveryPlanningSelfHostedModule
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
$script:DiscoveryPlanningReasonPrefix = 'DISCOVERY_PLANNING_GATE_BLOCKED:'
|
|
85
|
+
|
|
86
|
+
function Invoke-DiscoveryPlanningGateDecision {
|
|
87
|
+
<#
|
|
88
|
+
.SYNOPSIS
|
|
89
|
+
Parses the Codex PreToolUse envelope and returns the planning outcome.
|
|
90
|
+
.DESCRIPTION
|
|
91
|
+
Returns the shared outcome object (Decision, Code, Reason, Receipt,
|
|
92
|
+
Prerequisite). Every seam defaults to the real host and is injectable. A
|
|
93
|
+
recorded dependency failure returns a deny outcome before the envelope is read.
|
|
94
|
+
#>
|
|
95
|
+
[CmdletBinding()]
|
|
96
|
+
[OutputType([pscustomobject])]
|
|
97
|
+
param(
|
|
98
|
+
[Parameter(Mandatory = $false)][AllowNull()][AllowEmptyString()][string]$ToolInputRaw,
|
|
99
|
+
[Parameter(Mandatory = $false)][AllowNull()][hashtable]$HostEnvironment = $null,
|
|
100
|
+
[Parameter(Mandatory = $false)][AllowNull()][hashtable]$Store = $null,
|
|
101
|
+
[Parameter(Mandatory = $false)][AllowNull()][scriptblock]$ReadBytes = $null
|
|
102
|
+
)
|
|
103
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix $script:DiscoveryPlanningReasonPrefix
|
|
104
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
105
|
+
|
|
106
|
+
if ($null -eq $HostEnvironment) { $HostEnvironment = Get-DiscoveryTrustedHostEnvironment }
|
|
107
|
+
if ($null -eq $Store) { $Store = Get-DiscoveryStartStore }
|
|
108
|
+
|
|
109
|
+
$normalized = ConvertFrom-DiscoveryHostPayloadText -HostName 'codex' -Text $ToolInputRaw
|
|
110
|
+
$parameters = @{ Normalized = $normalized; HostEnvironment = $HostEnvironment; Store = $Store }
|
|
111
|
+
if ($null -ne $ReadBytes) { $parameters['ReadBytes'] = $ReadBytes }
|
|
112
|
+
return Get-DiscoveryPlanningDecision @parameters
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function Invoke-DiscoveryPlanningGateEntryPoint {
|
|
116
|
+
<#
|
|
117
|
+
.SYNOPSIS
|
|
118
|
+
Reads one Codex PreToolUse payload, writes the decision and returns the process exit code.
|
|
119
|
+
.DESCRIPTION
|
|
120
|
+
An unreadable envelope writes its reason to stderr and returns 2. A deny
|
|
121
|
+
writes the PreToolUse decision JSON to stdout and returns 0. An allow writes
|
|
122
|
+
nothing and returns 0, as the Codex gates do.
|
|
123
|
+
#>
|
|
124
|
+
[CmdletBinding()]
|
|
125
|
+
[OutputType([int])]
|
|
126
|
+
param([Parameter(Mandatory = $false)][AllowNull()][AllowEmptyString()][string]$PayloadRaw)
|
|
127
|
+
|
|
128
|
+
$outcome = Invoke-DiscoveryPlanningGateDecision -ToolInputRaw $PayloadRaw
|
|
129
|
+
# A dependency failure is already the PreToolUse deny decision.
|
|
130
|
+
if ($outcome -is [System.Collections.IDictionary]) { [Console]::Out.WriteLine(($outcome | ConvertTo-Json -Compress -Depth 5)); return 0 }
|
|
131
|
+
if ($outcome.Decision -eq 'allow') { return 0 }
|
|
132
|
+
if ($outcome.Code -eq 'ENVELOPE') {
|
|
133
|
+
[Console]::Error.WriteLine("$($script:DiscoveryPlanningReasonPrefix) $($outcome.Reason)")
|
|
134
|
+
return 2
|
|
135
|
+
}
|
|
136
|
+
$decision = ConvertTo-DiscoveryPlanningHookOutput -Outcome $outcome -ReasonPrefix $script:DiscoveryPlanningReasonPrefix
|
|
137
|
+
[Console]::Out.WriteLine(($decision | ConvertTo-Json -Compress -Depth 5))
|
|
138
|
+
return 0
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
# Guard allows dot-sourcing in tests without executing the entrypoint.
|
|
142
|
+
if ($MyInvocation.InvocationName -eq '.') {
|
|
143
|
+
return
|
|
144
|
+
}
|
|
145
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('DISCOVERY_PLANNING_GATE_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
146
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'DISCOVERY_PLANNING_GATE_BLOCKED:'
|
|
147
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
148
|
+
|
|
149
|
+
exit (Invoke-DiscoveryPlanningGateEntryPoint -PayloadRaw ([Console]::In.ReadToEnd()))
|