@danmoisan/drm-copilot-mcp 1.1.19 → 1.1.21
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 +172 -11
- package/package.json +1 -1
- package/resources/claude-customizations/.claude/agents/atomic-executor.md +17 -6
- package/resources/claude-customizations/.claude/agents/atomic-planner.md +10 -2
- package/resources/claude-customizations/.claude/agents/epic-orchestrator.md +5 -0
- package/resources/claude-customizations/.claude/agents/orchestrator.md +4 -1
- package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +4 -0
- package/resources/claude-customizations/.claude/agents/task-researcher.md +8 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-command.ps1 +190 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +22 -53
- package/resources/claude-customizations/.claude/hooks/hook-docs-only-diff.ps1 +5 -1
- package/resources/claude-customizations/.claude/hooks/premortem-section.ps1 +149 -0
- package/resources/claude-customizations/.claude/hooks/validate-executor-output.ps1 +210 -84
- package/resources/claude-customizations/.claude/hooks/validate-planner-output.ps1 +13 -1
- package/resources/claude-customizations/.claude/hooks/validate-task-researcher-output.ps1 +24 -5
- package/resources/claude-customizations/.claude/lib/ci-gate/Invoke-MergeConfirmationParser.ps1 +203 -0
- package/resources/claude-customizations/.claude/lib/codex-routing/CodexDeployment.psm1 +10 -10
- package/resources/claude-customizations/.claude/rules/plan-acceptance-gates.md +46 -10
- package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +48 -16
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +7 -3
- package/resources/claude-customizations/.claude/skills/csharp-change-budget-router/SKILL.md +2 -2
- package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +12 -3
- package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +4 -2
- package/resources/claude-customizations/.claude/skills/execution-environment/SKILL.md +134 -0
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +22 -9
- package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +29 -5
- package/resources/claude-customizations/.claude/skills/powershell-change-budget-router/SKILL.md +1 -1
- package/resources/claude-customizations/.claude/skills/python-change-budget-router/SKILL.md +1 -1
- package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +14 -6
- package/resources/claude-customizations/.claude/skills/research-issue/SKILL.md +6 -0
- package/resources/claude-customizations/config/orchestration-routing.json +7 -7
- package/resources/claude-customizations/pack-manifests/core.json +4 -0
- package/resources/codex-and-agents-customizations/.agents/skills/README.md +1 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-executor/SKILL.md +8 -7
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-plan-contract/SKILL.md +39 -4
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +8 -6
- package/resources/codex-and-agents-customizations/.agents/skills/codex-model-routing/SKILL.md +6 -6
- package/resources/codex-and-agents-customizations/.agents/skills/csharp-change-budget-router/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.agents/skills/epic-orchestrate/SKILL.md +15 -8
- package/resources/codex-and-agents-customizations/.agents/skills/epic-plan/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.agents/skills/execution-environment/SKILL.md +134 -0
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +16 -6
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/powershell-change-budget-router/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/python-change-budget-router/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/remediation-handoff-atomic-planner/SKILL.md +7 -3
- package/resources/codex-and-agents-customizations/.agents/skills/research-issue/SKILL.md +6 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c1.toml +11 -7
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c2.toml +11 -7
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3-elevated.toml +11 -7
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3.toml +11 -7
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c4.toml +11 -7
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor.toml +11 -7
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c1.toml +6 -3
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c2.toml +6 -3
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3-elevated.toml +6 -3
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3.toml +6 -3
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c4.toml +6 -3
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner.toml +6 -3
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planning.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/commit-steward-c1.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/commit-steward-c2.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/commit-steward-c3-elevated.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/commit-steward-c3.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/commit-steward-c4.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/commit-steward.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-atomic-planning.toml +1 -1
- 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/epic-orchestrator.toml +4 -2
- package/resources/codex-and-agents-customizations/.codex/agents/epic-planner.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c1.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c2.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3-elevated.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c4.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c1.toml +8 -5
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c2.toml +8 -5
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3-elevated.toml +8 -5
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3.toml +8 -5
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c4.toml +8 -5
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +8 -5
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-atomic-planning.toml +1 -1
- 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/pr-author-c1.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/pr-author-c2.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/pr-author-c3-elevated.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/pr-author-c3.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/pr-author-c4.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/pr-author.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/prd-feature-c1.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/prd-feature-c2.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/prd-feature-c3-elevated.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/prd-feature-c3.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/prd-feature-c4.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/prd-feature.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-atomic-planning.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/task-researcher-c1.toml +7 -1
- package/resources/codex-and-agents-customizations/.codex/agents/task-researcher-c2.toml +7 -1
- package/resources/codex-and-agents-customizations/.codex/agents/task-researcher-c3-elevated.toml +7 -1
- package/resources/codex-and-agents-customizations/.codex/agents/task-researcher-c3.toml +7 -1
- package/resources/codex-and-agents-customizations/.codex/agents/task-researcher-c4.toml +7 -1
- package/resources/codex-and-agents-customizations/.codex/agents/task-researcher.toml +7 -1
- package/resources/codex-and-agents-customizations/.codex/agents/typescript-engineer-c1.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/typescript-engineer-c2.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/typescript-engineer-c3-elevated.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/typescript-engineer-c3.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/typescript-engineer-c4.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/typescript-engineer.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate-command.ps1 +190 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate.ps1 +17 -38
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-docs-only-diff.ps1 +5 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/record-subagent-routing-attestation.ps1 +82 -70
- package/resources/codex-and-agents-customizations/.codex/prompts/feature-review-remediate.md +6 -4
- package/resources/codex-and-agents-customizations/.codex-variants/csharp-legacy/agents/csharp-typed-engineer.toml +1 -1
- package/resources/codex-and-agents-customizations/pack-manifests/core.json +2 -0
- package/resources/config/orchestration-routing.json +7 -7
- package/resources/customizations/.github/agents/atomic_executor.agent.md +21 -11
- package/resources/customizations/.github/agents/atomic_planning.agent.md +8 -3
- package/resources/customizations/.github/agents/csharp-atomic-executor.agent.md +13 -9
- package/resources/customizations/.github/agents/csharp-atomic-planning.agent.md +2 -2
- package/resources/customizations/.github/agents/csharp-orchestrator.agent.md +2 -2
- package/resources/customizations/.github/agents/csharp-typed-engineer.agent.md +3 -3
- package/resources/customizations/.github/agents/orchestrator.agent.md +8 -5
- package/resources/customizations/.github/agents/powershell-atomic-executor.agent.md +13 -9
- package/resources/customizations/.github/agents/powershell-atomic-planning.agent.md +2 -2
- package/resources/customizations/.github/agents/powershell-orchestrator.agent.md +2 -2
- package/resources/customizations/.github/agents/powershell-typed-engineer.agent.md +3 -3
- package/resources/customizations/.github/agents/python-atomic-executor.agent.md +13 -9
- package/resources/customizations/.github/agents/python-atomic-planning.agent.md +2 -2
- package/resources/customizations/.github/agents/python-orchestrator.agent.md +2 -2
- package/resources/customizations/.github/agents/task-researcher.agent.md +6 -0
- package/resources/customizations/.github/prompts/generate-atomic-plan.prompt.md +16 -10
- package/resources/customizations/.github/prompts/orchestrate-csharp-work.prompt.md +2 -2
- package/resources/customizations/.github/prompts/orchestrate-powershell-work.prompt.md +1 -1
- package/resources/customizations/.github/prompts/orchestrate-python-work.prompt.md +1 -1
- package/resources/customizations/.github/prompts/orchestrate-work.prompt.md +2 -2
- package/resources/customizations/.github/skills/atomic-plan-contract/SKILL.md +39 -4
- package/resources/customizations/.github/skills/csharp-change-budget-router/SKILL.md +1 -1
- package/resources/customizations/.github/skills/execution-environment/SKILL.md +134 -0
- package/resources/customizations/.github/skills/powershell-change-budget-router/SKILL.md +1 -1
- package/resources/customizations/.github/skills/remediation-handoff-atomic-planner/SKILL.md +7 -3
- package/resources/feature-templates/bug/plan.yyyy-MM-ddTHH-mm.md +10 -0
- package/resources/feature-templates/feature/plan.yyyy-MM-ddTHH-mm.md +11 -0
- package/resources/feature-templates/refactor/plan.yyyy-MM-ddTHH-mm.md +11 -0
- package/resources/lib/codex-routing/CodexDeployment.psm1 +10 -10
- package/resources/powershell/PoshQC/PoshQC.CoverageMerge.psm1 +163 -0
- package/resources/powershell/PoshQC/PoshQC.Shard.psm1 +296 -0
- package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +23 -4
- package/resources/powershell/PoshQC/PoshQC.psd1 +7 -1
- package/resources/powershell/PoshQC/PoshQC.psm1 +17 -5
- package/resources/powershell/PoshQC/README.md +13 -1
- package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +3 -0
package/resources/claude-customizations/.claude/lib/ci-gate/Invoke-MergeConfirmationParser.ps1
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Maps one pull-request snapshot to a merge-confirmation status (issue #952).
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Consumes the JSON emitted by
|
|
7
|
+
`gh pr view <n> --json state,mergeCommit,mergedAt,autoMergeRequest`, or a GraphQL
|
|
8
|
+
`pullRequest` node that may also carry `isInMergeQueue`, and reports whether the pull
|
|
9
|
+
request has merged. Merge procedures call this parser while they poll after a merge or
|
|
10
|
+
merge-queue enqueue, and record a merge only after it reports `merged`.
|
|
11
|
+
|
|
12
|
+
Mapping (state values are case-sensitive):
|
|
13
|
+
- MERGED with a non-empty mergeCommit.oid -> merged
|
|
14
|
+
- MERGED with a null mergeCommit or an empty oid -> error
|
|
15
|
+
- CLOSED -> closed
|
|
16
|
+
- OPEN with isInMergeQueue true, or with a present
|
|
17
|
+
non-null autoMergeRequest -> pending
|
|
18
|
+
- OPEN otherwise -> not_queued
|
|
19
|
+
- a null snapshot, a missing state, or any other
|
|
20
|
+
state value -> error
|
|
21
|
+
|
|
22
|
+
Every error message starts with 'Invoke-MergeConfirmationParser: '.
|
|
23
|
+
|
|
24
|
+
This script does NOT invoke `gh`. The caller runs `gh` and passes the resulting JSON
|
|
25
|
+
through -PrJson or the pipeline, so the mapping is deterministically testable.
|
|
26
|
+
|
|
27
|
+
.PARAMETER PrJson
|
|
28
|
+
The pull-request snapshot JSON. Accepts pipeline input. Defaults to '' so the file can be
|
|
29
|
+
dot-sourced with no arguments.
|
|
30
|
+
|
|
31
|
+
.PARAMETER AsJson
|
|
32
|
+
When set, emits the result as compressed JSON instead of a PowerShell object.
|
|
33
|
+
|
|
34
|
+
.EXAMPLE
|
|
35
|
+
pwsh -NoProfile -File .claude/lib/ci-gate/Invoke-MergeConfirmationParser.ps1 -PrJson $snapshot -AsJson
|
|
36
|
+
|
|
37
|
+
.OUTPUTS
|
|
38
|
+
A PSCustomObject (or a JSON string when -AsJson is set) with the properties Status
|
|
39
|
+
(merged, pending, not_queued, or closed), MergeCommitSha, and MergedAt. MergeCommitSha and
|
|
40
|
+
MergedAt are empty unless Status is merged.
|
|
41
|
+
#>
|
|
42
|
+
|
|
43
|
+
[CmdletBinding()]
|
|
44
|
+
param(
|
|
45
|
+
[Parameter(ValueFromPipeline = $true)]
|
|
46
|
+
[AllowEmptyString()]
|
|
47
|
+
[string]$PrJson = '',
|
|
48
|
+
|
|
49
|
+
[Parameter(Mandatory = $false)]
|
|
50
|
+
[switch]$AsJson
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# Function definitions live in begin so the script is a single explicit begin/process unit;
|
|
54
|
+
# the pipeline-bound -PrJson parameter forces a named process block.
|
|
55
|
+
begin {
|
|
56
|
+
function Get-MergeConfirmationPropertyValue {
|
|
57
|
+
<#
|
|
58
|
+
.SYNOPSIS
|
|
59
|
+
Return a named property value of a parsed object, or $null when it is absent.
|
|
60
|
+
.DESCRIPTION
|
|
61
|
+
Reads through PSObject.Properties so an absent property is not an error under
|
|
62
|
+
Set-StrictMode -Version Latest.
|
|
63
|
+
#>
|
|
64
|
+
[CmdletBinding()]
|
|
65
|
+
param(
|
|
66
|
+
[AllowNull()]
|
|
67
|
+
$InputObject,
|
|
68
|
+
|
|
69
|
+
[Parameter(Mandatory = $true)]
|
|
70
|
+
[string]$Name
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
if ($null -eq $InputObject) {
|
|
74
|
+
return $null
|
|
75
|
+
}
|
|
76
|
+
$property = $InputObject.PSObject.Properties[$Name]
|
|
77
|
+
if ($null -eq $property) {
|
|
78
|
+
return $null
|
|
79
|
+
}
|
|
80
|
+
return $property.Value
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function ConvertTo-MergeConfirmationTimeText {
|
|
84
|
+
<#
|
|
85
|
+
.SYNOPSIS
|
|
86
|
+
Render a mergedAt value as text: strings verbatim, dates as UTC ISO-8601.
|
|
87
|
+
#>
|
|
88
|
+
[CmdletBinding()]
|
|
89
|
+
[OutputType([string])]
|
|
90
|
+
param(
|
|
91
|
+
[AllowNull()]
|
|
92
|
+
$Value
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
$format = 'yyyy-MM-ddTHH:mm:ssZ'
|
|
96
|
+
$culture = [System.Globalization.CultureInfo]::InvariantCulture
|
|
97
|
+
if ($null -eq $Value) {
|
|
98
|
+
return ''
|
|
99
|
+
}
|
|
100
|
+
if ($Value -is [datetimeoffset]) {
|
|
101
|
+
return $Value.UtcDateTime.ToString($format, $culture)
|
|
102
|
+
}
|
|
103
|
+
if ($Value -is [datetime]) {
|
|
104
|
+
# A Kind of Unspecified carries no offset; JSON timestamps from gh are UTC.
|
|
105
|
+
$utc = if ($Value.Kind -eq [System.DateTimeKind]::Unspecified) { [datetime]::SpecifyKind($Value, [System.DateTimeKind]::Utc) } else { $Value.ToUniversalTime() }
|
|
106
|
+
return $utc.ToString($format, $culture)
|
|
107
|
+
}
|
|
108
|
+
return [string]$Value
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function Get-MergeConfirmationStatus {
|
|
112
|
+
<#
|
|
113
|
+
.SYNOPSIS
|
|
114
|
+
Map one parsed pull-request snapshot to the merge-confirmation result object.
|
|
115
|
+
.PARAMETER Snapshot
|
|
116
|
+
The parsed snapshot (gh pr view JSON or a GraphQL pullRequest node).
|
|
117
|
+
.OUTPUTS
|
|
118
|
+
PSCustomObject with Status, MergeCommitSha, and MergedAt.
|
|
119
|
+
#>
|
|
120
|
+
[CmdletBinding()]
|
|
121
|
+
[OutputType([pscustomobject])]
|
|
122
|
+
param(
|
|
123
|
+
[AllowNull()]
|
|
124
|
+
$Snapshot
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
if ($null -eq $Snapshot) {
|
|
128
|
+
throw 'Invoke-MergeConfirmationParser: the pull-request snapshot is null or empty.'
|
|
129
|
+
}
|
|
130
|
+
$state = Get-MergeConfirmationPropertyValue -InputObject $Snapshot -Name 'state'
|
|
131
|
+
if ($null -eq $state) {
|
|
132
|
+
throw 'Invoke-MergeConfirmationParser: the pull-request snapshot has no state field.'
|
|
133
|
+
}
|
|
134
|
+
$stateText = [string]$state
|
|
135
|
+
|
|
136
|
+
if ($stateText -ceq 'MERGED') {
|
|
137
|
+
$mergeCommit = Get-MergeConfirmationPropertyValue -InputObject $Snapshot -Name 'mergeCommit'
|
|
138
|
+
$oid = [string](Get-MergeConfirmationPropertyValue -InputObject $mergeCommit -Name 'oid')
|
|
139
|
+
if ([string]::IsNullOrWhiteSpace($oid)) {
|
|
140
|
+
throw 'Invoke-MergeConfirmationParser: state MERGED carries no merge commit oid.'
|
|
141
|
+
}
|
|
142
|
+
$mergedAt = ConvertTo-MergeConfirmationTimeText -Value (Get-MergeConfirmationPropertyValue -InputObject $Snapshot -Name 'mergedAt')
|
|
143
|
+
return [pscustomobject]@{ Status = 'merged'; MergeCommitSha = $oid; MergedAt = $mergedAt }
|
|
144
|
+
}
|
|
145
|
+
if ($stateText -ceq 'CLOSED') {
|
|
146
|
+
return [pscustomobject]@{ Status = 'closed'; MergeCommitSha = ''; MergedAt = '' }
|
|
147
|
+
}
|
|
148
|
+
if ($stateText -ceq 'OPEN') {
|
|
149
|
+
$inQueue = Get-MergeConfirmationPropertyValue -InputObject $Snapshot -Name 'isInMergeQueue'
|
|
150
|
+
$autoMerge = Get-MergeConfirmationPropertyValue -InputObject $Snapshot -Name 'autoMergeRequest'
|
|
151
|
+
$queued = ($inQueue -is [bool] -and $inQueue) -or ($null -ne $autoMerge)
|
|
152
|
+
$status = if ($queued) { 'pending' } else { 'not_queued' }
|
|
153
|
+
return [pscustomobject]@{ Status = $status; MergeCommitSha = ''; MergedAt = '' }
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
throw ("Invoke-MergeConfirmationParser: unrecognized pull-request state '{0}'." -f $stateText)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function Invoke-MergeConfirmationParser {
|
|
160
|
+
<#
|
|
161
|
+
.SYNOPSIS
|
|
162
|
+
Parse a pull-request snapshot JSON string and map it to a merge-confirmation status.
|
|
163
|
+
.PARAMETER PrJson
|
|
164
|
+
The snapshot JSON text.
|
|
165
|
+
.PARAMETER AsJson
|
|
166
|
+
Emit compressed JSON instead of the result object.
|
|
167
|
+
.OUTPUTS
|
|
168
|
+
PSCustomObject, or System.String when -AsJson is set.
|
|
169
|
+
#>
|
|
170
|
+
[CmdletBinding()]
|
|
171
|
+
param(
|
|
172
|
+
[AllowEmptyString()]
|
|
173
|
+
[AllowNull()]
|
|
174
|
+
[string]$PrJson,
|
|
175
|
+
|
|
176
|
+
[switch]$AsJson
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
$snapshot = $null
|
|
180
|
+
if (-not [string]::IsNullOrWhiteSpace($PrJson)) {
|
|
181
|
+
try {
|
|
182
|
+
$snapshot = $PrJson | ConvertFrom-Json -ErrorAction Stop
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
throw ('Invoke-MergeConfirmationParser: the pull-request snapshot is not valid JSON: ' + $_.Exception.Message)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
$result = Get-MergeConfirmationStatus -Snapshot $snapshot
|
|
190
|
+
if ($AsJson) {
|
|
191
|
+
return ($result | ConvertTo-Json -Depth 3 -Compress)
|
|
192
|
+
}
|
|
193
|
+
return $result
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
# Entry point. The parser runs only when the file is executed directly; when dot-sourced,
|
|
198
|
+
# $MyInvocation.InvocationName is '.', so the guard leaves only the function definitions.
|
|
199
|
+
process {
|
|
200
|
+
if ($MyInvocation.InvocationName -ne '.') {
|
|
201
|
+
Invoke-MergeConfirmationParser -PrJson $PrJson -AsJson:$AsJson
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
`scripts/dev_tools/resolve_codex_deployment.py`. It resolves the exact Codex
|
|
8
8
|
deployment agent, model, and reasoning effort for one delegation from the
|
|
9
9
|
logical agent, the assessed complexity band, the execution context, and the
|
|
10
|
-
orchestration complexity ceiling. C3 defaults to
|
|
11
|
-
|
|
12
|
-
planner and epic orchestrator personas are always forced to
|
|
10
|
+
orchestration complexity ceiling. C3 defaults to Sol/high and elevates to
|
|
11
|
+
Astra/high only for an epic child or a C4 orchestration ceiling; the epic
|
|
12
|
+
planner and epic orchestrator personas are always forced to Astra/ultra. No
|
|
13
13
|
model alias and no silent fallback is accepted.
|
|
14
14
|
|
|
15
15
|
SINGLE-IMPLEMENTATION RULE. The orchestrator-state U6.X checks
|
|
@@ -81,20 +81,20 @@ $script:LOGICAL_AGENT_ALIASES = @{ 'feature-review' = 'feature-reviewer' }
|
|
|
81
81
|
|
|
82
82
|
# The per-band deployment profiles (suffix, model, reasoning effort).
|
|
83
83
|
$script:BASE_PROFILES = @{
|
|
84
|
-
C1 = @{ suffix = 'c1'; model = 'gpt-
|
|
85
|
-
C2 = @{ suffix = 'c2'; model = 'gpt-
|
|
86
|
-
C3 = @{ suffix = 'c3'; model = 'gpt-
|
|
87
|
-
C4 = @{ suffix = 'c4'; model = 'gpt-
|
|
84
|
+
C1 = @{ suffix = 'c1'; model = 'gpt-6-luna'; model_reasoning_effort = 'low' }
|
|
85
|
+
C2 = @{ suffix = 'c2'; model = 'gpt-6.1-sol'; model_reasoning_effort = 'medium' }
|
|
86
|
+
C3 = @{ suffix = 'c3'; model = 'gpt-6.1-sol'; model_reasoning_effort = 'high' }
|
|
87
|
+
C4 = @{ suffix = 'c4'; model = 'gpt-6-astra'; model_reasoning_effort = 'max' }
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
# The profile a C3 delegation elevates to when the overlay applies.
|
|
91
|
-
$script:C3_ELEVATED_PROFILE = @{ suffix = 'c3-elevated'; model = 'gpt-
|
|
91
|
+
$script:C3_ELEVATED_PROFILE = @{ suffix = 'c3-elevated'; model = 'gpt-6-astra'; model_reasoning_effort = 'high' }
|
|
92
92
|
|
|
93
93
|
# The personas whose profile is forced regardless of band, context, or ceiling.
|
|
94
94
|
# Their deployment agent is the logical agent itself (empty suffix).
|
|
95
95
|
$script:FORCED_PERSONA_PROFILES = @{
|
|
96
|
-
'epic-planner' = @{ suffix = ''; model = 'gpt-
|
|
97
|
-
'epic-orchestrator' = @{ suffix = ''; model = 'gpt-
|
|
96
|
+
'epic-planner' = @{ suffix = ''; model = 'gpt-6-astra'; model_reasoning_effort = 'ultra' }
|
|
97
|
+
'epic-orchestrator' = @{ suffix = ''; model = 'gpt-6-astra'; model_reasoning_effort = 'ultra' }
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
|
|
@@ -7,14 +7,14 @@ paths:
|
|
|
7
7
|
- "docs/features/**/plan.*.md"
|
|
8
8
|
- "docs/features/**/remediation-plan.*.md"
|
|
9
9
|
- ".claude/skills/atomic-plan-contract/SKILL.md"
|
|
10
|
-
description: Acceptance-gate rules G1 through
|
|
10
|
+
description: Acceptance-gate rules G1 through G13 for atomic plans. G1 through G9 judge the shell commands a plan states as acceptance conditions; the document-level rules G10 through G13 report a SCRATCH definition that is not namespaced by issue number, a line-number citation, a commit-SHA citation, and a plan above the size guideline without a size justification.
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
# Atomic-Plan Acceptance Gates (G1 through
|
|
13
|
+
# Atomic-Plan Acceptance Gates (G1 through G13)
|
|
14
14
|
|
|
15
|
-
This rule governs the acceptance-gate rules the plan validator applies to an atomic plan: G1 through G9 judge the shell commands the plan states as acceptance conditions, and G10
|
|
15
|
+
This rule governs the acceptance-gate rules the plan validator applies to an atomic plan: G1 through G9 judge the shell commands the plan states as acceptance conditions, and G10 through G13 judge the whole plan document. It exists because a plan can state an acceptance condition that cannot fail: a coverage argument that collects no data, or a search for a literal that returns zero matches whatever the executor does. Such a condition reads as a verification step and gates nothing (issue #486).
|
|
16
16
|
|
|
17
|
-
The rules are enforced by `scripts/dev_tools/plan_gate_discrimination.py` and by the TypeScript parity port at `extensions/drm-copilot/src/lib/validate/plan-gate-discrimination.ts` with its shared-predicate module `plan-gate-rules.ts`. G1 through G9 are fed by the command extractor (`scripts/dev_tools/plan_gate_commands.py` and `extensions/drm-copilot/src/lib/validate/plan-gate-commands.ts`); G10 reads the whole document through `scripts/dev_tools/plan_gate_scratch.py` and `extensions/drm-copilot/src/lib/validate/plan-gate-scratch.ts`. Enforcement is validator logic plus this prose file. No JSON Schema is authored, imported, or read.
|
|
17
|
+
The rules are enforced by `scripts/dev_tools/plan_gate_discrimination.py` and by the TypeScript parity port at `extensions/drm-copilot/src/lib/validate/plan-gate-discrimination.ts` with its shared-predicate module `plan-gate-rules.ts`. G1 through G9 are fed by the command extractor (`scripts/dev_tools/plan_gate_commands.py` and `extensions/drm-copilot/src/lib/validate/plan-gate-commands.ts`); G10 reads the whole document through `scripts/dev_tools/plan_gate_scratch.py` and `extensions/drm-copilot/src/lib/validate/plan-gate-scratch.ts`, and G11 through G13 read it through `scripts/dev_tools/plan_gate_document.py` and `extensions/drm-copilot/src/lib/validate/plan-gate-document.ts`. Enforcement is validator logic plus this prose file. No JSON Schema is authored, imported, or read.
|
|
18
18
|
|
|
19
19
|
## Scope of Invocation — no grandfathering or exemption mechanism
|
|
20
20
|
|
|
@@ -26,7 +26,7 @@ The consequence is that adding a rule to this set is cheap in migration cost and
|
|
|
26
26
|
|
|
27
27
|
## Rule Table
|
|
28
28
|
|
|
29
|
-
Every finding string begins with the square-bracketed `P#-T#` identifier of the task the command is attributed to, and renders the offending value or literal between backticks. The G10 exception: a G10 finding begins with `Line N: ` instead, because a SCRATCH definition sits outside any task window; the prefix matches the structural-error prefix in the same error channel, and the offending logical line is still rendered between backticks.
|
|
29
|
+
Every finding string begins with the square-bracketed `P#-T#` identifier of the task the command is attributed to, and renders the offending value or literal between backticks. The G10 exception: a G10 finding begins with `Line N: ` instead, because a SCRATCH definition sits outside any task window; the prefix matches the structural-error prefix in the same error channel, and the offending logical line is still rendered between backticks. G11, G12, and G13 findings use the same `Line N: ` prefix for the same reason; G13 always reports `Line 1: ` because it judges the document as a whole.
|
|
30
30
|
|
|
31
31
|
| Rule | Condition | Shipped severity |
|
|
32
32
|
| --- | --- | --- |
|
|
@@ -41,14 +41,17 @@ Every finding string begins with the square-bracketed `P#-T#` identifier of the
|
|
|
41
41
|
| **G8b** | A `git diff` invocation carrying a non-flag ref operand together with `--name-only` or `--name-status`, whose attributed task text carries neither a `git add` span nor a `git status --porcelain` span. A name-listing diff enumerates tracked changes only, so a path the plan creates is invisible to it. | **Warning** |
|
|
42
42
|
| **G9** | A command carrying a `--cov` token, carrying no token beginning `--cov-report=term` and no token beginning `--cov-fail-under`, whose project `addopts` value also carries no `--cov-report=term`. No coverage table is printed, so a coverage number the acceptance condition demands can never be read. | **Warning** |
|
|
43
43
|
| **G10** | An unfenced logical line of the plan document (a physical line plus its indented continuation lines) that matches the SCRATCH definition predicate, and whose text after the first definition match carries neither an `issue-<issue-num>` nor an `issue-<digits>` namespace. One finding per logical line, reported against its first physical line. | **Blocking** |
|
|
44
|
+
| **G11** | A line-number citation in unfenced text, in any of three forms: the prose form `\b[Ll]ines?[ \t]+[0-9]+` evaluated with inline code spans masked; the path form `[A-Za-z0-9_./-]+\.[A-Za-z][A-Za-z0-9]{0,5}:[0-9]+` evaluated including inline code, skipped when the enclosing whitespace-delimited token contains `://`; and the anchor form `#L[0-9]+`. A line position moves whenever `main` moves. One finding per match. | **Blocking** |
|
|
45
|
+
| **G12** | A commit-SHA citation in unfenced text, including inline code: a bounded run `\b[0-9a-f]{7,40}\b` that holds at least one digit and at least one letter, is not preceded by `-`, `_`, or `.`, and is not followed by `-` or `_`. The adjacency conditions are checked in code, not by lookbehind. One finding per match. | **Blocking** |
|
|
46
|
+
| **G13** | A plan whose unfenced canonical task lines exceed `PLAN_TASK_GUIDELINE` (40) or whose physical lines exceed `PLAN_LINE_GUIDELINE` (400), with no `## Size Justification` heading followed by at least one non-blank, non-heading line before the next heading of level one or two. One finding per document. | **Blocking** |
|
|
44
47
|
|
|
45
|
-
G1 through
|
|
48
|
+
G1 through G13 are the complete shipped set. G1 through G6 were added by issue #486, G7 through G9 by issue #519, G10 by issue #932, and G11 through G13 by issue #964.
|
|
46
49
|
|
|
47
50
|
G1 through G4 form a cascade over each `--cov` value: the value is decided once, so a value G1 rejects is never additionally reported by G2 or G3. G4 is evaluated independently of the cascade because the ambiguous form is a defect whatever the value resolves to. G6 is evaluated before G5, because cross-line presence falsifies G5's tree-absence claim.
|
|
48
51
|
|
|
49
52
|
G8b is a distinct rule from G8 and not a sub-case of it: G8 reports a diff with no ref operand, G8b reports one that has a ref operand but cannot observe an untracked path. A single invocation can satisfy only one of the two, because the presence of a ref operand decides between them.
|
|
50
53
|
|
|
51
|
-
G1 and G4 are context-free and run on every invocation. G2, G3, G5, and G6 require a repository seam; with no context supplied they do not run. G7, G8, and G8b are likewise context-free and run on every invocation. G9 requires the repository seam, because it reads the project `addopts` value through it, so with no context supplied G9 does not run. All four of the rules added by issue #519 ship in the Warning channel, so none of them can alter the Blocking list at all. G10 is context-free and document-level: it reads the whole plan text, including the preamble and terms lists the command extractor drops, runs on every invocation, and can add Blocking findings without a context.
|
|
54
|
+
G1 and G4 are context-free and run on every invocation. G2, G3, G5, and G6 require a repository seam; with no context supplied they do not run. G7, G8, and G8b are likewise context-free and run on every invocation. G9 requires the repository seam, because it reads the project `addopts` value through it, so with no context supplied G9 does not run. All four of the rules added by issue #519 ship in the Warning channel, so none of them can alter the Blocking list at all. G10 is context-free and document-level: it reads the whole plan text, including the preamble and terms lists the command extractor drops, runs on every invocation, and can add Blocking findings without a context. G11, G12, and G13 are context-free and document-level in the same way, skip fenced code blocks with the command extractor's fence pattern, split physical lines on CR LF, LF, and CR only, use no lookbehind, and run after G10 on every invocation.
|
|
52
55
|
|
|
53
56
|
### Attribution window
|
|
54
57
|
|
|
@@ -154,7 +157,7 @@ A continuation line is non-blank, begins with whitespace, and is not a fence lin
|
|
|
154
157
|
|
|
155
158
|
The severity was fixed by the same two-conjunct decision rule used for G5 through G9, written and committed before the measurement was taken: Blocking if and only if the total G10 finding count is greater than zero **and** the recorded false-positive count is zero; otherwise the measurement indicates Warning. The pre-declared false-positive definition is a flagged logical line that is not a SCRATCH definition, or that defines SCRATCH in the canonical issue-namespaced form.
|
|
156
159
|
|
|
157
|
-
The measurement is recorded in `docs/features/
|
|
160
|
+
The measurement is recorded in `docs/features/archive/2026-10-15-plan-validator-accepts-bare-scratch-paths-932/evidence/qa-gates/g10-corpus-measurement.2026-10-16T01-21.md`. It scanned 493 plan and remediation-plan files under `docs/` at the merge base and produced 17 findings, all 17 true positives and 0 false positives, so both conjuncts hold and the rule yields Blocking.
|
|
158
161
|
|
|
159
162
|
G10 also ships Blocking by operator-approved scope for issue #932. The measurement alone is a weaker basis than the G7 through G9 precedent, because the research for issue #932 observed the committed plan corpus, including the definition forms the predicate targets, before the measurement was taken. The severity is a single constant in each runtime (`G10_SEVERITY`), and a parity test asserts the two constants agree.
|
|
160
163
|
|
|
@@ -174,6 +177,36 @@ One false-positive class is possible and recorded: the colon connector matches p
|
|
|
174
177
|
Each artifact names the token SCRATCH: it never records a host path.
|
|
175
178
|
```
|
|
176
179
|
|
|
180
|
+
### G11 — ships as Blocking by operator-approved scope
|
|
181
|
+
|
|
182
|
+
G11 enforces the design-level plan contract introduced by issue #964: a plan anchors on symbols, headings, and test names, never on line positions, because a line position moves whenever `main` moves and every such citation becomes a preflight defect. The severity was set by operator-approved scope for issue #964, following the G10 precedent, and not by a pre-declared measurement. The severity is a single constant in each runtime (`G11_SEVERITY`), and a parity test asserts the two constants agree.
|
|
183
|
+
|
|
184
|
+
The finding message is ``Line N: line-number citation `<match>` anchors on a position that moves when main moves; cite the symbol, heading, or test name instead.`` A G11 finding is a trivial preflight defect: the preflight executor replaces the citation in place and records the fix, so the Blocking channel does not cost a return to the planner.
|
|
185
|
+
|
|
186
|
+
### G12 — ships as Blocking by operator-approved scope
|
|
187
|
+
|
|
188
|
+
G12 enforces the same contract for commit identifiers: a commit SHA names a state that goes stale when `main` moves. The severity was set by operator-approved scope for issue #964. The digit-and-letter condition excludes decimal run and ruleset identifiers and all-letter words; the adjacency conditions exclude UUID segments and agent or worktree suffixes joined by `-` or `_`; and the bounded run excludes SHA-256 digests, because a 64-character run has no word boundary at 40 characters, so a digest literal can remain where it is the actual assertion. The severity is a single constant in each runtime (`G12_SEVERITY`), and a parity test asserts the two constants agree.
|
|
189
|
+
|
|
190
|
+
The finding message is ``Line N: commit-SHA citation `<match>` names a commit that goes stale when main moves; cite the branch, ref name, or merge base derivation instead.``
|
|
191
|
+
|
|
192
|
+
### G13 — ships as Blocking because its exoneration is author-controlled
|
|
193
|
+
|
|
194
|
+
G13 reports a plan above 40 canonical task lines or 400 physical lines that carries no `## Size Justification` section with content. The guideline numbers were derived from the issue #962 item, whose specification maps to an estimated 35 to 45 design-level tasks in 300 to 400 lines. G13 ships Blocking because the author controls its exoneration: a plan that needs more states why in one paragraph, which costs less than a preflight round. A justification section that holds only blank lines or headings does not exonerate. The severity is a single constant in each runtime (`G13_SEVERITY`), and a parity test asserts the two constants agree.
|
|
195
|
+
|
|
196
|
+
The finding message is ``Line 1: plan size `<T> tasks, <L> lines` exceeds the guideline of 40 tasks or 400 lines and carries no `## Size Justification` section; split the item or state why the size is necessary.``
|
|
197
|
+
|
|
198
|
+
### Known false-positive classes — G11 and G12
|
|
199
|
+
|
|
200
|
+
G11 and G12 do not suppress the following; each is a documented false-positive class rather than a deferred fix:
|
|
201
|
+
|
|
202
|
+
- **G11, prose that refers to a line of command output.** A sentence such as "line 1 of the output" is reported, because the prose form cannot tell a file position from an output position.
|
|
203
|
+
- **G11, a quoted validator message outside backticks.** A validator prefix such as `Line 5:` written as plain prose matches the prose form; the same text inside an inline code span is masked and not reported.
|
|
204
|
+
- **G11, an inline code span opened with two or more backticks.** The mask pairs single backticks, so a span such as a doubled-backtick quotation of a finding message that itself contains backticks is masked only in part, and a line reference inside it can match the prose form.
|
|
205
|
+
- **G11, a host and port written without a URL scheme.** A token such as `api.github.com:443` matches the path form, because only a token containing `://` is skipped and the path form is matched inside inline code spans as well as in prose; the same host and port written as a URL with a scheme, such as `https://api.github.com:443`, is not reported.
|
|
206
|
+
- **G12, a hexadecimal identifier that is not a commit.** A run of seven or more hexadecimal characters with a digit and a letter that is not joined by `-` or `_` is reported. The measured instances are synthetic fixture identifiers written into test-scenario task text and git object identifiers that are not commits, such as blob hashes recorded as parity evidence; a bare hexadecimal color is the same class.
|
|
207
|
+
|
|
208
|
+
The corpus measurement informed the false-positive class list and did not decide the channel. It is recorded in `docs/features/archive/2026-10-16-planning-process-churn-964/evidence/other/g11-g13-corpus-measurement.2026-10-16T23-46.md`. It scanned 615 committed plan and remediation-plan files under `docs/` and counted 13190 G11 findings in 350 files, 1681 G12 findings in 218 files, and 280 G13 findings. Those counts describe plans written before the rules existed; the validator runs only against the plan it is pointed at, so they do not enter any gate.
|
|
209
|
+
|
|
177
210
|
## The Write-Mode Register
|
|
178
211
|
|
|
179
212
|
G7 reads a fixed register of six entries. Each entry is an argv predicate plus a set of observation markers matched case-sensitively as substrings of the owning task's attributed text. The register is data, not code, so the same six entries are transcribed into the TypeScript twin without porting behaviour.
|
|
@@ -284,13 +317,16 @@ The prohibition is enforced by tests, not only by prose: a parity test asserts t
|
|
|
284
317
|
- Express coverage targets as importable dotted names (`--cov=scripts.dev_tools.module`), never as filesystem paths, and always with the `=` form.
|
|
285
318
|
- Where an acceptance condition is a search, assert a short, single-line, non-interpolated token that the plan quotes verbatim.
|
|
286
319
|
- Prefer a named test over a phrase search whenever a test can carry the assertion.
|
|
320
|
+
- Cite a symbol, a heading, or a test name. Never cite a line number, a `path:line` locator, a `#L` anchor, or a commit SHA; name the branch, the ref, or the merge-base derivation instead (G11, G12).
|
|
321
|
+
- Keep a plan within 40 tasks and 400 lines; a plan that needs more carries a non-empty `## Size Justification` section (G13).
|
|
287
322
|
|
|
288
323
|
`.claude/skills/atomic-plan-contract/SKILL.md` carries the authoring-side statement of this guidance and cross-references this file.
|
|
289
324
|
|
|
290
325
|
## Enforcement
|
|
291
326
|
|
|
292
|
-
- `scripts/dev_tools/plan_gate_commands.py` extracts task-attributed command candidates; `scripts/dev_tools/plan_gate_discrimination.py` evaluates G1 through G9, calls `scripts/dev_tools/plan_gate_scratch.py` for G10, and returns the two severity channels.
|
|
327
|
+
- `scripts/dev_tools/plan_gate_commands.py` extracts task-attributed command candidates; `scripts/dev_tools/plan_gate_discrimination.py` evaluates G1 through G9, calls `scripts/dev_tools/plan_gate_scratch.py` for G10 and `scripts/dev_tools/plan_gate_document.py` for G11 through G13, and returns the two severity channels.
|
|
293
328
|
- `scripts/dev_tools/validate_orchestration_artifacts.py` routes the existing `plan` artifact type through the two-channel entry point, prints each Warning to stderr prefixed with `PLAN GATE WARNING: `, and derives its exit code from the error channel alone. No new flag, option, or artifact type is added.
|
|
294
329
|
- The TypeScript parity port is dispatched from `extensions/drm-copilot/src/lib/validate/orchestration-artifacts.ts` for the existing `plan` artifact type. The MCP `validate_orchestration_artifacts` input-schema property-key set is unchanged; Warnings surface on an optional `warnings` field that is absent when there are none.
|
|
295
330
|
- `scripts/dev_tools/plan_gate_scratch.py` evaluates G10, the document-level SCRATCH definition rule, and `evaluate_plan_gates` in `scripts/dev_tools/plan_gate_discrimination.py` calls it on every invocation, with or without a context. The TypeScript twin `extensions/drm-copilot/src/lib/validate/plan-gate-scratch.ts` is called the same way from `evaluatePlanGates`. Through the Python CLI a G10 finding is printed as an error and the process exits 1; through the MCP service call it causes the call to throw with the message included.
|
|
296
|
-
-
|
|
331
|
+
- `scripts/dev_tools/plan_gate_document.py` evaluates G11, G12, and G13, and `evaluate_plan_gates` calls it on every invocation immediately after G10, with or without a context. The TypeScript twin `extensions/drm-copilot/src/lib/validate/plan-gate-document.ts` is called the same way from `evaluatePlanGates`. The MCP validator applies these rules only after the extension release that carries them is installed; until then, branch-current validation runs through `poetry run python -m scripts.dev_tools.validate_orchestration_artifacts plan <path>`.
|
|
332
|
+
- `.claude/hooks/validate-planner-output.ps1` carries no part of G1 through G13 enforcement. It separately rejects a line-reference locator in a `CITATION:` entry of the planner internal-review record, which is consistent with G11 but is a hook rule, not a validator rule.
|
|
@@ -21,6 +21,22 @@ Use this skill when:
|
|
|
21
21
|
- Task IDs must match their phase and be sequential per phase.
|
|
22
22
|
- Plans must pass the `mcp__drm-copilot__validate_orchestration_artifacts` MCP tool with `artifact_type: "plan"` and `artifact_path: <plan-path>` before they can be reported as approved.
|
|
23
23
|
|
|
24
|
+
## Design-Level Plan Contract (Mandatory)
|
|
25
|
+
|
|
26
|
+
A plan is a design-level document: it states what changes and how the change is proven, not a transcript of commands. Every task names the files it creates or edits, the symbols, headings, or tests it touches, the behavior the change produces, the tests that prove that behavior, and an acceptance condition stated as an observable outcome.
|
|
27
|
+
|
|
28
|
+
Rules:
|
|
29
|
+
|
|
30
|
+
- **Anchors are symbols, headings, or test names.** A plan never cites a line number, a `path:line` locator, a `#L` anchor, or a commit SHA, because each goes stale when `main` moves (validator rules G11 and G12). Scope comparisons name the merge-base derivation of `origin/main` and `HEAD`, not a commit.
|
|
31
|
+
- **Literals only where they are the asserted value.** A plan quotes a literal when an acceptance condition asserts that exact value. It does not quote file contents, command output, or prose for context.
|
|
32
|
+
- **Tool routes are not restated.** Tool routes, launchers, wrapper scripts, command-text restrictions, the batch budget, hook context, and CI shape are owned by the `execution-environment` skill. A plan references that skill instead of restating its content.
|
|
33
|
+
- **Changed existing behavior names its asserting tests.** A task that changes the observable behavior of an existing function, script, fixture, or test stub (its signature, argv, output, exit status, or the files it writes) names every existing test that asserts that behavior and states each test's disposition: unchanged because it is unaffected, or updated, with the reason for the update. The tests are found by searching the test tree for the symbol, the file name, and the asserted output. A test that asserts the current behavior and is outside the task's file set fails once the change lands, and the plan's own acceptance condition then cannot be met. The planner's adversarial self-review includes this search for every task that changes existing behavior.
|
|
34
|
+
- **Size guideline.** A plan stays within 40 canonical tasks and 400 physical lines. A plan that needs more carries a `## Size Justification` section with at least one line stating why the size is necessary (validator rule G13). Files produced by one generator run count as one generator task.
|
|
35
|
+
- **Pre-Mortem.** Every plan carries a `## Pre-Mortem` section with one bullet beginning with each of the seven labels `Review checklists`, `Coverage`, `Mirror parity`, `File size`, `Test isolation`, `CI-only behavior`, and `Evidence`. Each bullet states how the plan prevents that failure class, or states "not applicable" followed by the reason. The `Test isolation` bullet names the isolation runs the plan performs: a seeded shuffled Jest run with the seed recorded, a reversed-order run of the new or changed Python test modules, and a seeded shuffled file-order run of the touched Pester suites with at least three seeds, each seed recorded. The `Mirror parity` bullet also covers the execution-environment brief: a plan that alters a fact the brief states (for example, it adds or renames a CI job, changes a required status context, a tool route, or a batch-budget rule) includes a task that updates the brief in the same change, in all six byte-identical copies, and the bullet names that task. Without that task the brief states a superseded fact once the change lands, which breaks the brief's own maintenance rule. The planner SubagentStop hook blocks a plan without a complete section.
|
|
36
|
+
- **Final-phase self-review.** The final phase of every plan contains a self-review task that walks the policy-audit, code-review, and feature-audit templates under `docs/features/templates/policy_audit/` against the branch diff from the merge base and writes `<FEATURE>/evidence/qa-gates/self-review.<timestamp>.md` with one PASS, FAIL, or N/A row per checklist item. A FAIL row is fixed and the QA loop is re-run before the self-review is rewritten; the plan does not complete with a FAIL row.
|
|
37
|
+
|
|
38
|
+
This section takes precedence over the literal-quoting rules of `## Wrap-Tolerant Assertion Authoring (Mandatory)`: those rules govern the asserted value of an acceptance condition, not context.
|
|
39
|
+
|
|
24
40
|
## Short-Path Minimal Plan Contract
|
|
25
41
|
|
|
26
42
|
When orchestration selects short path, a minimal plan is still mandatory and must include these blocks:
|
|
@@ -145,38 +161,52 @@ Any regression test task expected to fail must be tagged with `[expect-fail]` an
|
|
|
145
161
|
|
|
146
162
|
## Planner Adversarial Self-Review (Mandatory)
|
|
147
163
|
|
|
148
|
-
Before any plan handoff, `atomic-planner` MUST complete one explicit adversarial self-review pass over every fact, assumption, and
|
|
164
|
+
Before any plan handoff, `atomic-planner` MUST complete one explicit adversarial self-review pass over every fact, assumption, and file, symbol, heading, or test citation the plan relies on. The pass is required on initial authoring and on every revision-delta round. A revision round is not exempt because it changed only part of the plan: the citations the revision touched describe the tree as it stands after the revision, and no earlier pass observed that state.
|
|
149
165
|
|
|
150
166
|
Rules:
|
|
151
167
|
|
|
152
|
-
- **Re-derive every citation in this pass.** Any
|
|
153
|
-
- **Re-check the sibling region.** The self-review MUST re-check the sibling
|
|
168
|
+
- **Re-derive every citation in this pass.** Any file, symbol, heading, test, or assertion that the planner's own edit touched, added, or removed in the current authoring or revision pass MUST be re-derived directly against current repository state in that same pass. The prohibited source is a citation carried forward from an earlier round, including one the planner itself verified in a prior round: that earlier verification observed the tree before the intervening edits, so it is evidence about a superseded state rather than about the state the plan now asserts.
|
|
169
|
+
- **Re-check the sibling region.** The self-review MUST re-check the sibling symbols, tests, and assertions that sit in the same file or section as any edited citation. The failure mechanism is sibling invalidation: a fix to one citation can invalidate an assumption baked into a sibling symbol or test that a prior round's citation did not cover, so a pass that verifies only the edited line leaves the invalidated sibling unreported and it surfaces as a defect on a later round.
|
|
154
170
|
|
|
155
171
|
Declaration requirement. Every plan handoff MUST carry exactly one of these two signal lines, written in the directive-line form already used elsewhere in this contract:
|
|
156
172
|
|
|
157
|
-
- `SELF-REVIEW: RE-DERIVED THIS PASS` — the adversarial self-review pass completed in this pass. This signal MUST be followed by an enumeration of the citations re-derived in that pass, one entry per citation, each naming the file and the
|
|
173
|
+
- `SELF-REVIEW: RE-DERIVED THIS PASS` — the adversarial self-review pass completed in this pass. This signal MUST be followed by an enumeration of the citations re-derived in that pass, one entry per citation, each naming the file and the symbol, heading, or test name that was re-derived. A signal carrying no enumeration is not a completed declaration.
|
|
158
174
|
- `SELF-REVIEW: BLOCKED` — the pass could not be completed. This signal halts the handoff. It does not permit a self-approved plan: the planner reports the blocking reason and waits for the caller rather than proceeding to hand off an unverified plan.
|
|
159
175
|
|
|
160
176
|
## Preflight Validation (Planner ↔ Executor)
|
|
161
177
|
|
|
162
178
|
### Planner Internal Review Record
|
|
163
179
|
|
|
164
|
-
Before executor preflight, the planner must emit exactly one bounded record between `PLANNER-INTERNAL-REVIEW: PASS` and the existing `PREFLIGHT:` signal. The record requires exactly one passing declaration each for `CITATION-TO-TREE`, `AC-TRACEABILITY`, and `SCOPE-BOUNDARY`; one or more `CITATION: <repository-relative path> | <
|
|
180
|
+
Before executor preflight, the planner must emit exactly one bounded record between `PLANNER-INTERNAL-REVIEW: PASS` and the existing `PREFLIGHT:` signal. The record requires exactly one passing declaration each for `CITATION-TO-TREE`, `AC-TRACEABILITY`, and `SCOPE-BOUNDARY`; one or more `CITATION: <repository-relative path> | <symbol, heading, or test name>` entries, whose locator is never a line reference (bare digits, `L` plus digits, `line` plus digits, or a path followed by a colon and digits); exactly one `AC-INVENTORY:` declaration containing unique nonblank IDs; one `AC-MAPPING: <ID> | IMPLEMENTATION: <nonblank> | TESTS: <nonblank> | EVIDENCE: <nonblank>` for every and only inventory ID; and exactly one `UNRESOLVED-GAPS: NONE`. Missing, blank, duplicate, non-passing, out-of-bounds, or inventory/mapping-disagreeing declarations block handoff. If review cannot pass, emit `SELF-REVIEW: BLOCKED` and do not hand the plan to preflight. `SELF-REVIEW: RE-DERIVED THIS PASS` remains distinct and does not replace executor clearance.
|
|
165
181
|
|
|
166
182
|
When validating or handing off plans for execution:
|
|
167
|
-
-
|
|
183
|
+
- Put the directive line `DIRECTIVE: PREFLIGHT VALIDATION ONLY` in the delegation prompt. The preflight directive belongs in the delegation prompt, never in a plan file. A plan file that still carries the line from an earlier contract is harmless, because the executor SubagentStop hook classifies a run from the delegation prompt recorded in the subagent transcript.
|
|
168
184
|
- Require one of the exact signals:
|
|
169
185
|
- `PREFLIGHT: ALL CLEAR`
|
|
170
186
|
- `PREFLIGHT: REVISIONS REQUIRED`
|
|
171
|
-
- If revisions are required, provide a precise plan delta and repeat validation until all clear.
|
|
172
187
|
- If the required planner ↔ executor handoff cannot be started or completed, stop and report blocked state; do not self-approve the plan.
|
|
173
188
|
|
|
174
|
-
|
|
189
|
+
### Single-Pass Preflight
|
|
190
|
+
|
|
191
|
+
Preflight completes in one pass. The preflight executor fixes trivial defects in place and returns only substantive defects, and a plan returns to the planner at most once.
|
|
175
192
|
|
|
176
193
|
- **Review the entire plan in one pass.** Under `DIRECTIVE: PREFLIGHT VALIDATION ONLY`, `atomic-executor` MUST continue checking every remaining phase, task, and prose region after finding an initial defect. Stopping at the first defect is prohibited: the unchecked remainder holds defects that the same pass could have reported, and each one that is left unreported becomes an additional round.
|
|
177
|
-
- **
|
|
178
|
-
- **
|
|
179
|
-
- **
|
|
194
|
+
- **Classify every defect as trivial or substantive.**
|
|
195
|
+
- **Trivial defects** are a stale or misspelled anchor, symbol, heading, or path whose intent is unambiguous; a citation correction, including removal of a G11 line-number or G12 commit-SHA citation; a typo; a literal-formatting defect that does not change what is asserted (quoting, `-e` for a hyphen-leading search pattern, plain `grep` instead of `git grep` for a file the plan creates, a full repository-relative pathspec); an evidence filename spelling; and a validator-blind defect class listed in the `execution-environment` skill whose correction keeps the assertion's meaning.
|
|
196
|
+
- **Substantive defects** are a missing or extra task; a wrong file set or design; an acceptance criterion with no implementing task; an unsatisfiable acceptance condition whose correction changes what is asserted; a task-ordering error; and a scope-boundary violation.
|
|
197
|
+
- **Fix trivial defects in place, in task text only.** The preflight executor edits task text and plan preamble in the same plan file. It never adds, removes, or reorders tasks, so the executor's anti-replanning rules are unchanged. Each fix is recorded in `<FEATURE>/evidence/other/preflight-fixes.<timestamp>.md`, which carries `Timestamp:`, `Plan:`, and one entry per fix.
|
|
198
|
+
- **Return substantive defects only, all of them.** `PREFLIGHT: REVISIONS REQUIRED` is returned only when at least one substantive defect remains, and it lists every substantive defect found in the pass. `PREFLIGHT: ALL CLEAR` may follow in-place fixes.
|
|
199
|
+
- **Check the fix against its own rule.** Before returning either signal, `atomic-executor` MUST check each in-place fix and each required change against every rule the plan enforces, including the fix's own prose against the same violation class it is remediating. Worked example: the prose of a tonality-compliance fix must not itself contain the hyperbole or humor that `.claude/rules/tonality.md` prohibits, because a fix that violates the rule it is written to enforce reintroduces the finding it closes.
|
|
200
|
+
|
|
201
|
+
Output format. After the `PREFLIGHT:` signal and the `CONVERGENCE:` line, the preflight return carries one line per defect:
|
|
202
|
+
|
|
203
|
+
- `PREFLIGHT-FIX: <task id or heading> | <defect class> | <change made>` for each trivial defect fixed in place.
|
|
204
|
+
- `PREFLIGHT-DEFECT: <task id or heading> | <defect class> | <required change>` for each substantive defect returned.
|
|
205
|
+
- `preflight-fix-record: <path>` when at least one fix was made, naming the record under `<FEATURE>/evidence/other/`.
|
|
206
|
+
|
|
207
|
+
`PREFLIGHT: ALL CLEAR` carries no `PREFLIGHT-DEFECT:` line, and `PREFLIGHT: REVISIONS REQUIRED` carries at least one. The executor SubagentStop hook blocks, repairably, a preflight return with zero or several `PREFLIGHT:` signals, a signal that disagrees with its defect lines, or a `PREFLIGHT-FIX:` line without an existing `preflight-fix-record:` path under `docs/features/`.
|
|
208
|
+
|
|
209
|
+
At most one return. A plan returns to the planner at most once. On `PREFLIGHT: REVISIONS REQUIRED`, the orchestrator delegates one planner revision carrying the full `PREFLIGHT-DEFECT:` list, then runs one more preflight. If that second preflight still reports a substantive defect, the orchestrator halts with `blocked_reason: "validator_failed"` during planning, or records `final_status: "blocked_preflight_iteration_limit"` in a remediation cycle. In a proportionate remediation cycle, where preflight and execution run in one executor delegation, a substantive defect stops the run with `BLOCKED at preflight (before [P0-T1])` before any task is checked.
|
|
180
210
|
|
|
181
211
|
Convergence signal. Every preflight return, whether it carries `PREFLIGHT: ALL CLEAR` or `PREFLIGHT: REVISIONS REQUIRED`, MUST additionally carry exactly one of these two forward-looking lines:
|
|
182
212
|
|
|
@@ -193,14 +223,16 @@ Before a plan can be treated as approved:
|
|
|
193
223
|
- reject the plan if that validator exits non-zero,
|
|
194
224
|
- do not treat human-readable summaries as a substitute for validator success.
|
|
195
225
|
|
|
196
|
-
The same validator call also applies the acceptance-gate rules
|
|
226
|
+
The same validator call also applies the acceptance-gate rules defined in `.claude/rules/plan-acceptance-gates.md`, starting with G1 through G6. Those rules report acceptance conditions that cannot fail — a coverage argument that collects no data, or a search for a literal that returns zero matches whatever the executor does. They run automatically on the existing `plan` route with no additional flag. Blocking findings appear in the validator's error output and fail the gate; Warnings are surfaced without failing it, prefixed with `PLAN GATE WARNING: ` on the CLI and carried on the optional `warnings` field of the MCP result. Read that rule file before authoring acceptance conditions.
|
|
197
227
|
|
|
198
|
-
The same call additionally applies the rules G7, G8, G8b, and G9, which report a write-mode command observed only by its exit code, an unanchored `git diff`, a name-listing diff with no companion span, and a coverage command that prints no table. All four ship in the Warning channel, so they surface without failing the gate. The same call also applies G10, a document-level rule that reports a SCRATCH definition not namespaced by issue number. G10 ships in the Blocking channel and reports each finding with a `Line N: ` prefix rather than a task identifier, because the definition sits outside any task window. The complete shipped set is therefore G1 through
|
|
228
|
+
The same call additionally applies the rules G7, G8, G8b, and G9, which report a write-mode command observed only by its exit code, an unanchored `git diff`, a name-listing diff with no companion span, and a coverage command that prints no table. All four ship in the Warning channel, so they surface without failing the gate. The same call also applies G10, a document-level rule that reports a SCRATCH definition not namespaced by issue number. G10 ships in the Blocking channel and reports each finding with a `Line N: ` prefix rather than a task identifier, because the definition sits outside any task window. The same call also applies the document-level rules G11, G12, and G13, which report a line-number citation, a commit-SHA citation, and a plan above 40 tasks or 400 lines without a non-empty `## Size Justification` section; all three ship in the Blocking channel with the `Line N: ` prefix. The complete shipped set is therefore G1 through G13. The installed MCP validator applies G11 through G13 only after the extension release that carries them is installed; until then, validate a plan with the repository's Python CLI `scripts/dev_tools/validate_orchestration_artifacts.py` and its `plan` subcommand, as the `execution-environment` skill states.
|
|
199
229
|
|
|
200
230
|
## Wrap-Tolerant Assertion Authoring (Mandatory)
|
|
201
231
|
|
|
202
232
|
An acceptance condition must be able to fail. A condition whose command returns the same result whatever the executor does verifies nothing, however precise it reads. Author every acceptance condition in a wrap-tolerant form: one that survives line wrapping and shell quoting in the file it asserts against.
|
|
203
233
|
|
|
234
|
+
These rules apply to the asserted value of an acceptance condition and are subordinate to `## Design-Level Plan Contract (Mandatory)`: they say how to quote a value that is asserted, not that a plan should quote file contents, command recipes, or tool routes. Where a rule below names a command shape, the shape is guidance for the executor's choice of command, which the `execution-environment` skill governs.
|
|
235
|
+
|
|
204
236
|
Rules:
|
|
205
237
|
|
|
206
238
|
- **Prefer a named test over a phrase search.** When a test can carry the assertion, name the test and its node ID and assert its pass count. A test node ID is stable under reformatting; a prose phrase is not. Reserve searches for cases where no test can express the condition.
|
|
@@ -216,7 +248,7 @@ Rules:
|
|
|
216
248
|
- **Observe a command's success-case output before asserting over that output (mandatory).** Run the command, or read a recorded run of it, and confirm the value you intend to assert is actually printed on a *successful* run. Do not infer it from the tool's documentation, from the plan, or from what the tool prints on failure. This requirement exists because the class of defect it prevents is not detectable by reading: an assertion on a line the tool prints only when it changed something is unsatisfiable on a clean run; a demand for a zero-diagnostic count from a tool that returns only an ok flag names a value with no source; a demand for separate line and branch percentages from a coverage run that prints one combined column reads two numbers that are never printed. G7 and G9 cover two decidable slices of this class. The remainder is covered by this requirement and by nothing else, so a reviewer cannot rely on the gate to catch it.
|
|
217
249
|
- **Fix the evidence in the plan; never leave the executor to select it.** An executor free to choose the evidence it is judged against cannot fail. Do not write an acceptance condition that asks the executor to identify "the known-genuine pair", to choose a survivor list, or to pick any suitable instance. Name the instances, or state the mechanical derivation that produces them, so a third party re-running it obtains the same set. This is authoring guidance and not a rule: a validator rule that scanned acceptance text for selection vocabulary was proposed and rejected, because that vocabulary is ordinary plan prose used in roles carrying no selection semantics and a keyword scan over prose is not statically decidable for the property it would claim to detect. The judgment is the author's, and it is not automated. `.claude/rules/plan-acceptance-gates.md` records the rejection and the reason for it.
|
|
218
250
|
- **Check that the task-ordering does not make the condition unsatisfiable.** No rule covers this. A gate that runs a test path containing deliberately-failing cases added by an earlier task, before the later task that makes them pass, cannot exit 0. A baseline captured after a write-mode formatter has already repaired pre-existing drift becomes either a blanket waiver or makes a later gate unsatisfiable. Read each acceptance condition against the state the plan will actually be in when its task runs.
|
|
219
|
-
- **Name the runner and job for a Pester acceptance criterion.**
|
|
251
|
+
- **Name the runner and job for a Pester acceptance criterion.** In `.github/workflows/_poshqc.yml`, the Pester suites run with coverage on `windows-latest` in the shard jobs `poshqc / PowerShell QC shard 1`, `shard 2`, and `shard 3`; `poshqc / PowerShell QC` is the aggregating required check, which requires the static and shard jobs to succeed and merges shard coverage; and `poshqc / PowerShell hook suites (Linux)` runs only `tests/scripts/claude-hooks` and `tests/scripts/codex-hooks` on `ubuntu-latest`, with coverage disabled. The execution-environment brief's `## CI Shape and Required Checks` section is the authoritative description of this shape. A Pester acceptance criterion may cite `ubuntu-latest` only for suites under `tests/scripts/claude-hooks` or `tests/scripts/codex-hooks`, never for coverage, and must name the job it relies on (`poshqc / PowerShell QC` or `poshqc / PowerShell hook suites (Linux)`).
|
|
220
252
|
- **Do not assert a fixed-string search literal that contains a backslash.** Git for Windows grep 3.0 reads a doubled backslash in a `grep -F` pattern as one backslash, so the same check returns a different count locally than on a CI runner and cannot pass in both places. Assert a backslash-free substring of the literal, a named test, or a hash or byte-identity check instead.
|
|
221
253
|
|
|
222
254
|
## Plan-Path Continuity Contract (Mandatory)
|
|
@@ -224,10 +256,10 @@ Rules:
|
|
|
224
256
|
When a caller provides an explicit target plan file path (for example `${plan-path}` or `${file}`):
|
|
225
257
|
|
|
226
258
|
- Planner MUST update that exact file in place.
|
|
227
|
-
- Planner MUST reuse the same file for
|
|
259
|
+
- Planner MUST reuse the same file for the single permitted preflight revision.
|
|
228
260
|
- Planner MUST NOT create additional timestamped sibling files (for example `plan.<timestamp>.md`) during the same planning cycle.
|
|
229
261
|
|
|
230
|
-
If the provided path does not exist, it may be created once, then reused for
|
|
262
|
+
If the provided path does not exist, it may be created once, then reused for the single permitted revision in that cycle.
|
|
231
263
|
|
|
232
264
|
## Mode source precedence (Mandatory)
|
|
233
265
|
|
|
@@ -203,9 +203,13 @@ The script emits pipe-delimited, `LC_ALL=C`-ordered records, one per line:
|
|
|
203
203
|
`.claude/settings.json`) carries no `gh` entry; and `.claude/hooks/enforce-epic-merge-gate.ps1`
|
|
204
204
|
would deny the command with `EPIC_MERGE_GATE_BLOCKED` if it were attempted. At this
|
|
205
205
|
boundary the agent reports the consolidation pull request's URL or number to the
|
|
206
|
-
operator and stops.
|
|
207
|
-
|
|
208
|
-
|
|
206
|
+
operator and stops. When `main` uses a merge queue (issue #952), the queue tests the merged
|
|
207
|
+
result of the pull request and the entries ahead of it against the latest `main`, so the
|
|
208
|
+
branch need not be up to date with `main`, and the operator adds it to the queue once its
|
|
209
|
+
checks pass. Without a merge queue, the ruleset on `main` sets
|
|
210
|
+
`strict_required_status_checks_policy`, so the branch must be up to date with `main` before
|
|
211
|
+
the merge becomes available to the operator. In either case the wait for the merge is
|
|
212
|
+
unbounded within a session. After the consolidation
|
|
209
213
|
PR merges, verify it with `git fetch` followed by
|
|
210
214
|
`git merge-base --is-ancestor documentationandmemories main`. Exit 0 confirms every
|
|
211
215
|
consolidated commit is now reachable from `main`; that is the only state that unlocks
|
|
@@ -28,7 +28,7 @@ When routed through `csharp-orchestrator`, small path still requires lifecycle s
|
|
|
28
28
|
- promote potential item to GitHub issue with `--work-mode minor-audit`,
|
|
29
29
|
- create active feature folder with `--work-mode minor-audit`,
|
|
30
30
|
- delegate minimal-audit plan creation to `atomic_planner` with `DIRECTIVE: MINIMAL-AUDIT PLAN REQUIRED`,
|
|
31
|
-
- require `atomic_executor` preflight
|
|
31
|
+
- require single-pass `atomic_executor` preflight ending in `PREFLIGHT: ALL CLEAR` (at most one return to the planner),
|
|
32
32
|
- execute Phase 0 only via atomic_executor before branching,
|
|
33
33
|
- run reduced small-audit after implementation and QC.
|
|
34
34
|
|
|
@@ -69,7 +69,7 @@ In all modes, per-batch budget remains: at most **3 production files** and **3 t
|
|
|
69
69
|
When `csharp-typed-engineer` runs in orchestrator handoff mode, it must execute the following delegation chain and must not bypass it with direct implementation:
|
|
70
70
|
|
|
71
71
|
1. Delegate to `atomic_planner` for an architecture plus testability plan only (no edits).
|
|
72
|
-
2. Require planner output to include final `PREFLIGHT: ALL CLEAR` from
|
|
72
|
+
2. Require planner output to include final `PREFLIGHT: ALL CLEAR` from single-pass preflight (at most one return to the planner).
|
|
73
73
|
3. Delegate plan execution to `atomic_executor`.
|
|
74
74
|
4. Delegate the final QA gate to `atomic_executor` per `csharp-qa-gate`.
|
|
75
75
|
5. Delegate post-implementation review to `feature-review` per `feature-review-workflow`.
|
|
@@ -126,7 +126,14 @@ function of the DAG.
|
|
|
126
126
|
`mcp__drm-copilot__collect_pr_context`. `epic-orchestrator` runs the same S9 CI-green
|
|
127
127
|
procedure (`pwsh -NoProfile -File .claude/lib/ci-gate/Invoke-CiGateParser.ps1`) directly against this PR, records
|
|
128
128
|
the result under the epic checkpoint's `epic_merge_pr` object, then executes
|
|
129
|
-
`gh pr merge --merge` once green, gated by `enforce-epic-merge-gate.ps1`.
|
|
129
|
+
`gh pr merge --merge` once green, gated by `enforce-epic-merge-gate.ps1`. Under a merge queue
|
|
130
|
+
on `main`, `gh pr merge` can return before the merge happens, so
|
|
131
|
+
`epic_merge_pr.merge_commit_sha` is recorded only after the merge is confirmed by polling and
|
|
132
|
+
ancestry check, using the confirmation procedure of step 3 of
|
|
133
|
+
`## Per-Item Merge to Main (Merge-on-Green)` in `.claude/skills/parallel-orchestrate/SKILL.md`
|
|
134
|
+
with `main` as the base branch; each pull-request snapshot is classified with
|
|
135
|
+
`pwsh -NoProfile -File .claude/lib/ci-gate/Invoke-MergeConfirmationParser.ps1 -PrJson <snapshot-json> -AsJson`
|
|
136
|
+
(issue #952).
|
|
130
137
|
|
|
131
138
|
## Merge-on-Green Kickoff Parameter
|
|
132
139
|
|
|
@@ -138,7 +145,9 @@ the literal epic-mode kickoff line:
|
|
|
138
145
|
The child's own `orchestrator`, on reading this line, records `epic_mode: true` and
|
|
139
146
|
`epic_context: { epic_feature_folder, integration_branch, epic_checkpoint_path }` at its first
|
|
140
147
|
checkpoint write, and on CI-green (S9 step 6) merges its own PR into the integration branch,
|
|
141
|
-
recording `epic_merge: { merge_commit_sha, target_branch, merged_at }`.
|
|
148
|
+
recording `epic_merge: { merge_commit_sha, target_branch, merged_at }`. The child records
|
|
149
|
+
`epic_merge` only after the merge is confirmed by polling and ancestry check against
|
|
150
|
+
`origin/<integration_branch>` (S9 step 6). Standalone (non-epic)
|
|
142
151
|
orchestration is unchanged: `epic_mode` absent or `false` makes S9 step 6 a no-op.
|
|
143
152
|
|
|
144
153
|
The run gates `enforce-orchestration-preimplementation-gate.ps1` and `enforce-epic-wave-barrier.ps1` locate the epic checkpoint by the `integration_branch:` value of this line. They select the live worktree whose `artifacts/orchestration/epic-orchestrator-state.json` records `route_id` `epic` and that integration branch, prefer the worktree that has the branch checked out when more than one records it, and deny the delegation with `TARGET_WORKTREE_NOT_DERIVABLE` or `TARGET_WORKTREE_AMBIGUOUS` when none or more than one remains. A stale copy of the epic checkpoint is moved to `artifacts/orchestration/handoff/` rather than left at a worktree root. The child run's own delegations to implementation agents carry the canonical issue-number line and `branch:` label defined in `.claude/skills/orchestrate/SKILL.md` `## Issue Number Consistency`.
|
|
@@ -353,7 +362,7 @@ that same call at the completion gate. The validation is implemented in
|
|
|
353
362
|
|
|
354
363
|
1. Every feature in the manifest has `merge_status` in `{merged, worktree_removed}`.
|
|
355
364
|
2. The final integration-to-`main` PR has merged and `epic_merge_pr.merge_commit_sha` is
|
|
356
|
-
recorded.
|
|
365
|
+
recorded, and it is recorded only after the merge is confirmed by polling and ancestry check.
|
|
357
366
|
3. `docs/features/epics/<epic-slug>/epic-status.md` reflects the completed state.
|
|
358
367
|
4. The epic checkpoint passes `validate_epic_orchestrator_state_text` with
|
|
359
368
|
`require_complete=True`.
|