@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/out/mcp-server.js
CHANGED
|
@@ -22913,7 +22913,7 @@ var BASE_REWRITE_RULES = [
|
|
|
22913
22913
|
},
|
|
22914
22914
|
{
|
|
22915
22915
|
pattern: /Return the finalized plan for validation-only preflight through `atomic-executor` and preserve the same target file path across revision loops\. Do not claim nested worker delegation from within planner execution\./g,
|
|
22916
|
-
replacement: 'Before reporting completion, explicitly spawn the `atomic-executor` subagent for validation-only preflight. The delegated prompt MUST include the exact directive `DIRECTIVE: PREFLIGHT VALIDATION ONLY`.\n\n- `atomic-executor` MUST return exactly one of:\n - `PREFLIGHT: ALL CLEAR`\n - `PREFLIGHT: REVISIONS REQUIRED`\n- Treat executor preflight findings as binding plan defects.\n- If preflight returns `PREFLIGHT: REVISIONS REQUIRED`, revise the same target plan file using the executor\'s precise plan delta and
|
|
22916
|
+
replacement: 'Before reporting completion, explicitly spawn the `atomic-executor` subagent for validation-only preflight. The delegated prompt MUST include the exact directive `DIRECTIVE: PREFLIGHT VALIDATION ONLY`.\n\n- `atomic-executor` MUST return exactly one of:\n - `PREFLIGHT: ALL CLEAR`\n - `PREFLIGHT: REVISIONS REQUIRED`\n- Treat executor preflight findings as binding plan defects.\n- If preflight returns `PREFLIGHT: REVISIONS REQUIRED`, revise the same target plan file once using the executor\'s precise plan delta and its full `PREFLIGHT-DEFECT:` list, and run one confirming preflight. Preflight is single-pass: trivial defects are fixed in place by the executor, and a plan returns to the planner at most once; a second substantive result halts with `blocked_reason: "validator_failed"`.\n- Reuse the same target plan file for the single permitted preflight revision in the same planning cycle.\n- If the required `atomic-executor` handoff cannot be started or completed, stop and report blocked state; do not self-approve the plan.\n- Before reporting completion, the target plan MUST pass the `validate_orchestration_artifacts` MCP tool with `artifact_type: "plan"` and `artifact_path: <plan-path>`.\n\nDo not claim nested worker delegation from within planner execution.',
|
|
22917
22917
|
description: "Expand the Claude atomic-planner preflight shorthand into the strict Codex atomic-executor handoff contract."
|
|
22918
22918
|
},
|
|
22919
22919
|
{
|
|
@@ -25001,39 +25001,39 @@ var LOGICAL_AGENT_ALIASES = {
|
|
|
25001
25001
|
var BASE_PROFILES = {
|
|
25002
25002
|
C1: {
|
|
25003
25003
|
suffix: "c1",
|
|
25004
|
-
model: "gpt-
|
|
25004
|
+
model: "gpt-6-luna",
|
|
25005
25005
|
model_reasoning_effort: "low"
|
|
25006
25006
|
},
|
|
25007
25007
|
C2: {
|
|
25008
25008
|
suffix: "c2",
|
|
25009
|
-
model: "gpt-
|
|
25009
|
+
model: "gpt-6.1-sol",
|
|
25010
25010
|
model_reasoning_effort: "medium"
|
|
25011
25011
|
},
|
|
25012
25012
|
C3: {
|
|
25013
25013
|
suffix: "c3",
|
|
25014
|
-
model: "gpt-
|
|
25014
|
+
model: "gpt-6.1-sol",
|
|
25015
25015
|
model_reasoning_effort: "high"
|
|
25016
25016
|
},
|
|
25017
25017
|
C4: {
|
|
25018
25018
|
suffix: "c4",
|
|
25019
|
-
model: "gpt-
|
|
25019
|
+
model: "gpt-6-astra",
|
|
25020
25020
|
model_reasoning_effort: "max"
|
|
25021
25021
|
}
|
|
25022
25022
|
};
|
|
25023
25023
|
var C3_ELEVATED_PROFILE = {
|
|
25024
25024
|
suffix: "c3-elevated",
|
|
25025
|
-
model: "gpt-
|
|
25025
|
+
model: "gpt-6-astra",
|
|
25026
25026
|
model_reasoning_effort: "high"
|
|
25027
25027
|
};
|
|
25028
25028
|
var FORCED_PERSONA_PROFILES = {
|
|
25029
25029
|
"epic-planner": {
|
|
25030
25030
|
suffix: "",
|
|
25031
|
-
model: "gpt-
|
|
25031
|
+
model: "gpt-6-astra",
|
|
25032
25032
|
model_reasoning_effort: "ultra"
|
|
25033
25033
|
},
|
|
25034
25034
|
"epic-orchestrator": {
|
|
25035
25035
|
suffix: "",
|
|
25036
|
-
model: "gpt-
|
|
25036
|
+
model: "gpt-6-astra",
|
|
25037
25037
|
model_reasoning_effort: "ultra"
|
|
25038
25038
|
}
|
|
25039
25039
|
};
|
|
@@ -28957,6 +28957,166 @@ function extractPlanCommands(text2) {
|
|
|
28957
28957
|
return commands;
|
|
28958
28958
|
}
|
|
28959
28959
|
|
|
28960
|
+
// ../../extensions/drm-copilot/src/lib/validate/plan-gate-document.ts
|
|
28961
|
+
var G11_SEVERITY = "blocking";
|
|
28962
|
+
var G12_SEVERITY = "blocking";
|
|
28963
|
+
var G13_SEVERITY = "blocking";
|
|
28964
|
+
var PLAN_TASK_GUIDELINE = 40;
|
|
28965
|
+
var PLAN_LINE_GUIDELINE = 400;
|
|
28966
|
+
var G11_PROSE_PATTERN = String.raw`\b[Ll]ines?[ \t]+[0-9]+`;
|
|
28967
|
+
var G11_PATH_PATTERN = String.raw`[A-Za-z0-9_./-]+\.[A-Za-z][A-Za-z0-9]{0,5}:[0-9]+`;
|
|
28968
|
+
var G11_ANCHOR_PATTERN = String.raw`#L[0-9]+`;
|
|
28969
|
+
var G12_SHA_PATTERN = String.raw`\b[0-9a-f]{7,40}\b`;
|
|
28970
|
+
var G13_TASK_PATTERN = String.raw`^- \[[ xX]\] \[P[0-9]+-T[0-9]+\] `;
|
|
28971
|
+
var INLINE_CODE_PATTERN = "`[^`]*`";
|
|
28972
|
+
var FENCE_RE2 = /^\s*```/;
|
|
28973
|
+
var PROSE_RE = new RegExp(G11_PROSE_PATTERN, "g");
|
|
28974
|
+
var PATH_RE = new RegExp(G11_PATH_PATTERN, "g");
|
|
28975
|
+
var ANCHOR_RE = new RegExp(G11_ANCHOR_PATTERN, "g");
|
|
28976
|
+
var SHA_RE = new RegExp(G12_SHA_PATTERN, "g");
|
|
28977
|
+
var TASK_RE = new RegExp(G13_TASK_PATTERN);
|
|
28978
|
+
var INLINE_CODE_RE = new RegExp(INLINE_CODE_PATTERN, "g");
|
|
28979
|
+
var WHITESPACE_RE = new RegExp(`^${PLAN_WHITESPACE_CLASS}$`);
|
|
28980
|
+
var JUSTIFICATION_HEADING_RE = /^##[ \t]+Size Justification[ \t]*$/;
|
|
28981
|
+
var SECTION_END_RE = /^#{1,2}(?:[ \t]|$)/;
|
|
28982
|
+
var HEADING_RE = /^#{1,6}(?:[ \t]|$)/;
|
|
28983
|
+
var DIGITS = "0123456789";
|
|
28984
|
+
var HEX_LETTERS = "abcdef";
|
|
28985
|
+
var SHA_BEFORE_REJECT = "-_.";
|
|
28986
|
+
var SHA_AFTER_REJECT = "-_";
|
|
28987
|
+
function unfencedLines(text2) {
|
|
28988
|
+
const result = [];
|
|
28989
|
+
let inFence = false;
|
|
28990
|
+
for (const [index, line] of splitPlanLines(text2).entries()) {
|
|
28991
|
+
if (FENCE_RE2.test(line)) {
|
|
28992
|
+
inFence = !inFence;
|
|
28993
|
+
continue;
|
|
28994
|
+
}
|
|
28995
|
+
if (!inFence) {
|
|
28996
|
+
result.push([index + 1, line]);
|
|
28997
|
+
}
|
|
28998
|
+
}
|
|
28999
|
+
return result;
|
|
29000
|
+
}
|
|
29001
|
+
function maskInlineCode(line) {
|
|
29002
|
+
return line.replace(INLINE_CODE_RE, (span) => " ".repeat(span.length));
|
|
29003
|
+
}
|
|
29004
|
+
function isWhitespace(character) {
|
|
29005
|
+
return character !== void 0 && WHITESPACE_RE.test(character);
|
|
29006
|
+
}
|
|
29007
|
+
function enclosingToken(line, start, end) {
|
|
29008
|
+
let left = start;
|
|
29009
|
+
while (left > 0 && !isWhitespace(line[left - 1])) {
|
|
29010
|
+
left -= 1;
|
|
29011
|
+
}
|
|
29012
|
+
let right = end;
|
|
29013
|
+
while (right < line.length && !isWhitespace(line[right])) {
|
|
29014
|
+
right += 1;
|
|
29015
|
+
}
|
|
29016
|
+
return line.slice(left, right);
|
|
29017
|
+
}
|
|
29018
|
+
function lineCitations(text2) {
|
|
29019
|
+
const findings = [];
|
|
29020
|
+
for (const [lineNumber, line] of unfencedLines(text2)) {
|
|
29021
|
+
for (const match of maskInlineCode(line).matchAll(PROSE_RE)) {
|
|
29022
|
+
findings.push([lineNumber, match[0]]);
|
|
29023
|
+
}
|
|
29024
|
+
for (const match of line.matchAll(PATH_RE)) {
|
|
29025
|
+
const token = enclosingToken(
|
|
29026
|
+
line,
|
|
29027
|
+
match.index,
|
|
29028
|
+
match.index + match[0].length
|
|
29029
|
+
);
|
|
29030
|
+
if (!token.includes("://")) {
|
|
29031
|
+
findings.push([lineNumber, match[0]]);
|
|
29032
|
+
}
|
|
29033
|
+
}
|
|
29034
|
+
for (const match of line.matchAll(ANCHOR_RE)) {
|
|
29035
|
+
findings.push([lineNumber, match[0]]);
|
|
29036
|
+
}
|
|
29037
|
+
}
|
|
29038
|
+
return findings;
|
|
29039
|
+
}
|
|
29040
|
+
function isShaCandidate(line, start, end) {
|
|
29041
|
+
const token = line.slice(start, end);
|
|
29042
|
+
if (![...token].some((character) => DIGITS.includes(character))) {
|
|
29043
|
+
return false;
|
|
29044
|
+
}
|
|
29045
|
+
if (![...token].some((character) => HEX_LETTERS.includes(character))) {
|
|
29046
|
+
return false;
|
|
29047
|
+
}
|
|
29048
|
+
const before = start > 0 ? line.charAt(start - 1) : "";
|
|
29049
|
+
if (before !== "" && SHA_BEFORE_REJECT.includes(before)) {
|
|
29050
|
+
return false;
|
|
29051
|
+
}
|
|
29052
|
+
const after = end < line.length ? line.charAt(end) : "";
|
|
29053
|
+
return !(after !== "" && SHA_AFTER_REJECT.includes(after));
|
|
29054
|
+
}
|
|
29055
|
+
function shaCitations(text2) {
|
|
29056
|
+
const findings = [];
|
|
29057
|
+
for (const [lineNumber, line] of unfencedLines(text2)) {
|
|
29058
|
+
for (const match of line.matchAll(SHA_RE)) {
|
|
29059
|
+
if (isShaCandidate(line, match.index, match.index + match[0].length)) {
|
|
29060
|
+
findings.push([lineNumber, match[0]]);
|
|
29061
|
+
}
|
|
29062
|
+
}
|
|
29063
|
+
}
|
|
29064
|
+
return findings;
|
|
29065
|
+
}
|
|
29066
|
+
function hasSizeJustification(text2) {
|
|
29067
|
+
let inSection = false;
|
|
29068
|
+
for (const [, line] of unfencedLines(text2)) {
|
|
29069
|
+
if (JUSTIFICATION_HEADING_RE.test(line)) {
|
|
29070
|
+
inSection = true;
|
|
29071
|
+
continue;
|
|
29072
|
+
}
|
|
29073
|
+
if (!inSection) {
|
|
29074
|
+
continue;
|
|
29075
|
+
}
|
|
29076
|
+
if (SECTION_END_RE.test(line)) {
|
|
29077
|
+
inSection = false;
|
|
29078
|
+
continue;
|
|
29079
|
+
}
|
|
29080
|
+
if (normalizePlanWhitespace(line) !== "" && !HEADING_RE.test(line)) {
|
|
29081
|
+
return true;
|
|
29082
|
+
}
|
|
29083
|
+
}
|
|
29084
|
+
return false;
|
|
29085
|
+
}
|
|
29086
|
+
function planSize(text2) {
|
|
29087
|
+
const tasks = unfencedLines(text2).filter(
|
|
29088
|
+
([, line]) => TASK_RE.test(line)
|
|
29089
|
+
).length;
|
|
29090
|
+
return [tasks, splitPlanLines(text2).length];
|
|
29091
|
+
}
|
|
29092
|
+
function lineCitationMessage(lineNumber, value) {
|
|
29093
|
+
return `Line ${String(lineNumber)}: line-number citation \`${value}\` anchors on a position that moves when main moves; cite the symbol, heading, or test name instead.`;
|
|
29094
|
+
}
|
|
29095
|
+
function shaCitationMessage(lineNumber, value) {
|
|
29096
|
+
return `Line ${String(lineNumber)}: commit-SHA citation \`${value}\` names a commit that goes stale when main moves; cite the branch, ref name, or merge base derivation instead.`;
|
|
29097
|
+
}
|
|
29098
|
+
function planSizeMessage(tasks, lines) {
|
|
29099
|
+
return `Line 1: plan size \`${String(tasks)} tasks, ${String(lines)} lines\` exceeds the guideline of ${String(PLAN_TASK_GUIDELINE)} tasks or ${String(PLAN_LINE_GUIDELINE)} lines and carries no \`## Size Justification\` section; split the item or state why the size is necessary.`;
|
|
29100
|
+
}
|
|
29101
|
+
function channelFor(report, severity) {
|
|
29102
|
+
return severity === "blocking" ? report.blocking : report.warnings;
|
|
29103
|
+
}
|
|
29104
|
+
function evaluateDocumentGates(report, text2) {
|
|
29105
|
+
const g11 = channelFor(report, G11_SEVERITY);
|
|
29106
|
+
for (const [lineNumber, value] of lineCitations(text2)) {
|
|
29107
|
+
g11.push(lineCitationMessage(lineNumber, value));
|
|
29108
|
+
}
|
|
29109
|
+
const g12 = channelFor(report, G12_SEVERITY);
|
|
29110
|
+
for (const [lineNumber, value] of shaCitations(text2)) {
|
|
29111
|
+
g12.push(shaCitationMessage(lineNumber, value));
|
|
29112
|
+
}
|
|
29113
|
+
const [tasks, lines] = planSize(text2);
|
|
29114
|
+
const overGuideline = tasks > PLAN_TASK_GUIDELINE || lines > PLAN_LINE_GUIDELINE;
|
|
29115
|
+
if (overGuideline && !hasSizeJustification(text2)) {
|
|
29116
|
+
channelFor(report, G13_SEVERITY).push(planSizeMessage(tasks, lines));
|
|
29117
|
+
}
|
|
29118
|
+
}
|
|
29119
|
+
|
|
28960
29120
|
// ../../extensions/drm-copilot/src/lib/validate/plan-gate-rules.ts
|
|
28961
29121
|
function emptyPlanGateReport() {
|
|
28962
29122
|
return { blocking: [], warnings: [] };
|
|
@@ -29344,7 +29504,7 @@ var G10_SEVERITY = "blocking";
|
|
|
29344
29504
|
var BACKTICK = "`";
|
|
29345
29505
|
var SCRATCH_DEFINITION_PATTERN = String.raw`(?:^|[^A-Za-z0-9_<>$/.-])${BACKTICK}?SCRATCH${BACKTICK}?(?:\*\*)?[ \t]*(?:means\b|:=|=|:|is (?:the|a|an)\b|resolves to\b|abbreviates\b|denotes\b|refers to\b|stands for\b)`;
|
|
29346
29506
|
var SCRATCH_NAMESPACE_PATTERN = String.raw`issue-(?:<issue-num>|[0-9]+)`;
|
|
29347
|
-
var
|
|
29507
|
+
var FENCE_RE3 = /^\s*```/;
|
|
29348
29508
|
var DEFINITION_RE = new RegExp(SCRATCH_DEFINITION_PATTERN);
|
|
29349
29509
|
var NAMESPACE_RE = new RegExp(SCRATCH_NAMESPACE_PATTERN);
|
|
29350
29510
|
var LEADING_WHITESPACE_RE = new RegExp(`^${PLAN_WHITESPACE_CLASS}`);
|
|
@@ -29352,7 +29512,7 @@ function continuesLogicalLine(line) {
|
|
|
29352
29512
|
if (normalizePlanWhitespace(line) === "" || !LEADING_WHITESPACE_RE.test(line)) {
|
|
29353
29513
|
return false;
|
|
29354
29514
|
}
|
|
29355
|
-
return !
|
|
29515
|
+
return !FENCE_RE3.test(line);
|
|
29356
29516
|
}
|
|
29357
29517
|
function isBareDefinition(logical) {
|
|
29358
29518
|
const match = DEFINITION_RE.exec(logical);
|
|
@@ -29380,7 +29540,7 @@ function bareScratchDefinitions(text2) {
|
|
|
29380
29540
|
recordIfBare(findings, pending);
|
|
29381
29541
|
pending = null;
|
|
29382
29542
|
}
|
|
29383
|
-
if (
|
|
29543
|
+
if (FENCE_RE3.test(line)) {
|
|
29384
29544
|
inFence = !inFence;
|
|
29385
29545
|
continue;
|
|
29386
29546
|
}
|
|
@@ -29504,6 +29664,7 @@ function evaluatePlanGates(text2, context) {
|
|
|
29504
29664
|
evaluateLiteralRules(report, text2, commands, context);
|
|
29505
29665
|
}
|
|
29506
29666
|
evaluateScratchGate(report, text2);
|
|
29667
|
+
evaluateDocumentGates(report, text2);
|
|
29507
29668
|
return report;
|
|
29508
29669
|
}
|
|
29509
29670
|
|
package/package.json
CHANGED
|
@@ -22,11 +22,13 @@ tools:
|
|
|
22
22
|
- "mcp__drm-copilot__run_poshqc_analyze"
|
|
23
23
|
- "mcp__drm-copilot__run_poshqc_test"
|
|
24
24
|
- "mcp__drm-copilot__run_poshqc_analyze_autofix"
|
|
25
|
+
- "mcp__drm-copilot__validate_orchestration_artifacts"
|
|
25
26
|
skills:
|
|
26
27
|
- policy-compliance-order
|
|
27
28
|
- atomic-plan-contract
|
|
28
29
|
- evidence-and-timestamp-conventions
|
|
29
30
|
- acceptance-criteria-tracking
|
|
31
|
+
- execution-environment
|
|
30
32
|
memory: project
|
|
31
33
|
hooks:
|
|
32
34
|
SubagentStop:
|
|
@@ -95,19 +97,28 @@ Concurrent child runs in one session share one session scratchpad, so every scra
|
|
|
95
97
|
|
|
96
98
|
## Preflight Validation
|
|
97
99
|
|
|
98
|
-
|
|
100
|
+
A run is a preflight run when its delegation prompt carries the directive `DIRECTIVE: PREFLIGHT VALIDATION ONLY`. The preflight directive belongs in the delegation prompt, never in a plan file. A directive line left in a plan file does not make an execution run a preflight run. Preflight follows `### Single-Pass Preflight` in the `atomic-plan-contract` skill:
|
|
99
101
|
|
|
100
|
-
-
|
|
101
|
-
-
|
|
102
|
+
- **Review the entire plan in one pass.** Check every phase, task, and prose region; do not stop at the first defect.
|
|
103
|
+
- **Classify every defect.** Trivial defects (stale or misspelled anchors, citation corrections including G11 and G12 findings, typos, literal formatting that does not change what is asserted, evidence filename spelling) are fixed in place. Substantive defects (missing or extra tasks, wrong file set or design, an acceptance criterion without a task, an assertion change, ordering, scope) are returned.
|
|
104
|
+
- **Fix in task text only.** Edit task text and plan preamble in the same plan file. Never add, remove, or reorder tasks. Record every fix in `<FEATURE>/evidence/other/preflight-fixes.<timestamp>.md`.
|
|
105
|
+
- **Return exactly one signal**, `PREFLIGHT: ALL CLEAR` or `PREFLIGHT: REVISIONS REQUIRED`, followed by one `CONVERGENCE:` line and then one line per defect:
|
|
106
|
+
- `PREFLIGHT-FIX: <task id or heading> | <defect class> | <change made>`
|
|
107
|
+
- `PREFLIGHT-DEFECT: <task id or heading> | <defect class> | <required change>`
|
|
108
|
+
- `preflight-fix-record: <path>` when at least one fix was made.
|
|
109
|
+
- `PREFLIGHT: ALL CLEAR` carries no `PREFLIGHT-DEFECT:` line; `PREFLIGHT: REVISIONS REQUIRED` carries at least one and lists every substantive defect found. A plan returns to the planner at most once; do not request or expect a further round.
|
|
110
|
+
- Validate the plan with `mcp__drm-copilot__validate_orchestration_artifacts` (`artifact_type: "plan"`), or with `poetry run python -m scripts.dev_tools.validate_orchestration_artifacts plan <path>` when branch-current rules are required (see the `execution-environment` skill).
|
|
102
111
|
|
|
103
112
|
## Blocking Protocol
|
|
104
113
|
|
|
105
|
-
Blocking is permitted only during preflight validation (before `[P0-T1]`). When preflight-blocked:
|
|
114
|
+
Blocking is permitted only during preflight validation (before `[P0-T1]`). This includes a combined preflight-and-execute run of a proportionate remediation cycle: the run first performs single-pass preflight, fixes trivial defects in place, and stops before `[P0-T1]` only when a substantive defect remains. When preflight-blocked:
|
|
106
115
|
|
|
107
116
|
1. State: `BLOCKED at preflight (before [P0-T1])`.
|
|
108
117
|
2. Provide a short, concrete explanation of why.
|
|
109
|
-
3. Provide a plan delta (exact new or modified task text) that `atomic-planner` can apply, preserving the plan's `[P#-T#]` ID conventions.
|
|
110
|
-
4. Request that `atomic-planner` produce the corrected plan or that the user explicitly approve the delta.
|
|
118
|
+
3. Provide a plan delta (exact new or modified task text) that `atomic-planner` can apply, preserving the plan's `[P#-T#]` ID conventions, with one `PREFLIGHT-DEFECT:` line per substantive defect.
|
|
119
|
+
4. Request that `atomic-planner` produce the corrected plan or that the user explicitly approve the delta. Leave every task unchecked.
|
|
120
|
+
|
|
121
|
+
Report the blocked state with the uppercase `BLOCKED` token: the SubagentStop hook matches only that token, so lowercase or title-case "blocked" prose is not read as a blocked claim.
|
|
111
122
|
|
|
112
123
|
After execution begins, do not block. Continue to completion using allowed micro-actions within the current task.
|
|
113
124
|
|
|
@@ -10,10 +10,12 @@ tools:
|
|
|
10
10
|
- "Edit(artifacts/**)"
|
|
11
11
|
- "Write(docs/**)"
|
|
12
12
|
- "Write(artifacts/**)"
|
|
13
|
+
- "mcp__drm-copilot__validate_orchestration_artifacts"
|
|
13
14
|
skills:
|
|
14
15
|
- policy-compliance-order
|
|
15
16
|
- atomic-plan-contract
|
|
16
17
|
- evidence-and-timestamp-conventions
|
|
18
|
+
- execution-environment
|
|
17
19
|
memory: project
|
|
18
20
|
hooks:
|
|
19
21
|
SubagentStop:
|
|
@@ -45,7 +47,9 @@ Generate plans using the atomic plan contract defined in the `atomic-plan-contra
|
|
|
45
47
|
- Task IDs: `- [ ] [P#-T#] <description>`
|
|
46
48
|
- Sequential task numbering within each phase
|
|
47
49
|
- Phase 0: baseline capture (repo-policy reading tasks + language-specific toolchain baselines)
|
|
48
|
-
- Final phase: full QA loop for each applicable language
|
|
50
|
+
- Final phase: full QA loop for each applicable language, ending with the self-review task that writes `<FEATURE>/evidence/qa-gates/self-review.<timestamp>.md`
|
|
51
|
+
|
|
52
|
+
Every plan is design-level per `## Design-Level Plan Contract (Mandatory)` in the `atomic-plan-contract` skill: tasks name files, symbols, behavior, tests, and acceptance; anchors are symbols, headings, or test names, never line numbers or commit SHAs; literals appear only where they are the asserted value; tool routes and launchers are not restated because the `execution-environment` skill owns them; and a plan above 40 tasks or 400 lines carries a `## Size Justification` section. Every plan carries a `## Pre-Mortem` section with one bullet for each of `Review checklists`, `Coverage`, `Mirror parity`, `File size`, `Test isolation`, `CI-only behavior`, and `Evidence`; the planner SubagentStop hook blocks a plan without it.
|
|
49
53
|
|
|
50
54
|
## Requirements
|
|
51
55
|
|
|
@@ -67,10 +71,14 @@ Concurrent child runs in one session share one session scratchpad, so every plan
|
|
|
67
71
|
|
|
68
72
|
## Preflight Validation
|
|
69
73
|
|
|
70
|
-
Before handing the plan to executor preflight, return the exact bounded line record defined in `atomic-plan-contract`, starting with `PLANNER-INTERNAL-REVIEW: PASS` and ending with the required `PREFLIGHT:` signal. The bounded record must include exactly one passing `CITATION-TO-TREE`, `AC-TRACEABILITY`, and `SCOPE-BOUNDARY` declaration; one or more current-tree `CITATION: <repository-relative path> | <
|
|
74
|
+
Before handing the plan to executor preflight, return the exact bounded line record defined in `atomic-plan-contract`, starting with `PLANNER-INTERNAL-REVIEW: PASS` and ending with the required `PREFLIGHT:` signal. The bounded record must include exactly one passing `CITATION-TO-TREE`, `AC-TRACEABILITY`, and `SCOPE-BOUNDARY` declaration; one or more current-tree `CITATION: <repository-relative path> | <symbol, heading, or test name>` records, none of which uses a line-reference locator; one complete unique `AC-INVENTORY:`; one complete `AC-MAPPING: <ID> | IMPLEMENTATION: <identifier> | TESTS: <identifier> | EVIDENCE: <identifier>` for every and only inventory ID; and exactly one `UNRESOLVED-GAPS: NONE`. A missing, duplicate, malformed, failed, blocked, or out-of-bounds record declaration requires `SELF-REVIEW: BLOCKED` and stops handoff.
|
|
75
|
+
|
|
76
|
+
Before handoff, validate the plan with `mcp__drm-copilot__validate_orchestration_artifacts` (`artifact_type: "plan"`) and correct every finding the validator reports. The installed validator applies only the rules of the installed extension release, as the `execution-environment` skill states.
|
|
71
77
|
|
|
72
78
|
Return the finalized plan for validation-only preflight through `atomic-executor` and preserve the same target file path across revision loops. Do not claim nested worker delegation from within planner execution.
|
|
73
79
|
|
|
80
|
+
Preflight is single-pass (`### Single-Pass Preflight` in `atomic-plan-contract`): the preflight executor applies the rule "Review the entire plan in one pass", fixes trivial defects in place, and returns substantive defects, and a plan returns to the planner at most once. Trivial defects are stale anchors, citation corrections, typos, and formatting that does not change an assertion; Substantive defects are missing or extra tasks, a wrong file set or design, an uncovered acceptance criterion, an assertion change, ordering, and scope. The preflight directive belongs in the delegation prompt, never in a plan file. The preflight return carries `PREFLIGHT-FIX: <task id or heading> | <defect class> | <change made>` lines for fixes, `PREFLIGHT-DEFECT: <task id or heading> | <defect class> | <required change>` lines for returned defects, and `preflight-fix-record: <path>` when a fix was made. When it returns, it carries the full `PREFLIGHT-DEFECT:` list; apply every listed change in one revision of the same file. If the preflight that follows still reports a substantive defect, the orchestrator halts with `blocked_reason: "validator_failed"` rather than requesting another revision.
|
|
81
|
+
|
|
74
82
|
## Output
|
|
75
83
|
|
|
76
84
|
Write the finalized plan to the target path provided by the calling agent. Return the plan path and final preflight signal.
|
|
@@ -14,6 +14,8 @@ tools:
|
|
|
14
14
|
- "Edit(artifacts/orchestration/**)"
|
|
15
15
|
- "Bash(git *)"
|
|
16
16
|
- "Bash(gh *)"
|
|
17
|
+
- "Bash(pwsh -NoProfile -File .claude/lib/ci-gate/Invoke-CiGateParser.ps1*)"
|
|
18
|
+
- "Bash(pwsh -NoProfile -File .claude/lib/ci-gate/Invoke-MergeConfirmationParser.ps1*)"
|
|
17
19
|
- "mcp__drm-copilot__collect_pr_context"
|
|
18
20
|
- "mcp__drm-copilot__validate_orchestration_artifacts"
|
|
19
21
|
skills:
|
|
@@ -161,6 +163,9 @@ Do not report completion until:
|
|
|
161
163
|
|
|
162
164
|
1. Every feature in the manifest has `merge_status: "merged"` or `"worktree_removed"`.
|
|
163
165
|
2. The final integration-to-`main` PR has merged (`epic_merge_pr.merge_commit_sha` recorded).
|
|
166
|
+
`epic_merge_pr.merge_commit_sha` is recorded only after the merge is confirmed by polling and
|
|
167
|
+
ancestry check, because under a merge queue on `main` `gh pr merge` can return before the
|
|
168
|
+
merge happens (issue #952).
|
|
164
169
|
3. `docs/features/epics/<epic-slug>/epic-status.md` reflects the completed state.
|
|
165
170
|
4. The epic checkpoint passes `validate_epic_orchestrator_state_text` with
|
|
166
171
|
`require_complete=True` (no wave-barrier violations, all features merged/removed).
|
|
@@ -33,6 +33,7 @@ skills:
|
|
|
33
33
|
- atomic-plan-contract
|
|
34
34
|
- acceptance-criteria-tracking
|
|
35
35
|
- evidence-and-timestamp-conventions
|
|
36
|
+
- execution-environment
|
|
36
37
|
memory: project
|
|
37
38
|
hooks:
|
|
38
39
|
SubagentStop:
|
|
@@ -126,6 +127,8 @@ Malformed-cycle rules:
|
|
|
126
127
|
- R10: each well-formed outcome's `verdict` must equal the verdict derived from its findings' classes.
|
|
127
128
|
- R11: `opened_by_review`, when present, must be a non-negative integer that indexes an object entry of `review_outcomes` whose `verdict` is `REMEDIATION_REQUIRED`.
|
|
128
129
|
|
|
130
|
+
Remediation mode lives in the inputs file, not in the checkpoint: each `remediation-inputs.<entry-ts>.md` carries exactly one line `Remediation-Mode: proportionate` or `Remediation-Mode: design`, so no checkpoint field is added. A cycle is proportionate when every `autonomous` finding can be fixed without changing a spec acceptance criterion, a public interface, or the item's file inventory beyond the files already in the branch diff plus their tests and mirrors; CI-failure findings are normally proportionate. A proportionate cycle runs one `atomic-planner` delegation and one `atomic-executor` delegation that performs single-pass preflight with in-place trivial fixes and then executes; the orchestrator records `preflight: {iterations: 1, final_status: "clear"}` before `execution_status`, which satisfies the malformed-cycle rule above. When that preflight finds a substantive defect, the executor stops with `BLOCKED at preflight (before [P0-T1])` and no checked task, and the cycle converts to design mode for one planner revision.
|
|
131
|
+
|
|
129
132
|
Cycle-aware `next_step` uses the form `remediation.cycle_N.{plan,preflight,execute,reaudit,exit_check}`, where `N` is `completed_attempts + 1` (the active cycle number) and the sub-step names the current position in the loop; `current_cycle` remains a record position in `cycles[]`.
|
|
130
133
|
|
|
131
134
|
### CI Monitoring and Post-PR Remediation
|
|
@@ -154,7 +157,7 @@ Each cycle produces exactly five artifacts:
|
|
|
154
157
|
|
|
155
158
|
### Preflight Sub-State Semantics
|
|
156
159
|
|
|
157
|
-
`preflight.final_status` is one of `{clear, changes_requested, pending}
|
|
160
|
+
`preflight.final_status` is one of `{clear, changes_requested, pending}`, extended by `blocked_preflight_iteration_limit` as defined in the remediation-handoff skill. A `changes_requested` status routes back to `atomic-planner` for plan revision at most once per cycle, carrying the full `PREFLIGHT-DEFECT:` list; when the confirming preflight still reports a substantive defect, the orchestrator records `blocked_preflight_iteration_limit` and halts the cycle. An `execution_status` in `{in_progress, complete, failed}` recorded while `final_status != clear` is malformed. `preflight.iterations` counts the number of preflight passes performed in the cycle; trivial defects fixed in place by the preflight executor do not add a pass.
|
|
158
161
|
|
|
159
162
|
### Scope-change Rule
|
|
160
163
|
|
|
@@ -22,6 +22,7 @@ tools:
|
|
|
22
22
|
- "Bash(pwsh -NoProfile -File .claude/lib/project-file-merge/Resolve-MergeableConflict.ps1*)"
|
|
23
23
|
- "Bash(pwsh -NoProfile -NonInteractive -File .claude/lib/parallel-drift/Invoke-ParallelDriftDetection.ps1*)"
|
|
24
24
|
- "Bash(pwsh -NoProfile -File .claude/lib/ci-gate/Invoke-CiGateParser.ps1*)"
|
|
25
|
+
- "Bash(pwsh -NoProfile -File .claude/lib/ci-gate/Invoke-MergeConfirmationParser.ps1*)"
|
|
25
26
|
- "Bash(dotnet tool restore*)"
|
|
26
27
|
- "Bash(dotnet csharpier check *)"
|
|
27
28
|
- "Bash(dotnet build *)"
|
|
@@ -287,6 +288,9 @@ In `closed` mode, do not report completion until:
|
|
|
287
288
|
|
|
288
289
|
1. Every non-withdrawn item has `merge_status` of `merged` or `worktree_removed`, each durably
|
|
289
290
|
confirmed by `git` and `gh` rather than by an in-memory notification.
|
|
291
|
+
A `merged` value is recorded only after the merge is confirmed by polling and ancestry check
|
|
292
|
+
(step 3 of the `parallel-orchestrate` skill's `## Per-Item Merge to Main (Merge-on-Green)`),
|
|
293
|
+
because under a merge queue `gh pr merge` exits 0 before the merge happens.
|
|
290
294
|
2. `docs/features/parallel/<slug>/parallel-status.md` has been regenerated a final time and
|
|
291
295
|
reflects the completed state.
|
|
292
296
|
3. The parallel checkpoint passes validation with `require_complete` (the F3 completion gate for
|
|
@@ -9,7 +9,9 @@ tools:
|
|
|
9
9
|
- WebFetch
|
|
10
10
|
- "Write(/docs/features/**/research/**)"
|
|
11
11
|
- "Write(/docs/research/**)"
|
|
12
|
+
skills:
|
|
12
13
|
- evidence-and-timestamp-conventions
|
|
14
|
+
- execution-environment
|
|
13
15
|
memory: project
|
|
14
16
|
hooks:
|
|
15
17
|
SubagentStop:
|
|
@@ -71,6 +73,12 @@ The orchestrator resolves which root to use from whether an active feature folde
|
|
|
71
73
|
|
|
72
74
|
- Propose a test strategy consistent with repository policy without writing test code.
|
|
73
75
|
|
|
76
|
+
### 6. Pre-Mortem
|
|
77
|
+
|
|
78
|
+
- Feature-associated research (a research path under `docs/features/`) MUST carry 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 next review or CI run could fail on that dimension and the mitigation the plan must carry; a label that does not apply is written as "not applicable" followed by the reason.
|
|
79
|
+
- One-off research under `docs/research/` is exempt.
|
|
80
|
+
- `.claude/hooks/validate-task-researcher-output.ps1` blocks feature research without a complete section. The `execution-environment` skill states the CI shape, contract tests, and isolation checks the section accounts for.
|
|
81
|
+
|
|
74
82
|
## Constraints
|
|
75
83
|
|
|
76
84
|
- Write only to the orchestrator-supplied research path under `docs/features/<feature>/research/` (feature-associated) or `docs/research/` (one-off). Do not modify source code or configurations.
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Scope predicate and pull-request selector reader for the epic merge gate (issue #952).
|
|
4
|
+
.DESCRIPTION
|
|
5
|
+
Dot-sourced by enforce-epic-merge-gate.ps1 on both runtimes; this file is byte-identical in
|
|
6
|
+
.claude/hooks and .codex/hooks. Under a merge queue every gh pr merge spelling (--merge, -m,
|
|
7
|
+
--squash, -s, --rebase, -r, --auto, --admin, or no method flag) adds the pull request to the
|
|
8
|
+
queue, and the gh api mutations enqueuePullRequest, enablePullRequestAutoMerge, and
|
|
9
|
+
mergePullRequest and the REST pulls/<n>/merge endpoint also reach the base branch. All of
|
|
10
|
+
them are in scope. A gh pr merge whose only action flag is --disable-auto is out of scope.
|
|
11
|
+
|
|
12
|
+
Pure string logic only: no disk, process, network, clock, or environment access. The file
|
|
13
|
+
dot-sources and imports nothing; it consumes Get-CommandLineInvocation and
|
|
14
|
+
Get-CommandLineStructuralMatch, which the gate loads from hook-command-invocation.ps1 first.
|
|
15
|
+
|
|
16
|
+
Known limitation (issue #952 code review CR-5): the gh api scope reads the command text
|
|
17
|
+
only. A GraphQL mutation supplied from a file (gh api graphql -F query=@mutation.graphql,
|
|
18
|
+
or gh api --input payload.json) is not visible to this text-based scope and is not gated.
|
|
19
|
+
#>
|
|
20
|
+
|
|
21
|
+
# gh pr merge flags that perform or schedule a merge. Any of them keeps a command in scope even
|
|
22
|
+
# when it also carries --disable-auto.
|
|
23
|
+
$script:EpicMergeGateActionFlags = @('--merge', '-m', '--squash', '-s', '--rebase', '-r', '--auto', '--admin')
|
|
24
|
+
|
|
25
|
+
# gh pr merge flags, including the inherited --repo, that consume the following token as a value.
|
|
26
|
+
$script:EpicMergeGateValueFlags = @('-b', '--body', '-F', '--body-file', '-t', '--subject', '-A', '--author-email', '--match-head-commit', '-R', '--repo')
|
|
27
|
+
|
|
28
|
+
# GraphQL mutations that merge, enqueue, or schedule the merge of a pull request.
|
|
29
|
+
$script:EpicMergeGateMutationNames = @('enqueuePullRequest', 'enablePullRequestAutoMerge', 'mergePullRequest')
|
|
30
|
+
|
|
31
|
+
# The REST merge endpoint path; group 1 is the pull-request number.
|
|
32
|
+
$script:EpicMergeGateRestMergePattern = '(?:^|/)pulls/(\d+)/merge(?:$|[^\w-])'
|
|
33
|
+
|
|
34
|
+
function Get-EpicMergeGateFlagName {
|
|
35
|
+
<#
|
|
36
|
+
.SYNOPSIS
|
|
37
|
+
Return the flag name of a dash-led token without any '=value' suffix.
|
|
38
|
+
.OUTPUTS
|
|
39
|
+
System.String
|
|
40
|
+
#>
|
|
41
|
+
[CmdletBinding()]
|
|
42
|
+
[OutputType([string])]
|
|
43
|
+
param([Parameter(Mandatory)][AllowEmptyString()][string] $Token)
|
|
44
|
+
|
|
45
|
+
$split = $Token.IndexOf('=')
|
|
46
|
+
if ($split -gt 0) { return $Token.Substring(0, $split) }
|
|
47
|
+
return $Token
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function ConvertFrom-EpicMergeGateSelector {
|
|
51
|
+
<#
|
|
52
|
+
.SYNOPSIS
|
|
53
|
+
Convert a gh pr merge selector to a pull-request number, or $null.
|
|
54
|
+
.DESCRIPTION
|
|
55
|
+
Accepts an all-digit selector or a URL whose path ends in /pull/<n>. A branch-name
|
|
56
|
+
selector carries no number and yields $null.
|
|
57
|
+
.OUTPUTS
|
|
58
|
+
System.Nullable[int]
|
|
59
|
+
#>
|
|
60
|
+
[CmdletBinding()]
|
|
61
|
+
[OutputType([int])]
|
|
62
|
+
param([Parameter(Mandatory)][AllowEmptyString()][string] $Selector)
|
|
63
|
+
|
|
64
|
+
$digits = $null
|
|
65
|
+
if ($Selector -match '^\d+$') {
|
|
66
|
+
$digits = $Selector
|
|
67
|
+
} elseif ($Selector -match '/pull/(\d+)/?(?:[?#].*)?$') {
|
|
68
|
+
$digits = $Matches[1]
|
|
69
|
+
}
|
|
70
|
+
$number = 0
|
|
71
|
+
if ($null -ne $digits -and [int]::TryParse($digits, [ref] $number)) { return $number }
|
|
72
|
+
return $null
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function Test-EpicMergeGateDisableAutoOnly {
|
|
76
|
+
<#
|
|
77
|
+
.SYNOPSIS
|
|
78
|
+
Report whether a Structural gh pr merge match carries --disable-auto and no action flag.
|
|
79
|
+
.OUTPUTS
|
|
80
|
+
System.Boolean
|
|
81
|
+
#>
|
|
82
|
+
[CmdletBinding()]
|
|
83
|
+
[OutputType([bool])]
|
|
84
|
+
param([Parameter(Mandatory)][pscustomobject] $Match)
|
|
85
|
+
|
|
86
|
+
$tokens = [string[]]@($Match.Segment.Tokens)
|
|
87
|
+
$hasDisableAuto = $false
|
|
88
|
+
for ($index = $Match.OperandIndex; $index -lt $tokens.Count; $index++) {
|
|
89
|
+
$name = Get-EpicMergeGateFlagName -Token $tokens[$index]
|
|
90
|
+
if ($script:EpicMergeGateActionFlags -ccontains $name) { return $false }
|
|
91
|
+
if ($name -ceq '--disable-auto') { $hasDisableAuto = $true }
|
|
92
|
+
}
|
|
93
|
+
return $hasDisableAuto
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function Test-EpicMergeGateApiMutationText {
|
|
97
|
+
<#
|
|
98
|
+
.SYNOPSIS
|
|
99
|
+
Report whether gh api text names a merge or enqueue mutation or the REST merge endpoint.
|
|
100
|
+
.OUTPUTS
|
|
101
|
+
System.Boolean
|
|
102
|
+
#>
|
|
103
|
+
[CmdletBinding()]
|
|
104
|
+
[OutputType([bool])]
|
|
105
|
+
param([Parameter(Mandatory)][AllowEmptyString()][AllowNull()][string] $Text)
|
|
106
|
+
|
|
107
|
+
if ([string]::IsNullOrEmpty($Text)) { return $false }
|
|
108
|
+
foreach ($name in $script:EpicMergeGateMutationNames) {
|
|
109
|
+
if ($Text.IndexOf($name, [System.StringComparison]::OrdinalIgnoreCase) -ge 0) { return $true }
|
|
110
|
+
}
|
|
111
|
+
return [regex]::IsMatch($Text, $script:EpicMergeGateRestMergePattern)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function Test-EpicMergeGateCommandInScope {
|
|
115
|
+
<#
|
|
116
|
+
.SYNOPSIS
|
|
117
|
+
Report whether a command line is a gated merge or enqueue action (issue #952).
|
|
118
|
+
.DESCRIPTION
|
|
119
|
+
True for any gh pr merge match, Structural or Indeterminate, unless the match is Structural
|
|
120
|
+
and its only action flag is --disable-auto; true for any gh api match whose tokens name a
|
|
121
|
+
merge or enqueue mutation or a pulls/<n>/merge path. Text that only mentions these words
|
|
122
|
+
produces no match and stays out of scope. An Indeterminate gh pr merge match stays in scope
|
|
123
|
+
(fail closed).
|
|
124
|
+
.OUTPUTS
|
|
125
|
+
System.Boolean
|
|
126
|
+
#>
|
|
127
|
+
[CmdletBinding()]
|
|
128
|
+
[OutputType([bool])]
|
|
129
|
+
param([Parameter(Mandatory)][AllowEmptyString()][AllowNull()][string] $CommandText)
|
|
130
|
+
|
|
131
|
+
foreach ($match in @(Get-CommandLineInvocation -CommandText $CommandText -CommandWord 'gh' -SubcommandPath @('pr', 'merge'))) {
|
|
132
|
+
if ($match.Status -ne 'Structural' -or -not (Test-EpicMergeGateDisableAutoOnly -Match $match)) { return $true }
|
|
133
|
+
}
|
|
134
|
+
foreach ($match in @(Get-CommandLineInvocation -CommandText $CommandText -CommandWord 'gh' -SubcommandPath @('api'))) {
|
|
135
|
+
if (Test-EpicMergeGateApiMutationText -Text (@($match.Segment.Tokens) -join ' ')) { return $true }
|
|
136
|
+
}
|
|
137
|
+
return $false
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function Get-EpicMergeGateSelectorPrNumber {
|
|
141
|
+
<#
|
|
142
|
+
.SYNOPSIS
|
|
143
|
+
Resolve the pull-request number of a gated merge or enqueue command, or $null.
|
|
144
|
+
.DESCRIPTION
|
|
145
|
+
For gh pr merge, only the first Structural match is read. Value flags are skipped with
|
|
146
|
+
their values, other flags are skipped, an equals-joined --merge=<digits> yields its
|
|
147
|
+
digits (an equals-joined value that is not a number is skipped like any other flag),
|
|
148
|
+
and the first non-flag token (or the token after a bare '--') is the selector.
|
|
149
|
+
For gh api, the number comes from a pulls/<n>/merge token. Any other command yields
|
|
150
|
+
$null, which the gate handles through its no-number branches.
|
|
151
|
+
.OUTPUTS
|
|
152
|
+
System.Nullable[int]
|
|
153
|
+
#>
|
|
154
|
+
[CmdletBinding()]
|
|
155
|
+
[OutputType([int])]
|
|
156
|
+
param([Parameter(Mandatory)][AllowEmptyString()][AllowNull()][string] $CommandText)
|
|
157
|
+
|
|
158
|
+
$match = Get-CommandLineStructuralMatch -CommandText $CommandText -CommandWord 'gh' -SubcommandPath @('pr', 'merge')
|
|
159
|
+
if ($null -ne $match) {
|
|
160
|
+
$tokens = [string[]]@($match.Segment.Tokens)
|
|
161
|
+
$index = $match.OperandIndex
|
|
162
|
+
while ($index -lt $tokens.Count) {
|
|
163
|
+
$token = $tokens[$index]
|
|
164
|
+
if ($token -ceq '--') {
|
|
165
|
+
if ($index + 1 -lt $tokens.Count) { return ConvertFrom-EpicMergeGateSelector -Selector $tokens[$index + 1] }
|
|
166
|
+
return $null
|
|
167
|
+
}
|
|
168
|
+
if ($token.StartsWith('-') -and $token.Length -gt 1) {
|
|
169
|
+
$name = Get-EpicMergeGateFlagName -Token $token
|
|
170
|
+
if ($name -ceq '--merge' -and $token.Length -gt $name.Length) {
|
|
171
|
+
$equalsNumber = ConvertFrom-EpicMergeGateSelector -Selector $token.Substring($name.Length + 1)
|
|
172
|
+
if ($null -ne $equalsNumber) { return $equalsNumber }
|
|
173
|
+
}
|
|
174
|
+
$index += if ($script:EpicMergeGateValueFlags -ccontains $token) { 2 } else { 1 }
|
|
175
|
+
continue
|
|
176
|
+
}
|
|
177
|
+
return ConvertFrom-EpicMergeGateSelector -Selector $token
|
|
178
|
+
}
|
|
179
|
+
return $null
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
foreach ($apiMatch in @(Get-CommandLineInvocation -CommandText $CommandText -CommandWord 'gh' -SubcommandPath @('api'))) {
|
|
183
|
+
foreach ($token in @($apiMatch.Segment.Tokens)) {
|
|
184
|
+
$rest = [regex]::Match([string]$token, $script:EpicMergeGateRestMergePattern)
|
|
185
|
+
$number = 0
|
|
186
|
+
if ($rest.Success -and [int]::TryParse($rest.Groups[1].Value, [ref] $number)) { return $number }
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return $null
|
|
190
|
+
}
|