@danmoisan/drm-copilot-mcp 1.1.4 → 1.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/out/mcp-server.js +286 -10
  2. package/package.json +1 -1
  3. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +477 -0
  4. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +120 -12
  5. package/resources/claude-customizations/.claude/rules/plan-acceptance-gates.md +131 -2
  6. package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +9 -0
  7. package/resources/claude-customizations/config/orchestration-routing.json +1 -0
  8. package/resources/claude-customizations/pack-manifests/core.json +1 -0
  9. package/resources/codex-and-agents-customizations/.agents/skills/codex-model-routing/SKILL.md +10 -0
  10. package/resources/codex-and-agents-customizations/.codex/agents/commit-steward-c1.toml +22 -0
  11. package/resources/codex-and-agents-customizations/.codex/agents/commit-steward-c2.toml +22 -0
  12. package/resources/codex-and-agents-customizations/.codex/agents/commit-steward-c3-elevated.toml +22 -0
  13. package/resources/codex-and-agents-customizations/.codex/agents/commit-steward-c3.toml +22 -0
  14. package/resources/codex-and-agents-customizations/.codex/agents/commit-steward-c4.toml +22 -0
  15. package/resources/codex-and-agents-customizations/.codex/agents/commit-steward.toml +2 -0
  16. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c1.toml +7 -0
  17. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c2.toml +7 -0
  18. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3-elevated.toml +7 -0
  19. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3.toml +7 -0
  20. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c4.toml +7 -0
  21. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +7 -0
  22. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
  23. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +477 -0
  24. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +125 -12
  25. package/resources/codex-and-agents-customizations/pack-manifests/core.json +8 -1
  26. package/resources/config/orchestration-routing.json +1 -0
  27. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +10 -2
@@ -36,10 +36,18 @@ Every finding string begins with the square-bracketed `P#-T#` identifier of the
36
36
  | **G4** | A `--cov` value supplied space-separated (`--cov <value>`) rather than with `=`. The ambiguous form can bind the following positional argument. Independent of resolvability, so it is reported for every value. | **Warning** |
37
37
  | **G5** | A checkable search literal that is absent from the tracked tree **and** not quoted in the plan document outside the command span it was read from. | **Warning** (see below) |
38
38
  | **G6** | A checkable search literal absent from every single line of a tracked file but present in that file's sliding-window join of adjacent lines. A line-oriented search returns zero matches. | **Warning** |
39
+ | **G7** | A write-mode command — one matching a write-mode register entry, that is a tool that rewrites tracked source and exits 0 after rewriting — whose attributed task text carries none of that entry's observation markers. The exit code alone cannot distinguish a clean run from a repairing one, so the acceptance condition holds either way. | **Warning** |
40
+ | **G8** | A `git diff` invocation carrying no non-flag ref operand and neither `--cached` nor `--staged`. It compares the worktree against the index, which is ambient state: the comparison passes vacuously once the change is committed. Exonerated when the attributed task text carries a second `git diff` or a `git status` span. | **Warning** |
41
+ | **G8b** | A `git diff` invocation carrying a non-flag ref operand together with `--name-only` or `--name-status`, whose attributed task text carries neither a `git add` span nor a `git status --porcelain` span. A name-listing diff enumerates tracked changes only, so a path the plan creates is invisible to it. | **Warning** |
42
+ | **G9** | A command carrying a `--cov` token, carrying no token beginning `--cov-report=term` and no token beginning `--cov-fail-under`, whose project `addopts` value also carries no `--cov-report=term`. No coverage table is printed, so a coverage number the acceptance condition demands can never be read. | **Warning** |
43
+
44
+ G1 through G9 are the complete shipped set. G1 through G6 were added by issue #486 and G7 through G9 by issue #519; the parenthetical in this file's title names the original set only.
39
45
 
40
46
  G1 through G4 form a cascade over each `--cov` value: the value is decided once, so a value G1 rejects is never additionally reported by G2 or G3. G4 is evaluated independently of the cascade because the ambiguous form is a defect whatever the value resolves to. G6 is evaluated before G5, because cross-line presence falsifies G5's tree-absence claim.
41
47
 
42
- G1 and G4 are context-free and run on every invocation. G2, G3, G5, and G6 require a repository seam; with no context supplied they do not run, and the Blocking list is byte-identical to the pre-change output for the same text.
48
+ G8b is a distinct rule from G8 and not a sub-case of it: G8 reports a diff with no ref operand, G8b reports one that has a ref operand but cannot observe an untracked path. A single invocation can satisfy only one of the two, because the presence of a ref operand decides between them.
49
+
50
+ G1 and G4 are context-free and run on every invocation. G2, G3, G5, and G6 require a repository seam; with no context supplied they do not run, and the Blocking list is byte-identical to the pre-change output for the same text. G7, G8, and G8b are likewise context-free and run on every invocation. G9 requires the repository seam, because it reads the project `addopts` value through it, so with no context supplied G9 does not run. All four of the rules added by issue #519 ship in the Warning channel, so none of them can alter the Blocking list at all.
43
51
 
44
52
  ### Attribution window
45
53
 
@@ -55,7 +63,7 @@ A repository seam that raises, or that reports a non-zero exit, causes G2, G3, G
55
63
 
56
64
  The shipped G5 severity was not chosen by argument. It was fixed by a pre-declared rule applied to a measurement over the committed plan corpus: Blocking if and only if the total G5 finding count is greater than zero **and** the recorded false-positive count is zero; otherwise Warning.
