@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.
Files changed (69) hide show
  1. package/out/mcp-server.js +896 -202
  2. package/package.json +1 -1
  3. package/resources/claude-customizations/.claude/agents/atomic-executor.md +1 -0
  4. package/resources/claude-customizations/.claude/agents/atomic-planner.md +1 -0
  5. package/resources/claude-customizations/.claude/agents/commit-message.md +42 -0
  6. package/resources/claude-customizations/.claude/agents/csharp-typed-engineer.md +1 -0
  7. package/resources/claude-customizations/.claude/agents/epic-orchestrator.md +128 -0
  8. package/resources/claude-customizations/.claude/agents/epic-review.md +1 -0
  9. package/resources/claude-customizations/.claude/agents/feature-review.md +1 -0
  10. package/resources/claude-customizations/.claude/agents/human-exception-runbook.md +48 -0
  11. package/resources/claude-customizations/.claude/agents/orchestrator.md +80 -2
  12. package/resources/claude-customizations/.claude/agents/powershell-typed-engineer.md +1 -0
  13. package/resources/claude-customizations/.claude/agents/pr-author.md +37 -21
  14. package/resources/claude-customizations/.claude/agents/prd-feature.md +1 -0
  15. package/resources/claude-customizations/.claude/agents/python-typed-engineer.md +1 -0
  16. package/resources/claude-customizations/.claude/agents/staged-review.md +1 -0
  17. package/resources/claude-customizations/.claude/agents/status-updater.md +1 -0
  18. package/resources/claude-customizations/.claude/agents/typescript-engineer.md +1 -0
  19. package/resources/claude-customizations/.claude/hooks/check-powershell-test-purity.ps1 +103 -65
  20. package/resources/claude-customizations/.claude/hooks/check-python-test-purity.ps1 +12 -9
  21. package/resources/claude-customizations/.claude/hooks/enforce-checkpoint-monotonic.ps1 +24 -16
  22. package/resources/claude-customizations/.claude/hooks/enforce-completion-consistency.ps1 +19 -13
  23. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +304 -0
  24. package/resources/claude-customizations/.claude/hooks/enforce-epic-wave-barrier.ps1 +304 -0
  25. package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate.ps1 +237 -0
  26. package/resources/claude-customizations/.claude/hooks/enforce-evidence-locations.ps1 +16 -12
  27. package/resources/claude-customizations/.claude/hooks/enforce-feature-folder-order.ps1 +14 -10
  28. package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +182 -0
  29. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +35 -8
  30. package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +17 -14
  31. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.epic-base-branch.ps1 +104 -0
  32. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.ps1 +268 -93
  33. package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner.ps1 +19 -11
  34. package/resources/claude-customizations/.claude/hooks/enforce-promotion-mcp-only.ps1 +28 -6
  35. package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +17 -14
  36. package/resources/claude-customizations/.claude/hooks/validate-bash.ps1 +146 -36
  37. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +27 -7
  38. package/resources/claude-customizations/.claude/rules/orchestrator-state.md +53 -0
  39. package/resources/claude-customizations/.claude/settings.json +38 -1
  40. package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +252 -0
  41. package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +59 -13
  42. package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +28 -0
  43. package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +22 -18
  44. package/resources/claude-customizations/pack-manifests/core.json +9 -0
  45. package/resources/codex-and-agents-customizations/.agents/skills/feature-promotion-lifecycle/SKILL.md +8 -2
  46. package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +24 -3
  47. package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +13 -0
  48. package/resources/codex-and-agents-customizations/.agents/skills/remediation-handoff-atomic-planner/SKILL.md +1 -1
  49. package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp/SKILL.md +65 -0
  50. package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +79 -0
  51. package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/invoke-csharp-engineer/SKILL.md +66 -0
  52. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +15 -14
  53. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -25
  54. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-consistency.ps1 +144 -28
  55. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-helpers.ps1 +163 -0
  56. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-pr-author-skill.ps1 +257 -93
  57. package/resources/codex-and-agents-customizations/.codex-variants/csharp-legacy/agents/csharp-typed-engineer.toml +98 -0
  58. package/resources/codex-and-agents-customizations/pack-manifests/core.json +24 -0
  59. package/resources/codex-and-agents-customizations/pack-manifests/csharp-legacy.json +11 -0
  60. package/resources/codex-and-agents-customizations/pack-manifests/csharp-modern.json +10 -0
  61. package/resources/codex-and-agents-customizations/pack-manifests/powershell.json +15 -0
  62. package/resources/codex-and-agents-customizations/pack-manifests/python.json +15 -0
  63. package/resources/codex-and-agents-customizations/pack-manifests/typescript.json +9 -0
  64. package/resources/config/orchestration-routing.json +92 -0
  65. package/resources/customizations/.github/agents/pr-author.agent.md +24 -18
  66. package/resources/icon.png +0 -0
  67. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +11 -0
  68. package/resources/codex-and-agents-customizations/.github/workflows/_validate-orchestrator-state.yml +0 -68
  69. 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
- The repository CI gate `Orchestrator State Gate` runs the same validator when a
145
- checkpoint is present. Branch protection should require this check for branches
146
- that use orchestrated completion.
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:
@@ -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.<timestamp>.md` with:
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
- [mcp_servers.drm-copilot]
137
- enabled = true
138
-
139
- [skills.config]
140
- policy-compliance-order = true
141
- orchestrate = true
142
- orchestrator-workflow = true
143
- feature-promotion-lifecycle = true
144
- repo-automation-adapter = true
145
- atomic-plan-contract = true
146
- acceptance-criteria-tracking = true
147
- evidence-and-timestamp-conventions = true
148
- pr-context-artifacts = true
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"
@@ -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
- The block reason names the specific missing evidence so the caller can
27
- remediate. When completion is not asserted, the write is allowed
28
- (backward compatibility).
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
- $missing += 'issue-num'
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 += 'feature-folder'
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
- if ($issueNum -eq '232') {
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]@{ decision = 'allow' }
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]@{ decision = 'allow' }
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]@{ decision = 'allow' }
353
+ return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
247
354
  }
248
355
 
249
- # Write tool: validate the content payload. Edit tool: partial new_string is
250
- # not reliable without the full target file content, so allow.
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
- return [ordered]@{ decision = 'allow' }
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]@{ decision = 'allow' }
375
+ return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
263
376
  }
264
377
 
265
378
  if (-not (Test-CompletionAsserted -Payload $payload)) {
266
- return [ordered]@{ decision = 'allow' }
379
+ return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
267
380
  }
268
381
 
269
- $missing = Get-MissingCompletionEvidence -Payload $payload
270
- if ($missing.Count -eq 0) {
271
- return [ordered]@{ decision = 'allow' }
382
+ $missingArgs = @{ Payload = $payload; FolderExistsCheck = $FolderExistsCheck }
383
+ if ($PSBoundParameters.ContainsKey('RoutingMatrixReader') -and $null -ne $RoutingMatrixReader) {
384
+ $missingArgs['RoutingMatrixReader'] = $RoutingMatrixReader
272
385
  }
273
-
274
- $issueContext = ''
275
- if ((Get-CheckpointStringValue -Payload $payload -Name 'issue-num') -eq '232') {
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
- decision = 'block'
281
- reason = "COMPLETION_CONSISTENCY_BLOCKED: the checkpoint asserts completion but is missing required completion evidence: $($missing -join ', ').$issueContext 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. Supply the missing evidence or remove the completion assertion."
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