Skip to content

t1330: Rate limit tracker for provider utilisation monitoring#2273

Merged
marcusquinn merged 8 commits intomainfrom
feature/t1330
Feb 25, 2026
Merged

t1330: Rate limit tracker for provider utilisation monitoring#2273
marcusquinn merged 8 commits intomainfrom
feature/t1330

Conversation

@marcusquinn
Copy link
Owner

@marcusquinn marcusquinn commented Feb 25, 2026

Summary

  • Adds aidevops stats rate-limits command to observability-helper.sh that monitors requests/min and tokens/min per provider from the existing observability DB (t1307), compares against configurable rate limits, and warns at 80% threshold
  • Integrates rate limit awareness into model-availability-helper.sh resolve_tier() so throttle-risk providers are automatically deprioritised in favour of fallback providers
  • Integrates rate limit warning into dispatch.sh resolve_model() static fallback path

Changes

New: .agents/configs/rate-limits.json.txt

Configurable rate limit definitions per provider (requests/min, tokens/min, billing_type). Copy to ~/.config/aidevops/rate-limits.json and adjust for your plan. Covers: anthropic, openai, google, deepseek, openrouter, groq, opencode, xai.

Extended: observability-helper.sh

  • cmd_rate_limits() — new command showing rolling-window utilisation vs configured limits per provider. Supports --json, --provider, --window flags.
  • check_rate_limit_risk() — returns ok/warn/critical for a provider based on current utilisation vs configured limits
  • Supporting helpers: _get_rate_limits_config(), _get_rate_limit_value(), _get_warn_pct(), _get_window_minutes(), _get_configured_providers()

Extended: model-availability-helper.sh

  • _check_provider_rate_limit_risk() — queries observability-helper.sh for rate limit status
  • _extract_provider() — extracts provider from model spec
  • resolve_tier() — now checks rate limit risk before selecting primary provider; if primary is at throttle risk (≥warn_pct), prefers fallback provider
  • cmd_rate_limits() — now also shows observability-derived utilisation alongside API header data

Extended: dispatch.sh

  • resolve_model() — adds rate limit risk check in static fallback path; logs warning when anthropic is at throttle risk, prompting operator to configure alternative providers

Acceptance Criteria

  • Rate limit definitions exist per provider (requests_per_min, tokens_per_min) in .agents/configs/rate-limits.json.txt
  • aidevops stats rate-limits shows current utilisation per provider
  • When a provider exceeds 80% of its rate limit, model routing prefers alternatives (via resolve_tier() in model-availability-helper.sh)
  • Rate limit data derived from existing observability SQLite DB — no new data collection
  • Works with both token-billed and subscription providers (billing_type field)
  • ShellCheck clean — zero errors/warnings on all modified .sh files

Testing

# Show rate limit utilisation
aidevops stats rate-limits

# JSON output for scripting
aidevops stats rate-limits --json

# Filter by provider
aidevops stats rate-limits --provider anthropic --json

# Via model-availability-helper
.agents/scripts/model-availability-helper.sh rate-limits

Ref: t1307 (observability DB), t1100 (budget-aware routing), GH#2263

Summary by CodeRabbit

  • New Features

    • CLI rate-limits command to view per-provider utilization (ok/warn/critical) with JSON output and filtering.
    • Automatic routing notices and fallback suggestions when a provider shows throttle risk.
    • Observability now surfaces rate-limit utilization alongside API-derived status.
  • Documentation

    • Added user-configurable rate-limits template, help text describing config location, fields, and usage.
  • Chores

    • Package/tooling version bumped to 1.1.0.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

Warning

Rate limit exceeded

@marcusquinn has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 49 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

📥 Commits

Reviewing files that changed from the base of the PR and between 2807eb9 and 9cd012a.

📒 Files selected for processing (3)
  • .agents/scripts/model-availability-helper.sh
  • .agents/scripts/observability-helper.sh
  • .agents/scripts/supervisor-archived/dispatch.sh

Walkthrough

Adds rate-limit awareness across the agents: a new rate-limits config template, observability-helper rate-limit tracking and CLI, model-availability-helper provider extraction and throttle-risk checks, and supervisor dispatch warnings when providers (notably Anthropic) hit warn/critical thresholds.

Changes

Cohort / File(s) Summary
Rate-limits config
.agents/configs/rate-limits.json.txt
New template defining per-provider limits (requests/tokens per minute), global metadata (warn_pct, window_minutes, threshold), and billing types.
Observability helper
.agents/scripts/observability-helper.sh
Adds rate-limit tracking (t1330): new config constants, config readers, provider value getters, risk scoring (check_rate_limit_risk), provider listing, cmd_rate_limits() CLI, help/dispatch wiring, and version bump to 1.1.0.
Model availability helper
.agents/scripts/model-availability-helper.sh
Adds _extract_provider() (model → provider mapping) and _check_provider_rate_limit_risk() to query observability; integrates throttle-risk checks into tier resolution and rate-limit/status display.
Supervisor dispatch
.agents/scripts/supervisor/dispatch.sh
Emits runtime warnings when Anthropic rate-limit status is warn/critical during model resolution (two code locations); no core selection changes.
Acceptance / tasks
todo/tasks/t1330-brief.md
Adds acceptance-check items for rate-limit definitions and a shellcheck verification block; no runtime logic changes.

Sequence Diagram(s)

sequenceDiagram
    participant ModelSelector as ModelSelector
    participant RLChecker as RateLimitChecker
    participant ObsHelper as ObservabilityHelper
    participant Config as RateLimitsConfig
    participant ProviderResolver as ProviderResolver

    ModelSelector->>RLChecker: ask risk for <model_id>
    RLChecker->>Config: read provider thresholds (window, warn_pct)
    Config-->>RLChecker: return thresholds
    RLChecker->>ObsHelper: query utilization metrics (requests/tokens)
    ObsHelper-->>RLChecker: return utilization data
    RLChecker->>RLChecker: compute status (ok / warn / critical)
    RLChecker-->>ModelSelector: return risk

    alt risk == warn or critical
        ModelSelector->>ProviderResolver: prefer fallback provider
    else risk == ok
        ModelSelector->>ProviderResolver: use primary provider
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

needs-review

Poem

🚦 Limits watched as metrics chime,
Fallbacks ready, chosen in time.
Observability hums in tune,
Warnings whisper, plans attune.
DevOps sails beneath the moon.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly and specifically describes the main feature being introduced—a rate limit tracker for provider utilization monitoring—which directly maps to the primary changes across observability-helper.sh, model-availability-helper.sh, and related configuration.
Docstring Coverage ✅ Passed Docstring coverage is 94.12% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/t1330

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello @marcusquinn, 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 significantly enhances the AI model routing system by integrating comprehensive rate limit awareness. It introduces a new command for monitoring provider utilization, enabling users to track requests and tokens per minute against defined limits. Crucially, the system now intelligently deprioritizes providers at risk of throttling, ensuring more resilient and efficient model selection. This proactive approach helps avoid service interruptions due to exceeding API rate limits.

Highlights

  • Rate Limit Monitoring Command: Introduced a new aidevops stats rate-limits command to monitor requests/min and tokens/min per provider from the observability database, comparing against configurable rate limits and warning at an 80% threshold.
  • Dynamic Provider Deprioritization: Integrated rate limit awareness into model-availability-helper.sh's resolve_tier() function, automatically deprioritizing throttle-risk providers in favor of fallback providers.
  • Static Fallback Rate Limit Warning: Integrated a rate limit warning into dispatch.sh's resolve_model() static fallback path, logging a warning if a primary provider (e.g., Anthropic) is at throttle risk.
  • Configurable Rate Limit Definitions: Added a new configuration file, .agents/configs/rate-limits.json.txt, allowing users to define rate limits (requests/min, tokens/min, billing_type) for various AI providers.
Changelog
  • .agents/configs/rate-limits.json.txt
    • Added a new JSON configuration file to define rate limits (requests/min, tokens/min, billing_type) for various AI providers, including a warning threshold and window minutes.
  • .agents/scripts/model-availability-helper.sh
    • Introduced _check_provider_rate_limit_risk to query observability-helper.sh for a provider's rate limit status.
    • Added _extract_provider to parse the provider name from a model specification.
    • Modified resolve_tier to check the primary provider's rate limit risk and prefer a fallback provider if the primary is at throttle risk.
    • Updated cmd_rate_limits to display observability-derived utilization alongside API header data.
  • .agents/scripts/observability-helper.sh
    • Added rate-limits as a new command option.
    • Updated the script version to 1.1.0.
    • Defined new constants for rate limit configuration file paths and default values.
    • Implemented helper functions: _get_rate_limits_config, _get_rate_limit_value, _get_warn_pct, _get_window_minutes, _get_configured_providers for managing rate limit settings.
    • Created check_rate_limit_risk to determine a provider's risk status (ok, warn, critical) based on current usage and configured limits.
    • Developed cmd_rate_limits to display detailed rate limit utilization, supporting JSON output, provider filtering, and window customization.
    • Extended cmd_help with new options and examples for the rate-limits command.
    • Integrated cmd_rate_limits into the main command dispatch logic.
  • .agents/scripts/supervisor/dispatch.sh
    • Updated comments in resolve_model to reflect the new rate limit awareness in model-availability-helper.sh.
    • Added a rate limit check within resolve_model's static fallback path to log warnings if Anthropic is at throttle risk, prompting users to configure alternatives.
Activity
  • No human activity has been recorded on this pull request yet.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link
Contributor

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 56 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Wed Feb 25 03:18:14 UTC 2026: Code review monitoring started
Wed Feb 25 03:18:15 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 56

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 56
  • VULNERABILITIES: 0

Generated on: Wed Feb 25 03:18:17 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a valuable rate-limiting awareness mechanism to improve provider routing. The implementation is well-structured, adding a new rate-limits command and integrating it into the model resolution logic. My review focuses on improving the robustness and maintainability of the new shell scripts. Specifically, I've pointed out several instances where suppressing stderr can hide important errors, and a case where manually constructing JSON can be unsafe. Addressing these points will make the new functionality more reliable and easier to debug.

@augmentcode
Copy link

augmentcode bot commented Feb 25, 2026

🤖 Augment PR Summary

Summary: Introduces rate-limit utilisation monitoring per provider and makes routing aware of throttle risk.

Changes:

  • Adds a configurable provider rate-limit template at .agents/configs/rate-limits.json.txt (requests/min, tokens/min, billing type, thresholds).
  • Extends observability-helper.sh with a new rate-limits command that reads the existing observability SQLite DB and reports rolling-window utilisation, with optional JSON output and filtering.
  • Adds check_rate_limit_risk() and supporting config helpers to classify providers as ok/warn/critical based on utilisation vs configured limits.
  • Updates model-availability-helper.sh tier resolution to prefer a fallback provider when the primary provider is at throttle risk.
  • Enhances model-availability-helper.sh rate-limits output to include observability-derived utilisation alongside API header-derived limits.
  • Updates supervisor dispatch.sh static fallback path to warn when Anthropic appears throttle-risk, prompting configuration of alternative providers.

Technical Notes: Rate-limit data is derived from the existing observability DB (no new collection) and uses a configurable rolling window with a default warn threshold of 80%.

🤖 Was this summary useful? React with 👍 or 👎

Copy link

@augmentcode augmentcode bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

coderabbitai[bot]
coderabbitai bot previously requested changes Feb 25, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 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/model-availability-helper.sh:
- Around line 944-945: The code is overwriting the rate-limit status returned by
_check_provider_rate_limit_risk by using "|| rl_risk=\"ok\"" which loses
"warn"/"critical" outputs; instead, capture the function output into rl_risk
regardless of exit code (call _check_provider_rate_limit_risk
"$primary_provider" and allow non-zero exits), then only apply a default if
rl_risk is empty (e.g., set rl_risk=${rl_risk:-ok}); ensure you still redirect
stderr as before and then use rl_risk in the subsequent check that compares to
"warn" or "critical".

