<!-- claude-slack-attribution -->
_Requested by **roshan desai** · [Slack
thread](https://onyx-company.slack.com/archives/C07V90R4GTX/p1792009768004209?thread_ts=1792009768.004209&cid=C07V90R4GTX)_
Before: an agent could start work on a stale branch or an old `main`, so
it read an out-of-date feature map (`.agents/feature-map/`) and missed
recent changes.
After: at session start, Claude Code and Codex fetch `origin/main` and
tell the agent to rebase on it only when the branch has merge conflicts
with `origin/main` or its merge base with `origin/main` is more than 3
days old. Otherwise the hook is silent. Keeping a branch current avoids
a much more involved conflict resolution later.
This adds a SessionStart hook that, when it fires, reports how far HEAD
is behind `origin/main`, why (conflicts, stale, or both) and which
`.agents/` files changed on main since the branch diverged. A branch
that already contains `origin/main`, or is only a few recent commits
behind without conflicts, gets no message.
How: `.agents/hooks/ensure_latest_main.py` runs `git fetch origin main`
(20 second limit, no credential prompts) and checks for conflicts with
`git merge-tree --write-tree HEAD origin/main` (exit 1) and for
staleness (merge-base commit date older than `_STALE_AFTER_DAYS = 3`),
and prints a message that the agent reads as context only if either
applies. It never rebases, pulls or touches the working tree, and it
always exits 0, so an offline or failed fetch only adds a note. It is
wired for the `startup` and `resume` sources in `.claude/settings.json`
and `.codex/hooks.json`. Other agents (for example Cursor, which has no
hook config in this repo) get the same rule as a line in `AGENTS.md`.
Set `ONYX_SKIP_MAIN_SYNC_CHECK=1` (or `true`, `yes`, `on`) to turn it
off; `0` or `false` leaves it on. It also repeats the check, fetching at
most once an hour, on later prompts.
## How Has This Been Tested?
External dependency tests
(`backend/tests/external_dependency_unit/scripts/test_ensure_latest_main_repos.py`,
run by the `scripts` group of the PR workflow) run the script against
throwaway git repos: up to date, fresh and clean (silent), merge base
older than 3 days (warns), conflicting (warns), a dirty or
untracked-only tree, an offline remote, malformed payloads,
skip-variable values, fetch throttling, and a directory that is not a
repo. All exit 0 and leave the working tree unchanged. A stubbed unit
test (`backend/tests/unit/scripts/test_ensure_latest_main.py`) covers
the ssh command handling. `ruff` and `mypy --strict` pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01TYt2dm3XFyAdzZygsG6CN7
---
_Generated by [Claude
Code](https://claude.ai/code/session_01TYt2dm3XFyAdzZygsG6CN7)_
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Agents now check at session start and on later prompts whether their
checkout conflicts with `origin/main` or is stale, so they stop working
from an outdated `.agents/feature-map/` and missing recent changes.
- Claude Code and Codex run a new hook that fetches `origin/main` and
tells the agent how to update, without ever pulling, rebasing, or
touching the working tree.
- The hook speaks only when the branch has merge conflicts with
`origin/main` (via `git merge-tree --write-tree`) or its merge base is
more than 3 days old; a branch that is merely a few recent commits
behind stays silent. It always exits 0, so offline or hanging fetches
degrade gracefully, and on prompts it fetches at most once an hour. Set
`ONYX_SKIP_MAIN_SYNC_CHECK` to a truthy value to disable it. When a
merge or rebase is already in progress, it tells the agent to finish or
abort it instead of starting another update.
- Other agents without hook config get the same rule in `AGENTS.md`, and
the suggested update command uses an explicit refspec so it works in
single-branch clones.
- Git-repo integration tests run under the external dependency test
group; the unit file keeps the one fully stubbed test.
<sup>Written for commit ad0de70fed.
Summary will update on new commits.</sup>
<a
href="https://cubic.dev/pr/onyx-dot-app/onyx/pull/16043?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="View guided diff"
src="https://www.cubic.dev/buttons/review-in-cubic-light.svg"></picture></a>
<a
href="https://www.cubic.dev/action/auto-fix/pr/onyx-dot-app/onyx/16043?returnTo=https%3A%2F%2Fgithub.com%2Fonyx-dot-app%2Fonyx%2Fpull%2F16043&source=description"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"><img
alt="Turn on auto-fix"
src="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added checks at session start and during later prompts to flag
branches that may conflict with `main` or have an outdated merge base,
with guidance for updating. Checks use the last known remote state if
fetching fails and do not change the working tree.
* Prompt-triggered fetches are limited to once per hour.
* **Documentation**
* Added guidance for keeping work up to date while preserving
uncommitted changes.
* **Tests**
* Added coverage for up-to-date, stale, conflicting, offline, and other
branch scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude <noreply@anthropic.com>
* refactor salesforce sqlite db access
* more refactoring
* refactor again
* refactor again
* rename object
* add finalizer to ensure db connection is always closed
* avoid unnecessarily nesting connections and commit regularly when possible
* remove db usage from csv download
* dead code
* hide deprecation warning in ddtrace
* remove unused param
* local testing WIP
* stuff for pytest-dotenv
* autodetect filter types instead of assuming last modified always works (it doesn't)
Move filtering responsibility up instead of making utility calls excessively stateful
* fix how changed parent id's are yielded
* remove slow part of test
* clean up comments
* small refactor
* more refactor
* add normalize test
* checkpoint and comments
* add helper function
* fix gitignore
* add gitignore
* update pyproject
* delta updates
* remove comments
* fix time import
* fix set init
* add salesforce env vars
* cleanup
* more cleanup
* filtered item is unbound here
* typo
* fix suffix check
* fix empty type query
---------
Co-authored-by: Richard Kuo (Onyx) <rkuo@onyx.app>
* add pip retries to the github workflows too
* let's try running on amd64 ... docker builds are unusually flaky
* bump
* try large
* no yaml anchors
* switch back down to Amd64
---------
Co-authored-by: Richard Kuo <rkuo@rkuo.com>