Skip to content

t1405: scope boundary for worker dispatch — pulse dispatches only within pulse-enabled repos#2933

Merged
marcusquinn merged 2 commits intomainfrom
feature/t1405-pulse-scope-boundary
Mar 5, 2026
Merged

t1405: scope boundary for worker dispatch — pulse dispatches only within pulse-enabled repos#2933
marcusquinn merged 2 commits intomainfrom
feature/t1405-pulse-scope-boundary

Conversation

@marcusquinn
Copy link
Owner

@marcusquinn marcusquinn commented Mar 5, 2026

Summary

  • Adds PULSE_SCOPE_REPOS env var (comma-separated repo slugs) exported by pulse-wrapper.sh from pulse: true repos in repos.json
  • Workers inherit this env var and use it to restrict code changes (branches, PRs) to scoped repos while still being able to file issues on any repo
  • Documents the scope boundary in pulse.md dispatch rules, full-loop.md cross-repo routing, AGENTS.md self-improvement section, and build.txt system prompt

Problem

The pulse correctly pre-fetches only pulse: true repos, but workers dispatched by the pulse could independently discover and act on issues in other repos via self-improvement routing. This led to workers creating 4 PRs, a fork, and branches on a repo the user doesn't own — without the user's knowledge.

Solution

Separate "observe and report" from "observe and fix":

  • Filing issues: ALWAYS allowed on any repo (cross-repo self-improvement is valuable feedback)
  • Code changes (branches, PRs, commits): ONLY allowed on repos in PULSE_SCOPE_REPOS
  • Interactive mode: No scope restriction (env var unset)

The enforcement is layered:

  1. Harness layer (pulse-wrapper.sh): Exports PULSE_SCOPE_REPOS before spawning the pulse agent
  2. Supervisor layer (pulse.md): Documents that dispatch must only target in-scope repos
  3. Worker layer (full-loop.md): Workers check scope before creating code changes on other repos
  4. System prompt (build.txt): All agents are aware of the scope boundary

Relationship to related issues

Closes #2928

Summary by CodeRabbit

  • Documentation

    • Added comprehensive scope boundary policy for automated task dispatch: code changes (branches/PRs/commits) are restricted to designated repositories, while filing issues is allowed across all repositories. Interactive mode disables scope restrictions. Clarifies cross-repo handling and queue routing when targets are out of scope.
  • Chores

    • Added configuration and workflow updates to enforce the scoped dispatch behavior for automated tasks.

@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a critical scope boundary for AI agents dispatched by the pulse system. The primary goal is to prevent automated workers from inadvertently making code changes (branches, PRs, commits) in repositories that are not explicitly managed or intended for modification by the user's pulse configuration. While maintaining the ability for agents to report issues across any repository for valuable feedback, this change ensures that active code development is strictly confined to designated, pulse-enabled repositories, thereby enhancing control and preventing unintended external interactions.

Highlights

  • PULSE_SCOPE_REPOS Environment Variable: Introduced PULSE_SCOPE_REPOS as a comma-separated list of repository slugs, explicitly defining where pulse-dispatched workers are permitted to make code changes.
  • Restricted Code Changes: Implemented a mechanism to prevent workers from creating branches, pull requests, or commits on repositories not listed in the PULSE_SCOPE_REPOS variable.
  • Unrestricted Issue Filing: Maintained the ability for workers to file issues on any repository, regardless of the PULSE_SCOPE_REPOS setting, to ensure valuable cross-repo feedback.
  • Documentation Updates: Updated AGENTS.md, build.txt, full-loop.md, and pulse.md to clearly document the new scope boundary rules and expected worker behavior.
  • pulse-wrapper.sh Integration: Modified pulse-wrapper.sh to automatically export the PULSE_SCOPE_REPOS environment variable, populating it with slugs from repositories marked with pulse: true in repos.json.
Changelog
  • .agents/AGENTS.md
    • Added a section detailing the scope boundary for code changes, explaining the PULSE_SCOPE_REPOS environment variable and the distinction between filing issues and making code changes.
  • .agents/prompts/build.txt
    • Incorporated instructions for agents regarding the PULSE_SCOPE_REPOS boundary, clarifying when code changes are permitted and when only issues should be filed.
  • .agents/scripts/commands/full-loop.md
    • Expanded the documentation with a comprehensive section on the scope boundary for code changes, including a bash snippet for checking PULSE_SCOPE_REPOS before initiating code modifications.
  • .agents/scripts/commands/pulse.md
    • Updated dispatch rules to explicitly state that workers should only be dispatched to repos within the pre-fetched state (i.e., repos with pulse: true in repos.json), reinforcing the PULSE_SCOPE_REPOS constraint.
  • .agents/scripts/pulse-wrapper.sh
    • Modified the prefetch_state function to calculate and export the PULSE_SCOPE_REPOS environment variable, populating it with slugs from pulse: true repositories.