57
65
 
58
- The measurement is recorded in `docs/features/active/2026-08-17-reject-unfalsifiable-acceptance-gates-in-atomic-plans-486/evidence/qa-gates/g5-corpus-measurement.2026-08-20T12-02.md`. It scanned 166 plan files, evaluated 100 candidate literals, and produced a total G5 finding count of 0. A zero false-positive count over zero findings measures nothing, so the first conjunct failed and **G5 ships as a Warning**.
66
+ The measurement is recorded in `docs/features/completed/2026-08-17-reject-unfalsifiable-acceptance-gates-in-atomic-plans-486/evidence/qa-gates/g5-corpus-measurement.2026-08-20T12-02.md`. That feature has since been completed and its folder moved out of the active tree, so the citation names the completed tree; the path this file previously carried, under `docs/features/active/`, no longer resolves. It scanned 166 plan files, evaluated 100 candidate literals, and produced a total G5 finding count of 0. A zero false-positive count over zero findings measures nothing, so the first conjunct failed and **G5 ships as a Warning**.
59
67
 
60
68
  The zero count is a property of the corpus, not a defect in the measurement. Every committed plan is a tracked file, so a fixed-string search for a literal quoted inside a committed plan always finds at least that plan itself, and the tree-absence condition holds for no committed candidate. The measurement artifact records the four checks that established this (non-vacuous enumeration, a working repository seam, a self-hit on every sampled lookup, and predicate-order equivalence with the shipped rule).
61
69
 
@@ -75,6 +83,127 @@ Rejecting such a plan would block a correct plan on evidence about a state the p
75
83
 
76
84
  The window size is fixed at four adjacent non-blank lines. Blank lines are removed before windowing, and one window is emitted per start position, so the boundary is exact: two lines further apart than the window size never appear in the same join. The size is recorded here rather than left implicit so that a later feature can revise it against measured wrap-depth data instead of re-deriving it.
77
85
 
