context: load project skills from git root#2164
Conversation
|
Proofs:
uv run pytest tests/sdk/context/skill/test_load_project_skills.py -q
# => 18 passed
TMP=/workspace/tmp_agents_repo
mkdir -p "$TMP/subdir" "$TMP/.git"
printf "%s\n" "# Project Guidelines" "" "SENTINEL_ROOT_123" > "$TMP/AGENTS.md"
cd "$TMP/subdir"
PYTHONPATH=/path/to/this/branch/openhands-sdk \
LLM_API_KEY=$OPENAI_API_KEY LLM_MODEL=openai/gpt-5-nano \
openhands --override-with-envs --headless --task "Reply with exactly: OK"
# (no AGENTS.md in subdir; only in repo root)
# verify saved SystemPromptEvent includes root AGENTS.md content:
python - <<"PY"
import json
from pathlib import Path
needle = "SENTINEL_ROOT_123"
conv = Path.home() / ".openhands" / "conversations"
# pick the newest conversation dir
latest = max(conv.iterdir(), key=lambda p: p.stat().st_mtime)
event0 = sorted((latest / "events").glob("event-00000-*.json"))[0]
blob = event0.read_text()
assert needle in blob
print("...", blob[blob.index(needle)-80:blob.index(needle)+len(needle)+80], "...", sep="")
PY
# output contains:
# [BEGIN context from [agents]]
# # Project Guidelines
#
# SENTINEL_ROOT_123
#
# [END Context] |
API breakage checks (Griffe)Result: Passed |
|
Follow-up: fixed flaky xdist teardown assertion in CI. CI was failing with:
Root cause: Local proof (matches CI style): uv run pytest -n 4 --maxfail=1 tests/sdk -q
# => 2376 passedCI for this PR is green now. |
all-hands-bot
left a comment
There was a problem hiding this comment.
🟡 Acceptable - Solves Real Problem, Minor Complexity Concern
Taste Rating: 🟡 Acceptable
Solid pragmatic fix. You're solving an actual user pain point (CLI users in subdirs missing repo-root AGENTS.md). The git root detection is clean - no shelling out, handles worktrees. Tests exercise real behavior.
One concern: Approaching the complexity threshold with nested loops. See inline comment.
Verdict: ✅ Worth merging after considering the simplification suggestion.
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
6b6ec21 to
59c1018
Compare
Co-authored-by: openhands <openhands@all-hands.dev>
|
Thanks for the review + the simplification suggestion. Addressed: I refactored the inner merging logic into a small helper ( Also added a more integration-style test (closer to the CLI “live test” proof):
It sets up a temp repo like:
Then it builds Relevant commands run locally: uv run pytest -q tests/sdk/context/skill/test_load_project_skills.py \
tests/sdk/conversation/test_repo_root_project_skills.py |
all-hands-bot
left a comment
There was a problem hiding this comment.
🟡 Acceptable - Solid Pragmatic Fix
Taste Rating: 🟡 Acceptable
You're solving a real problem (CLI users in subdirs missing repo-root AGENTS.md). The git root detection is clean - no shelling out, handles worktrees. Tests exercise real behavior, not mocks.
The complexity concern from the previous review was addressed by extracting _merge_loaded_skills(). Still 3-4 nesting levels, but justified by the requirements (multiple roots × multiple dirs × multiple skill types).
Key Insight: Simple data flow eliminates special cases - search both roots, merge with precedence. No edge case handling needed.
Verdict: ✅ Worth merging. Backward compatible, well-tested, solves actual user pain point.
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
enyst
left a comment
There was a problem hiding this comment.
😂 TestLLM was merged too recently, finally it found it after updating
What
When
load_project_skills()is called from a subdirectory inside a git repo, it now also loads third-party files (e.g.AGENTS.md) and skills directories from the git repo root.Why
OpenHands CLI passes the current working directory to
load_project_skills(). If the user runsopenhandsfrom a subdirectory, repo-level guidance in the repo root (AGENTS.md,.agents/skills/, etc.) was previously missed.How
.gitentry (dir or file).[work_dir, git_root]with work_dir precedence for duplicates.Tests
uv run pytest tests/sdk/context/skill/test_load_project_skills.py -qManual proof (CLI)
Ran OpenHands CLI headless from a git subdirectory with only root
AGENTS.mdpresent and confirmed the system prompt event included the root content.Commands used (high level):
.git/+ rootAGENTS.mdcontainingSENTINEL_ROOT_123openhands --override-with-envs --headless ...fromsubdir/SENTINEL_ROOT_123appears under[BEGIN context from [agents]]in the saved SystemPromptEvent JSON@enyst can click here to continue refining the PR
Agent Server images for this PR
• GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server
Variants & Base Images
eclipse-temurin:17-jdknikolaik/python-nodejs:python3.12-nodejs22golang:1.21-bookwormPull (multi-arch manifest)
# Each variant is a multi-arch manifest supporting both amd64 and arm64 docker pull ghcr.io/openhands/agent-server:62438a2-pythonRun
All tags pushed for this build
About Multi-Architecture Support
62438a2-python) is a multi-arch manifest supporting both amd64 and arm6462438a2-python-amd64) are also available if needed