Activity
  • No human activity (comments, reviews, etc.) 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.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 5, 2026

Walkthrough

Adds a pulse scope boundary: PULSE_SCOPE_REPOS (comma-separated repo slugs) is exported to dispatched workers; workers may file issues on any repo but may only create branches/PRs/commits on repos listed in PULSE_SCOPE_REPOS. Interactive (unset/empty) mode disables scope restrictions.

Changes

Cohort / File(s) Summary
Policy & Prompts
.agents/AGENTS.md, .agents/prompts/build.txt, .agents/scripts/commands/pulse.md
Documented scope boundary: PULSE_SCOPE_REPOS restricts code-changing actions (branches/PRs/commits) to scoped repos while allowing issue filing anywhere; clarified queue routing for out-of-scope targets.
Guard & Worker Guidance
.agents/scripts/commands/full-loop.md
Inserted scope-check text and a Bash guard snippet (appears twice) that prevents code changes when target repo is not in PULSE_SCOPE_REPOS; notes interactive-mode behavior.
Runtime Export
.agents/scripts/pulse-wrapper.sh
Exports PULSE_SCOPE_REPOS during prefetch_state by deriving comma-separated repo slugs from repo_entries and logging the value to the environment passed to workers.

Sequence Diagram(s)

sequenceDiagram
    participant Pulse as Pulse (prefetch)
    participant Env as Env (PULSE_SCOPE_REPOS)
    participant Worker as Dispatched Worker
    participant Repo as Target Repo
    participant Queue as Repo Maintainers' Queue

    Pulse->>Env: compute PULSE_SCOPE_REPOS (comma list)
    Pulse-->>Worker: start worker (inherits PULSE_SCOPE_REPOS)
    Worker->>Repo: discover issue or required fix
    alt Repo in PULSE_SCOPE_REPOS
        Worker->>Repo: create branch / open PR
    else Repo not in scope
        Worker->>Repo: file issue
        Worker->>Queue: stop implementation (dispatch halted)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • marcusquinn/aidevops#2471: Related changes to pulse prefetch infrastructure that this PR builds upon for deriving PULSE_SCOPE_REPOS.
  • marcusquinn/aidevops#2853: Overlapping edits to .agents/scripts/pulse-wrapper.sh and pulse prefetch/run flow; may conflict or interact with exported env changes.

Suggested labels

enhancement

Poem

🌩️ Pulse hums a careful tune tonight,
It lists its bounds and holds them tight.
Issues travel freely, flags unfurled,
But branches only stay in scoped world.
A tidy dance of report and fix — delight!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and specifically addresses the main change: introducing scope boundary enforcement for pulse-dispatched workers to dispatch only within pulse-enabled repos, which is the core objective of the PR.
Linked Issues check ✅ Passed The PR fully implements all coding objectives from issue #2928: exports PULSE_SCOPE_REPOS in pulse-wrapper.sh, restricts code changes to scoped repos in full-loop.md, documents dispatch rules in pulse.md, and adds system-prompt awareness in build.txt.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing scope boundary enforcement for pulse dispatch. No unrelated modifications or refactoring detected in the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% 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 docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/t1405-pulse-scope-boundary

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.

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 crucial scope boundary for pulse-dispatched workers, preventing them from making code changes outside of explicitly configured repositories. The implementation is well-layered, with changes to pulse-wrapper.sh to set the scope via an environment variable, and updates to documentation and agent prompts to ensure workers respect this boundary. My review found one minor opportunity to improve the robustness of how the scoped repository list is generated. Overall, this is a solid improvement for security and correctness.

Note: Security Review did not run due to the size of the PR.

# Workers CAN file issues on any repo (cross-repo self-improvement),
# but code changes (branches, PRs) are restricted to this list.
local scope_slugs
scope_slugs=$(echo "$repo_entries" | cut -d'|' -f1 | paste -sd ',' -)

Choose a reason for hiding this comment

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

medium

To make the creation of PULSE_SCOPE_REPOS more robust, consider filtering out empty slugs that might arise from malformed entries in repos.json. An empty slug in the list could result in a ,, substring, which could cause the scope check logic (grep -F ,,) to incorrectly pass for an empty target repository. Adding grep . to the pipeline is a simple way to filter out empty lines and ensure only valid slugs are included.