86
+ ### The shared measurement behind G7, G8, G8b, and G9
87
+
88
+ The four severities below were fixed by one corpus measurement recorded in `docs/features/active/2026-08-23-plan-acceptance-gates-miss-unobservable-and-ambient-state-gates-519/evidence/qa-gates/corpus-measurement.2026-08-24T00-00.md`. The pre-declared decision rule was written and committed **before** the driver existed and before any count was taken, so the ordering is verifiable from git history rather than only asserted in prose. Its form matches the G5 precedent: the shipped severity is Blocking if and only if the total finding count for that rule is greater than zero **and** the recorded false-positive count for that rule is zero; otherwise Warning.
89
+
90
+ The false-positive definition the rule consumes is likewise pre-declared: a finding is a false positive when the acceptance condition it reports is in fact falsifiable — when the plan states an observation sufficient to distinguish a passing run from a failing one, by a mechanism the rule's predicate does not recognise. A finding is a true positive when the acceptance condition it reports genuinely cannot fail, or can only be satisfied vacuously.
91
+
92
+ The measurement scanned 194 plan files under `docs/features`, covering the `active`, `completed`, and `archive` trees. Unlike the G5 measurement, every rule here found findings, so each false-positive count is a count over an examined population rather than over an empty one. The vacuity declaration therefore applies to no rule of this set.
93
+
94
+ | Rule | Corpus files | Candidates | Findings | True positives | False positives | Decision | Shipped |
95
+ | --- | --- | --- | --- | --- | --- | --- | --- |
96
+ | G7 | 194 | 519 | 466 | 444 | 22 | second conjunct fails | **Warning** |
97
+ | G8 | 194 | 237 | 82 | 75 | 7 | second conjunct fails | **Warning** |
98
+ | G8b | 194 | 47 | 19 | 19 | 0 | pre-declared unconditional clause | **Warning** |
99
+ | G9 | 194 | 273 | 8 | 4 | 4 | second conjunct fails | **Warning** |
100
+
101
+ ### G7 — ships as a Warning because the measurement recorded 22 false positives
102
+
103
+ G7's finding count of 466 satisfies the first conjunct, so the rule was not decided by a vacuous measurement. It fails the second conjunct: 22 of the 466 findings are false positives, in two classes named in full in the measurement artifact.
104
+
105
+ **Class 1, two findings — read-only argv shape.** The `prettier-write` register entry matches the argv shape `npm run format` and declares no exclusion for a check flag, so a check-mode invocation written as `npm run format -- --check` is matched as if it wrote. That command does not write and exits non-zero on drift, so its acceptance condition is falsifiable by the exit code alone.
106
+
107
+ **Class 2, twenty findings — the task observes the tree rather than the tool's stdout.** The attributed task text carries a `git status --porcelain` or `git status` span, so the plan distinguishes a clean run from a repairing one by comparing the tree before and after. G7's marker set recognises tool-output observation only, so it does not see this mechanism. Class 2 is the larger of the two and is the reason the rule cannot ship Blocking on this measurement: a plan that observes the tree has stated a real acceptance condition, and rejecting it would block a correct plan.
108
+
109
+ Both classes are addressable by a later feature — Class 1 by adding a check-flag exclusion to the `prettier-write` entry, Class 2 by admitting a tree-observation span as an alternative to a marker — but neither was changed here, because narrowing a predicate after reading its measurement would invalidate the measurement that decided its severity. A later feature that narrows either class must re-take the measurement the same way.
110
+
111
+ Counts, and every one of the 22 false positives named by plan path, task identifier, and offending span: `docs/features/active/2026-08-23-plan-acceptance-gates-miss-unobservable-and-ambient-state-gates-519/evidence/qa-gates/corpus-measurement.2026-08-24T00-00.md`.
112
+
113
+ ### G8 — ships as a Warning because the measurement recorded 7 false positives
114
+
115
+ G8's finding count of 82 satisfies the first conjunct. It fails the second: 7 findings are false positives, in two classes.
116
+
117
+ **Class 1, six findings — `--no-index`.** `git diff --no-index` compares two named paths on disk. It does not compare the worktree against the index, so G8's stated claim that the comparison passes vacuously once the change is committed is false for this form.
118
+
119
+ **Class 2, one finding — the unmerged-path filter.** `--diff-filter=U` selects conflicted paths during a merge or rebase. In that state the worktree-against-index comparison is the correct one and does not become vacuous on commit, because the conflict is precisely what is not yet committed.
120
+
121
+ Counts, and every one of the 7 false positives named by plan path, task identifier, and offending span: `docs/features/active/2026-08-23-plan-acceptance-gates-miss-unobservable-and-ambient-state-gates-519/evidence/qa-gates/corpus-measurement.2026-08-24T00-00.md`.
122
+
123
+ ### G8b — ships as a Warning unconditionally, by the pre-declared rule
124
+
125
+ G8b is exempt from the two-conjunct rule and **cannot reach the Blocking channel by any measured outcome**. That exemption was declared before the counts were taken, and it holds even though G8b is the only rule of the four whose measured false-positive count is zero.
126
+
127
+ The reason is that G8b carries the highest false-positive surface of the set, and a false-positive count taken over one corpus does not bound the false-positive surface of a predicate. Promoting a rule on the strength of a clean run over one corpus would convert an accident of that corpus into a gate. The 19 findings were nonetheless examined individually and all 19 were retained as true positives, across three sub-classes: a placeholder ref operand, which resolves to a real ref at run time and still cannot make the diff see an untracked path; an artifact-field label inside the span, which is cosmetic and leaves the underlying acceptance condition as the finding describes it; and a pathspec written without the `--` separator, where the predicate reads the pathspec as a ref operand. That last sub-class is a true positive for G8b and is simultaneously recorded in the measurement as a **G8 false negative**: the same span should also have been reported by G8, and was not.
128
+
129
+ Counts, the zero false-positive record, and the three sub-classes with their plan paths and offending spans: `docs/features/active/2026-08-23-plan-acceptance-gates-miss-unobservable-and-ambient-state-gates-519/evidence/qa-gates/corpus-measurement.2026-08-24T00-00.md`.
130
+
131
+ ### G9 — ships as a Warning because the measurement recorded 4 false positives
132
+
133
+ G9's finding count of 8 satisfies the first conjunct. It fails the second: 4 of the 8 findings are false positives, and all four share one cause — the offending span is not a command the plan states as an acceptance condition. Two are prose quotations of a flag or flag pair used to describe something the task declares out of scope; one is a test-data literal inside a sentence asserting a helper's return values; and one is a truncated restatement of a command whose full form on the task line does supply a terminal reporter. In every one of the four, the acceptance condition the task actually states is decided by a pass count, an exit code, or an artifact field, not by a coverage number.
134
+
135
+ The remaining 4 findings are true positives, and each is the exact defect the rule was written for: the acceptance condition demands a numeric coverage percentage, the command supplies no terminal reporter, the project `addopts` supplies only an LCOV reporter, and the number the acceptance demands is therefore never printed.
136
+
137
+ Counts, and every one of the 4 false positives named by plan path, task identifier, offending span, and the reason its acceptance condition is falsifiable: `docs/features/active/2026-08-23-plan-acceptance-gates-miss-unobservable-and-ambient-state-gates-519/evidence/qa-gates/corpus-measurement.2026-08-24T00-00.md`.
138
+
139
+ ## The Write-Mode Register
140
+
141
+ G7 reads a fixed register of six entries. Each entry is an argv predicate plus a set of observation markers matched case-sensitively as substrings of the owning task's attributed text. The register is data, not code, so the same six entries are transcribed into the TypeScript twin without porting behaviour.
142
+
143
+ ### Membership criterion
144
+
145
+ **A tool belongs in the write-mode register when it rewrites tracked source and still exits 0 after rewriting.** That conjunction is the whole criterion. The exit code of such a tool is the same on a clean run and on a repairing run, so a plan that states the invocation as an acceptance condition and records nothing but the exit code has asserted nothing the tool can fail. The register's markers name the literals the tool's success-case output prints, which is the observation that separates the two runs.
146
+
147
+ The six entries are `black-write`, `ruff-fix`, `prettier-write`, `poshqc-format`, `run_poshqc_analyze_autofix`, and `poshqc-suite`. The fifth is named for the MCP tool `run_poshqc_analyze_autofix`, whose argv predicate is an argv word ending with that name.
148
+
149
+ ### Executable-position constraint
150
+
151
+ A word satisfies an entry's argv shape only when its index lies within the leading four-word scan window and the word immediately preceding it does not begin with a hyphen. A tool name supplied as the operand of a search flag is therefore never read as an invocation, which mirrors the extractor's existing rule that a grep-family name appearing as an operand is not the executable. Without this constraint a task that searches a policy file for a register member's name would report a finding against its own search command — including a task that searches this file.
152
+
153
+ ### Exclusions, with the reason for each
154
+
155
+ Two tools that do write are deliberately **not** register members.
156
+
157
+ - **`git add` is excluded.** A plan stages in order to make a later diff complete, so its acceptance concerns the diff, not the staging. The staging itself carries no acceptance condition to make unfalsifiable, and G8b already reads a `git add` span as an exonerating companion rather than as an offence.
158
+ - **`npm ci` is excluded.** Its only write target is git-ignored, so it rewrites no tracked source and fails the membership criterion's first half. A plan can still state a real observation of it — an installed-package count, or the existence of a resolved binary — but it is not a case G7 needs to report.
159
+
160
+ ### Two writers that are not register members and are not exclusions
161
+
162
+ Two further tools write files without being register members, and they are recorded here so a later maintainer does not read their absence as an oversight.
163
+
164
+ - **The Python test runner** writes coverage output under the artifacts tree, for example the LCOV file the project `addopts` value names. It rewrites no tracked source, and its exit code already distinguishes a passing run from a failing one, so it fails the membership criterion on both halves.
165
+ - **The PoshQC test tool** likewise writes result and coverage files under the artifacts tree without rewriting tracked source, and likewise reports pass and fail through its own result. The three PoshQC entries that *are* members — format, analyze-autofix, and the suite — are members because they rewrite tracked PowerShell source in place.
166
+
167
+ A tool that writes only under the artifacts tree is therefore outside the register by construction. The register is about tracked source, not about writing in general.
168
+
169
+ ### Known false-negative class — the single-token tool-name span
170
+
171
+ The command extractor drops any command span shorter than two shell words. That two-word minimum-argv floor predates these rules, is pinned by an existing test, and was deliberately left unchanged: relaxing it would newly admit a single-word coverage-argument span into the G1 and G4 scan, which would change existing output, and changing existing output is exactly what this addition forbids itself.
172
+
173
+ The consequence is a false-negative class. **A tool invoked as a bare single-token name is never extracted, so G7 can never report it, however unobservable its acceptance condition is.** This is the form plans commonly use for MCP tools, including the PoshQC formatter, the PoshQC analyzer autofix tool, and the PoshQC composite suite tool — three of the six register entries. Those three entries are reachable only by a span whose first word is the tool name and whose second word is an operand, for example the tool name followed by a path.
174
+
175
+ This is a stated limitation, not a promise deferred, and it is recorded here for the same reason the placeholder guard's false-negative class is recorded above: it is the cost side of a trade, and a later feature must weigh it rather than rediscover it. The limitation is pinned by a test asserting that a single-token tool-name span produces zero findings from every one of the four rules, so the boundary cannot move silently.
176
+
177
+ A later feature may revisit the floor, but only together with a plan for the coverage-rule output change that relaxing it would cause. The two cannot be separated: the floor is one value read by one extractor feeding every rule, so any relaxation reaches G1 and G4 as well as G7.
178
+
179
+ ## Deliberately Uncovered Sub-Classes
180
+
181
+ Issue #519 measured five classes of unfalsifiable acceptance condition on a single plan. G7 and G9 cover two decidable slices of the first, G8 and G8b cover the third. The remainder is recorded here so a reviewer knows what these rules do **not** reach and that human attention is still required for it.
182
+
183
+ ### The general unobservable-success-output class, beyond what G7 and G9 reach
184
+
185
+ The class is: an acceptance condition that asserts over output the command does not emit on a successful run. G9 covers the slice where a coverage command prints no table at all, and G7 covers the slice where a write-mode tool's exit code is identical on a clean and a repairing run. Neither reaches the general case.
186
+
187
+ Three measured instances outside their reach illustrate why. A gate requiring a formatter's `reformatted` line to be recorded verbatim is unsatisfiable on a clean run, because that line is printed only when a file was rewritten. A gate demanding a zero-diagnostic count from an analyzer that returns only an ok flag and a one-sentence summary names a value that has no source. A gate demanding separate line and branch percentages from a coverage run that prints one combined `Cover` column reads two numbers that are never printed.
188
+
189
+ **Deciding these requires knowing each tool's success-case output, which is not derivable from the plan text, the rules, or the tool documentation.** That is what makes the class invisible to review: four careful review cycles on the measured plan missed it entirely, and it surfaced only when the reviewer ran the tools and observed what they actually printed. A rule would need a per-tool output model, which is a different mechanism from a register of argv predicates. The class is therefore addressed by an authoring requirement in `.claude/skills/atomic-plan-contract/SKILL.md` — that a plan author observe a command's success-case output before asserting over that output — and not by a rule.
190
+
191
+ ### The task-ordering class
192
+
193
+ The class is: an acceptance condition that is unsatisfiable because of where its task sits in the plan rather than because of what the command does. 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 the later gate unsatisfiable.
194
+
195
+ **No rule covers this class.** Detecting it requires intra-plan dependency reasoning across phases: the validator would have to model which task changes which file, and which later assertion depends on that change. That is a different analysis from the per-command predicates these rules apply. It is recorded here so a reviewer knows the class still needs human attention.
196
+
197
+ ### The executor-choice heuristic — rejected, and closed rather than deferred
198
+
199
+ The proposal was a rule that flags selection vocabulary in acceptance text — "any", "a suitable", "the known", "choose" — on the reasoning that an executor free to pick the evidence it is judged against cannot fail. The underlying concern is real and was measured: two conditions on the examined plan asked the executor to identify "the known-genuine pair" and to choose a survivor list.
200
+
201
+ **The rule is rejected.** The vocabulary it would scan for is ordinary plan prose used in roles that carry no selection semantics, and the research recorded a corpus instance in which the word "any" appears inside a *prohibition* rather than a selection — a case the scan would report and the author would be right to ignore. A keyword scan over prose is not statically decidable for the property the rule would claim to detect. This file's own guidance is to weigh a new rule on its authoring-time false-positive rate rather than on how many committed plans it would have flagged, and on that test the proposal fails.
202
+
203
+ The concern is addressed as authoring guidance in `.claude/skills/atomic-plan-contract/SKILL.md` instead, where a false positive costs an author a moment's judgment rather than a blocked plan.
204
+
205
+ **This is closed, not deferred.** Reviving it requires new evidence about its false-positive rate on plan prose, not a restatement of the original proposal.
206
+
78
207
  ## Checkable-Literal Definition and the Placeholder Guard