In @.agents/scripts/observability-helper.sh:
- Around line 1266-1296: Validate and sanitize the window_minutes value returned
by _get_window_minutes before embedding it into SQL: ensure window_minutes is a
positive integer (e.g., use a regex like '^[0-9]+$' or arithmetic casting) and
fallback to a safe default if invalid; replace direct interpolation of
"${window_minutes}" in db_query calls with the validated/clamped variable (same
change for occurrences around the other db_query blocks noted) and do the same
for any effective_window variables so SQL date modifiers only ever receive a
numeric value, preventing malformed queries and injection via CLI/config.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 76d1493 and 35be5c0d1822cba1d8c0e317927e3f71b7709e98.

📒 Files selected for processing (4)
  • .agents/configs/rate-limits.json.txt
  • .agents/scripts/model-availability-helper.sh
  • .agents/scripts/observability-helper.sh
  • .agents/scripts/supervisor/dispatch.sh

@marcusquinn marcusquinn added the needs-review Flagged for human review by AI supervisor label Feb 25, 2026
@marcusquinn
Copy link
Owner Author

Flagged for Human Review

Reason: PR #2273 (t1330) is OPEN but task t1330 was cancelled in supervisor DB. PR has 1 review request change and 2 comments. Decide whether to close this PR or merge the useful work and update DB state.

This issue has been flagged by the AI supervisor for human review. Please assess and take appropriate action.


Flagged by AI Supervisor (automated reasoning cycle)

@marcusquinn
Copy link
Owner Author

Flagged for Human Review

Reason: PR #2273 (t1330) is OPEN but task t1330 is cancelled in supervisor DB. PR has 1 review request and 2 comments. Needs human decision: close the PR or reopen the task.

This issue has been flagged by the AI supervisor for human review. Please assess and take appropriate action.


Flagged by AI Supervisor (automated reasoning cycle)

@marcusquinn
Copy link
Owner Author

Flagged for Human Review

Reason: PR #2273 (t1330) is OPEN but task t1330 was cancelled in supervisor DB. PR should be closed.

This issue has been flagged by the AI supervisor for human review. Please assess and take appropriate action.


Flagged by AI Supervisor (automated reasoning cycle)

@marcusquinn
Copy link
Owner Author

Flagged for Human Review

Reason: PR #2273 (t1330) is open but task t1330 was cancelled in supervisor DB as 'DB orphan with no TODO entry'. This PR should be closed to avoid confusion.

This issue has been flagged by the AI supervisor for human review. Please assess and take appropriate action.


Flagged by AI Supervisor (automated reasoning cycle)

@marcusquinn
Copy link
Owner Author

Flagged for Human Review

Reason: PR #2273 (t1330: Rate limit tracker) is still OPEN but t1330 was cancelled in supervisor DB as 'DB orphan with no TODO entry'. This orphan PR should be closed or the work salvaged. Human decision needed: close the PR or re-register the task.

This issue has been flagged by the AI supervisor for human review. Please assess and take appropriate action.


Flagged by AI Supervisor (automated reasoning cycle)

@marcusquinn
Copy link
Owner Author

Flagged for Human Review

Reason: t1330 (rate limit tracker) PR #2273 has 1 rejection and 2 comments, and the task was cancelled in supervisor DB as 'DB orphan with no TODO entry'. Determine if this feature is still wanted — if so, reopen and address review feedback; if not, close the PR.

This issue has been flagged by the AI supervisor for human review. Please assess and take appropriate action.


Flagged by AI Supervisor (automated reasoning cycle)

@github-actions
Copy link
Contributor

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 70 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Wed Feb 25 13:54:58 UTC 2026: Code review monitoring started
Wed Feb 25 13:54:59 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 70

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 70
  • VULNERABILITIES: 0

Generated on: Wed Feb 25 13:55:01 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@marcusquinn
Copy link
Owner Author

@coderabbitai review

All review feedback has been addressed across commits 48fcba65 and 73ccd647:

  1. CRITICAL: rl_risk overwrite bug (CodeRabbit, Augment) - Fixed: changed || rl_risk="ok" to || true + ${rl_risk:-ok} default so warn/critical status is preserved
  2. SQL injection via window_minutes (CodeRabbit, Augment) - Fixed: added numeric validation with regex ^[0-9]+$ and fallback to defaults in both check_rate_limit_risk() and cmd_rate_limits()
  3. Remove 2>/dev/null suppression (Gemini x8) - Fixed: removed all blanket stderr suppression across model-availability-helper.sh, observability-helper.sh, and dispatch.sh; || true / || val="0" patterns provide graceful fallback
  4. Unsafe JSON construction (Gemini) - Fixed: replaced printf-based JSON with jq -c -n using --arg/--argjson for safe escaping

ShellCheck clean on all three modified files.

@github-actions
Copy link
Contributor

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 70 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Wed Feb 25 13:57:28 UTC 2026: Code review monitoring started
Wed Feb 25 13:57:28 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 70

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 70
  • VULNERABILITIES: 0

Generated on: Wed Feb 25 13:57:31 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

@marcusquinn: Thank you for the detailed summary of the fixes! I can see you've addressed:

Critical security & correctness fixes:

  • rl_risk variable preservation (warn/critical states now properly maintained)
  • SQL injection prevention with numeric validation
  • Removed error suppression for better debugging
  • Safe JSON construction with jq

ShellCheck compliance confirmed on all modified scripts

I'll review the changes now to verify these fixes are correctly implemented across the three modified shell scripts.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@marcusquinn
Copy link
Owner Author

@coderabbitai review

All review feedback has been addressed in commit 48fcba65:

  1. Critical fix: Rate-limit risk bypass — || rl_risk="ok" was overwriting warn/critical status. Now uses || true inside subshell + ${var:-default} pattern to preserve function output regardless of exit code.
  2. SQL injection guard: window_minutes/effective_window validated as positive integers before SQL interpolation. Falls back to DEFAULT_WINDOW_MINUTES if invalid.
  3. Removed 2>/dev/null suppressions: All blanket stderr suppressions removed from new rate-limit code across 3 files. The || fallback patterns already handle errors gracefully.
  4. Safe JSON construction: Replaced manual printf JSON with jq -c -n --arg/--argjson for proper escaping.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

@marcusquinn: Thank you for the comprehensive summary of the security and correctness fixes in commit 48fcba65! I can see you've addressed:

Critical variable preservation - rl_risk now properly maintains warn/critical states
SQL injection prevention - Input validation on window_minutes with fallback
Improved debugging - Removed blanket stderr suppressions
Safe JSON handling - Using jq for proper escaping

I'll review the changes now across the three modified shell scripts to verify these fixes are correctly implemented.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]
coderabbitai bot previously requested changes Feb 25, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 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/observability-helper.sh:
- Around line 1356-1358: The pre-ingest command (cmd_ingest) can still emit
stdout parse info that contaminates the JSON produced by later rate-limits
--json; suppress all cmd_ingest output by redirecting both stdout and stderr (so
nothing prints to stdout) or use a true silent flag if cmd_ingest supports one,
keeping the existing fallback (|| true). Update the invocation of cmd_ingest in
the script to fully silence its output so downstream consumers of rate-limits
--json receive only valid JSON.

