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
1 change: 1 addition & 0 deletions docs/architecture/orchestrator.md
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,7 @@ if is_orchestrator_mode():
| `EGG_ORCH_SLICE_GLOBAL_MAX_CYCLES` | Slice-DAG: pipeline-wide summed slice-cycle cap (#2137) | `10` |
| `EGG_ORCH_SLICE_FAILURE_GRACE_SECONDS` | Slice-DAG: grace window before failure-cascade marks downstream subtree `BLOCKED_ON_FAILED_DEPENDENCY` (#2137) | `60.0` |
| `EGG_ORCH_STACKED_PR_RECONCILER_INTERVAL_SECONDS` | Slice-DAG: stacked-PR reconciler polling cadence for orphaned child PRs (#2137) | `30.0` |
| `EGG_ORCH_CROSS_REPO_MERGE_GATE_MAX_ATTEMPTS` | Slice-DAG: poll-attempt budget for the cross-repo merge-sequencing gate before a never-merging upstream PR escalates the dependent draft PR to a HITL hold (#3393); rides the stacked-PR reconciler's cadence | `240` |
| `EGG_BRC_EVENT_PUMP` | **Removed** ([#2908](https://github.com/jwbron/egg/issues/2908)). This flag once selected a legacy capped-restart consensus wrapper vs. the event-pump wrapper; the legacy template and the env-var read are both gone, so the orchestrator no longer consults this variable. Operators that referenced it in helm values / pod-spec env can drop the row. | n/a (removed) |
| `EGG_BRC_IDLE_BUDGET_MIN` | BRC idle / no-progress safety budget in minutes ([#2908](https://github.com/jwbron/egg/issues/2908)). The orchestrator event loop's convergence-stall check raises an overseer alert (anomaly `stuck-phase-transition`, priority `high`) at the budget threshold and escalates priority at `2 ×` budget, without transitioning the pipeline to FAILED. Default 30 min is well above the WS7-observed 10–13 min idle ceiling on real BRC phases. Read via `event_loop.get_idle_budget_minutes()` — see [Idle / no-progress safety budget](#idle--no-progress-safety-budget). | `30` |
| `EGG_EVENT_LOOP_OWNER` | **Removed** ([#3164](https://github.com/jwbron/egg/issues/3164)). This flag once selected an in-pod wait-loop vs. the orchestrator-owned BRC event loop; the in-pod wait arm is gone and orchestrator ownership is the only mode, so the variable is no longer read (`get_event_loop_owner` is removed from `orchestrator/env_config.py`). Operators that set it in helm values / pod-spec env can drop the row. | n/a (removed) |
Expand Down
34 changes: 22 additions & 12 deletions docs/architecture/slice-dag.md
Original file line number Diff line number Diff line change
Expand Up @@ -823,23 +823,32 @@ stacked-PR reconciler cadence.

- **Tier A — automated merge-state hold (default).** The dependent slice's PR
opens as a **draft** while the upstream PR is unmerged. A bounded poll watches
the upstream PR's merge state and, on merge, auto-marks the dependent PR ready
via the `mark_pr_ready(repo, pr_number)` gateway verb (wrapping `gh pr
ready`). **Merge detection keys off the PR `mergedAt` / merged boolean, not
head-SHA equality** — a squash or rebase merge produces a merge-commit SHA ≠
the PR head, so SHA-equality would misfire. Two failure terminals fall through
to a HITL hold rather than hanging: an upstream that reaches
**CLOSED-not-merged**, and a poll that exceeds its **attempt bound** (a
never-merging upstream). Both surface on pipeline status.
the upstream PR's merge state via the orchestrator-only gateway routes
`POST /api/v1/gh/pr/merge_state` (read) and `POST /api/v1/gh/pr/ready` (write)
— see [Gateway README](../../gateway/README.md) — and, on merge, auto-marks
the dependent PR ready via the `mark_pr_ready(repo, pr_number)` gateway verb
(wrapping `gh pr ready`). **Merge detection keys off the PR `mergedAt` /
merged boolean, not head-SHA equality** — a squash or rebase merge produces a
merge-commit SHA ≠ the PR head, so SHA-equality would misfire. Two failure
terminals fall through to a HITL hold rather than hanging: an upstream that
reaches **CLOSED-not-merged**, and a poll that exceeds its **attempt bound**
(`EGG_ORCH_CROSS_REPO_MERGE_GATE_MAX_ATTEMPTS`, default 240 ticks, ~2h at the
default 30s reconciler cadence — a never-merging upstream). Both surface on
pipeline status.
- **Tier B — HITL beyond-merge-state hold (opt-in).** For an edge the plan (or
task description) marks with a beyond-merge-state condition — a
release/publish of the upstream repo, a version-pin choice, or a genuine
cannot-continue development block — the dependent PR is held and released
**only by a HITL decision**, never by programmatic detection. Absent that
marker, a cross-repo edge defaults to the Tier-A automated hold.
cannot-continue development block — the dependent slice opts in via the
`[hold:beyond-merge-state]` marker in its `goal` (or a task description); the
dependent PR is then held and released **only by a HITL decision**, never by
programmatic detection. Absent that marker, a cross-repo edge defaults to the
Tier-A automated hold.

All HITL holds (Tier B, plus the two Tier-A failure terminals) route through the
same decision-queue mechanism and share a single release path.
same decision-queue mechanism and share a single release path — each registers a
HITL Decision offering two operator-selectable options: release the hold (marks
the PR ready) or keep it held (terminal; the PR stays draft for manual
handling).

### Per-repo gate, diff & convention scoping

Expand Down Expand Up @@ -958,6 +967,7 @@ on parse failure. The green-gate knobs below are read directly via
| `EGG_ORCH_SLICE_GLOBAL_MAX_CYCLES` | int | 10 | Pipeline-wide summed slice-cycle cap. *Currently inert — see local cycles row.* |
| `EGG_ORCH_SLICE_FAILURE_GRACE_SECONDS` | float | 60.0 | Grace window before a failure cascade marks the downstream subtree `BLOCKED_ON_FAILED_DEPENDENCY`. |
| `EGG_ORCH_STACKED_PR_RECONCILER_INTERVAL_SECONDS` | float | 30.0 | Reconciler polling cadence for orphaned child PRs. |
| `EGG_ORCH_CROSS_REPO_MERGE_GATE_MAX_ATTEMPTS` | int | 240 | Poll-attempt budget for the cross-repo merge-sequencing gate (#3393) before a never-merging upstream escalates to a HITL hold; ~2h at the default reconciler cadence. See [Cross-repo merge-sequencing hold](#cross-repo-merge-sequencing-hold-two-tier). |
| `EGG_SLICE_GREEN_GATE` | str | `off` | Per-slice green gate rollout switch (#3398): `off` skips the gate entirely; `log` runs the repo's configured checks at the slice tip and logs a red verdict without blocking; `on` blocks slice PR-open on a red verdict. Case-insensitive, with aliases — `on` also accepts `1`/`true`/`yes`, and `log` also accepts `log-only`/`log_only`. Unknown values resolve to `off`. |
| `EGG_SLICE_GREEN_GATE_SKIP_CHECKS` | str (comma-separated) | `security` | Configured check *names* (from `repositories.yaml` `checks`) the gate skips. |
| `EGG_SLICE_GREEN_GATE_TIMEOUT_SECONDS` | int | 1800 | Wall-clock budget for the check-runner pod (spawn-to-terminal); a hung suite degrades to fail-open rather than wedging the slice close. |
Expand Down
1 change: 1 addition & 0 deletions docs/development/STRUCTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ orchestrator/
├── concurrent_executor.py # Concurrent phase executor (spawns all agents simultaneously)
├── slice_scheduler.py # Wave-based scheduler for the implement-phase slice DAG: computes execution waves, caps concurrency, two-tier max_cycles accounting, failure-cascade detection (#2137)
├── stacked_pr_reconciler.py # Stacked-PR rebase reconciler: detects child slice PRs whose base branch was deleted after a parent merge and retargets them via gateway rebase_onto (#2137)
├── cross_repo_merge_gate.py # Cross-repo merge-sequencing gate for multi-repo pipelines: auto-readies (or HITL-holds) a dependent slice's draft PR once its cross-repo upstream PR merges; rides the stacked-PR reconciler cadence (#3393 slice-5)
├── slice_green_gate.py # Per-slice green gate: sandboxed one-shot Job runs the repo's configured checks at the integration-branch tip and blocks PR-open on red; staged rollout via EGG_SLICE_GREEN_GATE (off/log/on), fail-open on infra errors (#3398)
├── action_guards.py # Formal BRC state machine action guards (preconditions for propose/ack/nack/confirm/withdraw)
├── approval_matrix.py # Per-reviewer ACK/NACK matrix for BRC consensus
Expand Down
1 change: 1 addition & 0 deletions docs/reference/orchestrator-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ Agent role can be omitted when `EGG_AGENT_ROLE` is set.
| `EGG_ORCH_SLICE_GLOBAL_MAX_CYCLES` | Pipeline-wide cap on the summed total of slice re-proposal cycles. Default `10`. Either the local or global cap tripping escalates to HITL. *API live, not yet wired in the run loop — see [Slice-DAG Implement Phase](../architecture/slice-dag.md); #2199.* |
| `EGG_ORCH_SLICE_FAILURE_GRACE_SECONDS` | Grace window (seconds) between a slice failure and the orchestrator marking the downstream subtree `BLOCKED_ON_FAILED_DEPENDENCY`. Default `60`. Allows HITL resolution before the cascade fires. |
| `EGG_ORCH_STACKED_PR_RECONCILER_INTERVAL_SECONDS` | Polling cadence (seconds) of the stacked-PR reconciler that detects child slice PRs whose base branch was deleted after a parent merge. Default `30`. |
| `EGG_ORCH_CROSS_REPO_MERGE_GATE_MAX_ATTEMPTS` | Poll-attempt budget for the cross-repo merge-sequencing gate (#3393), which rides the stacked-PR reconciler's cadence. A never-merging upstream PR that exceeds this many reconcile ticks escalates the dependent draft PR to a HITL hold instead of waiting forever. Default `240` (~2h at the default 30s reconciler interval). See [Slice-DAG Implement Phase](../architecture/slice-dag.md). |
| `AGENT_ANCHOR_ID` | Agent anchor ID (`{role}-{short_container_id}`), auto-set by container spawner |
| `EGG_LIFECYCLE_SECRET` | Bearer token required for lifecycle-control endpoints (HITL resolve/cancel, pipeline CRUD, phase overrides, container spawn/stop). Stored at `~/.config/egg/lifecycle-secret`. Must be exported in the human's shell to run `egg-orch decision resolve`, `egg-orch pipeline delete`, etc. Agent pods never receive it (see #1769). |

Expand Down
16 changes: 16 additions & 0 deletions gateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,22 @@ POST /api/v1/gh/pr/close
Request: {repo, pr_number}
Policy: pr_ownership

POST /api/v1/gh/pr/merge_state
Request: {repo, pr_number}
Auth: Bearer {launcher_secret}
Description: Orchestrator-only read of a PR's merge state ({state, mergedAt}).
Powers the cross-repo merge-sequencing gate (#3393): the
orchestrator polls an upstream slice PR to decide when to
mark a downstream draft PR ready. Keys off mergedAt/state,
not head-SHA equality (a squash/rebase merge changes the SHA).

POST /api/v1/gh/pr/ready
Request: {repo, pr_number}
Auth: Bearer {launcher_secret}
Description: Orchestrator-only draft→ready transition (wraps `gh pr ready`).
Write half of the cross-repo merge-sequencing gate (#3393):
called when the upstream PR merges.

POST /api/v1/gh/execute
Request: {args[], require_auth}
Policy: deny-by-default allowlist (parity with /api/v1/git/execute).
Expand Down
Loading