79
208
 
80
209
  G5 and G6 apply only to a *checkable* literal. The specification defines a checkable literal by two conditions: the command carries the fixed-string flag `-F`, or the pattern contains none of the regular-expression metacharacters `. * [ ] ^ $ \ ( ) { } | + ?`. That condition is conservative in POSIX BRE, POSIX ERE, PCRE, and the Rust regex dialect simultaneously, so no dialect-selection logic is required.
@@ -159,6 +159,8 @@ Before a plan can be treated as approved:
159
159
 
160
160
  The same validator call also applies the acceptance-gate rules G1 through G6 defined in `.claude/rules/plan-acceptance-gates.md`. Those rules report acceptance conditions that cannot fail — a coverage argument that collects no data, or a search for a literal that returns zero matches whatever the executor does. They run automatically on the existing `plan` route with no additional flag. Blocking findings appear in the validator's error output and fail the gate; Warnings are surfaced without failing it, prefixed with `PLAN GATE WARNING: ` on the CLI and carried on the optional `warnings` field of the MCP result. Read that rule file before authoring acceptance conditions.
161
161
 
162
+ The same call additionally applies the rules G7, G8, G8b, and G9, which report a write-mode command observed only by its exit code, an unanchored `git diff`, a name-listing diff with no companion span, and a coverage command that prints no table. All four ship in the Warning channel, so they surface without failing the gate. The complete shipped set is therefore G1 through G9.
163
+
162
164
  ## Wrap-Tolerant Assertion Authoring (Mandatory)
