This repo is a monorepo: core stays stable, apps iterate fast, and shared packages form the only legal bridge.
syris/
├── core/
│ └── syris_core/ # SYRIS core (Python, uv)
│ ├── pyproject.toml
│ ├── src/syris_core/ # import namespace
│ └── tests/
├── apps/
│ ├── dashboard/ # mission control (Next.js)
│ ├── docs/ # internal docs (Next.js + Fumadocs)
│ └── nutrition/ # standalone app(s)
├── packages/
│ ├── shared-types/ # cross-app contracts (TS/JSON schema)
│ ├── api-client/ # typed client for core API (TS)
│ └── ui/ # optional shared UI primitives
├── archive/ # deprecated modules (read-only)
└── ops/ # deployment and ops artifactssrc/syris_core/
├── main.py # Boot: wire loops + API
├── schemas/ # Pure Pydantic v2 — no DB, no logic
│ ├── events.py # MessageEvent, RoutingDecision
│ ├── tasks.py # Task, Step
│ ├── tools.py # ToolCall, ToolResult
│ ├── audit.py # AuditEvent
│ ├── approvals.py # Approval
│ ├── safety.py # AutonomyLevel, RiskLevel enums
│ └── common.py # shared value types
├── pipeline/ # Thin stage orchestrators
│ ├── normalizer.py
│ ├── router.py
│ ├── executor.py
│ └── runner.py # Main pipeline loop
├── routing/ # Router internals (separate from pipeline/)
│ ├── filters.py # Hard filters: spam, quiet hours
│ ├── fastpath.py # Deterministic intent DSL
│ ├── rules_eval.py # Rules engine evaluation
│ └── llm_fallback.py # LLM — last resort only
├── tasks/ # Task engine
│ ├── engine.py
│ ├── step_runner.py
│ ├── state.py # State machine enforcement
│ └── recovery.py # Restart reconciliation
├── tools/ # Tool runtime
│ ├── registry.py
│ ├── executor.py # Gates + idempotency + audit
│ ├── idempotency.py
│ ├── adapter.py # BaseTool ABC
│ └── builtin/noop.py
├── integrations/
│ ├── inbound/base.py # InboundAdapter ABC
│ ├── outbound/base.py # OutboundAdapter ABC
│ └── mcp/ # Milestone 6
│ ├── connection.py
│ ├── provider.py
│ ├── adapter.py
│ └── trust.py
├── scheduler/
│ ├── scheduler.py
│ ├── watchers/
│ │ ├── base.py
│ │ └── heartbeat.py
│ └── rules/
│ ├── engine.py
│ └── models.py
├── safety/
│ ├── autonomy.py
│ ├── risk.py
│ ├── gates.py
│ └── dryrun.py
├── observability/
│ ├── audit.py # AuditWriter — sole emit point
│ ├── projections.py # Sync updaters (in-transaction)
│ ├── health.py
│ └── alarms.py
├── secrets/store.py # get_secret() only
├── storage/
│ ├── db.py
│ ├── models.py # ORM models (separate from schemas/)
│ ├── repos/ # One repo per aggregate root
│ └── migrations/ # Alembic
├── api/
│ ├── app.py
│ ├── auth.py
│ └── routes/
└── workers/ # Milestone 7 skeletonschemas/ contains Pydantic v2 data contracts only — no DB access, no logic. ORM models live in storage/models.py. routing/ is separate from pipeline/ so that fastpath.py and rules_eval.py can be unit-tested without instantiating the full pipeline.
Anything under apps/* is a standalone application and must not import from core/*.
Allowed: apps/* → packages/*
Not allowed: apps/* → core/*
All integration code lives under core/syris_core/ because integrations deploy together with the control plane, share the secrets and scopes policy, and participate in the same audit and trace runtime.
storage/repos/ contains one repository object per aggregate root. Pipeline and task engine code imports from repos, not from the ORM directly. This is load-bearing for the Postgres migration path: swap repo internals, callers do not change.
Core:
uv sync
uv run syris # control plane
uv run syris-api # API serverApps:
bun run dev # in each app directory (dashboard / docs / nutrition)