Skip to content

Issue #174 - #177

Merged
immuhammad merged 2 commits into
mainfrom
feature/issue-174
Aug 3, 2026
Merged

immuhammad merged 2 commits into
mainfrom
feature/issue-174

Conversation

@immuhammad

Copy link
Copy Markdown
Owner

Closes #174.

Introduce orchestrator.yaml's github_repo key (orc_github_repo reader,
validated owner/repo, fail-closed) and thread it through as GH_REPO:
`orc up` exports it into the tmux session env before any pane exists;
every scripted gh call site in watch.sh, orc-seed-merge-watch.sh, and
orc-worktree.sh's PR creation is pinned with --repo; the merge/review
watchers and the seed helper refuse to poll/seed at all when it's
unset rather than guessing at the wrong repo. `orc init` derives a
default from the target's own git origin remote and round-trips it
through --force resync.

Closes #174.
@immuhammad

Copy link
Copy Markdown
Owner Author

REQUEST-CHANGES

1. bin/orc: tmux env-propagation ordering completely misses pane 0

File: bin/orc (around line 228 and 252)
Failure Scenario: The PR comment claims this block must sit "before every branch below that calls tmux new-session", but the code places tmux set-environment -t "$session" GH_REPO "$github_repo" exactly after tmux new-session. Because tmux new-session creates the session and spawns the shell for pane 0 simultaneously, pane 0's shell is already spawned before set-environment runs.
Consequently, any processes run in pane 0 (such as a human manually running orc finish, or the Orchestra agent doing so) will not have GH_REPO in their environment. This means orc finish's gh pr create will silently fall back to the unpinned cwd-derived behavior. The test didn't catch this because it checks pane 0.4 (the watcher pane), which is created by a later split-window command after the environment was updated.

2. lib/watch.sh: Log dedup masks a permanent stall state