163
165
 
164
166
  An acceptance condition must be able to fail. A condition whose command returns the same result whatever the executor does verifies nothing, however precise it reads. Author every acceptance condition in a wrap-tolerant form: one that survives line wrapping and shell quoting in the file it asserts against.
@@ -171,6 +173,13 @@ Rules:
171
173
  - **Dotted coverage-argument form.** Coverage assertions must name an importable dotted module, for example `--cov=scripts.dev_tools.plan_gate_discrimination`. The filesystem-path spellings `--cov=scripts/dev_tools/module.py` and `--cov=scripts/dev_tools/module` collect no data, so a coverage threshold asserted against them cannot fail. Rules G1 through G3 report those spellings.
172
174
  - **Use the `=` form, not the space-separated form.** `--cov <value>` can bind the following positional argument. Rule G4 reports it.
173
175
  - **Quote what the task will create.** When an asserted literal does not yet exist in the tree, quote the exact literal in the plan prose outside the command span. The gate reads that quotation as the executor's instruction and exonerates the assertion; a paraphrase does not.
176
+ - **Record an observation beyond the exit code for a write-mode command.** A formatter or a fixing linter rewrites tracked source and still exits 0 after rewriting, so its exit code is identical on a clean run and on a repairing one. State, in the task text, the literal its success-case output prints — for example the summary line a formatter prints when it changed nothing — or state a before-and-after tree observation. Rule G7 in `.claude/rules/plan-acceptance-gates.md` reports a write-mode command whose task text carries neither.
177
+ - **Anchor every `git diff` to a ref.** A `git diff` with no ref operand and no `--cached` compares the worktree against the index, which is ambient state: it passes vacuously once the change is committed, so the assertion cannot fail for the executor who commits before running it. Supply an explicit ref operand, usually the base branch. Rule G8 reports the unanchored form.
178
+ - **Pair a name-listing diff with a staging or porcelain-status companion.** An anchored `git diff --name-only` or `--name-status` enumerates tracked changes only, so it can never report a file the task creates, and an assertion that it lists newly created files always sees an empty list. Add a `git add` span or a `git status --porcelain` span in the same task. Rule G8b reports a name-listing diff with neither companion. The two mechanisms are complementary and each alone is wrong in one state: the anchored diff is blind to untracked files, and porcelain status goes empty once the change is committed.
179
+ - **Pass a terminal reporter to every coverage command.** The project `addopts` value supplies an LCOV reporter only, so a coverage command that does not pass `--cov-report=term-missing` prints no coverage table at all, and a numeric percentage the acceptance condition demands can never be read from it. Rule G9 reports a coverage command that supplies no terminal reporter and no `--cov-fail-under` threshold.
180
+ - **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.
181
+ - **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.
182
+ - **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.
174
183
 
175
184
  ## Plan-Path Continuity Contract (Mandatory)
176
185
 
@@ -346,6 +346,7 @@
346
346
  "task-researcher",
