Compare commits

..

1 commit

Author SHA1 Message Date
dependabot[bot]
168843926d
chore(deps): bump vite-tsconfig-paths from 5.1.4 to 6.1.1 in /ui
Bumps [vite-tsconfig-paths](https://github.com/aleclarson/vite-tsconfig-paths) from 5.1.4 to 6.1.1.
- [Release notes](https://github.com/aleclarson/vite-tsconfig-paths/releases)
- [Commits](https://github.com/aleclarson/vite-tsconfig-paths/compare/v5.1.4...v6.1.1)

---
updated-dependencies:
- dependency-name: vite-tsconfig-paths
  dependency-version: 6.1.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-02 19:34:25 +00:00
14 changed files with 45 additions and 231 deletions

View file

@ -1,123 +0,0 @@
# === LangSmith ===
LANGSMITH_API_KEY_PROD="" # From step 4a
# NOTE: LANGCHAIN_TRACING_V2 and LANGCHAIN_PROJECT are RESERVED on LangGraph Platform
# (LangSmith deployments) — the platform sets them itself and rejects the deploy if
# you provide them. Only set them for local/self-hosted runs, not in a deployment's env.
LANGSMITH_TENANT_ID_PROD=""
LANGSMITH_TRACING_PROJECT_ID_PROD="" # Fallback project ID for "View trace" links; graphs trace into the open-swe-agent / open-swe-review projects by name
LANGSMITH_URL_PROD="https://smith.langchain.com"
# === LLM ===
LLM_MODEL_ID="" # Default model, e.g. "bedrock_converse:us.anthropic.claude-opus-4-8"
ANTHROPIC_API_KEY="" # Anthropic API key
OPENAI_API_KEY="" # OpenAI API key (when using openai: models)
GOOGLE_API_KEY="" # Google AI API key (when using google_genai: models)
FIREWORKS_API_KEY="" # Fireworks API key (when using fireworks: models)
# AWS credentials for Bedrock (when using bedrock_converse: models). Region defaults to us-east-1.
AWS_ACCESS_KEY_ID=""
AWS_SECRET_ACCESS_KEY=""
# === GitHub App (required) ===
GITHUB_APP_ID="" # From step 3c
GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
"
GITHUB_APP_INSTALLATION_ID="" # From step 3d
# === GitHub Webhook (required) ===
GITHUB_WEBHOOK_SECRET="" # The secret you generated in step 3b
# === Dashboard GitHub OAuth (required for the dashboard) ===
# Direct GitHub OAuth used by the dashboard login flow (not via LangSmith).
GITHUB_APP_CLIENT_ID="" # From step 3c
GITHUB_APP_CLIENT_SECRET="" # From step 3c
# === Agent-runtime GitHub OAuth via LangSmith (optional) ===
# Without these, all agent operations use the GitHub App's bot token.
# With these, each agent run authenticates as the triggering user.
GITHUB_OAUTH_PROVIDER_ID="" # The provider ID from steps 3a / 4b
# Secret used to mint short-lived service JWTs that ask LangSmith to resolve a
# specific user's GitHub token. Needed for per-user token resolution in deployed mode.
X_SERVICE_AUTH_JWT_SECRET=""
# === Repo Allowlist (optional) ===
# Comma-separated list of GitHub orgs the agent is allowed to operate on.
# Also gates dashboard login to members of these orgs (requires the GitHub App's
# Organization -> Members: Read-only permission; without it, all dashboard logins are rejected).
# Leave empty to allow all orgs.
ALLOWED_GITHUB_ORGS="" # e.g. "my-org,my-other-org"
# Comma-separated list of specific owner/repo pairs the agent is allowed to operate on.
# For GitHub/Linear webhooks, a repo is allowed if its org is in ALLOWED_GITHUB_ORGS OR its owner/repo is in ALLOWED_GITHUB_REPOS.
# Slack mentions are not rejected from regex-inferred repository text; repository access is bounded by GitHub App installation permissions.
# Leave both empty to allow all repos.
ALLOWED_GITHUB_REPOS="" # e.g. "some-user/their-repo,another-org/specific-repo"
# === Default Repository ===
# Used across all triggers when no repo is specified.
DEFAULT_REPO_OWNER="" # Default GitHub org (e.g. "my-org")
DEFAULT_REPO_NAME="" # Default GitHub repo (e.g. "my-repo")
# === Dashboard (required to run the web dashboard) ===
# Public URL that browsers use for /dashboard/api/* and OAuth callbacks.
# Use the FastAPI backend URL for local/cross-origin direct API calls.
# Use the dashboard frontend URL when a same-origin frontend rewrite proxies /dashboard/api/*.
# Its scheme drives cookie security: http:// => SameSite=Lax (local);
# https:// => Secure + SameSite=None (production).
DASHBOARD_API_BASE_URL="http://localhost:2024"
# Public base URL of the dashboard frontend (the ui/ app). Default post-login redirect.
DASHBOARD_BASE_URL="http://localhost:3000"
# HMAC secret for dashboard JWTs (session cookie and OAuth state).
DASHBOARD_JWT_SECRET="" # Generate with: openssl rand -hex 32
# Comma-separated origins allowed for credentialed CORS and post-login redirects.
# Required whenever the frontend and API are on different origins — including local
# dev (UI :3000 -> API :2024 is cross-origin). CORS is only enabled when this is set.
DASHBOARD_ALLOWED_ORIGINS="http://localhost:3000" # prod: your frontend origin(s)
# Comma-separated GitHub login or email allowlist for admin dashboard endpoints.
# Empty => nobody is an admin.
CONFIGURED_ADMINS="" # e.g. "alice,bob@my-org.com"
# URL of the LangGraph server the FastAPI side calls to trigger/stream runs.
# Defaults to http://localhost:2024 locally; set to your deployment URL in prod.
LANGGRAPH_URL="http://localhost:2024"
# === Linear (if using Linear trigger) ===
LINEAR_API_KEY="" # From step 5
LINEAR_WEBHOOK_SECRET="" # From step 5
# === Slack (if using Slack trigger) ===
SLACK_BOT_TOKEN="" # From step 5
SLACK_BOT_USER_ID=""
SLACK_BOT_USERNAME=""
SLACK_SIGNING_SECRET=""
# Optional: Slack-specific default repo (falls back to DEFAULT_REPO_OWNER/NAME).
SLACK_REPO_OWNER=""
SLACK_REPO_NAME=""
# Optional: "Sign in with Slack" account linking (GitHub <-> Slack). See step 5.
SLACK_CLIENT_ID=""
SLACK_CLIENT_SECRET=""
SLACK_TEAM_ID="" # Optional; restrict linking to one workspace (T...)
# === Exa (optional — enables web search tool) ===
EXA_API_KEY="" # From https://dashboard.exa.ai
# === Reviewer / Analyzer (optional) ===
# LangSmith dataset where reviewer finding outcomes are recorded and read back by
# the analyzer. Defaults to "openswe-reviewer-outcomes" if unset.
REVIEWER_OUTCOMES_DATASET=""
# Single GitHub org whose members may trigger the agent on *public* repos.
# Empty => no public-repo gate (back-compat). Distinct from ALLOWED_GITHUB_ORGS.
PUBLIC_REPO_ORG_GATE=""
# === Sandbox (optional) ===
# Provider: langsmith (default), modal, daytona, runloop, or local. See CUSTOMIZATION.md.
SANDBOX_TYPE="langsmith"
DEFAULT_SANDBOX_SNAPSHOT_ID="" # Required when SANDBOX_TYPE=langsmith (see step 4c)
DEFAULT_SANDBOX_SNAPSHOT_FS_CAPACITY_BYTES="" # Root FS size in bytes (default: 32 GiB)
DEFAULT_SANDBOX_VCPUS="" # vCPUs per sandbox (default: 4)
DEFAULT_SANDBOX_MEM_BYTES="" # Memory in bytes per sandbox (default: 15 GiB)
DEFAULT_SANDBOX_IDLE_TTL_SECONDS="" # Auto-stop after N seconds idle (default: 7200; 0 disables)
DEFAULT_SANDBOX_DELETE_AFTER_STOP_SECONDS="" # Delete N seconds after stop (default: 86400; 0 disables)
# === Token Encryption ===
TOKEN_ENCRYPTION_KEY="" # Generate with: openssl rand -base64 32
# Supports key rotation: see "Rotating TOKEN_ENCRYPTION_KEY" below

View file

@ -22,15 +22,6 @@ updates:
groups:
minor-and-patch:
update-types: ["minor", "patch"]
ignore:
# @types/node must track the runtime Node major, not the latest release.
# /ui is the web dashboard deployed on Vercel; pin @types/node to the Node
# major Vercel builds/runs it on. Dependabot can't see that and a too-new
# types major still compiles (passes CI, wrong at runtime). Sanctioned
# exception to the no-blanket-ignore rule (engineering-handbook
# github-standards Pinning Principle). Minor/patch within the major flow.
- dependency-name: "@types/node"
update-types: ["version-update:semver-major"]
# Docker — root Dockerfile
- package-ecosystem: "docker"

1
.gitignore vendored
View file

@ -39,7 +39,6 @@ yarn-error.log*
.env*.local
.env
.env.*
!.env.example
# vercel
.vercel

View file

@ -116,17 +116,3 @@ Webhooks compute deterministic thread ids so the same Linear issue / Slack threa
- New dashboard endpoints: add to `agent/dashboard/routes.py`. The router is auto-mounted on the FastAPI app.
- New graphs: register the entrypoint in `langgraph.json` under `graphs`.
- Minimal-to-no code comments — only when the *why* isn't obvious from the code.
## Fork maintenance — syncing `upstream/main`
This is a long-lived fork of `langchain-ai/open-swe` with Sea Haven customizations woven into upstream-owned files (notably `agent/prompt.py` prompt constants, `agent/webapp.py`, and the tool/middleware wiring). Merging upstream is a triage exercise, not a fast-forward. When you want upstream's clean changes but must **defer a large structural refactor** (and its entangled features), work in this order:
1. **Triage before resolving.** Merge-base is `git merge-base HEAD upstream/main`. The truthful conflict set is the combined merge, `git merge-tree --write-tree --name-only HEAD upstream/main` — a per-commit probe against each commit's parent *overstates* conflicts (a file a refactor merely added shows up as a phantom `modify/delete`). Decide keep-baseline vs adopt-refactor **before** resolving, and surface the choice to a human for any auth/webhook/IAM surface.
2. **Chase the cascade, not just the textual conflicts.** The hard part is the non-conflicting files the refactor also touched. Get the refactor's file set (`git diff-tree --no-commit-id --name-status -r <refactor-sha>`) and cross-reference the files this fork modified (`git diff --name-only <fork-base> HEAD`). Files in both = hand-resolve; files only the refactor touched = mechanical.
3. **Deferring a refactor:** default every refactor-touched file to **upstream**, except the deleted-module cluster, which stays at your **baseline (HEAD)** — and move its **paired tests to the same side**. A file goes to HEAD when its upstream version imports a module the refactor deleted, or kept code needs an old API. Bring back files the refactor deleted but you still use with `git checkout HEAD -- <file>`. Iterate `pytest --co -q` to chase import breaks one module at a time.
4. **Two silent hazards.** (a) A thin upstream router ends with `from .webhooks.slack import process_slack_mention`; merged alongside your monolith's *local* `def process_slack_mention`, Python rebinds the name at import, so **upstream's handler runs and silently drops your fixes** — delete those re-import lines. (b) A new tool/middleware importing a deleted module crashes the whole graph at import — if you defer the feature, delete the tool file **and** all its wiring (`server.py` tool list, `tools/__init__.py`, prompt guidance, e2e harness, its test).
5. **Keep test + impl on the same side** — a test at upstream and its impl at HEAD (or vice-versa) yields async-vs-sync or contract drift. Keep the whole vertical (backend + UI + e2e spec + fixtures) on one side.
6. **Run CI in layers** — `ruff`/`tsc` (syntax/types) → `pytest --co` (import-time breaks) → unit tests (contract mismatches) → **E2E (Playwright + the real LangGraph dev server)**, which is the only layer that catches import-time crashes in tool/middleware *wiring* and frontend↔backend contract drift. "Unit green" is not "done" for a structural merge.
7. **Tooling-switch fallout** — a package-manager/build-tool switch (upstream `pnpm`, this fork keeps `bun`) auto-merges into build scripts, CI, the `packageManager` field, and lockfiles even when you reject it for the product build. After merging, sweep those and never ship two lockfiles.
Validate on a throwaway branch with granular commits (one per cascade class) and let each CI layer prove out before promoting.

View file

@ -32,22 +32,6 @@ TEAM_SETTINGS_KEY = "default"
ORG_GUIDELINES_MAX_CHARS = 10_000
REVIEW_TRACING_PROJECT_MAX_CHARS = 256
# Sea Haven review baseline seeded as the org-wide guidelines default. Surfaces
# in the reviewer prompt for every repo until an admin overrides it with a
# non-empty value via the dashboard (PUT /team-settings). Keep it stack-agnostic
# and well under ORG_GUIDELINES_MAX_CHARS.
DEFAULT_ORG_REVIEW_GUIDELINES = """\
Sea Haven review baseline (applies to every repo unless a repo-specific guideline overrides it):
- Severity: map findings to critical / high / medium / low. Reserve critical and high for correctness bugs, security issues, data loss, or broken contracts — not style.
- Secrets & config: flag any hardcoded secret, credential, or real `.env`/config value committed to source, and any sensitive value placed outside the platform's secrets manager.
- Security surface (raise as high): changes to authentication/authorization or access checks; IAM/policy/permission or infrastructure-access changes; changes to the exported signature or contract of a public handler/endpoint; and untrusted-input handling (request parsing, deserialization, file uploads, SSRF-prone fetches, and template/SQL/command construction — flag unescaped interpolation of dynamic or user-controlled data).
- Tests: flag new behavior that ships without a corresponding test, and "fixes" that only silence a check (added excludes, `noqa` / `# type: ignore`, skipped or `xfail`ed tests).
- Naming & conventions: flag resources or code that break the repo's established naming and layout conventions.
- Deferred work: a finding the author chooses to defer must be captured in a tracked issue, not dropped silently.
Only file a finding that anchors to a changed line and names a concrete failure mode. Do not police pre-existing issues outside the diff or raise pure style nits."""
class TeamSettingsUpdate(BaseModel):
review_draft_prs: bool = False
@ -168,7 +152,7 @@ def _default_settings() -> dict[str, Any]:
"pr_summaries": True,
"review_trace_links": True,
"review_tracing_project": None,
"org_guidelines": DEFAULT_ORG_REVIEW_GUIDELINES,
"org_guidelines": None,
"default_agent_model": fallback_model,
"default_agent_reasoning_effort": fallback_effort,
"default_agent_subagent_model": fallback_model,

View file

@ -163,12 +163,8 @@ Before any task that changes code, set up the repo in your sandbox, in order:
This authors every commit. It is required for CI (e.g. Vercel preview deploys reject commits whose author email can't be resolved to a GitHub account; this email resolves). Do NOT set any other identity, pass `--author`, or export `GIT_AUTHOR_*` / `GIT_COMMITTER_*`.
4. **Choose your branch** — Use a Sea Haven branch name: `<prefix>/<description>`, all kebab-case. Pick the prefix by the kind of work:
- `feature/` — new functionality or an enhancement
- `fix/` — a defect caught before it reaches production
- `bug/` — a defect caught before it reaches production
- `hotfix/` — a fix for a production-impacting issue
- `chore/` — tooling, dependencies, config, or other maintenance
- `docs/` — documentation-only changes
- `refactor/` — internal restructuring with no behavior change
- `release/` — release preparation
Keep `<description>` short and kebab-case (e.g. `feature/add-receipt-parser`). When a ticket key is resolvable from the run context, put it first: `feature/<KEY>-add-receipt-parser`; if no key is resolvable, omit it. Never commit directly to `main`. Keep the branch thread-stable: if a branch already exists for this thread, reuse it: fetch and check it out, starting from `origin/<branch>` (not the base branch) so prior commits are preserved for review — do not recreate it.
5. **Read `AGENTS.md`** — IMMEDIATELY after cloning, you MUST check if `AGENTS.md` exists at the repository root (`{working_dir}/<repo>/AGENTS.md`). If it exists, you MUST read it IN FULL before doing ANY other work: its contents are **mandatory rules** that OVERRIDE your default behavior — treat them with the same authority as this system prompt. Violating AGENTS.md rules is a CRITICAL FAILURE. If `AGENTS.md` does not exist, skip this step.
@ -237,17 +233,26 @@ This applies only after you've made code changes. By default, open or update a d
Steps, in order:
1. **Lint & format.** Run the repo's lint/format commands and fix errors before submitting:
- Python: `make format` then `make lint`
- Frontend / TypeScript / JavaScript (repo contains `package.json`): `yarn format` then `yarn lint`
- Go (repo contains `.go` files): find the commands from `Makefile`/`go.mod`/CI and run them
1. **Lint & format.** Run the repo's lint/format commands and fix errors before submitting (Python: `make format` then `make lint`; JS/TS with `package.json`: `yarn format` then `yarn lint`; Go: find the commands from `Makefile`/`go.mod`/CI). Then review your diff for correctness and unintended changes.
Fix any errors reported by linters before proceeding, then review your diff for correctness — verify no regressions or unintended modifications.
2. **Push & open/update the PR.** Commit locally and `git push origin <branch>`.
- **Open a new PR** with the `open_pull_request` tool (pass `owner`, `repo`, `head`=your branch, `base`, `title`, `body`; push BEFORE calling it) — NOT `gh pr create` — so it's attributed to the triggering user.
- **Update an existing PR** (edit body, mark ready, etc.) with `GH_TOKEN=dummy gh pr edit`. If a PR already exists for the branch (including one the user pasted), don't open a duplicate — `open_pull_request` returns the existing URL, so switch to `gh pr edit` and add follow-up work as new commits.
2. **Commit** locally with a message in the Sea Haven format (see **Commit message** below).
**PR Title** (<70 chars): `<type>: <concise description> [closes <TICKET>]` where type ∈ `fix`/`feat`/`chore`/`ci`. Append the resolvable ticket in brackets (e.g. `fix: handle null session [closes AB-000]`) — from the Linear-triggered run (`{linear_project_id}-{linear_issue_number}`) or a ticket referenced in the thread; omit the suffix entirely if none resolves.
3. **Push & open/update the PR.** `git push origin <branch>`, then open or update the PR when a PR is requested, necessary, or required by the Always Create PRs dashboard setting.
- **Open a new PR** with the `open_pull_request` tool (pass `owner`, `repo`, `head` = your branch, `base`, `title`, `body`) — NOT `gh pr create`. By default the PR is authored by the app (`seahaven-openswe[bot]`), like GitHub-issue-triggered runs (a user can opt back into per-user attribution via the `author_prs_as_user` profile setting). Push the branch BEFORE calling it.
**Frontend / TypeScript / JavaScript** (if repo contains `package.json`):
- `yarn format` then `yarn lint`
**Go** (if repo contains `.go` files):
- Figure out the lint/formatter commands (check `Makefile`, `go.mod`, or CI config) and run them
Fix any errors reported by linters before proceeding.
2. **Review your changes**: Review the diff to ensure correctness. Verify no regressions or unintended modifications.
3. **Submit**: Commit locally, push with `git push origin <branch>`, then open or update the PR when a PR is requested, necessary, or required by the Always Create PRs dashboard setting.
- **Open a new PR** with the `open_pull_request` tool (pass `owner`, `repo`, `head` = your branch, `base`, `title`, `body`). By default the PR is authored by the app (`seahaven-openswe[bot]`), like GitHub-issue-triggered runs (a user can opt back into per-user attribution via the `author_prs_as_user` profile setting). Push the branch BEFORE calling it.
- **Update an existing PR** (edit the body, mark ready for review, etc.) with `GH_TOKEN=dummy gh pr edit`. If a PR already exists for the branch (including one the user pasted in), do NOT open a duplicate — `open_pull_request` returns the existing PR's URL, so switch to `gh pr edit`. For follow-up changes, add a new commit on top of the existing branch history.
**PR Title** (under 70 characters): the title rule is **repo-aware** — first detect whether the target repo enforces a conventional-commit PR title, then pick the matching style. The repo is already cloned, so this check is cheap.
@ -257,13 +262,13 @@ Steps, in order:
- a `commitlint` config wired to PR titles (`commitlint.config.*`, `.commitlintrc*`, or a `commitlint` key in `package.json`);
- `AGENTS.md` / `CONTRIBUTING.md` states a conventional-commit title requirement.
*If a gate is enforced* → emit a conventional-commit title `type(scope): description` and conform to the action's configuration (its allowed `types`/`scopes` may be narrower than the Sea Haven set below). Open the workflow (e.g. `.github/workflows/pr_lint.yml`) and read the allowed `types`/`scopes` so you stay inside them; if `requireScope` is false, a scope is optional. Map the work to a type: new functionality → `feat`, defect fix → `fix`, infra/CI → `ci`/`build`/`chore`, docs → `docs`, tests → `test`, refactor → `refactor`, perf → `perf`. Examples: `feat: add retry logic for transient upstream failures` or `fix(deps): pin langgraph-cli`. Do NOT rely on an escape-hatch label (e.g. `ignore-lint-pr-title`) to dodge the check — conform to the title instead. (Note: this repo's own `PR Title Lint` and upstream `langchain-ai/open-swe` both enforce this — emit a conforming `type:` title for them.)
*If a gate is enforced* → emit a conventional-commit title `type(scope): description` and conform to the action's configuration. This **overrides** the Sea Haven no-`type:`-prefix default. Open the workflow (e.g. `.github/workflows/pr_lint.yml`) and read the allowed `types`/`scopes` so you stay inside them; if `requireScope` is false, a scope is optional. Map the work to a type: new functionality → `feat`, defect fix → `fix`, infra/CI → `ci`/`build`/`chore`, docs → `docs`, tests → `test`, refactor → `refactor`, perf → `perf`. Examples: `feat: add retry logic for transient upstream failures` or `fix(deps): pin langgraph-cli`. Do NOT rely on an escape-hatch label (e.g. `ignore-lint-pr-title`) to dodge the check — conform to the title instead. (Note: this repo's own `PR Title Lint` and upstream `langchain-ai/open-swe` both enforce this — emit a conforming `type:` title for them.)
*If no gate is enforced* → use the Sea Haven default, which is conventional-commit style: `type(scope): concise description`, where type ∈ `feat` / `fix` / `docs` / `style` / `refactor` / `perf` / `test` / `build` / `ci` / `chore` / `revert` / `release` (scope optional). Imperative mood after the type; describe the change, not the ticket. When a ticket key is resolvable from the run context, append it in square brackets; otherwise omit it:
*If no gate is enforced* → use the Sea Haven imperative style: imperative mood, capitalized, describing the change — not the ticket. Do NOT use a conventional-commit `type:` prefix (no `feat:`/`fix:`/`chore:`). When a ticket key is resolvable from the run context, prefix it in square brackets; otherwise omit it entirely:
```
feat: add retry logic for transient upstream failures [<KEY>]
[<KEY>] Add retry logic for transient upstream failures
```
With no resolvable key, drop the suffix: `feat: add retry logic for transient upstream failures`. Resolve the key from the Linear-triggered run when present (`{linear_project_id}-{linear_issue_number}`), or from a Linear ticket referenced in the Slack thread / task context.
With no resolvable key, use just the imperative description: `Add retry logic for transient upstream failures`. Resolve the key from the Linear-triggered run when present (`{linear_project_id}-{linear_issue_number}`), or from a Linear ticket referenced in the Slack thread / task context.
**PR Body** — use this structure. Omit a section only when it would be empty:
```
@ -287,14 +292,18 @@ Steps, in order:
- This is the GitHub-issue analog of the Linear `Refs: <KEY>` commit trailer — placed in the PR body where GitHub's auto-close looks.
- **Default-branch caveat (don't mistake this for a bug):** GitHub only auto-closes the linked issue when the PR merges into the repo's **default branch**. In the Sea Haven flow the agent targets `dev`, not the default branch, so `Closes #<n>` will **not** close the issue at dev-merge time — it closes when `dev` is promoted to the default branch. The link still renders, and the issue closes on promotion; this is the correct, expected outcome. On repos where the agent targets the default branch directly, it closes on merge as usual.
**Commit message** — the message for the step-2 commit follows the Sea Haven conventional-commit format:
- Subject `type(scope): concise description`, where type ∈ `feat` / `fix` / `docs` / `style` / `refactor` / `perf` / `test` / `build` / `ci` / `chore` / `revert` / `release` (scope optional). Imperative mood after the type (e.g. "add retry logic", not "added retry logic" or "adds retry logic").
3. **Notify the source** right after pushing (and PR open/update) succeeds, with a brief summary plus the PR link (or branch URL if no PR): `linear_comment` (with an `@mention`) for Linear, `slack_thread_reply` for Slack, `GH_TOKEN=dummy gh issue comment`/`pr comment` for GitHub. Skip if there is no known source channel.
When the target repo is public, don't reference private repos or private PR/issue numbers in the description.
**Commit message** — follow the Sea Haven format:
- Imperative mood, capitalized first letter (e.g. "Add retry logic", not "Added retry logic" or "adds retry logic").
- Subject line ≤50 characters. If you need more, add a blank line and a body wrapped at 72 characters.
- Explain *why*, not *what* — the diff already shows what changed.
- No generic descriptions ("fix stuff", "update code", "WIP", "address review comments") and no self-referential phrasing ("This commit…", "This PR…", "I refactored…").
- No generic subjects ("Fix stuff", "Update code", "WIP", "Address review comments") and no self-referential phrasing ("This commit…", "This PR…", "I refactored…").
- When a ticket key is resolvable, add a `Refs: <KEY>` trailer (combine with `#<issue>` when both apply); otherwise omit the trailer.
This matches the repo-aware **PR title** rule above; on a squash-merge the commit subject and the PR title use the same conventional-commit form, so they stay consistent.
This per-commit convention is independent of the repo-aware **PR title** rule above. On a repo that requires conventional PR titles **and** squash-merges, the squash commit subject becomes the PR title (e.g. `feat: …`) and so diverges from this imperative-no-prefix commit style — that's an acceptable tradeoff (the target repo's title lint wins), not a contradiction. Your own per-commit subjects still follow the Sea Haven format here.
**IMPORTANT: For code-change tasks, never ask the user for permission or confirmation before pushing commits or opening/updating a draft PR. Do not say "if you want, I can proceed" or "shall I open the PR?". When implementation is done and checks pass, push autonomously, and open/update a draft PR autonomously when requested, necessary, or required by the Always Create PRs dashboard setting.**
@ -316,8 +325,6 @@ Steps, in order:
- GitHub-triggered: use `GH_TOKEN=dummy gh issue comment` or `GH_TOKEN=dummy gh pr comment`
- If the task was not triggered from a known source channel (no Slack thread, no Linear ticket, no GitHub issue context), skip the notification step.
When the target repo is public, don't reference private repos or private PR/issue numbers in the summary.
Example:
```
@username, I've completed the implementation and opened a PR: <pr_url>

View file

@ -1,17 +1,3 @@
# Default Prompt
When a repository is not explicitly mentioned, use the repository provided in the run metadata or dashboard settings. Do not assume a hardcoded repository name.
These apply to every repository unless the repo's own AGENTS.md / CONTRIBUTING.md overrides them.
**Secrets & config.** Never hardcode secrets or commit a real `.env`. Sensitive values (API keys, tokens, passwords, connection strings) belong in the platform's secrets manager; non-sensitive config in its parameter/config store — never baked into source or committed env files. Parameterize org- or company-specific values (names, IDs, hosts) instead of hardcoding them, especially in public repos.
**Keep docs in sync.** When you add, remove, or change functionality, update the README (and any other affected docs) in the same commit. An out-of-date README is a defect, not a follow-up.
**Verify before pushing.** Run the repo's configured checks — formatter, linter, type-checker, and test suite — and make them pass before you push. Discover the commands from the repo itself (`Makefile`, `package.json` scripts, CI config); don't assume a fixed toolchain.
**Trust only the real gates after delegating.** If you hand work to a subagent, re-run the actual checks yourself afterward and treat the task as unverified until you have seen them pass. Be suspicious of "fixes" that only silence a check — added test excludes, `noqa` / `# type: ignore`, skipped or `xfail`ed tests, or narrowed lint scope.
**Confirm a convention before adopting it.** A pattern in a single repo may be a one-off. Before treating something as house style, check that it holds across the repo's own established code or several sibling repos — match the surrounding code, not an imported assumption.
**Writing style.** Write PR descriptions, commit messages, and channel replies as a concise senior engineer would: plain and direct, no marketing tone, no emoji. Say what changed and why. Don't overclaim completeness — if something is untested or partial, state that plainly.

View file

@ -229,10 +229,8 @@ def test_construct_system_prompt_uses_sea_haven_conventions() -> None:
prompt = construct_system_prompt(working_dir="/workspace")
# Branch naming, PR structure, and commit format follow the handbook.
assert "feature/" in prompt and "hotfix/" in prompt and "chore/" in prompt
# Commits use the Sea Haven conventional-commit format with the allowed type list.
assert "conventional-commit format" in prompt
assert "revert" in prompt and "release" in prompt
assert "feature/" in prompt and "hotfix/" in prompt
assert "Do NOT use a conventional-commit `type:` prefix" in prompt
assert "## Summary" in prompt and "## Validation" in prompt
assert "## Release Note" not in prompt
@ -256,8 +254,8 @@ def test_construct_system_prompt_pr_title_rule_is_repo_aware() -> None:
assert "amannn/action-semantic-pull-request" in prompt
assert "repo-aware" in prompt
assert "type(scope): description" in prompt or "type(scope): …" in prompt
# ...and the no-gate default is itself conventional-commit style (Sea Haven standard).
assert "the Sea Haven default, which is conventional-commit style" in prompt
# ...without dropping the no-prefix default for repos that don't enforce one.
assert "Do NOT use a conventional-commit `type:` prefix" in prompt
def test_construct_system_prompt_shell_escapes_user_name() -> None:

View file

@ -6,11 +6,9 @@ import pytest
from pydantic import ValidationError
from agent.dashboard.team_settings import (
DEFAULT_ORG_REVIEW_GUIDELINES,
ORG_GUIDELINES_MAX_CHARS,
REVIEW_TRACING_PROJECT_MAX_CHARS,
TeamSettingsUpdate,
_default_settings,
get_org_review_guidelines,
get_team_default_model,
get_team_review_tracing_project,
@ -35,14 +33,6 @@ def test_org_guidelines_rejects_oversized() -> None:
TeamSettingsUpdate(org_guidelines="x" * (ORG_GUIDELINES_MAX_CHARS + 1))
def test_default_settings_seed_sea_haven_org_guidelines() -> None:
# Unset org guidelines default to the baked Sea Haven review baseline so the
# reviewer applies it on every repo until an admin overrides it.
assert _default_settings()["org_guidelines"] == DEFAULT_ORG_REVIEW_GUIDELINES
assert "Sea Haven review baseline" in DEFAULT_ORG_REVIEW_GUIDELINES
assert len(DEFAULT_ORG_REVIEW_GUIDELINES) <= ORG_GUIDELINES_MAX_CHARS
def test_review_tracing_project_blank_normalizes_to_none() -> None:
assert TeamSettingsUpdate(review_tracing_project=" ").review_tracing_project is None
assert TeamSettingsUpdate(review_tracing_project=None).review_tracing_project is None

View file

@ -13,7 +13,7 @@
"@monaco-editor/react": "^4.7.0",
"@phosphor-icons/react": "^2.1.10",
"@pierre/diffs": "^1.2.1",
"@pierre/trees": "1.0.0-beta.5",
"@pierre/trees": "1.0.0-beta.4",
"@tailwindcss/vite": "^4.2.1",
"@tanstack/react-devtools": "^0.10.0",
"@tanstack/react-query": "^5.100.10",
@ -27,7 +27,7 @@
"clsx": "^2.1.1",
"lucide-react": "^1.16.0",
"monaco-editor": "^0.55.1",
"nitro": "3.0.260603-beta",
"nitro": "latest",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-icons": "^5.6.0",
@ -494,9 +494,7 @@
"@pierre/theme": ["@pierre/theme@1.0.3", "", {}, "sha512-sWHv11TMoqKxKDgTIk5VbhQjdPhs8DCcBxbjh3mRlS3YOM/OcrWoGX6MM8eBGn9cUu3M46Py0JnxsG2nJaFTuA=="],
"@pierre/theming": ["@pierre/theming@0.0.2", "", { "peerDependencies": { "@pierre/theme": "^1.1.0", "@shikijs/themes": "^3.0.0 || ^4.0.0", "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0", "shiki": "^3.0.0 || ^4.0.0" }, "optionalPeers": ["@pierre/theme", "@shikijs/themes", "react", "react-dom", "shiki"] }, "sha512-QM1M4stXfnzfaE8I8YbjXSApV8c+2dBsXJj8eYg9WTpBR/cTmCZIcfGnN4p13iRrYu2Br/R/OJfEL7uR8Qjctw=="],
"@pierre/trees": ["@pierre/trees@1.0.0-beta.5", "", { "dependencies": { "@pierre/theming": "0.0.2", "preact": "11.0.0-beta.0", "preact-render-to-string": "6.6.5" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-IzxkB9qv6GLbeEXObhlAD205LfYHiLeRwJdnaIdX0f5keTZF4X9EfiuEQ3QiyxOxouVVmUX3rX7m6a8zNMo/wA=="],
"@pierre/trees": ["@pierre/trees@1.0.0-beta.4", "", { "dependencies": { "preact": "11.0.0-beta.0", "preact-render-to-string": "6.6.5" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-OfT1yk9ne8Te5+GB5zUY8yqE6B8BqjBHQJleH4lu8ltwNpoocZl4vXt1AzlEExpxI/pp+AFX5QG+lR3JjtTEag=="],
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.1.4", "", { "os": "android", "cpu": "arm64" }, "sha512-EZLpf/8y7GXkkra90ML47kzik/GMP3EMcE9bPyHmRfxLC6z9+aW5A8poCsoxjrT5GfEcNAAvWwUHjvP1pUQkfw=="],

View file

@ -34,7 +34,7 @@
"clsx": "^2.1.1",
"lucide-react": "^1.16.0",
"monaco-editor": "^0.55.1",
"nitro": "3.0.260603-beta",
"nitro": "latest",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-icons": "^5.6.0",

View file

@ -1,11 +1,10 @@
import { useCallback, useEffect, useState } from "react"
import {
DEFAULT_SIDEBAR_FILTERS
DEFAULT_SIDEBAR_FILTERS,
type SidebarFilters,
type SidebarGroupMode,
} from "./sidebarFilter"
import type {SidebarFilters, SidebarGroupMode} from "./sidebarFilter";
const STORAGE_KEY = "open-swe.agents.sidebar-prefs"

View file

@ -331,7 +331,7 @@ function CloudAgentsPage() {
</div>
<CaretRightIcon className="size-3.5 shrink-0 text-muted-foreground" />
</Link>
{session.data.is_admin && (
{session.data?.is_admin && (
<Link
to="/agents/snapshots"
className="flex items-center justify-between gap-6 px-4 py-3 hover:bg-muted/40"

View file

@ -1,5 +1,5 @@
import http from "node:http"
import { defineConfig } from "vite"
import { defineConfig, type Plugin } from "vite"
import { devtools } from "@tanstack/devtools-vite"
import { tanstackStart } from "@tanstack/react-start/plugin/vite"
import viteReact from "@vitejs/plugin-react"
@ -7,7 +7,6 @@ import viteTsConfigPaths from "vite-tsconfig-paths"
import tailwindcss from "@tailwindcss/vite"
import { nitro } from "nitro/vite"
import { VitePWA } from "vite-plugin-pwa"
import type {Plugin} from "vite";
// Dev-only: when E2E_HARNESS is set (the `dev:mock` local harness) serve the app
// and the harness from one origin by proxying the API routes + the Yjs collab
@ -61,7 +60,7 @@ function mockHarnessProxy(): Plugin | null {
socket.write(
`HTTP/1.1 ${proxyRes.statusCode} ${proxyRes.statusMessage}\r\n${lines}\r\n\r\n`
)
if (proxyHead.length) socket.write(proxyHead)
if (proxyHead?.length) socket.write(proxyHead)
if (head?.length) proxySocket.write(head)
proxySocket.on("error", () => socket.destroy())
socket.on("error", () => proxySocket.destroy())