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
55 changes: 53 additions & 2 deletions contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ class DoctorResponse(BaseModel):
class IngestSpan(BaseModel):
"""Source excerpt from a meeting, document, or manual input."""
text: str = ""
source_type: str = "manual" # transcript | notion | document | manual | implementation_choice
source_type: str = "manual" # transcript | notion | document | manual | agent_session | implementation_choice
source_ref: str = ""
speakers: list[str] = []
meeting_date: str = ""
Expand All @@ -289,6 +289,7 @@ class IngestMapping(BaseModel):
code_regions: list[IngestCodeRegion] = []
search_hint: str = ""
product_signoff: dict | None = None
feature_group: str | None = None


class IngestDecision(BaseModel):
Expand All @@ -312,6 +313,7 @@ class IngestDecision(BaseModel):
source_excerpt: str = ""
search_hint: str = ""
product_signoff: dict | None = None
feature_group: str | None = None


class IngestActionItem(BaseModel):
Expand All @@ -327,7 +329,7 @@ class IngestPayload(BaseModel):
commit_hash: str = ""
query: str = ""
mappings: list[IngestMapping] = []
source: str = "manual"
source: str = "manual" # transcript | notion | slack | document | manual | agent_session | implementation_choice
title: str = ""
date: str = ""
participants: list[str] = []
Expand Down Expand Up @@ -535,5 +537,54 @@ class SupersessionCandidate(BaseModel):
projected_status: Literal["reflected", "drifted", "pending", "ungrounded"] = "ungrounded"


# ── Tool: bicameral.history ──────────────────────────────────────────────────


class HistorySource(BaseModel):
"""One input span that originated or updated a decision."""
source_ref: str # e.g. "sprint-14-planning"
source_type: Literal["transcript", "slack", "document", "agent_session", "manual"]
date: str # ISO date
speaker: str | None = None
quote: str # verbatim excerpt from source_span.text


class HistoryFulfillment(BaseModel):
"""Code grounding for a decision."""
file_path: str
symbol: str | None = None
start_line: int
end_line: int
git_url: str | None = None
grounded_at_ref: str = "" # git ref when first grounded
baseline_hash: str | None = None
current_hash: str | None = None


class HistoryDecision(BaseModel):
"""Balance-sheet view of one decision: commitment + fulfillment + balance."""
id: str # decision_id
summary: str # canonical decision text
featureId: str
status: Literal["reflected", "drifted", "ungrounded", "superseded", "discovered"]
sources: list[HistorySource] # 1+ input spans; empty for discovered
fulfillment: HistoryFulfillment | None = None # None when ungrounded or discovered without grounding
drift_evidence: str | None = None # human-readable delta when drifted


class HistoryFeature(BaseModel):
"""A feature group containing related decisions."""
id: str # feature group id (slugified name)
name: str # canonical feature_group noun phrase
decisions: list[HistoryDecision]


class HistoryResponse(BaseModel):
features: list[HistoryFeature]
truncated: bool = False
total_features: int = 0
as_of: str = "" # git ref evaluated against


# Forward references
IngestResponse.model_rebuild()
2 changes: 1 addition & 1 deletion handlers/brief.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Handler for /bicameral_brief MCP tool.
"""Internal module — not registered as an MCP tool. Called by handle_ingest and handle_preflight.

Pre-meeting one-pager generator. Accepts a topic (and optional participant
list) and returns a structured response with decisions-in-scope, drift
Expand Down
142 changes: 0 additions & 142 deletions handlers/doctor.py

This file was deleted.

Loading
Loading