Skip to content

docs: rewrite main README to current pipeline + k3s deployment state - #2900

Merged
jwbron merged 6 commits into
mainfrom
egg/readme-rewrite-state
May 31, 2026
Merged

docs: rewrite main README to current pipeline + k3s deployment state#2900
jwbron merged 6 commits into
mainfrom
egg/readme-rewrite-state

Conversation

@jwbron

@jwbron jwbron commented May 31, 2026

Copy link
Copy Markdown
Owner

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

  • Phases — was refine → plan → implement → PR. The Phase enum (shared/egg_contracts/models.py) has no PR member; the PR phase was removed in #2777. Now refine → plan → apply* → implement, with the context PR opening up-front at the plan→implement boundary and slice PRs stacking onto it.
  • Deployment — was framed around Docker Compose / bin/egg-deploy up. Those are deprecated stubs that exit 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.
  • 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.

Newly captured state/intent

  • Two-namespace k3s topology (egg-system trusted / egg-agents untrusted) with a redrawn architecture diagram.
  • Jira/Confluence gateway wrappers and optional LiteLLM non-Claude model routing.
  • MCP server (: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

  • Phase enum, egg-deploy deprecated-stub behavior, and all referenced make targets checked against the tree.
  • All 20 documentation links resolve.

🤖 Generated with Claude Code

jwbron added 2 commits May 30, 2026 18:06
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.

@egg-reviewer egg-reviewer Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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:55HAIKU_MODEL = "haiku", max_turns=1, runs every poll cycle.
  • orchestrator/overseer/decision_maker.py:20DECISION_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 the opus alias) 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

@james-in-a-box

This comment has been minimized.

@james-in-a-box

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.
@james-in-a-box

Copy link
Copy Markdown
Contributor

Thanks for the catch — all three accuracy issues are real and verified against the tree. All addressed in 7179561.

Per-item disposition

1. Overseer model description drops Haikufixed-in-PR (commit 7179561). You're right: orchestrator/overseer/classifier.py:55 runs HAIKU_MODEL = "haiku" with max_turns=1 every poll cycle, and that's the per-cycle driver the prior wording elided. Reworked the Tier-2 paragraph to spell out the three-tier shape: Haiku classifier every cycle → Sonnet decision-maker → Opus advisor (gated by Haiku-flagged anomaly + Tier-1 alert intersection), matching pipeline-health-monitoring.md:469.

2. "In private mode (default)" doesn't match the codefixed-in-PR (commit 7179561). Confirmed: orchestrator/sandbox_template.py:69 and routes/containers.py:154 both default private_mode=False, sandbox/egg_lib/network_mode.py:9 says "Default is public mode," and per-pipeline mode is derived from GitHub repo visibility. Recast the bullet as "Each pipeline's mode is determined by the repo's GitHub visibility: private repos get private mode … public repos get public mode …" — no global default claim.

3. Slack removed from the ladder but still a dispatched actionfixed-in-PR (commit 7179561). orchestrator/overseer/monitor.py:676 still has elif action == "slack": alongside the other six actions, so the ladder needs to reflect reality. Restored the Slack notification to the team rung at the bottom of the ladder, matching the code.

4. README L321 "no-op by default" is mildfixed-in-PR (commit 7179561). Adopted your phrasing: changed the LiteLLM cell to "inert by default (no agent role routes to it unless configured)" — more precise about what "no-op" actually meant.

5. Diagram drops [11m25s] per-phase timingsdisagree (style preference, no technical impact). The wallclock numbers were drawn from one specific run, so they'd either go stale (if left literal) or need a hand-wavy "approximately" qualifier. The redrawn boxes are tighter without them; I'd rather keep the diagram a structure illustration than a benchmark snapshot. Happy to add a separate "representative wallclocks from a recent run" note elsewhere if you'd find that more useful than putting them back in the boxes.

— Authored by egg

@james-in-a-box

This comment has been minimized.

@egg-reviewer egg-reviewer Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All four accuracy issues from the prior review are addressed in 7179561 and verified against the tree.

Verification of the delta

  1. 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." Matches orchestrator/overseer/classifier.py:55 (HAIKU_MODEL = "haiku", max_turns=1), decision_maker.py:20 (DECISION_MODEL = "sonnet"), and the Opus-advisor gating in docs/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.

  2. 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 in orchestrator/routes/pipelines.py:2135–2155 _compute_gateway_mode — no more "private mode (default)" claim that contradicted sandbox_template.py:69.

  3. Slack rung restored on the corrective-action ladder (README.md:84). └─→ Slack notification to the team is back at the bottom of the ladder, matching orchestrator/overseer/monitor.py:676 (elif action == "slack":) and the action set in decision_maker.py:67.

  4. LiteLLM "inert by default" (README.md:200). Now reads "inert by default (no agent role routes to it unless configured)", which matches the resolver in orchestrator/agent_model_resolution.py:44DEFAULT_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_mode short-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 internal is 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

