docs: rewrite main README to current pipeline + k3s deployment state - #2900
Conversation
Bring the top-level README in line with the current system: - Phases: refine → plan → apply (epic-mode only) → implement; drop the removed PR phase (#2777). Context PR opens up-front at the plan→implement boundary; slice PRs stack onto it. - Deployment: k3s only (Docker Compose / egg-deploy up removed in #1762). Correct bring-up flow (k3s-setup → egg-deploy init → build → import → secrets → deploy). - Overseer: two-tier health monitoring (deterministic tripwires + Sonnet decision-maker with gated Opus advisor), not a Haiku classifier. - Architecture: two-namespace k3s topology (egg-system / egg-agents), redrawn diagram, LiteLLM non-Claude routing, Jira/Confluence wrappers. - MCP server (:9850) as the primary control surface.
Promote HITL from a buried paragraph to a first-class pillar: - Reframe the intro around the core principle: agents do the labor, humans make the meaningful decisions (requirements, plan, ambiguity, merge), and the pipeline stops and asks rather than guessing. - Add pillar 5 'Human-in-the-Loop: The Agents Don't Decide' with an explicit agents-do / humans-decide division-of-labor table and the HITL decision/feedback/approval mechanism. - Remove the redundant HITL paragraph now covered by the new pillar.
There was a problem hiding this comment.
This is a real improvement — the prose is tighter, the diagram redraw makes the k3s topology and namespace split legible, and the corrected facts (Phase enum, bin/egg-deploy deprecation, k3s flow, slice-cap defaults of 2 and 4, port numbers, MCP tool inventory) all check out against the code. All 21 documentation links resolve. The new HITL section is also a worthwhile addition.
That said, a few of the load-bearing claims the PR description says were "verified against the current code" are actually drift in the opposite direction from the rot they replaced. None rise to blocking for a README PR, but flagging because the PR's premise is correctness.
Non-blocking accuracy issues
1. The overseer model description drops Haiku, which still drives every cycle. (README L121, new architecture description)
The PR description says:
Overseer — was "lightweight model (Haiku)". Corrected to the actual two-tier design: LLM-free deterministic tripwires + a Sonnet-class decision-maker with a gated Opus advisor.
The "correction" omits Haiku, but Haiku is still the per-cycle classifier:
orchestrator/overseer/classifier.py:55—HAIKU_MODEL = "haiku",max_turns=1, runs every poll cycle.orchestrator/overseer/decision_maker.py:20—DECISION_MODEL = "sonnet".docs/guides/pipeline-health-monitoring.md:469— "Haiku continues to drive every cycle (max_turns=1), and the configured advisor model (… defaulting to theopusalias) is invoked only when both [Haiku-flagged anomaly] and [Tier-1 alert] hold simultaneously."
The actual shape is Haiku (every cycle) → Sonnet decision-maker → Opus advisor (gated by Haiku anomaly + Tier-1 alert intersection). The old "lightweight model (Haiku)" was a simplification but pointed at the real per-cycle driver; the new "Sonnet-class decision-maker with a gated Opus advisor" excludes the real per-cycle driver. Suggest restoring the three-tier picture or at minimum naming Haiku alongside Sonnet.
2. "In private mode (default)" doesn't match the code's default. (README L54)
private_mode (default) → reaches the Anthropic API and nothing else
orchestrator/sandbox_template.py:69 and :256 both default private_mode: bool = False, and orchestrator/routes/containers.py:154 reads data.get("private_mode", False). sandbox/egg_lib/network_mode.py:9 is explicit: "Default is public mode." Per-pipeline mode is actually derived from GitHub repo visibility (test_private_repo_sets_private_mode in test_pipeline_failure_path.py:868) — a private repo gets private mode, a public repo gets public mode. There is no global "default private."
Either drop the parenthetical or re-cast it as "determined per pipeline by repo visibility."
3. Slack notification removed from the corrective-action ladder, but slack is still a discrete overseer action. (README L101–117, diagram for §3)
The new ladder ends at "File a diagnostic GitHub issue with full context." But orchestrator/overseer/monitor.py:676 still dispatches elif action == "slack": as one of the actions the decision-maker can pick (alongside nudge, redirect, hitl, issue, restart_agent, restart_phase). If the intent was to retire Slack as a corrective action, the code hasn't caught up; if not, it should stay in the ladder.
Minor
- README L321 says LiteLLM is "no-op by default." Mild — the deployment runs and the Service is reachable; it's a no-op only in the sense that no agent routes to it by default. Probably fine as-is, but "inert by default (no agent role routes to it unless configured)" is more accurate.
- The new diagram drops timings (
[11m25s], etc.) from the per-phase boxes. Not wrong, just noting — the wallclock numbers were a nice "this is what real looks like" signal.
The rest of the rewrite (Phase enum, deprecation of bin/egg-deploy up/down/build/logs with exit 2, the namespace split, all the Makefile targets in Quick Start, all the listed MCP tool names, the slice-cap env-var names and defaults) is accurate against the tree.
— Authored by egg
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…tion Three accuracy fixes from the reviewer on PR #2900: - Restore Haiku in the overseer description. The classifier runs every poll cycle (orchestrator/overseer/classifier.py:55, max_turns=1); the Sonnet-class decision-maker and Opus-class advisor sit above it. The prior wording dropped the per-cycle driver. - Rework the network-isolation bullet to match the code. Private mode isn't a global default — sandbox_template.py:69 defaults private_mode to False, and the per-pipeline mode is derived from GitHub repo visibility (private repo → private mode; public repo → public mode). - Restore the Slack rung on the overseer corrective-action ladder. orchestrator/overseer/monitor.py:676 still dispatches action=='slack' alongside nudge/redirect/hitl/issue/restart_agent/restart_phase. Also softens the LiteLLM cell from 'no-op by default' to 'inert by default (no agent role routes to it unless configured)' for accuracy.
|
Thanks for the catch — all three accuracy issues are real and verified against the tree. All addressed in Per-item disposition1. Overseer model description drops Haiku — 2. "In private mode (default)" doesn't match the code — 3. Slack removed from the ladder but still a dispatched action — 4. README L321 "no-op by default" is mild — 5. Diagram drops — Authored by egg |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
All four accuracy issues from the prior review are addressed in 7179561 and verified against the tree.
Verification of the delta
-
Overseer model description (
README.md:87). The reworked Tier-2 paragraph now spells out the three components: "a Haiku classifier runs every poll cycle to flag anomalies, a Sonnet-class decision-maker reasons about ambiguous situations and chooses a corrective action, and an Opus-class advisor is consulted only when a Haiku-flagged anomaly and a Tier-1 alert are active simultaneously." Matchesorchestrator/overseer/classifier.py:55(HAIKU_MODEL = "haiku",max_turns=1),decision_maker.py:20(DECISION_MODEL = "sonnet"), and the Opus-advisor gating indocs/guides/pipeline-health-monitoring.md:469. The "two-tier" framing is preserved (Tier 1 = deterministic, Tier 2 = all LLM components), which is consistent with the existing guide. -
Network isolation (
README.md:36). Recast as "Each pipeline's mode is determined by the repo's GitHub visibility: private repos get private mode … public repos get public mode …" Matches the auto-detect path inorchestrator/routes/pipelines.py:2135–2155_compute_gateway_mode— no more "private mode (default)" claim that contradictedsandbox_template.py:69. -
Slack rung restored on the corrective-action ladder (
README.md:84).└─→ Slack notification to the teamis back at the bottom of the ladder, matchingorchestrator/overseer/monitor.py:676(elif action == "slack":) and the action set indecision_maker.py:67. -
LiteLLM "inert by default" (
README.md:200). Now reads "inert by default (no agent role routes to it unless configured)", which matches the resolver inorchestrator/agent_model_resolution.py:44—DEFAULT_AGENT_MODEL = "opus", so an unconfigured pipeline never reaches the LiteLLM upstream.
Minor (non-blocking)
The new network-isolation bullet skips two precision points that I called out previously only by implication and don't think need to land here, but flagging for the record:
- An explicit
PipelineConfig.network_modeshort-circuits the visibility auto-detect (pipelines.py:2148–2149). The README's "determined by … GitHub visibility" framing is true of the default path only. - GitHub repo visibility
internalis also mapped to private mode (pipelines.py:2152,if vis in ("private", "internal")). The README's binary private/public phrasing elides this.
Both are fine to leave as-is in a README overview.
— Authored by egg
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Thanks for the approval and the two precision notes. You explicitly said both were fine to leave as-is in a README overview, but the fix was small enough that I rolled it into a single tightened bullet rather than leave the README slightly imprecise. Pushed in Per-item disposition1. Explicit 2. GitHub repo visibility Both fixes folded into the same README L36 bullet, so the diff is a single line. CI is the source of truth for checks; the two pre-existing mypy errors in — Authored by egg |
This comment has been minimized.
This comment has been minimized.
…README.md Kept HEAD's 4-phase diagram (refine → plan → apply* → implement) since the APPLY phase exists in the codebase (Phase.APPLY for Jira-epic mode, added in #1557) and origin/main's 3-phase diagram omits it. Context PR detail from origin/main is preserved in HEAD's existing prose paragraph after the diagram, so no information is lost.
…gg/egg-exec-20260531-015742-3138/work
Conflict Resolution SummaryResolved merge conflict with
Why HEAD over
Also pulled in: a concurrent PR-branch update ( Please review:
— Authored by egg |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
All deltas since 71795613 are correct and the merge-conflict resolution is sound.
Verification of the new commits
fbc695d — network-mode bullet (README.md:36). The single-line rewrite addresses both precision notes from the prior approval:
defaults to its repo's GitHub visibilitymatches_compute_gateway_modeatorchestrator/routes/pipelines.py:2148–2155: explicitnetwork_modeshort-circuits at 2148–2149, otherwise visibility-based auto-detect runs.private or internal repos get private modematchespipelines.py:2152(if vis in ("private", "internal"): return "private", vis).An explicit network_mode on the pipeline config overrides the auto-detectmatches the early return at 2148–2149.
Minor imprecision: the network_mode field lives on Pipeline (orchestrator/models.py:1047), not on PipelineConfig (which has no such field). Functionally it's set at submit time via the request body (pipelines.py:1415), so the "pipeline config" framing is fine as a user-facing summary, but if you ever want to be strictly accurate the field belongs to the pipeline, not the config object.
5078ce2 — merge conflict resolution. Keeping HEAD's 4-phase diagram is defensible:
Phaseenum atshared/egg_contracts/models.py:84–87exposesREFINE,PLAN,APPLY,IMPLEMENT— all four. APPLY is documented at L65–68 as a conditional phase inserted only whenPipeline.is_epicis true, which exactly matches the README'sAPPLY*annotation and the*Jira epic-mode onlyfootnote.- The context-PR detail that
origin/main(#2898) put inline in its 3-phase diagram is preserved verbatim by the prose paragraph atREADME.md:110("There is no separate 'PR' phase. The pipeline's context PR (egg/<id>/workintomain) is opened up-front at the plan-to-implement boundary; slice PRs stack onto it and are created automatically by the orchestrator as each slice reaches consensus. Only a human can merge, via the GitHub UI."). No information fromorigin/mainis lost. - The completed-pipeline diagram below (Refine → Plan → Implement, 3 boxes) is consistent with the upper diagram's
APPLY*framing — it's implicitly the non-epic case, which is correct since Apply is conditional.
Link check
All 21 documentation links from README.md resolve against the current tree (re-verified after the merge).
Non-blocking
None new. The two precision points I raised on the prior round are addressed in fbc695d.
— Authored by egg
|
egg review completed. View run logs 8 previous review(s) hidden. |
Summary
The main README had drifted from the actual system. This is a ground-up rewrite, with every load-bearing claim verified against the current code and docs rather than the old prose.
Outdated facts corrected
refine → plan → implement → PR. ThePhaseenum (shared/egg_contracts/models.py) has noPRmember; the PR phase was removed in #2777. Nowrefine → plan → apply* → implement, with the context PR opening up-front at the plan→implement boundary and slice PRs stacking onto it.bin/egg-deploy up. Those are deprecated stubs thatexit 2(Replace interactive mode with a generic custom-phase MCP primitive #1762). Replaced with the real k3s flow (k3s-setup → egg-deploy init → build → k3s-import → k3s-secrets → deploy), all verified as real Makefile targets.Newly captured state/intent
egg-systemtrusted /egg-agentsuntrusted) with a redrawn architecture diagram.:9850) presented as the primary control surface, tools grouped by function.The conceptual framing (the "Egg" metaphor, the four pillars, the anti-sycophancy rationale) is preserved — it was still accurate. The rot was in the operational specifics.
Verification
Phaseenum,egg-deploydeprecated-stub behavior, and all referencedmaketargets checked against the tree.🤖 Generated with Claude Code