Skip to content

[issue-3393][slice-2/6] List-shaped submission + uniform... - #3423

Merged
jwbron merged 7 commits into
mainfrom
egg/issue-3393/slice-2
Jul 2, 2026
Merged

[issue-3393][slice-2/6] List-shaped submission + uniform...#3423
jwbron merged 7 commits into
mainfrom
egg/issue-3393/slice-2

Conversation

@james-in-a-box

@james-in-a-box james-in-a-box Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Make submission genuinely list-shaped end to end and enforce the two uniformity rules. submit_task and POST /api/v1/pipelines accept a list of {repo, base_branch}; a bare single repo stays accepted (back-compat). Submission-time validation rejects mixed-visibility sets and mixed-auth-mode sets with actionable errors (reusing get_repo_visibility and per-repo get_auth_mode). Same-name repo sets are NOT rejected (operator ruling #6). One repo is designated primary (first unless flagged) for naming and slice-default.

Base PR: #3418

What's in this PR

Commits (6):

.egg-state/agent-outputs/coder/brc-memory-issue-3393.md |   83 +
 .egg-state/brc-history/3393-implement-slice-2.json      | 2686 ++++++++++++++++++++++++++++++++
 .egg-state/brc-history/3393-implement-slice-2.md        | 2857 +++++++++++++++++++++++++++++++++++
 config/repo_config.py                                   |   33 +
 gateway/repo_visibility.py                              |   84 +
 gateway/tests/test_repo_visibility.py                   |  150 ++
 orchestrator/mcp_tools/_submit.py                       |   58 +-
 orchestrator/mcp_tools/_tool_defs.py                    |   38 +-
 orchestrator/routes/pipelines.py                        |  204 +++
 orchestrator/state_store/_crud.py                       |   20 +-
 orchestrator/tests/test_pipelines.py                    |  263 ++++
 11 files changed, 6470 insertions(+), 6 deletions(-)

This slice

List-shaped submission + uniform visibility/auth validation

Files affected:

  • orchestrator/mcp_tools/_submit.py
  • orchestrator/routes/pipelines.py
  • gateway/repo_visibility.py
  • gateway/git_client/_credentials.py
  • orchestrator/tests/test_pipelines.py
  • gateway/tests/test_repo_visibility.py
Tasks (3) + acceptance criteria
  • task-2-1: Extend the submission surface to accept a repo list. In orchestrator/mcp_tools/_submit.py (submit_task, currently a single repo + base_branch at :78-79): accept either a single repo/base_branch (back-compat) or a list of {repo, base_branch} entries; normalize to the list-shaped Pipeline repo set from slice 1 with the first entry (or an explicitly flagged one) as primary. In orchestrator/routes/pipelines.py: thread the repo list through the POST /api/v1/pipelines handler and pipeline construction so the full list reaches Pipeline; do not collapse to a single repo. Do not add the uniformity validators here (TASK-2-2) and do not touch the three collapse sites (slice 3).
    • Acceptance criteria: - submit_task accepts a list of {repo, base_branch}; a bare single repo still works unchanged. - The pipelines route constructs a Pipeline with the full repo list (per-repo base_branch), primary = first/flagged. - No collapse to repos[0] is introduced in the submission path.
  • task-2-2: Add submission-time uniformity validation. Reuse gateway/repo_visibility.py get_repo_visibility(owner, repo) to require all repos in a run to be uniformly private or uniformly public, and gateway/git_client/_credentials.py get_auth_mode(repo) to require a single uniform auth mode across the run. On a mixed set, reject the submission with an actionable error naming the offending repos and which dimension (visibility vs auth) diverged. Do NOT reject same-name repo sets — the collision is resolved by the owner/repo re-key in slice 3 (operator ruling Phase 4: CLI implementation #6). Add small, focused helper functions (e.g. assert_uniform_visibility, assert_uniform_auth) on the gateway modules where the per-repo lookups live, and call them from the submission path in orchestrator/routes/pipelines.py.
    • Acceptance criteria: - A mixed-visibility repo set is rejected with an actionable, repo-naming error. - A mixed-auth-mode repo set is rejected with an actionable error. - Same-name repo sets are NOT rejected. - Uniform sets pass; single-repo submissions are trivially uniform.
  • task-2-3: Add tests for slice 2 in orchestrator/tests (submission) and gateway/tests (uniformity helpers): list submission accepted and constructs the full repo list; bare single-repo submission still accepted; mixed-visibility set rejected with the expected error; mixed-auth-mode set rejected; same-name-different-owner set NOT rejected; primary-repo defaulting to first/flagged. Include the N=1 regression path.
    • Acceptance criteria: - Tests cover list + single-repo submission, both uniformity rejections, the same-name-allowed case, and primary defaulting. - N=1 submission behavior is asserted unchanged. - make test (narrowed) and make test-all green.

Stack

egg and others added 7 commits July 2, 2026 04:50
List-shaped submission outcomes (multi-repo list fidelity, same-name/
different-owner distinctness, per-repo base_branch, primary defaulting,
N=1 back-compat) asserted green at the model layer. Coder-dependent
behavior (repos-list forwarding in _handle_submit_task; the
validate_visibility_uniformity / validate_auth_mode_uniformity gateway
helpers) is authored and skip-guarded pending the parallel coder's
slice-2 integration, activating at convergence. Interface handed to the
coder via task-2-1/task-2-2 coverage gaps.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…idation

task-2-1 (list-shaped submission): submit_task (mcp_tools/_tool_defs.py,
_submit.py) accepts a 'repos' list of {repo, base_branch, primary?} in addition
to the single 'repo' (back-compat); handler normalizes canonically primary-first
and mirrors the primary onto the legacy repo/base_branch scalars; required
relaxed to [description]. POST /api/v1/pipelines (routes/pipelines.py) threads
the full list through via _normalize_submission_repos and constructs the
Pipeline with repos: list[RepoSpec] (no repos[0] collapse). state_store.
create_pipeline gains an optional 'repos' param onto Pipeline.repos; N=1 stays
byte-for-byte unchanged (repos=None => slice-1 validator synthesizes from the
singleton).

task-2-2 (uniform visibility/auth): _assert_repo_set_uniform rejects mixed-
visibility or mixed-auth repo sets at submission with an actionable, repo-naming
400; single repo is trivially uniform (no gateway round-trip). assert_uniform_auth
added to config/repo_config.py (canonical home of get_auth_mode, bundled into
both images) and imported by the orchestrator; visibility resolved via
GatewayClient.get_repo_visibility (mirrors _compute_gateway_mode). Same-short-
name-different-owner repos are NOT rejected.

Runtime-boundary deviation: the orchestrator image ships config/repo_config.py
but NOT gateway/, so the uniformity guards live where the submission path can
actually reach them (auth in repo_config, visibility inline via HTTP
GatewayClient) rather than as dead helpers in gateway modules. Behavioral
acceptance met in full; flagged for reviewer_contract.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Distilled slice-2 change model + the runtime-boundary deviation rationale so
one-shot re-spawns stay consistent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ester task-2-3)

Add validate_visibility_uniformity + validate_auth_mode_uniformity to
gateway/repo_visibility.py matching the exact interface the tester's task-2-3
tests expect (gateway/tests/test_repo_visibility.py + orchestrator/tests/
test_pipelines.py): raise ValueError naming offenders on a mixed set; internal
shares the private posture; same-name/different-owner NOT rejected; single/
uniform is a no-op. validate_auth_mode_uniformity delegates to
config/repo_config.py assert_uniform_auth so the auth rule has one source of
truth. The orchestrator's submission-time _assert_repo_set_uniform is documented
as the HTTP-boundary twin of validate_visibility_uniformity (the orchestrator
image does not ship gateway/, so it mirrors the check via GatewayClient).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…curity v1)

Address reviewer_security NACK: the visibility uniformity check silently dropped
a repo from the vote when its visibility resolved to None (if vis is None:
continue), which could ADMIT a genuinely-mixed private+public multi-repo set
whenever a secondary momentarily failed to resolve — the exact leak vector the
control blocks, with no downstream re-check (_compute_gateway_mode reads only the
primary repo).

Fix in both twins (orchestrator _assert_repo_set_uniform and gateway
validate_visibility_uniformity): for a multi-repo set, a repo whose visibility is
not a known public|private|internal bucket (None OR unrecognized label) now FAILS
CLOSED with an actionable, repo-naming rejection instead of being excluded from
the vote. N=1 short-circuits before any lookup (the gateway helper now also
short-circuits len<=1), so the common case pays nothing. The auth check's
config-read exception path is likewise made fail-closed for consistency.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jwbron
jwbron changed the base branch from egg/issue-3393/slice-1 to main July 2, 2026 20:56
@jwbron
jwbron merged commit 0a0eab9 into main Jul 2, 2026
26 of 31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant