@danmoisan/drm-copilot-mcp 1.1.11 → 1.1.14
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 +368 -209
- package/package.json +2 -2
- package/resources/claude-customizations/.claude/agents/epic-orchestrator.md +1 -1
- package/resources/claude-customizations/.claude/agents/epic-planner.md +4 -1
- package/resources/claude-customizations/.claude/agents/parallel-planner.md +18 -1
- package/resources/claude-customizations/.claude/agents/pr-author.md +15 -0
- package/resources/claude-customizations/.claude/hooks/enforce-completion-consistency.ps1 +16 -8
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-authorization.ps1 +443 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +33 -37
- package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +120 -5
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +127 -0
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +172 -24
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +14 -27
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +66 -5
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +134 -10
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.epic-base-branch.ps1 +37 -8
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.ps1 +3 -1
- package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner-helpers.ps1 +332 -0
- package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner.ps1 +211 -182
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadius.psm1 +43 -6
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusScheduling.psm1 +486 -0
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusValidation.psm1 +5 -2
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusWriteIntent.psm1 +446 -0
- package/resources/claude-customizations/.claude/lib/codex-routing/CodexDeployment.psm1 +1 -0
- package/resources/claude-customizations/.claude/lib/worktree-resolution/EpicScopeReadiness.psm1 +176 -0
- package/resources/claude-customizations/.claude/lib/worktree-resolution/EpicScopeResolution.psm1 +369 -0
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeItemResolution.psm1 +392 -0
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeResolution.psm1 +500 -0
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeTargetResolution.psm1 +347 -0
- package/resources/claude-customizations/.claude/rules/orchestrator-state.md +27 -0
- package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +150 -2
- package/resources/claude-customizations/.claude/rules/plan-acceptance-gates.md +5 -5
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +12 -0
- package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +14 -1
- package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +15 -0
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +4 -1
- package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +32 -17
- package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +39 -6
- package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +39 -10
- package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +15 -0
- package/resources/claude-customizations/.claude/skills/quota-throttling/SKILL.md +221 -0
- package/resources/claude-customizations/config/blast-radius.json +14 -1
- package/resources/claude-customizations/pack-manifests/core.json +11 -0
- package/resources/codex-and-agents-customizations/.agents/skills/codex-model-routing/SKILL.md +13 -14
- package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate.ps1 +193 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-planning-only.ps1 +15 -5
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-resolution.ps1 +493 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +189 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +172 -24
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +14 -27
- package/resources/codex-and-agents-customizations/.codex/scripts/Resolve-CodexDeployment.ps1 +87 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/Resolve-CodexTopology.ps1 +96 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/codex-routing-cli-common.ps1 +370 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/epic-child-launch-contract.ps1 +475 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/epic-child-launch-runtime.ps1 +445 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/epic-child-persistence-runtime.ps1 +118 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/epic-child-sandbox-preflight.ps1 +69 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/launch-epic-child-wave.ps1 +471 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/post-codex-worktree-session.ps1 +280 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/resume-epic-child.ps1 +263 -0
- package/resources/codex-and-agents-customizations/.codex-variants/csharp-legacy/agents/csharp-typed-engineer.toml +2 -1
- package/resources/codex-and-agents-customizations/pack-manifests/core.json +20 -1
- package/resources/lib/codex-routing/CodexDeployment.psm1 +315 -0
- package/resources/lib/codex-routing/CodexTopology.psm1 +394 -0
- package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +37 -0
|
@@ -170,6 +170,13 @@ frontmatter default — `opus` for these workers — which suppresses a `fable`
|
|
|
170
170
|
MUST NOT hard-code `model=opus` in a way that overrides the resolved routing model, mirroring
|
|
171
171
|
step 5 of `## Model Selection` in `.claude/skills/orchestrate/SKILL.md`.
|
|
172
172
|
|
|
173
|
+
Every such spawn of `Agent(pr-author)` also carries the canonical issue number line and a
|
|
174
|
+
`branch: <name>` label naming the branch checked out in the worktree the pull request is opened
|
|
175
|
+
from, per `## Issue Number Consistency` in `.claude/skills/orchestrate/SKILL.md`.
|
|
176
|
+
`enforce-model-routing-receipt.ps1` identifies the item from those two lines and denies a gated
|
|
177
|
+
delegation it cannot identify, so a spawn that omits both is refused rather than validated against
|
|
178
|
+
whichever checkpoint occupies the calling session's root.
|
|
179
|
+
|
|
173
180
|
`route` is never an input to model selection; `route` remains file-count driven and governs only
|
|
174
181
|
agents, skills, and MCP tools. A skill whose frontmatter `context` field holds the value `fork`
|
|
175
182
|
inherits the parent model and ignores a model override, so model selection applies to agent
|
|
@@ -281,7 +288,9 @@ checkpoint JSON remains the durable, machine-authoritative source.
|
|
|
281
288
|
`epic_feature_folder`, `epic_manifest_path` (which points at
|
|
282
289
|
`docs/features/epics/<epic-slug>/epic.md`), `epic_status_doc_path`, `integration_branch`,
|
|
283
290
|
`completed_steps`, `next_step`, `last_updated`, `current_wave`, `waves[]`, `features[]`,
|
|
284
|
-
`epic_merge_pr`,
|
|
291
|
+
`epic_merge_pr`, `epic_issue_num` (the epic-level issue `epic-planner` promoted),
|
|
292
|
+
`model_routing_receipts[]` (the routing receipt for each delegation `epic-orchestrator` itself
|
|
293
|
+
spawns), and the three receipt arrays (`delegation_receipts[]`, `skill_receipts[]`,
|
|
285
294
|
`mcp_call_receipts[]`). The
|
|
286
295
|
`merge_status` enum is: `not_started`, `worktree_created`, `pr_open`, `ci_green`,
|
|
287
296
|
`merge_conflict`, `blocked_conflict_loop_limit`, `merged`, `worktree_removed`. The optional
|
|
@@ -298,6 +307,10 @@ Validate the checkpoint through the
|
|
|
298
307
|
that same call at the completion gate. The validation is implemented in
|
|
299
308
|
`scripts/dev_tools/validate_epic_orchestrator_state.py`.
|
|
300
309
|
|
|
310
|
+
**Checkpoint hygiene (issue #673).** The coordinating session never holds a per-feature checkpoint at its own root. Before the first child delegation of a run it moves any `artifacts/orchestration/orchestrator-state.json` at its root to `artifacts/orchestration/handoff/orchestrator-state.issue-<issue-num>.<yyyy-MM-ddTHH-mm>.json`, and writes none there for the rest of the run, because each item's checkpoint lives in that item's worktree. A gated call the coordinator issues on an item's behalf is resolved by the item's issue number and branch, never by the coordinator root.
|
|
311
|
+
|
|
312
|
+
**Integration-PR checkpoint shape (issue #663).** The integration-to-`main` pull request and its `Agent(pr-author)` delegation are gated against `artifacts/orchestration/epic-orchestrator-state.json`, and no per-feature checkpoint is written for them. Before `epic-orchestrator` opens that pull request, the epic checkpoint carries `route_id: "epic"`, `integration_branch`, `epic_issue_num`, and a `features[]` array in which every entry's `merge_status` is `merged` or `worktree_removed`. Before the `Agent(pr-author)` delegation, `epic-orchestrator` records the `pr-author` routing receipt in that file's `model_routing_receipts[]`. The pr-author gate, the epic base-branch check, the model-routing gate, and the preimplementation gate treat a call as epic scope when its branch signal (or, for a staging command or file edit, the worktree HEAD) equals `integration_branch`; the pull request base must then be `main`.
|
|
313
|
+
|
|
301
314
|
## Completion Requirements
|
|
302
315
|
|
|
303
316
|
`epic-orchestrator` must not report completion until:
|
|
@@ -66,6 +66,10 @@ At manifest-authoring time child issues do not exist yet, so `issue_num` values
|
|
|
66
66
|
placeholders and back-filled from each child's promotion receipt as preparation completes. The
|
|
67
67
|
manifest is committed in final, resolved form before the kickoff artifact is written.
|
|
68
68
|
|
|
69
|
+
## Epic-Level Issue Promotion
|
|
70
|
+
|
|
71
|
+
Issue #663. Before the first preparation-mode child delegation, `epic-planner` promotes one epic-level GitHub issue for the epic itself. It authors a potential entry under `docs/features/potential/` describing the epic and promotes it through `mcp__drm-copilot__potential_to_issue` with `promotion_type: epic`; `gh issue create` is not used. It records the resulting number as `epic_issue_num` in the epic planning checkpoint (`artifacts/orchestration/epic-planner-state.json`) and in the kickoff prompt artifact, and `epic-orchestrator` copies it into the epic checkpoint `artifacts/orchestration/epic-orchestrator-state.json` at its first checkpoint write. The integration-to-`main` pull request uses `epic_issue_num` as its canonical issue number.
|
|
72
|
+
|
|
69
73
|
## Complexity Assessment
|
|
70
74
|
|
|
71
75
|
Assess each child feature's complexity band (`C1`-`C4`) using the `model_policy` scale and
|
|
@@ -200,6 +204,17 @@ content-widening options, and any operand that resolves outside the five exempt
|
|
|
200
204
|
exempt operand with one production operand denies the whole invocation. Name each exempt path
|
|
201
205
|
explicitly; the exemption is allow-side only and every parse ambiguity denies.
|
|
202
206
|
|
|
207
|
+
#### Attribution trailers (issue #713)
|
|
208
|
+
|
|
209
|
+
With no ready feature checkpoint, the exemption admits two attribution-trailer forms on a pathspec-bearing `git commit`, each followed by the double-dash separator and the exempt path operands:
|
|
210
|
+
|
|
211
|
+
- The trailer option: `git commit -m 'docs: plan' --trailer 'Co-Authored-By: Name <email>' --trailer 'Claude-Session: <url>' -- <exempt paths>`. The separate-value form and the `--trailer=<value>` form are both admitted, any number of times, on `git commit` only; `git add --trailer` and a trailer option with no value are denied. Git writes every trailer value into one trailer block.
|
|
212
|
+
- The one-paragraph multi-message form: the subject in the first `-m` and every trailer in one single-quoted second `-m` value, separated by a literal newline. Each `-m` value becomes its own paragraph and git parses only the last paragraph as the trailer block, so trailers split across separate `-m` values do not form one trailer block.
|
|
213
|
+
|
|
214
|
+
Quoting rules: `$` and backtick are literal and admitted inside single quotes, and denied outside quotes and inside double quotes, where the shell expands them. `<` and `>` are admitted inside single or double quotes and denied outside quotes. An unquoted `#` is denied anywhere, because it starts a shell comment that the exemption does not model; a `#` inside quotes is admitted. A typographic quote character (U+2018 to U+201E) anywhere in the command line is denied, because a PowerShell host reads it as a quote.
|
|
215
|
+
|
|
216
|
+
Not admitted: heredoc-fed messages, including `git commit -m "$(cat <<'EOF' ... EOF)"` and `git commit -F - <<'EOF'`, and message files supplied through `-F <file>` or `--file=<file>`. Use one of the two forms above instead.
|
|
217
|
+
|
|
203
218
|
## Checkpoint Handling
|
|
204
219
|
|
|
205
220
|
Persist `artifacts/orchestration/epic-planner-state.json` after every completed step with the
|
|
@@ -33,6 +33,7 @@ On every invocation, the main session must:
|
|
|
33
33
|
1. Read `artifacts/orchestration/orchestrator-state.json` to check for existing state.
|
|
34
34
|
2. If a valid checkpoint exists with a matching objective, resume from the recorded `next_step`.
|
|
35
35
|
3. If no checkpoint exists or the objective is new, begin the orchestration lifecycle from the start.
|
|
36
|
+
4. **Checkpoint hygiene (issue #673).** When the checkpoint at `artifacts/orchestration/orchestrator-state.json` records an `issue-num` other than the item this invocation is about, move it to `artifacts/orchestration/handoff/orchestrator-state.issue-<issue-num>.<yyyy-MM-ddTHH-mm>.json` before writing a new checkpoint, rather than overwriting it or leaving it in place. Apply the same move when this session hands an item whose checkpoint it holds to another session or worktree. A checkpoint left at a session root is read by gates that resolve against that root, so a foreign one there is state a gate can answer from.
|
|
36
37
|
|
|
37
38
|
## Prepared-State Portable Handoff Intake
|
|
38
39
|
|
|
@@ -255,10 +256,12 @@ A bounded loop consisting of five steps. The loop variable `remediation_pass` st
|
|
|
255
256
|
|
|
256
257
|
The canonical issue number is derived once from the active feature folder name: extract the trailing integer from the folder base name (e.g., `2026-04-26-push-down-claude-customizations-162` yields `162`). Record as `issue_num` in the checkpoint.
|
|
257
258
|
|
|
258
|
-
Every delegation prompt to `atomic-planner`, `atomic-executor`,
|
|
259
|
+
Every delegation prompt to a receipt-gated subagent type — `atomic-planner`, `atomic-executor`, `feature-review`, `task-researcher`, `prd-feature`, and `pr-author` — must include the line:
|
|
259
260
|
|
|
260
261
|
> `Canonical issue number for this feature is <issue_num>. All artifact content, file paths, and cross-references must use this number.`
|
|
261
262
|
|
|
263
|
+
Each such prompt also carries a `branch: <name>` label naming the branch checked out in the item's worktree, written as the first `branch:` occurrence in the prompt. Before promotion assigns an issue number, the branch label alone is required. Two gates, `enforce-model-routing-receipt.ps1` and `enforce-prd-feature-before-planner.ps1`, identify the item from these two lines: they deny a gated delegation they cannot identify rather than checking it against whichever checkpoint occupies the calling session's root, and they never use a feature-folder path to choose the worktree, because a merged feature folder exists in every checkout branched from main.
|
|
264
|
+
|
|
262
265
|
If a subagent artifact references a different issue number, the orchestrator rejects it, requests correction, and records the discrepancy under `artifact_errors` in the checkpoint.
|
|
263
266
|
|
|
264
267
|
## Step S9 — CI Green Gate
|
|
@@ -58,25 +58,38 @@ re-derivation is mandatory and is not an optimization to skip when the checkpoin
|
|
|
58
58
|
advances `proposed` -> `admitted` -> `prepared` during this step, recorded as item-state updates in
|
|
59
59
|
`items[]` with the checkpoint's lifecycle timestamps.
|
|
60
60
|
|
|
61
|
-
3. **Compute conflict edges over ALL items, including in-flight ones.** Invoke the
|
|
62
|
-
|
|
61
|
+
3. **Compute conflict edges over ALL items, including in-flight ones.** Invoke the scheduling
|
|
62
|
+
entry point Get-BlastRadiusConflictEdge from the destination-runtime PowerShell port
|
|
63
63
|
`.claude/lib/blast-radius/BlastRadius.psm1`, which is published by push-down and needs no Python
|
|
64
64
|
interpreter (the default PowerShell 5.1 execution policy blocks `Import-Module` of a `.psm1`
|
|
65
65
|
file, so `pwsh` is mandatory: run as `$repoRoot = git rev-parse --show-toplevel; Import-Module
|
|
66
66
|
(Join-Path $repoRoot '.claude/lib/blast-radius/BlastRadius.psm1') -Force -ErrorAction Stop`).
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
`
|
|
71
|
-
|
|
67
|
+
Call it once, as `Get-BlastRadiusConflictEdge -Item <items> -Config <config> -Relation ${function:Test-BlastRadiusConflict}`, where each item
|
|
68
|
+
record carries `key` (the `items[].issue_num` value), `radius` (the item's radius hashtable, not
|
|
69
|
+
a string), and the optional complexity `band`, and `-Config` is the required parsed
|
|
70
|
+
`config/blast-radius.json` mapping, which push-down publishes into the destination workspace.
|
|
71
|
+
The -Relation argument is required and carries the facade's detection relation; an omitted
|
|
72
|
+
relation fails fast. The entry point applies the contention relation `Test-BlastRadiusConflict` to every unordered
|
|
73
|
+
pair and then the integration-cost edge rule of `.claude/rules/parallel-orchestration.md`
|
|
74
|
+
(hard classes, integer cost, pairwise benefit, and the configured `conflict_tolerance`); the
|
|
75
|
+
relation still reads the mapping's optional `mergeable_paths` list and contributes no
|
|
76
|
+
`path_overlap` edge for a path matching it while the path stays in the declared radius.
|
|
77
|
+
`schedule_conflict_edges(items, config)` and `conflicts(a, b, config)` in
|
|
72
78
|
`scripts/dev_tools/compute_blast_radius.py` (defined in
|
|
73
|
-
`scripts/dev_tools/
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
edge of `items[].issue_num` values,
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
`scripts/dev_tools/_blast_radius_scheduling.py` and `scripts/dev_tools/_blast_radius_conflicts.py`)
|
|
80
|
+
remain the repository authority and the parity reference. The call returns a hashtable with
|
|
81
|
+
`edges` (records `a`, `b`, `reason`, `hard`, `cost`, `benefit`, already normalized so `a < b`)
|
|
82
|
+
and `tolerated_overlaps` (records `a`, `b`, `reasons`, `cost`, `benefit`). Take each returned
|
|
83
|
+
edge as an `(int, int)` conflict edge of `items[].issue_num` values, and record the returned
|
|
84
|
+
tolerated overlaps in the checkpoint's tolerated_overlaps list. When `Test-BlastRadiusConflict`
|
|
85
|
+
is called directly for a single pair, read the verdict from `$result['conflict']`; do not test
|
|
86
|
+
the returned hashtable itself, since it is always truthy under PowerShell boolean coercion, so a
|
|
87
|
+
bare `if ($result)` check treats every pair as conflicting. Do not reimplement the relation or
|
|
88
|
+
the edge rule, do not apply the relation to each pair by hand, and do not compute edges over the
|
|
89
|
+
unstarted subset only: an in-flight conflict is precisely what the admission decision turns on.
|
|
90
|
+
A tolerated overlap is not an edge: the two items run in the same or adjacent cohorts without a
|
|
91
|
+
barrier, and the later-merging item merges `origin/main` under the existing per-item
|
|
92
|
+
merge-conflict handling and re-passes CI before it merges.
|
|
80
93
|
|
|
81
94
|
4. **Decide admission.** Call
|
|
82
95
|
`decide_admission(candidate, conflict_edges, in_flight, current_cohort_members=current_cohort_members)`
|
|
@@ -150,9 +163,11 @@ re-derivation is mandatory and is not an optimization to skip when the checkpoin
|
|
|
150
163
|
|
|
151
164
|
- One admission per invocation, one `mutations[]` entry per successful admission. A failed
|
|
152
165
|
preparation appends no entry and leaves `items[]` without the candidate.
|
|
153
|
-
- No field and no enum member is added to `mutations[]`, `
|
|
154
|
-
|
|
155
|
-
|
|
166
|
+
- No field and no enum member is added to `mutations[]`, `items[]`, or any state or merge-status
|
|
167
|
+
enum. A `conflict_edges[]` entry may carry only the three tolerated extra fields `hard`, `cost`,
|
|
168
|
+
and `benefit` (tolerated-not-validated, returned by the scheduling entry point), and no reason
|
|
169
|
+
member is added: the four `conflict_edges[].reason` members are unchanged. The nine parallel
|
|
170
|
+
enums are owned by `.claude/rules/parallel-orchestration.md` and are consumed, never extended.
|
|
156
171
|
- This operation never moves, restates, or re-derives an in-flight item's cohort or state.
|
|
157
172
|
- This operation performs no destructive side effect: it closes no pull request and removes no
|
|
158
173
|
worktree. Those belong to `/parallel-remove` with `--disposition abandon`.
|
|
@@ -234,6 +234,8 @@ There is no final integration pull request and no fan-in path: the epic surface'
|
|
|
234
234
|
integration-branch lifecycle has no counterpart on this surface, and its absence is structural
|
|
235
235
|
rather than an omission.
|
|
236
236
|
|
|
237
|
+
**Checkpoint hygiene (issue #673).** The coordinating session never holds a per-feature checkpoint at its own root. Before the first item delegation of a run it moves any `artifacts/orchestration/orchestrator-state.json` at its root to `artifacts/orchestration/handoff/orchestrator-state.issue-<issue-num>.<yyyy-MM-ddTHH-mm>.json`, and writes none there for the rest of the run, because each item's checkpoint lives in that item's worktree. A gated call the coordinator issues on an item's behalf is resolved by the item's issue number and branch, never by the coordinator root.
|
|
238
|
+
|
|
237
239
|
## Parallel-Mode Kickoff Parameter
|
|
238
240
|
|
|
239
241
|
When `parallel-orchestrator` delegates an item to `Agent(orchestrator)`, the delegation prompt
|
|
@@ -326,12 +328,43 @@ Procedure, per item:
|
|
|
326
328
|
|
|
327
329
|
**Merge-gate authorization.** `.claude/hooks/enforce-epic-merge-gate.ps1` is a project-wide
|
|
328
330
|
`PreToolUse` Bash-matcher hook that denies any `gh pr merge --merge` unless a checkpoint satisfies
|
|
329
|
-
one of its allow conditions; its block reason is `EPIC_MERGE_GATE_BLOCKED`. The gate
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
331
|
+
one of its allow conditions; its block reason is `EPIC_MERGE_GATE_BLOCKED`. The gate has
|
|
332
|
+
four allow conditions
|
|
333
|
+
which it evaluates in this order: a per-feature checkpoint with `epic_mode == true` and
|
|
334
|
+
`step9_status == "passed"`; an epic checkpoint whose `epic_merge_pr.ci_gate.conclusion` is
|
|
335
|
+
`success` with a matching `pr_number`; the parallel condition described next; and a standalone
|
|
336
|
+
merge authorization record, described after it. The parallel condition authorizes a per-item merge
|
|
337
|
+
when the parallel-orchestrator checkpoint has `route_id == "parallel"`, the target item's
|
|
338
|
+
`merge_status == "ci_green"`, and, when a PR number is named, it matches the item's `pr_number`.
|
|
339
|
+
Step 3 above is therefore permitted for a legitimate parallel merge; a missing, unreadable, or
|
|
340
|
+
invalid parallel checkpoint, a target item whose `merge_status` is not `ci_green`, or a PR number
|
|
341
|
+
that matches no item still fails closed with `EPIC_MERGE_GATE_BLOCKED`.
|
|
342
|
+
|
|
343
|
+
The standalone condition (issue #670) is the only route for merging a pull request that is not a
|
|
344
|
+
parallel item, such as a standalone fix that unblocks the run. It is evaluated last and never
|
|
345
|
+
overrides the other three. Writer procedure for the coordinating session:
|
|
346
|
+
|
|
347
|
+
1. Write the record into a top-level `standalone_merge_authorizations` array in the
|
|
348
|
+
parallel-orchestrator checkpoint (`artifacts/orchestration/parallel-orchestrator-state.json`);
|
|
349
|
+
the gate also reads the key from the per-feature and epic checkpoints.
|
|
350
|
+
2. Write one entry per authorized pull request, with these fields: `pr_number` (JSON integer),
|
|
351
|
+
`pr_url` (ending in `/pull/<pr_number>`), `issue_num` (JSON integer), `branch_name`,
|
|
352
|
+
`authorized_by`, `authorized_at` (ISO 8601 date-time), `session_id`, `basis` (at least 20
|
|
353
|
+
characters), and optionally `run_slug`.
|
|
354
|
+
3. Set `session_id` to the session id of the coordinating session that will run the merge
|
|
355
|
+
command. The gate compares it with the live hook envelope and denies on any difference, so a
|
|
356
|
+
record written by another session or a previous run authorizes nothing.
|
|
357
|
+
4. Name the pull request explicitly in the merge command (`gh pr merge <PR> --merge`); a bare
|
|
358
|
+
command never satisfies the standalone condition.
|
|
359
|
+
|
|
360
|
+
A blanket flag is actively rejected: a `standalone_merge_authorizations` value that names no
|
|
361
|
+
specific pull request (for example `true`) denies with
|
|
362
|
+
`STANDALONE_MERGE_AUTHORIZATION_NOT_PR_SPECIFIC`. Other denials carry
|
|
363
|
+
`STANDALONE_MERGE_AUTHORIZATION_ABSENT`, `STANDALONE_MERGE_AUTHORIZATION_PR_MISMATCH`, or
|
|
364
|
+
`STANDALONE_MERGE_AUTHORIZATION_MALFORMED` (naming the failing field) after the
|
|
365
|
+
`EPIC_MERGE_GATE_BLOCKED` token. The record is a policy-level, auditable declaration, not a
|
|
366
|
+
security control; see the Standalone-Merge-Authorization section of
|
|
367
|
+
`.claude/rules/orchestrator-state.md` for the full field rules and the disclosure.
|
|
335
368
|
|
|
336
369
|
Branch protection on `main` affects only the pacing of step 3, not its ownership: if `main`
|
|
337
370
|
requires branches to be up to date, an automated `gh pr update-branch` plus re-green cycle is
|
|
@@ -312,16 +312,25 @@ The library returns the partition; the planner supplies the record fields.
|
|
|
312
312
|
### Seeding procedure
|
|
313
313
|
|
|
314
314
|
1. Invoke `compute-cohorts.sh` exactly once per plan run, over the full conflict graph, after every
|
|
315
|
-
item is `prepared` and radius-validated. Derive the conflict edge set
|
|
316
|
-
|
|
315
|
+
item is `prepared` and radius-validated. Derive the conflict edge set with one call to the
|
|
316
|
+
scheduling entry point over every item's `declared` radius and complexity band: Get-BlastRadiusConflictEdge
|
|
317
|
+
(`Get-BlastRadiusConflictEdge -Item <records carrying key, radius, band> -Config <parsed truth table> -Relation ${function:Test-BlastRadiusConflict}`)
|
|
318
|
+
in PowerShell, or `schedule_conflict_edges(items, config)` (re-exported from
|
|
319
|
+
`compute_blast_radius.py`, taking `SchedulingItem` records) in Python. Do not apply the
|
|
320
|
+
detection relation to each pair by hand: the entry point applies it to every unordered pair and
|
|
321
|
+
then applies the integration-cost edge rule of `.claude/rules/parallel-orchestration.md`
|
|
322
|
+
(hard classes, integer cost, pairwise benefit, and the configured `conflict_tolerance`). It
|
|
323
|
+
returns `edges` and `tolerated_overlaps`. The -Relation argument is required; pass the facade's
|
|
324
|
+
Test-BlastRadiusConflict function object as shown. Pass the returned `edges` pairs as
|
|
317
325
|
`--edges "<a>:<b> ..."` and the item keys as `--keys "<k1> <k2> ..."`.
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
above for `Test-BlastRadius`: that function
|
|
324
|
-
emptiness is falsy, while this one returns a
|
|
326
|
+
The detection relation inside the entry point contributes no `path_overlap` edge for a path
|
|
327
|
+
matching the truth table's optional `mergeable_paths` list, and the path stays in the declared
|
|
328
|
+
radius. When `Test-BlastRadiusConflict` is called directly (for example, while investigating a
|
|
329
|
+
single pair), read the verdict from the conflict key of the returned hashtable: the hashtable
|
|
330
|
+
itself is always truthy, so a bare boolean test on the result treats every pair as conflicting.
|
|
331
|
+
This is the sibling hazard to the `@(...)` warning above for `Test-BlastRadius`: that function
|
|
332
|
+
writes an `IList`-shaped pipeline result whose emptiness is falsy, while this one returns a
|
|
333
|
+
hashtable whose emptiness is not expressible at all.
|
|
325
334
|
2. Immediately after the conflict-edge set is derived and before anything consumes it, run the
|
|
326
335
|
lane-assertion diagnostic:
|
|
327
336
|
`bash .claude/lib/bash/report-lane-assertion.sh --manifest docs/features/parallel/<slug>/parallel.md --edges "<a>:<b> ..."`
|
|
@@ -341,7 +350,16 @@ The library returns the partition; the planner supplies the record fields.
|
|
|
341
350
|
Recording the diagnostic's result in the planner checkpoint is a tolerated extra field, not a
|
|
342
351
|
validated one; no validator changes for it.
|
|
343
352
|
3. Record `cohorts[]` at `generation: 0`, each cohort's `item_keys[]` sorted ascending.
|
|
344
|
-
4. Record `conflict_edges[]` as `{a, b, reason}` entries for auditability
|
|
353
|
+
4. Record `conflict_edges[]` as `{a, b, reason}` entries for auditability; each entry may also carry
|
|
354
|
+
the tolerated extra fields `hard`, `cost`, and `benefit` returned by the entry point. Record the
|
|
355
|
+
returned tolerated overlaps in a `tolerated_overlaps` list on the planner checkpoint, one
|
|
356
|
+
`{a, b, reasons, cost, benefit}` entry per detected, non-hard pair within tolerance. No reason
|
|
357
|
+
member is added and no validator reads these fields.
|
|
358
|
+
**Soft-overlap merge rule.** A tolerated pair is not an edge: its two items run in the same or
|
|
359
|
+
adjacent cohorts without a barrier. The later-merging item of a tolerated pair merges
|
|
360
|
+
`origin/main` under the existing per-item merge-conflict handling and re-passes CI before it
|
|
361
|
+
merges. This is the operator-directed configured policy of issue #722; it never licenses
|
|
362
|
+
hand-narrowing a radius.
|
|
345
363
|
5. Record `recolor_generation: 0` and `current_cohort: 0`.
|
|
346
364
|
6. Record `max_concurrency` — default 4, bounded 1 through 32 by the F3 schema — without enforcing
|
|
347
365
|
it. Enforcement is F5's, through
|
|
@@ -570,6 +588,17 @@ content-widening options, and any operand that resolves outside the five exempt
|
|
|
570
588
|
exempt operand with one production operand denies the whole invocation. Name each exempt path
|
|
571
589
|
explicitly; the exemption is allow-side only and every parse ambiguity denies.
|
|
572
590
|
|
|
591
|
+
#### Attribution trailers (issue #713)
|
|
592
|
+
|
|
593
|
+
With no ready feature checkpoint, the exemption admits two attribution-trailer forms on a pathspec-bearing `git commit`, each followed by the double-dash separator and the exempt path operands:
|
|
594
|
+
|
|
595
|
+
- The trailer option: `git commit -m 'docs: plan' --trailer 'Co-Authored-By: Name <email>' --trailer 'Claude-Session: <url>' -- <exempt paths>`. The separate-value form and the `--trailer=<value>` form are both admitted, any number of times, on `git commit` only; `git add --trailer` and a trailer option with no value are denied. Git writes every trailer value into one trailer block.
|
|
596
|
+
- The one-paragraph multi-message form: the subject in the first `-m` and every trailer in one single-quoted second `-m` value, separated by a literal newline. Each `-m` value becomes its own paragraph and git parses only the last paragraph as the trailer block, so trailers split across separate `-m` values do not form one trailer block.
|
|
597
|
+
|
|
598
|
+
Quoting rules: `$` and backtick are literal and admitted inside single quotes, and denied outside quotes and inside double quotes, where the shell expands them. `<` and `>` are admitted inside single or double quotes and denied outside quotes. An unquoted `#` is denied anywhere, because it starts a shell comment that the exemption does not model; a `#` inside quotes is admitted. A typographic quote character (U+2018 to U+201E) anywhere in the command line is denied, because a PowerShell host reads it as a quote.
|
|
599
|
+
|
|
600
|
+
Not admitted: heredoc-fed messages, including `git commit -m "$(cat <<'EOF' ... EOF)"` and `git commit -F - <<'EOF'`, and message files supplied through `-F <file>` or `--file=<file>`. Use one of the two forms above instead.
|
|
601
|
+
|
|
573
602
|
## Completion Report
|
|
574
603
|
|
|
575
604
|
The final report to the operator must include:
|
|
@@ -76,3 +76,18 @@ writes and the `gh pr create` / `gh pr edit --body-file` handoff.
|
|
|
76
76
|
- Do not treat PR numbers as issues.
|
|
77
77
|
- Auto-close bullets must use exactly `- Closes #NNN` format, sourced only from "Issues to autoclose" or "Author-asserted autoclose issues."
|
|
78
78
|
- If GitHub validation is unavailable/unverified, do not emit `Closes`; use the fallback `None` bullet.
|
|
79
|
+
|
|
80
|
+
## Required `--head` on `gh pr create` (issue #687)
|
|
81
|
+
|
|
82
|
+
Every `gh pr create` command this agent issues MUST carry an explicit
|
|
83
|
+
`--head <branch>` naming the branch the pull request is opened from.
|
|
84
|
+
|
|
85
|
+
This is what makes the call's target derivable. `enforce-pr-author-skill.ps1` resolves the
|
|
86
|
+
worktree the call pertains to from the command text, and validates the orchestrator checkpoint
|
|
87
|
+
belonging to that worktree. Without `--head`, `gh pr create` infers its head branch from the
|
|
88
|
+
current checkout and the command carries no signal at all, so the gate denies with
|
|
89
|
+
`TARGET_WORKTREE_NOT_DERIVABLE` rather than validating against whichever checkpoint occupies the
|
|
90
|
+
session root, which in a parallel or epic topology belongs to a different item.
|
|
91
|
+
|
|
92
|
+
Pass `--head` even when the branch is the current one: the gate resolves it to the session root
|
|
93
|
+
and behaves exactly as before, and the command stays correct if it is ever replayed elsewhere.
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: quota-throttling
|
|
3
|
+
description: 'Quota throttling and account-switching policy for multi-agent orchestration. Use when pacing agent work against five-hour and seven-day usage limits, deciding whether and when to switch accounts, setting concurrency caps, forecasting a rate-limit wall, handling total weekly exhaustion, or designing a usage monitor. Covers account viability, failover-dependent pacing targets, the measured cost model, commit-before-the-wall, and the coordinator/agent division of labour.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Quota Throttling and Account-Switching Policy
|
|
7
|
+
|
|
8
|
+
Policy for keeping long-running, multi-agent orchestration inside account usage limits without
|
|
9
|
+
losing work. Derived from about five days of continuous multi-agent orchestration (TaskMaster runs
|
|
10
|
+
`bugs-2026-09-11` and `bugs-2026-09-17`).
|
|
11
|
+
|
|
12
|
+
Every figure marked **MEASURED** was observed; figures marked **ESTIMATE** are extrapolations.
|
|
13
|
+
Cost figures are machine- and repository-specific. Re-measure before relying on them elsewhere.
|
|
14
|
+
|
|
15
|
+
## When to Use This Skill
|
|
16
|
+
|
|
17
|
+
Use this skill when:
|
|
18
|
+
|
|
19
|
+
- a coordinating session runs orchestrators, epic runs, or parallel runs that spawn subagents;
|
|
20
|
+
- deciding whether to start, stagger, hold, or stop agent work because of usage limits;
|
|
21
|
+
- choosing whether and when to switch between accounts;
|
|
22
|
+
- a rate-limit wall is forecast, or every account is exhausted;
|
|
23
|
+
- designing a monitor that watches usage or CI state.
|
|
24
|
+
|
|
25
|
+
## Reading Quota
|
|
26
|
+
|
|
27
|
+
The coordinator reads usage from the account switcher, for example `cswap list --json`. The
|
|
28
|
+
fields each rule below depends on:
|
|
29
|
+
|
|
30
|
+
| Field | Meaning |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `accounts[].active` | Whether the account currently supplies credentials. |
|
|
33
|
+
| `accounts[].usageStatus` | Must be `ok`; any other value makes the account non-viable. |
|
|
34
|
+
| `usage.fiveHour.pct` | Five-hour window utilization, an integer percentage. |
|
|
35
|
+
| `usage.fiveHour.resetsAt` | Authoritative ISO-8601 UTC reset time. `null` means the window has not started. |
|
|
36
|
+
| `usage.sevenDay.pct` | Seven-day utilization, an integer percentage. |
|
|
37
|
+
| `usage.sevenDay.resetsAt` | Authoritative ISO-8601 UTC weekly reset time. |
|
|
38
|
+
| `usage.sevenDay.willLastToReset` | The switcher's own projection of whether the weekly budget lasts. |
|
|
39
|
+
| `usage.*.clock`, `usage.*.countdown` | Human-readable display values. `clock` is LOCAL time; do not use it for arithmetic. |
|
|
40
|
+
|
|
41
|
+
Some switchers switch automatically on the five-hour threshold alone and do not consult the
|
|
42
|
+
seven-day window. Such a switcher can hand over to an account whose five-hour window has reset
|
|
43
|
+
but whose weekly budget is spent. Apply section 1 yourself rather than relying on the switcher.
|
|
44
|
+
|
|
45
|
+
## 1. Account Viability
|
|
46
|
+
|
|
47
|
+
An account is a viable target only if BOTH hold:
|
|
48
|
+
|
|
49
|
+
- seven-day usage < 95%
|
|
50
|
+
- five-hour usage < 90%
|
|
51
|
+
|
|
52
|
+
The weekly gate dominates. An account at >= 95% weekly is NOT a viable target regardless of its
|
|
53
|
+
five-hour state, and must be excluded from all pacing math.
|
|
54
|
+
|
|
55
|
+
The binding budget is `min(five-hour headroom to 90%, weekly headroom to 95%)`. Compute both every
|
|
56
|
+
time. Late in a week the weekly headroom is usually the smaller number, and the five-hour window
|
|
57
|
+
is then irrelevant.
|
|
58
|
+
|
|
59
|
+
## 2. Pacing Target Depends on Whether a Failover Exists
|
|
60
|
+
|
|
61
|
+
**Two or more viable accounts: front-load.** Target about 90% of the five-hour window in about
|
|
62
|
+
2 hours (about 45% per hour). Reaching 90% triggers a switch, so the unused remainder of the
|
|
63
|
+
window costs nothing.
|
|
64
|
+
|
|
65
|
+
**Exactly one viable account: spread.** Target about 90% across the WHOLE five-hour window (about
|
|
66
|
+
18% per hour). Front-loading here is wrong: reaching 90% at the 2-hour mark produces a stall of
|
|
67
|
+
about 3 hours with no account to switch to.
|
|
68
|
+
|
|
69
|
+
These are different policies, not different settings of one policy. Applying the two-account
|
|
70
|
+
target to a one-account situation is the most expensive mistake observed (see section 12,
|
|
71
|
+
item 1).
|
|
72
|
+
|
|
73
|
+
## 3. Cost Model (MEASURED, Serialized Single Items)
|
|
74
|
+
|
|
75
|
+
| Activity | Five-hour points | Weekly points | Wall clock |
|
|
76
|
+
|---|---|---|---|
|
|
77
|
+
| Coordination only (API calls, git, checkpoint writes, no agents) | ~3 total | negligible | — |
|
|
78
|
+
| One item, full cycle (child + executor + toolchain + coverage run) | ~17 | ~3 | ~43 min |
|
|
79
|
+
| One plan revision, or a low-cost item | ~4-5 | — | — |
|
|
80
|
+
| Three items entering Phase 0 simultaneously | 96-108 per hour | — | a full five-hour window in 62 min |
|
|
81
|
+
|
|
82
|
+
Builds and test runs consume wall-clock time but zero quota. A long quiet period at 0% per hour
|
|
83
|
+
with agents alive usually means they are inside a build, not stalled.
|
|
84
|
+
|
|
85
|
+
Ratio (ESTIMATE, two data points): one full five-hour window is about 14 weekly points.
|
|
86
|
+
|
|
87
|
+
## 4. Concurrency Control
|
|
88
|
+
|
|
89
|
+
A concurrency cap governs an orchestrator's DIRECT children. Each child spawns its own
|
|
90
|
+
grandchildren (executors, planners, researchers), and those are the dominant consumers. Always
|
|
91
|
+
express a cap as a budget on TOTAL AGENTS IN THE SUBTREE, and require that it be propagated
|
|
92
|
+
verbatim to every level.
|
|
93
|
+
|
|
94
|
+
A cap change only restricts NEW starts. It does nothing to work already running. Cutting a cap
|
|
95
|
+
from 6 to 2 mid-flight changed the burn rate by zero, because the cost was in agents already
|
|
96
|
+
alive.
|
|
97
|
+
|
|
98
|
+
For in-flight burn there are exactly two controls:
|
|
99
|
+
|
|
100
|
+
- **Commit-and-hold** — finish the current task, commit, start nothing new.
|
|
101
|
+
- **Stopping agents outright** — destructive; use only as a last resort.
|
|
102
|
+
|
|
103
|
+
**Stagger starts.** The dominant cost driver is not item count; it is simultaneous Phase 0
|
|
104
|
+
cycles. Bring items in one at a time and let each settle before starting the next.
|
|
105
|
+
|
|
106
|
+
## 5. Measurement Discipline
|
|
107
|
+
|
|
108
|
+
- The usage percentage is an INTEGER. At 5-minute sampling the computed rate quantizes to
|
|
109
|
+
multiples of about 12% per hour. Do not react to a single sample; measure over spans of at
|
|
110
|
+
least 15 minutes.
|
|
111
|
+
- The FIRST sample after an account switch is inflated by batched accounting. Take a second
|
|
112
|
+
reading before acting on it, but do not dismiss it either; it has been partly real more than
|
|
113
|
+
once.
|
|
114
|
+
- Reset times: the human-readable `clock` field is LOCAL time. The ISO `resetsAt` field is
|
|
115
|
+
authoritative. Convert before doing arithmetic; a four-hour error from this changed a plan.
|
|
116
|
+
- Five-hour window elapsed time = 300 − (minutes until reset). The window starts on first use,
|
|
117
|
+
not on a fixed clock boundary.
|
|
118
|
+
- VERIFY a reset directly before resuming. Never infer it from the clock. A reset timestamp can
|
|
119
|
+
pass while the counter still reads the old value for a minute or two.
|
|
120
|
+
|
|
121
|
+
## 6. Approaching a Wall
|
|
122
|
+
|
|
123
|
+
Commit BEFORE the wall, not at it. A rate-limit error terminates an agent immediately; the agent
|
|
124
|
+
does not wait out the gap and resume. The duration of the outage does not change this risk: even
|
|
125
|
+
a 60-second gap terminates in-flight work.
|
|
126
|
+
|
|
127
|
+
Sequence when a wall is forecast:
|
|
128
|
+
|
|
129
|
+
1. Order all in-flight children to COMMIT NOW, in whatever state, without finishing the current
|
|
130
|
+
task. A committed partial result is recoverable; an uncommitted complete one is not.
|
|
131
|
+
2. Let them keep working until the wall actually arrives.
|
|
132
|
+
3. Set the commit checkpoint with real margin, and recompute it as the rate moves. A checkpoint
|
|
133
|
+
that lands ON the forecast wall protects nothing.
|
|
134
|
+
|
|
135
|
+
Git operations are LOCAL and consume no model quota; they succeed on a fully exhausted account.
|
|
136
|
+
If errors start before committing finishes, keep retrying the COMMIT specifically and nothing
|
|
137
|
+
else.
|
|
138
|
+
|
|
139
|
+
## 7. Total Weekly Exhaustion
|
|
140
|
+
|
|
141
|
+
When no account is viable:
|
|
142
|
+
|
|
143
|
+
1. **Serialize** — stop all parallel activity; zero new starts.
|
|
144
|
+
2. **Commit ALL working documents across ALL worktrees** — every item worktree, the plan-home
|
|
145
|
+
worktree, and every in-flight child, not only the current item.
|
|
146
|
+
3. **Report and hold.**
|
|
147
|
+
|
|
148
|
+
This differs from a routine pause: the outage may last days, so nothing may be left uncommitted
|
|
149
|
+
on the assumption of a quick return.
|
|
150
|
+
|
|
151
|
+
## 8. Switching
|
|
152
|
+
|
|
153
|
+
- Switch at 90% of the five-hour window IF a viable target exists.
|
|
154
|
+
- If no viable target exists, do NOT switch; hold until the earliest reset. Switching onto an
|
|
155
|
+
exhausted account produces immediate failures.
|
|
156
|
+
- Verify the switch landed (active account, both windows) before releasing work.
|
|
157
|
+
- A mid-flight credential change is transparent to running agents. Instruct them explicitly not
|
|
158
|
+
to treat the change, or a brief error around it, as a failure signal.
|
|
159
|
+
|
|
160
|
+
## 9. Usage Credits and Overage
|
|
161
|
+
|
|
162
|
+
Never spend credits on work. The ONLY sanctioned use is completing a non-destructive
|
|
163
|
+
serialization and commit so that work is not lost. If any path offers to continue past a limit
|
|
164
|
+
by consuming credits, stop and ask the user.
|
|
165
|
+
|
|
166
|
+
## 10. Reserve Policy
|
|
167
|
+
|
|
168
|
+
Holding an account's last few points as an emergency commit reserve is correct ONLY while
|
|
169
|
+
something is uncommitted. Verify first: if every branch is pushed and every worktree is clean,
|
|
170
|
+
the reserve protects nothing and should be spent on useful work instead. Check before assuming.
|
|
171
|
+
|
|
172
|
+
## 11. Monitor Design
|
|
173
|
+
|
|
174
|
+
Report on thresholds, not on every sample. An idle monitor that fires every ten minutes costs a
|
|
175
|
+
turn each time and hides the signal among routine readings.
|
|
176
|
+
|
|
177
|
+
**A check for the ABSENCE of a bad state is satisfied by the absence of ALL state.** A CI waiter
|
|
178
|
+
polling for "no pending checks" reported SETTLED during the window between one run being
|
|
179
|
+
superseded and the next registering, when no checks existed at all. Require a POSITIVE assertion
|
|
180
|
+
instead: a conjunction that an empty set cannot satisfy (for example, "at least one required check
|
|
181
|
+
exists AND none is pending").
|
|
182
|
+
|
|
183
|
+
Alert on:
|
|
184
|
+
|
|
185
|
+
- threshold crossings;
|
|
186
|
+
- a sustained rate above target;
|
|
187
|
+
- a non-`ok` status;
|
|
188
|
+
- account-viability changes;
|
|
189
|
+
- window rollovers.
|
|
190
|
+
|
|
191
|
+
Stay silent otherwise.
|
|
192
|
+
|
|
193
|
+
## 12. Observed Failure Modes
|
|
194
|
+
|
|
195
|
+
1. Applying the two-account front-load target with only one viable account.
|
|
196
|
+
Cost: about 95 minutes of idle time.
|
|
197
|
+
2. Cutting a concurrency cap to control burn from work already running.
|
|
198
|
+
Cost: none directly, but the effective control went unused while the window drained.
|
|
199
|
+
3. Launching multiple items into simultaneous Phase 0.
|
|
200
|
+
Cost: a full five-hour window in 62 minutes.
|
|
201
|
+
4. Assuming a fallback account was fresh without checking.
|
|
202
|
+
Cost: about 1 hour, and seven items' preparation output stranded uncommitted when agents were
|
|
203
|
+
terminated.
|
|
204
|
+
5. Setting a commit checkpoint that landed on the forecast wall instead of before it.
|
|
205
|
+
6. Reacting to single 5-minute samples inside the quantization band, producing cap oscillation
|
|
206
|
+
that achieved nothing.
|
|
207
|
+
|
|
208
|
+
## 13. Division of Labour
|
|
209
|
+
|
|
210
|
+
An orchestrating agent generally CANNOT see quota. Do not ask it to estimate usage. The workable
|
|
211
|
+
split is:
|
|
212
|
+
|
|
213
|
+
- the **agent** reports its COST PROFILE: how many agents are alive, what kind of work they are
|
|
214
|
+
doing, and what it is about to start;
|
|
215
|
+
- the **coordinator** supplies the MEASUREMENT and the decision.
|
|
216
|
+
|
|
217
|
+
Have the agent announce before starting each item, and reply with a live reading.
|
|
218
|
+
|
|
219
|
+
Corollary: if the coordinator is slow to respond, the agent should proceed on its own rather than
|
|
220
|
+
stall. A four-hour idle period occurred because an agent correctly held for a ruling that was
|
|
221
|
+
never sent. Absorbing a small pacing error is preferable to repeating that.
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
".claude/skills/policy-compliance-order/SKILL.md",
|
|
21
21
|
".claude/agent-memory/**",
|
|
22
22
|
".agents/skills/**",
|
|
23
|
-
"scripts/vscode/**"
|
|
23
|
+
"scripts/vscode/**",
|
|
24
|
+
".github/copilot-instructions.md"
|
|
24
25
|
],
|
|
25
26
|
"mergeable_paths": [
|
|
26
27
|
"**/*.csproj",
|
|
@@ -29,6 +30,18 @@
|
|
|
29
30
|
"**/*.vbproj",
|
|
30
31
|
"**/*.props"
|
|
31
32
|
],
|
|
33
|
+
"conflict_tolerance": {
|
|
34
|
+
"tolerance_percent": 100,
|
|
35
|
+
"weights": { "same_file": 8, "possible_overlap": 2, "append_only": 1, "module": 2 },
|
|
36
|
+
"band_durations": { "C1": 1, "C2": 2, "C3": 4, "C4": 8 },
|
|
37
|
+
"default_band": "C1",
|
|
38
|
+
"append_only_paths": [
|
|
39
|
+
"**/CHANGELOG.md",
|
|
40
|
+
"extensions/drm-copilot/resources/claude-customizations/pack-manifests/core.json"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"write_intent_extraction": true,
|
|
44
|
+
"path_roots": [],
|
|
32
45
|
"modules": {
|
|
33
46
|
"config": ["config/**"]
|
|
34
47
|
},
|
|
@@ -27,12 +27,14 @@
|
|
|
27
27
|
".claude/hooks/enforce-discovery-artifact-gate.ps1",
|
|
28
28
|
".claude/hooks/enforce-epic-invocation-origin.ps1",
|
|
29
29
|
".claude/hooks/enforce-epic-merge-gate.ps1",
|
|
30
|
+
".claude/hooks/enforce-epic-merge-gate-authorization.ps1",
|
|
30
31
|
".claude/hooks/enforce-epic-wave-barrier.ps1",
|
|
31
32
|
".claude/hooks/enforce-epic-worktree-removal-gate.ps1",
|
|
32
33
|
".claude/hooks/enforce-evidence-locations.ps1",
|
|
33
34
|
".claude/hooks/enforce-feature-folder-order.ps1",
|
|
34
35
|
".claude/hooks/enforce-model-routing-receipt.ps1",
|
|
35
36
|
".claude/hooks/enforce-orchestration-preimplementation-gate.ps1",
|
|
37
|
+
".claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1",
|
|
36
38
|
".claude/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1",
|
|
37
39
|
".claude/hooks/enforce-orchestration-preimplementation-gate-modes.ps1",
|
|
38
40
|
".claude/hooks/enforce-parallel-abandon-gate.ps1",
|
|
@@ -44,6 +46,7 @@
|
|
|
44
46
|
".claude/hooks/enforce-pr-author-skill.epic-base-branch.ps1",
|
|
45
47
|
".claude/hooks/enforce-pr-author-skill.ps1",
|
|
46
48
|
".claude/hooks/enforce-pr-author-skill-helpers.ps1",
|
|
49
|
+
".claude/hooks/enforce-prd-feature-before-planner-helpers.ps1",
|
|
47
50
|
".claude/hooks/enforce-prd-feature-before-planner.ps1",
|
|
48
51
|
".claude/hooks/enforce-promotion-mcp-only.ps1",
|
|
49
52
|
".claude/hooks/hook-command-invocation.ps1",
|
|
@@ -103,6 +106,7 @@
|
|
|
103
106
|
".claude/skills/pr-author/SKILL.md",
|
|
104
107
|
".claude/skills/pr-base-branch-merge-base/SKILL.md",
|
|
105
108
|
".claude/skills/pr-context-artifacts/SKILL.md",
|
|
109
|
+
".claude/skills/quota-throttling/SKILL.md",
|
|
106
110
|
".claude/skills/remediation-handoff-atomic-planner/SKILL.md",
|
|
107
111
|
".claude/skills/research-issue/SKILL.md",
|
|
108
112
|
".claude/skills/review-epic/SKILL.md",
|
|
@@ -138,6 +142,8 @@
|
|
|
138
142
|
".claude/lib/blast-radius/BlastRadiusTokenShape.psm1",
|
|
139
143
|
".claude/lib/cleanup-manifest/CleanupWorktreeManifest.psm1",
|
|
140
144
|
".claude/lib/blast-radius/BlastRadiusConflict.psm1",
|
|
145
|
+
".claude/lib/blast-radius/BlastRadiusScheduling.psm1",
|
|
146
|
+
".claude/lib/blast-radius/BlastRadiusWriteIntent.psm1",
|
|
141
147
|
".claude/lib/project-file-merge/ProjectFileMergeGrammar.psm1",
|
|
142
148
|
".claude/lib/project-file-merge/ProjectFileMerge.psm1",
|
|
143
149
|
".claude/lib/project-file-merge/Resolve-MergeableConflict.ps1",
|
|
@@ -163,6 +169,11 @@
|
|
|
163
169
|
".claude/lib/mermaid/MermaidLineScanner.psm1",
|
|
164
170
|
".claude/lib/mermaid/MermaidMarkdownFences.psm1",
|
|
165
171
|
".claude/lib/mermaid/MermaidValidation.psm1",
|
|
172
|
+
".claude/lib/worktree-resolution/WorktreeResolution.psm1",
|
|
173
|
+
".claude/lib/worktree-resolution/WorktreeTargetResolution.psm1",
|
|
174
|
+
".claude/lib/worktree-resolution/WorktreeItemResolution.psm1",
|
|
175
|
+
".claude/lib/worktree-resolution/EpicScopeResolution.psm1",
|
|
176
|
+
".claude/lib/worktree-resolution/EpicScopeReadiness.psm1",
|
|
166
177
|
".claude/skills/mermaid-diagram/references/flowchart.md",
|
|
167
178
|
".claude/skills/mermaid-diagram/references/sequence.md",
|
|
168
179
|
".claude/skills/mermaid-diagram/references/class.md",
|