Suggested change
scope_slugs=$(echo "$repo_entries" | cut -d'|' -f1 | paste -sd ',' -)
scope_slugs=$(echo "$repo_entries" | cut -d'|' -f1 | grep . | paste -sd ',' -)

@marcusquinn marcusquinn force-pushed the feature/t1405-pulse-scope-boundary branch from cd6062f to af983b1 Compare March 5, 2026 17:11
@marcusquinn
Copy link
Owner Author

/qlty check

Separate 'observe and report' from 'observe and fix' for pulse-dispatched
workers. Workers CAN file issues on any repo (cross-repo self-improvement),
but code changes (branches, PRs) are restricted to repos listed in the
PULSE_SCOPE_REPOS env var, which is set by pulse-wrapper.sh from repos
with pulse: true in repos.json.

This prevents the pattern where pulse-dispatched workers create PRs on
repos outside the user's managed scope (observed: 4 PRs + a fork on a
repo the user doesn't own).

Closes #2928
@marcusquinn marcusquinn force-pushed the feature/t1405-pulse-scope-boundary branch from 791d386 to c28ab93 Compare March 5, 2026 17:26
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/commands/full-loop.md:
- Around line 483-494: The scope-guard currently files an issue for out-of-scope
repos but does not stop execution; after the gh issue create call inside the
if-block that detects TARGET_SLUG not in PULSE_SCOPE_REPOS, add an explicit
control-flow stop (e.g., exit or return) immediately after filing the issue so
the script enforces "file the issue and stop" and prevents any subsequent
branch/commit/PR logic from running; update the block that references
TARGET_SLUG, PULSE_SCOPE_REPOS, and the gh issue create invocation to include
this exit.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: eee7df94-9bfc-404b-8abb-87856ba09f42

📥 Commits

Reviewing files that changed from the base of the PR and between 682383d and 791d386.

📒 Files selected for processing (5)
  • .agents/AGENTS.md
  • .agents/prompts/build.txt
  • .agents/scripts/commands/full-loop.md
  • .agents/scripts/commands/pulse.md
  • .agents/scripts/pulse-wrapper.sh

@marcusquinn
Copy link
Owner Author

CI Status

All checks pass except qlty check which reports "Build errored" — this is a qlty cloud infrastructure error, not a code quality finding.

Local verification (all pass):

  • shellcheck .agents/scripts/pulse-wrapper.sh — clean
  • markdownlint-cli2 on all changed .md files — 0 errors
  • qlty check (CLI v0.615.0) on all changed files — no issues
  • Each qlty plugin individually (actionlint, markdownlint, shellcheck, trivy, trufflehog, ripgrep) — no issues

Evidence this is a qlty cloud issue:

The branch has been rebased onto latest main. The PR is mergeable.

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

🔍 Code Quality Report

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

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