File: lib/watch.sh (around lines 220 and 402)
Failure Scenario: If the watcher starts with GH_REPO unset, it logs a warning exactly once and sets the _MW_GH_REPO_WARNED/_RW_GH_REPO_WARNED flag. The warning says: "skipping GitHub polling until orchestrator.yaml's github_repo is configured".
However, since watch.sh only reads $GH_REPO from its environment (and never re-parses the YAML on the fly), configuring github_repo in orchestrator.yaml will do absolutely nothing until the tmux session is completely restarted. The user is misled by the log message into thinking the change will be picked up dynamically, and because of the dedup flag, the watcher will stay silently dead forever without further warnings. The log message should explicitly instruct the user to restart the session/room (just like orc-seed-merge-watch.sh's warning does).

Security Pass (Risky Diff: Watcher/Merge Paths)

I ran the dedicated security pass for changes touching watcher authority and push/merge paths.

  • Regex injection: The regex ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ correctly fails closed on any shell metacharacters or spaces because it enforces beginning/end anchors (^ and $). No unvalidated inputs can reach gh.
  • Target spoofing via YAML: Since orchestrator.yaml is not a protected path, an agent could theoretically change github_repo to an attacker-controlled repo. However, doing so would only make the watcher poll the attacker's repo for PRs and try to close issues on the attacker's repo. It would not leak capabilities against the host repo. orc finish would still push to the local .git/config's protected origin before failing to create the PR on the attacker's repo. So this does not introduce a privilege escalation.

1. bin/orc: GH_REPO now reaches pane 0. tmux new-session creates the
   session AND spawns pane 0's shell in the same step, so a
   `set-environment` call issued afterward updates the session's
   environment table too late for pane 0 -- only panes spawned by a
   later split-window picked it up (the existing test only ever
   checked one of those, pane 0.4, so it passed regardless). Pass
   `-e GH_REPO=...` directly on the `new-session` invocation instead,
   confirmed empirically to cover pane 0 as well as every later split
   pane. Wrapped the (possibly empty) -e args in the
   `${arr[@]+"${arr[@]}"}` idiom -- bash 3.2 (macOS's system bash, which
   these scripts run under) throws "unbound variable" on a plain
   `"${arr[@]}"` expansion of an empty array under `set -u`.

2. lib/watch.sh: reworded the once-per-watcher-start GH_REPO-unset log
   line in both merge_watch_check/review_watch_check. The old wording
   ("...until orchestrator.yaml's github_repo is configured") implied a
   live yaml edit alone would be picked up; these watchers only read
   GH_REPO from their own process env at session start and never
   re-parse the yaml, so a misconfigured room stayed silently dead
   forever once the dedup flag suppressed further warnings. Now says
   explicitly that a room restart ('orc up' again after killing the
   session) is required.

Tests: added a pane-0 GH_REPO check in tests/orc.test.sh (the exact gap
agy's review pointed at) and a message-content assertion in
tests/watch.test.sh for both watchers. Full suite green (33 files, 0
failures).
@immuhammad

Copy link
Copy Markdown
Owner Author

APPROVE

Probe List (Round 2):

  1. Edge-case correctness (bin/orc pane 0 bug): Checked the new -e injection on tmux new-session. Passing it via session_env_args using the ${arr[@]+"${arr[@]}"} idiom correctly avoids Bash 3.2 set -u unbound variable errors when the array is empty. This guarantees pane 0 receives GH_REPO in its environment at spawn time. The new test strictly asserts against pane 0 (0.0), successfully proving the fix.
  2. Failure modes (watch.sh dedup stall): Verified the log messages for both merge and review watchers. They now explicitly state that the room must be restarted ('orc up' again after killing the session) to pick up the GH_REPO change, completely resolving the misleading instruction that would otherwise lead to a permanent stall.

Both REQUEST-CHANGES findings are fully fixed. Excellent work.

@immuhammad
immuhammad marked this pull request as ready for review August 3, 2026 13:55
Copilot AI review requested due to automatic review settings August 3, 2026 13:55
@immuhammad
immuhammad merged commit 646437b into main Aug 3, 2026
1 check passed
@immuhammad
immuhammad deleted the feature/issue-174 branch August 3, 2026 13:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Implements Issue #174 by introducing a github_repo orchestrator.yaml scalar that is exported as GH_REPO, and then pinning scripted gh invocations to that repo (via --repo "$GH_REPO"), with watcher/seed paths failing closed when the repo is not configured.

Changes:

  • Add github_repo config plumbing (orc_github_repo, orc init render/round-trip, orc up export into tmux session env).
  • Pin watcher gh calls in lib/watch.sh and add fail-closed behavior when GH_REPO is unset (with once-per-process warnings).
  • Add/extend test coverage to assert fail-closed behavior and --repo pinning across watcher, seeding, and worktree flows.

Reviewed changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tests/watch.test.sh Sets a default GH_REPO for legacy tests; adds fail-closed + --repo pinning assertions.
tests/orc.test.sh Adds validation tests for orc_github_repo; asserts orc up propagates GH_REPO into tmux panes and warns when unset/invalid.
tests/orc-worktree.test.sh Verifies gh pr create is pinned when GH_REPO is set and unchanged when unset.
tests/orc-seed-merge-watch.test.sh Ensures seeding refuses to write state when GH_REPO is unset (avoids poisoning idempotent guard).
tests/orc-init.test.sh Ensures orc init renders github_repo from explicit answers and auto-derives from git origin when possible.
tests/orc-init-force.test.sh Ensures --force answers round-trip and re-derive behavior includes github_repo.
templates/orchestrator.yaml Documents new github_repo key and its operational effect on scripted gh calls.
orchestrator.yaml Sets github_repo for this repo.
lib/watch.sh Pins gh calls with --repo "$GH_REPO" and fails closed when unset (logs once per watcher start).
lib/orc-worktree.sh Adds optional --repo "$GH_REPO" pinning for gh pr create.
lib/orc-seed-merge-watch.sh Refuses to seed when GH_REPO is unset to keep seeding retryable.
lib/orc-config.sh Adds orc_github_repo reader/validator for github_repo.
bin/orc Exports GH_REPO from validated config into the tmux session environment (tmux new-session -e).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

Pin every scripted gh call to the configured repo (github_repo key, GH_REPO, fail closed)

2 participants