@danmoisan/drm-copilot-mcp 1.1.25 → 1.1.27
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 +170 -52
- package/package.json +1 -1
- package/resources/claude-customizations/.claude/agents/atomic-executor.md +3 -3
- package/resources/claude-customizations/.claude/agents/atomic-planner.md +2 -2
- package/resources/claude-customizations/.claude/agents/csharp-typed-engineer.md +7 -7
- package/resources/claude-customizations/.claude/agents/feature-review.md +6 -3
- package/resources/claude-customizations/.claude/agents/orchestrator.md +11 -7
- 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/agents/powershell-typed-engineer.md +7 -7
- package/resources/claude-customizations/.claude/agents/python-typed-engineer.md +6 -6
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-review.ps1 +699 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +16 -1
- 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/hooks/validate-feature-review-coverage-rules.ps1 +50 -16
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorState.psm1 +6 -1
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCompletion.psm1 +4 -2
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCompletionChecks.psm1 +51 -2
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateReceipts.psm1 +5 -2
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRemediationAccounting.psm1 +116 -4
- 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/csharp.md +8 -8
- package/resources/claude-customizations/.claude/rules/orchestrator-state.md +28 -2
- package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +17 -1
- package/resources/claude-customizations/.claude/rules/powershell.md +2 -2
- package/resources/claude-customizations/.claude/settings.json +1 -0
- package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +9 -13
- 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/csharp-qa-gate/SKILL.md +14 -15
- package/resources/claude-customizations/.claude/skills/epic-progress-report/SKILL.md +338 -0
- package/resources/claude-customizations/.claude/skills/epic-progress-report/scripts/Get-EpicProgressReport.Logic.ps1 +248 -0
- package/resources/claude-customizations/.claude/skills/epic-progress-report/scripts/Get-EpicProgressReport.Metrics.ps1 +232 -0
- package/resources/claude-customizations/.claude/skills/epic-progress-report/scripts/Get-EpicProgressReport.Render.ps1 +196 -0
- package/resources/claude-customizations/.claude/skills/epic-progress-report/scripts/Get-EpicProgressReport.State.ps1 +286 -0
- package/resources/claude-customizations/.claude/skills/epic-progress-report/scripts/Get-EpicProgressReport.ps1 +475 -0
- package/resources/claude-customizations/.claude/skills/execution-environment/SKILL.md +31 -16
- package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +21 -9
- package/resources/claude-customizations/.claude/skills/invoke-csharp-engineer/SKILL.md +5 -5
- package/resources/claude-customizations/.claude/skills/invoke-powershell-engineer/SKILL.md +4 -4
- package/resources/claude-customizations/.claude/skills/invoke-python-engineer/SKILL.md +4 -4
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +24 -2
- package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +71 -7
- package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +34 -2
- package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +82 -12
- package/resources/claude-customizations/.claude/skills/powershell-qa-gate/SKILL.md +16 -17
- package/resources/claude-customizations/.claude/skills/python-qa-gate/SKILL.md +15 -16
- package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +1 -1
- package/resources/claude-customizations/.claude-variants/csharp-legacy/agents/csharp-typed-engineer.md +6 -6
- package/resources/claude-customizations/.claude-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +13 -14
- package/resources/claude-customizations/.claude-variants/csharp-legacy/skills/invoke-csharp-engineer/SKILL.md +4 -4
- package/resources/claude-customizations/pack-manifests/core.json +15 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-plan-contract/SKILL.md +8 -12
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/csharp-qa-gate/SKILL.md +13 -14
- package/resources/codex-and-agents-customizations/.agents/skills/execution-environment/SKILL.md +31 -16
- package/resources/codex-and-agents-customizations/.agents/skills/feature-review/SKILL.md +5 -1
- package/resources/codex-and-agents-customizations/.agents/skills/feature-review-workflow/SKILL.md +18 -5
- package/resources/codex-and-agents-customizations/.agents/skills/invoke-csharp-engineer/SKILL.md +4 -4
- package/resources/codex-and-agents-customizations/.agents/skills/invoke-powershell-engineer/SKILL.md +4 -4
- package/resources/codex-and-agents-customizations/.agents/skills/invoke-python-engineer/SKILL.md +4 -4
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +24 -2
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-state/SKILL.md +16 -1
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +3 -3
- package/resources/codex-and-agents-customizations/.agents/skills/powershell/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.agents/skills/powershell-qa-gate/SKILL.md +15 -16
- package/resources/codex-and-agents-customizations/.agents/skills/python-qa-gate/SKILL.md +14 -15
- package/resources/codex-and-agents-customizations/.agents/skills/repo-automation-adapter/SKILL.md +2 -0
- package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +13 -14
- package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/invoke-csharp-engineer/SKILL.md +4 -4
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c1.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c2.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3-elevated.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c4.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c1.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c2.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3-elevated.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c4.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-atomic-executor.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-atomic-planning.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-orchestrator.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c1.toml +6 -6
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c2.toml +6 -6
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c3-elevated.toml +6 -6
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c3.toml +6 -6
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c4.toml +6 -6
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer.toml +6 -6
- package/resources/codex-and-agents-customizations/.codex/agents/feature-review.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-atomic-executor.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-atomic-planning.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-di-unit-test-engineer.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-orchestrator.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c1.toml +7 -7
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c2.toml +7 -7
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c3-elevated.toml +7 -7
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c3.toml +7 -7
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c4.toml +7 -7
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer.toml +7 -7
- package/resources/codex-and-agents-customizations/.codex/agents/pytest-unit-test-coding.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-atomic-executor.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/python-atomic-planning.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-execution-only-typed.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-orchestrator.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c1.toml +6 -6
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c2.toml +6 -6
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c3-elevated.toml +6 -6
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c3.toml +6 -6
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c4.toml +6 -6
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer.toml +6 -6
- package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate-review.ps1 +699 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate.ps1 +29 -2
- 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/.codex/hooks/validate-feature-review-coverage.ps1 +51 -4
- package/resources/codex-and-agents-customizations/.codex-variants/csharp-legacy/agents/csharp-typed-engineer.toml +6 -6
- package/resources/codex-and-agents-customizations/pack-manifests/core.json +3 -0
- package/resources/customizations/.github/agents/5.1-Beast-adjusted.agent.md +1 -1
- package/resources/customizations/.github/agents/Powershell DI Unit Test Engineer.agent.md +20 -26
- package/resources/customizations/.github/agents/atomic_executor.agent.md +4 -4
- package/resources/customizations/.github/agents/atomic_planning.agent.md +4 -4
- package/resources/customizations/.github/agents/commentary-remediation.agent.md +1 -1
- package/resources/customizations/.github/agents/commit-steward.agent.md +1 -1
- package/resources/customizations/.github/agents/csharp-atomic-executor.agent.md +14 -14
- package/resources/customizations/.github/agents/csharp-atomic-planning.agent.md +2 -2
- package/resources/customizations/.github/agents/csharp-orchestrator.agent.md +4 -4
- package/resources/customizations/.github/agents/csharp-typed-engineer.agent.md +19 -22
- package/resources/customizations/.github/agents/epic-review.agent.md +1 -1
- package/resources/customizations/.github/agents/gpt-5-beast-mode.agent.md +3 -3
- package/resources/customizations/.github/agents/orchestrator.agent.md +8 -8
- package/resources/customizations/.github/agents/powershell-atomic-executor.agent.md +12 -12
- package/resources/customizations/.github/agents/powershell-atomic-planning.agent.md +4 -4
- package/resources/customizations/.github/agents/powershell-orchestrator.agent.md +6 -6
- package/resources/customizations/.github/agents/powershell-typed-engineer.agent.md +21 -24
- package/resources/customizations/.github/agents/pytest-unit-test-coding.agent.md +13 -17
- package/resources/customizations/.github/agents/python-atomic-executor.agent.md +11 -11
- package/resources/customizations/.github/agents/python-atomic-planning.agent.md +2 -2
- package/resources/customizations/.github/agents/python-execution-only-typed.agent.md +14 -17
- package/resources/customizations/.github/agents/python-orchestrator.agent.md +7 -7
- package/resources/customizations/.github/agents/python-typed-engineer.agent.md +17 -20
- package/resources/customizations/.github/agents/staged-review.agent.md +2 -2
- package/resources/customizations/.github/agents/tdd-green.agent.md +1 -1
- package/resources/customizations/.github/agents/tdd-red.agent.md +3 -3
- package/resources/customizations/.github/agents/tdd-refactor.agent.md +2 -2
- package/resources/customizations/.github/agents/typescript-engineer.agent.md +3 -3
- package/resources/customizations/.github/codex/execute-hard-lock.prompt.md +3 -3
- package/resources/customizations/.github/instructions/general-code-change.instructions.md +1 -1
- package/resources/customizations/.github/instructions/powershell-unit-test.instructions.md +1 -1
- package/resources/customizations/.github/instructions/python-code-change.instructions.md +5 -5
- package/resources/customizations/.github/instructions/python-suppressions.instructions.md +3 -3
- package/resources/customizations/.github/instructions/python-unit-test.instructions.md +1 -1
- package/resources/customizations/.github/prompts/execute-hard-lock.prompt.md +2 -2
- package/resources/customizations/.github/prompts/generate-commit-message-repo.prompt.md +2 -2
- package/resources/customizations/.github/prompts/remediate-comments.prompt.md +2 -2
- package/resources/customizations/.github/prompts/review-feature.prompt.md +1 -1
- package/resources/customizations/.github/skills/atomic-plan-contract/SKILL.md +8 -12
- package/resources/customizations/.github/skills/execution-environment/SKILL.md +31 -16
- package/resources/customizations/.github/skills/feature-review-workflow/SKILL.md +15 -2
- package/resources/feature-templates/bug/plan.yyyy-MM-ddTHH-mm.md +4 -4
- package/resources/feature-templates/feature/plan.yyyy-MM-ddTHH-mm.md +3 -3
- package/resources/feature-templates/refactor/plan.yyyy-MM-ddTHH-mm.md +2 -2
- package/resources/powershell/PoshQC/PoshQC.ScanConfig.psm1 +3 -1
- package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +14 -12
- package/resources/powershell/PoshQC/PoshQC.psm1 +3 -3
- package/resources/powershell/PoshQC/README.md +8 -8
- package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +2 -2
- package/resources/templates/policy_audit/AGENTS.md +9 -10
- package/resources/templates/policy_audit/policy-audit.yyyy-MM-ddTHH-mm.md +19 -20
|
@@ -60,7 +60,7 @@ Enforced by `validate_parallel_orchestrator_state_text(text, *, require_complete
|
|
|
60
60
|
|
|
61
61
|
9. **Blast-radius shape.** Each item's `blast_radius` must be an object carrying `paths`, `modules`, `shared_surfaces`, and `contracts` as lists of non-empty strings, a `source` in `{derived, declared, observed}`, and a non-empty `computed_at` string. `modules`, `shared_surfaces`, and `contracts` may be empty lists.
|
|
62
62
|
|
|
63
|
-
10. **Prohibited dependency edges.** No object anywhere in the checkpoint may carry a `depends_on` key, and no top-level `depends_on` key may be present. Ordering is expressed only as blast-radius overlap. Presence is an explicit rejection, not mere absence.
|
|
63
|
+
10. **Prohibited dependency edges.** No object anywhere in the checkpoint may carry a `depends_on` key, and no top-level `depends_on` key may be present. Ordering is expressed only as blast-radius overlap and as the operator precedence input declared in `## Prepared-Item Admission (issue #1047)`, which is a separating input and not a dependency key. Presence is an explicit rejection, not mere absence.
|
|
64
64
|
|
|
65
65
|
11. **Prohibited integration-branch fields.** The checkpoint must not carry `integration_branch` or `epic_merge_pr` at any level. Each parallel item opens its own pull request against `main`, so there is no integration branch and no final integration pull request.
|
|
66
66
|
|
|
@@ -256,6 +256,22 @@ F3 deliberately excludes the kickoff-prompt contract module `scripts/dev_tools/p
|
|
|
256
256
|
|
|
257
257
|
F3's `require_ready_for_execution` gate is STRUCTURAL ONLY. It enforces the kickoff-PATH invariant (P9: `kickoff_prompt_path` must equal `artifacts/orchestration/parallel-kickoff-<parallel_slug>.md`) and does not parse or cross-check kickoff CONTENT. The deeper readiness-integrity machinery of the epic surface — git-integrity checks, launch-evidence binding, and kickoff-contract cross-checks — is left to F4, which may layer repository-aware checks behind an additional keyword without changing the schema. F3 likewise does not recompute the cohort coloring (planner invariant P5).
|
|
258
258
|
|
|
259
|
+
## Prepared-Item Admission (issue #1047)
|
|
260
|
+
|
|
261
|
+
`/parallel-add` and `/parallel-plan` admit an item at the stage its pushed branch already reached. The decisions are made in code by the admission helper `.claude/lib/parallel-admission/Invoke-ParallelAdmission.ps1` (subcommands `guard-run`, `assess`, `order-cohorts`, `test-cohorts`, `record`, and `reuse-edges`). Every field below is tolerated and not validated: the Python validators and the TypeScript validator port accept it with zero errors, and no enum of `## Enum Ownership (F6/F7/F8 consume, never extend)` changes.
|
|
262
|
+
|
|
263
|
+
**Tolerated item fields.** A parallel-orchestrator checkpoint item may carry `preparation_status` (`none|research|spec|plan|cleared`, as reported by `assess`), `plan_hash` (the git blob hash of the plan at the item branch head), `base_commit` (the commit the staleness check compares `origin/main` against), and `band_source` (`caller|planner_checkpoint|assessment`). A parallel-planner checkpoint item may carry `plan_hash` and `base_commit`. The planner keeps its ready value `preparation_status: prepared` (invariant P7), which corresponds to the admission stage `cleared`; no second ready value is introduced.
|
|
264
|
+
|
|
265
|
+
**Precedence input.** Both checkpoints may carry a top-level `precedence[]` list of `{before, after, source, recorded_at}` entries, recorded from the operator's `--after` flags with `source` equal to `operator`. An entry states that the `after` item starts in a later cohort than the `before` item and only after the `before` item has merged. It is a separating input: each pair is passed to the cohort computation as an extra edge, and `order-cohorts` lifts an unstarted `after` item above its `before` item. It is not a `depends_on` key, and invariant 10, P3, and M7 are unchanged. Keys must resolve to items, an item is never paired with itself, and the entries must be acyclic. An entry is inactive once its `before` item has `merge_status` `merged` or `worktree_removed` or `state` `withdrawn`; a `blocked` predecessor still holds its dependent. A combined item inherits the union of its members' entries, and a pair inside one combination is dropped.
|
|
266
|
+
|
|
267
|
+
**Preparation receipt.** The preparation child writes `<feature folder>/evidence/other/preparation-receipt.<yyyy-MM-ddTHH-mm>.json` before its commit, carrying `schema_version`, `stage`, `research_path`, `spec_path`, `plan_path`, `plan_hash`, `base_commit`, `preflight_status`, and `recorded_at`. The lexicographically greatest receipt name wins, a newer receipt supersedes an older one, and no receipt is deleted. A receipt whose `plan_hash` differs from the current blob hash is downgraded to `plan`.
|
|
268
|
+
|
|
269
|
+
**Durable scheduling record.** `docs/features/parallel/<slug>/parallel-scheduling.json`, committed on `parallel/<slug>-plan`, carries `schema_version`, `parallel_slug`, `edges[]`, `tolerated_overlaps[]`, `precedence[]`, and `items[]` with `issue_num`, `branch_name`, `plan_path`, `plan_hash`, `base_commit`, `preparation_status`, and `complexity_band`. The planner writes it at seeding and `/parallel-add` rewrites it after each admission; the helper's `record` subcommand prints the content and performs no git write. A re-seed applies the reuse rule through the helper's `reuse-edges` subcommand, which reads the record by ref and reuses an item's recorded edges only when the recorded `plan_hash` equals the current blob hash. The run manifest stays read-only to the orchestrator.
|
|
270
|
+
|
|
271
|
+
**Admission output signal.** A helper rule rejection exits 1 with one stderr line `PARALLEL_ADMISSION_REJECTED: <code>: <detail>`, where the code is one of `run_closed`, `precedence_cycle`, `precedence_unknown_item`, and `precedence_violated`. This signal is separate from the mutation rejection signal of `## Mutation Rejection Signal (issue #1012)`: a `run_closed` rejection is emitted after a checkpoint exists and emits no mutation rejection signal, and that section's closed code set is unchanged.
|
|
272
|
+
|
|
273
|
+
**Known gap (Layer 2).** The Python orchestrator-state validator does not check precedence. Precedence is enforced by the helper's `test-cohorts` rejection and by Layer 1 of the cohort barrier hook (`Test-ParallelCohortBarrierClear` in `.claude/hooks/enforce-parallel-cohort-barrier-helpers.ps1`); the retrospective Layer 2 invariant reads `conflict_edges[]` only.
|
|
274
|
+
|
|
259
275
|
## Blast-Radius Contention Doctrine (issue #489)
|
|
260
276
|
|
|
261
277
|
The conflict graph that seeds cohorts is only as good as the evidence that produces its edges. Two
|
|
@@ -15,7 +15,7 @@ This rule file summarizes the PowerShell-specific policies for this repository.
|
|
|
15
15
|
1. **Formatting — Invoke-Formatter**: Format all PowerShell files via PoshQC. MCP command: `mcp__drm-copilot__run_poshqc_format`
|
|
16
16
|
2. **Linting — PSScriptAnalyzer**: Run PoshQC analyzer with repo settings. MCP command: `mcp__drm-copilot__run_poshqc_analyze`. Optional autofix: `mcp__drm-copilot__run_poshqc_analyze_autofix`
|
|
17
17
|
3. **Type checking**: Not applicable for PowerShell; skip to testing.
|
|
18
|
-
4. **Testing — Pester (
|
|
18
|
+
4. **Testing — Pester (v6.x)**: Run tests via MCP. MCP command: `mcp__drm-copilot__run_poshqc_test`. Use repo config at `scripts/powershell/PoshQC/settings/pester.runsettings.psd1`.
|
|
19
19
|
|
|
20
20
|
Run the toolchain in order: format → analyze → test. Restart from step 1 if any step fails or changes files. Use the MCP server functions; do not substitute VS Code task wrappers.
|
|
21
21
|
|
|
@@ -53,7 +53,7 @@ Introduce the smallest seam that enables reliable mocking. Apply these options i
|
|
|
53
53
|
|
|
54
54
|
## Testing Standards
|
|
55
55
|
|
|
56
|
-
- Use **Pester** (
|
|
56
|
+
- Use **Pester** (v6.x) as the test framework.
|
|
57
57
|
- Organize tests to mirror code structure (e.g., `tests/scripts/dev-tools/ScriptName.Tests.ps1`).
|
|
58
58
|
- Name test files `*.Tests.ps1`.
|
|
59
59
|
- Use `Describe`/`Context`/`It` blocks; one behavior per `It`.
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"Bash(bash .claude/lib/bash/mutate-parallel-run.sh*)",
|
|
12
12
|
"Bash(bash .claude/lib/bash/remove-parallel-item.sh*)",
|
|
13
13
|
"Bash(bash .claude/lib/bash/validate-parallel-manifest.sh*)",
|
|
14
|
+
"Bash(pwsh -NoProfile -NonInteractive -File .claude/lib/parallel-admission/Invoke-ParallelAdmission.ps1*)",
|
|
14
15
|
"Read",
|
|
15
16
|
"Edit(docs/**)",
|
|
16
17
|
"Edit(artifacts/**)",
|
|
@@ -32,7 +32,7 @@ Rules:
|
|
|
32
32
|
- **Tool routes are not restated.** Tool routes, launchers, wrapper scripts, command-text restrictions, the batch budget, hook context, and CI shape are owned by the `execution-environment` skill. A plan references that skill instead of restating its content.
|
|
33
33
|
- **Changed existing behavior names its asserting tests.** A task that changes the observable behavior of an existing function, script, fixture, or test stub (its signature, argv, output, exit status, or the files it writes) names every existing test that asserts that behavior and states each test's disposition: unchanged because it is unaffected, or updated, with the reason for the update. The tests are found by searching the test tree for the symbol, the file name, and the asserted output. A test that asserts the current behavior and is outside the task's file set fails once the change lands, and the plan's own acceptance condition then cannot be met. The planner's adversarial self-review includes this search for every task that changes existing behavior.
|
|
34
34
|
- **Size guideline.** A plan stays within 40 canonical tasks and 400 physical lines. A plan that needs more carries a `## Size Justification` section with at least one line stating why the size is necessary (validator rule G13). Files produced by one generator run count as one generator task.
|
|
35
|
-
- **Pre-Mortem.** Every plan carries a `## Pre-Mortem` section with one bullet beginning with each of the seven labels `Review checklists`, `Coverage`, `Mirror parity`, `File size`, `Test isolation`, `CI-only behavior`, and `Evidence`. Each bullet states how the plan prevents that failure class, or states "not applicable" followed by the reason. The `Test isolation` bullet names the
|
|
35
|
+
- **Pre-Mortem.** Every plan carries a `## Pre-Mortem` section with one bullet beginning with each of the seven labels `Review checklists`, `Coverage`, `Mirror parity`, `File size`, `Test isolation`, `CI-only behavior`, and `Evidence`. Each bullet states how the plan prevents that failure class, or states "not applicable" followed by the reason. The `Test isolation` bullet names the parallel gates the plan uses: one `Invoke-PoshQCParallelTest` run, one `pytest -n auto` run, and Jest through its normal parallel workers, each re-run only after a fix. The `Mirror parity` bullet also covers the execution-environment brief: a plan that alters a fact the brief states (for example, it adds or renames a CI job, changes a required status context, a tool route, or a batch-budget rule) includes a task that updates the brief in the same change, in all six byte-identical copies, and the bullet names that task. Without that task the brief states a superseded fact once the change lands, which breaks the brief's own maintenance rule. The planner SubagentStop hook blocks a plan without a complete section.
|
|
36
36
|
- **Final-phase self-review.** The final phase of every plan contains a self-review task that walks the policy-audit, code-review, and feature-audit templates under `docs/features/templates/policy_audit/` against the branch diff from the merge base and writes `<FEATURE>/evidence/qa-gates/self-review.<timestamp>.md` with one PASS, FAIL, or N/A row per checklist item. A FAIL row is fixed and the QA loop is re-run before the self-review is rewritten; the plan does not complete with a FAIL row.
|
|
37
37
|
|
|
38
38
|
This section takes precedence over the literal-quoting rules of `## Wrap-Tolerant Assertion Authoring (Mandatory)`: those rules govern the asserted value of an acceptance condition, not context.
|
|
@@ -43,12 +43,11 @@ When orchestration selects short path, a minimal plan is still mandatory and mus
|
|
|
43
43
|
|
|
44
44
|
1) Baseline capture block
|
|
45
45
|
- policy reads in required order,
|
|
46
|
-
- baseline
|
|
46
|
+
- static baseline capture (format, lint, type check, and analyzer findings) for each language that has explicit baseline command tasks in the plan; no test suite runs in this block.
|
|
47
47
|
- required artifacts:
|
|
48
48
|
- a Phase 0 policy-read evidence artifact in the canonical evidence location defined by `evidence-and-timestamp-conventions`
|
|
49
49
|
- one baseline artifact per baseline command step (no aggregate-only baseline artifact)
|
|
50
50
|
- each baseline step artifact MUST include: `Timestamp:`, `Command:`, `EXIT_CODE:`, `Output Summary:`
|
|
51
|
-
- baseline test-step artifacts for languages with mandatory coverage policy MUST include numeric coverage headline values in `Output Summary:` (baseline percent and, when applicable, targeted module/new-code percent).
|
|
52
51
|
|
|
53
52
|
2) Delegated implementation block
|
|
54
53
|
- explicit handoff task to the small-path implementation engineer,
|
|
@@ -59,7 +58,7 @@ When orchestration selects short path, a minimal plan is still mandatory and mus
|
|
|
59
58
|
- rerun behavior when any step changes files or fails.
|
|
60
59
|
- one final-QC artifact per QC command step (no aggregate-only final-QC artifact)
|
|
61
60
|
- each final-QC step artifact MUST include: `Timestamp:`, `Command:`, `EXIT_CODE:`, `Output Summary:`
|
|
62
|
-
- final-QC test commands for languages with mandatory coverage policy MUST run in coverage mode and record numeric
|
|
61
|
+
- final-QC test commands for languages with mandatory coverage policy MUST run in coverage mode and record numeric coverage values from the single gate run in `Output Summary:`.
|
|
63
62
|
- final-QC command tasks that are present in the approved plan MUST execute their stated commands; `SKIPPED` is invalid unless the task text itself explicitly authorizes a skip condition.
|
|
64
63
|
|
|
65
64
|
4) Reduced audit block
|
|
@@ -96,7 +95,7 @@ Branching after Phase 0:
|
|
|
96
95
|
|
|
97
96
|
Phase 0 must include tasks to read policy files in the order defined in `policy-compliance-order`.
|
|
98
97
|
|
|
99
|
-
Phase 0 must also capture
|
|
98
|
+
Phase 0 must also capture static baselines (format, lint, type check, and analyzer findings) for the languages touched, and no test suite runs in it. Baseline artifact conventions (location + required fields) are defined in `evidence-and-timestamp-conventions`.
|
|
100
99
|
|
|
101
100
|
For short-path/minimal-audit plans, Phase 0 evidence is incomplete unless both artifacts exist:
|
|
102
101
|
- `phase0-instructions-read.md` with at least: `Timestamp:`, `Policy Order:`, and explicit list of files read.
|
|
@@ -128,12 +127,9 @@ Plans name evidence artifacts `<name>.<timestamp>.md` and never fix a plan-time
|
|
|
128
127
|
|
|
129
128
|
For any language in scope where repository policy requires coverage validation:
|
|
130
129
|
|
|
131
|
-
- The approved plan MUST include explicit
|
|
132
|
-
-
|
|
133
|
-
-
|
|
134
|
-
- baseline coverage,
|
|
135
|
-
- post-change coverage,
|
|
136
|
-
- new/changed-code coverage.
|
|
130
|
+
- The approved plan MUST include an explicit final-QC coverage capture task.
|
|
131
|
+
- The final-QC artifact MUST record numeric coverage values (not placeholders such as `UNVERIFIED`).
|
|
132
|
+
- The plan MUST include a threshold task that reports each changed file from the single gate run against the coverage thresholds. New behavior is tested. No earlier figure is compared.
|
|
137
133
|
- If required coverage values are unavailable, the plan outcome MUST be remediation-required and MUST NOT be reported as PASS.
|
|
138
134
|
|
|
139
135
|
## Final QA Loop (Required for Code/Test Changes)
|
|
@@ -248,7 +244,7 @@ Rules:
|
|
|
248
244
|
- **Observe a command's success-case output before asserting over that output (mandatory).** Run the command, or read a recorded run of it, and confirm the value you intend to assert is actually printed on a *successful* run. Do not infer it from the tool's documentation, from the plan, or from what the tool prints on failure. This requirement exists because the class of defect it prevents is not detectable by reading: an assertion on a line the tool prints only when it changed something is unsatisfiable on a clean run; a demand for a zero-diagnostic count from a tool that returns only an ok flag names a value with no source; a demand for separate line and branch percentages from a coverage run that prints one combined column reads two numbers that are never printed. G7 and G9 cover two decidable slices of this class. The remainder is covered by this requirement and by nothing else, so a reviewer cannot rely on the gate to catch it.
|
|
249
245
|
- **Fix the evidence in the plan; never leave the executor to select it.** An executor free to choose the evidence it is judged against cannot fail. Do not write an acceptance condition that asks the executor to identify "the known-genuine pair", to choose a survivor list, or to pick any suitable instance. Name the instances, or state the mechanical derivation that produces them, so a third party re-running it obtains the same set. This is authoring guidance and not a rule: a validator rule that scanned acceptance text for selection vocabulary was proposed and rejected, because that vocabulary is ordinary plan prose used in roles carrying no selection semantics and a keyword scan over prose is not statically decidable for the property it would claim to detect. The judgment is the author's, and it is not automated. `.claude/rules/plan-acceptance-gates.md` records the rejection and the reason for it.
|
|
250
246
|
- **Check that the task-ordering does not make the condition unsatisfiable.** No rule covers this. A gate that runs a test path containing deliberately-failing cases added by an earlier task, before the later task that makes them pass, cannot exit 0. A baseline captured after a write-mode formatter has already repaired pre-existing drift becomes either a blanket waiver or makes a later gate unsatisfiable. Read each acceptance condition against the state the plan will actually be in when its task runs.
|
|
251
|
-
- **Name the runner and job for a Pester acceptance criterion.** In `.github/workflows/_poshqc.yml`, the Pester suites run with coverage on `windows-latest` in the shard jobs `poshqc / PowerShell QC shard 1`, `shard 2`, and `shard 3`; `poshqc / PowerShell QC` is the aggregating
|
|
247
|
+
- **Name the runner and job for a Pester acceptance criterion.** In `.github/workflows/_poshqc.yml`, the Pester suites run with coverage on `windows-latest` in the shard jobs `poshqc / PowerShell QC shard 1`, `shard 2`, and `shard 3`; `poshqc / PowerShell QC` is the aggregating check, whose result `CI Required Gate` requires, and it requires the static and shard jobs to succeed and merges shard coverage; and `poshqc / PowerShell hook suites (Linux)` runs only `tests/scripts/claude-hooks` and `tests/scripts/codex-hooks` on `ubuntu-latest`, with coverage disabled. The execution-environment brief's `## CI Shape and Required Checks` section is the authoritative description of this shape. A Pester acceptance criterion may cite `ubuntu-latest` only for suites under `tests/scripts/claude-hooks` or `tests/scripts/codex-hooks`, never for coverage, and must name the job it relies on (`poshqc / PowerShell QC` or `poshqc / PowerShell hook suites (Linux)`).
|
|
252
248
|
- **Do not assert a fixed-string search literal that contains a backslash.** Git for Windows grep 3.0 reads a doubled backslash in a `grep -F` pattern as one backslash, so the same check returns a different count locally than on a CI runner and cannot pass in both places. Assert a backslash-free substring of the literal, a named test, or a hash or byte-identity check instead.
|
|
253
249
|
|
|
254
250
|
## Plan-Path Continuity Contract (Mandatory)
|
|
@@ -275,7 +271,7 @@ When a plan is generated or validated from a feature folder, resolve selected mo
|
|
|
275
271
|
|
|
276
272
|
## Mode-Specific Mandatory Plan Gates
|
|
277
273
|
|
|
278
|
-
- `minor-audit` plans MUST include baseline evidence tasks, targeted verification evidence tasks, and end-state evidence tasks.
|
|
274
|
+
- `minor-audit` plans MUST include static baseline evidence tasks, targeted verification evidence tasks read from the gate run, and end-state evidence tasks.
|
|
279
275
|
- `minor-audit` plans MUST require `${feature-folder}/issue.md` to contain an explicit `## Acceptance Criteria` section; do not infer acceptance criteria from other `issue.md` sections.
|
|
280
276
|
- `minor-audit` plans MUST NOT treat missing `spec.md` or `user-story.md` as automatic blockers.
|
|
281
277
|
- `minor-audit` execution/validation/audit MUST fail closed when `spec.md` or `user-story.md` exists unexpectedly in the active folder, when the explicit `## Acceptance Criteria` section is missing from `issue.md`, when required Phase 0 artifacts are missing, or when checklist state contradicts evidence on disk.
|
|
@@ -162,7 +162,9 @@ The script emits pipe-delimited, `LC_ALL=C`-ordered records, one per line:
|
|
|
162
162
|
2. **Editorial triage of the cherry-pick candidates.** Review each
|
|
163
163
|
`COMMIT|...|UNIQUE|...` record — this is the LLM-judgment boundary. Confirm
|
|
164
164
|
editorially that the unique commits are genuinely documentation/agent-memory
|
|
165
|
-
content
|
|
165
|
+
content: paths under the repository-relative prefixes `docs/` and `.claude/agent-memory/`,
|
|
166
|
+
compared case-sensitively. A Markdown file outside those two prefixes (for example
|
|
167
|
+
`CLAUDE.md` or `.claude/rules/*.md`) is not consolidation content.
|
|
166
168
|
The script only reports the deterministic facts (SHA, paths, author, date); deciding
|
|
167
169
|
what counts as documentation is this skill's responsibility.
|
|
168
170
|
|
|
@@ -174,21 +176,42 @@ The script emits pipe-delimited, `LC_ALL=C`-ordered records, one per line:
|
|
|
174
176
|
reuse it silently. Conflicts are aborted and surfaced as `CONFLICT` for editorial
|
|
175
177
|
resolution, never auto-resolved.
|
|
176
178
|
|
|
179
|
+
**Cleanup context.** A cleanup run writes no orchestration checkpoint, so the enforcement
|
|
180
|
+
hooks recognize its operations by the cleanup context instead: the sanctioned-removal
|
|
181
|
+
manifest at the session root (`artifacts/orchestration/cleanup-worktrees-manifest.json` in
|
|
182
|
+
the main checkout where this skill runs, written whole with Write; see Sanctioned Removal
|
|
183
|
+
Manifest) and the consolidation worktree, identified by its branch
|
|
184
|
+
`documentationandmemories`. Any staging in that worktree beyond what the script performs
|
|
185
|
+
uses `git -C <consolidation root> add -- <path>` with paths under `docs/` or
|
|
186
|
+
`.claude/agent-memory/` only, and the commit uses
|
|
187
|
+
`git -C <consolidation root> commit -F <message file>` with no pathspec. The preimplementation
|
|
188
|
+
gate admits that commit only when every staged path is under those two prefixes.
|
|
189
|
+
|
|
177
190
|
4. **Push and hand off PR creation to `Agent(pr-author)`.** Push the consolidation
|
|
178
|
-
branch (`git
|
|
179
|
-
`
|
|
180
|
-
`
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
191
|
+
branch (`git -C <consolidation root> push -u origin documentationandmemories`).
|
|
192
|
+
The push precedes `gh pr create`: the PR-author gate requires
|
|
193
|
+
`refs/remotes/origin/documentationandmemories` to resolve to the same commit as the
|
|
194
|
+
consolidation worktree `HEAD`, so push again after any later commit in that worktree. Refresh the
|
|
195
|
+
PR-context bundle with `mcp__drm-copilot__collect_pr_context` using base branch `main` and
|
|
196
|
+
`workspace_root` set to the consolidation worktree, so that
|
|
197
|
+
`artifacts/pr_context.summary.txt` and `artifacts/pr_context.appendix.txt` exist beneath the
|
|
198
|
+
consolidation worktree. A consolidation pull request has no orchestrator-state checkpoint and
|
|
199
|
+
is not validated against one; the hooks perform the cleanup readiness check instead.
|
|
200
|
+
`enforce-model-routing-receipt.ps1` admits the `Agent(pr-author)` delegation, and
|
|
201
|
+
`enforce-pr-author-skill.ps1` admits `gh pr create`, only while a fresh, valid manifest exists
|
|
202
|
+
at the session root; the PR-author gate also requires an explicit
|
|
203
|
+
`--head documentationandmemories --base main` and a branch diff limited to `docs/` and
|
|
204
|
+
`.claude/agent-memory/`, and its receipt checks still apply. Then delegate PR creation to
|
|
205
|
+
`Agent(pr-author)` per `.claude/skills/pr-author/SKILL.md`, which owns the body-file and
|
|
206
|
+
receipt contract; defer to that skill for it rather than restating any value from it here.
|
|
207
|
+
The delegation is non-isolated and passes the absolute body path beneath the consolidation
|
|
208
|
+
worktree, as that skill's coordinator-session topology requires. For `<N>`,
|
|
187
209
|
use the GitHub issue number the run executes under when the run has one. When the run
|
|
188
210
|
has none, `<N>` is an arbitrary run-scoped identifier chosen by the pr-author agent.
|
|
189
|
-
The delegation prompt MUST carry
|
|
190
|
-
and
|
|
191
|
-
|
|
211
|
+
The delegation prompt MUST carry exactly one `branch: documentationandmemories` label, on
|
|
212
|
+
its own line, and no `--head` or `--branch` text, plus the canonical issue number line when
|
|
213
|
+
the run has an issue number.
|
|
214
|
+
`enforce-model-routing-receipt.ps1` identifies the item from those lines and denies a
|
|
192
215
|
gated delegation it cannot identify. A cleanup run with no issue number is therefore
|
|
193
216
|
identified by the branch label alone, which is why the label is required and the issue line
|
|
194
217
|
is not.
|
|
@@ -397,6 +420,15 @@ specific files or commit SHAs, before step 9 acts on any finding.
|
|
|
397
420
|
`git worktree remove <path>` command only when a record in it covers that exact path. A removal
|
|
398
421
|
issued with no covering record is denied with each gate's existing, unchanged reason code.
|
|
399
422
|
|
|
423
|
+
The manifest lives at the session root: the main checkout where this skill runs. Both removal
|
|
424
|
+
gates, the PR-author gate, and the model-routing gate read the relative path
|
|
425
|
+
`artifacts/orchestration/cleanup-worktrees-manifest.json` against the hook process location,
|
|
426
|
+
which is the session root, so a manifest written in any other worktree is never read. Write the
|
|
427
|
+
whole document with Write; the preimplementation gate admits that Write without a checkpoint
|
|
428
|
+
only at the session-root spelling and only when the content carries the expected `tool` and
|
|
429
|
+
`schema_version`. An Edit of the manifest is not supported without a checkpoint, and neither is a
|
|
430
|
+
Codex `apply_patch` Update, Delete, or Move of it; rewrite the document with Write instead.
|
|
431
|
+
|
|
400
432
|
The document is UTF-8 JSON with `snake_case` keys. It carries six top-level fields. Its `removals`
|
|
401
433
|
and `preserved_files` entries are sibling arrays and are never nested: removal records are keyed by
|
|
402
434
|
worktree path, preserve records by the pair of worktree path and file path, and the gates must
|
|
@@ -445,7 +477,8 @@ These records serve the consolidation consumer and are never read by either gate
|
|
|
445
477
|
consumer reads that worktree's `MEMORY.md`.
|
|
446
478
|
- `source_path` — string, required, repo-relative within that worktree. The file to preserve.
|
|
447
479
|
- `change_class` — string, required, either `untracked` or `modified`, recording whether staging
|
|
448
|
-
adds a new file or carries a working-tree modification.
|
|
480
|
+
adds a new file or carries a working-tree modification. How each class is staged is described
|
|
481
|
+
under `### Preserve staging outcomes`.
|
|
449
482
|
- `disposition` — string, required, exactly `PRESERVE`.
|
|
450
483
|
- `verdict` — string, required, a member of the step-5 verdict vocabulary listed above.
|
|
451
484
|
- `target_path` — string, required, repo-relative on the consolidation branch. Required because the
|
|
@@ -499,6 +532,52 @@ These records serve the consolidation consumer and are never read by either gate
|
|
|
499
532
|
}
|
|
500
533
|
```
|
|
501
534
|
|
|
535
|
+
### Preserve staging outcomes
|
|
536
|
+
|
|
537
|
+
`cleanup-worktrees.sh --preserve` reports each record's outcome as
|
|
538
|
+
`ACTION|preserve-stage|<target_path>|<result>`. The result vocabulary is:
|
|
539
|
+
|
|
540
|
+
- `OK` — the record was written and staged.
|
|
541
|
+
- `FAILED` — a write or staging operation failed; the remaining records continue.
|
|
542
|
+
- `SKIPPED-INVALID` — a record field failed validation.
|
|
543
|
+
- `MISSING-SOURCE` — the source file does not exist in the named worktree.
|
|
544
|
+
- `HOST-TOKEN-BLOCKED` — the incoming bytes carry a host-identifying token; the whole pass stops
|
|
545
|
+
with exit 3 and nothing is staged.
|
|
546
|
+
- `IGNORED-TARGET` — the target path is ignored on the consolidation branch and is not forced.
|
|
547
|
+
- `MISSING-WORKTREE` — the consolidation worktree does not exist.
|
|
548
|
+
- `REFUSED-WOULD-REGRESS` — staging the record would lose a line that the consolidation branch
|
|
549
|
+
already carries, or the record repeats an earlier record's `target_path`.
|
|
550
|
+
|
|
551
|
+
Staging depends on whether `<consolidation-worktree>/<target_path>` is an existing regular file:
|
|
552
|
+
|
|
553
|
+
- Absent target, either `change_class`: the source is copied byte for byte.
|
|
554
|
+
- Existing target, `untracked` record: the source is copied only when every line of the target is
|
|
555
|
+
present in the source in the same order; otherwise the record is refused.
|
|
556
|
+
- Existing target, `modified` record with a merge base (the source path equals the target path, and
|
|
557
|
+
the file exists at the merge base of the worktree `HEAD` and the consolidation `HEAD`): the
|
|
558
|
+
worktree change must only add lines to the base (G1); a `git merge-file --union --object-id`
|
|
559
|
+
merge of the target, the base, and the source then runs; the merged result must keep every target
|
|
560
|
+
line (G2) and must add no line beyond the worktree's own additions (G3). The merged blob is
|
|
561
|
+
staged.
|
|
562
|
+
- Existing target, `modified` record without a merge base: treated as an existing `untracked`
|
|
563
|
+
target.
|
|
564
|
+
- A record whose `target_path` repeats an earlier record's in the same pass is refused; the first
|
|
565
|
+
record keeps the target.
|
|
566
|
+
|
|
567
|
+
A refused record still emits its `PRESERVE|` record, writes a `cleanup-worktrees: refused` line to
|
|
568
|
+
stderr naming the failed guard, appends no `MEMORY.md` index line, and makes the pass exit 1.
|
|
569
|
+
|
|
570
|
+
Residuals:
|
|
571
|
+
|
|
572
|
+
- A resurrected line textually identical to a line the worktree added cannot be distinguished by G3.
|
|
573
|
+
- The merge path requires Git 2.43 or later for `merge-file --object-id`; an older Git fails the
|
|
574
|
+
merge and the record is refused.
|
|
575
|
+
- The order in which `--union` places two insertions at the same position is not specified by Git;
|
|
576
|
+
G2 and G3 bound the result whatever the order.
|
|
577
|
+
- The planning phase writes unreferenced blob objects (`hash-object -w`, `merge-file --object-id`)
|
|
578
|
+
to the object store; it writes no index, ref, or working-tree file.
|
|
579
|
+
- A refused record is not consolidated; the operator consolidates it manually.
|
|
580
|
+
|
|
502
581
|
### Accepted residual
|
|
503
582
|
|
|
504
583
|
Both gates read the command text of the `Bash` tool call they are given. A removal routed
|
|
@@ -30,19 +30,24 @@ source "$SCRIPT_DIR/cleanup_worktrees_actions_lib.sh"
|
|
|
30
30
|
# shellcheck source=.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_detached_lib.sh
|
|
31
31
|
# shellcheck disable=SC1091
|
|
32
32
|
source "$SCRIPT_DIR/cleanup_worktrees_detached_lib.sh"
|
|
33
|
-
#
|
|
34
|
-
#
|
|
33
|
+
# None of the four libraries below requires being sourced last, and none claims to be.
|
|
34
|
+
# Each library's source-time work is limited to function definitions plus constant and
|
|
35
35
|
# environment-default variable assignments; none of them calls a function while being
|
|
36
36
|
# sourced, and no function name is defined by more than one library, so no later source can
|
|
37
37
|
# shadow an earlier definition. Bash resolves a function name when the call runs, not when
|
|
38
38
|
# the caller is defined, so the cross-library calls resolve whatever the order: the
|
|
39
39
|
# disposable-dirt classifier is called BY run_report and BY delete_candidate in the
|
|
40
40
|
# libraries above, and the preserve library calls cleanup_wt_git from the enumeration
|
|
41
|
-
# library
|
|
42
|
-
# therefore grouping for readability only.
|
|
41
|
+
# library, consolidation_worktree_path from the actions library, and the staging decision
|
|
42
|
+
# from the merge library. The order here is therefore grouping for readability only.
|
|
43
43
|
# shellcheck source=.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_dirt_lib.sh
|
|
44
44
|
# shellcheck disable=SC1091
|
|
45
45
|
source "$SCRIPT_DIR/cleanup_worktrees_dirt_lib.sh"
|
|
46
|
+
# The merge library holds the preserve staging decision. It is sourced before the
|
|
47
|
+
# line-ending library so that library stays immediately before the preserve library.
|
|
48
|
+
# shellcheck source=.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_merge_lib.sh
|
|
49
|
+
# shellcheck disable=SC1091
|
|
50
|
+
source "$SCRIPT_DIR/cleanup_worktrees_preserve_merge_lib.sh"
|
|
46
51
|
# The line-ending and index group is placed immediately before the preserve library, whose
|
|
47
52
|
# read-only planning phase calls the functions it defines.
|
|
48
53
|
# shellcheck source=.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_eol_lib.sh
|
|
@@ -69,12 +74,20 @@ Commands:
|
|
|
69
74
|
preserve | --preserve
|
|
70
75
|
Stage the manifest's preserved_files[] findings onto the
|
|
71
76
|
consolidation branch. Takes no operand; the manifest path comes
|
|
72
|
-
from CLEANUP_WT_MANIFEST_PATH.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
from CLEANUP_WT_MANIFEST_PATH. Staging depends on the target and
|
|
78
|
+
change_class: a target absent from the consolidation branch is
|
|
79
|
+
copied byte for byte; an existing target is copied only when
|
|
80
|
+
none of its lines would be lost (untracked, or modified with no
|
|
81
|
+
merge base), or receives a three-way union merge of the
|
|
82
|
+
worktree's added lines (modified with a merge base). A record
|
|
83
|
+
that would lose a line, fails a merge guard, or repeats an
|
|
84
|
+
earlier target_path is refused with
|
|
85
|
+
ACTION|preserve-stage|<target>|REFUSED-WOULD-REGRESS. The
|
|
86
|
+
MEMORY.md index line is carried across using the destination
|
|
87
|
+
file's own re-derived line-ending convention, and the whole pass
|
|
88
|
+
is refused when the incoming bytes carry a host-identifying
|
|
89
|
+
token. Exit 0 clean, 1 something was skipped or refused or an
|
|
90
|
+
index was created, 3 host-token hard stop, 127 a required tool
|
|
78
91
|
could not be resolved.
|
|
79
92
|
--help | -h | help Print this help and exit 0.
|
|
80
93
|
|
|
@@ -12,12 +12,13 @@
|
|
|
12
12
|
# cleanup_worktrees_actions_lib.sh, because it calls cleanup_wt_git (defined in the
|
|
13
13
|
# enumeration library) and consolidation_worktree_path (defined in the actions library).
|
|
14
14
|
#
|
|
15
|
-
# Two-phase design. preserve_plan
|
|
16
|
-
# and every record, verifies each source
|
|
17
|
-
#
|
|
18
|
-
# plan stream.
|
|
19
|
-
#
|
|
20
|
-
#
|
|
15
|
+
# Two-phase design. preserve_plan writes no index, ref, or working-tree file: it validates
|
|
16
|
+
# the manifest and every record, verifies each source exists, runs the host-token
|
|
17
|
+
# pre-pass, takes each staging and index decision, and emits the PRESERVE| and ACTION|
|
|
18
|
+
# records plus an internal plan stream. Its one write is the exception stated in
|
|
19
|
+
# cleanup_worktrees_preserve_merge_lib.sh: unreferenced blob objects created by
|
|
20
|
+
# `hash-object -w` and `merge-file --object-id`. preserve_commit_plan is the only writer of
|
|
21
|
+
# files and is entered only when the pre-pass reported no match.
|
|
21
22
|
#
|
|
22
23
|
# Seams. All git commands go through cleanup_wt_git (CLEANUP_WT_GIT_BIN); jq resolves
|
|
23
24
|
# through preserve_resolve_jq (CLEANUP_WT_JQ_BIN); the manifest path comes from
|
|
@@ -174,9 +175,8 @@ preserve_validate_record() {
|
|
|
174
175
|
# ACTION|preserve-stage|<target-path>|SKIPPED-INVALID; the first violation in the chain
|
|
175
176
|
# below wins, because one bad field skips the record whatever the others say.
|
|
176
177
|
#
|
|
177
|
-
# change_class is validated for vocabulary
|
|
178
|
-
#
|
|
179
|
-
# here so no later change invents a divergent path for one of them.
|
|
178
|
+
# change_class is validated here for vocabulary only; its effect on staging belongs to
|
|
179
|
+
# preserve_merge_decide (absent target copied, existing target guarded or merged).
|
|
180
180
|
#
|
|
181
181
|
# host_token_scan is refused when it is absent, is not a JSON object, is missing either
|
|
182
182
|
# member, or carries a result outside clean/tokens_present: a record whose scan metadata
|
|
@@ -236,16 +236,18 @@ preserve_validate_record() {
|
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
preserve_plan_one() {
|
|
239
|
-
# Plan one manifest record.
|
|
239
|
+
# Plan one manifest record. Writes no index, ref, or working-tree file; the staging
|
|
240
|
+
# decision may write unreferenced blob objects (`hash-object -w`, `merge-file
|
|
241
|
+
# --object-id`), the exception cleanup_worktrees_preserve_merge_lib.sh states.
|
|
240
242
|
#
|
|
241
|
-
# The PRESERVE|
|
|
242
|
-
#
|
|
243
|
-
#
|
|
244
|
-
#
|
|
243
|
+
# The PRESERVE| record is emitted for every record that survives validation, before any
|
|
244
|
+
# per-record outcome is known, as DIRTY|<worktree-path>|<status-line> is; the outcome
|
|
245
|
+
# travels separately on the ACTION| result channel. The source file is read by plain
|
|
246
|
+
# file I/O at <worktree_path>/<source_path>, never through git (see the header).
|
|
245
247
|
#
|
|
246
|
-
# The
|
|
247
|
-
#
|
|
248
|
-
#
|
|
248
|
+
# The plan entry carries ten columns: target_path, source file, destination file, index
|
|
249
|
+
# action, index path, index line, terminator token, leading-terminator flag, staging
|
|
250
|
+
# mode (`copy` or `merge`), and the merged blob id (empty for `copy`).
|
|
249
251
|
#
|
|
250
252
|
# Args: $1 = the tab-separated record. Returns 0 when the record was planned and 1 when
|
|
251
253
|
# it was skipped, refused, or reported.
|
|
@@ -294,6 +296,11 @@ preserve_plan_one() {
|
|
|
294
296
|
printf 'cleanup-worktrees: destination is ignored, refusing to force: %s\n' "$tgt" >&2
|
|
295
297
|
return 1
|
|
296
298
|
fi
|
|
299
|
+
# The staging decision (merge library): a repeated target_path is refused, and a target
|
|
300
|
+
# that already exists is guarded or merged rather than overwritten. A refusal returns
|
|
301
|
+
# before the index decision, so a refused record produces no index record either.
|
|
302
|
+
preserve_merge_check_duplicate "$tgt" || return 1
|
|
303
|
+
preserve_merge_decide "${PRESERVE_FIELDS[2]}" "$wt" "$src" "$tgt" "$PRESERVE_CWT" || return 1
|
|
297
304
|
# The index decision, including the line-ending re-derivation it rests on, lives in
|
|
298
305
|
# the line-ending library. A memory_index_line of JSON null means the file is not a
|
|
299
306
|
# memory entry: it is copied and staged, and no index is read, created, or appended to.
|
|
@@ -307,16 +314,19 @@ preserve_plan_one() {
|
|
|
307
314
|
ipre=$PRESERVE_INDEX_PRE
|
|
308
315
|
fi
|
|
309
316
|
local entry
|
|
310
|
-
printf -v entry '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s' \
|
|
311
|
-
"$tgt" "$srcfile" "$PRESERVE_CWT/$tgt" "$iaction" "$ipath" "$iline" "$iterm" "$ipre"
|
|
317
|
+
printf -v entry '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s' \
|
|
318
|
+
"$tgt" "$srcfile" "$PRESERVE_CWT/$tgt" "$iaction" "$ipath" "$iline" "$iterm" "$ipre" \
|
|
319
|
+
"$PRESERVE_STAGE_MODE" "$PRESERVE_STAGE_OID"
|
|
312
320
|
PRESERVE_PLAN_STREAM+=("$entry")
|
|
313
321
|
return 0
|
|
314
322
|
}
|
|
315
323
|
|
|
316
324
|
preserve_plan() {
|
|
317
|
-
# Phase 1 of the two-phase driver: read, validate, decide, and report. It
|
|
318
|
-
#
|
|
319
|
-
# byte-unchanged and there is nothing to undo.
|
|
325
|
+
# Phase 1 of the two-phase driver: read, validate, decide, and report. It writes no
|
|
326
|
+
# index, ref, or working-tree file, so a failure anywhere in it leaves the consolidation
|
|
327
|
+
# worktree byte-unchanged and there is nothing to undo. The one exception is the staging
|
|
328
|
+
# decision's unreferenced blob objects (`hash-object -w`, `merge-file --object-id`),
|
|
329
|
+
# which nothing references unless phase 2 stages the merged result.
|
|
320
330
|
#
|
|
321
331
|
# Records are processed in LC_ALL=C order of the pair (worktree_path, source_path)
|
|
322
332
|
# rather than in manifest array order, because the report stream's ordering is
|
|
@@ -324,10 +334,8 @@ preserve_plan() {
|
|
|
324
334
|
# a contract. The sort is field-aware rather than whole-line, so a worktree_path that
|
|
325
335
|
# is a prefix of another cannot reorder the pair.
|
|
326
336
|
#
|
|
327
|
-
#
|
|
328
|
-
#
|
|
329
|
-
# per record that reached the writing phase, and PRESERVE_EXIT accumulates the
|
|
330
|
-
# per-record skip signal that becomes the pass's exit code.
|
|
337
|
+
# Outcomes survive the loop on globals: PRESERVE_PLAN_STREAM (one entry per planned
|
|
338
|
+
# record), PRESERVE_EXIT (the per-record skip signal), and PRESERVE_SEEN_TARGETS.
|
|
331
339
|
#
|
|
332
340
|
# Returns 0 when the pass may proceed to the writing phase, 1 when the manifest itself
|
|
333
341
|
# was rejected, 3 on the host-token hard stop, and 127 when a required tool could not
|
|
@@ -337,6 +345,9 @@ preserve_plan() {
|
|
|
337
345
|
PRESERVE_EXIT=0
|
|
338
346
|
PRESERVE_BLOCKED=0
|
|
339
347
|
PRESERVE_CWT=""
|
|
348
|
+
# Read by preserve_merge_check_duplicate in the merge library (SC2034 cannot see it).
|
|
349
|
+
# shellcheck disable=SC2034
|
|
350
|
+
PRESERVE_SEEN_TARGETS=""
|
|
340
351
|
local manifest records sorted line rc=0
|
|
341
352
|
manifest=${CLEANUP_WT_MANIFEST_PATH:-artifacts/orchestration/cleanup-worktrees-manifest.json}
|
|
342
353
|
PRESERVE_CWT=$(consolidation_worktree_path) || return $?
|
|
@@ -353,31 +364,26 @@ preserve_plan() {
|
|
|
353
364
|
[[ -n $line ]] || continue
|
|
354
365
|
preserve_plan_one "$line" || PRESERVE_EXIT=1
|
|
355
366
|
done <<<"$sorted"
|
|
356
|
-
# The hard stop is evaluated
|
|
357
|
-
#
|
|
358
|
-
# for any record. Nothing has been written at this point, so there is nothing to undo.
|
|
367
|
+
# The hard stop is evaluated after every record is examined, so every match is reported
|
|
368
|
+
# and the writing phase is entered for no record; no file has been written to undo.
|
|
359
369
|
((PRESERVE_BLOCKED == 0)) || return 3
|
|
360
370
|
return 0
|
|
361
371
|
}
|
|
362
372
|
|
|
363
373
|
preserve_commit_plan() {
|
|
364
|
-
# Phase 2: the only function in this library that writes
|
|
374
|
+
# Phase 2: the only function in this library that writes files. It executes each plan
|
|
375
|
+
# entry's decisions with exactly four kinds of operation: mkdir -p of the destination
|
|
376
|
+
# directory, the content write, the index append or creation, and the staging call. It
|
|
377
|
+
# takes no staging decision of its own, which keeps it thin enough to stay measured.
|
|
365
378
|
#
|
|
366
|
-
#
|
|
367
|
-
#
|
|
368
|
-
#
|
|
369
|
-
#
|
|
370
|
-
# leave in the coverage denominator rather than exclude from measurement.
|
|
379
|
+
# The content write follows column 9. `merge` writes the merged blob phase 1 recorded
|
|
380
|
+
# (`cat-file blob <oid>`); `copy` or empty copies the source byte for byte. Neither
|
|
381
|
+
# applies a line-ending transformation to the preserved content; the line-ending
|
|
382
|
+
# obligation is scoped to the index append, and staging re-normalizes tracked text.
|
|
371
383
|
#
|
|
372
|
-
#
|
|
373
|
-
#
|
|
374
|
-
|
|
375
|
-
# line-ending obligation is scoped to the index append, where the defect occurred.
|
|
376
|
-
#
|
|
377
|
-
# A non-zero result from any of the three operations emits
|
|
378
|
-
# ACTION|preserve-stage|<target-path>|FAILED and contributes to exit 1; it never aborts
|
|
379
|
-
# the remaining records, because each record's write is independent of the others.
|
|
380
|
-
local entry tgt srcfile dstfile iaction ipath iline iterm ipre fail
|
|
384
|
+
# A failed operation emits ACTION|preserve-stage|<target-path>|FAILED and contributes to
|
|
385
|
+
# exit 1; it never aborts the remaining records, whose writes are independent.
|
|
386
|
+
local entry tgt srcfile dstfile iaction ipath iline iterm ipre mode oid fail
|
|
381
387
|
((${#PRESERVE_PLAN_STREAM[@]} > 0)) || return 0
|
|
382
388
|
for entry in "${PRESERVE_PLAN_STREAM[@]}"; do
|
|
383
389
|
preserve_split_tsv "$entry"
|
|
@@ -389,10 +395,12 @@ preserve_commit_plan() {
|
|
|
389
395
|
iline=${PRESERVE_FIELDS[5]}
|
|
390
396
|
iterm=${PRESERVE_FIELDS[6]}
|
|
391
397
|
ipre=${PRESERVE_FIELDS[7]}
|
|
392
|
-
fail=""
|
|
398
|
+
mode=${PRESERVE_FIELDS[8]-} oid=${PRESERVE_FIELDS[9]-} fail=""
|
|
393
399
|
if ! mkdir -p -- "${dstfile%/*}" 2>/dev/null; then
|
|
394
400
|
fail="cannot create the destination directory"
|
|
395
|
-
elif ! cat
|
|
401
|
+
elif [[ $mode == "merge" ]] && ! cleanup_wt_git -C "$PRESERVE_CWT" cat-file blob "$oid" >"$dstfile"; then
|
|
402
|
+
fail="reading the merged blob failed"
|
|
403
|
+
elif [[ $mode != "merge" ]] && ! cat -- "$srcfile" >"$dstfile" 2>/dev/null; then
|
|
396
404
|
fail="the verbatim byte copy failed"
|
|
397
405
|
elif [[ $iaction != "none" ]] &&
|
|
398
406
|
! preserve_render_index_append "$ipath" "$iline" "$iterm" "$ipre"; then
|