Project Context for AI Agents¶
This file contains critical rules and patterns that AI agents must follow when implementing code in this project. Focus on unobvious details that agents might otherwise miss.
Technology Stack & Versions¶
Core Technologies¶
- Backend: Python 3.13+, FastAPI
>=0.115.6, Uvicorn>=0.34.0 - Agent Runtime: DeepAgents
>=0.6.8(create_deep_agent), LangGraph checkpoint-sqlite>=3.1.1 - Frontend: React
^18.3.1, Vite^5.4.0, TypeScript^5.5.3(strict mode) - UI: shadcn/ui (zinc base, lucide icons), Radix UI, Tailwind CSS
^3.4.7
Key Dependencies¶
pydantic>=2.10.0+pydantic-settings>=2.7.0— all data models & configlangchain-mcp-adapters>=0.3.0— optional MCP tool loadingsse-starlette>=2.2.0— SSE streamingtransitions>=0.9.0— legacy FSM (being phased out)pytest>=8.0.0,pytest-asyncio>=0.24.0
Critical Version & Compatibility Invariants¶
- MCP tools bypass the permissions model (ADR-013) — tools loaded via
MCP_SERVERSdo NOT getFilesystemBackendroute enforcement. Treat them as untrusted. - Any filesystem-mutating tool must be added to
interrupt_oninagent/runtime.py— otherwise it bypasses HITL review. - Checkpointer: sync
SqliteSaver, created once at startup (not inside request/async context) — avoids both theRuntimeError: no running event loopand blocking the event loop.AsyncSqliteSaverwas reverted; do not reintroduce it. - Deprecated modules are off-limits for new code:
models/,state/,scoring/,orchestrator/,storage/(Siemens FSM being phased out in Phase 4). astream_events(version="v3")is the streaming contract (ADR-012) — don't write v2-only consumers; graceful v2 fallback only.- Never hardcode paths — use
ROOT_DIR/WORKSPACE_DIR/CONFIG_DIRfromconfig.py.APP_ROOT_DIRpins the root in Docker (path-depth differs from local; wrong resolution writes outside mounted volumes and data vanishes on restart).
Critical Implementation Rules¶
Language-Specific Rules¶
Python (Backend)¶
- 🚫 NEVER fabricate output. Never silently convert failed agentic output into fabricated success. Every failure is an explicit error/retry state. This is the project's core principle — the reason it exists.
- Python 3.13+ idiomatic syntax — type hints,
|union syntax,matchstatements. No backports orfrom __future__workarounds. - Set credentials in
os.environBEFORE importing LangChain —init_chat_model()reads from env, not pydantic-settings. Import order is a security boundary, not just style. New credential fields go inSettings(config.py) AND are propagated toos.environ. - Import order: standard library → third-party → application (see
coding-guidelines.md§2.2). - PEP 8 with 100-character line limit.
- pydantic v2 for all data models;
pydantic-settingsfor configuration.
TypeScript (Frontend)¶
- TypeScript strict mode (enforced in
tsconfig.json), BUTnoUnusedLocals/noUnusedParametersare deliberatelyfalse— do NOT "fix" by enabling them. - Path alias
@/*→./src/*— use@/components/...,@/lib/utils, etc. - Functional components with hooks — no class components.
- Centralized API client — use
@/api/clientfor REST,@/api/deepagentsfor agent/interrupt calls. Don't scatter rawfetchcalls. - Frontend error handling mirrors backend — surface API errors (throw), don't swallow or convert to
null. cn()utility from@/lib/utilsfor conditional class merging.
Framework-Specific Rules¶
React (Frontend)¶
- shadcn/ui components from
@/components/ui/— use these, not hand-rolled equivalents. - Radix UI primitives for complex interactions (dialog, dropdown, tabs, tooltip, etc.).
- Tailwind CSS for styling — no inline styles or CSS modules.
- Component structure: functional components with typed
Propsinterface, following the shadcn pattern (seecoding-guidelines.md§3.2). - SSE streaming via
useDeepAgentStreamhook — binds to backendastream_eventsoutput. Don't spin up rawEventSourceper component (SSE is unidirectional, ~6 concurrent connections/browser on HTTP/1.1 — connection exhaustion risk).
FastAPI (Backend)¶
- File-size limits are hard rules: route files < 150 lines, services/repositories < 200, agent runtime < 200.
- API route pattern:
APIRouter(prefix="/api", tags=[...])with pydanticRequestModel/ResponseModel(seecoding-guidelines.md§2.4). - SSE via
StreamingResponse— one/api/sseendpoint with event type tagging (ADR-005). - Always use
get_deep_agent_runtime()factory inagent/runtime.py— never constructcreate_deep_agentad-hoc (divergent configs).
LangGraph / DeepAgents¶
- Threads are the single source of truth — native LangGraph checkpoints persisted via
SqliteSaver. Don't invent a parallel thread store; metadata goes in checkpoint metadata. - Supervisor + teams hierarchy — supervisor routes intents via LLM; teams are DeepAgents sub-graphs.
- @mention routing is DEFERRED — don't build a hard-coded @mention parser; the supervisor handles routing.
- New filesystem routes need explicit access mode — don't default to read/write.
/kb/and/skills/are read-only;/workspace/is read/write (CompositeBackend, ADR-003). astream_events(version="v3")for streaming (see Technology Stack).
Testing Rules¶
- Framework:
pytest+pytest-asyncio. Test location:backend/tests/, one file per module (e.g.,test_scoring.py,test_threads.py). - Run before commit:
pytest backend/tests— all tests must pass. - Mock the LLM/runtime boundary — tests must NEVER depend on a live model or live MCP server (flaky, slow, costly).
- Test the interrupt/resume contract, not the human — HITL "E2E" means verifying an interrupt is raised, persisted, and resumable.
- Use a separate test DB — don't clobber the dev
checkpoints.db; the syncSqliteSaverconnection is created once at startup. - Know your async/sync boundary — async tests use
pytest.mark.asyncio; don't mix with the sync checkpointer. - Don't add tests to deprecated modules (
scoring/,state/FSM, etc.) — new tests go to the LangGraph/thread layer. - Shared fixtures go in
conftest.py— don't duplicate setup across test files. - Test structure: class-based (
TestFeature) with descriptive methods (test_happy_path,test_error_case).
Code Quality & Style Rules¶
- 🚫 NO Sandbox Execution (headline rule) — no shell/code-runner tools, period, until a real sandbox exists. Arbitrary code execution bypasses
FilesystemBackendroute enforcement and is a fabrication vector. File mutation is gated byinterrupt_on; arbitrary code execution is not allowed at all. - Single Responsibility — each file has one job (see file-size limits in Framework section).
- Provenance on artifacts/events, not every helper — keep it lean. Trust levels:
generated,trusted,verified-tool-call,fallback. Tag honestly; the trust tag is an audit trail, not a license to fabricate. - Preserve
snake_caseAPI contract on the frontend — backend returnssnake_case(e.g.,idea_id,composite_score); don't "helpfully" convert tocamelCasein TS. - Docstrings: Google-style with
Args:/Returns:; inline comments explain WHY, not WHAT;# TODO:for planned work. - Naming: Python
snake_case/PascalCase; TScamelCase/PascalCase; test filestest_<module>.py.
Development Workflow Rules¶
- Read docs in order before implementing (
tasks.md→features.md→architecture.md→architecture-decisions.md→coding-guidelines.md→code-review-guidelines.md→prd.md→product-context.md) — not optional. [IMPLEMENTED]requires the code to actually run and pass tests — not just exist. Never fabricate completion.- Credential documentation chain (4 steps): add field to
Settings→ propagate toos.environ→ document inarchitecture.md→ document incoding-guidelines.md. - Commit format:
type(scope): description— scope required (backend,frontend,agent,config,docs); description imperative, lowercase, no period. - Self-review checklist gate (
agents.md§7.1) — never mark[COMPLETED]without running it. - Branch-based workflow — don't commit directly to main; use
feat/,fix/,refactor/,docs/branches. - Task status markers:
[PENDING],[IN PROGRESS],[IMPLEMENTED],[COMPLETED],[DEFERRED]. - Cross-reference rules — when updating docs, update related cross-references (see
agents.md§6). - Sprint numbering rule (decision 2026-07-21):
planning-artifacts/epics.mdalways holds the current sprint's backlog. When a sprint is delivered, its epic breakdown is archived asplanning-artifacts/sprint-N.md(e.g., Sprint 1 = EP-0..EP-7 →sprint-1.md). Epic numbers continue across sprints and never restart at 1 (Sprint 2 = EP-8..EP-12). Story IDs follow the epic number (8-1,8-2, ...). Never overwriteepics.mdwith a renumbered backlog — archive first, then continue the sequence. - Jules delegation rule (decision 2026-07-21, updated to GitHub-issue flow): User stories (user-visible, multi-file, need product context) are executed by local agents via the BMAD story workflow. Small self-contained, verifiable items are delegated to the Google Jules agent and tracked as GitHub issues (label
jules+ priority labelP0–P3+ topic labeltech-debt/test-gap/refactor/docs, milestone = current sprint). Flow:deferred-work.mdis the raw capture ledger (unchanged) → triage creates a GitHub issue (self-contained body: Context / First verify / Do / Pass when / Out of scope / Branch line — Jules has no BMAD skills or project memory) → copy the issue body as the Jules task prompt → one PR todevelop→ human review gate, never auto-merge → merge auto-closes the issue (Closes #N) → ledger entry marked RESOLVED. Issues are generated at triage time, never pre-generated in bulk beyond known items. Every issue body includes a mandatory "First verify (ledger may be stale)" step. Jules-eligible topics (all must hold): self-contained (one concern, one PR, ≤~5 files), objectively verifiable pass/fail, no architectural decisions, not blocked on missing infra, doesn't touch deprecated modules (models/,state/,scoring/,orchestrator/,storage/). Architectural work (Runner.py LangGraph migration, Recharts v3, SSE subscription consolidation) and auth-blocked items stay out of the Jules queue. - Windows-First Documentation (decision 2026-08-16, Sprint 2): all documentation ships with Windows alternatives from the first draft; docs PRs are gated on it. Standard lives in
docs/coding-guidelines.md§6.3 (Epic 7 retrospective item #2).
Branch Management Rules¶
CRITICAL: NEVER commit or push directly to main or develop branches
All changes MUST go through pull requests. Feature PRs target develop only.
Branch Naming Convention¶
- Format:
feat/<story-key>-<short-description> - Example:
feat/1-2-update-config-py - Story keys use the story identifier (e.g.,
1-2,2-5) - For fixes:
fix/<story-key>-<short-description> - For refactoring:
refactor/<story-key>-<short-description> - For docs:
docs/<story-key>-<short-description> - For production emergencies:
hotfix/<issue-description>— can merge to bothmainanddevelop
PR Rules¶
- One story = one PR (never share a PR across multiple stories)
- PR target: Always
developbranch (nevermain) - Exception:
hotfix/branches may targetmaindirectly, then sync todevelop - PR title format:
<story-key>: <description> - PR body: Reference story file and acceptance criteria
- Main branch is production — only
developorhotfix/can merge intomain
Commit Message Format¶
- Format:
type(scope): description - Types:
feat,fix,chore,docs,style,refactor,perf,test - Scope examples:
ci,backend,frontend,e2e - Examples:
feat(backend): add thread archive endpointfix(ci): correct workflow triggertest(e2e): add login flow tests
Self-Review Checklist (Before Creating PR)¶
- All acceptance criteria met
- Tests pass locally
- No console errors or warnings
- Code follows project conventions
- Documentation updated if needed
- No debugging code left behind
- Branch naming convention followed
- PR targets
developbranch
Critical Don't-Miss Rules¶
- 🚫 Never fabricate output — no silent fallback to fabricated success. The #1 rule of this project.
- 🚫 Never add credentials directly to code — use
.envfiles andpydantic-settings. - 🚫 Never build on deprecated modules —
models/,state/,scoring/,orchestrator/,storage/are being phased out. - 🚫 Never add shell/code-runner tools — sandbox execution is deferred.
- Any new filesystem-mutating tool MUST be added to
interrupt_on— otherwise it bypasses HITL review (the most likely silent failure). - LangSmith tracing ships prompts/tool calls to an external service — don't enable
langsmith_enabledwithout knowing what's traced; never put secrets in prompts. - One checkpointer connection, created at startup, reused everywhere — don't create new
SqliteSaverconnections (sharedcheck_same_thread=Falseconnection; new ones causedatabase is locked). MCP_SERVERSfailures are silently skipped — invalid JSON or unavailable adapter means tools silently don't load; verify they're actually loaded.- Route all file access through the
CompositeBackend— never write to hardcoded absolute paths outside configured routes (containment boundary). - Handle SSE reconnect/partial streams — EventSource auto-reconnects, but don't assume a stream is complete on connection drop.
Usage Guidelines¶
For AI Agents:
- Read this file before implementing any code
- Follow ALL rules exactly as documented
- When in doubt, prefer the more restrictive option
- Update this file if new patterns emerge
For Humans:
- Keep this file lean and focused on agent needs
- Update when technology stack changes
- Review quarterly for outdated rules
- Remove rules that become obvious over time
Last Updated: 2026-08-01