docs(platform): add policy configs, runbooks, ops scripts and platform documentation
Config policies (16 files): alert_routing, architecture_pressure, backlog, cost_weights, data_governance, incident_escalation, incident_intelligence, network_allowlist, nodes_registry, observability_sources, rbac_tools_matrix, release_gate, risk_attribution, risk_policy, slo_policy, tool_limits, tools_rollout Ops (22 files): Caddyfile, calendar compose, grafana voice dashboard, deployments/incidents logs, runbooks for alerts/audit/backlog/incidents/sofiia/voice, cron jobs, scripts (alert_triage, audit_cleanup, migrate_*, governance, schedule), task_registry, voice alerts/ha/latency/policy Docs (30+ files): HUMANIZED_STEPAN v2.7-v3 changelogs and runbooks, NODA1/NODA2 status and setup, audit index and traces, backlog, incident, supervisor, tools, voice, opencode, release, risk, aistalk, spacebot Made-with: Cursor
This commit is contained in:
133
docs/GRAPH_CONTRACT.md
Normal file
133
docs/GRAPH_CONTRACT.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# Sofiia Dialog Graph — Canonical Contract v1.0
|
||||
|
||||
## Core Invariants
|
||||
|
||||
Every meaningful artifact in the Sofiia system MUST be represented in the Dialog Graph:
|
||||
|
||||
```
|
||||
1. Every artifact has a node.
|
||||
2. Every action has an edge.
|
||||
3. No artifact exists without graph presence.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Node Types
|
||||
|
||||
| node_type | ref_id points to | Created by |
|
||||
|-----------------|-----------------------|------------------------------------|
|
||||
| `message` | message_id (session) | session message handler |
|
||||
| `task` | tasks.task_id | `create_task()` — atomically |
|
||||
| `meeting` | meetings.meeting_id | `create_meeting()` — atomically |
|
||||
| `doc` | documents.doc_id | document upload/create |
|
||||
| `agent_run` | run_id (supervisor) | `create_evidence_pack()` |
|
||||
| `ops_run` | job_id (ops) | ops job completion hook |
|
||||
| `repo_changeset`| changeset_id | repo diff / PR tracking |
|
||||
| `pull_request` | PR number/id | PR flow integration |
|
||||
| `decision` | decision_id | explicit decision recording |
|
||||
| `goal` | goal_id | strategic goal setting |
|
||||
|
||||
---
|
||||
|
||||
## Edge Types
|
||||
|
||||
| edge_type | Meaning | Example |
|
||||
|---------------------|-------------------------------------------|------------------------------------|
|
||||
| `references` | A mentions/cites B | message → doc |
|
||||
| `summarizes` | A is a summary of B | doc → session |
|
||||
| `derives_task` | A produced task B | message → task |
|
||||
| `updates_doc` | A updates/modifies doc B | ops_run → doc |
|
||||
| `schedules_meeting` | A scheduled meeting B | message → meeting |
|
||||
| `resolves` | A resolves/closes B | task → task (blocker resolved) |
|
||||
| `blocks` | A blocks B | task → task |
|
||||
| `relates_to` | A is related to B | any → any |
|
||||
| `produced_by` | B was produced by run A | agent_run → task/doc |
|
||||
| `executed_as` | plan A was executed as ops_run B | decision → ops_run |
|
||||
|
||||
---
|
||||
|
||||
## Atomic Creation Rules
|
||||
|
||||
When creating an artifact, the node MUST be created in the same SQLite transaction:
|
||||
|
||||
```python
|
||||
# CORRECT: task + node in one BEGIN...COMMIT
|
||||
await db.execute("BEGIN")
|
||||
await db.execute("INSERT INTO tasks ...")
|
||||
await db.execute("INSERT INTO dialog_nodes ... ON CONFLICT DO UPDATE")
|
||||
await db.commit()
|
||||
|
||||
# WRONG: two separate commits
|
||||
await create_task(...) # commit 1
|
||||
await upsert_dialog_node(...) # commit 2 — can diverge
|
||||
```
|
||||
|
||||
Functions that guarantee atomicity:
|
||||
- `db.create_task()` — always upserts task node
|
||||
- `db.create_meeting()` — always upserts meeting node
|
||||
- `db.create_evidence_pack()` — creates agent_run node + derived task nodes + edges
|
||||
|
||||
---
|
||||
|
||||
## Evidence Pack
|
||||
|
||||
After every Supervisor run, an Evidence Pack MUST be recorded:
|
||||
|
||||
```json
|
||||
{
|
||||
"run_id": "<uuid>",
|
||||
"graph_name": "release_check|incident_triage|...",
|
||||
"status": "completed",
|
||||
"summary": "...",
|
||||
"findings": [...],
|
||||
"recommendations": [...],
|
||||
"follow_up_tasks": [
|
||||
{"title": "...", "description": "...", "priority": "normal|high|urgent"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
This creates:
|
||||
1. `agent_run` dialog node
|
||||
2. `doc_version` with evidence markdown (if evidence_log.md exists in project)
|
||||
3. `task` nodes for each follow_up_task (in `backlog` with label `evidence`)
|
||||
4. `produced_by` edges: agent_run → each task node
|
||||
|
||||
---
|
||||
|
||||
## Integrity Checks
|
||||
|
||||
Run `GET /api/projects/{id}/graph/integrity` to verify:
|
||||
|
||||
| Check | Description |
|
||||
|-------------------------|------------------------------------------------------|
|
||||
| `orphaned_edge_from` | Edges referencing non-existent from_node |
|
||||
| `orphaned_edge_to` | Edges referencing non-existent to_node |
|
||||
| `dangling_task_nodes` | `node_type=task` nodes with no matching task row |
|
||||
| `dangling_meeting_nodes`| `node_type=meeting` nodes with no matching meeting |
|
||||
| `self_loop_edges` | Edges where from_node_id == to_node_id |
|
||||
|
||||
**Expected**: `{"ok": true, "violations": []}`
|
||||
|
||||
---
|
||||
|
||||
## DDL Freeze
|
||||
|
||||
As of v1.0, the schema is **frozen**. Any schema changes require:
|
||||
1. A migration file in `services/sofiia-console/migrations/`
|
||||
2. Update to this contract document
|
||||
3. Update to `tests/test_graph_integrity.py`
|
||||
|
||||
Current canonical DDL: `services/sofiia-console/app/db.py` (init_db function)
|
||||
|
||||
---
|
||||
|
||||
## Quality Gates
|
||||
|
||||
Before merging any feature that touches artifacts:
|
||||
|
||||
| Gate | Check |
|
||||
|---------------------|----------------------------------------------|
|
||||
| **Reproducibility** | Does the feature create a node + edge? |
|
||||
| **Safety** | Is creation atomic (single transaction)? |
|
||||
| **Observability** | Does `GET /graph/integrity` stay `ok: true`? |
|
||||
Reference in New Issue
Block a user