t1423: Add priority-class worker reservations for per-repo concurrency fairness#3966
Conversation
… fairness (t1423) Product repos get a guaranteed minimum share of worker slots (default 60%). Tooling repos get the remainder. Soft reservation — when one class has no pending work, the other can use freed slots. - Add PRODUCT_RESERVATION_PCT config (default 60%) - Add calculate_priority_allocations() to pulse-wrapper.sh - Add _append_priority_allocations() to surface data in pulse state - Update pulse.md Step 1 with class enforcement guidance - Update priority order and Hard Rule 6 Closes #3965
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a sophisticated worker slot allocation mechanism within the pulse supervisor, designed to ensure fair concurrency between product and tooling development efforts. By reserving a minimum percentage of worker slots for product repositories, it prevents critical user-facing work from being stalled by high volumes of internal hygiene tasks. The system incorporates a flexible soft reservation approach, allowing dynamic reallocation of unused slots, and prioritizes essential operations like merges and CI fixes to maintain continuous integration and delivery pipelines. Highlights
Changelog
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThis change introduces a priority-class worker reservation system (t1423) to enforce fair per-repo concurrency. It adds configuration-driven allocation calculations in the wrapper script and enforcement logic in dispatch documentation, reserving product-repo slots via a configurable percentage while allowing soft sharing when one class has no pending work. Changes
Sequence Diagram(s)sequenceDiagram
participant PulseWrapper as pulse-wrapper.sh
participant State as State File
participant PulseAgent as Pulse Agent
participant Dispatch as Dispatch Logic
PulseWrapper->>PulseWrapper: calculate_priority_allocations()
Note over PulseWrapper: Read repos.json, MAX_WORKERS,<br/>PRODUCT_RESERVATION_PCT
PulseWrapper->>State: Write pulse-priority-allocations
PulseWrapper->>State: _append_priority_allocations()<br/>to STATE_FILE
PulseAgent->>State: Read prefetched state
Note over PulseAgent: Extract PRODUCT_MIN<br/>and TOOLING_MAX
PulseAgent->>Dispatch: Check target repo class
alt Tooling Worker & Product Below Minimum
Dispatch->>Dispatch: Reserve slots, skip tooling
Dispatch->>Dispatch: Dispatch product work
else Product Worker or Class Has No Pending
Dispatch->>Dispatch: Proceed with dispatch
end
Dispatch->>State: Update worker allocation state
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🔍 Code Quality Report�[0;35m[MONITOR]�[0m Code Review Monitoring Report �[0;34m[INFO]�[0m Latest Quality Status: �[0;34m[INFO]�[0m Recent monitoring activity: 📈 Current Quality Metrics
Generated on: Mon Mar 9 06:16:57 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
There was a problem hiding this comment.
Code Review
This pull request introduces a priority-class worker reservation system, which is a great improvement for ensuring fairness. My review focuses on improving the implementation's efficiency and robustness. I've identified a high-severity logic bug in an edge case, an opportunity to make the jq processing more efficient, and a couple of places where error suppression should be removed to aid debugging, in line with repository guidelines.
.agents/scripts/pulse-wrapper.sh
Outdated
| if [[ "$product_min" -ge "$max_workers" && "$tooling_repos" -gt 0 ]]; then | ||
| product_min=$((max_workers - 1)) | ||
| fi |
There was a problem hiding this comment.
There's a logic issue in this block for the edge case where max_workers is 1. If there is one worker slot and at least one tooling repo, the current logic will set product_min to 0, giving the only available slot to a tooling repo. This defeats the purpose of guaranteeing a minimum share for product repos. The fix is to ensure this logic only applies when there is more than one worker to distribute.
| if [[ "$product_min" -ge "$max_workers" && "$tooling_repos" -gt 0 ]]; then | |
| product_min=$((max_workers - 1)) | |
| fi | |
| if [[ "$max_workers" -gt 1 && "$product_min" -ge "$max_workers" && "$tooling_repos" -gt 0 ]]; then | |
| product_min=$((max_workers - 1)) | |
| fi |
| PRODUCT_MIN=$(grep '^PRODUCT_MIN=' ~/.aidevops/logs/pulse-priority-allocations 2>/dev/null | cut -d= -f2 || echo 0) | ||
| TOOLING_MAX=$(grep '^TOOLING_MAX=' ~/.aidevops/logs/pulse-priority-allocations 2>/dev/null | cut -d= -f2 || echo "$MAX_WORKERS") |
There was a problem hiding this comment.
In alignment with repository guidelines to avoid blanket error suppression, it's better to remove 2>/dev/null. This change will make potential issues like file-not-found or permission errors visible in the logs, which is valuable for debugging, while the || construct will still correctly handle default values when the file is missing or a key isn't found.
| PRODUCT_MIN=$(grep '^PRODUCT_MIN=' ~/.aidevops/logs/pulse-priority-allocations 2>/dev/null | cut -d= -f2 || echo 0) | |
| TOOLING_MAX=$(grep '^TOOLING_MAX=' ~/.aidevops/logs/pulse-priority-allocations 2>/dev/null | cut -d= -f2 || echo "$MAX_WORKERS") | |
| PRODUCT_MIN=$(grep '^PRODUCT_MIN=' ~/.aidevops/logs/pulse-priority-allocations | cut -d= -f2 || echo 0) | |
| TOOLING_MAX=$(grep '^TOOLING_MAX=' ~/.aidevops/logs/pulse-priority-allocations | cut -d= -f2 || echo "$MAX_WORKERS") |
References
- Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.
.agents/scripts/pulse-wrapper.sh
Outdated
| product_repos=$(jq '[.initialized_repos[] | select(.pulse == true and (.local_only // false) == false and .slug != "" and .priority == "product")] | length' "$repos_json" 2>/dev/null) || product_repos=0 | ||
| tooling_repos=$(jq '[.initialized_repos[] | select(.pulse == true and (.local_only // false) == false and .slug != "" and .priority == "tooling")] | length' "$repos_json" 2>/dev/null) || tooling_repos=0 | ||
| [[ "$product_repos" =~ ^[0-9]+$ ]] || product_repos=0 | ||
| [[ "$tooling_repos" =~ ^[0-9]+$ ]] || tooling_repos=0 |
There was a problem hiding this comment.
These four lines can be replaced with a more efficient and robust approach. The current implementation calls jq twice, parsing the same large JSON file each time. A single jq process can calculate both counts at once. This also provides an opportunity to remove 2>/dev/null, which aligns with repository guidelines to not suppress stderr, making debugging easier. The suggested code consolidates the counting, removes the error suppression, and uses a cleaner way to set default values.
| product_repos=$(jq '[.initialized_repos[] | select(.pulse == true and (.local_only // false) == false and .slug != "" and .priority == "product")] | length' "$repos_json" 2>/dev/null) || product_repos=0 | |
| tooling_repos=$(jq '[.initialized_repos[] | select(.pulse == true and (.local_only // false) == false and .slug != "" and .priority == "tooling")] | length' "$repos_json" 2>/dev/null) || tooling_repos=0 | |
| [[ "$product_repos" =~ ^[0-9]+$ ]] || product_repos=0 | |
| [[ "$tooling_repos" =~ ^[0-9]+$ ]] || tooling_repos=0 | |
| read -r product_repos tooling_repos < <(jq -r ' | |
| .initialized_repos | | |
| map(select(.pulse == true and (.local_only // false) == false and .slug != "")) | | |
| [ | |
| (map(select(.priority == "product")) | length), | |
| (map(select(.priority == "tooling")) | length) | |
| ] | @tsv | |
| ' "$repos_json") | |
| product_repos=${product_repos:-0} | |
| tooling_repos=${tooling_repos:-0} |
References
- Consolidate multiple 'jq' calls into a single pass where possible to improve performance and script efficiency.
- Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.
- Fix 1-worker edge case: product keeps the only slot (was giving it to tooling) - Consolidate two jq calls into single pass for efficiency - Keep 2>/dev/null on jq (repos.json may not exist during first run)
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.agents/scripts/commands/pulse.md:
- Line 1049: Update the hard rule that currently reads "NEVER exceed MAX_WORKERS
or violate priority-class reservations" to mirror Step 1 exemptions: explicitly
allow merges and priority-2 CI-fix dispatches to bypass class reservations and
consume product-reserved slots when those specific conditions apply; modify the
sentence in the hard-rules section (the rule text containing "NEVER exceed
MAX_WORKERS or violate priority-class reservations") to include an exception
clause referencing "merges" and "priority-2 CI-fix dispatches" so the stronger
wording does not block the intended bypass behavior described in Step 1.
- Around line 62-65: Update the predicate that determines "product repos have
pending work" (used in the tooling dispatch rule where it checks product_active
< PRODUCT_MIN) to include not only open issues and failing-CI PRs but also
mission features, salvage work, review-fix work, approved debt tasks, and any
other dispatchable product work types (e.g., approved/ready backlog items and
orphaned PRs); ensure the documentation and the soft-reservation rule (when
product repos have no pending work their reserved slots become available)
reference the expanded set so tooling dispatch correctly skips when any of these
product work categories exist.
In @.agents/scripts/pulse-wrapper.sh:
- Around line 3202-3205: The branch that forces product_min down to
max_workers-1 incorrectly runs when max_workers==1 and tooling_repos>0, allowing
tooling to steal the only slot; update the conditional around product_min
adjustment (the block referencing product_min, max_workers, tooling_repos) so it
only reduces product_min when max_workers is greater than 1 (e.g. add a
"$max_workers" -gt 1 check) so you don't lower product_min to 0 when there's a
single worker.
- Around line 3168-3170: The conditional that checks if "$repos_json" exists or
jq is available returns early without touching the previous allocation state;
update this branch so that before returning it truncates or overwrites
"$alloc_file" (the pulse-priority-allocations state file) to an empty/clean
state and logs that action to "$LOGFILE" (same context as the existing message),
ensuring stale reservations are removed when repos.json or jq is missing; locate
the check referencing "$repos_json", "jq", "$LOGFILE" and "$alloc_file" and add
the truncation/overwrite step immediately before the return.
- Around line 3184-3217: Clamp PRODUCT_RESERVATION_PCT to a maximum of 100
before using it to compute product_min and before persisting it to the
allocation file: introduce a local variable (e.g., pct_clamped) or overwrite
PRODUCT_RESERVATION_PCT with its min(PRODUCT_RESERVATION_PCT,100) value, use
that clamped value in the product_min calculation (the block that computes
product_min and tooling_max) and write the clamped value to the alloc_file
instead of the raw PRODUCT_RESERVATION_PCT so the allocation math and output
cannot exceed 100%.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 504a3728-5eff-4d5f-a538-75f9a690400b
⛔ Files ignored due to path filters (1)
todo/tasks/t1423-brief.mdis excluded by!todo/tasks/*-brief.md
📒 Files selected for processing (2)
.agents/scripts/commands/pulse.md.agents/scripts/pulse-wrapper.sh
| 3. **If dispatching a tooling worker:** check whether product-class workers are using fewer than `PRODUCT_MIN` slots. If `product_active < PRODUCT_MIN` AND product repos have pending work (open issues or failing PRs), the remaining product slots are **reserved** — skip the tooling dispatch and look for product work instead. | ||
| 4. **If dispatching a product worker:** always proceed — product has no ceiling (only a floor). | ||
| 5. **Exemptions:** Merges (priority 1) and CI-fix dispatches (priority 2) are exempt from class checks — they always proceed regardless of class. | ||
| 6. **Soft reservation:** When product repos have no pending work (no open issues, no failing-CI PRs, no orphaned PRs), their reserved slots become available for tooling. The reservation protects product work when it exists, not when it doesn't. |
There was a problem hiding this comment.
Reserve product slots for any dispatchable product work, not just issues/failing PRs.
This check treats product repos as idle when they only have mission features, salvage work, review-fix work, or approved debt tasks pending. In that case tooling can still consume the reserved pool, which defeats the fairness guarantee for product repos.
Suggested fix
-3. **If dispatching a tooling worker:** check whether product-class workers are using fewer than `PRODUCT_MIN` slots. If `product_active < PRODUCT_MIN` AND product repos have pending work (open issues or failing PRs), the remaining product slots are **reserved** — skip the tooling dispatch and look for product work instead.
+3. **If dispatching a tooling worker:** check whether product-class workers are using fewer than `PRODUCT_MIN` slots. If `product_active < PRODUCT_MIN` AND product repos have any dispatchable pending work (for example: open issues, failing/review-fix PRs, orphaned/salvage PRs, active mission features, or approved debt tasks), the remaining product slots are **reserved** — skip the tooling dispatch and look for product work instead.
@@
-6. **Soft reservation:** When product repos have no pending work (no open issues, no failing-CI PRs, no orphaned PRs), their reserved slots become available for tooling. The reservation protects product work when it exists, not when it doesn't.
+6. **Soft reservation:** When product repos have no dispatchable pending work, their reserved slots become available for tooling. The reservation protects product work when it exists, not when it doesn't.🧰 Tools
🪛 LanguageTool
[style] ~63-~63: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...and look for product work instead. 4. If dispatching a product worker: always ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.agents/scripts/commands/pulse.md around lines 62 - 65, Update the predicate
that determines "product repos have pending work" (used in the tooling dispatch
rule where it checks product_active < PRODUCT_MIN) to include not only open
issues and failing-CI PRs but also mission features, salvage work, review-fix
work, approved debt tasks, and any other dispatchable product work types (e.g.,
approved/ready backlog items and orphaned PRs); ensure the documentation and the
soft-reservation rule (when product repos have no pending work their reserved
slots become available) reference the expanded set so tooling dispatch correctly
skips when any of these product work categories exist.
| 4. **NEVER use `claude` CLI.** Always `opencode run`. | ||
| 5. **NEVER include private repo names** in public issue titles/bodies/comments. | ||
| 6. **NEVER exceed MAX_WORKERS.** Count before dispatching. | ||
| 6. **NEVER exceed MAX_WORKERS or violate priority-class reservations.** Count before dispatching. Check class allocations (Step 1) — tooling workers must not consume product-reserved slots when product work is pending. |
There was a problem hiding this comment.
Mirror the Step 1 exemptions in the hard rule.
Step 1 explicitly allows merges and priority-2 CI-fix dispatches to bypass class reservations, but this hard rule reads like an absolute prohibition. Because the hard-rules section has stronger wording, the agent can end up blocking the exempt cases you intended to keep moving.
Suggested fix
-6. **NEVER exceed MAX_WORKERS or violate priority-class reservations.** Count before dispatching. Check class allocations (Step 1) — tooling workers must not consume product-reserved slots when product work is pending.
+6. **NEVER exceed MAX_WORKERS.** For normal dispatches, do not violate priority-class reservations. Count before dispatching. Check class allocations (Step 1) — tooling workers must not consume product-reserved slots when product work is pending. **Exemption:** merges and priority-2 CI-fix dispatches still proceed as described in Step 1.🧰 Tools
🪛 LanguageTool
[style] ~1049-~1049: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...blic issue titles/bodies/comments. 6. **NEVER exceed MAX_WORKERS or violate priority-...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.agents/scripts/commands/pulse.md at line 1049, Update the hard rule that
currently reads "NEVER exceed MAX_WORKERS or violate priority-class
reservations" to mirror Step 1 exemptions: explicitly allow merges and
priority-2 CI-fix dispatches to bypass class reservations and consume
product-reserved slots when those specific conditions apply; modify the sentence
in the hard-rules section (the rule text containing "NEVER exceed MAX_WORKERS or
violate priority-class reservations") to include an exception clause referencing
"merges" and "priority-2 CI-fix dispatches" so the stronger wording does not
block the intended bypass behavior described in Step 1.
| if [[ ! -f "$repos_json" ]] || ! command -v jq &>/dev/null; then | ||
| echo "[pulse-wrapper] repos.json or jq not available — skipping priority allocations" >>"$LOGFILE" | ||
| return 0 |
There was a problem hiding this comment.
Delete stale allocation state on the skip path.
If repos.json or jq is unavailable here, the function returns without touching the previous pulse-priority-allocations file. Step 1 in pulse.md reads that file directly, so the next pulse can enforce stale reservations instead of falling back to the flat-pool behavior. Clear or overwrite "$alloc_file" before returning. As per coding guidelines, automation scripts should focus on reliability and robustness.
Suggested fix
if [[ ! -f "$repos_json" ]] || ! command -v jq &>/dev/null; then
+ rm -f "$alloc_file"
echo "[pulse-wrapper] repos.json or jq not available — skipping priority allocations" >>"$LOGFILE"
return 0
fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if [[ ! -f "$repos_json" ]] || ! command -v jq &>/dev/null; then | |
| echo "[pulse-wrapper] repos.json or jq not available — skipping priority allocations" >>"$LOGFILE" | |
| return 0 | |
| if [[ ! -f "$repos_json" ]] || ! command -v jq &>/dev/null; then | |
| rm -f "$alloc_file" | |
| echo "[pulse-wrapper] repos.json or jq not available — skipping priority allocations" >>"$LOGFILE" | |
| return 0 |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.agents/scripts/pulse-wrapper.sh around lines 3168 - 3170, The conditional
that checks if "$repos_json" exists or jq is available returns early without
touching the previous allocation state; update this branch so that before
returning it truncates or overwrites "$alloc_file" (the
pulse-priority-allocations state file) to an empty/clean state and logs that
action to "$LOGFILE" (same context as the existing message), ensuring stale
reservations are removed when repos.json or jq is missing; locate the check
referencing "$repos_json", "jq", "$LOGFILE" and "$alloc_file" and add the
truncation/overwrite step immediately before the return.
| # Calculate reservations | ||
| # product_min = ceil(max_workers * PRODUCT_RESERVATION_PCT / 100) | ||
| # Using integer arithmetic: ceil(a/b) = (a + b - 1) / b | ||
| local product_min tooling_max | ||
| if [[ "$product_repos" -eq 0 ]]; then | ||
| # No product repos — all slots available for tooling | ||
| product_min=0 | ||
| tooling_max="$max_workers" | ||
| elif [[ "$tooling_repos" -eq 0 ]]; then | ||
| # No tooling repos — all slots available for product | ||
| product_min="$max_workers" | ||
| tooling_max=0 | ||
| else | ||
| product_min=$(((max_workers * PRODUCT_RESERVATION_PCT + 99) / 100)) | ||
| # Ensure product_min doesn't exceed max_workers | ||
| if [[ "$product_min" -gt "$max_workers" ]]; then | ||
| product_min="$max_workers" | ||
| fi | ||
| # Ensure at least 1 slot for tooling when tooling repos exist | ||
| if [[ "$product_min" -ge "$max_workers" && "$tooling_repos" -gt 0 ]]; then | ||
| product_min=$((max_workers - 1)) | ||
| fi | ||
| tooling_max=$((max_workers - product_min)) | ||
| fi | ||
|
|
||
| # Write allocation file (key=value, readable by pulse.md) | ||
| { | ||
| echo "MAX_WORKERS=${max_workers}" | ||
| echo "PRODUCT_REPOS=${product_repos}" | ||
| echo "TOOLING_REPOS=${tooling_repos}" | ||
| echo "PRODUCT_MIN=${product_min}" | ||
| echo "TOOLING_MAX=${tooling_max}" | ||
| echo "PRODUCT_RESERVATION_PCT=${PRODUCT_RESERVATION_PCT}" | ||
| } >"$alloc_file" |
There was a problem hiding this comment.
Clamp reservation percentages above 100 before persisting them.
A value like PRODUCT_RESERVATION_PCT=150 currently produces impossible state output (150% minimum) and allocation math that operators will not expect. Clamp to 100 before computing and writing the allocation file.
Suggested fix
- local product_min tooling_max
+ local reservation_pct="$PRODUCT_RESERVATION_PCT"
+ local product_min tooling_max
+ if [[ "$reservation_pct" -gt 100 ]]; then
+ reservation_pct=100
+ fi
if [[ "$product_repos" -eq 0 ]]; then
# No product repos — all slots available for tooling
product_min=0
tooling_max="$max_workers"
elif [[ "$tooling_repos" -eq 0 ]]; then
@@
- product_min=$(((max_workers * PRODUCT_RESERVATION_PCT + 99) / 100))
+ product_min=$(((max_workers * reservation_pct + 99) / 100))
@@
- echo "PRODUCT_RESERVATION_PCT=${PRODUCT_RESERVATION_PCT}"
+ echo "PRODUCT_RESERVATION_PCT=${reservation_pct}"
} >"$alloc_file"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # Calculate reservations | |
| # product_min = ceil(max_workers * PRODUCT_RESERVATION_PCT / 100) | |
| # Using integer arithmetic: ceil(a/b) = (a + b - 1) / b | |
| local product_min tooling_max | |
| if [[ "$product_repos" -eq 0 ]]; then | |
| # No product repos — all slots available for tooling | |
| product_min=0 | |
| tooling_max="$max_workers" | |
| elif [[ "$tooling_repos" -eq 0 ]]; then | |
| # No tooling repos — all slots available for product | |
| product_min="$max_workers" | |
| tooling_max=0 | |
| else | |
| product_min=$(((max_workers * PRODUCT_RESERVATION_PCT + 99) / 100)) | |
| # Ensure product_min doesn't exceed max_workers | |
| if [[ "$product_min" -gt "$max_workers" ]]; then | |
| product_min="$max_workers" | |
| fi | |
| # Ensure at least 1 slot for tooling when tooling repos exist | |
| if [[ "$product_min" -ge "$max_workers" && "$tooling_repos" -gt 0 ]]; then | |
| product_min=$((max_workers - 1)) | |
| fi | |
| tooling_max=$((max_workers - product_min)) | |
| fi | |
| # Write allocation file (key=value, readable by pulse.md) | |
| { | |
| echo "MAX_WORKERS=${max_workers}" | |
| echo "PRODUCT_REPOS=${product_repos}" | |
| echo "TOOLING_REPOS=${tooling_repos}" | |
| echo "PRODUCT_MIN=${product_min}" | |
| echo "TOOLING_MAX=${tooling_max}" | |
| echo "PRODUCT_RESERVATION_PCT=${PRODUCT_RESERVATION_PCT}" | |
| } >"$alloc_file" | |
| # Calculate reservations | |
| # product_min = ceil(max_workers * PRODUCT_RESERVATION_PCT / 100) | |
| # Using integer arithmetic: ceil(a/b) = (a + b - 1) / b | |
| local reservation_pct="$PRODUCT_RESERVATION_PCT" | |
| local product_min tooling_max | |
| if [[ "$reservation_pct" -gt 100 ]]; then | |
| reservation_pct=100 | |
| fi | |
| if [[ "$product_repos" -eq 0 ]]; then | |
| # No product repos — all slots available for tooling | |
| product_min=0 | |
| tooling_max="$max_workers" | |
| elif [[ "$tooling_repos" -eq 0 ]]; then | |
| # No tooling repos — all slots available for product | |
| product_min="$max_workers" | |
| tooling_max=0 | |
| else | |
| product_min=$(((max_workers * reservation_pct + 99) / 100)) | |
| # Ensure product_min doesn't exceed max_workers | |
| if [[ "$product_min" -gt "$max_workers" ]]; then | |
| product_min="$max_workers" | |
| fi | |
| # Ensure at least 1 slot for tooling when tooling repos exist | |
| if [[ "$product_min" -ge "$max_workers" && "$tooling_repos" -gt 0 ]]; then | |
| product_min=$((max_workers - 1)) | |
| fi | |
| tooling_max=$((max_workers - product_min)) | |
| fi | |
| # Write allocation file (key=value, readable by pulse.md) | |
| { | |
| echo "MAX_WORKERS=${max_workers}" | |
| echo "PRODUCT_REPOS=${product_repos}" | |
| echo "TOOLING_REPOS=${tooling_repos}" | |
| echo "PRODUCT_MIN=${product_min}" | |
| echo "TOOLING_MAX=${tooling_max}" | |
| echo "PRODUCT_RESERVATION_PCT=${reservation_pct}" | |
| } >"$alloc_file" |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.agents/scripts/pulse-wrapper.sh around lines 3184 - 3217, Clamp
PRODUCT_RESERVATION_PCT to a maximum of 100 before using it to compute
product_min and before persisting it to the allocation file: introduce a local
variable (e.g., pct_clamped) or overwrite PRODUCT_RESERVATION_PCT with its
min(PRODUCT_RESERVATION_PCT,100) value, use that clamped value in the
product_min calculation (the block that computes product_min and tooling_max)
and write the clamped value to the alloc_file instead of the raw
PRODUCT_RESERVATION_PCT so the allocation math and output cannot exceed 100%.
🔍 Code Quality Report�[0;35m[MONITOR]�[0m Code Review Monitoring Report �[0;34m[INFO]�[0m Latest Quality Status: �[0;34m[INFO]�[0m Recent monitoring activity: 📈 Current Quality Metrics
Generated on: Mon Mar 9 06:25:51 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
|



Summary
Changes
PRODUCT_RESERVATION_PCTconfig,calculate_priority_allocations()function,_append_priority_allocations()state outputTesting
Current allocation (4 product, 4 tooling repos, ~6 workers)
Closes #3965
Summary by CodeRabbit
New Features
Documentation