@danmoisan/drm-copilot-mcp 1.1.24 → 1.1.26
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/package.json +1 -1
- package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +7 -3
- package/resources/claude-customizations/.claude/agents/parallel-planner.md +6 -2
- package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +41 -0
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-cleanup.ps1 +481 -0
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +3 -1
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-cohort-barrier-helpers.ps1 +69 -3
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +2 -2
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.cleanup.ps1 +246 -0
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.docs-only.ps1 +1 -0
- package/resources/claude-customizations/.claude/hooks/hook-cleanup-context.ps1 +343 -0
- package/resources/claude-customizations/.claude/lib/parallel-admission/Invoke-ParallelAdmission.ps1 +626 -0
- package/resources/claude-customizations/.claude/lib/parallel-admission/ParallelAdmission.psm1 +508 -0
- package/resources/claude-customizations/.claude/lib/parallel-admission/ParallelAdmissionJson.psm1 +141 -0
- package/resources/claude-customizations/.claude/lib/parallel-admission/ParallelAdmissionPrecedence.psm1 +508 -0
- package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +17 -1
- package/resources/claude-customizations/.claude/settings.json +1 -0
- package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +1 -1
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +93 -14
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup-worktrees.sh +23 -10
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_lib.sh +54 -46
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_merge_lib.sh +234 -0
- package/resources/claude-customizations/.claude/skills/execution-environment/SKILL.md +15 -5
- package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +71 -7
- package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +26 -2
- package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +82 -12
- package/resources/claude-customizations/pack-manifests/core.json +8 -0
- package/resources/codex-and-agents-customizations/.agents/skills/execution-environment/SKILL.md +15 -5
- package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-cleanup.ps1 +481 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +4 -2
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-cleanup-context.ps1 +343 -0
- package/resources/codex-and-agents-customizations/pack-manifests/core.json +2 -0
- package/resources/customizations/.github/skills/execution-environment/SKILL.md +15 -5
- package/resources/powershell/PoshQC/PoshQC.ScanConfig.psm1 +3 -1
- package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +12 -10
|
@@ -11,6 +11,14 @@ This brief states the environment facts that every researcher, planner, prefligh
|
|
|
11
11
|
|
|
12
12
|
Maintenance rule: this brief is updated in the same change that alters any fact it states. It carries no line numbers and no commit identifiers; it cites files, symbols, headings, job names, and test names. The same text is byte-identical in six locations: `.claude/skills/execution-environment/SKILL.md`, `.agents/skills/execution-environment/SKILL.md`, `.github/skills/execution-environment/SKILL.md`, and their bundled copies under `extensions/drm-copilot/resources/`. Where the Claude and Codex runtimes differ, both paths are named (`.claude/hooks/...` and `.codex/hooks/...`).
|
|
13
13
|
|
|
14
|
+
## Development Toolchain Baseline
|
|
15
|
+
|
|
16
|
+
The host manifest, both devcontainer Dockerfiles, and development CI use Python 3.13.17, Node.js 26.13.0/npm 11.20.0, PowerShell 7.6.9, and Poetry 2.3.2. Shell validation pins shfmt 3.14.1, ShellCheck 0.11.0, and actionlint 1.7.12. Host bootstrap treats manifest versions as minima and preserves equal/newer installations; the container verifier accepts later Python patches within 3.13 and checks the other selected pins.
|
|
17
|
+
|
|
18
|
+
The devcontainer minor image can lag the Python patch, so both Dockerfiles copy the verified official Python runtime stage and select it and NodeSource ahead of older base-feature shims. Full configuration builds include the selected devcontainer features; a raw Dockerfile image alone does not prove feature-provided commands. Runtime verification uses an isolated Linux virtual environment rather than the host Windows environment.
|
|
19
|
+
|
|
20
|
+
Python 3.11/3.12 compatibility jobs, consumer package engines, and independent release-publishing runtime pins remain unchanged. The shared version predicate lives in `scripts/bash/container_versions.sh`; `.devcontainer/verify-container.sh` resolves it relative to its own repository location.
|
|
21
|
+
|
|
14
22
|
## Tool Routes by Agent
|
|
15
23
|
|
|
16
24
|
- `atomic-executor` has no PowerShell tool. Its `tools:` list is Read, Grep, Glob, Edit, Write, several `Bash(...)` entries, the four `mcp__drm-copilot__run_poshqc_*` tools, and `mcp__drm-copilot__validate_orchestration_artifacts`. A `(pattern)` suffix on a `tools:` entry admits the bare tool, so the executor has Bash, subject to the repository hooks and the runtime guard described under Command-Text Restrictions.
|
|
@@ -50,6 +58,8 @@ Two separate mechanisms restrict Bash command text. They are kept apart here bec
|
|
|
50
58
|
- Hooks for an isolated subagent run inside the subagent's worktree with that worktree's hook scripts, which are `main`'s copies. A hook change on a branch is not exercised by isolated subagents until it merges.
|
|
51
59
|
- Hook behavior on a branch is therefore proven by Pester suites, not by a live subagent run. A live check of a branch hook needs a non-isolated delegation from the item worktree.
|
|
52
60
|
- The batch-budget hooks evaluate the checkpoint of the target worktree that `Resolve-HookTargetWorktree` resolves for the edited file, so an edit made from a coordinating session into an item worktree is evaluated against the item worktree's checkpoint. The preimplementation gate (#1010) resolves the file path of a Write or Edit call and the `-C` values and absolute operands of `git add` and `git commit` through the same resolver, and denies when the worktree listing fails or names no worktree; its delegation checks still resolve by portable identity. The PR authoring gate (#1011) resolves the branch that a `gh pr create` or `gh pr edit` command names (`--head`, `--branch`, or a `branch:` label) through the same resolver when the command carries no canonical issue number line, and otherwise keeps its portable-identity and current-branch resolution. The other gates that read `artifacts/orchestration/orchestrator-state.json` are unchanged and still use the root that holds the hook script.
|
|
61
|
+
- Cleanup legs (#1026): a `cleanup-merged-worktrees` run writes no checkpoint, so the preimplementation gate (`.claude/hooks/enforce-orchestration-preimplementation-gate-cleanup.ps1` and its `.codex/hooks/` twin), the PR-authoring gate (`.claude/hooks/enforce-pr-author-skill.cleanup.ps1`), and the model-routing gate (`.claude/hooks/enforce-model-routing-receipt.ps1`) carry allow-side cleanup legs, evaluated only where each gate would otherwise deny, that share the pure predicates of `hook-cleanup-context.ps1`. The legs admit a Write of the session-root manifest `artifacts/orchestration/cleanup-worktrees-manifest.json` with valid content (an Edit stays denied), Write or Edit of paths under `docs/` or `.claude/agent-memory/` and of the pr-author receipt inside the consolidation worktree on branch `documentationandmemories`, `git -C <consolidation root> add` and `commit` of those paths, `Agent(pr-author)` with `branch: documentationandmemories`, and `gh pr create --head documentationandmemories --base main` while a fresh valid manifest exists at the session root and the pushed `refs/remotes/origin/documentationandmemories` resolves to the same commit as the consolidation worktree `HEAD`. A preimplementation-gate denial appends a cleanup sub-code (`Cleanup leg not applied`) only after a cleanup leg has identified the consolidation worktree as the target and a later condition fails; a call rejected by a prefilter keeps the unchanged deny text even when its target is the consolidation worktree, as does every other call.
|
|
62
|
+
- Scratch rule (#1026): the preimplementation gate allows a Write or Edit of an absolute local path that lies outside every registered worktree and the session root and under a temporary root, read through the seam `Get-OrchestrationGateTemporaryRoot` (the long-name `GetTempPath()` value and the `TEMP`, `TMP`, and `TMPDIR` values, which can carry the 8.3 short-name spelling). The rule fails closed when any registered worktree lies under a temporary root.
|
|
53
63
|
- Enforcement hooks do not invoke Python; bash is preferred and PowerShell is acceptable (`tests/scripts/claude-runtime/enforcement-hooks-no-python-invocation.Tests.ps1`).
|
|
54
64
|
|
|
55
65
|
## MCP Surfaces Run the Installed Extension
|
|
@@ -61,14 +71,14 @@ Two separate mechanisms restrict Bash command text. They are kept apart here bec
|
|
|
61
71
|
## CI Shape and Required Checks
|
|
62
72
|
|
|
63
73
|
- `.github/workflows/ci.yml` triggers on `push` to `main` and `development`, on `pull_request` to `main`, `development`, and `epic/**`, on `workflow_dispatch`, and on `merge_group` (`types: [checks_requested]`, added by issue #952), with no path filters. When the merge queue on `main` is enabled, every required check is produced by a `merge_group` run of `ci.yml` as well as by the pull-request run; `.github/workflows/README.md` (`## Triggers`) records the trigger set.
|
|
64
|
-
- Jobs in `ci.yml` and their check names: `Change scope` (job `changes`, the change-scope decision below); `CI full run` (job `full-run-marker`, which runs only on a full run, marks that run as a valid base for later decisions, and is not a required check); `quality-checks7 / Code Quality & Tests (<python-version>)` on Python 3.11, 3.12, and 3.13 (`_quality-checks.yml`: Black check, Ruff, Pyright, the Codex generator `--check`, the tier classification, and Pytest on every version; Pytest with line and branch coverage and the coverage-threshold check on the JSON report totals run on 3.13 only); `security-scan / Security Scanning` (its `safety check` step carries `continue-on-error: true` and does not fail the check); `docs-validation / Documentation Validation`; `build-check / Build Package`; `shell-coverage / Shell Coverage (Bats + kcov)`; `drm-copilot-extension-tests / drm-copilot Extension Tests (<os>)` on `ubuntu-latest` and `windows-latest`; `root-typescript-tests / Root TypeScript Tests (<os>)` on `ubuntu-latest` and `windows-latest`; `NPM Audit Gate / npm audit (<manifest>)` (the calling job carries the name `NPM Audit Gate`);
|
|
74
|
+
- Jobs in `ci.yml` and their check names: `Change scope` (job `changes`, the change-scope decision below); `CI full run` (job `full-run-marker`, which runs only on a full run, marks that run as a valid base for later decisions, and is not a required check); `quality-checks7 / Code Quality & Tests (<python-version>)` on Python 3.11, 3.12, and 3.13 (`_quality-checks.yml`: Black check, Ruff, Pyright, the Codex generator `--check`, the tier classification, and Pytest on every version; Pytest with line and branch coverage and the coverage-threshold check on the JSON report totals run on 3.13 only); `security-scan / Security Scanning` (its `safety check` step carries `continue-on-error: true` and does not fail the check); `docs-validation / Documentation Validation`; `build-check / Build Package`; `shell-coverage / Shell Coverage (Bats + kcov)`; `drm-copilot-extension-tests / drm-copilot Extension Tests (<os>)` on `ubuntu-latest` and `windows-latest`; `root-typescript-tests / Root TypeScript Tests (<os>)` on `ubuntu-latest` and `windows-latest`; `NPM Audit Gate / npm audit (<manifest>)` (the calling job carries the name `NPM Audit Gate`); the `poshqc` group below; and `CI Required Gate` (job `ci-required-gate`, issue #1074), which needs every other `ci.yml` job, runs under `if: always()` on `ubuntu-latest`, and passes `toJSON(needs)` to `scripts/ci/Invoke-CiRequiredGate.ps1`. The gate is green on a full run only when every needed job is `success`, and on a docs-only run only when `CI full run`, `root-typescript-tests`, and `NPM Audit Gate` are `success` or `skipped` and every other needed job is `success`; a `failure`, `cancelled`, or unknown result, a `Change scope` result other than `success`, and unreadable input are red. `tests/scripts/workflows/CiRequiredGateWorkflow.Tests.ps1` pins its `needs:` set against the other job ids of `ci.yml`.
|
|
65
75
|
- PowerShell CI (`_poshqc.yml`): `poshqc / PowerShell QC static` (format and analyze on `windows-latest`); the shard matrix `poshqc / PowerShell QC shard 1`, `shard 2`, and `shard 3` (`Invoke-PoshQCTest -ShardIndex -ShardCount` over the scan folders of `config/poshqc-scan.json`, with coverage, on `windows-latest`); the aggregator `poshqc / PowerShell QC`, which requires the static and shard jobs to succeed, verifies shard completeness against a Pester discovery count, and merges shard coverage; and `poshqc / PowerShell hook suites (Linux)`, which runs only `tests/scripts/claude-hooks` and `tests/scripts/codex-hooks` on `ubuntu-latest` with coverage disabled. A new test file under a scanned folder is assigned to a shard automatically and is counted by the completeness check.
|
|
66
76
|
- Change-scope decision (issue #962): the `Change scope` job runs `scripts/ci/Invoke-CiChangeScope.ps1` and publishes the job output `code`. The decision is `code=false` (docs-only) only on a `pull_request` event from this repository, through one of two comparisons. Green-run base: every file changed since the newest successful `ci.yml` run on the pull-request branch whose `CI full run` job succeeded, and whose head commit is present and an ancestor of the current head, is on the allowlist `config/ci-docs-only-paths.json`; the reason is `DOCS_ONLY_SINCE_<green head sha>`. Merge-base fallback (issue #973): when the green-run step ends with no earlier full green run (`NO_FULL_GREEN_RUN`), a missing base (`BASE_NOT_PRESENT`), or a non-ancestor base (`BASE_NOT_ANCESTOR`), and the pull request's base ref is exactly `main`, the script computes `git merge-base` of the payload base SHA (`BASE_SHA`, from `github.event.pull_request.base.sha`; the base ref arrives as `BASE_REF`) and the head, lists the files changed since that merge base with the same diff arguments, and decides `DOCS_ONLY_SINCE_MERGE_BASE_<merge base sha>` when every changed file is allowlisted. Both comparisons run the diff with rename detection off, so both the old and the new path of a rename are classified. A path is allowlisted when it starts with `docs/features/active/`, `docs/features/archive/`, `docs/features/completed/`, `docs/features/epics/`, `docs/features/parallel/`, `docs/features/potential/`, or `docs/research/`, does not start with `docs/features/templates/` or `docs/features/potential/template.md`, and ends in `.md`, `.txt`, `.log`, `.json`, or `.xml`; the allowlist file itself is not allowlisted. Every other case is a full run (`code=true`): `push`, `merge_group`, and `workflow_dispatch` events, a fork pull request, unreadable run or job data, no earlier full green run or a missing or non-ancestor base when the base ref is not `main`, a merge base that cannot be resolved (`MERGE_BASE_UNRESOLVED`, for example a blank base SHA or a base commit missing from the checkout), a failed ancestry check, an empty diff, any path outside the allowlist, and any error. The decision step carries `continue-on-error: true` and the callers compare the output with `!= 'false'`, so a failed or missing decision also gives a full run.
|
|
67
|
-
- Docs-only behavior (`code=false`): `ci.yml` passes `run-heavy: false` to `_quality-checks.yml`, `_security-scan.yml`, `_build-check.yml`, `_poshqc.yml`, `_shell-coverage.yml`, and `_drm-copilot-extension-tests.yml`. Each
|
|
77
|
+
- Docs-only behavior (`code=false`): `ci.yml` passes `run-heavy: false` to `_quality-checks.yml`, `_security-scan.yml`, `_build-check.yml`, `_poshqc.yml`, `_shell-coverage.yml`, and `_drm-copilot-extension-tests.yml`. Each job that runs with its steps gated still starts under its full-run check name with every step skipped, so it reports `success` without running its suite. In `_poshqc.yml` the aggregator `poshqc / PowerShell QC` runs with every step gated, and `poshqc / PowerShell QC static`, the shard jobs, and `poshqc / PowerShell hook suites (Linux)` are skipped at job level. `docs-validation / Documentation Validation` runs in full. `root-typescript-tests`, `NPM Audit Gate`, and `CI full run` are skipped at job level. Eight currently required contexts therefore never report on a docs-only run: `poshqc / PowerShell QC shard 1`, `poshqc / PowerShell QC shard 2`, `poshqc / PowerShell QC shard 3`, `root-typescript-tests / Root TypeScript Tests (ubuntu-latest)`, `root-typescript-tests / Root TypeScript Tests (windows-latest)`, `NPM Audit Gate / npm audit (.)`, `NPM Audit Gate / npm audit (extensions/drm-copilot)`, and `NPM Audit Gate / npm audit (packages/mcp-server)`, so a docs-only head stays blocked under the 20-context ruleset. `CI Required Gate` passes on a docs-only run, because it accepts `skipped` for exactly those skipped callers. A `success` on a docs-only commit is therefore not evidence that the heavy suites pass for that commit; that evidence is the newest run whose `CI full run` job succeeded.
|
|
68
78
|
- A commit that changes any path outside the allowlist (any code, workflow, configuration, script, test, or customization file) runs the full set of jobs, and its `CI full run` job marks it as a base for later docs-only decisions. A standalone `workflow_dispatch` of a reusable workflow, or a caller that omits `run-heavy`, also runs in full. `.github/workflows/README.md` (`## Change-Scope Decision (Issue #962)`) records the reason codes and the per-context behavior table.
|
|
69
|
-
- Required contexts of ruleset 15241672,
|
|
70
|
-
- Refresh rule: a change that renames a job, adds or removes a matrix entry, or changes the ruleset refreshes this list in the same change, and the orchestrator re-confirms the contexts with a read-only `gh api repos/drmoisan/drm-copilot/rulesets/15241672` call before relying on them.
|
|
71
|
-
- Skipped-check semantics: a job skipped by an `if:` condition reports success to a required check; a workflow that does not run at all reports nothing, which leaves the required check pending.
|
|
79
|
+
- Required contexts of ruleset 15241672, read through a read-only `gh api` call on 2026-11-04 (20 contexts, each with `integration_id` 15368): `drm-copilot-extension-tests / drm-copilot Extension Tests (ubuntu-latest)`, `drm-copilot-extension-tests / drm-copilot Extension Tests (windows-latest)`, `docs-validation / Documentation Validation`, `poshqc / PowerShell QC`, `shell-coverage / Shell Coverage (Bats + kcov)`, `security-scan / Security Scanning`, `quality-checks7 / Code Quality & Tests (3.11)`, `quality-checks7 / Code Quality & Tests (3.12)`, `quality-checks7 / Code Quality & Tests (3.13)`, `build-check / Build Package`, `NPM Audit Gate / npm audit (extensions/drm-copilot)`, `NPM Audit Gate / npm audit (.)`, `NPM Audit Gate / npm audit (packages/mcp-server)`, `root-typescript-tests / Root TypeScript Tests (ubuntu-latest)`, `root-typescript-tests / Root TypeScript Tests (windows-latest)`, `poshqc / PowerShell QC shard 1`, `poshqc / PowerShell QC shard 2`, `poshqc / PowerShell QC shard 3`, `poshqc / PowerShell QC static`, `poshqc / PowerShell hook suites (Linux)`. After the owner's post-merge ruleset edit (issue #1074 runbook), the single required context is `CI Required Gate` (`integration_id` 15368), and the individual job contexts remain visible but are no longer required.
|
|
80
|
+
- Refresh rule: a change that renames a job, adds or removes a `ci.yml` job or a matrix entry, or changes the ruleset refreshes this list in the same change, and the orchestrator re-confirms the contexts with a read-only `gh api repos/drmoisan/drm-copilot/rulesets/15241672` call before relying on them. A new `ci.yml` job must also be added to the `needs:` list of `ci-required-gate`; `tests/scripts/workflows/CiRequiredGateWorkflow.Tests.ps1` fails until it is.
|
|
81
|
+
- Skipped-check semantics: a job skipped by an `if:` condition reports success to a required check; a workflow that does not run at all reports nothing, which leaves the required check pending. A matrix job skipped at job level reports no expanded context (its matrix name is never expanded), and a reusable-workflow caller skipped in `ci.yml` reports no nested contexts, so each such required context stays pending.
|
|
72
82
|
- A pull request into a branch other than `main`, `development`, or `epic/**` gets no CI run; dispatch `ci.yml` manually for it.
|
|
73
83
|
|
|
74
84
|
## CI-Only Failure Classes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: parallel-add
|
|
3
3
|
description: Admit one new item into a running parallel run — preparation via a preparation-mode child orchestrator run, conflict-edge computation against all items including in-flight ones, and the admission decision that either places the item in the current cohort or defers it and recolors the unstarted subgraph. Appends exactly one mutations[] entry. In-flight items are never moved.
|
|
4
|
-
argument-hint: "[issue|potential-entry]"
|
|
4
|
+
argument-hint: "[issue|potential-entry] [--after <earlier>] [--band <Cn>]"
|
|
5
5
|
context: fork
|
|
6
6
|
agent: parallel-orchestrator
|
|
7
7
|
---
|
|
@@ -28,7 +28,9 @@ this operation may and may not disturb. Read that section before applying anythi
|
|
|
28
28
|
`/parallel-run` for that.
|
|
29
29
|
- `$ARGUMENTS` names exactly one item: a GitHub issue number or reference, or a path to an entry
|
|
30
30
|
under `docs/features/potential/`. An argument naming more than one item is rejected; admit one
|
|
31
|
-
item per invocation so each admission decision and its mutation entry stay attributable.
|
|
31
|
+
item per invocation so each admission decision and its mutation entry stay attributable. The
|
|
32
|
+
`--after <earlier>` and `--band <Cn>` flags are not items, so the multi-item rejection applies to
|
|
33
|
+
positional items only.
|
|
32
34
|
- The run-existence check is evaluated first, before any argument-shape check: a pending or
|
|
33
35
|
not-started run, and a run whose `parallel_slug` no checkpoint tracks, are rejected before the
|
|
34
36
|
argument is examined.
|
|
@@ -37,6 +39,15 @@ this operation may and may not disturb. Read that section before applying anythi
|
|
|
37
39
|
the run's slug is known, put the line `parallel_slug: <slug>` before the signal, and end the
|
|
38
40
|
final output with the literal line `PARALLEL_MUTATION_REJECTED: run_not_started` as its last
|
|
39
41
|
line, with no formatting and no trailing text.
|
|
42
|
+
- After the run-existence check passes, apply the closed-run guard in code. Read the manifest mode
|
|
43
|
+
with `bash .claude/lib/bash/validate-parallel-manifest.sh --print-mode <manifest-path>`, then run
|
|
44
|
+
`pwsh -NoProfile -NonInteractive -File .claude/lib/parallel-admission/Invoke-ParallelAdmission.ps1 guard-run -CheckpointPath artifacts/orchestration/parallel-orchestrator-state.json -ManifestMode <mode>`.
|
|
45
|
+
The guard rejects when either mode is `closed`, when a `mutations[]` entry has `op` `close`, or
|
|
46
|
+
when the two modes disagree. On exit 1, stop with the helper's stderr line
|
|
47
|
+
(`PARALLEL_ADMISSION_REJECTED: run_closed: <detail>`) as the reported reason, change no state,
|
|
48
|
+
and emit no mutation rejection signal: `run_closed` is an admission rejection code defined in
|
|
49
|
+
`## Prepared-Item Admission (issue #1047)` of `.claude/rules/parallel-orchestration.md`, not a
|
|
50
|
+
mutation rejection code.
|
|
40
51
|
- A closed run and an argument naming more than one item are rejected only after the run-existence
|
|
41
52
|
check, while the run's checkpoint exists; each of these rejections emits no rejection signal, and
|
|
42
53
|
the stop validates against that checkpoint.
|
|
@@ -61,13 +72,39 @@ re-derivation is mandatory and is not an optimization to skip when the checkpoin
|
|
|
61
72
|
1. **Enter `proposed`.** Add the item to `items[]` in state `proposed` with its `issue_num` as the
|
|
62
73
|
primary key. Item keys are integers throughout this surface; there is no string key.
|
|
63
74
|
|
|
64
|
-
2. **Prepare the item.**
|
|
75
|
+
2. **Prepare the item.** First assess how far the item's pushed branch is already prepared:
|
|
76
|
+
`pwsh -NoProfile -NonInteractive -File .claude/lib/parallel-admission/Invoke-ParallelAdmission.ps1 assess -Branch origin/<item branch> -FeatureFolder <feature folder> -PlannerCheckpointPath artifacts/orchestration/parallel-planner-state.json`,
|
|
77
|
+
adding `-Band <Cn>` when the operator passed `--band`. The helper reads the branch by ref, selects
|
|
78
|
+
the newest preparation receipt or infers the stage from the branch files, compares the files the
|
|
79
|
+
plan cites against `origin/main` since the base commit, and prints `next_action`.
|
|
80
|
+
- When `next_action` is `admit_prepared` (stage `cleared`, verdict `fresh`), run no preparation
|
|
81
|
+
child, no preflight, and no plan revision. Record the output's `preparation_status`,
|
|
82
|
+
`plan_hash`, `base_commit`, `complexity_band` (the `band.value`), and `band_source` (the
|
|
83
|
+
`band.source`) on the item, and continue with step 3.
|
|
84
|
+
- Otherwise delegate the preparation child described below on the item's pushed branch, not on
|
|
85
|
+
a new branch, and append after the unchanged kickoff line the resume line
|
|
86
|
+
`Preparation resume: stage <stage>. Existing artifacts: <paths>. Do not repeat a completed stage; supersede with new timestamped files.`
|
|
87
|
+
with `<stage>` set to the output's `resume_stage` and `<paths>` listing the existing
|
|
88
|
+
`research_path`, `spec_path`, and `plan_path` relative to the feature folder. A stale item
|
|
89
|
+
(verdict `stale`) resumes at preflight with the output's `changed_cited_paths` as the findings,
|
|
90
|
+
under the single-pass rule of `.claude/skills/orchestrate/SKILL.md` `## Delegation Model`
|
|
91
|
+
(trivial defects fixed in place, one planner revision for substantive defects, and a halt with
|
|
92
|
+
the defect list when a second round still fails). A plan that never cleared preflight always
|
|
93
|
+
runs preflight. A contract change found by that preflight, or a `premise_falsified` verdict
|
|
94
|
+
(a cited path removed on `main`), resumes at `plan`: the new plan is a new timestamped file,
|
|
95
|
+
and no superseded artifact is deleted.
|
|
96
|
+
- The band source order is `--band` (`band_source: caller`), then the planner checkpoint item's
|
|
97
|
+
`complexity_band` (`planner_checkpoint`), then the `## Complexity Assessment` procedure below
|
|
98
|
+
(`assessment`).
|
|
99
|
+
|
|
100
|
+
Otherwise run preparation through a preparation-mode child `Agent(orchestrator)`
|
|
65
101
|
run, reusing the existing `route_id: preparation` contract UNCHANGED: promotion, research,
|
|
66
102
|
`spec.md`, `user-story.md`, the atomic plan, and preflight clearance. Do not fork a variant
|
|
67
103
|
contract for parallel admission. Preparation yields the item's DECLARED blast radius, and only
|
|
68
104
|
the planner-computed declared radius is authoritative for scheduling. The item's lifecycle
|
|
69
105
|
advances `proposed` -> `admitted` -> `prepared` during this step, recorded as item-state updates in
|
|
70
|
-
`items[]` with the checkpoint's lifecycle timestamps.
|
|
106
|
+
`items[]` with the checkpoint's lifecycle timestamps. When the band source is `assessment`, after
|
|
107
|
+
the admitted item's preflight
|
|
71
108
|
clearance, perform the `parallel-plan` skill's `## Complexity Assessment` procedure for it, and
|
|
72
109
|
record the resulting `complexity_band` on the admitted orchestrator-checkpoint item so step 3's
|
|
73
110
|
edge derivation and the parent's model routing read the same band.
|
|
@@ -125,6 +162,11 @@ re-derivation is mandatory and is not an optimization to skip when the checkpoin
|
|
|
125
162
|
`qualifies for combination; not combined (combination applies at planning time only)`. This
|
|
126
163
|
step never combines items: it adds no checkpoint field and makes no `mutations[]` change for a
|
|
127
164
|
qualifying pair.
|
|
165
|
+
Record each `--after <earlier>` flag as one top-level `precedence[]` entry
|
|
166
|
+
`{before, after, source, recorded_at}` with `before` the earlier item, `after` the candidate,
|
|
167
|
+
`source` `operator`, and `recorded_at` the current UTC minute. Each precedence pair is a
|
|
168
|
+
separating input, never a dependency key: add it to the edges passed to steps 4 and 5 as one
|
|
169
|
+
more `<a>:<b>` edge with `a < b`, so the coloring always separates the pair.
|
|
128
170
|
|
|
129
171
|
4. **Decide admission.** Call the bundled entry point, which needs no Python interpreter:
|
|
130
172
|
|
|
@@ -166,12 +208,23 @@ re-derivation is mandatory and is not an optimization to skip when the checkpoin
|
|
|
166
208
|
`.claude/skills/parallel-orchestrate/SKILL.md` — so the current cohort durably holds `scheduled`
|
|
167
209
|
members that a candidate can contend with.
|
|
168
210
|
|
|
211
|
+
A candidate with an active unmerged predecessor (a `precedence[]` entry whose `before` item has a
|
|
212
|
+
`merge_status` other than `merged` or `worktree_removed` and a `state` other than `withdrawn`) is
|
|
213
|
+
forced to `defer_and_recolor` even when `admit` prints `admit_current_cohort`.
|
|
214
|
+
|
|
169
215
|
A conflict with an unstarted member of the CURRENT cohort defers the candidate and recolors,
|
|
170
216
|
because the next `max_concurrency` batch would otherwise launch the two concurrently. A conflict
|
|
171
217
|
with an unstarted item OUTSIDE the current cohort does not defer: the cohort barrier keeps the
|
|
172
218
|
two from running concurrently, so the coloring's existing separation already resolves it.
|
|
173
219
|
|
|
174
|
-
5. **Apply the recolor result.**
|
|
220
|
+
5. **Apply the recolor result.** Before writing, pass the recolor result through the precedence
|
|
221
|
+
lift: `pwsh -NoProfile -NonInteractive -File .claude/lib/parallel-admission/Invoke-ParallelAdmission.ps1 order-cohorts -Cohorts <table-json> -Edges "<a>:<b> ..." -Precedence "<before>:<after> ..." -Pinned "<k> ..." -Floor <current_cohort>`,
|
|
222
|
+
which moves an unstarted `after` item above its `before` items and never moves a pinned item.
|
|
223
|
+
After writing, and before step 6 appends the mutation entry, run
|
|
224
|
+
`pwsh -NoProfile -NonInteractive -File .claude/lib/parallel-admission/Invoke-ParallelAdmission.ps1 test-cohorts -CheckpointPath artifacts/orchestration/parallel-orchestrator-state.json`;
|
|
225
|
+
on exit 1 (`precedence_violated`, `precedence_cycle`, or `precedence_unknown_item`), restore the
|
|
226
|
+
prior `cohorts[]` and `recolor_generation` and stop with the helper's stderr line.
|
|
227
|
+
Write the recolor output field `cohort_assignments` (as lifted) into
|
|
175
228
|
`cohorts[]` and set the top-level `recolor_generation` to the output field `generation`. The
|
|
176
229
|
result's key set equals the
|
|
177
230
|
unstarted set exactly and contains no pinned key: no in-flight item changes cohort or state as a
|
|
@@ -216,12 +269,23 @@ re-derivation is mandatory and is not an optimization to skip when the checkpoin
|
|
|
216
269
|
"parallel-orchestrator-state"`. A non-empty error list means the admission was applied
|
|
217
270
|
incorrectly; correct the checkpoint rather than proceeding.
|
|
218
271
|
|
|
272
|
+
8. **Rewrite the durable scheduling record.** Build the record content with
|
|
273
|
+
`pwsh -NoProfile -NonInteractive -File .claude/lib/parallel-admission/Invoke-ParallelAdmission.ps1 record -RunFolder docs/features/parallel/<slug> -Entry <entry-json>`,
|
|
274
|
+
where the entry carries the checkpoint's `conflict_edges`, `tolerated_overlaps`, `precedence`,
|
|
275
|
+
and `items`. The helper prints the content and makes no git write. Write it to
|
|
276
|
+
`docs/features/parallel/<slug>/parallel-scheduling.json` on `parallel/<slug>-plan` and commit it
|
|
277
|
+
with a pathspec under `docs/features/parallel/`, so a re-seed from another checkout reads the
|
|
278
|
+
recorded edges and plan hashes by ref.
|
|
279
|
+
|
|
219
280
|
## Constraints
|
|
220
281
|
|
|
221
282
|
- One admission per invocation, one `mutations[]` entry per successful admission. A failed
|
|
222
283
|
preparation appends no entry and leaves `items[]` without the candidate.
|
|
223
|
-
- No field and no enum member is added to `mutations[]
|
|
224
|
-
|
|
284
|
+
- No field and no enum member is added to `mutations[]` or any state or merge-status enum. The only
|
|
285
|
+
fields added to `items[]` are the four tolerated fields `preparation_status`, `plan_hash`,
|
|
286
|
+
`base_commit`, and `band_source` declared in `## Prepared-Item Admission (issue #1047)` of
|
|
287
|
+
`.claude/rules/parallel-orchestration.md`, which also declares the top-level `precedence[]` list
|
|
288
|
+
this skill records. A `conflict_edges[]` entry may carry only the three tolerated extra fields `hard`, `cost`,
|
|
225
289
|
and `benefit` (tolerated-not-validated, returned by the scheduling entry point), and no reason
|
|
226
290
|
member is added: the four `conflict_edges[].reason` members are unchanged. The nine parallel
|
|
227
291
|
enums are owned by `.claude/rules/parallel-orchestration.md` and are consumed, never extended.
|
|
@@ -129,6 +129,16 @@ completion notification. A blocked item (`blocked_ci_loop_limit` or `blocked_dri
|
|
|
129
129
|
`merged` nor `worktree_removed`, so it holds every conflicting later-cohort neighbour and,
|
|
130
130
|
transitively, the tail of its own conflict component; items outside that component are unaffected.
|
|
131
131
|
|
|
132
|
+
**Precedence.** An item named as `after` in an active `precedence[]` entry (the operator ordering
|
|
133
|
+
input declared in `## Prepared-Item Admission (issue #1047)` of
|
|
134
|
+
`.claude/rules/parallel-orchestration.md`) may start only when its `before` item has `merge_status`
|
|
135
|
+
`merged` or `worktree_removed`, whatever the two items' cohorts. A `withdrawn` predecessor releases
|
|
136
|
+
the constraint, and a `blocked` predecessor holds its dependent. Layer 1 enforces this rule through
|
|
137
|
+
`Test-ParallelCohortBarrierClear` in `.claude/hooks/enforce-parallel-cohort-barrier-helpers.ps1`,
|
|
138
|
+
which denies a target whose predecessor is not released and fails closed on a missing predecessor
|
|
139
|
+
record. Layer 2 does not check precedence: the Python orchestrator-state validator reads
|
|
140
|
+
`conflict_edges[]` only.
|
|
141
|
+
|
|
132
142
|
**`current_cohort` is a progress indicator, not a gate.** `current_cohort` is the LOWEST
|
|
133
143
|
current-generation cohort index that still contains a non-terminal, non-withdrawn item. It is
|
|
134
144
|
recomputed and written only on durable confirmation from `git worktree list --porcelain`,
|
|
@@ -265,6 +275,10 @@ carries exactly these five elements.
|
|
|
265
275
|
execution from that plan rather than re-running promotion, research, or planning. The item's
|
|
266
276
|
prepared feature folder and approved atomic plan are already committed and preflight-clear on the
|
|
267
277
|
item's own pushed feature branch.
|
|
278
|
+
The prompt also carries the item's admitted plan hash as `plan-hash: <hex>` and instructs the child, before any other step, to run `git rev-parse HEAD:<plan-path>` and to stop with `blocked_reason: premise_falsified` when the printed hash differs from `<hex>`.
|
|
279
|
+
The `<hex>` value is the item's `plan_hash` from the orchestrator checkpoint item, else the
|
|
280
|
+
kickoff `## Integrity` row for its plan path. The check runs before the child reconciles with
|
|
281
|
+
`origin/main`, so a plan that changed after admission never reaches atomic execution.
|
|
268
282
|
The execution child starts a new checkpoint in its own worktree, and the preparation checkpoint
|
|
269
283
|
does not carry over, so the prompt also instructs the child to verify the item's GitHub issue
|
|
270
284
|
read-only (gh issue view), not to call `potential_to_issue` or the promotion-entry tool, and to
|
|
@@ -404,6 +418,15 @@ Procedure, per item:
|
|
|
404
418
|
CI-dependent acceptance criteria. When either check fails, do not record
|
|
405
419
|
`merge_status: ci_green` and do not run `gh pr merge`; the item waits until its child pushes
|
|
406
420
|
the check-off and re-runs S9, and the parent does not commit the check-off itself.
|
|
421
|
+
**Turn gap.** A child can end its turn with its pull request open and its CI green gate still
|
|
422
|
+
pending. On every child completion, read the child checkpoint
|
|
423
|
+
`<worktree>/artifacts/orchestration/orchestrator-state.json`, with the worktree path located by
|
|
424
|
+
`git worktree list --porcelain`. When its `step9_status` is not `passed` or its `blocked_reason`
|
|
425
|
+
is `awaiting_ci`, keep `merge_status: pr_open` and treat the item as not done: poll
|
|
426
|
+
`gh pr checks` through the parser above until the conclusion is terminal, then
|
|
427
|
+
re-delegate the child once to resume at the CI green gate, by the same re-delegation mechanism as
|
|
428
|
+
`## Per-Item Merge-Conflict Handling`; a CI-failure cycle counts toward `remediation_loop`.
|
|
429
|
+
Record `ci_green` only after that resumed run reports its CI green gate `passed`.
|
|
407
430
|
3. Execute `gh pr merge --merge <PR>` for that item's pull request, whose base is `main`.
|
|
408
431
|
Do not pass `--delete-branch` or `--auto`. A zero exit status does not prove a merge: when
|
|
409
432
|
`main` uses a merge queue, `gh pr merge` exits 0 after it enqueues the pull request or enables
|
|
@@ -711,8 +734,9 @@ This section is consumption documentation only. The checkpoint schema is owned b
|
|
|
711
734
|
as prose invariants in `.claude/rules/parallel-orchestration.md`, and enforced by
|
|
712
735
|
`scripts/dev_tools/validate_parallel_orchestrator_state.py`. Consume that schema;
|
|
713
736
|
add no field to it that `.claude/rules/parallel-orchestration.md` does not declare,
|
|
714
|
-
and extend no enum in it.
|
|
715
|
-
|
|
737
|
+
and extend no enum in it. The declared optional item fields are `mergeable_conflicts_resolved`,
|
|
738
|
+
`preparation_status`, `plan_hash`, `base_commit`, and `band_source`, and the declared optional
|
|
739
|
+
top-level field is `precedence[]` (`## Prepared-Item Admission (issue #1047)` of the rule).
|
|
716
740
|
|
|
717
741
|
Fields `parallel-orchestrator` writes to `artifacts/orchestration/parallel-orchestrator-state.json`:
|
|
718
742
|
`objective`, `route_id: "parallel"`, `parallel_slug`, `parallel_manifest_path`,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: parallel-plan
|
|
3
3
|
description: Prepare a set of thematically unrelated items for concurrent execution before any execution begins - item intake over issue numbers and potential-entry paths, concurrent preparation-mode child orchestrator delegations, blast-radius computation and V1-V3 validation, cohort seeding with a recomputation-parity check, run-manifest and planner-checkpoint authoring, and the parallel-orchestrator kickoff artifact.
|
|
4
|
-
argument-hint: "[items: issue numbers and/or potential-entry paths]"
|
|
4
|
+
argument-hint: "[items: issue numbers and/or potential-entry paths] [--after <later>:<earlier> ...]"
|
|
5
5
|
context: fork
|
|
6
6
|
agent: parallel-planner
|
|
7
7
|
---
|
|
@@ -16,7 +16,8 @@ $ARGUMENTS
|
|
|
16
16
|
This skill frames work for the `parallel-planner` agent, parallel to how
|
|
17
17
|
`.claude/skills/epic-plan/SKILL.md` frames work for `epic-planner`. The `parallel` surface
|
|
18
18
|
schedules thematically unrelated items by computed blast-radius contention: there is no worthiness
|
|
19
|
-
assessment, no operator-supplied ordering
|
|
19
|
+
assessment, no operator-supplied ordering beyond the optional `--after <later>:<earlier>`
|
|
20
|
+
precedence flags, and no shared branch into which item work merges.
|
|
20
21
|
Planning ends at preflight clearance and cohort seeding; no atomic execution, PR authoring, or CI
|
|
21
22
|
monitoring occurs under this skill.
|
|
22
23
|
|
|
@@ -62,13 +63,29 @@ identical forms.
|
|
|
62
63
|
- **`kind`.** Record `kind: feature | bug` at intake from the item source (issue labels, or the
|
|
63
64
|
potential entry's declared kind). When the source is indeterminate, default to `feature` and note
|
|
64
65
|
the choice `[recommendation, not upstream-constrained]`.
|
|
66
|
+
- **Admission assessment.** Run the same `assess` subcommand `/parallel-add` step 2 runs for every
|
|
67
|
+
item whose branch is pushed:
|
|
68
|
+
`pwsh -NoProfile -NonInteractive -File .claude/lib/parallel-admission/Invoke-ParallelAdmission.ps1 assess -Branch origin/<item branch> -FeatureFolder <feature folder>`.
|
|
69
|
+
An item with no pushed branch (an unpromoted potential entry) takes `full_preparation`. Fan-out
|
|
70
|
+
takes only the items whose `next_action` is not `admit_prepared`. An item whose `next_action` is
|
|
71
|
+
`admit_prepared` (stage `cleared`, verdict `fresh`) runs no preparation child: record its
|
|
72
|
+
`plan_path`, `research_path`, `plan_hash`, `base_commit`, `branch_name`, and
|
|
73
|
+
`preflight_status: PREFLIGHT: ALL CLEAR` from the branch, set `preparation_status: prepared`
|
|
74
|
+
(the planner ready value that corresponds to the admission stage `cleared`), and record
|
|
75
|
+
`topology_receipt` as not applicable, because no preparation child ran for it.
|
|
76
|
+
- **Precedence input.** Record each `--after <later>:<earlier>` flag as one top-level
|
|
77
|
+
`precedence[]` entry `{before, after, source, recorded_at}` with `source` `operator`, as
|
|
78
|
+
declared in `## Prepared-Item Admission (issue #1047)` of `.claude/rules/parallel-orchestration.md`.
|
|
79
|
+
The flags are optional and are never requested.
|
|
65
80
|
|
|
66
81
|
The operator is never asked for ordering edges, cohort assignments, or a worthiness verdict.
|
|
67
82
|
Intake proceeds directly to preparation fan-out.
|
|
68
83
|
|
|
69
84
|
## Preparation Fan-Out
|
|
70
85
|
|
|
71
|
-
One preparation-mode `Agent(orchestrator)` run per item
|
|
86
|
+
One preparation-mode `Agent(orchestrator)` run per incomplete item, that is, per item whose
|
|
87
|
+
`assess` `next_action` is not `admit_prepared`; the waves below cover the incomplete items only.
|
|
88
|
+
Preparation produces documents and plans
|
|
72
89
|
rather than code, and items carry no ordering constraint, so preparations may run concurrently —
|
|
73
90
|
but they are BOUNDED, not unbounded.
|
|
74
91
|
|
|
@@ -84,6 +101,8 @@ JSON array of arrays, returns the batches in order, and sorts the keys itself, s
|
|
|
84
101
|
does not depend on caller ordering. Launch wave *k* as one message carrying that wave's `Agent`
|
|
85
102
|
calls, each `isolation: "worktree"` and `run_in_background: true`.
|
|
86
103
|
Create each preparation worktree's branch from `origin/main`.
|
|
104
|
+
A resumed item (`next_action` `resume_preparation`) instead runs on its pushed branch, as
|
|
105
|
+
`## Issue Combination` step 3 does, so its completed stages stay on that branch.
|
|
87
106
|
Launch wave *k+1* only after every child of wave *k* has TERMINATED — not merely reported
|
|
88
107
|
progress. All of this happens inside a single `/parallel-plan` invocation with no operator action
|
|
89
108
|
between waves.
|
|
@@ -107,13 +126,18 @@ invocations after the initial plan. Use `/parallel-plan` for intake and `/parall
|
|
|
107
126
|
admit an item into a run that is already in flight.
|
|
108
127
|
|
|
109
128
|
Each delegation prompt includes this literal kickoff line, followed by the model-budget marker
|
|
110
|
-
line
|
|
129
|
+
line, for an issue-number item only, the issue-adoption line, for a resumed item only, the
|
|
130
|
+
preparation-resume line, and the preparation-receipt line:
|
|
111
131
|
|
|
112
132
|
> `Preparation mode: true. route_id: preparation. parallel_slug: <slug>. Perform promotion, research, feature documents (spec.md, user-story.md), atomic planning, and preflight clearance only. Atomic execution, PR authoring, and CI monitoring are out of scope for this run and are executed later by parallel-orchestrator. After the atomic-executor preflight returns PREFLIGHT: ALL CLEAR, commit the feature folder and plan to the current branch, push the current branch to origin, set out-of-scope step statuses to not-applicable, set next_step to S5_atomic_execution, and stop, reporting the plan-path and preflight status.`
|
|
113
133
|
>
|
|
114
134
|
> `model_budget.fable_policy: <disabled|available|preferred>.`
|
|
115
135
|
>
|
|
116
136
|
> `Issue adoption: this item's GitHub issue already exists. Verify it read-only (gh issue view), do not call potential_to_issue or the promotion-entry tool, and record a top-level issue_adoption object in the checkpoint per .claude/rules/orchestrator-state.md with origin filed_before_orchestration (or transferred when the issue was transferred), waiving potential_to_issue and the promotion-entry tool for the checkpoint's promotion-type. When a lifecycle record for the item exists under docs/features/potential/promoted/, cite it as potential_record.`
|
|
137
|
+
>
|
|
138
|
+
> `Preparation resume: stage <stage>. Existing artifacts: <paths>. Do not repeat a completed stage; supersede with new timestamped files.`
|
|
139
|
+
>
|
|
140
|
+
> `Preparation receipt: before the commit, write <feature folder>/evidence/other/preparation-receipt.<yyyy-MM-ddTHH-mm>.json with schema_version, stage, research_path, spec_path, plan_path, plan_hash, base_commit, preflight_status, and recorded_at.`
|
|
117
141
|
|
|
118
142
|
Properties of that line, each individually load-bearing:
|
|
119
143
|
|
|
@@ -144,6 +168,21 @@ to execution, so the execution child records its own adoption (see
|
|
|
144
168
|
creates and commits the feature folder, the execution child's adoption also waives
|
|
145
169
|
`new_active_feature_folder` and records `feature_folder_record` for that committed folder.
|
|
146
170
|
|
|
171
|
+
**Preparation-resume line.** The preparation-resume line is emitted only for a resumed item, after
|
|
172
|
+
the issue-adoption line (or after the model-budget marker line for a potential-entry item). Its
|
|
173
|
+
`<stage>` is the `assess` `resume_stage`, and its `<paths>` are the existing `research_path`,
|
|
174
|
+
`spec_path`, and `plan_path` written relative to the feature folder. The line carries no mode
|
|
175
|
+
marker and no active feature-folder path and does not match the hook issue-number pattern, so hook
|
|
176
|
+
target resolution and mode classification are unchanged. A stale item resumes at preflight with
|
|
177
|
+
the `assess` `changed_cited_paths` as findings under the unchanged single-pass rule of
|
|
178
|
+
`.claude/skills/orchestrate/SKILL.md` `## Delegation Model`; a falsified premise resumes at `plan`,
|
|
179
|
+
and a superseded artifact is replaced by a new timestamped file and never deleted.
|
|
180
|
+
|
|
181
|
+
**Preparation-receipt line.** The preparation-receipt line is emitted for every delegated item. The
|
|
182
|
+
child resolves `<feature folder>` to its own folder and writes the receipt declared in
|
|
183
|
+
`## Prepared-Item Admission (issue #1047)` of `.claude/rules/parallel-orchestration.md` before its
|
|
184
|
+
commit, so a later `assess` reads the stage, plan hash, and base commit from the branch.
|
|
185
|
+
|
|
147
186
|
**No edit to shared surfaces.** No edit is made to `.claude/skills/orchestrate/SKILL.md` or to
|
|
148
187
|
`config/orchestration-routing.json`, including the `preparation` route. The route mechanism is
|
|
149
188
|
marker-driven; the child contract's "commit ... to the current branch" wording is satisfied by a
|
|
@@ -437,7 +476,13 @@ The library returns the partition; the planner supplies the record fields.
|
|
|
437
476
|
(hard classes, integer cost, pairwise benefit, and the configured `conflict_tolerance`). It
|
|
438
477
|
returns `edges` and `tolerated_overlaps`. The -Relation argument is required; pass the facade's
|
|
439
478
|
Test-BlastRadiusConflict function object as shown. Pass the returned `edges` pairs as
|
|
440
|
-
`--edges "<a>:<b> ..."` and the item keys as `--keys "<k1> <k2> ..."`.
|
|
479
|
+
`--edges "<a>:<b> ..."` and the item keys as `--keys "<k1> <k2> ..."`. Add each recorded
|
|
480
|
+
`precedence[]` pair to `--edges` as one more separating `<a>:<b>` edge with `a < b`, so the
|
|
481
|
+
coloring always separates the pair. Then pass the coloring through the precedence lift:
|
|
482
|
+
`pwsh -NoProfile -NonInteractive -File .claude/lib/parallel-admission/Invoke-ParallelAdmission.ps1 order-cohorts -Cohorts <compute-cohorts output> -Edges "<a>:<b> ..." -Precedence "<before>:<after> ..."`.
|
|
483
|
+
No item has started at seeding, so the call passes no option that holds an item in place, and
|
|
484
|
+
its `cohorts` output is the table steps 3 and 5 record. A `precedence_cycle` or
|
|
485
|
+
`precedence_unknown_item` rejection (exit 1) stops the run with the helper's stderr line.
|
|
441
486
|
The detection relation inside the entry point contributes no `path_overlap` edge for a path
|
|
442
487
|
matching the truth table's optional `mergeable_paths` list, and the path stays in the declared
|
|
443
488
|
radius. When `Test-BlastRadiusConflict` is called directly (for example, while investigating a
|
|
@@ -482,6 +527,18 @@ The library returns the partition; the planner supplies the record fields.
|
|
|
482
527
|
(the bash port of `compute_concurrency_batches(cohort_item_keys, max_concurrency)`), which fills
|
|
483
528
|
slots in ascending item-key order. Recoloring under add, remove, or drift mutation is F6 and F8
|
|
484
529
|
scope. This skill performs seeding only.
|
|
530
|
+
7. **Durable scheduling record.** Build the record content with
|
|
531
|
+
`pwsh -NoProfile -NonInteractive -File .claude/lib/parallel-admission/Invoke-ParallelAdmission.ps1 record -RunFolder docs/features/parallel/<slug> -Entry <entry-json>`
|
|
532
|
+
from the recorded `conflict_edges`, `tolerated_overlaps`, `precedence`, and `items`; the helper
|
|
533
|
+
prints the content and makes no git write. Write it to
|
|
534
|
+
`docs/features/parallel/<slug>/parallel-scheduling.json` and commit it on `parallel/<slug>-plan`
|
|
535
|
+
with the manifest. A re-seed applies the reuse rule per item with
|
|
536
|
+
`pwsh -NoProfile -NonInteractive -File .claude/lib/parallel-admission/Invoke-ParallelAdmission.ps1 reuse-edges -Slug <slug> -IssueNum <issue> -PlanHash <plan_hash>`,
|
|
537
|
+
where `<plan_hash>` is the item's `plan_hash` from its `assess` output. The helper reads the
|
|
538
|
+
committed record by ref from `origin/parallel/<slug>-plan`, runs no fetch, and prints
|
|
539
|
+
`{action, edges, reason}`. On `action` `reuse` the printed `edges` are that item's recorded
|
|
540
|
+
edges and are reused; on `action` `recompute` (reason `record_missing`, `unknown_item`, or
|
|
541
|
+
`plan_hash_changed`) that item's edges are recomputed.
|
|
485
542
|
|
|
486
543
|
### Recomputation parity (planner-owned check)
|
|
487
544
|
|
|
@@ -492,12 +549,18 @@ skill discharges that obligation as documented procedure, not as a new module:
|
|
|
492
549
|
|
|
493
550
|
1. After writing `cohorts[]` into the checkpoint and **before** emitting the kickoff artifact,
|
|
494
551
|
re-invoke `compute_cohorts` over exactly the `item_keys` and `conflict_edges` recorded in the
|
|
495
|
-
checkpoint.
|
|
552
|
+
checkpoint (through `compute-cohorts.sh`), plus the separating edges of the recorded
|
|
553
|
+
`precedence[]` pairs, and pass the result through `order-cohorts` with the recorded precedence,
|
|
554
|
+
exactly as `### Seeding procedure` step 1 does.
|
|
496
555
|
2. Assert that the recomputed list of lists maps to exactly the recorded `cohorts[]` at
|
|
497
556
|
`generation: 0`: the same partition, the same `index` assignment, and the same ascending
|
|
498
|
-
`item_keys[]` ordering.
|
|
499
|
-
|
|
500
|
-
|
|
557
|
+
`item_keys[]` ordering. Then run
|
|
558
|
+
`pwsh -NoProfile -NonInteractive -File .claude/lib/parallel-admission/Invoke-ParallelAdmission.ps1 test-cohorts -CheckpointPath artifacts/orchestration/parallel-planner-state.json`,
|
|
559
|
+
which rejects with `precedence_violated` when a cohort places an `after` item at or before an
|
|
560
|
+
active `before` item.
|
|
561
|
+
3. A mismatch is a **Blocking** condition, and so is a `test-cohorts` rejection. Stop the run and
|
|
562
|
+
report the mismatch or the rejection. Do not auto-correct the recorded cohorts, and do not emit
|
|
563
|
+
the kickoff artifact.
|
|
501
564
|
|
|
502
565
|
No production module is added for this check; it is a re-invocation of the landed library.
|
|
503
566
|
|
|
@@ -558,20 +621,22 @@ Write `artifacts/orchestration/parallel-planner-state.json` after every complete
|
|
|
558
621
|
|
|
559
622
|
Top-level fields: `objective`, `parallel_slug`, `parallel_manifest_path`, `mode`,
|
|
560
623
|
`max_concurrency`, `plan_home_branch` (`parallel/<slug>-plan`), `items[]`, `cohorts[]`,
|
|
561
|
-
`conflict_edges[]`, `
|
|
624
|
+
`conflict_edges[]`, `precedence[]` (the operator precedence entries, declared in
|
|
625
|
+
`## Prepared-Item Admission (issue #1047)` of the rule), `recolor_generation`, `kickoff_prompt_path`
|
|
562
626
|
(`artifacts/orchestration/parallel-kickoff-<slug>.md`), `completed_steps`, `next_step`, and
|
|
563
627
|
`last_updated`. F3's landed required-key set (planner invariant P1) is a strict subset of this
|
|
564
628
|
list, and `plan_home_branch` is a permitted additional field.
|
|
565
629
|
|
|
566
630
|
Per item: `issue_num`, `feature_folder`, `kind`, `state`, `complexity_band`, `complexity_assessment`,
|
|
567
631
|
`preparation_status`,
|
|
568
|
-
`research_path`, `plan_path`, `preflight_status`, `branch_name`, `worktree_path`, `blast_radius`
|
|
632
|
+
`research_path`, `plan_path`, `plan_hash`, `base_commit`, `preflight_status`, `branch_name`, `worktree_path`, `blast_radius`
|
|
569
633
|
(with `source: "declared"`), `radius_validation` (the `v1`, `v2`, and `v3` results with their
|
|
570
634
|
severities), `model_routing_receipt`, and `topology_receipt`.
|
|
571
635
|
|
|
572
636
|
**Deliberately absent:** any `epic_worthiness` analogue, any `depends_on` field, and any `wave`
|
|
573
637
|
field. The parallel surface renders no worthiness verdict and expresses ordering only as
|
|
574
|
-
blast-radius overlap
|
|
638
|
+
blast-radius overlap and as the operator `precedence[]` input, which is a separating input and not
|
|
639
|
+
a dependency field.
|
|
575
640
|
|
|
576
641
|
**Readiness contract.** Before reporting completion the checkpoint must satisfy F3's
|
|
577
642
|
`require_ready_for_execution` gate: at least two items (invariant P6); every item
|
|
@@ -674,6 +739,11 @@ Structural requirements enforced by the contract module:
|
|
|
674
739
|
commit of `parallel/<slug>-plan` as run-level provenance and a per-item `plan-path | plan-hash`
|
|
675
740
|
table whose hashes are 40 to 64 hex characters with no repeated plan path.
|
|
676
741
|
|
|
742
|
+
The planner writes the `## Integrity` section with one row per item, whose `plan-hash` is that
|
|
743
|
+
item's `assess` `plan_hash` (the plan blob hash at the item branch head), the same value recorded
|
|
744
|
+
on the checkpoint item and in the durable scheduling record. The parallel orchestrator passes it to
|
|
745
|
+
the item's execution child in kickoff element 4, which verifies it before any other step.
|
|
746
|
+
|
|
677
747
|
Validate the artifact through `mcp__drm-copilot__validate_orchestration_artifacts` with
|
|
678
748
|
`artifact_type: "parallel-kickoff"`. That artifact type dispatches to
|
|
679
749
|
`scripts/dev_tools/parallel_kickoff_contract.py`, which this feature delivers.
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
".claude/hooks/enforce-file-size-limit.ps1",
|
|
48
48
|
".claude/hooks/enforce-model-routing-receipt.ps1",
|
|
49
49
|
".claude/hooks/enforce-orchestration-preimplementation-gate.ps1",
|
|
50
|
+
".claude/hooks/enforce-orchestration-preimplementation-gate-cleanup.ps1",
|
|
50
51
|
".claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1",
|
|
51
52
|
".claude/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1",
|
|
52
53
|
".claude/hooks/enforce-orchestration-preimplementation-gate-modes.ps1",
|
|
@@ -60,6 +61,7 @@
|
|
|
60
61
|
".claude/hooks/enforce-powershell-batch-budget.ps1",
|
|
61
62
|
".claude/hooks/enforce-pr-author-command-allowlist.ps1",
|
|
62
63
|
".claude/hooks/enforce-pr-author-skill.artifact-root.ps1",
|
|
64
|
+
".claude/hooks/enforce-pr-author-skill.cleanup.ps1",
|
|
63
65
|
".claude/hooks/enforce-pr-author-skill.current-branch.ps1",
|
|
64
66
|
".claude/hooks/enforce-pr-author-skill.docs-only.ps1",
|
|
65
67
|
".claude/hooks/enforce-pr-author-skill.epic-base-branch.ps1",
|
|
@@ -71,6 +73,7 @@
|
|
|
71
73
|
".claude/hooks/enforce-python-batch-budget.ps1",
|
|
72
74
|
".claude/hooks/feature-folder-resolution.ps1",
|
|
73
75
|
".claude/hooks/feature-review-coverage-thresholds.ps1",
|
|
76
|
+
".claude/hooks/hook-cleanup-context.ps1",
|
|
74
77
|
".claude/hooks/hook-command-heredoc.ps1",
|
|
75
78
|
".claude/hooks/hook-command-invocation.ps1",
|
|
76
79
|
".claude/hooks/hook-command-invocation-operands.ps1",
|
|
@@ -122,6 +125,7 @@
|
|
|
122
125
|
".claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_lib.sh",
|
|
123
126
|
".claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_eol_lib.sh",
|
|
124
127
|
".claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_lib.sh",
|
|
128
|
+
".claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_merge_lib.sh",
|
|
125
129
|
".claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_report_records_lib.sh",
|
|
126
130
|
".claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_scan_helper.sh",
|
|
127
131
|
".claude/skills/commit-message/SKILL.md",
|
|
@@ -231,6 +235,10 @@
|
|
|
231
235
|
".claude/lib/parallel-drift/ParallelDriftHalt.psm1",
|
|
232
236
|
".claude/lib/parallel-drift/ParallelDrift.psm1",
|
|
233
237
|
".claude/lib/parallel-drift/Invoke-ParallelDriftDetection.ps1",
|
|
238
|
+
".claude/lib/parallel-admission/ParallelAdmission.psm1",
|
|
239
|
+
".claude/lib/parallel-admission/ParallelAdmissionPrecedence.psm1",
|
|
240
|
+
".claude/lib/parallel-admission/Invoke-ParallelAdmission.ps1",
|
|
241
|
+
".claude/lib/parallel-admission/ParallelAdmissionJson.psm1",
|
|
234
242
|
".claude/rules/parallel-orchestration.md",
|
|
235
243
|
".claude/rules/shell.md",
|
|
236
244
|
".claude/lib/bash/abandon-parallel-item.sh",
|
package/resources/codex-and-agents-customizations/.agents/skills/execution-environment/SKILL.md
CHANGED
|
@@ -11,6 +11,14 @@ This brief states the environment facts that every researcher, planner, prefligh
|
|
|
11
11
|
|
|
12
12
|
Maintenance rule: this brief is updated in the same change that alters any fact it states. It carries no line numbers and no commit identifiers; it cites files, symbols, headings, job names, and test names. The same text is byte-identical in six locations: `.claude/skills/execution-environment/SKILL.md`, `.agents/skills/execution-environment/SKILL.md`, `.github/skills/execution-environment/SKILL.md`, and their bundled copies under `extensions/drm-copilot/resources/`. Where the Claude and Codex runtimes differ, both paths are named (`.claude/hooks/...` and `.codex/hooks/...`).
|
|
13
13
|
|
|
14
|
+
## Development Toolchain Baseline
|
|
15
|
+
|
|
16
|
+
The host manifest, both devcontainer Dockerfiles, and development CI use Python 3.13.17, Node.js 26.13.0/npm 11.20.0, PowerShell 7.6.9, and Poetry 2.3.2. Shell validation pins shfmt 3.14.1, ShellCheck 0.11.0, and actionlint 1.7.12. Host bootstrap treats manifest versions as minima and preserves equal/newer installations; the container verifier accepts later Python patches within 3.13 and checks the other selected pins.
|
|
17
|
+
|
|
18
|
+
The devcontainer minor image can lag the Python patch, so both Dockerfiles copy the verified official Python runtime stage and select it and NodeSource ahead of older base-feature shims. Full configuration builds include the selected devcontainer features; a raw Dockerfile image alone does not prove feature-provided commands. Runtime verification uses an isolated Linux virtual environment rather than the host Windows environment.
|
|
19
|
+
|
|
20
|
+
Python 3.11/3.12 compatibility jobs, consumer package engines, and independent release-publishing runtime pins remain unchanged. The shared version predicate lives in `scripts/bash/container_versions.sh`; `.devcontainer/verify-container.sh` resolves it relative to its own repository location.
|
|
21
|
+
|
|
14
22
|
## Tool Routes by Agent
|
|
15
23
|
|
|
16
24
|
- `atomic-executor` has no PowerShell tool. Its `tools:` list is Read, Grep, Glob, Edit, Write, several `Bash(...)` entries, the four `mcp__drm-copilot__run_poshqc_*` tools, and `mcp__drm-copilot__validate_orchestration_artifacts`. A `(pattern)` suffix on a `tools:` entry admits the bare tool, so the executor has Bash, subject to the repository hooks and the runtime guard described under Command-Text Restrictions.
|
|
@@ -50,6 +58,8 @@ Two separate mechanisms restrict Bash command text. They are kept apart here bec
|
|
|
50
58
|
- Hooks for an isolated subagent run inside the subagent's worktree with that worktree's hook scripts, which are `main`'s copies. A hook change on a branch is not exercised by isolated subagents until it merges.
|
|
51
59
|
- Hook behavior on a branch is therefore proven by Pester suites, not by a live subagent run. A live check of a branch hook needs a non-isolated delegation from the item worktree.
|
|
52
60
|
- The batch-budget hooks evaluate the checkpoint of the target worktree that `Resolve-HookTargetWorktree` resolves for the edited file, so an edit made from a coordinating session into an item worktree is evaluated against the item worktree's checkpoint. The preimplementation gate (#1010) resolves the file path of a Write or Edit call and the `-C` values and absolute operands of `git add` and `git commit` through the same resolver, and denies when the worktree listing fails or names no worktree; its delegation checks still resolve by portable identity. The PR authoring gate (#1011) resolves the branch that a `gh pr create` or `gh pr edit` command names (`--head`, `--branch`, or a `branch:` label) through the same resolver when the command carries no canonical issue number line, and otherwise keeps its portable-identity and current-branch resolution. The other gates that read `artifacts/orchestration/orchestrator-state.json` are unchanged and still use the root that holds the hook script.
|
|
61
|
+
- Cleanup legs (#1026): a `cleanup-merged-worktrees` run writes no checkpoint, so the preimplementation gate (`.claude/hooks/enforce-orchestration-preimplementation-gate-cleanup.ps1` and its `.codex/hooks/` twin), the PR-authoring gate (`.claude/hooks/enforce-pr-author-skill.cleanup.ps1`), and the model-routing gate (`.claude/hooks/enforce-model-routing-receipt.ps1`) carry allow-side cleanup legs, evaluated only where each gate would otherwise deny, that share the pure predicates of `hook-cleanup-context.ps1`. The legs admit a Write of the session-root manifest `artifacts/orchestration/cleanup-worktrees-manifest.json` with valid content (an Edit stays denied), Write or Edit of paths under `docs/` or `.claude/agent-memory/` and of the pr-author receipt inside the consolidation worktree on branch `documentationandmemories`, `git -C <consolidation root> add` and `commit` of those paths, `Agent(pr-author)` with `branch: documentationandmemories`, and `gh pr create --head documentationandmemories --base main` while a fresh valid manifest exists at the session root and the pushed `refs/remotes/origin/documentationandmemories` resolves to the same commit as the consolidation worktree `HEAD`. A preimplementation-gate denial appends a cleanup sub-code (`Cleanup leg not applied`) only after a cleanup leg has identified the consolidation worktree as the target and a later condition fails; a call rejected by a prefilter keeps the unchanged deny text even when its target is the consolidation worktree, as does every other call.
|
|
62
|
+
- Scratch rule (#1026): the preimplementation gate allows a Write or Edit of an absolute local path that lies outside every registered worktree and the session root and under a temporary root, read through the seam `Get-OrchestrationGateTemporaryRoot` (the long-name `GetTempPath()` value and the `TEMP`, `TMP`, and `TMPDIR` values, which can carry the 8.3 short-name spelling). The rule fails closed when any registered worktree lies under a temporary root.
|
|
53
63
|
- Enforcement hooks do not invoke Python; bash is preferred and PowerShell is acceptable (`tests/scripts/claude-runtime/enforcement-hooks-no-python-invocation.Tests.ps1`).
|
|
54
64
|
|
|
55
65
|
## MCP Surfaces Run the Installed Extension
|
|
@@ -61,14 +71,14 @@ Two separate mechanisms restrict Bash command text. They are kept apart here bec
|
|
|
61
71
|
## CI Shape and Required Checks
|
|
62
72
|
|
|
63
73
|
- `.github/workflows/ci.yml` triggers on `push` to `main` and `development`, on `pull_request` to `main`, `development`, and `epic/**`, on `workflow_dispatch`, and on `merge_group` (`types: [checks_requested]`, added by issue #952), with no path filters. When the merge queue on `main` is enabled, every required check is produced by a `merge_group` run of `ci.yml` as well as by the pull-request run; `.github/workflows/README.md` (`## Triggers`) records the trigger set.
|
|
64
|
-
- Jobs in `ci.yml` and their check names: `Change scope` (job `changes`, the change-scope decision below); `CI full run` (job `full-run-marker`, which runs only on a full run, marks that run as a valid base for later decisions, and is not a required check); `quality-checks7 / Code Quality & Tests (<python-version>)` on Python 3.11, 3.12, and 3.13 (`_quality-checks.yml`: Black check, Ruff, Pyright, the Codex generator `--check`, the tier classification, and Pytest on every version; Pytest with line and branch coverage and the coverage-threshold check on the JSON report totals run on 3.13 only); `security-scan / Security Scanning` (its `safety check` step carries `continue-on-error: true` and does not fail the check); `docs-validation / Documentation Validation`; `build-check / Build Package`; `shell-coverage / Shell Coverage (Bats + kcov)`; `drm-copilot-extension-tests / drm-copilot Extension Tests (<os>)` on `ubuntu-latest` and `windows-latest`; `root-typescript-tests / Root TypeScript Tests (<os>)` on `ubuntu-latest` and `windows-latest`; `NPM Audit Gate / npm audit (<manifest>)` (the calling job carries the name `NPM Audit Gate`);
|
|
74
|
+
- Jobs in `ci.yml` and their check names: `Change scope` (job `changes`, the change-scope decision below); `CI full run` (job `full-run-marker`, which runs only on a full run, marks that run as a valid base for later decisions, and is not a required check); `quality-checks7 / Code Quality & Tests (<python-version>)` on Python 3.11, 3.12, and 3.13 (`_quality-checks.yml`: Black check, Ruff, Pyright, the Codex generator `--check`, the tier classification, and Pytest on every version; Pytest with line and branch coverage and the coverage-threshold check on the JSON report totals run on 3.13 only); `security-scan / Security Scanning` (its `safety check` step carries `continue-on-error: true` and does not fail the check); `docs-validation / Documentation Validation`; `build-check / Build Package`; `shell-coverage / Shell Coverage (Bats + kcov)`; `drm-copilot-extension-tests / drm-copilot Extension Tests (<os>)` on `ubuntu-latest` and `windows-latest`; `root-typescript-tests / Root TypeScript Tests (<os>)` on `ubuntu-latest` and `windows-latest`; `NPM Audit Gate / npm audit (<manifest>)` (the calling job carries the name `NPM Audit Gate`); the `poshqc` group below; and `CI Required Gate` (job `ci-required-gate`, issue #1074), which needs every other `ci.yml` job, runs under `if: always()` on `ubuntu-latest`, and passes `toJSON(needs)` to `scripts/ci/Invoke-CiRequiredGate.ps1`. The gate is green on a full run only when every needed job is `success`, and on a docs-only run only when `CI full run`, `root-typescript-tests`, and `NPM Audit Gate` are `success` or `skipped` and every other needed job is `success`; a `failure`, `cancelled`, or unknown result, a `Change scope` result other than `success`, and unreadable input are red. `tests/scripts/workflows/CiRequiredGateWorkflow.Tests.ps1` pins its `needs:` set against the other job ids of `ci.yml`.
|
|
65
75
|
- PowerShell CI (`_poshqc.yml`): `poshqc / PowerShell QC static` (format and analyze on `windows-latest`); the shard matrix `poshqc / PowerShell QC shard 1`, `shard 2`, and `shard 3` (`Invoke-PoshQCTest -ShardIndex -ShardCount` over the scan folders of `config/poshqc-scan.json`, with coverage, on `windows-latest`); the aggregator `poshqc / PowerShell QC`, which requires the static and shard jobs to succeed, verifies shard completeness against a Pester discovery count, and merges shard coverage; and `poshqc / PowerShell hook suites (Linux)`, which runs only `tests/scripts/claude-hooks` and `tests/scripts/codex-hooks` on `ubuntu-latest` with coverage disabled. A new test file under a scanned folder is assigned to a shard automatically and is counted by the completeness check.
|
|
66
76
|
- Change-scope decision (issue #962): the `Change scope` job runs `scripts/ci/Invoke-CiChangeScope.ps1` and publishes the job output `code`. The decision is `code=false` (docs-only) only on a `pull_request` event from this repository, through one of two comparisons. Green-run base: every file changed since the newest successful `ci.yml` run on the pull-request branch whose `CI full run` job succeeded, and whose head commit is present and an ancestor of the current head, is on the allowlist `config/ci-docs-only-paths.json`; the reason is `DOCS_ONLY_SINCE_<green head sha>`. Merge-base fallback (issue #973): when the green-run step ends with no earlier full green run (`NO_FULL_GREEN_RUN`), a missing base (`BASE_NOT_PRESENT`), or a non-ancestor base (`BASE_NOT_ANCESTOR`), and the pull request's base ref is exactly `main`, the script computes `git merge-base` of the payload base SHA (`BASE_SHA`, from `github.event.pull_request.base.sha`; the base ref arrives as `BASE_REF`) and the head, lists the files changed since that merge base with the same diff arguments, and decides `DOCS_ONLY_SINCE_MERGE_BASE_<merge base sha>` when every changed file is allowlisted. Both comparisons run the diff with rename detection off, so both the old and the new path of a rename are classified. A path is allowlisted when it starts with `docs/features/active/`, `docs/features/archive/`, `docs/features/completed/`, `docs/features/epics/`, `docs/features/parallel/`, `docs/features/potential/`, or `docs/research/`, does not start with `docs/features/templates/` or `docs/features/potential/template.md`, and ends in `.md`, `.txt`, `.log`, `.json`, or `.xml`; the allowlist file itself is not allowlisted. Every other case is a full run (`code=true`): `push`, `merge_group`, and `workflow_dispatch` events, a fork pull request, unreadable run or job data, no earlier full green run or a missing or non-ancestor base when the base ref is not `main`, a merge base that cannot be resolved (`MERGE_BASE_UNRESOLVED`, for example a blank base SHA or a base commit missing from the checkout), a failed ancestry check, an empty diff, any path outside the allowlist, and any error. The decision step carries `continue-on-error: true` and the callers compare the output with `!= 'false'`, so a failed or missing decision also gives a full run.
|
|
67
|
-
- Docs-only behavior (`code=false`): `ci.yml` passes `run-heavy: false` to `_quality-checks.yml`, `_security-scan.yml`, `_build-check.yml`, `_poshqc.yml`, `_shell-coverage.yml`, and `_drm-copilot-extension-tests.yml`. Each
|
|
77
|
+
- Docs-only behavior (`code=false`): `ci.yml` passes `run-heavy: false` to `_quality-checks.yml`, `_security-scan.yml`, `_build-check.yml`, `_poshqc.yml`, `_shell-coverage.yml`, and `_drm-copilot-extension-tests.yml`. Each job that runs with its steps gated still starts under its full-run check name with every step skipped, so it reports `success` without running its suite. In `_poshqc.yml` the aggregator `poshqc / PowerShell QC` runs with every step gated, and `poshqc / PowerShell QC static`, the shard jobs, and `poshqc / PowerShell hook suites (Linux)` are skipped at job level. `docs-validation / Documentation Validation` runs in full. `root-typescript-tests`, `NPM Audit Gate`, and `CI full run` are skipped at job level. Eight currently required contexts therefore never report on a docs-only run: `poshqc / PowerShell QC shard 1`, `poshqc / PowerShell QC shard 2`, `poshqc / PowerShell QC shard 3`, `root-typescript-tests / Root TypeScript Tests (ubuntu-latest)`, `root-typescript-tests / Root TypeScript Tests (windows-latest)`, `NPM Audit Gate / npm audit (.)`, `NPM Audit Gate / npm audit (extensions/drm-copilot)`, and `NPM Audit Gate / npm audit (packages/mcp-server)`, so a docs-only head stays blocked under the 20-context ruleset. `CI Required Gate` passes on a docs-only run, because it accepts `skipped` for exactly those skipped callers. A `success` on a docs-only commit is therefore not evidence that the heavy suites pass for that commit; that evidence is the newest run whose `CI full run` job succeeded.
|
|
68
78
|
- A commit that changes any path outside the allowlist (any code, workflow, configuration, script, test, or customization file) runs the full set of jobs, and its `CI full run` job marks it as a base for later docs-only decisions. A standalone `workflow_dispatch` of a reusable workflow, or a caller that omits `run-heavy`, also runs in full. `.github/workflows/README.md` (`## Change-Scope Decision (Issue #962)`) records the reason codes and the per-context behavior table.
|
|
69
|
-
- Required contexts of ruleset 15241672,
|
|
70
|
-
- Refresh rule: a change that renames a job, adds or removes a matrix entry, or changes the ruleset refreshes this list in the same change, and the orchestrator re-confirms the contexts with a read-only `gh api repos/drmoisan/drm-copilot/rulesets/15241672` call before relying on them.
|
|
71
|
-
- Skipped-check semantics: a job skipped by an `if:` condition reports success to a required check; a workflow that does not run at all reports nothing, which leaves the required check pending.
|
|
79
|
+
- Required contexts of ruleset 15241672, read through a read-only `gh api` call on 2026-11-04 (20 contexts, each with `integration_id` 15368): `drm-copilot-extension-tests / drm-copilot Extension Tests (ubuntu-latest)`, `drm-copilot-extension-tests / drm-copilot Extension Tests (windows-latest)`, `docs-validation / Documentation Validation`, `poshqc / PowerShell QC`, `shell-coverage / Shell Coverage (Bats + kcov)`, `security-scan / Security Scanning`, `quality-checks7 / Code Quality & Tests (3.11)`, `quality-checks7 / Code Quality & Tests (3.12)`, `quality-checks7 / Code Quality & Tests (3.13)`, `build-check / Build Package`, `NPM Audit Gate / npm audit (extensions/drm-copilot)`, `NPM Audit Gate / npm audit (.)`, `NPM Audit Gate / npm audit (packages/mcp-server)`, `root-typescript-tests / Root TypeScript Tests (ubuntu-latest)`, `root-typescript-tests / Root TypeScript Tests (windows-latest)`, `poshqc / PowerShell QC shard 1`, `poshqc / PowerShell QC shard 2`, `poshqc / PowerShell QC shard 3`, `poshqc / PowerShell QC static`, `poshqc / PowerShell hook suites (Linux)`. After the owner's post-merge ruleset edit (issue #1074 runbook), the single required context is `CI Required Gate` (`integration_id` 15368), and the individual job contexts remain visible but are no longer required.
|
|
80
|
+
- Refresh rule: a change that renames a job, adds or removes a `ci.yml` job or a matrix entry, or changes the ruleset refreshes this list in the same change, and the orchestrator re-confirms the contexts with a read-only `gh api repos/drmoisan/drm-copilot/rulesets/15241672` call before relying on them. A new `ci.yml` job must also be added to the `needs:` list of `ci-required-gate`; `tests/scripts/workflows/CiRequiredGateWorkflow.Tests.ps1` fails until it is.
|
|
81
|
+
- Skipped-check semantics: a job skipped by an `if:` condition reports success to a required check; a workflow that does not run at all reports nothing, which leaves the required check pending. A matrix job skipped at job level reports no expanded context (its matrix name is never expanded), and a reusable-workflow caller skipped in `ci.yml` reports no nested contexts, so each such required context stays pending.
|
|
72
82
|
- A pull request into a branch other than `main`, `development`, or `epic/**` gets no CI run; dispatch `ci.yml` manually for it.
|
|
73
83
|
|
|
74
84
|
## CI-Only Failure Classes
|