Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ jobs:
with:
fail-on-severity: high
# LicenseRef-scancode-free-unknown: aiosqlite 0.21.0 — MIT per classifiers, scancode misdetects
# Python-2.0.1: editorconfig 0.17.1 (via jsbeautifier via litestar[standard])
allow-licenses: >-
MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause,
ISC, MPL-2.0, PSF-2.0, Unlicense, 0BSD,
CC0-1.0, Python-2.0,
CC0-1.0, Python-2.0, Python-2.0.1,
LicenseRef-scancode-free-unknown
comment-summary-in-pr: always
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ uv run pre-commit run --all-files # all pre-commit hooks

```text
src/ai_company/
api/ # FastAPI REST + WebSocket routes
api/ # Litestar REST + WebSocket API (controllers, guards, channels)
budget/ # Cost tracking, budget enforcement (pre-flight/in-flight checks, auto-downgrade), billing periods, cost tiers, quota/subscription tracking, CFO cost optimization (anomaly detection, efficiency analysis, downgrade recommendations, approval decisions), spending reports
cli/ # Typer CLI commands
cli/ # CLI interface (future — thin API wrapper if needed)
communication/ # Message bus, dispatcher, messenger, channels, delegation, loop prevention, conflict resolution, meeting protocol
config/ # YAML company config loading and validation
core/ # Shared domain models and base classes
Expand Down Expand Up @@ -83,7 +83,7 @@ src/ai_company/
- **Every module** with business logic MUST have: `from ai_company.observability import get_logger` then `logger = get_logger(__name__)`
- **Never** use `import logging` / `logging.getLogger()` / `print()` in application code
- **Variable name**: always `logger` (not `_logger`, not `log`)
- **Event names**: always use constants from the domain-specific module under `ai_company.observability.events` (e.g. `PROVIDER_CALL_START` from `events.provider`, `BUDGET_RECORD_ADDED` from `events.budget`, `CFO_ANOMALY_DETECTED` from `events.cfo`, `CONFLICT_DETECTED` from `events.conflict`, `MEETING_STARTED` from `events.meeting`, `CLASSIFICATION_START` from `events.classification`, `CONSOLIDATION_START` from `events.consolidation`, `ORG_MEMORY_QUERY_START` from `events.org_memory`). Import directly: `from ai_company.observability.events.<domain> import EVENT_CONSTANT`
- **Event names**: always use constants from the domain-specific module under `ai_company.observability.events` (e.g. `PROVIDER_CALL_START` from `events.provider`, `BUDGET_RECORD_ADDED` from `events.budget`, `CFO_ANOMALY_DETECTED` from `events.cfo`, `CONFLICT_DETECTED` from `events.conflict`, `MEETING_STARTED` from `events.meeting`, `CLASSIFICATION_START` from `events.classification`, `CONSOLIDATION_START` from `events.consolidation`, `ORG_MEMORY_QUERY_START` from `events.org_memory`, `API_REQUEST_STARTED` from `events.api`). Import directly: `from ai_company.observability.events.<domain> import EVENT_CONSTANT`
- **Structured kwargs**: always `logger.info(EVENT, key=value)` — never `logger.info("msg %s", val)`
- **All error paths** must log at WARNING or ERROR with context before raising
- **All state transitions** must log at INFO
Expand Down
138 changes: 66 additions & 72 deletions DESIGN_SPEC.md

Large diffs are not rendered by default.

17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ AI Company lets you spin up a virtual organization staffed entirely by AI agents

## Current Capability Snapshot

### Implemented (M0–M4 complete, M5 in progress)
### Implemented (M0–M6 complete)

- **Company Config + Core Models** - Strong Pydantic validation, immutable config models, runtime state models
- **Provider Layer** - LiteLLM-based provider abstraction with routing, retry, and rate limiting
Expand All @@ -24,22 +24,25 @@ AI Company lets you spin up a virtual organization staffed entirely by AI agents
- **Memory Interface (M5)** - Pluggable `MemoryBackend` protocol with capability discovery, shared knowledge protocol, domain models, config, factory, and context injection retrieval pipeline (ranking, token-budget formatting). Shared organizational memory via `OrgMemoryBackend` protocol with hybrid prompt+retrieval backend. Memory consolidation/archival with pluggable strategies and retention enforcement
- **Coordination Error Taxonomy (M5)** - Post-execution classification pipeline detecting logical contradictions, numerical drift, context omissions, and coordination failures
- **Budget Enforcement (M5)** - `BudgetEnforcer` service with pre-flight checks, in-flight budget checking, auto-downgrade, configurable cost tiers, and quota/subscription tracking; `CostOptimizer` CFO service with anomaly detection, efficiency analysis, downgrade recommendations, and approval decisions; `ReportGenerator` for multi-dimensional spending reports
- **Litestar REST API (M6)** - 13 controllers + WebSocket handler covering company, agents, tasks, budget, approvals, analytics, messages, meetings, projects, departments, artifacts, providers, health, and WebSocket real-time feed
- **Human Approval Queue (M6)** - Approval submission, approve/reject with reason, list/filter by status, WebSocket notifications for approval events
- **WebSocket Real-Time Feed (M6)** - Channel-based subscriptions (tasks, agents, budget, messages, system, approvals), per-channel payload filters, message-bus bridge
- **Route Guards (M6)** - Role-based read/write access control (stub auth for M6; real JWT/OAuth planned for M7)

### Not implemented yet (planned milestones)

- **Memory Backends (M5)** - Initial Mem0 adapter backend ([ADR-001](docs/decisions/ADR-001-memory-layer.md)) pending; research backends (GraphRAG, Temporal KG) planned
- **API Layer (M6)** - `api/` package and route modules are placeholders
- **CLI Surface (M6)** - `cli/` package is placeholder-only
- **Security/Approval System (M7)** - `security/` package is placeholder-only
- **Advanced Product Surface** - web dashboard, HR workflows, progressive trust, and external integrations
- **CLI Surface** - `cli/` package is placeholder-only
- **Security/Approval System (M7)** - `security/` package is placeholder-only; real authentication (JWT/OAuth), progressive trust, SecOps agent
- **Advanced Product Surface** - web dashboard, HR workflows, and external integrations

## Status

**M5: Memory & Budget** in progress (M0 Tooling, M1 Config & Core, M2 Providers, M3 Single Agent, M4 Multi-Agent — all done). See [DESIGN_SPEC.md](DESIGN_SPEC.md) for the full high-level specification.
**M7: Security & HR** next (M0–M6 all done). See [DESIGN_SPEC.md](DESIGN_SPEC.md) for the full high-level specification.

## Tech Stack

- **Python 3.14+** with FastAPI, Pydantic, Typer
- **Python 3.14+** with Litestar, Pydantic
- **uv** as package manager, **Hatchling** as build backend
- **LiteLLM** for multi-provider LLM abstraction
- **structlog** for structured logging and observability
Expand Down
10 changes: 8 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ dependencies = [
"jinja2==3.1.6",
"jsonschema==4.26.0",
"litellm==1.82.0",
"litestar[standard,structlog,pydantic,brotli,prometheus]==2.21.1",
"pydantic==2.12.5",
"pyyaml==6.0.3",
"structlog==25.5.0",
]

[build-system]
requires = ["hatchling"]
requires = ["hatchling==1.29.0"]
build-backend = "hatchling.build"

[tool.hatch.version]
Expand Down Expand Up @@ -94,7 +95,7 @@ select = [
"FURB", # refurb
"RUF", # ruff-specific rules
"S", # flake8-bandit (security)
"FAST", # fastapi
# "FAST" removed — using Litestar, not FastAPI
"ASYNC", # flake8-async
"FBT", # flake8-boolean-trap
"PL", # pylint
Expand Down Expand Up @@ -160,6 +161,10 @@ ignore_missing_imports = true
module = "aiosqlite.*"
ignore_missing_imports = true

[[tool.mypy.overrides]]
module = "litestar.*"
ignore_missing_imports = true

[tool.pydantic-mypy]
init_forbid_extra = true
init_typed = true
Expand Down Expand Up @@ -200,6 +205,7 @@ markers = [
addopts = ["--strict-markers", "--strict-config", "-ra", "--tb=short"]
filterwarnings = [
"error",
"ignore:Core Pydantic V1 functionality:UserWarning",
]
Comment on lines 206 to 209
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find project-owned Pydantic V1 APIs that the global warning filter would hide.
rg -n --glob 'src/**/*.py' --glob 'tests/**/*.py' \
  -e '\bpydantic\.v1\b' \
  -e 'from pydantic\.v1 import' \
  -e '\broot_validator\s*\(' \
  -e '\bvalidator\s*\(' \
  -e '\bparse_obj_as\s*\('

Repository: Aureliolo/ai-company

Length of output: 46


🏁 Script executed:

grep -n "pydantic" pyproject.toml

Repository: Aureliolo/ai-company

Length of output: 221


🏁 Script executed:

fd --type f --extension py | head -20 | xargs grep -l "BaseModel\|model_validator\|ConfigDict" | head -10

Repository: Aureliolo/ai-company

Length of output: 218


🏁 Script executed:

grep -n "litestar" pyproject.toml

Repository: Aureliolo/ai-company

Length of output: 163


🏁 Script executed:

# Check git context to see if there's a reason for this filter
git log --oneline --all -- pyproject.toml | head -10

Repository: Aureliolo/ai-company

Length of output: 781


🏁 Script executed:

# Search for any comments or notes about why Pydantic V1 warnings are being suppressed
rg -n "Pydantic\s*V1|pydantic.*v1" pyproject.toml

Repository: Aureliolo/ai-company

Length of output: 124


🏁 Script executed:

# Check if any code comments reference this warning suppression
rg -n "Core Pydantic V1 functionality" .

Repository: Aureliolo/ai-company

Length of output: 141


Scope the Pydantic V1 warning filter to the specific third-party emitter.

Line 208 suppresses Core Pydantic V1 functionality warnings globally. While the project is fully Pydantic v2 compliant (verified in code), suppressing warnings at the test level masks the signal for any future regressions. Rather than "ignore:Core Pydantic V1 functionality:UserWarning", scope this to the specific library emitting the warning (likely Litestar), for example: "ignore:Core Pydantic V1 functionality:UserWarning:litestar" or add filterwarnings only for specific affected tests if warnings originate from Litestar's own code path.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pyproject.toml` around lines 206 - 209, The global warning filter entry
"ignore:Core Pydantic V1 functionality:UserWarning" should be narrowed to the
specific emitter to avoid masking future regressions; update the filterwarnings
list entry to include the third-party module (e.g. replace it with "ignore:Core
Pydantic V1 functionality:UserWarning:litestar") or move a scoped filter to the
specific tests that trigger it so only the Litestar-emitted Pydantic V1 warning
is suppressed.


# ---------------------------------------------------------------------------
Expand Down
5 changes: 5 additions & 0 deletions src/ai_company/api/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""API module — Litestar REST + WebSocket interface.

Import ``create_app`` from ``ai_company.api.app`` directly to
avoid circular imports with ``config.schema``.
"""
Loading