Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .agents/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ Every agent session — interactive, worker, or supervisor — should improve th

If uncertain, ask: "Would this fix apply to every repo the framework manages, or only this one?" Framework-wide problems go to aidevops; project-specific problems stay local. Never create framework tasks in a project repo — they become invisible to framework maintainers and pollute the project's task namespace.

**Scope boundary for code changes (t1405, GH#2928).** Separate "observe and report" from "observe and fix". When dispatched by the pulse, the `PULSE_SCOPE_REPOS` env var lists the repo slugs where you may create branches and PRs. Filing issues is always allowed on any repo — cross-repo bug reports are valuable. But 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. The issue enters that repo's queue for their maintainers (or their own pulse) to handle. If `PULSE_SCOPE_REPOS` is empty or unset (interactive mode), no scope restriction applies.

**What counts as self-improvement:**
- Filing issues for repeated failure patterns
- Improving agent prompts when workers consistently misunderstand instructions
Expand Down
2 changes: 2 additions & 0 deletions .agents/prompts/build.txt
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ Git is the primary audit trail for all work. Every change should be discoverable

**Self-improvement repo routing:** When creating self-improvement tasks (see AGENTS.md "Self-Improvement"), route to the correct repo — not the repo you happen to be running in. Heuristic: if the observation references files under `~/.aidevops/`, framework scripts (`ai-actions.sh`, `ai-lifecycle.sh`, `supervisor/`, `dispatch.sh`, `pre-edit-check.sh`, helper scripts), agent prompt behaviour, or supervisor/pulse/orchestration logic, the task belongs in the aidevops repo. Run `claim-task-id.sh --repo-path <aidevops-repo-path>` first — it allocates the task ID and (by default) creates the GitHub issue. Only run `gh issue create --repo <aidevops-slug>` if `claim-task-id.sh` was invoked with `--no-issue` or its output did not include a `ref=GH#` (or `ref=GL#`) token; otherwise the issue already exists and a second create would duplicate it. Project-specific problems (CI, code, dependencies, domain logic) stay in the current repo. Framework tasks filed in project repos are invisible to framework maintainers and pollute the project's ID namespace.

**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.

**Git-readiness check:** When working in a project directory that is NOT a git repo, or is a git repo without `TODO.md` / aidevops initialisation, flag this to the user: "This project has no git tracking / no aidevops task management. Work here won't be traceable. Consider `git init` + `aidevops init` to enable the full workflow." Use judgment — a throwaway script directory doesn't need this, but any project with ongoing development does.

**Pre-edit rules:**
Expand Down
22 changes: 22 additions & 0 deletions .agents/scripts/commands/full-loop.md
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,28 @@ When running as a headless worker (dispatched by the supervisor via `opencode ru

Then continue with your assigned task in the current repo. The pulse supervisor will pick up the cross-repo issue on its next cycle. This prevents framework-level work from being tracked in app repos and vice versa.

**Scope boundary for code changes (t1405, GH#2928):** When dispatched by the pulse (headless mode), the `PULSE_SCOPE_REPOS` env var contains a comma-separated list of repo slugs that you are allowed to create branches and PRs on. This is set by `pulse-wrapper.sh` from repos with `pulse: true` in repos.json.

- **Filing issues**: ALWAYS allowed on any repo, regardless of scope. Cross-repo bug reports are valuable feedback to maintainers.
- **Creating branches, PRs, or committing code**: ONLY allowed on repos listed 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**: you are in interactive mode (not pulse-dispatched) — no scope restriction applies.

```bash
# Check if a target repo is in scope before creating code changes
TARGET_SLUG="owner/repo"
if [[ -n "${PULSE_SCOPE_REPOS:-}" ]]; then
if ! echo ",$PULSE_SCOPE_REPOS," | grep -qF ",$TARGET_SLUG,"; then
echo "Repo $TARGET_SLUG is outside pulse scope — filing issue only, not implementing fix"
gh issue create --repo "$TARGET_SLUG" --title "TITLE" \
--body "Discovered while working on CURRENT_TASK. DETAILS"
echo "BLOCKED: target repo out of pulse scope; issue filed — stopping."
exit 0
fi
fi
```

This prevents the pattern where a pulse-dispatched worker creates PRs on repos the user doesn't manage (observed: 4 PRs + a fork on a repo the user doesn't own).

10. **Issue-task alignment (MANDATORY)** — Before linking your PR to an issue or claiming a task, verify your work matches the issue's actual description. Workers have hijacked issues by using a task ID for completely unrelated work (e.g., PR "Fix ShellCheck noise" closed issue "Add local dev row to build-plus.md" because both used t1344).

**Before creating a PR that references an issue:**
Expand Down
1 change: 1 addition & 0 deletions .agents/scripts/commands/pulse.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ sleep 2
- Use `--dir <path>` from repos.json
- Route non-code tasks with `--agent`: SEO, Content, Marketing, Business, Research (see AGENTS.md "Agent Routing")
- **Bundle-aware agent routing (t1364.6):** Before dispatching, check if the target repo has a bundle with `agent_routing` overrides. Run `bundle-helper.sh get agent_routing <repo-path>` — if the task domain (code, seo, content, marketing) has a non-default agent, use `--agent <name>`. Example: a content-site bundle routes `marketing` tasks to the Marketing agent instead of Build+. Explicit `--agent` flags in the issue body always override bundle defaults.
- **Scope boundary (t1405, GH#2928):** ONLY dispatch workers for repos in the pre-fetched state (i.e., repos with `pulse: true` in repos.json). The `PULSE_SCOPE_REPOS` env var (set by `pulse-wrapper.sh`) contains the comma-separated list of in-scope repo slugs. Workers inherit this env var and use it to restrict code changes (branches, PRs) to scoped repos. Workers CAN still file issues on any repo (cross-repo self-improvement), but the pulse must NEVER dispatch a worker to implement a fix on a repo outside this scope — even if an issue exists there. Issues on non-pulse repos enter that repo's queue for their own maintainers to handle.

### Priority order

Expand Down
9 changes: 9 additions & 0 deletions .agents/scripts/pulse-wrapper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,15 @@ prefetch_state() {
# Append active worker snapshot for orphaned PR detection (t216)
prefetch_active_workers >>"$STATE_FILE"

# Export PULSE_SCOPE_REPOS — comma-separated list of repo slugs that
# workers are allowed to create PRs/branches on (t1405, GH#2928).
# 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 | grep . | paste -sd ',' -)
export PULSE_SCOPE_REPOS="$scope_slugs"
echo "[pulse-wrapper] PULSE_SCOPE_REPOS=${scope_slugs}" >>"$LOGFILE"

local repo_count
repo_count=$(echo "$repo_entries" | wc -l | tr -d ' ')
echo "[pulse-wrapper] Pre-fetched state for $repo_count repos → $STATE_FILE" >>"$LOGFILE"
Expand Down
Loading