@danmoisan/drm-copilot-mcp 1.0.1 → 1.0.8
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 +896 -202
- package/package.json +1 -1
- package/resources/claude-customizations/.claude/agents/atomic-executor.md +1 -0
- package/resources/claude-customizations/.claude/agents/atomic-planner.md +1 -0
- package/resources/claude-customizations/.claude/agents/commit-message.md +42 -0
- package/resources/claude-customizations/.claude/agents/csharp-typed-engineer.md +1 -0
- package/resources/claude-customizations/.claude/agents/epic-orchestrator.md +128 -0
- package/resources/claude-customizations/.claude/agents/epic-review.md +1 -0
- package/resources/claude-customizations/.claude/agents/feature-review.md +1 -0
- package/resources/claude-customizations/.claude/agents/human-exception-runbook.md +48 -0
- package/resources/claude-customizations/.claude/agents/orchestrator.md +80 -2
- package/resources/claude-customizations/.claude/agents/powershell-typed-engineer.md +1 -0
- package/resources/claude-customizations/.claude/agents/pr-author.md +37 -21
- package/resources/claude-customizations/.claude/agents/prd-feature.md +1 -0
- package/resources/claude-customizations/.claude/agents/python-typed-engineer.md +1 -0
- package/resources/claude-customizations/.claude/agents/staged-review.md +1 -0
- package/resources/claude-customizations/.claude/agents/status-updater.md +1 -0
- package/resources/claude-customizations/.claude/agents/typescript-engineer.md +1 -0
- package/resources/claude-customizations/.claude/hooks/check-powershell-test-purity.ps1 +103 -65
- package/resources/claude-customizations/.claude/hooks/check-python-test-purity.ps1 +12 -9
- package/resources/claude-customizations/.claude/hooks/enforce-checkpoint-monotonic.ps1 +24 -16
- package/resources/claude-customizations/.claude/hooks/enforce-completion-consistency.ps1 +19 -13
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +304 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-wave-barrier.ps1 +304 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate.ps1 +237 -0
- package/resources/claude-customizations/.claude/hooks/enforce-evidence-locations.ps1 +16 -12
- package/resources/claude-customizations/.claude/hooks/enforce-feature-folder-order.ps1 +14 -10
- package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +182 -0
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +35 -8
- package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +17 -14
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.epic-base-branch.ps1 +104 -0
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.ps1 +268 -93
- package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner.ps1 +19 -11
- package/resources/claude-customizations/.claude/hooks/enforce-promotion-mcp-only.ps1 +28 -6
- package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +17 -14
- package/resources/claude-customizations/.claude/hooks/validate-bash.ps1 +146 -36
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +27 -7
- package/resources/claude-customizations/.claude/rules/orchestrator-state.md +53 -0
- package/resources/claude-customizations/.claude/settings.json +38 -1
- package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +252 -0
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +59 -13
- package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +28 -0
- package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +22 -18
- package/resources/claude-customizations/pack-manifests/core.json +9 -0
- package/resources/codex-and-agents-customizations/.agents/skills/feature-promotion-lifecycle/SKILL.md +8 -2
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +24 -3
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +13 -0
- package/resources/codex-and-agents-customizations/.agents/skills/remediation-handoff-atomic-planner/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp/SKILL.md +65 -0
- package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +79 -0
- package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/invoke-csharp-engineer/SKILL.md +66 -0
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +15 -14
- package/resources/codex-and-agents-customizations/.codex/config.toml +1 -25
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-consistency.ps1 +144 -28
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-helpers.ps1 +163 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-pr-author-skill.ps1 +257 -93
- package/resources/codex-and-agents-customizations/.codex-variants/csharp-legacy/agents/csharp-typed-engineer.toml +98 -0
- package/resources/codex-and-agents-customizations/pack-manifests/core.json +24 -0
- package/resources/codex-and-agents-customizations/pack-manifests/csharp-legacy.json +11 -0
- package/resources/codex-and-agents-customizations/pack-manifests/csharp-modern.json +10 -0
- package/resources/codex-and-agents-customizations/pack-manifests/powershell.json +15 -0
- package/resources/codex-and-agents-customizations/pack-manifests/python.json +15 -0
- package/resources/codex-and-agents-customizations/pack-manifests/typescript.json +9 -0
- package/resources/config/orchestration-routing.json +92 -0
- package/resources/customizations/.github/agents/pr-author.agent.md +24 -18
- package/resources/icon.png +0 -0
- package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +11 -0
- package/resources/codex-and-agents-customizations/.github/workflows/_validate-orchestrator-state.yml +0 -68
- package/resources/codex-and-agents-customizations/.github/workflows/validate-orchestrator-state.yml +0 -15
|
@@ -109,6 +109,24 @@ staging, commits, or implementation delegation. This gate covers edits, formatte
|
|
|
109
109
|
If any required item is missing, implementation is blocked until the checkpoint
|
|
110
110
|
and lifecycle state are corrected.
|
|
111
111
|
|
|
112
|
+
## Plan-Path Resolution Gate
|
|
113
|
+
|
|
114
|
+
After active feature folder creation and before any planning delegation, the
|
|
115
|
+
main session must resolve `${plan-path}` from the active feature folder:
|
|
116
|
+
|
|
117
|
+
1. Enumerate existing `${feature-folder}/plan*.md` files in deterministic
|
|
118
|
+
filename order.
|
|
119
|
+
2. If one or more files exist, persist `${plan-path}` as the first existing
|
|
120
|
+
file and require every planner and executor handoff to use that exact path.
|
|
121
|
+
3. If no `plan*.md` file exists, create exactly one canonical target path using
|
|
122
|
+
the repository's feature-folder plan naming convention, persist that path,
|
|
123
|
+
and reuse it for all revisions.
|
|
124
|
+
4. Do not default to `${feature-folder}/plan.md` when a timestamped scaffolded
|
|
125
|
+
plan already exists.
|
|
126
|
+
5. If checkpoint state names a different plan path than the resolved existing
|
|
127
|
+
plan file, correct the checkpoint before planner delegation. Do not create a
|
|
128
|
+
second plan artifact to satisfy an incorrect checkpoint value.
|
|
129
|
+
|
|
112
130
|
## Pre-Implementation Violation Handling
|
|
113
131
|
|
|
114
132
|
If an implementation action is attempted before a required orchestration gate
|
|
@@ -141,9 +159,12 @@ There is no fallback. If the MCP server or validation tool is unavailable, or
|
|
|
141
159
|
if validation fails, the orchestrator must update blocked state and stop rather
|
|
142
160
|
than reporting completion.
|
|
143
161
|
|
|
144
|
-
|
|
145
|
-
checkpoint is present
|
|
146
|
-
that
|
|
162
|
+
No CI workflow performs this validation. The `artifacts/` directory is gitignored,
|
|
163
|
+
so the orchestrator-state checkpoint is never present in a CI checkout; a prior
|
|
164
|
+
CI gate (`validate-orchestrator-state.yml`) that attempted this check was a
|
|
165
|
+
structural no-op for that reason and has been removed. The MCP-server-based
|
|
166
|
+
validation described above is this ecosystem's enforcement mechanism for the
|
|
167
|
+
orchestrator-state checkpoint.
|
|
147
168
|
|
|
148
169
|
Completion validation requires the checkpoint to prove mandatory handoffs and
|
|
149
170
|
skill use. The checkpoint must include:
|
package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md
CHANGED
|
@@ -101,6 +101,16 @@ Persist and reuse these fields exactly:
|
|
|
101
101
|
- `lifecycle_operations`
|
|
102
102
|
- `pre-implementation-violation`
|
|
103
103
|
|
|
104
|
+
Plan-path invariant:
|
|
105
|
+
- `${plan-path}` is resolved only after `${feature-folder}` exists.
|
|
106
|
+
- The orchestrator MUST enumerate existing `${feature-folder}/plan*.md` files
|
|
107
|
+
in deterministic filename order before planner delegation.
|
|
108
|
+
- If any existing plan file is present, `${plan-path}` MUST be that first
|
|
109
|
+
existing file. Do not persist or delegate against `${feature-folder}/plan.md`
|
|
110
|
+
when a timestamped scaffolded plan already exists.
|
|
111
|
+
- If checkpoint state conflicts with the resolved existing plan file, correct
|
|
112
|
+
checkpoint state before delegation and do not create a duplicate plan.
|
|
113
|
+
|
|
104
114
|
For small-path runs, also persist:
|
|
105
115
|
- `bootstrap_mode`
|
|
106
116
|
- `phase0_execution_summary`
|
|
@@ -310,6 +320,9 @@ Required behavior:
|
|
|
310
320
|
7. When those specialists are not yet migrated, perform the authoring steps directly without changing template headings.
|
|
311
321
|
8. Spawn `atomic-planner` to finalize `${plan-path}` and require `PREFLIGHT: ALL CLEAR`.
|
|
312
322
|
Hard enforcement for Step 7:
|
|
323
|
+
- Before spawning `atomic-planner`, resolve `${plan-path}` by enumerating
|
|
324
|
+
existing `${feature-folder}/plan*.md` files. Reuse the first existing file
|
|
325
|
+
in deterministic filename order, including timestamped scaffolded plans.
|
|
313
326
|
- The planning route MUST be `atomic-planner -> atomic-executor` for preflight validation.
|
|
314
327
|
- The planner MUST update `${plan-path}` in place and MUST NOT create additional `plan.*.md` files for revisions.
|
|
315
328
|
- The approved plan MUST include explicit Phase 0 baseline evidence tasks and explicit final-QA evidence or coverage tasks for each language in scope where policy requires them.
|
|
@@ -22,7 +22,7 @@ Trigger remediation when any of these are true:
|
|
|
22
22
|
|
|
23
23
|
## Required Remediation Inputs
|
|
24
24
|
|
|
25
|
-
Create `remediation-inputs
|
|
25
|
+
Create `remediation/<timestamp>/remediation-inputs.md` (one timestamped `remediation/` folder per cycle; reaudit artifacts from a triggering or exit review live under the sibling `audit/<timestamp>/` folder, per the canonical pattern documented in the Claude-side `remediation-handoff-atomic-planner` skill) with:
|
|
26
26
|
- Enumerated fix list with file paths, expected behavior, and verification commands.
|
|
27
27
|
- A “do not do” list (no scope creep, no policy weakening, no silent skips).
|
|
28
28
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: csharp
|
|
3
|
+
paths:
|
|
4
|
+
- "**/*.cs"
|
|
5
|
+
- "**/*.csproj"
|
|
6
|
+
description: C#-specific toolchain and coding standards.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# C# Code Standards
|
|
10
|
+
|
|
11
|
+
Legacy C# variant resource for Codex push-down.
|
|
12
|
+
|
|
13
|
+
This rule file summarizes the C#-specific policies for this repository.
|
|
14
|
+
|
|
15
|
+
## Toolchain
|
|
16
|
+
|
|
17
|
+
1. **Formatting — CSharpier**: All C# source files must be formatted with CSharpier. Do not use `dotnet format`. Command: `dotnet tool run csharpier .` or `csharpier .`
|
|
18
|
+
2. **Linting — .NET Analyzers**: C# code must pass Roslyn/.NET analyzer diagnostics. Command: `msbuild TaskMaster.sln /t:Build /p:Configuration=Debug /p:Platform="Any CPU" /p:EnableNETAnalyzers=true /p:EnforceCodeStyleInBuild=true`
|
|
19
|
+
3. **Type Checking — Nullable Analysis**: Enable nullable reference types and fail on warnings. Command: `msbuild TaskMaster.sln /t:Build /p:Configuration=Debug /p:Platform="Any CPU" /p:Nullable=enable /p:TreatWarningsAsErrors=true`
|
|
20
|
+
4. **Testing — MSTest + Moq + FluentAssertions**: Run tests with: `vstest.console.exe <test-assembly-paths> /EnableCodeCoverage`
|
|
21
|
+
|
|
22
|
+
Run the toolchain in order: format → lint → type-check → test. Restart from step 1 if any step fails or changes files.
|
|
23
|
+
|
|
24
|
+
## Coding Standards
|
|
25
|
+
|
|
26
|
+
- **Naming**: `PascalCase` for types and public members. `camelCase` for locals and private fields/parameters.
|
|
27
|
+
- **Null safety**: Keep nullable reference types enabled. Model optional values with nullable annotations and guard clauses.
|
|
28
|
+
- **Composition over inheritance**: Keep classes cohesive and scoped to one responsibility. Favor composition unless polymorphism is a clear requirement.
|
|
29
|
+
- **Async/await**: Use `async`/`await` for I/O-bound operations. Prefer `using`/`await using` for disposable resources.
|
|
30
|
+
- **Exceptions**: Fail fast with explicit exceptions. Avoid broad `catch (Exception)` unless at a defined boundary with added context.
|
|
31
|
+
- **Public surface**: Keep public API surface intentional and minimal. Prefer `internal` for non-public APIs.
|
|
32
|
+
- **XML docs**: Public APIs should include XML documentation comments when behavior or contract is non-obvious.
|
|
33
|
+
|
|
34
|
+
## Testing Standards
|
|
35
|
+
|
|
36
|
+
- Use **MSTest** (`Microsoft.VisualStudio.TestTools.UnitTesting`) as the test framework.
|
|
37
|
+
- Use **Moq** for mocking.
|
|
38
|
+
- Prefer **FluentAssertions** for assertions; use MSTest `Assert` only when FluentAssertions is not practical.
|
|
39
|
+
- Use `[TestClass]` and `[TestMethod]` attributes.
|
|
40
|
+
- Follow Arrange–Act–Assert structure.
|
|
41
|
+
- No external dependencies in unit tests.
|
|
42
|
+
- Repository-wide line coverage must remain >= 80%.
|
|
43
|
+
- Any new module, class, or method must reach >= 90% coverage.
|
|
44
|
+
- Coverage regression on changed lines is a blocking finding.
|
|
45
|
+
|
|
46
|
+
## Deterministic Test Rules
|
|
47
|
+
|
|
48
|
+
Unit tests must not depend on network, mutable machine PATH or profile state, implicit working-directory assumptions, or external services. Use seam-based mocking for all external boundaries (processes, HTTP, filesystem, clocks). Tests must produce identical results in the IDE test runner and in CLI runs so local and CI behavior agree.
|
|
49
|
+
|
|
50
|
+
## DI Seams
|
|
51
|
+
|
|
52
|
+
Introduce the smallest seam that enables reliable unit testing. Apply in this order of preference:
|
|
53
|
+
|
|
54
|
+
1. **Interface seam (preferred)** — extract boundary calls into narrow purpose-specific interfaces (for example, `IProcessRunner`, `IFileSystem`, `IClock`). Keep interfaces minimal.
|
|
55
|
+
2. **Injectable delegate seam** — use a narrow `Func<>`/`Action<>` delegate for a single call path when a full interface is excessive. Default behavior must remain safe and deterministic.
|
|
56
|
+
3. **Adapter seam for static or third-party APIs** — wrap the static or third-party call behind a small adapter so tests can mock the adapter with Moq.
|
|
57
|
+
|
|
58
|
+
## Prohibited Behaviors
|
|
59
|
+
|
|
60
|
+
- Broad refactors across unrelated projects or files.
|
|
61
|
+
- Introducing heavy generic abstraction frameworks without need.
|
|
62
|
+
- Creating analyzer debt and deferring cleanup.
|
|
63
|
+
- Weakening assertions or relaxing test expectations to make tests pass.
|
|
64
|
+
- Adding sleeps, retries, or timing hacks to mask flaky behavior.
|
|
65
|
+
- Reporting success without running the required toolchain.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: csharp-qa-gate
|
|
3
|
+
description: Final QA gate for C# changes. Executes the full CSharpier -> .NET Analyzers -> Nullable Analysis -> MSTest toolchain, compares against a captured baseline, enforces zero-regression deltas, and produces the required reporting block before the agent declares the change complete.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# C# QA Gate
|
|
7
|
+
|
|
8
|
+
Legacy C# variant resource for Codex push-down.
|
|
9
|
+
|
|
10
|
+
Canonical procedure for the Phase D final quality gate that every C# change must pass before completion is reported.
|
|
11
|
+
|
|
12
|
+
## When to Use This Skill
|
|
13
|
+
|
|
14
|
+
Use this skill when:
|
|
15
|
+
|
|
16
|
+
- `csharp-typed-engineer` is about to declare a change complete.
|
|
17
|
+
- An executor has finished applying a planned batch and must verify zero regressions against the baseline captured in Phase A.
|
|
18
|
+
- A reviewer needs to confirm the toolchain was actually run and produced a clean pass.
|
|
19
|
+
|
|
20
|
+
## Required Inputs
|
|
21
|
+
|
|
22
|
+
Before invoking this gate, the agent must have:
|
|
23
|
+
|
|
24
|
+
- a baseline record produced in Phase A, containing analyzer findings, compiler/nullable diagnostics, MSTest pass/fail status, and per-file coverage status for the in-scope files,
|
|
25
|
+
- the exact list of touched production and test files,
|
|
26
|
+
- a clean working tree (all planned edits committed to the working copy).
|
|
27
|
+
|
|
28
|
+
## Toolchain Execution Sequence
|
|
29
|
+
|
|
30
|
+
Run the full toolchain in this exact order. If any step fails or modifies files, fix the issue and restart from step 1. Do not stop the loop until all four steps complete without errors in a single pass.
|
|
31
|
+
|
|
32
|
+
1. `dotnet tool run csharpier .`
|
|
33
|
+
2. `msbuild TaskMaster.sln /t:Build /p:Configuration=Debug /p:Platform="Any CPU" /p:EnableNETAnalyzers=true /p:EnforceCodeStyleInBuild=true`
|
|
34
|
+
3. `msbuild TaskMaster.sln /t:Build /p:Configuration=Debug /p:Platform="Any CPU" /p:Nullable=enable /p:TreatWarningsAsErrors=true`
|
|
35
|
+
4. `vstest.console.exe <test-assembly-paths> /EnableCodeCoverage`
|
|
36
|
+
|
|
37
|
+
If the environment prevents running any tool, stop and report the change as **unverified**. Do not declare completion.
|
|
38
|
+
|
|
39
|
+
## Delta Requirements (Zero-Regression Hard Gate)
|
|
40
|
+
|
|
41
|
+
Compare the final results to the Phase A baseline. All of the following must hold:
|
|
42
|
+
|
|
43
|
+
- **Analyzer delta**: 0 new findings across the repository.
|
|
44
|
+
- **Compiler / nullable delta**: 0 new diagnostics across the repository.
|
|
45
|
+
- **MSTest delta**: 0 new failing tests.
|
|
46
|
+
- **Per-file coverage delta**: coverage for every touched file is greater than or equal to the baseline for that file.
|
|
47
|
+
- **Overall coverage delta** (when the repo enforces it): overall coverage is greater than or equal to the baseline.
|
|
48
|
+
- **New modules, classes, or methods**: coverage >= 90% for each new unit introduced in the batch.
|
|
49
|
+
|
|
50
|
+
If any delta check fails, the agent must revert or fix immediately and rerun the full toolchain. Do not proceed to reporting until all deltas are clean.
|
|
51
|
+
|
|
52
|
+
## Required Reporting Block
|
|
53
|
+
|
|
54
|
+
Every completion response must include the following sections:
|
|
55
|
+
|
|
56
|
+
1. **Scope** — exact file list touched in this change.
|
|
57
|
+
2. **Baseline** — analyzer, compiler/nullable, MSTest, and coverage status recorded in Phase A.
|
|
58
|
+
3. **Plan** — design and test-strategy summary, referencing the approved plan.
|
|
59
|
+
4. **Diffs** — patch-style or full-file replacements for scoped files only.
|
|
60
|
+
5. **QA Gate Results** — analyzer, compiler/nullable, MSTest, and coverage deltas. If any step could not be run, mark the corresponding line **unverified** and state why.
|
|
61
|
+
|
|
62
|
+
## Evidence Storage
|
|
63
|
+
|
|
64
|
+
Persist toolchain output according to `evidence-and-timestamp-conventions`:
|
|
65
|
+
|
|
66
|
+
- store baseline outputs under `<FEATURE>/evidence/baseline/<timestamp>/`,
|
|
67
|
+
- store post-change outputs under `<FEATURE>/evidence/qa-gates/<timestamp>/`,
|
|
68
|
+
- use ISO-8601 UTC timestamps in folder names.
|
|
69
|
+
|
|
70
|
+
This location is canonical per evidence-and-timestamp-conventions and is not overridable.
|
|
71
|
+
See `.agents/skills/evidence-and-timestamp-conventions/SKILL.md` for the canonical evidence path authority.
|
|
72
|
+
|
|
73
|
+
The evidence paths must be referenced in the agent's completion message to satisfy the `SubagentStop` completion-artifact gate.
|
|
74
|
+
|
|
75
|
+
## Prohibited Shortcuts
|
|
76
|
+
|
|
77
|
+
- Do not disable, skip, or narrow any step of the toolchain to reach a clean result.
|
|
78
|
+
- Do not add analyzer suppressions, `#pragma warning disable`, `#nullable disable`, or test `[Ignore]` attributes to suppress new findings introduced by the change.
|
|
79
|
+
- Do not report success based on partial or targeted runs alone. Targeted runs are allowed mid-batch, but the final gate requires a full-solution pass.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: invoke-csharp-engineer
|
|
3
|
+
description: Invoke the csharp-typed-engineer worker to design, implement, and verify C# changes within typed repository boundaries. Applies CSharpier -> .NET Analyzers -> Nullable Analysis -> MSTest toolchain, the 1-3 production-file small-path budget, and zero-regression quality gates.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Implement C# Skill
|
|
7
|
+
|
|
8
|
+
Legacy C# variant resource for Codex push-down.
|
|
9
|
+
|
|
10
|
+
This direct-use wrapper delegates C# implementation work to the `csharp-typed-engineer` worker. Use this entry point when a prompt needs a scoped C# change that must stay inside the typed engineer's guardrails.
|
|
11
|
+
|
|
12
|
+
## When to Use This Skill
|
|
13
|
+
|
|
14
|
+
Use this skill when:
|
|
15
|
+
|
|
16
|
+
- The user requests a C# code change, bug fix, refactor, or test addition.
|
|
17
|
+
- Estimated scope fits the small path (1-3 production files plus corresponding tests).
|
|
18
|
+
- The toolchain (CSharpier, .NET Analyzers, Nullable Analysis, MSTest) can be run in the current environment, or the user has explicitly authorized an unverified plan-only response.
|
|
19
|
+
|
|
20
|
+
If the estimated scope exceeds the small-path budget, this skill defers to the orchestrated flow via `csharp-change-budget-router` instead of proceeding directly.
|
|
21
|
+
|
|
22
|
+
## Inputs
|
|
23
|
+
|
|
24
|
+
- Objective statement (what the change must accomplish).
|
|
25
|
+
- Files or entrypoints in scope.
|
|
26
|
+
- Constraints, including public APIs that must be preserved.
|
|
27
|
+
- Optional approved plan. If none is supplied, the worker delegates plan authoring to `atomic_planner` before any edits.
|
|
28
|
+
- Optional budget override in the form `budget: prod=<N>, test=<M>` subject to repo policy compliance.
|
|
29
|
+
|
|
30
|
+
## Output Paths
|
|
31
|
+
|
|
32
|
+
- C# source and test files within the approved scope.
|
|
33
|
+
- Baseline evidence under `<FEATURE>/evidence/baseline/<timestamp>/` and post-change evidence under `<FEATURE>/evidence/qa-gates/<timestamp>/` per `evidence-and-timestamp-conventions`.
|
|
34
|
+
- This location is canonical per evidence-and-timestamp-conventions and is not overridable. See `.agents/skills/evidence-and-timestamp-conventions/SKILL.md` for the canonical evidence path authority.
|
|
35
|
+
- Plan artifacts under the active feature folder when the task is feature-scoped.
|
|
36
|
+
|
|
37
|
+
## Required Reporting Block
|
|
38
|
+
|
|
39
|
+
The worker must return the following reporting block:
|
|
40
|
+
|
|
41
|
+
1. Scope (exact file list).
|
|
42
|
+
2. Baseline (CSharpier, .NET Analyzers, Nullable Analysis, MSTest, coverage status).
|
|
43
|
+
3. Plan (design and test strategy).
|
|
44
|
+
4. Diffs (patch-style or full-file replacements).
|
|
45
|
+
5. QA Gate Results (CSharpier, .NET Analyzers, Nullable Analysis, MSTest, and coverage deltas, or clearly marked **unverified**).
|
|
46
|
+
|
|
47
|
+
## Worker Routing
|
|
48
|
+
|
|
49
|
+
- Worker: `csharp-typed-engineer`
|
|
50
|
+
|
|
51
|
+
## Preloaded Contracts
|
|
52
|
+
|
|
53
|
+
The worker operates under the following preloaded skills and rules:
|
|
54
|
+
|
|
55
|
+
- `policy-compliance-order`
|
|
56
|
+
- `csharp-change-budget-router`
|
|
57
|
+
- `atomic-plan-contract`
|
|
58
|
+
- `csharp-qa-gate`
|
|
59
|
+
- `acceptance-criteria-tracking`
|
|
60
|
+
- `feature-promotion-lifecycle`
|
|
61
|
+
- `remediation-handoff-atomic-planner`
|
|
62
|
+
- `evidence-and-timestamp-conventions`
|
|
63
|
+
- `.agents/skills/csharp/SKILL.md` (path-scoped for `**/*.cs` and `**/*.csproj`)
|
|
64
|
+
- `AGENTS.md`
|
|
65
|
+
- `AGENTS.md`
|
|
66
|
+
- `AGENTS.md`
|
|
@@ -76,6 +76,8 @@ Every agent named above must exist as a native Codex agent under `.codex/agents/
|
|
|
76
76
|
- Do not rename, back up, or create sidecar checkpoint files.
|
|
77
77
|
- Do not create or edit `${feature-folder}/issue.md`, `${feature-folder}/spec.md`, `${feature-folder}/user-story.md`, or `plan*.md` until lifecycle setup succeeds.
|
|
78
78
|
- Do not persist placeholder lifecycle values such as `NONE`, `TBD`, or empty strings once lifecycle setup begins.
|
|
79
|
+
- After active folder creation and before planner delegation, resolve `${plan-path}` by enumerating existing `${feature-folder}/plan*.md` files in deterministic filename order. If a scaffolded timestamped plan exists, persist and delegate against that exact file. Do not default to `${feature-folder}/plan.md` and do not create a second plan artifact when a plan already exists.
|
|
80
|
+
- For issue #306, the canonical existing plan path is `docs/features/active/2026-07-04-codex-agent-role-config-306/plan.2026-07-04T13-47.md`; reuse that exact file and do not create `docs/features/active/2026-07-04-codex-agent-role-config-306/plan.md`.
|
|
79
81
|
|
|
80
82
|
## Checkpoint Persistence
|
|
81
83
|
|
|
@@ -133,17 +135,16 @@ The MCP validator and required CI checks are the hard completion boundary. There
|
|
|
133
135
|
Do not claim mission completion unless all required delegations completed with receipts and the required orchestration artifacts exist on disk.
|
|
134
136
|
'''
|
|
135
137
|
|
|
136
|
-
[
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
pr-base-branch-merge-base = true
|
|
138
|
+
[skills]
|
|
139
|
+
config = [
|
|
140
|
+
{ name = "policy-compliance-order", enabled = true },
|
|
141
|
+
{ name = "orchestrate", enabled = true },
|
|
142
|
+
{ name = "orchestrator-workflow", enabled = true },
|
|
143
|
+
{ name = "feature-promotion-lifecycle", enabled = true },
|
|
144
|
+
{ name = "repo-automation-adapter", enabled = true },
|
|
145
|
+
{ name = "atomic-plan-contract", enabled = true },
|
|
146
|
+
{ name = "acceptance-criteria-tracking", enabled = true },
|
|
147
|
+
{ name = "evidence-and-timestamp-conventions", enabled = true },
|
|
148
|
+
{ name = "pr-context-artifacts", enabled = true },
|
|
149
|
+
{ name = "pr-base-branch-merge-base", enabled = true },
|
|
150
|
+
]
|
|
@@ -84,28 +84,4 @@ command = "pwsh -NoProfile -File .codex/hooks/enforce-orchestration-preimplement
|
|
|
84
84
|
|
|
85
85
|
[[hooks.SubagentStop]]
|
|
86
86
|
matcher = "feature-review|feature-reviewer"
|
|
87
|
-
command = "pwsh -NoProfile -File .codex/hooks/validate-feature-review-coverage.ps1"
|
|
88
|
-
|
|
89
|
-
[permissions.orchestrator-workspace]
|
|
90
|
-
description = "Workspace editing for deterministic orchestration with secret-path deny rules."
|
|
91
|
-
extends = ":workspace"
|
|
92
|
-
|
|
93
|
-
[permissions.orchestrator-workspace.filesystem]
|
|
94
|
-
glob_scan_max_depth = 4
|
|
95
|
-
|
|
96
|
-
[permissions.orchestrator-workspace.filesystem.":workspace_roots"]
|
|
97
|
-
"**/.env" = "deny"
|
|
98
|
-
"**/.env.*" = "deny"
|
|
99
|
-
"secrets" = "deny"
|
|
100
|
-
"secrets/**" = "deny"
|
|
101
|
-
|
|
102
|
-
[permissions.orchestrator-workspace.network]
|
|
103
|
-
enabled = true
|
|
104
|
-
|
|
105
|
-
[permissions.orchestrator-workspace.network.domains]
|
|
106
|
-
"github.com" = "allow"
|
|
107
|
-
"api.github.com" = "allow"
|
|
108
|
-
"objects.githubusercontent.com" = "allow"
|
|
109
|
-
"registry.npmjs.org" = "allow"
|
|
110
|
-
"pypi.org" = "allow"
|
|
111
|
-
"files.pythonhosted.org" = "allow"
|
|
87
|
+
command = "pwsh -NoProfile -File .codex/hooks/validate-feature-review-coverage.ps1"
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-consistency.ps1
CHANGED
|
@@ -23,9 +23,11 @@
|
|
|
23
23
|
variables.feature-folder);
|
|
24
24
|
- a ci_gate object with conclusion == "success" and a non-empty head_sha.
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
When completion evidence is missing the hook emits a PreToolUse JSON
|
|
27
|
+
response with hookSpecificOutput.permissionDecision='deny' and a reason that
|
|
28
|
+
names the specific missing evidence so the caller can remediate. When
|
|
29
|
+
completion is not asserted, the write is allowed via
|
|
30
|
+
hookSpecificOutput.permissionDecision='allow' (backward compatibility).
|
|
29
31
|
|
|
30
32
|
Edit tool calls supply only old_string/new_string (a partial patch) and
|
|
31
33
|
cannot be reliably validated without the full target file content, so they
|
|
@@ -39,6 +41,11 @@
|
|
|
39
41
|
[CmdletBinding()]
|
|
40
42
|
param()
|
|
41
43
|
|
|
44
|
+
# Dot-source the shared validation helpers. Guarded so a missing file produces a
|
|
45
|
+
# clear error and so dot-sourcing this hook in tests loads the helpers too.
|
|
46
|
+
$script:CompletionHelpersPath = Join-Path $PSScriptRoot 'enforce-completion-helpers.ps1'
|
|
47
|
+
. $script:CompletionHelpersPath
|
|
48
|
+
|
|
42
49
|
function ConvertFrom-CheckpointJson {
|
|
43
50
|
<#
|
|
44
51
|
.SYNOPSIS
|
|
@@ -53,6 +60,29 @@ function ConvertFrom-CheckpointJson {
|
|
|
53
60
|
return $Json | ConvertFrom-Json -ErrorAction Stop
|
|
54
61
|
}
|
|
55
62
|
|
|
63
|
+
function Get-CheckpointFileContent {
|
|
64
|
+
<#
|
|
65
|
+
.SYNOPSIS
|
|
66
|
+
Reads the on-disk checkpoint content for the read-then-validate Edit path.
|
|
67
|
+
.DESCRIPTION
|
|
68
|
+
Returns the full file text when the path resolves to a file on disk, or
|
|
69
|
+
$null when the file does not exist. Tests inject a CheckpointReader
|
|
70
|
+
scriptblock instead of mocking this function so no temporary files are
|
|
71
|
+
required.
|
|
72
|
+
#>
|
|
73
|
+
[CmdletBinding()]
|
|
74
|
+
[OutputType([string])]
|
|
75
|
+
param(
|
|
76
|
+
[Parameter(Mandatory)]
|
|
77
|
+
[string] $Path
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
|
|
81
|
+
return $null
|
|
82
|
+
}
|
|
83
|
+
return Get-Content -LiteralPath $Path -Raw -ErrorAction Stop
|
|
84
|
+
}
|
|
85
|
+
|
|
56
86
|
function Test-IsCheckpointPath {
|
|
57
87
|
[CmdletBinding()]
|
|
58
88
|
[OutputType([bool])]
|
|
@@ -149,7 +179,13 @@ function Get-MissingCompletionEvidence {
|
|
|
149
179
|
param(
|
|
150
180
|
[Parameter(Mandatory)]
|
|
151
181
|
[AllowNull()]
|
|
152
|
-
$Payload
|
|
182
|
+
$Payload,
|
|
183
|
+
|
|
184
|
+
[Parameter(Mandatory = $false)]
|
|
185
|
+
[scriptblock] $FolderExistsCheck = { param($p) Test-Path -LiteralPath $p -PathType Container },
|
|
186
|
+
|
|
187
|
+
[Parameter(Mandatory = $false)]
|
|
188
|
+
[scriptblock] $RoutingMatrixReader
|
|
153
189
|
)
|
|
154
190
|
|
|
155
191
|
$missing = @()
|
|
@@ -158,16 +194,17 @@ function Get-MissingCompletionEvidence {
|
|
|
158
194
|
if (-not $issueNum -and $null -ne $Payload -and ($Payload.PSObject.Properties.Name -contains 'variables')) {
|
|
159
195
|
$issueNum = Get-CheckpointStringValue -Payload $Payload.variables -Name 'issue-num'
|
|
160
196
|
}
|
|
161
|
-
if (-not $issueNum) {
|
|
162
|
-
|
|
197
|
+
if (-not (Test-IsValidIssueNum -Value $issueNum)) {
|
|
198
|
+
# Name the offending value so sentinel/placeholder inputs are explicit.
|
|
199
|
+
$missing += "issue-num value '$issueNum' is not a valid issue number (must be digits-only)"
|
|
163
200
|
}
|
|
164
201
|
|
|
165
202
|
$featureFolder = Get-CheckpointStringValue -Payload $Payload -Name 'feature-folder'
|
|
166
203
|
if (-not $featureFolder -and $null -ne $Payload -and ($Payload.PSObject.Properties.Name -contains 'variables')) {
|
|
167
204
|
$featureFolder = Get-CheckpointStringValue -Payload $Payload.variables -Name 'feature-folder'
|
|
168
205
|
}
|
|
169
|
-
if (-not $featureFolder) {
|
|
170
|
-
$missing +=
|
|
206
|
+
if (-not (Test-IsValidFeatureFolder -Value $featureFolder -FolderExistsCheck $FolderExistsCheck)) {
|
|
207
|
+
$missing += "feature-folder value '$featureFolder' is not a valid feature folder (must be under docs/features/active/ and exist)"
|
|
171
208
|
}
|
|
172
209
|
|
|
173
210
|
$ciGate = $null
|
|
@@ -188,7 +225,14 @@ function Get-MissingCompletionEvidence {
|
|
|
188
225
|
}
|
|
189
226
|
}
|
|
190
227
|
|
|
191
|
-
|
|
228
|
+
# PR-gate evidence is required only when the checkpoint's selected route
|
|
229
|
+
# opts into it via requires_pr_gate in the routing matrix. This replaces the
|
|
230
|
+
# former issue-number special-casing with route-driven enforcement.
|
|
231
|
+
$prGateArgs = @{ Payload = $Payload }
|
|
232
|
+
if ($PSBoundParameters.ContainsKey('RoutingMatrixReader') -and $null -ne $RoutingMatrixReader) {
|
|
233
|
+
$prGateArgs['RoutingMatrixReader'] = $RoutingMatrixReader
|
|
234
|
+
}
|
|
235
|
+
if (Test-RouteRequiresPrGate @prGateArgs) {
|
|
192
236
|
$prGate = $null
|
|
193
237
|
if ($null -ne $Payload -and ($Payload.PSObject.Properties.Name -contains 'pr_gate')) {
|
|
194
238
|
$prGate = $Payload.pr_gate
|
|
@@ -213,6 +257,60 @@ function Get-MissingCompletionEvidence {
|
|
|
213
257
|
return [string[]]$missing
|
|
214
258
|
}
|
|
215
259
|
|
|
260
|
+
function Resolve-EditedCheckpointContent {
|
|
261
|
+
<#
|
|
262
|
+
.SYNOPSIS
|
|
263
|
+
Returns the patched checkpoint content for an Edit-tool call, or $null
|
|
264
|
+
when the patch cannot be applied against the on-disk checkpoint.
|
|
265
|
+
.DESCRIPTION
|
|
266
|
+
Implements the read-then-validate Edit path. When the tool input carries
|
|
267
|
+
an old_string (an Edit patch), the on-disk checkpoint is read through the
|
|
268
|
+
injectable CheckpointReader seam and the old_string -> new_string
|
|
269
|
+
replacement is applied in memory (no on-disk mutation). Returns $null
|
|
270
|
+
when there is no old_string, the on-disk file does not exist, or the
|
|
271
|
+
old_string is not present in the on-disk content, signalling the caller
|
|
272
|
+
to allow (defer).
|
|
273
|
+
#>
|
|
274
|
+
[CmdletBinding()]
|
|
275
|
+
[OutputType([string])]
|
|
276
|
+
param(
|
|
277
|
+
[Parameter(Mandatory)]
|
|
278
|
+
[AllowNull()]
|
|
279
|
+
$ToolInput,
|
|
280
|
+
|
|
281
|
+
[Parameter(Mandatory)]
|
|
282
|
+
[scriptblock] $CheckpointReader
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
$oldString = $null
|
|
286
|
+
if ($null -ne $ToolInput -and ($ToolInput.PSObject.Properties.Name -contains 'old_string')) {
|
|
287
|
+
$oldString = [string]$ToolInput.old_string
|
|
288
|
+
}
|
|
289
|
+
if ([string]::IsNullOrEmpty($oldString)) {
|
|
290
|
+
return $null
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
$newString = ''
|
|
294
|
+
if ($ToolInput.PSObject.Properties.Name -contains 'new_string') {
|
|
295
|
+
$newString = [string]$ToolInput.new_string
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
$onDisk = & $CheckpointReader 'artifacts/orchestration/orchestrator-state.json'
|
|
299
|
+
if ([string]::IsNullOrEmpty([string]$onDisk)) {
|
|
300
|
+
# The on-disk checkpoint does not exist (or is empty); cannot patch.
|
|
301
|
+
return $null
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
$onDiskText = [string]$onDisk
|
|
305
|
+
if (-not $onDiskText.Contains($oldString)) {
|
|
306
|
+
# The old_string is not present, so the patch does not apply here.
|
|
307
|
+
return $null
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
# Apply the patch in memory using a literal (non-regex) replacement.
|
|
311
|
+
return $onDiskText.Replace($oldString, $newString)
|
|
312
|
+
}
|
|
313
|
+
|
|
216
314
|
function Invoke-CompletionConsistencyDecision {
|
|
217
315
|
<#
|
|
218
316
|
.SYNOPSIS
|
|
@@ -222,11 +320,20 @@ function Invoke-CompletionConsistencyDecision {
|
|
|
222
320
|
[CmdletBinding()]
|
|
223
321
|
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
224
322
|
param(
|
|
225
|
-
[string] $ToolInputRaw
|
|
323
|
+
[string] $ToolInputRaw,
|
|
324
|
+
|
|
325
|
+
[Parameter(Mandatory = $false)]
|
|
326
|
+
[scriptblock] $FolderExistsCheck = { param($p) Test-Path -LiteralPath $p -PathType Container },
|
|
327
|
+
|
|
328
|
+
[Parameter(Mandatory = $false)]
|
|
329
|
+
[scriptblock] $CheckpointReader = { param($Path) Get-CheckpointFileContent -Path $Path },
|
|
330
|
+
|
|
331
|
+
[Parameter(Mandatory = $false)]
|
|
332
|
+
[scriptblock] $RoutingMatrixReader
|
|
226
333
|
)
|
|
227
334
|
|
|
228
335
|
if (-not $ToolInputRaw) {
|
|
229
|
-
return [ordered]@{
|
|
336
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
230
337
|
}
|
|
231
338
|
|
|
232
339
|
try {
|
|
@@ -238,19 +345,25 @@ function Invoke-CompletionConsistencyDecision {
|
|
|
238
345
|
|
|
239
346
|
$filePath = $toolInput.file_path
|
|
240
347
|
if (-not $filePath) {
|
|
241
|
-
return [ordered]@{
|
|
348
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
242
349
|
}
|
|
243
350
|
|
|
244
351
|
$normalized = $filePath -replace '\\', '/'
|
|
245
352
|
if (-not (Test-IsCheckpointPath -NormalizedPath $normalized)) {
|
|
246
|
-
return [ordered]@{
|
|
353
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
247
354
|
}
|
|
248
355
|
|
|
249
|
-
# Write tool: validate the content payload. Edit tool:
|
|
250
|
-
#
|
|
356
|
+
# Write tool: validate the content payload directly. Edit tool: no content is
|
|
357
|
+
# supplied, so read the on-disk checkpoint through the injectable seam and
|
|
358
|
+
# apply the old_string -> new_string patch in memory (read-then-validate).
|
|
251
359
|
$content = $toolInput.content
|
|
252
360
|
if (-not $content) {
|
|
253
|
-
|
|
361
|
+
$content = Resolve-EditedCheckpointContent -ToolInput $toolInput -CheckpointReader $CheckpointReader
|
|
362
|
+
if (-not $content) {
|
|
363
|
+
# No content, and the Edit could not be resolved against on-disk
|
|
364
|
+
# state (missing file or non-matching patch): defer and allow.
|
|
365
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
366
|
+
}
|
|
254
367
|
}
|
|
255
368
|
|
|
256
369
|
try {
|
|
@@ -259,26 +372,29 @@ function Invoke-CompletionConsistencyDecision {
|
|
|
259
372
|
catch {
|
|
260
373
|
# The content itself is not valid JSON. Let downstream tools surface the
|
|
261
374
|
# error rather than blocking with a misleading reason here.
|
|
262
|
-
return [ordered]@{
|
|
375
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
263
376
|
}
|
|
264
377
|
|
|
265
378
|
if (-not (Test-CompletionAsserted -Payload $payload)) {
|
|
266
|
-
return [ordered]@{
|
|
379
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
267
380
|
}
|
|
268
381
|
|
|
269
|
-
$
|
|
270
|
-
if ($
|
|
271
|
-
|
|
382
|
+
$missingArgs = @{ Payload = $payload; FolderExistsCheck = $FolderExistsCheck }
|
|
383
|
+
if ($PSBoundParameters.ContainsKey('RoutingMatrixReader') -and $null -ne $RoutingMatrixReader) {
|
|
384
|
+
$missingArgs['RoutingMatrixReader'] = $RoutingMatrixReader
|
|
272
385
|
}
|
|
273
|
-
|
|
274
|
-
$
|
|
275
|
-
|
|
276
|
-
$issueContext = ' Issue #232 requires pr_gate evidence and current-head ci_gate evidence.'
|
|
386
|
+
$missing = Get-MissingCompletionEvidence @missingArgs
|
|
387
|
+
if ($missing.Count -eq 0) {
|
|
388
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
277
389
|
}
|
|
278
390
|
|
|
391
|
+
$reason = "COMPLETION_CONSISTENCY_BLOCKED: the checkpoint asserts completion but is missing required completion evidence: $($missing -join ', '). A completion-asserting checkpoint must include a non-empty issue-num, a non-empty feature-folder, and a ci_gate object with conclusion == 'success' and a non-empty head_sha; routes whose requires_pr_gate is true must also include pr_gate evidence with a matching head_sha. Supply the missing evidence or remove the completion assertion."
|
|
279
392
|
return [ordered]@{
|
|
280
|
-
|
|
281
|
-
|
|
393
|
+
hookSpecificOutput = [ordered]@{
|
|
394
|
+
hookEventName = 'PreToolUse'
|
|
395
|
+
permissionDecision = 'deny'
|
|
396
|
+
permissionDecisionReason = $reason
|
|
397
|
+
}
|
|
282
398
|
}
|
|
283
399
|
}
|
|
284
400
|
|
|
@@ -295,6 +411,6 @@ catch {
|
|
|
295
411
|
exit 1
|
|
296
412
|
}
|
|
297
413
|
|
|
298
|
-
$decision | ConvertTo-Json -Compress | Write-Output
|
|
414
|
+
$decision | ConvertTo-Json -Compress -Depth 5 | Write-Output
|
|
299
415
|
|
|
300
416
|
exit 0
|