* feat(reviewer): explicit-request verdicts + shell verdict guard
Mention-triggered reviews that explicitly ask for a verdict now submit a
real APPROVE/REQUEST_CHANGES through publish_review; auto-reviews stay
advisory (COMMENT). Authorization is enforced in code: publish_review
honors a verdict only when the dispatching webhook set verdict_requested,
which only the explicit-mention path does.
- request_pr_review gains instructions (forwarded verbatim into an escaped
requester_instructions data block) and request_verdict
- self-review guard downgrades verdicts on Open SWE-authored PRs; stale
APPROVEs are best-effort dismissed when later findings land
- new PullRequestVerdictGuardMiddleware blocks gh pr review
--approve/-a/--request-changes/-r, gh api, and curl verdict fallbacks on
both the coding-agent and reviewer graphs
- shared escape helper moved to agent/utils/prompt_data.py
* fix(reviewer): harden verdict path against security-review findings
Adversarial security review (detector fan-out + proof-or-kill verifier)
of the verdict feature surfaced several verdict-integrity gaps; resolve
the confirmed ones:
- head-drift (high): a mid-run push moves the resolved head, so an APPROVE
could anchor to an unreviewed commit. Downgrade any verdict to a comment
when the resolved head differs from the reviewed head (verdict_ignored
reason head_moved); the push's own re-review submits a fresh verdict.
- self-review fail-open: downgrade to comment when the PR author cannot be
confirmed (author_unknown), and compare bot logins case-insensitively.
- verdict_submitted now reflects GitHub's returned review state, not just
the event we asked for, so a coerced APPROVE isn't reported as submitted.
- an authorized verdict whose findings all anchor outside the diff now
posts as a bodied review with zero inline comments instead of failing.
- add finding_reply to the shared data-block escape tag superset.
Cross-family review (GPT-4.1) FIX item on the #1736 port: prove the
warn-and-drop path for unprincipaled user tokens leaves the cached bot
token reachable.
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
(cherry picked from commit 1ea0e600dcc234fa5a333c6f4b80b90e2e6679d3)
Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
* feat: optional separate LangSmith key/endpoint for sandboxes
Adds optional SANDBOX_LANGSMITH_API_KEY / SANDBOX_LANGSMITH_ENDPOINT env
overrides so sandboxes can run against a different LangSmith workspace than
the one used for tracing and other API calls. Both fall back to the existing
LANGSMITH_API_KEY / LANGSMITH_ENDPOINT resolution, so default behavior is
unchanged.
Applied to sandbox create/connect/delete, the GitHub proxy config, and repo
snapshot builds.
* feat: name langsmith sandboxes openswe-<b32(thread id)>
New sandboxes get a deterministic, thread-traceable name derived from the
LangGraph thread id (UUID base32-encoded lowercase, no padding), e.g.
openswe-ci2fm6asgrlhqerukz4bencwpa. Falls back to an unset name when no thread
id is present. Reconnect/delete still key off the server-assigned sandbox id.
* fix: pass sandbox base URL (root + /v2/sandboxes) to langsmith SDK clients
The SDK's api_endpoint is the sandbox base, not the API root — its methods
append /boxes, /snapshots, etc. Passing the bare root sent calls to
<root>/boxes instead of <root>/v2/sandboxes/boxes. Add _get_sandbox_api_endpoint
for the SDK clients (async client, provider, snapshot SandboxClient) while the
proxy-config PATCH keeps using the root.
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
(cherry picked from commit e826864dce0e56cda7decbc48254b1e13eef07e2)
Co-authored-by: Ramon Nogueira <ramon.nogueira@langchain.dev>
Add SANDBOX_CREATE_EXTRA_JSON so operators can merge extra fields (e.g.
{"_internal_runtime":"v2"}) into the LangSmith sandbox-create request body.
The SDK's create_sandbox builds a fixed payload with no passthrough, so we
wrap the HTTP client's post to inject the fields on the POST /boxes request
only. Malformed JSON fails at startup validation.
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
(cherry picked from commit 2238303306493ae6fcd0c2d4ab4236adf283a896)
Co-authored-by: Ramon Nogueira <ramon.nogueira@langchain.dev>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
(cherry picked from commit 79df6b2ff283afdbd36660be888c130ea964fe3f)
Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
* fix: defensive copy in get_reviewer_agent and get_chat_agent [closes#1584]
Factory functions were mutating the caller's RunnableConfig in-place via
config['recursion_limit'] = DEFAULT_RECURSION_LIMIT. Add copy.deepcopy(config)
at the top of each factory and switch the recursion_limit write to setdefault
so a caller-supplied ceiling is respected.
* fix: preserve runtime config object identities
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
---------
Co-authored-by: Fleet Agent <fleet-agent@langchain.dev>
Co-authored-by: Johannes du Plessis <51395795+johannes117@users.noreply.github.com>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
(cherry picked from commit c34e04f44da7ec7638cdafc71e0bb40e77070efd)
Co-authored-by: Jacob Albert <122248719+jacobalbert3@users.noreply.github.com>
* refactor: move docs/resources/assets to domain layout
Part of the domain-reorg adoption (build plan step C1): fork content,
upstream layout. Moves INSTALLATION.md/CUSTOMIZATION.md under docs/,
static/ under assets/, and default_prompt.md under agent/resources/
(packaged via agent/resources/__init__.py), then switches prompt.py's
loader to importlib.resources with an explicit DEFAULT_PROMPT_PATH
override, matching upstream's hunk. README and CUSTOMIZATION.md links
updated for the new paths; wheel build verified to still ship
agent/resources/default_prompt.md.
* refactor: consolidate reviewer modules into agent/review/
Part of the domain-reorg adoption (build plan step C2): fork content,
upstream layout. Nine 1:1 module moves (reviewer_diff/eval_store/
findings/groups/publish/reconcile/trace_context + review_style_
collector/guidance) into agent/review/, with internal relative
imports re-wired to the new package depth. agent/review/__init__.py
mirrors upstream's thin re-export shim (one of the 21 verified "A"
structural adds).
Rewrote the 38 grep hits across importer files (agent/{analyzer,
ci_autofix,reviewer,webapp}.py, agent/dashboard/*, agent/middleware/
settle_review_check.py, agent/tools/*, agent/utils/github_feedback.py,
agent/webhooks/github.py, evals/reviewer/*, and the reviewer test
suite) to point at agent.review.*; 4 of the 38 hits were name
collisions (list_reviewer_findings, reviewer_outcomes,
_reviewer_thread_id, reviewer_thread_id — not the moved modules) and
were left untouched. tests/test_github_checks.py's module-alias
import (`from agent import reviewer_publish`) follows upstream's own
`from agent.review import publish as reviewer_publish` pattern so
downstream `reviewer_publish.*` call sites needed no changes.
agent/reviewer.py and agent/webapp.py stay in place per the hard
rule (fork content, import-only rewire) and are not part of this
package.
Gates: ruff check + ruff format --check, pytest --co -q (1637
collected), full unit suite (1637 passed), and the reviewer/findings
suite in isolation (pytest -k "review or finding", 421 passed).
* refactor: adopt graphs/runtime/providers shims + retarget langgraph.json
Part of the domain-reorg adoption (build plan step C3): fork content,
upstream layout. Adds agent/graphs/{agent,analyzer,chat,reviewer,
scheduler}.py as thin re-export shims delegating to the existing fork
graph factories (agent.server/analyzer/chat/reviewer/scheduler), plus
agent/providers/__init__.py re-exporting agent.utils.model's
make_model/provider_model_kwargs/fallback_model_id_for surface —
verbatim upstream content, verified each import resolves against fork
modules with no name changes needed.
agent/runtime/{constants,execution}.py deviate from upstream's
verbatim shim bodies: rather than duplicating DEFAULT_LLM_MODEL_ID/
DEFAULT_LLM_MAX_TOKENS/DEFAULT_RECURSION_LIMIT/MODEL_CALL_RECURSION_LIMIT
and graph_loaded_for_execution's logic (upstream's shims assume
agent/server.py already had these extracted into runtime/ modules,
which is out of this commit's scope — server.py is untouched), they
import the fork's existing agent.server attributes directly. This
keeps the values/logic single-sourced instead of forking a second
copy that could drift.
agent/runtime/sandbox.py's delegation targets also differ from
upstream: fork's sandbox lifecycle helpers are private
(_get_cached_sandbox_backend, _configure_git_identity,
_recreate_sandbox in agent/server.py) since the fork's sync
4-case `__creating__` sentinel design (AGENTS.md) never made them
public. get_cached_sandbox_backend() also drops upstream's
caller-supplied `reconnect` callback parameter — fork's
_get_cached_sandbox_backend is a plain cache lookup; reconnection is
handled internally by ensure_sandbox_for_thread/
check_or_recreate_sandbox, not via a passed-in callback. No other
signature changes.
Added fork-only agent/graphs/ci_monitor.py (delegates to
agent.ci_monitor:get_ci_monitor) for symmetry, since upstream deleted
its ci-autofix cluster and has no equivalent shim. langgraph.json's
five stock graph entrypoints plus the fork-only ci_monitor now all
point at agent.graphs.<name>; http.app stays agent.webapp:app
(unchanged, per plan).
Deliberately NOT included (owned by build plan step C4, the FastAPI
split, gated on /sh-security-review): agent/api/{__init__,app,
health}.py, agent/webhooks/common.py, and the three
agent/webhooks/{github,linear,slack}_routes.py files. Those aren't
thin structural shims like the 21-file list implies in isolation —
they carry the fork's actual webhook dispatch/verify logic split out
of the still-monolithic webapp.py, which hasn't happened yet.
Building them now against upstream's placeholder content would ship
incomplete auth surface that C4 would just discard and redo.
Pinned oven-sh/setup-bun's bun-version to 1.3.14 (the version
installed locally; ui/ has no .bun-version file or package.json
engines/packageManager field pinning one) across all three CI jobs
that install bun, removing the latest-resolution flake.
Gates: ruff check + ruff format --check (clean), pytest --co -q
(1637 collected, no import errors), a direct import smoke-test of
every new module's public symbols, and a make dev boot check —
langgraph dev registered all six graphs (agent, reviewer, analyzer,
chat, scheduler, ci_monitor) each importing from agent.graphs.*, and
loaded the custom app from agent.webapp:app, before the process was
killed. (The subsequent lifespan failure, "DEFAULT_SANDBOX_SNAPSHOT_ID
must be set when SANDBOX_TYPE=langsmith", is expected with no .env
secrets configured in this environment and unrelated to this commit.)
* refactor: split webapp.py into api/ + per-source webhook routes
Plan step C4 (docs/upstream-sync/domain-reorg/reorg-build-plan.md, approved
decisions 1-2): split the 2,590-line agent/webapp.py monolith into
agent/webhooks/common.py (shared verify/dispatch helpers), agent/api/app.py
(composition), agent/api/health.py (/health + /webhooks/run-complete), and
per-source {github,linear,slack,jira,confluence}_routes.py. Atlassian
Connect lifecycle + descriptor routes (/connect/*) fold into
confluence_routes.py; webapp.py becomes the upstream-shaped compatibility
shim (from .api.app import app). langgraph.json http.app stays
agent.webapp:app via the shim.
Fork content, upstream layout: linear/slack route files verified
content-identical to upstream 8356eb34 and taken verbatim; github_routes is
upstream + the fork's CI auto-fix trigger wiring; jira/confluence routes are
fork-only, transformed to the same common.X / service.X module-attribute
style. All signature verification (GitHub HMAC, Slack, Linear
timestamp-freshness, verify_jira_secret + opt-in HMAC/timestamp/IP
allowlist, Connect JWT/qsh), token-attribution gating, TID-COLLIDE-01 repo
binding, _is_repo_auto_review_enabled gates, and public-repo org gate move
unchanged.
Handlers rewired from webapp.X to common.X; test monkeypatch sites across
26 files + conftest.py + e2e/harness.py retargeted to
webhook_common/handler/route modules per upstream's pattern. Residual
agent.webapp importers: only the shim, langgraph.json http.app, Makefile
uvicorn target, and docs (doc-path updates land in C7).
Gates: ruff check + format, pytest --co, full unit (1637 passed), full
Playwright E2E vs real langgraph dev (9/9), residual-importer sweep.
* refactor: move tests into tests/<domain>/ layout
Applies the plan's C5 step: git mv every test per the domain-reorg
move-map (movemap-m50.txt) into tests/{agent,analyzer,auth,dashboard,
github,middleware,models,reviewer,sandbox,slack,tools,webhooks}/, plus
the 13 fork-only placements from the scoping report §2c (Atlassian
webhook tests -> tests/webhooks/, test_atlassian_connect.py and
test_auth_error_leak.py -> tests/auth/, jira/confluence util tests ->
tests/tools/, test_repo_binding_isolation.py -> tests/sandbox/,
bot-identity/autofix tests -> tests/github/).
Path-only move: the only content edits are parents[1] -> parents[2]
fixes in test_e2b_integration.py and test_daytona_integration.py,
required because their __file__-relative ROOT path gained one more
directory level in the move.
Monkeypatch retargets for these files were already completed in C4;
none remained outstanding here.
* refactor: move ui/src/{components,lib}/agents into features/ layout
Part of the domain-reorg adoption (build plan step C6): fork content,
upstream layout. git mv's all 80 pure-rename files from the move-map
(agent-scoped components/lib -> ui/src/features/{agents,automations,
reviews,settings}/...), including ported/ splitting into
features/agents/experiments/ (still-unintegrated desktop-host ports)
and features/agents/components/chat/ (CloudPromptBar, CodeBlock,
DiffView, Logo, Markdown, ReplyCard, ShellCommand, ToolExecution --
files actually wired into the live dashboard). Fork-diverged files
(PlanReview.tsx, WorkflowApprovalCard.tsx, AgentsSidebar.tsx,
SidebarFilterMenu.tsx, AgentGitPanel.tsx, AutomationEditor.tsx,
DiffView.tsx, CloudPromptBar.tsx) keep fork content -- verified via
diff that only import lines changed.
Rewrote @/components/agents and @/lib/agents imports across all 54
importer files plus the moved files' own internal imports (grep-driven,
85-entry alias map covering every old->new path pair). Two hazards
caught only by the build gate (not tsc, since both files sit under the
new experiments/** tsconfig exclude): ui/src/lib/notifications.ts had
a relative `./agents/types` import (no `@/` alias) that the grep missed;
and features/agents/experiments/index.ts's barrel re-export of the
messages module needed to switch from an `@/` alias to a relative
import (`../components/messages`) after landing inside the newly
tsconfig-excluded experiments/ directory -- vite-tsconfig-paths failed
to resolve it at build time even though tsc stayed silent.
AgentPromptBar.tsx (the 2-line CloudPromptBar re-export shim) moves to
features/agents/components/ with its export path retargeted at
CloudPromptBar's new chat/ location -- a D/A pair, not a content loss,
since the import-path edit drops it below git's rename-similarity
threshold. ported/index.ts is the same D/A story for the same reason.
Swapped the 8-file ported/ exclude lists in tsconfig.json and
eslint.config.js for the single `src/features/agents/experiments/**`
glob (upstream's simplification, no behavior change). Deleted
ui/pnpm-workspace.yaml (lockfile hygiene -- bun stays the toolchain).
Gates: bunx tsc --noEmit (clean), bun run build (clean after the two
notifications.ts / experiments-index.ts fixes above), bun run test
(33/33), and the full Playwright E2E suite against the real langgraph
dev server + built dashboard (9/9).
* docs: land reorg in ledger, fix path refs, ship plan artifacts (C7)
C7 of the domain-reorg adoption (build plan docs/upstream-sync/domain-reorg/
reorg-build-plan.md, step C7):
- CLAUDE.md / AGENTS.md: retarget architecture path references to the new
layout — graph entrypoints via agent.graphs.* shims, the agent/api/ +
agent/webhooks/*_routes.py FastAPI split (webapp.py now a shim),
agent/review/ package, tests/<domain>/ test paths, and the new-graph/
test conventions. README.md already pointed at docs/ (C1) — no change.
- triage.jsonl: flip 8356eb34 (#1726) to landed on branch
refactor/domain-reorg-adoption; add re-triage notes to the 8 unblocked
rows (#1732/#1761/#1744/#1748/#1742 clean, #1736/#1758/#1760 near-clean).
triage.md regenerated via make triage-render.
- Ship the plan, scoping report, move-map artifacts, and the
domain-reorg-adoption workflow so the exercise is reproducible.
Memory + Confluence handled out-of-band (not in this commit): project
memory updated with the new module layout; Confluence check found no IT
page documents the repo module map — no Confluence change required.
C7 of the domain-reorg adoption (build plan docs/upstream-sync/domain-reorg/
reorg-build-plan.md, step C7):
- CLAUDE.md / AGENTS.md: retarget architecture path references to the new
layout — graph entrypoints via agent.graphs.* shims, the agent/api/ +
agent/webhooks/*_routes.py FastAPI split (webapp.py now a shim),
agent/review/ package, tests/<domain>/ test paths, and the new-graph/
test conventions. README.md already pointed at docs/ (C1) — no change.
- triage.jsonl: flip 8356eb34 (#1726) to landed on branch
refactor/domain-reorg-adoption; add re-triage notes to the 8 unblocked
rows (#1732/#1761/#1744/#1748/#1742 clean, #1736/#1758/#1760 near-clean).
triage.md regenerated via make triage-render.
- Ship the plan, scoping report, move-map artifacts, and the
domain-reorg-adoption workflow so the exercise is reproducible.
Memory + Confluence handled out-of-band (not in this commit): project
memory updated with the new module layout; Confluence check found no IT
page documents the repo module map — no Confluence change required.
Part of the domain-reorg adoption (build plan step C6): fork content,
upstream layout. git mv's all 80 pure-rename files from the move-map
(agent-scoped components/lib -> ui/src/features/{agents,automations,
reviews,settings}/...), including ported/ splitting into
features/agents/experiments/ (still-unintegrated desktop-host ports)
and features/agents/components/chat/ (CloudPromptBar, CodeBlock,
DiffView, Logo, Markdown, ReplyCard, ShellCommand, ToolExecution --
files actually wired into the live dashboard). Fork-diverged files
(PlanReview.tsx, WorkflowApprovalCard.tsx, AgentsSidebar.tsx,
SidebarFilterMenu.tsx, AgentGitPanel.tsx, AutomationEditor.tsx,
DiffView.tsx, CloudPromptBar.tsx) keep fork content -- verified via
diff that only import lines changed.
Rewrote @/components/agents and @/lib/agents imports across all 54
importer files plus the moved files' own internal imports (grep-driven,
85-entry alias map covering every old->new path pair). Two hazards
caught only by the build gate (not tsc, since both files sit under the
new experiments/** tsconfig exclude): ui/src/lib/notifications.ts had
a relative `./agents/types` import (no `@/` alias) that the grep missed;
and features/agents/experiments/index.ts's barrel re-export of the
messages module needed to switch from an `@/` alias to a relative
import (`../components/messages`) after landing inside the newly
tsconfig-excluded experiments/ directory -- vite-tsconfig-paths failed
to resolve it at build time even though tsc stayed silent.
AgentPromptBar.tsx (the 2-line CloudPromptBar re-export shim) moves to
features/agents/components/ with its export path retargeted at
CloudPromptBar's new chat/ location -- a D/A pair, not a content loss,
since the import-path edit drops it below git's rename-similarity
threshold. ported/index.ts is the same D/A story for the same reason.
Swapped the 8-file ported/ exclude lists in tsconfig.json and
eslint.config.js for the single `src/features/agents/experiments/**`
glob (upstream's simplification, no behavior change). Deleted
ui/pnpm-workspace.yaml (lockfile hygiene -- bun stays the toolchain).
Gates: bunx tsc --noEmit (clean), bun run build (clean after the two
notifications.ts / experiments-index.ts fixes above), bun run test
(33/33), and the full Playwright E2E suite against the real langgraph
dev server + built dashboard (9/9).
Applies the plan's C5 step: git mv every test per the domain-reorg
move-map (movemap-m50.txt) into tests/{agent,analyzer,auth,dashboard,
github,middleware,models,reviewer,sandbox,slack,tools,webhooks}/, plus
the 13 fork-only placements from the scoping report §2c (Atlassian
webhook tests -> tests/webhooks/, test_atlassian_connect.py and
test_auth_error_leak.py -> tests/auth/, jira/confluence util tests ->
tests/tools/, test_repo_binding_isolation.py -> tests/sandbox/,
bot-identity/autofix tests -> tests/github/).
Path-only move: the only content edits are parents[1] -> parents[2]
fixes in test_e2b_integration.py and test_daytona_integration.py,
required because their __file__-relative ROOT path gained one more
directory level in the move.
Monkeypatch retargets for these files were already completed in C4;
none remained outstanding here.
Plan step C4 (docs/upstream-sync/domain-reorg/reorg-build-plan.md, approved
decisions 1-2): split the 2,590-line agent/webapp.py monolith into
agent/webhooks/common.py (shared verify/dispatch helpers), agent/api/app.py
(composition), agent/api/health.py (/health + /webhooks/run-complete), and
per-source {github,linear,slack,jira,confluence}_routes.py. Atlassian
Connect lifecycle + descriptor routes (/connect/*) fold into
confluence_routes.py; webapp.py becomes the upstream-shaped compatibility
shim (from .api.app import app). langgraph.json http.app stays
agent.webapp:app via the shim.
Fork content, upstream layout: linear/slack route files verified
content-identical to upstream 8356eb34 and taken verbatim; github_routes is
upstream + the fork's CI auto-fix trigger wiring; jira/confluence routes are
fork-only, transformed to the same common.X / service.X module-attribute
style. All signature verification (GitHub HMAC, Slack, Linear
timestamp-freshness, verify_jira_secret + opt-in HMAC/timestamp/IP
allowlist, Connect JWT/qsh), token-attribution gating, TID-COLLIDE-01 repo
binding, _is_repo_auto_review_enabled gates, and public-repo org gate move
unchanged.
Handlers rewired from webapp.X to common.X; test monkeypatch sites across
26 files + conftest.py + e2e/harness.py retargeted to
webhook_common/handler/route modules per upstream's pattern. Residual
agent.webapp importers: only the shim, langgraph.json http.app, Makefile
uvicorn target, and docs (doc-path updates land in C7).
Gates: ruff check + format, pytest --co, full unit (1637 passed), full
Playwright E2E vs real langgraph dev (9/9), residual-importer sweep.
Part of the domain-reorg adoption (build plan step C3): fork content,
upstream layout. Adds agent/graphs/{agent,analyzer,chat,reviewer,
scheduler}.py as thin re-export shims delegating to the existing fork
graph factories (agent.server/analyzer/chat/reviewer/scheduler), plus
agent/providers/__init__.py re-exporting agent.utils.model's
make_model/provider_model_kwargs/fallback_model_id_for surface —
verbatim upstream content, verified each import resolves against fork
modules with no name changes needed.
agent/runtime/{constants,execution}.py deviate from upstream's
verbatim shim bodies: rather than duplicating DEFAULT_LLM_MODEL_ID/
DEFAULT_LLM_MAX_TOKENS/DEFAULT_RECURSION_LIMIT/MODEL_CALL_RECURSION_LIMIT
and graph_loaded_for_execution's logic (upstream's shims assume
agent/server.py already had these extracted into runtime/ modules,
which is out of this commit's scope — server.py is untouched), they
import the fork's existing agent.server attributes directly. This
keeps the values/logic single-sourced instead of forking a second
copy that could drift.
agent/runtime/sandbox.py's delegation targets also differ from
upstream: fork's sandbox lifecycle helpers are private
(_get_cached_sandbox_backend, _configure_git_identity,
_recreate_sandbox in agent/server.py) since the fork's sync
4-case `__creating__` sentinel design (AGENTS.md) never made them
public. get_cached_sandbox_backend() also drops upstream's
caller-supplied `reconnect` callback parameter — fork's
_get_cached_sandbox_backend is a plain cache lookup; reconnection is
handled internally by ensure_sandbox_for_thread/
check_or_recreate_sandbox, not via a passed-in callback. No other
signature changes.
Added fork-only agent/graphs/ci_monitor.py (delegates to
agent.ci_monitor:get_ci_monitor) for symmetry, since upstream deleted
its ci-autofix cluster and has no equivalent shim. langgraph.json's
five stock graph entrypoints plus the fork-only ci_monitor now all
point at agent.graphs.<name>; http.app stays agent.webapp:app
(unchanged, per plan).
Deliberately NOT included (owned by build plan step C4, the FastAPI
split, gated on /sh-security-review): agent/api/{__init__,app,
health}.py, agent/webhooks/common.py, and the three
agent/webhooks/{github,linear,slack}_routes.py files. Those aren't
thin structural shims like the 21-file list implies in isolation —
they carry the fork's actual webhook dispatch/verify logic split out
of the still-monolithic webapp.py, which hasn't happened yet.
Building them now against upstream's placeholder content would ship
incomplete auth surface that C4 would just discard and redo.
Pinned oven-sh/setup-bun's bun-version to 1.3.14 (the version
installed locally; ui/ has no .bun-version file or package.json
engines/packageManager field pinning one) across all three CI jobs
that install bun, removing the latest-resolution flake.
Gates: ruff check + ruff format --check (clean), pytest --co -q
(1637 collected, no import errors), a direct import smoke-test of
every new module's public symbols, and a make dev boot check —
langgraph dev registered all six graphs (agent, reviewer, analyzer,
chat, scheduler, ci_monitor) each importing from agent.graphs.*, and
loaded the custom app from agent.webapp:app, before the process was
killed. (The subsequent lifespan failure, "DEFAULT_SANDBOX_SNAPSHOT_ID
must be set when SANDBOX_TYPE=langsmith", is expected with no .env
secrets configured in this environment and unrelated to this commit.)
Part of the domain-reorg adoption (build plan step C2): fork content,
upstream layout. Nine 1:1 module moves (reviewer_diff/eval_store/
findings/groups/publish/reconcile/trace_context + review_style_
collector/guidance) into agent/review/, with internal relative
imports re-wired to the new package depth. agent/review/__init__.py
mirrors upstream's thin re-export shim (one of the 21 verified "A"
structural adds).
Rewrote the 38 grep hits across importer files (agent/{analyzer,
ci_autofix,reviewer,webapp}.py, agent/dashboard/*, agent/middleware/
settle_review_check.py, agent/tools/*, agent/utils/github_feedback.py,
agent/webhooks/github.py, evals/reviewer/*, and the reviewer test
suite) to point at agent.review.*; 4 of the 38 hits were name
collisions (list_reviewer_findings, reviewer_outcomes,
_reviewer_thread_id, reviewer_thread_id — not the moved modules) and
were left untouched. tests/test_github_checks.py's module-alias
import (`from agent import reviewer_publish`) follows upstream's own
`from agent.review import publish as reviewer_publish` pattern so
downstream `reviewer_publish.*` call sites needed no changes.
agent/reviewer.py and agent/webapp.py stay in place per the hard
rule (fork content, import-only rewire) and are not part of this
package.
Gates: ruff check + ruff format --check, pytest --co -q (1637
collected), full unit suite (1637 passed), and the reviewer/findings
suite in isolation (pytest -k "review or finding", 421 passed).
Part of the domain-reorg adoption (build plan step C1): fork content,
upstream layout. Moves INSTALLATION.md/CUSTOMIZATION.md under docs/,
static/ under assets/, and default_prompt.md under agent/resources/
(packaged via agent/resources/__init__.py), then switches prompt.py's
loader to importlib.resources with an explicit DEFAULT_PROMPT_PATH
override, matching upstream's hunk. README and CUSTOMIZATION.md links
updated for the new paths; wheel build verified to still ship
agent/resources/default_prompt.md.
All 18 pre-domain-reorg (pre-8356eb34) deferred rows resolved: 13 wont-merge
(6 already in dev via squash-sync #81, 5 sandbox-refactor chain kept on fork
lifecycle, Stagehand vs tool-curation policy, GPT-5.6 vs Bedrock/Fireworks-only
picker) and 5 landed via #197#198#199#200#201. Remaining deferred rows are
all post-reorg.
* fix: separate review access from automatic reviews (#1720)
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
(cherry picked from commit 92d631704e9c38f6aeedf70baede85a7c638567e)
* fix: rename fork-only auto-fix gates to _is_repo_auto_review_enabled
The cherry-pick of upstream 92d63170 renamed _is_repo_enabled_for_review
to _is_repo_auto_review_enabled, but the fork's CI auto-fix, auto-fix
toggle command, and auto-fix review-feedback gates (not present upstream)
still referenced the old name and would raise NameError at request time.
Rename them in place — auto-fix surfaces stay gated on the dashboard
auto-review opt-in list, preserving current fork behavior.
---------
Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* fix: align reviewer eval with published findings (#1713)
* fix: make reviewer eval reflect published findings
Serialize and deduplicate finding persistence, align review calibration around the final six-finding publication, and make judge matching order-independent and auditable.
* fix: honor reviewer eval limits
Forward configured caps into publication snapshots and keep recall-at-cap bounded for diagnostic all-findings runs.
(cherry picked from commit 71e3b8183882bcc42e318f3f220c291617ebcb67)
Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
* Empty commit to trigger CI
---------
Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
Additive sandbox provider adapted to this fork's synchronous create_sandbox
factory: agent/integrations/e2b.py registered as a lazy-import entry in
SANDBOX_FACTORIES, so the e2b/langchain-e2b imports only load when
SANDBOX_TYPE=e2b (dark-safe on unset env; unset E2B_API_KEY raises a clean
ValueError only when the provider is selected). Supports reconnect-by-id and
optional E2B_TEMPLATE. Non-langsmith providers skip the GitHub proxy step,
so the GitHub-App token flow is untouched.
Upstream: langchain-ai/open-swe 48217b68 (#1489), re-implemented against the
fork's sync sandbox lifecycle rather than cherry-picked (upstream ships on
the deferred async sandbox.py base).
Docs: provider tables/lists in README, CUSTOMIZATION, INSTALLATION; the
CUSTOMIZATION registration example now shows the lazy-tuple form the code
actually uses. uv.lock refreshed (adds e2b, langchain-e2b, dockerfile-parse).
* fix: migrate stale admin model defaults
Normalize retired model IDs before validation and in settings responses so full admin updates remain saveable after model upgrades.
* fix: restrict retired model migration
Only migrate explicitly retired model IDs so malformed provider model names and efforts continue to fail validation.
(cherry picked from commit 62e0ca2d4898ebc3c2ae8887030a364779d907cb)
Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
(cherry picked from commit 092abafa4cb955c3823f727d35d7bad94e1147ab)
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
* fix: let admins interrupt runaway agents (#1730)
Add a workspace-wide admin control that cancels every active run while preserving thread history.
(cherry picked from commit 09eaf94c3e612db969daa000b909805963fe1de9)
* chore: reconcile triage ledger
Signed-off-by: Adam Moussa <adam@seahavenind.com>
* fix: change ui import from refactor
Signed-off-by: Adam Moussa <adam@seahavenind.com>
---------
Signed-off-by: Adam Moussa <adam@seahavenind.com>
Co-authored-by: Johannes du Plessis <johannes@langchain.dev>