Eight milestones sequence the implementation. Each milestone builds on the previous and has a specific "done when" criterion that is testable, not aspirational.
Timeline: Day 1–2
Goal: A running process with DB, API, and audit writer. No pipeline yet.
Deliverables:
pyproject.toml with deps (fastapi, uvicorn, sqlalchemy, alembic, pydantic)audit_events, system_health tablesAuditWriter implemented and unit-testedGET /health returns a hardcoded heartbeatGET /audit returns audit events (empty list)Done when: uv run syris-api → hit /health → get response. Write an audit event manually → see it at /audit. All tested.
Timeline: Week 1
Goal: An event flows end-to-end through Normalize → Route → Execute (fast only) and every stage emits a queryable audit event.
Deliverables:
schemas/ package: MessageEvent, RoutingDecision, AuditEvent (Pydantic v2)storage/models.py + repos for events, audit, routing_decisionsnormalizer.py: accepts raw dict + channel, returns MessageEvent, persists + auditsrouter.py: hard filter + one fast path (timer intent), returns RoutingDecisionpipeline/executor.py: fast lane only, calls NoopTool, auditstools/executor.py: scope check + idempotency + NoopTool + auditGET /events, GET /audit, GET /audit?trace_id=X workingDone when: POST a raw event → watch it traverse pipeline → query full trace at /audit?trace_id=X showing 4 audit events (event.ingested, routing.decided, tool_call.attempted, tool_call.succeeded). Zero log-spelunking.
Timeline: Week 2
Goal: Multi-step workflows with checkpointing, retries, and crash recovery.
Deliverables:
schemas/tasks.py: Task, Step, RetryPolicystorage/repos/tasks.pytasks/engine.py: claim → execute → checkpoint loop with FOR UPDATE SKIP LOCKEDtasks/step_runner.py: run step, handle retries, write checkpointtasks/state.py: state machine enforcement (illegal transitions blocked at DB level)tasks/recovery.py: startup reconciliationGET /tasks, GET /tasks/{id}, POST /tasks/{id}/cancel|pause|resumeDone when: Create 3-step task → kill process mid-step-2 → restart → observe task resumes from step 2. Audit shows interruption and recovery. No duplicated side effects.
Timeline: Week 3
Goal: Autonomy levels, risk classification, and approval gates working end-to-end.
Deliverables:
safety/autonomy.py: read/write current level, persist historysafety/risk.py: classify tool action → risk levelsafety/gates.py: gate decision logic per autonomy × risk matrixsafety/dryrun.py: preview protocolschemas/approvals.py + storage/repos/approvals.pyGET /approvals, POST /approvals/{id}/approve|denyPOST /controls/autonomyDone when: With autonomy = A1, medium-risk tool call creates Approval at /approvals, blocks execution. Operator approves via API. Tool executes. Full trace queryable.
Timeline: Week 4
Goal: Timers and scheduled events flow through the pipeline proactively.
Deliverables:
scheduler/scheduler.py: cron + interval + one-shot loopstorage/repos/schedules.pyscheduler/watchers/base.py + HeartbeatWatcherGET /schedules, POST /schedules, PATCH /schedules/{id}GET /watchers, PATCH /watchers/{id}GET /health now uses real heartbeat dataDone when: Create 30-second interval schedule → observe firing in /audit. Heartbeat appears in /health. Disable watcher via API → confirm it stops ticking in /audit.
Timeline: Week 5
Goal: IFTTT-style rules fire, suppress correctly, and emit child events.
Deliverables:
scheduler/rules/engine.py + condition evaluatorstorage/repos/rules.py (rules stored in DB)WatcherStateGET /rules, PATCH /rules/{id}Done when: Rule matching ha_event fires → emits child event with parent_event_id set → both in audit with same trace_id. Same event fired 5× within debounce window → 1 rule.triggered + 4 rule.suppressed in audit.
Timeline: Week 6–7
Goal: An MCP server's tools appear in the tool registry and execute with full SYRIS gating.
Deliverables:
integrations/mcp/connection.py: persistent connection + reconnectintegrations/mcp/provider.py: tool discovery + registry syncintegrations/mcp/adapter.py: MCPToolAdapter(BaseTool)integrations/mcp/trust.py: TrustPolicy schema + loaderGET /integrations showing MCP server healthDone when: Connect real MCP server → tools appear in GET /integrations. Execute one tool → full audit trail (scope check, risk, idempotency, gate, result). Disconnect → health degrades in dashboard within 30 seconds.
Timeline: Week 8
Goal: A gated job submission and status reporting mechanism exists.
Deliverables:
workers/manager.py: job table, spawn/progress/cancelworkers/runtimes/process.py: OS process isolationGET /state shows job countDone when: Submit stub long-running job via API → observe in /state → cancel → see cancellation in audit.
Timeline: Week 9+
Goal: A Home Assistant adapter or email adapter working end-to-end with live data.
Deliverables:
Done when: A real-world event flows in from HA or email, routes correctly, executes a tool with full audit trail, and requires/passes approval if risk demands it. SYRIS is useful.
On This Page
Milestone 0: SkeletonMilestone 1: Pipeline skeleton with real audit outputMilestone 2: Task engineMilestone 3: Safety layer + ApprovalsMilestone 4: Scheduler + WatchersMilestone 5: Rules EngineMilestone 6: MCP IntegrationMilestone 7: Worker SkeletonMilestone 8: First real integrationsRelated