347
347
  "prd-feature",
348
348
  "pr-author",
349
+ "commit-steward",
349
350
  "python-typed-engineer",
350
351
  "powershell-typed-engineer",
351
352
  "csharp-typed-engineer",
@@ -34,6 +34,7 @@
34
34
  ".claude/hooks/enforce-model-routing-receipt.ps1",
35
35
  ".claude/hooks/enforce-orchestration-preimplementation-gate.ps1",
36
36
  ".claude/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1",
37
+ ".claude/hooks/enforce-orchestration-preimplementation-gate-modes.ps1",
37
38
  ".claude/hooks/enforce-parallel-abandon-gate.ps1",
38
39
  ".claude/hooks/enforce-parallel-cohort-barrier.ps1",
39
40
  ".claude/hooks/enforce-parallel-cohort-barrier-helpers.ps1",
@@ -65,6 +65,16 @@ epic root personas are forced independently of file count.
65
65
  7. Spawn the generated agent profile. Do not spawn the base alias and claim that
66
66
  a different model was selected.
67
67
 
68
+ ## Normal routed-delegation launch binding
69
+
70
+ Before every normal nested `spawn_agent` call, resolve independently for that delegation. Validate the generated profile name, model, reasoning effort, path, and SHA-256 against the resolver result and the generated profile on disk. Add
71
+ the exact validated receipt to `codex_model_routing_receipts[]`, including its non-empty `phase` and delegation identifier, in the selected checkpoint that `SubagentStart` reads. Durably flush the selected checkpoint before launch, then launch only the resolver-returned `deployment_agent`.
72
+
73
+ Reject the launch when the receipt is late, a generic alias is supplied, the
74
+ checkpoint is ambiguous, profile validation fails, persistence or durable flush
75
+ fails, or start attestation returns `routing_valid: false`. Do not accept child output or child mutations after `routing_valid: false`; retain downstream
76
+ recorder, authority-store, mutation-gate, and stop-gate enforcement.
77
+
68
78
  The route name `feature-review` resolves to the native
69
79
  `feature-reviewer-<profile>` agent family; retain `feature-review` as the
70
80
  receipt's logical agent name.
@@ -0,0 +1,22 @@
1
+ name = "commit-steward-c1"
2
+ description = "Generate a high-signal conventional commit message for the current repository based on staged changes only."
3
+ model = "gpt-5.6-luna"
4
+ model_reasoning_effort = "low"
5
+
6
+ developer_instructions = """
7
+ You are a commit-message specialist.
8
+
9
+ Use the following repo-local skill as the canonical workflow source:
10
+ - commit-message-conventions
11
+
12
+ Core behavior:
13
+ - Generate an audit-quality Git commit message for the current repository.
14
+ - Use an explicitly supplied commit-context artifact when one is provided.
15
+ - Otherwise inspect the local staged state directly with non-destructive Git commands.
16
+ - Do not create the commit. Do not stage, unstage, or modify files.
17
+ - Treat the shared skill as the source of truth for commit classification, formatting, interpretation, and prohibitions.
18
+
19
+ Final response contract:
20
+ - Output exactly one fenced `text` code block containing only the commit message.
21
+ - Do not include commentary, alternatives, or explanations outside the code block.
22
+ """
@@ -0,0 +1,22 @@
1
+ name = "commit-steward-c2"
2
+ description = "Generate a high-signal conventional commit message for the current repository based on staged changes only."
3
+ model = "gpt-5.6-terra"
4
+ model_reasoning_effort = "medium"
5
+
6
+ developer_instructions = """
7
+ You are a commit-message specialist.
8
+
9
+ Use the following repo-local skill as the canonical workflow source:
10
+ - commit-message-conventions
11
+
12
+ Core behavior:
13
+ - Generate an audit-quality Git commit message for the current repository.
14
+ - Use an explicitly supplied commit-context artifact when one is provided.
15
+ - Otherwise inspect the local staged state directly with non-destructive Git commands.
16
+ - Do not create the commit. Do not stage, unstage, or modify files.
17
+ - Treat the shared skill as the source of truth for commit classification, formatting, interpretation, and prohibitions.
18
+
19
+ Final response contract:
20
+ - Output exactly one fenced `text` code block containing only the commit message.
21
+ - Do not include commentary, alternatives, or explanations outside the code block.
22
+ """
@@ -0,0 +1,22 @@
1
+ name = "commit-steward-c3-elevated"
2
+ description = "Generate a high-signal conventional commit message for the current repository based on staged changes only."
3
+ model = "gpt-5.6-sol"
4
+ model_reasoning_effort = "high"
5
+
6
+ developer_instructions = """
7
+ You are a commit-message specialist.
8
+
9
+ Use the following repo-local skill as the canonical workflow source:
10
+ - commit-message-conventions
11
+
12
+ Core behavior:
13
+ - Generate an audit-quality Git commit message for the current repository.
14
+ - Use an explicitly supplied commit-context artifact when one is provided.
15
+ - Otherwise inspect the local staged state directly with non-destructive Git commands.
16
+ - Do not create the commit. Do not stage, unstage, or modify files.
17
+ - Treat the shared skill as the source of truth for commit classification, formatting, interpretation, and prohibitions.
18
+
19
+ Final response contract:
20
+ - Output exactly one fenced `text` code block containing only the commit message.
21
+ - Do not include commentary, alternatives, or explanations outside the code block.
22
+ """
@@ -0,0 +1,22 @@
1
+ name = "commit-steward-c3"
2
+ description = "Generate a high-signal conventional commit message for the current repository based on staged changes only."
3
+ model = "gpt-5.6-terra"
4
+ model_reasoning_effort = "high"
5
+
6
+ developer_instructions = """
7
+ You are a commit-message specialist.
8
+
9
+ Use the following repo-local skill as the canonical workflow source:
10
+ - commit-message-conventions
11
+
12
+ Core behavior:
13
+ - Generate an audit-quality Git commit message for the current repository.
14
+ - Use an explicitly supplied commit-context artifact when one is provided.
15
+ - Otherwise inspect the local staged state directly with non-destructive Git commands.
16
+ - Do not create the commit. Do not stage, unstage, or modify files.
17
+ - Treat the shared skill as the source of truth for commit classification, formatting, interpretation, and prohibitions.
18
+
19
+ Final response contract:
20
+ - Output exactly one fenced `text` code block containing only the commit message.
21
+ - Do not include commentary, alternatives, or explanations outside the code block.
22
+ """
@@ -0,0 +1,22 @@
1
+ name = "commit-steward-c4"
2
+ description = "Generate a high-signal conventional commit message for the current repository based on staged changes only."
3
+ model = "gpt-5.6-sol"
4
+ model_reasoning_effort = "max"
5
+
6
+ developer_instructions = """
7
+ You are a commit-message specialist.
8
+
9
+ Use the following repo-local skill as the canonical workflow source:
10
+ - commit-message-conventions
11
+
12
+ Core behavior:
13
+ - Generate an audit-quality Git commit message for the current repository.
14
+ - Use an explicitly supplied commit-context artifact when one is provided.
15
+ - Otherwise inspect the local staged state directly with non-destructive Git commands.
16
+ - Do not create the commit. Do not stage, unstage, or modify files.
17
+ - Treat the shared skill as the source of truth for commit classification, formatting, interpretation, and prohibitions.
18
+
19
+ Final response contract:
20
+ - Output exactly one fenced `text` code block containing only the commit message.
21
+ - Do not include commentary, alternatives, or explanations outside the code block.
22
+ """
@@ -1,5 +1,7 @@
1
1
  name = "commit-steward"