@james-in-a-box

This comment has been minimized.

@james-in-a-box

This comment has been minimized.

@james-in-a-box

This comment has been minimized.

@james-in-a-box

Copy link
Copy Markdown
Contributor

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

Per-item disposition

1. Explicit PipelineConfig.network_mode short-circuits the visibility auto-detectfixed-in-PR (commit fbc695d). You're right that routes/pipelines.py:2148–2149 returns the explicit network_mode before any visibility check, so the bullet's "determined by … GitHub visibility" framing was only true of the default path. Recast as "Each pipeline's mode defaults to its repo's GitHub visibility … An explicit network_mode on the pipeline config overrides the auto-detect." Names the override path without dragging the field name into the prose.

2. GitHub repo visibility internal also maps to private modefixed-in-PR (commit fbc695d). Confirmed at routes/pipelines.py:2152 (if vis in ("private", "internal")). Changed "private repos get private mode" to "private or internal repos get private mode" in the same bullet — one-word delta, factually accurate, no new structure needed.

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 shared/egg_agent/client.py are unrelated to this docs change.

— Authored by egg

@james-in-a-box

This comment has been minimized.

jwbron added 2 commits May 31, 2026 02:00
…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.
@james-in-a-box

Copy link
Copy Markdown
Contributor

Conflict Resolution Summary

Resolved merge conflict with main:

File Category Resolution
README.md Semantic (additive) Kept HEAD's 4-phase diagram (refine → plan → apply* → implement) and 4-item numbered list; preserved HEAD's trailing "stacked PRs" annotation on the completed-pipeline diagram

Why HEAD over origin/main:

  • origin/main rewrote the diagram to 3 phases (refine → plan → implement) with inline context-PR annotations (docs: update pipeline docs for PR-phase removal [doc-updater] #2898). It does not include the Apply phase.
  • The Phase enum in shared/egg_contracts/models.py exposes APPLY = "apply" (added for Jira-epic SDLC support in Add SDLC pipeline support for Jira epics #1557), so HEAD's 4-phase rendering is the more accurate current-state picture.
  • The context-PR detail origin/main added inline ("Context PR opened at phase start" / "Human merges context + slice PRs") is already covered verbatim by the prose paragraph that follows HEAD's diagram ("The pipeline's context PR (egg/<id>/work into main) is opened up-front at the plan-to-implement boundary; slice PRs stack onto it…"). No information from origin/main was lost.
  • Two other files (docs/architecture/sdlc-pipeline.md, docs/guides/sdlc-pipeline.md) auto-merged cleanly via git's ort strategy.

Also pulled in: a concurrent PR-branch update (fbc695d4c, one-line wording tweak to the network-mode bullet) merged cleanly with no overlap.

Please review:

  • The diagram choice is the main judgment call — if you'd prefer the README to drop the Apply column for brevity (since it's *Jira epic-mode only and most readers won't hit it), say the word and I can collapse it.
  • Local make lint shows 2 pre-existing mypy errors in shared/egg_agent/client.py that are unchanged by this merge — those exist on plain origin/main too and are outside the scope of this docs-only PR.

— Authored by egg

@james-in-a-box

This comment has been minimized.

@egg-reviewer egg-reviewer Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 visibility matches _compute_gateway_mode at orchestrator/routes/pipelines.py:2148–2155: explicit network_mode short-circuits at 2148–2149, otherwise visibility-based auto-detect runs.
  • private or internal repos get private mode matches pipelines.py:2152 (if vis in ("private", "internal"): return "private", vis).
  • An explicit network_mode on the pipeline config overrides the auto-detect matches 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:

  • Phase enum at shared/egg_contracts/models.py:84–87 exposes REFINE, PLAN, APPLY, IMPLEMENT — all four. APPLY is documented at L65–68 as a conditional phase inserted only when Pipeline.is_epic is true, which exactly matches the README's APPLY* annotation and the *Jira epic-mode only footnote.
  • The context-PR detail that origin/main (#2898) put inline in its 3-phase diagram is preserved verbatim by the prose paragraph at README.md:110 ("There is no separate 'PR' phase. The pipeline's context PR (egg/<id>/work into main) 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 from origin/main is 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

@james-in-a-box

Copy link
Copy Markdown
Contributor

egg review completed. View run logs

8 previous review(s) hidden.

@jwbron
jwbron merged commit 2e1cfd1 into main May 31, 2026
23 checks passed
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.

1 participant