feat(brain): @mosaic/brain structured data service (#10)
Implement @mosaic/brain — typed structured data service with MCP + REST API, JSON file backend, and schema validation via Zod. Collections: tasks, projects, events, agents, tickets, appreciations, missions, mission_tasks. MCP tools: brain_tasks, brain_projects, brain_events, brain_agents, brain_tickets, brain_today, brain_stale, brain_stats, brain_search, brain_audit, brain_missions, brain_mission, brain_mission_tasks, plus mutation tools for all collections. REST API mirrors MCP 1:1 at /v1/*. Bearer token auth with timing-safe comparison. Fastify server with per-request MCP instances (stateless HTTP transport). JSON file storage with proper-lockfile for concurrent access. Also adds Brain* types to @mosaic/types. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -340,3 +340,315 @@ export interface WizardState {
|
||||
readonly runtimes: RuntimeState;
|
||||
readonly selectedSkills: readonly string[];
|
||||
}
|
||||
|
||||
// === Brain (Structured Data) ===
|
||||
|
||||
export type BrainDomain =
|
||||
| 'work'
|
||||
| 'software-dev'
|
||||
| 'homelab'
|
||||
| 'family'
|
||||
| 'marriage'
|
||||
| 'finances'
|
||||
| 'fitness'
|
||||
| 'music'
|
||||
| 'home-improvement'
|
||||
| 'woodworking'
|
||||
| 'home'
|
||||
| 'consulting'
|
||||
| 'personal';
|
||||
|
||||
export type BrainTaskStatus =
|
||||
| 'backlog'
|
||||
| 'scheduled'
|
||||
| 'in-progress'
|
||||
| 'blocked'
|
||||
| 'done'
|
||||
| 'cancelled';
|
||||
|
||||
export type BrainProjectStatus =
|
||||
| 'planning'
|
||||
| 'active'
|
||||
| 'paused'
|
||||
| 'blocked'
|
||||
| 'completed'
|
||||
| 'archived';
|
||||
|
||||
export type BrainAgentStatus = 'active' | 'idle' | 'blocked' | 'completed';
|
||||
|
||||
export type BrainEventType =
|
||||
| 'meeting'
|
||||
| 'deadline'
|
||||
| 'maintenance'
|
||||
| 'event'
|
||||
| 'recurring'
|
||||
| 'milestone'
|
||||
| 'task'
|
||||
| 'constraint'
|
||||
| 'client-work'
|
||||
| 'appointment'
|
||||
| 'reminder'
|
||||
| 'conflict'
|
||||
| 'time-off';
|
||||
|
||||
export type BrainEventStatus =
|
||||
| 'scheduled'
|
||||
| 'confirmed'
|
||||
| 'tentative'
|
||||
| 'completed'
|
||||
| 'cancelled'
|
||||
| 'done'
|
||||
| 'blocked'
|
||||
| 'postponed'
|
||||
| 'deferred'
|
||||
| 'in-progress'
|
||||
| 'pending-approval'
|
||||
| 'canceled'
|
||||
| 'needs-resolution';
|
||||
|
||||
export type BrainMissionStatus =
|
||||
| 'planning'
|
||||
| 'active'
|
||||
| 'blocked'
|
||||
| 'completed'
|
||||
| 'cancelled';
|
||||
|
||||
// --- Brain: Task ---
|
||||
|
||||
export interface BrainTask {
|
||||
readonly id: string;
|
||||
readonly title: string;
|
||||
readonly domain: BrainDomain;
|
||||
readonly project?: string | null;
|
||||
readonly priority: TaskPriority;
|
||||
readonly status: BrainTaskStatus;
|
||||
readonly progress?: number | null;
|
||||
readonly due?: string | null;
|
||||
readonly blocks?: readonly string[];
|
||||
readonly blocked_by?: readonly string[];
|
||||
readonly related?: readonly string[];
|
||||
readonly canonical_source?: string | null;
|
||||
readonly assignee?: string | null;
|
||||
readonly created: string;
|
||||
readonly updated: string;
|
||||
readonly notes?: string | null;
|
||||
readonly notes_nontechnical?: string | null;
|
||||
}
|
||||
|
||||
// --- Brain: Project ---
|
||||
|
||||
export interface BrainProject {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly description?: string | null;
|
||||
readonly domain: BrainDomain;
|
||||
readonly status: BrainProjectStatus;
|
||||
readonly priority: number;
|
||||
readonly progress?: number | null;
|
||||
readonly repo?: string | null;
|
||||
readonly branch?: string | null;
|
||||
readonly current_milestone?: string | null;
|
||||
readonly next_milestone?: string | null;
|
||||
readonly blocker?: string | null;
|
||||
readonly owner?: string | null;
|
||||
readonly docs_path?: string | null;
|
||||
readonly created: string;
|
||||
readonly updated: string;
|
||||
readonly notes?: string | null;
|
||||
readonly notes_nontechnical?: string | null;
|
||||
}
|
||||
|
||||
// --- Brain: Event ---
|
||||
|
||||
export interface BrainEvent {
|
||||
readonly id: string;
|
||||
readonly title: string;
|
||||
readonly date: string;
|
||||
readonly end_date?: string | null;
|
||||
readonly time?: string | null;
|
||||
readonly end_time?: string | null;
|
||||
readonly domain: BrainDomain;
|
||||
readonly type: BrainEventType;
|
||||
readonly status?: BrainEventStatus;
|
||||
readonly priority?: TaskPriority | null;
|
||||
readonly recur?: boolean | null;
|
||||
readonly recur_rate?: string | null;
|
||||
readonly recur_start?: string | null;
|
||||
readonly recur_end?: string | null;
|
||||
readonly location?: string | null;
|
||||
readonly project?: string | null;
|
||||
readonly related_task?: string | null;
|
||||
readonly related_tasks?: readonly string[];
|
||||
readonly notes?: string | null;
|
||||
readonly gcal_id?: string | null;
|
||||
readonly ics_uid?: string | null;
|
||||
}
|
||||
|
||||
// --- Brain: Agent ---
|
||||
|
||||
export interface BrainAgent {
|
||||
readonly id: string;
|
||||
readonly project: string;
|
||||
readonly focus?: string | null;
|
||||
readonly repo?: string | null;
|
||||
readonly branch?: string | null;
|
||||
readonly status: BrainAgentStatus;
|
||||
readonly workload?: 'light' | 'medium' | 'heavy' | null;
|
||||
readonly next_step?: string | null;
|
||||
readonly blocker?: string | null;
|
||||
readonly updated: string;
|
||||
}
|
||||
|
||||
// --- Brain: Ticket ---
|
||||
|
||||
export interface BrainTicket {
|
||||
readonly id: string;
|
||||
readonly title: string;
|
||||
readonly status: number;
|
||||
readonly priority: number;
|
||||
readonly urgency: number;
|
||||
readonly impact: number;
|
||||
readonly date_creation: string;
|
||||
readonly date_mod: string;
|
||||
readonly content?: string | null;
|
||||
readonly assigned_to?: string | null;
|
||||
}
|
||||
|
||||
// --- Brain: Appreciation ---
|
||||
|
||||
export interface BrainAppreciation {
|
||||
readonly date: string;
|
||||
readonly from: 'jason' | 'melanie';
|
||||
readonly to: 'jason' | 'melanie';
|
||||
readonly text: string;
|
||||
}
|
||||
|
||||
// --- Brain: Mission ---
|
||||
|
||||
export interface BrainMission {
|
||||
readonly id: string;
|
||||
readonly title: string;
|
||||
readonly project: string;
|
||||
readonly prd_path?: string | null;
|
||||
readonly status: BrainMissionStatus;
|
||||
readonly created: string;
|
||||
readonly updated: string;
|
||||
readonly notes?: string | null;
|
||||
}
|
||||
|
||||
// --- Brain: Mission Task ---
|
||||
|
||||
export interface BrainMissionTask {
|
||||
readonly id: string;
|
||||
readonly mission_id: string;
|
||||
readonly title: string;
|
||||
readonly phase?: string | null;
|
||||
readonly status: BrainTaskStatus;
|
||||
readonly priority: TaskPriority;
|
||||
readonly dependencies: readonly string[];
|
||||
readonly assigned_to?: string | null;
|
||||
readonly pr?: string | null;
|
||||
readonly order: number;
|
||||
readonly created: string;
|
||||
readonly updated: string;
|
||||
readonly completed_at?: string | null;
|
||||
readonly notes?: string | null;
|
||||
}
|
||||
|
||||
// --- Brain: Filter/Query Types ---
|
||||
|
||||
export interface BrainTaskFilters {
|
||||
readonly status?: BrainTaskStatus;
|
||||
readonly priority?: TaskPriority;
|
||||
readonly domain?: BrainDomain;
|
||||
readonly project?: string;
|
||||
readonly due_before?: string;
|
||||
readonly due_after?: string;
|
||||
readonly assignee?: string;
|
||||
readonly limit?: number;
|
||||
}
|
||||
|
||||
export interface BrainProjectFilters {
|
||||
readonly status?: BrainProjectStatus;
|
||||
readonly domain?: BrainDomain;
|
||||
readonly priority_min?: number;
|
||||
readonly priority_max?: number;
|
||||
readonly limit?: number;
|
||||
}
|
||||
|
||||
export interface BrainEventFilters {
|
||||
readonly date_from?: string;
|
||||
readonly date_to?: string;
|
||||
readonly domain?: BrainDomain;
|
||||
readonly type?: BrainEventType;
|
||||
readonly status?: BrainEventStatus;
|
||||
readonly limit?: number;
|
||||
}
|
||||
|
||||
export interface BrainMissionFilters {
|
||||
readonly status?: BrainMissionStatus;
|
||||
readonly project?: string;
|
||||
readonly limit?: number;
|
||||
}
|
||||
|
||||
export interface BrainMissionTaskFilters {
|
||||
readonly mission_id: string;
|
||||
readonly status?: BrainTaskStatus;
|
||||
readonly phase?: string;
|
||||
readonly priority?: TaskPriority;
|
||||
}
|
||||
|
||||
// --- Brain: Computed Response Types ---
|
||||
|
||||
export interface BrainMissionSummary extends BrainMission {
|
||||
readonly task_count: number;
|
||||
readonly completed_count: number;
|
||||
readonly progress: number;
|
||||
readonly next_available: readonly BrainMissionTask[];
|
||||
readonly blocked_tasks: readonly BrainMissionTask[];
|
||||
}
|
||||
|
||||
export interface BrainTodaySummary {
|
||||
readonly date: string;
|
||||
readonly events_today: readonly BrainEvent[];
|
||||
readonly events_upcoming: readonly BrainEvent[];
|
||||
readonly tasks_near_term: readonly BrainTask[];
|
||||
readonly tasks_blocked: readonly BrainTask[];
|
||||
readonly tasks_stale: readonly BrainTask[];
|
||||
readonly tasks_almost_done: readonly BrainTask[];
|
||||
readonly active_missions: readonly BrainMissionSummary[];
|
||||
readonly stats: BrainStats;
|
||||
}
|
||||
|
||||
export interface BrainStats {
|
||||
readonly tasks: number;
|
||||
readonly projects: number;
|
||||
readonly events: number;
|
||||
readonly agents: number;
|
||||
readonly tickets: number;
|
||||
readonly missions: number;
|
||||
readonly tasks_by_status: Readonly<Record<string, number>>;
|
||||
readonly tasks_by_domain: Readonly<Record<string, number>>;
|
||||
readonly projects_by_status: Readonly<Record<string, number>>;
|
||||
}
|
||||
|
||||
export interface BrainStaleReport {
|
||||
readonly days: number;
|
||||
readonly tasks: readonly BrainTask[];
|
||||
readonly projects: readonly BrainProject[];
|
||||
}
|
||||
|
||||
export interface BrainAuditResult {
|
||||
readonly orphan_refs: readonly string[];
|
||||
readonly broken_dependencies: readonly string[];
|
||||
readonly missing_required_fields: readonly string[];
|
||||
readonly duplicate_ids: readonly string[];
|
||||
}
|
||||
|
||||
export interface BrainSearchResult {
|
||||
readonly collection: string;
|
||||
readonly id: string;
|
||||
readonly title: string;
|
||||
readonly match_context: string;
|
||||
readonly score: number;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user