�[0;34m[INFO]�[0m Recent monitoring activity:
Thu Mar 5 17:37:09 UTC 2026: Code review monitoring started
Thu Mar 5 17:37:10 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 108

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 108
  • VULNERABILITIES: 0

Generated on: Thu Mar 5 17:37:12 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

…(t1405)

- Add explicit exit 0 after gh issue create in scope guard to enforce
  'file the issue and stop' behavior (CodeRabbit CHANGES_REQUESTED)
- Fix indentation in scope guard code block
- Filter empty slugs from PULSE_SCOPE_REPOS to prevent malformed entries
  from bypassing scope check (Gemini review suggestion)
@github-actions
Copy link

github-actions bot commented Mar 5, 2026

🔍 Code Quality Report

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

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

�[0;34m[INFO]�[0m Recent monitoring activity:
Thu Mar 5 18:15:06 UTC 2026: Code review monitoring started
Thu Mar 5 18:15:06 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 108

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 108
  • VULNERABILITIES: 0

Generated on: Thu Mar 5 18:15:09 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 5, 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.

🧹 Nitpick comments (1)
.agents/prompts/build.txt (1)

239-240: Consider adding supervisor routing context for completeness.

The current text says "file the issue and stop — do not implement the fix" but doesn't explain what happens after filing the issue. The full-loop.md documentation (lines 475) includes helpful context: "The pulse supervisor will pick up the cross-repo issue on its next cycle." Adding a brief mention of this continuation path would help workers understand that filing the issue is a proper handoff, not a dead-end.

Optional refinement to clarify the workflow
-**Pulse scope boundary (t1405, GH#2928):** When dispatched by the pulse, `PULSE_SCOPE_REPOS` (comma-separated repo slugs) defines which repos you may create branches and PRs on. Filing issues is always allowed on any repo. Code changes (branches, PRs, commits) are restricted to repos in `PULSE_SCOPE_REPOS`. If the target repo is not in scope, file the issue and stop — do not implement the fix. If `PULSE_SCOPE_REPOS` is empty or unset (interactive mode), no scope restriction applies. This prevents pulse-dispatched workers from creating PRs on repos outside the user's managed scope.
+**Pulse scope boundary (t1405, GH#2928):** When dispatched by the pulse, `PULSE_SCOPE_REPOS` (comma-separated repo slugs) defines which repos you may create branches and PRs on. Filing issues is always allowed on any repo. Code changes (branches, PRs, commits) are restricted to repos in `PULSE_SCOPE_REPOS`. If the target repo is not in scope, file the issue and stop — do not implement the fix; the pulse supervisor will pick it up on the next cycle. If `PULSE_SCOPE_REPOS` is empty or unset (interactive mode), no scope restriction applies. This prevents pulse-dispatched workers from creating PRs on repos outside the user's managed scope.

This adds 11 words to clarify that cross-repo issues are routed to the supervisor, consistent with the detailed explanation in full-loop.md.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/prompts/build.txt around lines 239 - 240, Update the
PULSE_SCOPE_REPOS guidance to mention what happens after filing a cross-repo
issue: when a worker detects the target repo is out of scope it should "file the
issue and stop — do not implement the fix", and you must append a short note
that the filed cross-repo issue will be picked up by the pulse supervisor on its
next cycle (consistent with full-loop.md). Locate the paragraph referencing
PULSE_SCOPE_REPOS in .agents/prompts/build.txt and add a brief sentence about
supervisor routing so workers know filing the issue hands it off rather than
leaving it untracked.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.agents/prompts/build.txt:
- Around line 239-240: Update the PULSE_SCOPE_REPOS guidance to mention what
happens after filing a cross-repo issue: when a worker detects the target repo
is out of scope it should "file the issue and stop — do not implement the fix",
and you must append a short note that the filed cross-repo issue will be picked
up by the pulse supervisor on its next cycle (consistent with full-loop.md).
Locate the paragraph referencing PULSE_SCOPE_REPOS in .agents/prompts/build.txt
and add a brief sentence about supervisor routing so workers know filing the
issue hands it off rather than leaving it untracked.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4c414e7f-f443-4f6e-a954-f9caae1893b1

📥 Commits

Reviewing files that changed from the base of the PR and between 791d386 and ec1c37b.

📒 Files selected for processing (5)
  • .agents/AGENTS.md
  • .agents/prompts/build.txt
  • .agents/scripts/commands/full-loop.md
  • .agents/scripts/commands/pulse.md
  • .agents/scripts/pulse-wrapper.sh
🚧 Files skipped from review as they are similar to previous changes (3)
  • .agents/AGENTS.md
  • .agents/scripts/commands/pulse.md
  • .agents/scripts/commands/full-loop.md

@marcusquinn marcusquinn merged commit 2332d0e into main Mar 5, 2026
20 of 21 checks passed
@marcusquinn marcusquinn deleted the feature/t1405-pulse-scope-boundary branch March 5, 2026 18:20
marcusquinn added a commit that referenced this pull request Mar 6, 2026
…ws (#2980)

When bots are rate-limited, they post quota/rate-limit notices instead of
actual code reviews. The gate was counting these as valid reviews (PASS)
because it only checked for comment existence, not content.

Now both the helper script and CI workflow:
- Base64-encode comment bodies to handle multi-line content correctly
- Check each bot comment against known rate-limit patterns
- Only count comments as real reviews if they don't match rate-limit patterns
- Return WAITING (not PASS) when all bot comments are rate-limit notices
- Show rate-limited bots separately in output and CI summary

Tested against PR #2978 (rate-limited → WAITING) and PR #2933 (real review → PASS).
marcusquinn added a commit that referenced this pull request Mar 6, 2026
…ws (#2980) (#2982)

When bots are rate-limited, they post quota/rate-limit notices instead of
actual code reviews. The gate was counting these as valid reviews (PASS)
because it only checked for comment existence, not content.

Now both the helper script and CI workflow:
- Base64-encode comment bodies to handle multi-line content correctly
- Check each bot comment against known rate-limit patterns
- Only count comments as real reviews if they don't match rate-limit patterns
- Return WAITING (not PASS) when all bot comments are rate-limit notices
- Show rate-limited bots separately in output and CI summary

Tested against PR #2978 (rate-limited → WAITING) and PR #2933 (real review → PASS).
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.

feat: scope boundary for worker dispatch — pulse dispatches only within pulse-enabled repos

1 participant