2
2
  description = "Generate a high-signal conventional commit message for the current repository based on staged changes only."
3
+ model = "gpt-5.6-terra"
4
+ model_reasoning_effort = "high"
3
5
 
4
6
  developer_instructions = """
5
7
  You are a commit-message specialist.
@@ -76,6 +76,13 @@ and reasoning effort. Spawn the generated deployment agent named by those receip
76
76
  standalone run whose ceiling is C3 uses Terra/High; C3 epic children and C3 work with a C4 sibling
77
77
  use Sol/High. Missing profiles or models block with `model_unavailable`; do not fall back silently.
78
78
 
79
+ The transaction must resolve independently before every normal nested `spawn_agent` call, and validate the generated profile name, model, reasoning effort, path, and SHA-256. Append the exact validated receipt, with a non-empty phase and delegation identifier, to `codex_model_routing_receipts` in the selected checkpoint that `SubagentStart` reads. The process must durably flush selected-checkpoint persistence before launch, then call `spawn_agent` only with the resolver-returned `deployment_agent`.
80
+
81
+ Reject generic aliases, ambiguous checkpoints, failed profile validation, failed persistence, late
82
+ receipts, and invalid start attestations. When the start attestation returns `routing_valid: false`,
83
+ reject child output and mutations; do not relax the recorder, authority-store, mutation-gate, or
84
+ stop-gate enforcement.
85
+
79
86
  The production-file result and the model result are independent. File count selects small typed
80
87
  engineer versus large orchestrator topology. The C1-C4 result selects the suffix and pinned model
81
88
  for that already-selected family; it must not change the topology.
@@ -76,6 +76,13 @@ and reasoning effort. Spawn the generated deployment agent named by those receip
76
76
  standalone run whose ceiling is C3 uses Terra/High; C3 epic children and C3 work with a C4 sibling
77
77
  use Sol/High. Missing profiles or models block with `model_unavailable`; do not fall back silently.
78
78
 
79
+ The transaction must resolve independently before every normal nested `spawn_agent` call, and validate the generated profile name, model, reasoning effort, path, and SHA-256. Append the exact validated receipt, with a non-empty phase and delegation identifier, to `codex_model_routing_receipts` in the selected checkpoint that `SubagentStart` reads. The process must durably flush selected-checkpoint persistence before launch, then call `spawn_agent` only with the resolver-returned `deployment_agent`.
80
+
81
+ Reject generic aliases, ambiguous checkpoints, failed profile validation, failed persistence, late
82
+ receipts, and invalid start attestations. When the start attestation returns `routing_valid: false`,
83
+ reject child output and mutations; do not relax the recorder, authority-store, mutation-gate, or
84
+ stop-gate enforcement.
85
+
79
86
  The production-file result and the model result are independent. File count selects small typed
80
87
  engineer versus large orchestrator topology. The C1-C4 result selects the suffix and pinned model
81
88
  for that already-selected family; it must not change the topology.
@@ -76,6 +76,13 @@ and reasoning effort. Spawn the generated deployment agent named by those receip
76
76
  standalone run whose ceiling is C3 uses Terra/High; C3 epic children and C3 work with a C4 sibling
77
77
  use Sol/High. Missing profiles or models block with `model_unavailable`; do not fall back silently.
78
78
 
79
+ The transaction must resolve independently before every normal nested `spawn_agent` call, and validate the generated profile name, model, reasoning effort, path, and SHA-256. Append the exact validated receipt, with a non-empty phase and delegation identifier, to `codex_model_routing_receipts` in the selected checkpoint that `SubagentStart` reads. The process must durably flush selected-checkpoint persistence before launch, then call `spawn_agent` only with the resolver-returned `deployment_agent`.
80
+
81
+ Reject generic aliases, ambiguous checkpoints, failed profile validation, failed persistence, late
82
+ receipts, and invalid start attestations. When the start attestation returns `routing_valid: false`,
83
+ reject child output and mutations; do not relax the recorder, authority-store, mutation-gate, or
84
+ stop-gate enforcement.
85
+
79
86
  The production-file result and the model result are independent. File count selects small typed
80
87
  engineer versus large orchestrator topology. The C1-C4 result selects the suffix and pinned model
81
88
  for that already-selected family; it must not change the topology.
@@ -76,6 +76,13 @@ and reasoning effort. Spawn the generated deployment agent named by those receip
76
76
  standalone run whose ceiling is C3 uses Terra/High; C3 epic children and C3 work with a C4 sibling
77
77
  use Sol/High. Missing profiles or models block with `model_unavailable`; do not fall back silently.
78
78
 
79
+ The transaction must resolve independently before every normal nested `spawn_agent` call, and validate the generated profile name, model, reasoning effort, path, and SHA-256. Append the exact validated receipt, with a non-empty phase and delegation identifier, to `codex_model_routing_receipts` in the selected checkpoint that `SubagentStart` reads. The process must durably flush selected-checkpoint persistence before launch, then call `spawn_agent` only with the resolver-returned `deployment_agent`.
80
+
81
+ Reject generic aliases, ambiguous checkpoints, failed profile validation, failed persistence, late
82
+ receipts, and invalid start attestations. When the start attestation returns `routing_valid: false`,
83
+ reject child output and mutations; do not relax the recorder, authority-store, mutation-gate, or
84
+ stop-gate enforcement.
85
+
79
86
  The production-file result and the model result are independent. File count selects small typed
80
87
  engineer versus large orchestrator topology. The C1-C4 result selects the suffix and pinned model
81
88
  for that already-selected family; it must not change the topology.
@@ -76,6 +76,13 @@ and reasoning effort. Spawn the generated deployment agent named by those receip
76
76
  standalone run whose ceiling is C3 uses Terra/High; C3 epic children and C3 work with a C4 sibling
77
77
  use Sol/High. Missing profiles or models block with `model_unavailable`; do not fall back silently.
78
78
 
79
+ The transaction must resolve independently before every normal nested `spawn_agent` call, and validate the generated profile name, model, reasoning effort, path, and SHA-256. Append the exact validated receipt, with a non-empty phase and delegation identifier, to `codex_model_routing_receipts` in the selected checkpoint that `SubagentStart` reads. The process must durably flush selected-checkpoint persistence before launch, then call `spawn_agent` only with the resolver-returned `deployment_agent`.
80
+
81
+ Reject generic aliases, ambiguous checkpoints, failed profile validation, failed persistence, late
82
+ receipts, and invalid start attestations. When the start attestation returns `routing_valid: false`,
83
+ reject child output and mutations; do not relax the recorder, authority-store, mutation-gate, or
84
+ stop-gate enforcement.
85
+
79
86
  The production-file result and the model result are independent. File count selects small typed
80
87
  engineer versus large orchestrator topology. The C1-C4 result selects the suffix and pinned model
81
88
  for that already-selected family; it must not change the topology.
@@ -76,6 +76,13 @@ and reasoning effort. Spawn the generated deployment agent named by those receip
76
76
  standalone run whose ceiling is C3 uses Terra/High; C3 epic children and C3 work with a C4 sibling
77
77
  use Sol/High. Missing profiles or models block with `model_unavailable`; do not fall back silently.
78
78
 
79
+ The transaction must resolve independently before every normal nested `spawn_agent` call, and validate the generated profile name, model, reasoning effort, path, and SHA-256. Append the exact validated receipt, with a non-empty phase and delegation identifier, to `codex_model_routing_receipts` in the selected checkpoint that `SubagentStart` reads. The process must durably flush selected-checkpoint persistence before launch, then call `spawn_agent` only with the resolver-returned `deployment_agent`.
80
+
81
+ Reject generic aliases, ambiguous checkpoints, failed profile validation, failed persistence, late
82
+ receipts, and invalid start attestations. When the start attestation returns `routing_valid: false`,
83
+ reject child output and mutations; do not relax the recorder, authority-store, mutation-gate, or
84
+ stop-gate enforcement.
85
+
79
86
  The production-file result and the model result are independent. File count selects small typed
80
87
  engineer versus large orchestrator topology. The C1-C4 result selects the suffix and pinned model
81
88
  for that already-selected family; it must not change the topology.
@@ -2,7 +2,7 @@ default_permissions = ":danger-full-access"
2
2
 
3
3
  [mcp_servers.drm-copilot]
4
4
  command = "npx"
5
- args = ["-y", "@danmoisan/drm-copilot-mcp@1.1.4"]
5
+ args = ["-y", "@danmoisan/drm-copilot-mcp@1.1.5"]
6
6
  required = true
7
7
  enabled_tools = [
8
8
  "collect_commit_context",