In `@todo/tasks/t1330-brief.md`:
- Around line 42-64: The fenced YAML and code blocks in the acceptance criteria
(the ```yaml blocks showing the verify/pattern/path snippets and the ShellCheck
snippet) lack the required blank lines before and after the fences causing MD031
errors; fix by inserting a single blank line immediately before each opening
```yaml (and ```bash) fence and a blank line immediately after each closing ```
fence so the blocks are separated from surrounding text and satisfy markdownlint
rules (affects the blocks containing verify/method/pattern/path and the
ShellCheck run).

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 35be5c0d1822cba1d8c0e317927e3f71b7709e98 and 48fcba65dc8fd11103942163ca14c66100aba552.

📒 Files selected for processing (4)
  • .agents/scripts/model-availability-helper.sh
  • .agents/scripts/observability-helper.sh
  • .agents/scripts/supervisor/dispatch.sh
  • todo/tasks/t1330-brief.md

@marcusquinn
Copy link
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@marcusquinn
Copy link
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Extends observability-helper.sh with rate-limits command that monitors
requests/min and tokens/min per provider from the observability DB (t1307),
compares against configurable rate limits, and warns at 80% threshold.

Changes:
- observability-helper.sh: add cmd_rate_limits(), check_rate_limit_risk(),
  and supporting helpers (_get_rate_limits_config, _get_rate_limit_value,
  _get_warn_pct, _get_window_minutes, _get_configured_providers). Exposes
  'aidevops stats rate-limits' CLI with --json, --provider, --window flags.
- model-availability-helper.sh: add _check_provider_rate_limit_risk() and
  _extract_provider() helpers. Integrate rate limit awareness into resolve_tier()
  so throttle-risk providers are deprioritised in favour of fallback providers.
  Update cmd_rate_limits() to also show observability-derived utilisation.
- dispatch.sh: add rate limit risk check in resolve_model() static fallback
  path — logs a warning when anthropic is at throttle risk.
- .agents/configs/rate-limits.json.txt: configurable rate limit definitions
  per provider (requests/min, tokens/min, billing_type). Copy to
  ~/.config/aidevops/rate-limits.json and adjust for your plan.

Acceptance criteria met:
- Rate limit definitions exist per provider (requests_per_min, tokens_per_min)
- 'aidevops stats rate-limits' shows current utilisation per provider
- When a provider exceeds 80% of its rate limit, model routing prefers alternatives
- Rate limit data derived from existing observability SQLite DB (no new collection)
- Works with both token-billed and subscription providers
- ShellCheck clean (zero errors/warnings)
…guard, stderr visibility

- Fix critical bug: || rl_risk="ok" was overwriting warn/critical status
  from _check_provider_rate_limit_risk (non-zero exit codes triggered ||).
  Now uses || true inside subshell + default pattern.
- Validate window_minutes/effective_window as positive integers before SQL
  interpolation to prevent malformed queries and injection via CLI/config.
- Remove blanket 2>/dev/null suppressions from new rate-limit code across
  model-availability-helper.sh, observability-helper.sh, dispatch.sh.
  The || fallback patterns already handle errors gracefully.
- Replace manual printf JSON construction with jq --arg/--argjson for
  safe escaping of special characters in JSON output.

Addresses: CodeRabbit, Augment, Gemini review comments on PR #2273.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions
Copy link
Contributor

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 71 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Wed Feb 25 15:58:49 UTC 2026: Code review monitoring started
Wed Feb 25 15:58:50 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 71

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 71
  • VULNERABILITIES: 0

Generated on: Wed Feb 25 15:58:52 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@marcusquinn
Copy link
Owner Author

All review comments have been addressed in commits 985f456, 8139e7a, 950f4b7, and 2807eb9:

  1. rl_risk capture bug (CodeRabbit, Augment): Fixed — now uses || true to preserve stdout, with ${rl_risk:-ok} default
  2. Timeout protection (CodeRabbit): Added 5s timeout via gtimeout/timeout with ok fallback
  3. 2>/dev/null removal (Gemini): Removed from all rate-limit code paths across 3 files
  4. window_minutes SQL validation (CodeRabbit, Augment): Added integer regex check with safe default
  5. req_limit/tok_limit validation (CodeRabbit): Added _sanitize_uint() helper, applied at both call sites
  6. cmd_ingest stdout contamination (CodeRabbit): Added >/dev/null redirect for clean JSON
  7. JSON construction (Gemini): Replaced printf with jq --arg/--argjson
  8. MD031 brief formatting (CodeRabbit): Fixed blank lines around fenced blocks

ShellCheck: zero violations on all modified .sh files.

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

@marcusquinn: Excellent comprehensive remediation across all four commits! Your systematic approach to addressing every piece of feedback is impressive:

🔒 Security & correctness hardened:

  • Variable state preservation (rl_risk) prevents logic bypass
  • Timeout protection guards against hanging helpers
  • SQL injection prevention with validated integers
  • Input sanitization via _sanitize_uint() helper
  • Safe JSON construction throughout

🛠️ Observability & quality:

  • Error visibility restored (stderr no longer suppressed)
  • Clean JSON output for programmatic consumers
  • Markdown compliance maintained

Zero technical debt maintained:

  • ShellCheck: 0 violations across all modified shell scripts

I'll conduct a complete re-review of all changes now to verify the implementation of these 8 fixes across the four commits and ensure the rate-limit tracking feature meets all acceptance criteria.

✅ Actions performed

Full review triggered.

@marcusquinn
Copy link
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]
coderabbitai bot previously requested changes Feb 25, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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/observability-helper.sh:
- Around line 1307-1320: The rolling-window SQL comparisons use datetime('now',
...) which produces a space-separated timestamp while recorded_at is stored as
ISO-8601 (with 'T' and 'Z'), causing lexical mis-ordering; update the queries
invoked by db_query (those computing actual_reqs and actual_tokens and any other
recorded_at filters) to use strftime('%Y-%m-%dT%H:%M:%SZ', 'now',
'-${window_minutes} minutes') (or equivalent ISO-formatted cutoff) so the
recorded_at vs cutoff comparison is ISO-compatible; keep using
sql_escape("$provider") and the same WHERE clauses but replace datetime('now',
'-...') with the ISO strftime expression for minute- and day-level windows to
fix over-counting.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 950f4b7 and 2807eb9.

📒 Files selected for processing (2)
  • .agents/scripts/model-availability-helper.sh
  • .agents/scripts/observability-helper.sh

- Move || true outside command substitution for rl_risk capture to
  clarify intent (functionally equivalent but more explicit)
- Redirect both stdout and stderr for cmd_ingest in cmd_rate_limits()
  to prevent any output contaminating --json responses
- Issue 3 (timeout) was already addressed in prior commits
@marcusquinn
Copy link
Owner Author

@coderabbitai review

Fixes applied for the 3 actionable issues from the latest review:

  1. rl_risk capture (model-availability-helper.sh:957): Moved || true outside the command substitution — rl_risk=$(...) || true instead of rl_risk=$(... || true). Both are functionally equivalent (verified: echo output is captured before return triggers the || branch), but the new form is more explicit about intent.

  2. cmd_ingest output contamination (observability-helper.sh:1374): Changed >/dev/null to >/dev/null 2>&1 to suppress both stdout and stderr, preventing any output from contaminating --json responses.

  3. Timeout protection (model-availability-helper.sh:869-886): Already implemented in prior commits with gtimeout/timeout detection and 5-second limit. No additional changes needed.

ShellCheck: zero violations on both files.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

@marcusquinn: Thank you for the detailed breakdown of the three fixes! I can see you've systematically addressed the actionable items:

Error handling clarity (model-availability-helper.sh:957):

  • Moved || true outside command substitution for explicit intent
  • rl_risk=$(...) || true pattern clearly shows fallback behavior

Output contamination prevention (observability-helper.sh:1374):

  • Enhanced suppression to >/dev/null 2>&1
  • Ensures clean JSON output by silencing both stdout and stderr

Timeout protection (model-availability-helper.sh:869-886):

  • Already implemented with gtimeout/timeout detection and 5s limit
  • No additional changes needed

Zero technical debt maintained — ShellCheck clean on both modified files.

I'll review the implementation now to verify these fixes are correctly applied.

Note: The multiple flagged comments in this PR indicate that task t1330 was cancelled in the supervisor DB. This administrative issue will need human resolution (close PR or reconcile task state) before merge.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

…exical ordering

datetime('now', ...) produces 'YYYY-MM-DD HH:MM:SS' (space-separated) while
recorded_at stores ISO-8601 'YYYY-MM-DDThh:mm:ssZ' (with T and Z). The 'T'
character sorts after space, causing lexical comparisons to over-count rows
in rolling windows (e.g., 00:01 records included in a 1-minute window at 23:59).

Replace all datetime('now', ...) with strftime('%Y-%m-%dT%H:%M:%SZ', 'now', ...)
to match the schema's INSERT format, fixing rate-limit risk detection and all
stats/summary/trend/prune queries.

Addresses: coderabbit review on PR #2273 (timestamp format mismatch)
@github-actions
Copy link
Contributor

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 90 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Wed Feb 25 16:39:10 UTC 2026: Code review monitoring started
Wed Feb 25 16:39:11 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 90

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 90
  • VULNERABILITIES: 0

Generated on: Wed Feb 25 16:39:14 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link

@marcusquinn marcusquinn dismissed stale reviews from coderabbitai[bot], coderabbitai[bot], coderabbitai[bot], and coderabbitai[bot] February 25, 2026 17:11

All issues addressed in subsequent commits. Verified by independent code review.

@marcusquinn marcusquinn merged commit 2e99667 into main Feb 25, 2026
10 of 11 checks passed
marcusquinn added a commit that referenced this pull request Feb 26, 2026
…N-quoted pipe-delimited output

jq -s without -r wraps output in JSON quotes ("0|0" instead of 0|0),
breaking downstream awk percentage calculations in rate-limit tracking.

Rebased on main after t1337.5 refactor — original t1330 commits already
merged via PR #2273; this commit contains only the jq quoting bugfix.
marcusquinn added a commit that referenced this pull request Feb 26, 2026
…N-quoted pipe-delimited output (#2389)

jq -s without -r wraps output in JSON quotes ("0|0" instead of 0|0),
breaking downstream awk percentage calculations in rate-limit tracking.

Rebased on main after t1337.5 refactor — original t1330 commits already
merged via PR #2273; this commit contains only the jq quoting bugfix.

Co-authored-by: marcusquinn <6428977+marcusquinn@users.noreply.github.com>
@marcusquinn
Copy link
Owner Author

Resolves #2263.

marcusquinn added a commit that referenced this pull request Mar 14, 2026
The MD031 fenced-block spacing violations in todo/tasks/t1330-brief.md were
fixed in PR #2273 (commits 21e4b9e..2807eb9). markdownlint now reports 0
errors. This commit marks the acceptance criteria checkboxes as complete to
reflect t1330's verified delivery (pr:#2389 completed:2026-02-26).

Closes #3416
marcusquinn added a commit that referenced this pull request Mar 14, 2026
…ean (#4784)

The MD031 fenced-block spacing violations in todo/tasks/t1330-brief.md were
fixed in PR #2273 (commits 21e4b9e..2807eb9). markdownlint now reports 0
errors. This commit marks the acceptance criteria checkboxes as complete to
reflect t1330's verified delivery (pr:#2389 completed:2026-02-26).

Closes #3416
superdav42 added a commit to superdav42/aidevops that referenced this pull request Mar 16, 2026
* fix(t3578): address PR #311 review notes in GLM-OCR docs (#4716)

* fix(t3588): align google analytics MCP tool filter naming (#4714)

* fix: add dspyground install command to docs note (#4713)

* fix(t3571): use portable ERE task-id boundaries in PR matching (#4723)

* fix(t3576): sort LAZY_MCPS entries for maintainability (#4722)

* fix(t3575): clarify gh_grep on-demand guidance (#4721)

* fix(t3170): separate local declaration from assignment in get_shell_rc (#4711)

Addresses Gemini cross-PR review feedback (PR #1253): local var="$1"
combined form masks exit codes; use separate declare+assign per styleguide.

Closes #3170

* fix: replace repeated grep-per-field with single-pass while/case in email-signature-parser-helper.sh (#4724)

Address 3 Gemini review findings from PR #3055:
- merge_toon_contact: replace 6 grep calls with one while/case pass over $existing (HIGH)
- resolve_contact_filename: replace 2 grep calls with one while/case pass over file (MEDIUM)
- list_contacts: replace 2 grep calls per file with one while/case pass per file (MEDIUM)

All three sites now parse fields in a single read loop, eliminating redundant
subshell forks and grep invocations. ShellCheck: zero new violations.

Closes #3161

* fix(t3591): externalize worker efficiency dispatch prompt (#4725)

* fix: refactor build_curl_args to accept protocol param, add SSL warning (#4726)

- Pass pre-computed protocol to build_curl_args() in both cron-dispatch.sh
  and cron-helper.sh, eliminating the redundant get_protocol() subshell call
  inside the function when callers already have the value
- Add log_warn when OPENCODE_INSECURE=1 in cron-helper.sh to match the
  existing warning in cron-dispatch.sh (operator visibility parity)
- Use log_warn (stderr) instead of log_info (stdout) for the SSL warning in
  cron-dispatch.sh for correct severity routing

Addresses gemini review feedback from PR #305.
Closes #3529

* docs(remote-dispatch): address PR #2109 review feedback (#4728)

- Clarify credential transport: keys embedded as export lines in uploaded
  shell script, not via AcceptEnv/SendEnv (which cannot silently fail)
- Add /proc/<pid>/environ exposure note for security-conscious deployments
- Add mitigation guidance: restrict host access or use short-lived tokens
- Add opencode-ai as preferred npm install option; keep @anthropic-ai/claude-code
  as the claude CLI alternative

Closes #3445

* fix(supervisor): guard cooldown file write against unset SUPERVISOR_STATE_DIR and move timestamp after success (#4729)

- Use ${SUPERVISOR_STATE_DIR:-/var/lib/supervisor} instead of SUPERVISOR_DIR for
  task_creation_cooldown_file to guard against unset variable under set -u/-e
- Add mkdir -p before writing the cooldown timestamp to ensure directory exists
- Move date +%s write to AFTER confirming TODO.md exists and task creation runs,
  preventing the cooldown from throttling retries when prerequisites are missing

Addresses PR #1170 review feedback (issue #3526).

* fix(t3528): address PR #317 review feedback (#4730)

- Move NODE_PATH snippet from build-agent.md into node-helpers.md and
  replace with a file:line reference (CodeRabbit feedback)
- Add FTS5 capability probe to sqlite3 status check in onboarding-helper.sh
  so partial installs (sqlite3 present, FTS5 missing) are correctly reported
  as 'partial' rather than 'ready' (CodeRabbit + Gemini feedback)
- Add fts5 field to JSON output using jq for type-safe boolean construction

Closes #3528

* fix(supervisor): redirect jq stderr to SUPERVISOR_LOG in dismiss_bot_reviews (#4731)

Replace 2>/dev/null with 2>>"${SUPERVISOR_LOG:-/dev/null}" on three jq
commands in the dismiss_bot_reviews function and check_pr_status function.

This aligns with the repository style guide (no blanket stderr suppression)
and allows jq parsing errors from malformed gh api responses to be captured
in the supervisor log for debugging, rather than silently discarded.

Closes #3564
Addresses gemini-code-assist review feedback on PR #952

* fix(t3566): deduplicate ai bot review verification guidance (#4732)

* fix: align merge-conflict error token with retry filter in deploy.sh (#4734)

Change the error string written on auto-rebase failure from the human-readable
'Merge conflict — auto-rebase failed' to the machine-readable token
'merge_conflict:auto_rebase_failed'. This aligns with the case-match in
evaluate.sh:718 and dispatch.sh:673 which filter on 'merge_conflict' — without
this fix, tasks blocked by auto-rebase failure were not picked up for retry.

Fix 2 (git add before diff --check) was already present in deploy.sh at line
2248 from a prior refactor — no change needed there.

Closes #3524

* chore(version-manager): extract badge patterns into local variables (#4735)

Addresses Gemini code review suggestion from PR #134: store the
dynamic and hardcoded badge grep patterns in local variables to
improve maintainability and avoid repeating the pattern strings.

Closes #3522

* fix(linters): handle markdownlint execution errors separately from rule violations (#4737)

When markdownlint fails due to bad config, invalid arguments, or other
non-rule errors, the output won't match the MD[0-9] pattern, causing
violation_count=0 and a false success return—even in blocking mode.

Capture lint_exit separately (|| lint_exit=$?) and treat non-zero exit
codes as blocking errors in changed-file mode and advisory warnings in
full-scan mode. Covers both cases: output present (non-rule error message)
and no output (silent config parse failure).

Closes #3505
Addresses CodeRabbit review on PR #271

* refactor(dispatch): consolidate pro tier into sonnet case statement (#4736)

Merge the redundant `pro` case into `sonnet | eval | health | pro` since
both resolve to the same model (anthropic/claude-sonnet-4-6). Reduces
duplication and improves maintainability as suggested in PR #799 review.

Closes #3519

* fix(t3521): harden version validator script invocation and JSON parsing (#4738)

* fix(t3510): harden grep count handling in setup modules (#4739)

* docs(#3492): restore sentry setup context and token access note (#4740)

* chore(t3517): convert status label lists to bash arrays (#4741)

Replace comma-separated string iteration with bash arrays in:
- supervisor-archived/issue-sync.sh: ALL_STATUS_LABELS constant + sync_issue_status_label() loop
- issue-sync-helper.sh: _DONE_REMOVE_LABELS constant + _mark_issue_done()

Eliminates IFS manipulation and here-string splitting for safer, more
idiomatic bash iteration. Addresses Gemini review feedback on PR #1375.

ShellCheck: zero new violations.

* fix(t3504): clarify 4-hour max runtime comment (#4743)

* fix(t3490): improve terminal capability guidance readability (#4744)

* fix(markdown): normalize remember command example spacing (#4745)

* fix: consolidate duplicate pro tier mapping (#4746)

* fix(t3496): escape task ID regex in completion filters (#4747)

* fix(auto-update): detect script drift when VERSION matches to prevent stale pulse (#4749)

When a script fix is merged without a version bump, the deployed copy in
~/.aidevops/ stays stale until setup.sh is run manually. The auto-update
stale check only compared VERSION files, missing intra-version script changes.

Add a sentinel-based script drift check: compare SHA-256 of
gh-failure-miner-helper.sh between repo and deployed. If they differ,
re-deploy all agents via setup.sh --non-interactive.

Root cause of GH#4727: PR #4704 fixed gh-failure-miner-helper.sh (merged
07:43) but the pulse ran at 08:40 using the old deployed version, which
still treated Codacy ACTION_REQUIRED as a CI failure and produced a false
systemic cluster, causing the pulse LLM to create a duplicate issue.

Closes #4727

* feat: add --include-positive flag to scan-merged for debugging positive-review filters (#4748)

Closes #4733

Adds --include-positive to quality-feedback-helper.sh scan-merged to bypass
the positive-review suppression filters (summary-only, approval-only,
no-actionable-sentiment). Intended for use with --dry-run to audit which
reviews are being suppressed and verify the filters are working correctly.

Changes:
- cmd_scan_merged: parse --include-positive flag, pass to _scan_single_pr
- _scan_single_pr: accept include_positive arg; bypass summary_only filter
  and approval/sentiment select() when true; use select() pattern instead
  of pipe-through-boolean to avoid jq object-construction errors
- Help text: document --include-positive with usage example
- Tests: 5 new tests covering flag unit behaviour and _scan_single_pr
  integration (27/27 passing, 0 shellcheck violations)

* fix: address PR #254 review feedback on worktree cleanup and divergence handling (#4750)

- Extract worktree cleanup bash block from full-loop.md into new
  worktree-cleanup.md subagent doc; replace inline snippet with
  progressive-disclosure pointer (CodeRabbit finding)
- Replace destructive git reset --hard suggestion in version-manager.sh
  diverged-branch path with safer guidance: inspect divergence first,
  then choose reset (squash-merged) or rebase (unmerged commits)
  (CodeRabbit finding)

Closes #3518

* fix(t3455): add Windows and Linux Claude Desktop config paths to mcp-integrations.md (#4751)

The Claude Desktop config path was macOS-only. Added cross-platform paths
for all three OS in both the OpenAPI Search MCP and Cloudflare Code Mode MCP
sections, addressing Gemini review feedback from PR #2077.

Closes #3455

* fix: standardize Claude Code terminology in mcp-integrations.md (#4752)

Remove 'CLI' suffix from 'Claude Code CLI' comment in mcp-integrations.md
to match the consistent 'Claude Code' naming used throughout the project.

Addresses Gemini review feedback from PR #217.
Closes #3485

* fix(clawdhub-helper): remove 2>/dev/null suppressions to improve debuggability (#4754)

Addresses Gemini code review feedback from PR #288. Three stderr suppressions
were hiding error output from npm install, npx playwright install, node fetch.mjs,
and npx clawdhub install, making it impossible to diagnose failures in the
Playwright/CLI skill-fetch fallback chain.

The find 2>/dev/null on line 293 is intentionally retained — it suppresses
permission-denied noise from filesystem traversal, not operational errors.

Closes #3474

* fix(t3480): mark Twilio governance template fields as informational (#4756)

* docs: clarify runtime identity guidance (#4757)

* fix: address Gemini style violations from PR #1401 review (t3487) (#4758)

Three style guide violations flagged by Gemini on PR #1401 but not
addressed before the supervisor was archived in PR #2291:

1. Replace 2>/dev/null with 2>>"$SUPERVISOR_LOG" on db() call (line 576)
   — blanket error suppression hides db failures; log them instead
2. Split local repo_slug="$1" / local pr_number="$2" in check_review_threads()
   — separate declaration from assignment for set -e safety (Rule #11)
3. Split local repo_slug="$1" / local pr_number="$2" in resolve_bot_review_threads()
   — same Rule #11 fix
4. Replace 2>/dev/null with 2>>"$SUPERVISOR_LOG" on jq call (line 1061)
   — log jq parse errors for diagnostics (Rule #50)

ShellCheck: zero violations. File is archived but kept consistent with
the style guide for reference integrity.

Closes #3487

* fix(t3484): address PR #187 MCP review feedback (#4761)

* fix(t3472): align agent tool map line wrapping (#4760)

* fix: explicit return propagation and remove jq stderr suppression in muapi-helper.sh (#4759)

Address PR #2013 review feedback (issue #3372):
- Add explicit 'return $?' to submit_specialized() and all cmd_* functions
  that call submit_specialized, so exit codes propagate to callers
- Remove '2>/dev/null' from jq calls in cmd_balance() and cmd_usage()
  so jq parse errors are visible for debugging

* fix(#3475): reduce repeated option variable declarations in SEO export parsers (#4762)

* fix: address PR #327 review feedback on blank line and phrasing clarity (#4763)

- Replace print_info "" with echo for blank line in setup-mcp-integrations.sh
  (print_info adds [INFO] prefix, making blank lines non-blank in output)
- Clarify @github-search note in github-search.md to avoid implying it
  replaces grep_app when Oh-My-OpenCode is installed; now explicit it is
  the built-in aidevops alternative

Closes #3463

* fix: improve add-skill-helper.sh comment clarity and tighten diagram pattern (#4764)

- Add ordering notes to database, diagrams, and programming language
  category comments (Gemini PR #297 review suggestions)
- Remove overly broad 'diagram' token from diagrams grep pattern; retain
  specific alternatives (mermaid, flowchart, sequence.diagram, er.diagram,
  uml) to avoid false-positive matches in architecture docs (Augment)
- Update add-skill.md Category Detection table to include all new
  categories added in PR #297 (architecture, database, diagrams,
  programming) so maintainer docs stay in sync with the script (Augment)

Closes #3461

* fix: guard empty eval arrays and unset _emit_token in dispatch.sh (#4766)

Address CodeRabbit review feedback from PR #2053 (t3459):

1. check_cli_health: guard against empty version_cmd after eval — if
   build_cli_cmd returns non-zero or produces no tokens, log an error
   and return 1 instead of executing an empty command.

2. check_model_health: same guard for probe_cmd — prevents silent
   empty exec when build_cli_cmd fails for probe action.

3. build_cli_cmd: unset -f _emit_token before returning — the nested
   helper leaked into the global function namespace after first call;
   cleanup prevents unexpected collisions with future callers.

shellcheck -x -S warning: zero violations
bash -n: syntax OK

Closes #3459

* fix: add cross-platform Claude Desktop paths and clarify --transport http flag in cloudflare-mcp.md (#4765)

Addresses PR #2077 review feedback (issue #3456):
- Add Windows (%APPDATA%) and Linux (~/.config/Claude) config paths alongside macOS
- Add note explaining --transport http is the MCP transport type name, not the URL
  scheme; http is correct even for HTTPS endpoints (selects protocol framing, not TLS)

Closes #3456

* fix: remove stale 'API references' phrase and fix broken path refs in cloudflare-platform.md (#4767)

- Line 11: remove 'and API references' from Role declaration — api.md files
  are superseded by Code Mode MCP; phrase implied they still exist
- Lines 13, 21, 57: fix 3 broken path refs tools/api/cloudflare-mcp.md →
  ../../tools/api/cloudflare-mcp.md (correct relative path from services/hosting/)

Closes #3454

* fix: remove openai/gpt-4o from DEFAULT_HEADLESS_MODELS — only anthropic configured (#4768)

openai provider is not configured in opencode.json, causing ProviderModelNotFoundError
on every other worker dispatch. DEFAULT_HEADLESS_MODELS now uses only the configured
anthropic/claude-sonnet-4-6 model.

Closes #4755

* fix(t3441): address Gemini review feedback from PR #2143 (#4769)

- Separate local self_pid declaration from assignment (local self_pid; self_pid=$$)
  to follow the repo style guide (declare and assign separately for exit code safety)
- Remove 2>/dev/null from while condition ([[ "$self_pid" -gt 1 ]]) — blanket
  suppression on control structures masks syntax errors and is unnecessary
- Remove 2>/dev/null from cat pid_file — file existence already checked by [[ -f ]]
  guard on the preceding line; suppression is redundant and hides permission errors
- Remove 2>/dev/null from pgrep — pgrep returns exit 1 on no match (already guarded
  by || true); suppression masks real errors like missing binary or invalid args

Closes #3441

* fix: address Gemini review feedback from PR #2120 (t3442) (#4770)

- Separate local declaration from assignment for ai_pid_file (exit code safety)
- Remove blanket 2>/dev/null suppression on ai_pid_file write and rm — use || true
  so filesystem errors (permission denied, missing dir) remain visible in logs
- Remove 2>/dev/null from _list_descendants call — errors should surface for diagnosis
- Normalize newline-delimited PID output from _list_descendants to space-delimited
  protected_pids via while/read loop, fixing grep -q match reliability

Closes #3442

* fix(t3471): use generic placeholders in file discovery table (#4772)

Replace '*.md'/-e md examples with '<pattern>'/<ext>/<dir> placeholders
in context-guardrails.md so AI agents understand the commands apply to
any file type, not just Markdown files.

Addresses Gemini review feedback from PR #125.
Closes #3471

* fix(t3462): tighten task ID extraction matching and simplify parsing loop (#4773)

* fix(t3419): address PR #156 review feedback in video-prompt-design (#4774)

- Fix typo: 'thats' → 'that's' in camera positioning instruction (line 43)
- Fix typo: 'thats' → 'that's' in camera positioning example (line 95)
- Align dialogue format in quick-reference with detailed example:
  '(Character Name): "Speech" (Tone: descriptor)' — colon syntax prevents
  subtitle generation (Gemini suggestion for clarity/consistency)

* fix: address PR #2219 review feedback in ai-deploy-decisions.sh (#4775)

- Fix severity merge to use id-based lookup instead of positional index
  (prevents misassignment when AI reorders/omits threads)
- Add hard gate: PR must be MERGED before AI can set verified=true
  (prevents non-merged PRs from being marked as verified)
- Include thread id in AI prompt so AI can echo it back for stable mapping

Closes #3431

* fix: address PR #2156 quality-debt review feedback (t3440) (#4776)

- Remove 2>/dev/null from blocked/retrying/verify_failed task-detail DB
  queries so errors (DB locked, SQL syntax) surface instead of being
  silently swallowed; || echo "" fallback preserved for set -e safety
- Extract _format_task_alert_list() helper to eliminate duplicated
  blocked/verify_failed alert formatting logic (DRY refactor)
- ShellCheck: zero violations

* fix(t3420): address PR #219 review feedback (#4777)

- get_git_context: capture toplevel before basename to prevent '.' output
  when not inside a git repo (CodeRabbit)
- generate-opencode-agents: update UPDATE_AVAILABLE example from 3-field
  to 4-field format matching actual output (CodeRabbit)
- detect_app fallback: normalize parent process name to lowercase before
  case matching to handle capitalized names on some platforms (Augment)
- detect_app fallback: add windsurf and continue process name patterns
  to match env-var detection coverage (Gemini)

Closes #3420

* fix(t3416): mark t1330 acceptance criteria complete, confirm MD031 clean (#4784)

The MD031 fenced-block spacing violations in todo/tasks/t1330-brief.md were
fixed in PR #2273 (commits 21e4b9e..2807eb9). markdownlint now reports 0
errors. This commit marks the acceptance criteria checkboxes as complete to
reflect t1330's verified delivery (pr:#2389 completed:2026-02-26).

Closes #3416

* fix: make cloudflare-platform.md references clickable links (#4778)

Addresses review feedback from PR #147 (gemini-code-assist, augmentcode):
inline code formatting on cross-references is not clickable in GitHub
render. Convert all three Markdown-renderable references to link syntax.

Closes #3405

* fix(t3388): correct t1332-brief.md inaccuracies from PR #2274 review (#4790)

- Phase 4 → Phase 0.75 (actual phase where stuck detection runs in pulse.sh)
- suggestions: [string] → suggested_actions: string (single string, not array)
- ai-reason.sh → dispatch.sh (stuck-detection.sh depends on dispatch.sh for
  resolve_ai_cli and resolve_model, not ai-reason.sh)
- Update Estimate Breakdown table to match corrected phase reference

Closes #3388

* fix(t3391): address PR #2284 review feedback on circuit breaker (#4792)

- Serialize manual 'trip' path with _cb_with_state_lock via new
  _cb_trip_impl() to prevent interleaving with concurrent pulse writes
- Count ENVIRONMENT failures in circuit-breaker accounting so repeated
  infra failures can trip the breaker (prefixed 'environment:' for
  downstream reporting distinction)

All other review findings (numeric validation, lock wrapper, repo-scoping,
jq hardening, tripped_at parse safety, cb_record_success on early-success
path, jq empty-string fallbacks, elapsed helper deduplication) were
already addressed in prior commits on this branch.

Closes #3391

* fix: t3381 address PR #2201 review feedback on t1305 opencode streaming hooks doc (#4791)

- Add date (2026-02-22) for PR #14727 in timeline for consistency
- Add reasoning-delta case to processor.ts code sketch for completeness
- Backtick processor.ts, Bun.file(), Filesystem in architecture section
- Use 109k+ star count consistently with Target Repository section

Closes #3381

* fix: add missing GET /payments/credits and /payments/usage endpoints to muapi.md (#4789)

Addresses quality-debt review feedback from PR #2013 (gemini-code-assist).
The Payments & Credits section was missing the balance and usage check endpoints
that are implemented in muapi-helper.sh. Also corrects the checkout session
endpoint method (GET→POST) and adds the /api/v1/ version prefix for consistency
with the rest of the document.

Closes #3373

* fix(t3403): make setup-aidevops repo path resolution dynamic (#4787)

* fix(t3410): centralize supervisor terminal status SQL fragments (#4785)

* fix(t3415): harden blocked task DB registration (#4782)

* fix(t3407): return non-zero from cloudron log_error (#4781)

* fix(t3412): remove 2>/dev/null suppression from gh/jq calls in supervisor scripts (#4780)

Addresses gemini review feedback on PR #2114. The 2>/dev/null redirections
on parse_pr_url(), gh pr view, and detect_repo_slug() calls were hiding
authentication failures, network errors, and jq parse errors. The || fallback
constructs already handle failure safely under set -e; stderr is now routed
to SUPERVISOR_LOG for diagnostics.

Closes #3412

* fix(t3409): apply PR #184 review feedback from gemini (#4779)

- AGENTS.md: clarify runtime identity to include MCP persona guidance
  without the restrictive '(backup tools)' phrasing that could cause
  agents to avoid using MCP tools unless a primary tool fails
- architecture.md: sort tier 2 MCP tool list alphabetically for
  readability and to prevent duplicate additions

Closes #3409

* fix(t3401): replace hardcoded ~/.aidevops/ paths with ${AIDEVOPS_DIR:-$HOME/.aidevops}/ in generate-opencode-commands.sh (#4783)

Addresses Gemini code review feedback from PR #95: hardcoded ~/.aidevops/
paths make it difficult to customise the install location. Replaces all 43
occurrences (tilde and $HOME variants) with the ${AIDEVOPS_DIR:-$HOME/.aidevops}
pattern, consistent with the convention already used in git-workflow.md and
deploy.sh.

Closes #3401

* fix(t3397): ignore no-suggestion review summaries in debt scan (#4786)

* fix(t3427): preserve AI stderr context in staleness checks (#4793)

* fix(t3428): keep timeout classifier stderr and clarify AI prompt (#4794)

Route stderr from timeout-classification AI calls into SUPERVISOR_LOG so failures remain diagnosable instead of being silently dropped.

Also remove contradictory prompt instructions by requiring a single JSON-only response format for category output.

Closes #3428

* fix(t3393): fix mentions type to Record<string, number> and add BigInt/Int64 JSON string note (#4795)

- Replace {string: int64} with Record<string, number> for mentions field (correct TypeScript index map syntax)
- Replace int64 with number for quotedItemId (TypeScript/JSON representation)
- Add type note explaining Int64→number mapping and recommending JSON string encoding for large IDs to avoid precision loss with BigInt(value) on already-rounded JSON numbers

Addresses CodeRabbit CHANGES_REQUESTED on PR #4788.

* fix: deduplicate React.memo bullet and clarify useDeferredValue in expo.md performance section (#4796)

Resolves redundancy introduced by PR #2011 review feedback application.
Line 181 covers React.memo for list items; line 182 now distinctly covers
useDeferredValue for heavy components, removing the duplicate React.memo reference.

Closes #3369

* fix(t3421): add uv tool subcommand check to setup prerequisites (#4797)

Addresses Gemini review feedback from PR #186: checking only
'command -v uv' is insufficient when 'uv tool' subcommand is the
actual invocation, since older uv versions lack the 'tool' subcommand
and would pass the guard but fail at runtime.

- setup-modules/mcp-setup.sh: guard outscraper-mcp-server install with
  'uv tool --help' check; add descriptive warning + update hint when uv
  is present but too old
- setup-modules/plugins.sh: guard cisco-ai-skill-scanner uv-path with
  same 'uv tool --help' check (fallback chain to pipx/venv/pip3 still
  applies when uv tool is unavailable)

Closes #3421

* fix(t3367): fail check on stale TOON subagent counts (#4798)

* fix(issue3359): replace brittle sleep dispatch checks with PID tracking guidance (#4799)

* fix(t3365): add regression coverage for non-actionable Gemini summary reviews (#4806)

* fix(t3362): dedupe pulse timestamp parsing via helper (#4805)

* fix(t3368): clean phase1 eval checkpoint on signal (#4804)

* fix(issue3363): add regression test for non-actionable Gemini review (#4803)

* fix(t3433): reduce jq churn and surface adopt-untracked errors (#4802)

* fix(t3366): remove blanket tail stderr suppression in stale diagnosis (#4800)

* fix(t3424): preserve supervisor health issue lookup reliability (#4801)

Remove stderr suppression from supervisor health issue gh/jq calls so auth and API failures remain debuggable, and ensure supervisor labels are backfilled/created consistently to keep label-based lookup effective after title edits.

* fix: improve DOM style extraction to use representative set with deduplication (#4807)

Addresses medium quality-debt review feedback from PR #2693 (GH#3350).
Replaces fixed tag-list querySelectorAll approach with a representative-set
traversal + style grouping strategy, which is more efficient on large pages
and captures styled elements beyond the original fixed tag list (e.g. div cards).

Closes #3350

* fix: correct imported_at timestamps for Cloudron skills to actual merge time (#4808)

PR #2651 merged at 2026-03-01T16:19:15Z. The three Cloudron skill entries
(cloudron-app-packaging, cloudron-app-publishing, cloudron-server-ops) had
placeholder timestamps of 18:00:00Z instead of the actual import time.

Addresses quality-debt review feedback from gemini on PR #2651 (issue #3351).

Closes #3351

* fix: bump Google model tiers to Gemini 3 in MODEL_TIERS (#4809)

Update flash/pro tier mappings from gemini-2.5 to gemini-3-preview models,
addressing CodeRabbit review feedback on PR #2126. Both models are confirmed
present in OpenCode's Google provider config and available via OpenRouter.

Closes #3341

* fix(t3353): replace python3 JSON parsing with jq in clawdhub/add-skill helpers (#4810)

Address medium quality-debt review feedback from PR #183 (Gemini):
- clawdhub-helper.sh: replace python3 JSON validation with jq -e in fetch_skill_info
- clawdhub-helper.sh: surface HTTP/network errors with curl -fsS instead of -s
- clawdhub-helper.sh: replace python3 owner extraction with jq in fetch_skill_content_playwright
- clawdhub-helper.sh: add EXIT trap for guaranteed temp dir cleanup
- clawdhub-helper.sh: surface npm/playwright install errors (redirect stderr to stdout)
- clawdhub-helper.sh: replace python3 info display with jq in cmd_info
- clawdhub-helper.sh: replace python3 search output with jq in cmd_search
- clawdhub-helper.sh: pass query as argv to python3 in URL encoding (injection-safe)
- add-skill-helper.sh: replace python3 metadata extraction with jq in cmd_add_clawdhub
- add-skill-helper.sh: skip ClawdHub URLs in cmd_check_updates with informational log

Closes #3353

* fix: address PR #2173 review feedback in resolve_ai_cli() (#4811)

- Correct npm package name from 'opencode' to 'opencode-ai' in install instructions
- Use proper name 'OpenCode' (capitalised) in log messages
- Rename unused `resolved_model` to `_resolved_model` to signal intentional non-use

Closes #3332

* fix: correct imported_at timestamps for Cloudron skills to actual merge time (#4812)

PR #2651 merged at 2026-03-01T16:19:15Z. The three Cloudron skill entries
(cloudron-app-packaging, cloudron-app-publishing, cloudron-server-ops) had
placeholder timestamps of 18:00:00Z instead of the actual import time.

Addresses quality-debt review feedback from gemini on PR #2651 (issue #3351).

Closes #3351

* fix: bump Google model tiers to Gemini 3 in MODEL_TIERS (#4813)

Update flash/pro tier mappings from gemini-2.5 to gemini-3-preview models,
addressing CodeRabbit review feedback on PR #2126. Both models are confirmed
present in OpenCode's Google provider config and available via OpenRouter.

Closes #3341

* fix: add blank lines around fenced code blocks in t1349-brief.md (MD031) (#4815)

Resolves MD031 (blanks-around-fences) violations flagged by CodeRabbit in PR #2462.
All 8 fenced code blocks in the Acceptance Criteria section now have blank lines
before and after, satisfying the 'Lint clean' acceptance criterion in the brief itself.

Closes #3315

* fix(t3329): use here-string with || true for eligible task count in ai-lifecycle.sh (#4816)

Fixes buggy line-counting logic flagged in PR #2113 review (Gemini).
The previous pattern `printf '%s\n' "$eligible_tasks" | grep -c '.' || echo "0"`
produces a multi-line value ("0\n0") when eligible_tasks is empty, because
grep -c exits 1 on no match and the || echo "0" appends a second zero.

Replace with `grep -c . <<< "$eligible_tasks" || true` which correctly
returns a single "0" on empty input and aligns with the repo style guide
requirement to use || true (not || echo) under set -e.

Closes #3329

* fix: clarify enhancement rollout priority in t1311 research (#4818)

* fix(t3311): regenerate pattern-3 skills after clean (#4819)

* fix(t3326): add regression test for non-actionable Gemini summary (#4820)

* fix(t3342): filter 'no suggestions for improvement' review summaries (#4822)

* fix(issue3313): restore portable proof-log and dedup regressions (#4826)

Replace removed local integration scripts with in-repo regression coverage, and harden contact filename resolution so same-name contacts with different emails are handled predictably.

* fix(issue3350): refine representative style extraction guidance (#4823)

* fix(t3353): surface ClawdHub API fetch and JSON errors (#4817)

* fix(issue3303): add regression test for non-actionable Gemini review (#4825)

* fix(t3325): add regression test for non-actionable gemini review (#4824)

* fix: use <PLACEHOLDER> style values in matterbridge config examples (#4830)

Addresses CodeRabbit review feedback on PR #2255 (issue #3309):
- Add explicit acceptance criterion to t1328-brief.md requiring all config
  examples use <PLACEHOLDER> style values for tokens/credentials, with a
  note referencing tools/credentials/ agents for secure storage
- Replace all bare credential values in matterbridge.md with <PLACEHOLDER>
  tokens (MATRIX_PASSWORD, DISCORD_BOT_TOKEN, TELEGRAM_BOT_TOKEN, etc.)
  and add aidevops secret set guidance inline
- Update matterbridge-helper.sh config template to use <PLACEHOLDER> values
  and add a header comment directing users to tools/credentials/ agents

Closes #3309

* refactor: deduplicate scheduler detection in setup.sh (#4828)

* fix(t3488): parameterize review fix-cycle count query (#4827)

Address Gemini medium review feedback from PR #1388 by replacing task_id SQL interpolation with db_param binding in supervisor deploy triage logic.

Closes #3488

* fix(t3422): remove 2>/dev/null suppression from resolve_model calls (#4829)

Addresses Gemini review feedback on PR #2256. The 2>/dev/null redirections
on resolve_model() calls in ai-actions.sh, batch.sh, and dispatch.sh were
hiding syntax errors in helper scripts and configuration issues. The ||
fallback constructs already handle failure safely; stderr is now visible
for diagnostics.

- ai-actions.sh: resolve_model in _exec_escalate_model()
- batch.sh: resolve_model in cmd_add() tier resolution
- dispatch.sh: resolve_model in verify-mode dispatch branch

Closes #3422

* t3307: clarify PR triage merge step with explicit two-step issue close (#4831)

* fix: clarify PR triage merge step with explicit two-step issue close

Address gemini-code-assist review feedback from PR #2474. The 'Green CI +
all gates passed' bullet was ambiguous — 'closed with a comment' could be
read as a single gh issue close --comment action. Rephrase to match the
document's established convention: comment first to link the merged PR,
then close as two separate steps. Also aligns placeholder style with the
rest of the document (<number>/<slug> vs NUMBER/SLUG).

Closes #3307

* docs: clarify two-step comment-then-close in PR triage audit trail

Make the order of operations explicit in the PR triage bullet: comment
on the issue first (linking the merged PR), then close it. Previously
the sentence implied a single action; now it shows the two separate gh
commands, consistent with the rest of the document's style.

Addresses Gemini review feedback on PR #2474. Closes #3307.

* fix(t3296): add memory-helper.sh references to README domain index entries (#4832)

Address PR #2650 review feedback (gemini findings):
- README.md:505 Pattern Tracking row: replace 'memory system' with 'memory-helper.sh'
- README.md:759 Review row: replace '(memory system)' with '(memory-helper.sh)'

Closes #3296

* fix: parameterize review-triage fix-cycle queries (#4833)

* fix: include .sh files in AI framework audit glob (#4834)

* fix(t3295): remove Docling from PDF OCR overview link (#4835)

* fix: clarify milestone validation blocking vs diagnostics behavior (#4836)

* docs: clarify persistent-label CI guard behavior (#4837)

Clarify that pulse must not use close-keyword references on persistent issues and document the guard-persistent-issues safety-net behavior to prevent accidental closure loops.

* fix: correct XMTP npm module init instructions (#4838)

* fix(issue3282): use fake timers in approval timeout test (#4841)

* fix(t3281): harden health dashboard task issue linking (#4842)

* test: add regression for issue #3323 positive Gemini review filtering (#4821)

* fix: address PR #2475 review feedback in runners-check.md (#4843)

- Replace `cat ... 2>/dev/null` with `test -r` readability check to surface
  file permission errors instead of silently falling back to default value
- Remove `2>/dev/null` from launchctl/crontab calls so system errors
  (command not found, permission issues) are visible for debugging

Closes #3298

* fix(GH#4814): add regression tests for positive-only review filter (#4840)

Adds two regression tests to prevent re-filing quality-debt issues
for purely positive bot reviews:

1. Exact incident body from GH#4814 (PR #2166 Gemini review):
   'The changes are well-implemented and improve the script's
   robustness and quality.' — COMMENTED state, 0 inline comments,
   bot reviewer. Must produce 0 findings (filtered by $summary_only).

2. Positive review body with actionable inline comments present:
   When a bot posts a positive review body but also has inline
   comments with actionable content, the review body is filtered
   but the inline comment is kept. Verifies $summary_only does
   not suppress inline findings.

The filtering logic was already correct (added in prior commits);
these tests lock in the behaviour and prevent regression.

Closes #4814

* fix: add env overrides for simplex bot runtime config (#4850)

* fix: add explicit bun-types to simplex bot tsconfig (#4849)

* fix: address onboarding-helper review feedback from PR #2729 (#4848)

* fix: avoid reconstructing session ID in executeCommand (GH#3266) (#4847)

The sessionId was being reconstructed in command-executor.ts using
hardcoded 'direct:<id>' / 'group:<id>' string patterns, duplicating
the format defined in session.ts. If the format ever changed, this
code would break silently.

Fix: trackSession() now returns the session ID directly from
SessionStore. The ID is threaded through processItem → routeCommand →
buildCommandContext and stored in CommandContext.sessionId.
executeCommand uses ctx.sessionId instead of reconstructing it.

Addresses PR #2375 review feedback (gemini, medium severity).

* fix: surface scanner and jq stderr in skill-scan instead of suppressing (#4846)

Addresses PR #2493 review feedback (issue #3249):
- Redirect skill-scanner background process stderr to indexed .err files
  instead of /dev/null, so Python env/dependency/syntax errors are visible
- Report .err file contents to stderr in the collection loop when non-empty
- Remove 2>/dev/null from jq skill_sources parse so malformed JSON errors
  are visible and set -e can abort on failure as intended

* fix(t3273): replace hardcoded oh-my-pi local path in plans (#4845)

* fix: avoid SIGPIPE false negatives in old-label migration checks (#4844)

Under set -o pipefail, 'launchctl list | grep -qF' can return exit code
141 (SIGPIPE) when grep exits early after a match, causing the migration/
unload path to be skipped even when the old label is present.

Apply the same variable-capture pattern already used in _launchd_is_loaded:
capture launchctl list output into a variable first, then pipe to grep.
Fixes both cmd_enable (line 571) and cmd_disable (line 688).

Closes #3270 (PR #2365 review feedback)

* t3599: extract scheduler detection and migration helpers in setup.sh (#4839)

* fix(t3599): extract scheduler detection and migration helpers to eliminate duplication

Extract two helper functions from the duplicated scheduler setup logic in setup.sh:
- _detect_scheduler_installed: checks both launchd and cron for an existing scheduler
- _migrate_scheduler_cron_to_launchd: handles cron→launchd migration with proper
  failure handling (on failure, signals caller to re-attempt install rather than
  silently marking the scheduler as installed)

Refactor the auto-update and supervisor pulse detection blocks to use these helpers.
Also fixes the migration failure guard: previously a failed cron→launchd migration
would still set _auto_update_installed=true, permanently skipping re-installation.

Addresses review feedback from PR #1971 (gemini-code-assist).
Closes #3599

* fix(t3599): consolidate scheduler setup detection logic

* fix(t3215): generalize dependency-detection search guidance (#4851)

* fix: apply PR #2652 readability feedback to Cloudron packaging docs (#4852)

* fix: remove blanket 2>/dev/null suppression in cleanup_osgrep (#4854)

Per PR #2170 review feedback (issue #3214): pgrep stdout redirect
is sufficient for existence checks; pkill errors are already guarded
by || true and should remain visible for debugging per style guide.

* fix: handle root commit in git diff shortstat for session miner (#4855)

When the oldest commit in a session window is a root commit (no parent),
`git diff --shortstat <hash>~1` fails with an invalid ref error, silently
dropping diff stats for that session.

Fix: check for a parent via `rev-parse --verify --quiet <hash>^`. If none
exists, diff from the canonical empty-tree object (4b825dc...) instead of
`<hash>~1`. This correctly captures insertions from the initial commit.

Closes #3230
Addresses PR #2658 review feedback (gemini-code-assist, extract.py:494)

* fix(tests): fix VERBOSE passthrough in test-verify-brief.sh (#4858)

Replace misleading `export VERBOSE` with proper CLI flag forwarding.
verify-brief.sh parses --verbose from its own $@, not from an env var,
so the export had no effect. Now uses VERBOSE_ARG string variable with
${VERBOSE_ARG:+$VERBOSE_ARG} expansion (bash 3.2 compatible) passed
directly to all verify-brief.sh invocations.

Closes #3255
Addresses PR #2187 review feedback (coderabbit finding)

* fix: address PR #2357 review feedback on full-loop-helper.sh (#4856)

- Add PR_NUMBER to load_state allowlist so cmd_resume preserves the
  PR reference recorded during pr-create phase instead of overwriting
  it with an empty string (fixes reviewer finding at line 331)
- Extract _run_foreground() function with EXIT trap that removes the
  PID file on process exit, preventing status/logs from falsely
  reporting an active background loop after the subprocess terminates
  (fixes reviewer finding at lines 292/294/307)
- Add explicit return 0 to load_state() per shell quality standards

Closes #3238

* fix(t3244): align /role description and usage with all 5 valid roles (#4857)

The description and usage message for the /role command only listed
observer/member/admin, but validRoles also included author and moderator.
This inconsistency would confuse users who couldn't discover the full
role set from the bot's own help text.

Closes #3244

* fix: correct strategic review scheduling claims in onboarding.md (#4862)

Address PR #2344 review feedback (issue #3217):
- Clarify strategic review is a separate scheduled process, not a pulse step
- Fix misleading claim that 'enabling the pulse enables everything'
- Session miner and circuit breaker correctly noted as pulse exit steps
- Add runners.md reference for strategic review setup

Closes #3217

* fix: address PR #2336 review feedback in strategic-review.md (#4861)

- Fix worktree list to iterate per-repo (git worktree list is repo-scoped,
  not global); removes incorrect 'all repos share the worktree namespace' note
- Fix gh pr merge to require explicit PR number and --repo flag to prevent
  acting on the wrong PR in a cross-repo context

Closes #3216

* fix: address PR #2694 review feedback in brand-identity.md (#4860)

- formality_spectrum: change type from string to number (0) in template
  and example ("4" -> 4) for consistency with brand_positioning numeric scales
- destructive.style: split mixed visual+behavioural value into separate
  style and behaviour fields in both template schema and example
- Brand-identity.toon: fix capitalisation typo to brand-identity.toon

Closes #3224

* fix: address PR #2680 gemini review feedback in per-tenant-rag.md (#4859)

- Remove duplicate alpha default from reciprocalRankFusion signature;
  DEFAULT_QUERY_CONFIG.hybridAlpha is the single source of truth (line 453)
- Fix token budget in assembleContext to account for attribution string
  and separator tokens, preventing context window overrun

Closes #3226

* fix: remove grep stderr suppression in sanity pipeline checks (#4868)

* fix: alphabetize communications links in AGENTS index (#4867)

* fix(t3201): add timeout to Telegram runner dispatch example (#4866)

* fix: clarify Nostr and Matrix AI training policies in privacy-comparison (#4865)

Nostr's AI training policy is relay-dependent (relay operators can process
and monetize public notes), not 'None' at the protocol level. Matrix's
policy is server-dependent (homeserver admins can access unencrypted
messages), not 'None (Foundation)'.

Addresses PR #2776 review feedback from gemini-code-assist.
Closes #3204

* fix: is_model_available returns failure for unknown providers (#4864)

PR #2366 review feedback (issue #3210): the unknown-provider branch
previously returned 0 (success), allowing resolve_chain to emit a model
string with no credential or health verification. This produces silent
runtime failures when the routing table is extended beyond the known
providers (anthropic/openai/google).

Change: return 1 with a warning for unknown providers, consistent with
the existing behaviour for known providers with missing API keys. The
model-availability-helper.sh delegation path is unaffected.

* fix: sort communications keywords alphabetically in subagent-index.toon (#4863)

Address PR #2765 review feedback (gemini-code-assist, medium severity):
- Sort services/communications/ keywords alphabetically for readability
- Improve description to list bot types consistently (Discord bot, Matrix bot)

Closes #3208

* fix(t3189): add no-further-feedback review regression test (#4873)

* fix(issue3188): add regression test for non-actionable Gemini approval review (#4872)

PR #2887 Gemini review ('I approve of this refactoring') was incorrectly
captured as a quality-debt finding by scan-merged before the summary_praise_only
filter was added. The filter already handles this body (summary_praise_only=true
via 'improves', 'consistent', 'good improvement'). Add a regression test to
prevent reintroduction.

Resolves #3188.

* fix(t3209): harden ampcode result files and error visibility (#4871)

* fix: harden budget cost parsing and 7-day burn-rate metric (#4870)

* fix: remove 2>/dev/null from check_permission_failure_pr (GH#3195) (#4869)

Extends PR #2825 fix to check_permission_failure_pr function:
- Remove stderr suppression from gh pr view (exit code captured separately)
- Remove stderr suppression from gh pr comment (|| true retained)

Consistent with check_external_contributor_pr pattern fixed in #2825.

Closes #3195

* fix: eliminate newline-injection vulnerability in shellcheck-wrapper arg filtering (#4875)

Replace printf/read serialization round-trip in _filter_args with direct
global array population. The previous pattern used printf '%s\n' to serialize
args and while IFS= read -r to deserialize them in main(), which was vulnerable
to argument splitting if any arg contained a newline — an attacker could embed
a newline in a filename to inject a second argument and bypass the
--external-sources stripping that prevents 11 GB RSS memory explosions.

Addresses GH#3176 (quality-debt review feedback from PR #2918, Gemini finding
at shellcheck-wrapper.sh:93).

* fix: align grep -c pattern in setup_terminal_title with established || : convention (#4877)

PR #3003 review feedback (issue #3167): the Tabby disabled_count assignment
used '|| true' on the outer statement rather than '|| :' inside the command
substitution, inconsistent with the pattern established at lines 214-219.

Move || : inside the subshell so grep -c exit-1 (no matches) is suppressed
at the source; 0 already handles the empty-string case.
ShellCheck: zero violations.

* fix(t3175): remove redundant wc whitespace trimming (#4878)

* fix(issue3158): add regression test for non-actionable Gemini approval review (#4882)

PR #3060 Gemini review ("The changes are correct and well-justified.") was a
false-positive quality-debt finding. The summary_praise_only filter already
handles this body correctly (via 'effectively' and 'improves'); this test
prevents reintroduction.

Resolves #3158.

* fix(t3178): remove kill stderr suppression in timeout fallback (#4880)

* fix(issue3117): correct mcporter security doc path reference (#4879)

* fix(t3186): harden supervisor state-machine regression tests (#4884)

* fix(t3159): revert out-of-scope indentation changes in backup safety test (#4883)

* fix(t3120): surface jq dataset parse errors in bench parsing (#4881)

* fix(issue3174): sanitize flag file reads in cmd_start and cmd_stop (#4876)

Apply tr sanitization to started_at reads in cmd_start() and cmd_stop()
to prevent terminal escape injection, consistent with the existing pattern
already applied in cmd_status(). Addresses remaining unsanitized reads
from PR #2943 review feedback (GH#3174).

Closes #3174

* fix(issue3145): add regression test for PR #3077 Gemini summary-only review (#4885)

The Gemini Code Assist review on PR #3077 was a positive summary with no
actionable critique (state=COMMENTED, no inline comments). The scan-merged
command created a false-positive quality-debt issue (#3145) before the
summary_only and summary_praise_only filters were added.

This commit adds a regression test using the exact PR #3077 review body to
ensure the two-layer filter (summary_only rule + summary_praise_only heuristic)
continues to suppress this class of non-actionable Gemini summaries.

30/30 tests pass, shellcheck clean.

Closes #3145

* fix(t3173): filter praise-only Gemini review summaries (#4886)

* fix(t4874): prevent false-positive issues when suggestion already applied before merge (#4887)

scan-merged was creating quality-debt issues for review comments whose
suggestion had already been applied by the author before merging.

Root cause (two interacting bugs):
1. _extract_verification_snippet treated suggestion fences the same as diff
   fences, skipping all lines starting with '-'. Markdown list items like
   '- **Enhances:** t1393' start with '-' and were silently dropped, leaving
   no extractable snippet → finding marked unverifiable → issue created.

2. Even when a snippet was extracted from a suggestion fence, the semantics
   were inverted: the code treated 'snippet found in file' as 'problem still
   exists → keep', but for suggestion fences the snippet IS the proposed fix
   text — finding it in HEAD means the fix was already applied → resolved.

Fix:
- Split diff vs suggestion fence handling in _extract_verification_snippet:
  diff fences skip +/- lines (unified-diff markers); suggestion fences do NOT
  skip '-' lines (they are literal replacement content, not removal markers).
- Add _body_has_suggestion_fence() helper to detect suggestion fence presence.
- Invert snippet semantics in _finding_still_exists_on_main for suggestion
  fences: snippet found in HEAD → fix applied → resolved → skip;
  snippet absent from HEAD → fix not yet applied → keep → create issue.
- Fix grep -Fq to use -e flag so patterns starting with '-' are not
  misinterpreted as grep options (macOS BSD grep does not support '--').

Regression tests (GH#4874):
- suggestion fence: skip finding when markdown list item already applied
- suggestion fence: create issue when markdown list item not yet applied
- Updated test_handles_suggestion_fence_and_comments to reflect correct
  semantics (suggestion text in file → fix applied → no issue)

Incident: false-positive issue #3183 from PR #2871 (merge d8d438a5).
Closes #4874

* fix(t3116): remove stderr suppression in security posture helper (#4888)

* fix(t3110): update actions/checkout pin in opencode template (#4889)

Align the checkout action with the newer v4.1.7 commit referenced in the Gemini quality-debt finding from PR #3103. This keeps the pinned SHA current within the v4 line while preserving immutable action pinning.

* feat: add Qlty maintainability tracking to daily quality sweep and local linting (#4890)

Systemic improvement to the daily code quality auditing routines:

1. Enhanced daily quality sweep (stats-functions.sh):
   - Use SARIF output from qlty CLI for structured smell analysis
   - Report per-rule breakdown (function-complexity, file-complexity, etc.)
   - Report per-file breakdown (top 10 files by smell density)
   - Fetch Qlty Cloud badge grade (A/B/C/D/F) from badge SVG
   - Track qlty_smells and qlty_grade in sweep state for delta detection
   - Add Qlty grade + smell count to quality review dashboard
   - Include Qlty in composite badge status indicator
   - Add Qlty grade to issue title for at-a-glance monitoring

2. Enhanced local linting (linters-local.sh):
   - New check_qlty_maintainability() function
   - SARIF-based smell count with severity thresholds
   - Top smell types and top files for targeted fixes
   - Qlty Cloud badge grade check with colour-coded output
   - Respects bundle skip_gates for project-specific overrides

This makes Qlty maintainability a first-class metric alongside SonarCloud,
tracked daily with deltas, surfaced in dashboards, and actionable by the
supervisor for creating targeted quality-debt issues.

* feat: add all-time model usage table and comma-format dollar amounts (#4891)

- Add _format_cost() helper for comma-separated dollar amounts
- Parameterize _get_model_usage() and _get_token_totals() with period (30d/all)
- Extract _render_model_usage_table() to eliminate ~90 lines of duplication
- Profile README now shows both 30-day and all-time model usage tables

* feat: source all-time model usage from opencode.db for full history (#4893)

- Query opencode.db message table (data back to Nov 2025) for all-time stats
- Add _compute_costs_from_tokens() to calculate costs from pricing table
- Add GPT-5.x, grok, kimi, big-pickle to _model_cost_rates()
- Merge model name variants (e.g., claude-opus-4-5-20251101 -> claude-opus-4-5)
- 30-day table still uses llm-requests.db (accurate recorded costs)

* refactor: reduce Qlty maintainability smells in Python scripts (batch 1)

Extract-function refactoring across 3 Python scripts to reduce Qlty
maintainability smells from 32 to 5 (84% reduction in these files,
139 → 111 total across the codebase).

entity-extraction.py (8 → 2 smells):
- Extract _extract_json_from_response, _validate_and_clean_entities
  from _parse_llm_response (complexity 24 → below threshold)
- Extract _build_arg_parser, _format_entity_summary from main
- Replace 6-return extract_entities with dispatch dict _METHOD_DISPATCH
- Flatten nested control flow with guard clauses
- Extract _run_ollama_list to deduplicate similar code

session-miner/extract.py (11 → 1 smells):
- Extract 16 helpers from 5 high-complexity functions
- Replace _summarize_tool_input 9-return chain with _TOOL_SUMMARIZERS dict
- Unify 3 duplicated chunk-building loops into _chunk_records
- Flatten nested control flow with _parse_json_safe helper
- File complexity 208 → 116

email-to-markdown.py (13 → 2 smells):
- Extract 20+ helpers from 7 high-complexity functions
- normalise_email_sections (complexity 44) → _SectionState + 7 handlers
- build_frontmatter (complexity 44) → 3 YAML formatting helpers
- main (complexity 37) → _build_arg_parser + _run_batch + _run_single
- generate_summary 10 returns → _try_llm_summary dispatch
- File complexity 303 → 223

Remaining smells are irreducible without module splits:
- File-level complexity (inherent to module scope)
- email_to_markdown 9 params (public API, cannot change)

* refactor: reduce Qlty maintainability smells in JS/TS files (batch 2)

Extract-function refactoring across 2 JavaScript files to reduce Qlty
maintainability smells from 45 to 23 (49% reduction in these files,
111 → 89 total across the codebase).

index.mjs (12 → 1 smell):
- Extract helpers from all 8 high-complexity functions
- messagesTransformHook (27): 4 helpers for violation detection pipeline
- validateReturnStatements (27): walkFunctionsForReturns + sub-helpers
- validatePositionalParams (21): checkPositionalParamLine + predicates
- runMarkdownQualityPipeline (25): checkMD031, checkTrailingWhitespace
- loadAgentIndex (23): parseToonSubagentBlock + collectLeafAgents
- Replace complex binary expressions with named pattern arrays
- File complexity 359 → 316

playwright-automator.mjs (33 → 22 smells):
- Extract runBatchJob to deduplicate identical batch patterns
- Convert 4 functions from positional params to options objects
- Extract helpers from top 5 complexity functions:
  login (42): tryFillField, tryClickSubmit, isNonAuthUrl
  runDiscovery (43): categoriseRoutes, diffRoutesAgainstCache
  fetchProjectApiWithPolling (40): fetchProjectApiData, evaluateNewestJobStatus
  waitForVideoGeneration (33): logVideoPollingProgress
  batchVideo (32): submitVideoBatch, pollAndRecordVideoResults

* fix: bash 3.2 compatibility — unblock pulse dispatch and add automated checker (#4896)

Root cause: headless-runtime-helper.sh passed the opencode command array as a
single printf-escaped string to sandbox-exec-helper.sh. The sandbox received
one argument and passed it to env as a single executable path, causing 'No such
file or directory' on every pulse cycle. Additionally, tee stdout contaminated
the $() exit code capture, causing arithmetic parse errors.

Fixes:
- headless-runtime-helper.sh: pass cmd array elements as separate args to
  sandbox; write exit code to temp file instead of $() capture
- setup.sh: replace declare -A with string-based dedup (bash 4.0+ feature)
- mission-dashboard-helper.sh: replace local -A with string-based dedup
- aidevops-update-check.sh: replace ${var,,} with tr case conversion
- quality-feedback-helper.sh: replace ${BASH_REMATCH[1],,} with tr

Prevention:
- build.txt: add comprehensive bash 3.2 compatibility rules covering forbidden
  features, subshell traps, and array passing across process boundaries
- linters-local.sh: add check_bash32_compat() gate that scans all shell scripts
  for declare -A, mapfile, ${var,,}, namerefs, coproc, and &>> patterns

* chore: bump version to 2.172.30

* fix: bash escape quoting — "\t" produces literal backslash-t, not tab (#4897)

setup.sh built plist XML with "\t\t<string>..." which produced literal
\t\t in the plist file. launchd rejected the invalid XML with I/O error,
silently killing the supervisor pulse. The auto-update triggered by
v2.172.30 regenerated the plist, exposing this latent bug.

Fix: use $'\t\t' (ANSI-C quoting) for actual tab characters.

Prevention:
- build.txt: add escape sequence quoting rules explaining that bash
  double quotes do NOT interpret \t \n \r (unlike C/Python/JS)
- linters-local.sh: add "\t"/"\n" detection in string concatenation
  context to the bash 3.2 compat checker

* chore: bump version to 2.172.31

* feat: add ripgrep (rg) to required dependencies in setup (#4892)

ripgrep is used extensively by the framework and agents for fast content
search. Previously it was only offered as an optional file discovery tool
in a separate setup step. Now it is installed alongside jq, curl, and ssh
as a required dependency.

Introduces a separate missing_packages array to handle the command-to-
package name mapping (rg command -> ripgrep package), since the package
name is the same across all supported platforms (brew, apt, dnf, yum,
pacman, apk).

* docs: note pulse supervisor requires Anthropic sonnet, OpenAI unreliable for orchestration

* docs: add pulse model constraint to model-routing.md — sonnet only, openai unreliable for orchestration

* fix: remove ssh from required deps in setup-modules/core.sh (#4899)

ssh is pre-installed on virtually all Unix systems. The package name
'ssh' doesn't exist on most package managers (correct names vary:
openssh-client, openssh-clients, openssh). Removing the check avoids
a broken install attempt on any platform.

Closes #4898

* chore(release): bump version to 2.173.0

* refactor: reduce Qlty maintainability smells in Python/JS scripts (batch 3a)

* refactor: reduce Qlty maintainability smells in Python scripts (batch 3a)

Extract-function refactoring in 2 Python scripts to reduce smells.
Total codebase: 89 → 69 smells.

extraction_pipeline.py (6 → 1 smell):
- Extract _get_field_rules, _score_field from compute_confidence (29)
- Extract _validate_total_check, _validate_date_field from validate_extraction (31)
- Extract _parse_extract_options from cmd_extract (19, 6 returns)
- File complexity 137 → 103

email-summary.py (6 → 2 smells):
- Extract _filter_meaningful_lines, _split_sentences from _extract_first_sentences (25)
- Extract _build_cli_parser, _handle_json_output from main (18)
- Consolidate summarise_ollama returns with early-exit pattern
- File complexity 121 → 112

* refactor: reduce Qlty maintainability smells in OpenCode TS files (batch 3b)

Extract-function refactoring across 5 TypeScript files.
Total codebase: 69 → 64 smells.

toon.ts lib (5 → 0 smells):
- Extract convertPrimitive, convertArrayToToon, convertObjectToToon
- Extract parseLiteral, parseTabularBlock, parseKeyValuePair
- Extract detectKnownValue for value type dispatch

github-release.ts (2 → 0 smells):
- Extract normalizeVersion, requireVersion, createRelease, createDraftRelease

toon.ts tool (2 → 0 smells):
- Extract resolveInputData, handleEncode/Decode/Compare/Stats

use-streaming.ts (1 → 0 smells):
- Extract dispatchStreamEvent, parseSseLines, readSseStream
- StreamEventHandlers interface for dependency injection

parallel-quality.ts (1 → 0 smells):
- Extract resolveChecksToRun, buildResultSummary, formatQualityResults

* chore: claim t1484

* refactor: reduce Qlty maintainability smells (batch3c)

* refactor: reduce Qlty smells in playwright-automator.mjs (batch 3c)

Extract-function refactoring in playwright-automator.mjs.
Total codebase: 64 → 52 smells (-12).

Extracted helpers from 6 high-complexity functions:
- dismissInterruptions (29): dismissModalsAndBanners, dismissOverlaysAndAgreements
- configureImageOptions (31): setAspectRatio, setEnhanceToggle
- waitForImageGeneration (30): checkImageGenCompletion, retryGenerateIfStalled
- motionPreset (28): listMotionPresets, resolveMotionPresetUrl
- apiRequest (26): apiExecuteFetch, parseApiErrorDetail
- smokeTest (23): smokeTestNavigation, smokeTestCredits

* chore: claim t1485

* chore: claim t1486

* chore: claim t1487

* chore: add module-split tasks for top 4 file-complexity smells (t1485-t1488)

Create detailed task briefs for splitting the 4 highest file-complexity
files into focused modules. Each brief includes proposed module structure,
acceptance criteria, and model tier (opus) for pulse dispatch.

t1485: playwright-automator.mjs (1272) → 6 modules ref:GH#4905
t1486: opencode-aidevops/index.mjs (316) → 5 modules ref:GH#4906
t1487: email-to-markdown.py (223) → 4 modules ref:GH#4907
t1488: seo-content-analyzer.py (177) → 3 modules ref:GH#4908

These are the remaining irreducible file-complexity smells from the
quality sweep session that reduced Qlty smells from 139 → 52.

* fix: split footer text into separate paragraphs for readability (#4909)

Each sentence in the model usage and work-with-AI table footers is now
its own italic paragraph, fixing broken markdown rendering where multi-line
_..._ blocks didn't render correctly on GitHub.

* chore: claim t1488

* chore: claim t1489

* chore: add Codacy quality gate adjustment task (t1489)

Codacy quality gate (0 max new issues) trips on extract-function
refactoring — observed 4x during quality sweep session. Project grade
stays A; only the gate threshold is violated. ref:GH#4910

* chore: claim t1490

* fix: add comma thousands separators to token counts (e.g., 10,425.3M) (#4911)

* feat: bridge daily quality sweep to code-simplifier pipeline (t1490)

Add _create_simplification_issues() to the daily quality sweep that
auto-creates simplification-debt issues for files with high Qlty smell
density (>5 smells). This bridges the gap between the sweep's SARIF
analysis and the code-simplifier's human-gated dispatch pipeline.

Behaviour:
- Only creates issues for files with >5 smells
- Max 3 new issues per sweep (rate limiting)
- Deduplicates against existing open simplification-debt issues
- Issues created with simplification-debt + needs-maintainer-review labels
- Assigned to repo maintainer (from repos.json)
- Issue body includes per-rule breakdown, suggested approach, and
  verification steps — matching code-simplifier.md format
- Maintainer approves/declines via comment (approved/declined: reason)
- Approved issues enter pulse dispatch queue at priority 8

Closes #4912

* perf: tune worker RAM allocation — 512MB per worker, 6GB reserve (was 1GB/8GB)

opencode headless sessions are lightweight (~200-400MB). The previous
1GB/worker + 8GB reserve limited a 24GB machine to 10 workers despite
a max_workers_cap of 24. New values allow full utilisation.

* fix: ensure simplification-debt labels exist before issue creation

gh issue create fails with 'label not found' if the simplification-debt
or needs-maintainer-review labels don't exist on the repo yet. Add
label creation (idempotent — gh label create is a no-op if exists) before
the issue creation loop.

* fix: auto-assign issues on creation to prevent duplicate dispatch

claim-task-id.sh now assigns the current GitHub user to newly created
issues immediately. This closes the race window where multiple pulses
or machines could dispatch workers for the same unassigned issue.

* fix: make pulse-wrapper.sh source-safe in zsh/supervisor sessions (GH#4904) (#4920)

- shared-constants.sh: guard all BASH_SOURCE[0] references with :-fallback
  so sourcing from zsh (where BASH_SOURCE is unset) with set -u does not
  abort with 'BASH_SOURCE[0]: parameter not set'
- config-helper.sh: same BASH_SOURCE guard; fix main() guard to check
  BASH_SOURCE is non-empty before comparing to $0, preventing main() from
  running when sourced from zsh (where $0 == 'zsh' == BASH_SOURCE fallback)
- pulse-wrapper.sh: replace [[ $cmd =~ /full-loop|Supervisor Pulse|... ]]
  with case statement — zsh parses the | as a pipe operator inside [[ ]],
  causing 'parse error near |' at lines 3037 and 3062

Verified: sourcing in zsh and bash 3.2 both succeed; all 14 pulse-wrapper
tests pass; shellcheck zero violations on all three files.

* t1486: split opencode-aidevops index into focused modules (#4915)

* refactor: split opencode plugin index into focused modules

* chore: re-trigger Codacy analysis after gate threshold adjustment (GH#4910)

* t1487: Split email-to-markdown.py into focused modules (complexity 223 → 43) (#4914)

* refactor(t1487): split email-to-markdown.py into focused modules

Reduces file-complexity from 223 to ~43 by extracting three pipeline modules:
- email_parser.py: MIME parsing, headers, body, attachment extraction (~274 lines, complexity ~48)
- email_normaliser.py: section normalisation, thread reconstruction, frontmatter (~455 lines, complexity ~68)
- email_md_summary.py: LLM/heuristic summary generation (~259 lines, complexity ~35)
- email-to-markdown.py: pipelin…
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant