rspace-online/modules/rtime/schemas.ts

264 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* rTime Automerge document schemas.
*
* DocId formats:
* {space}:rtime:commitments → CommitmentsDoc (commitment pool)
* {space}:rtime:tasks → TasksDoc (weaving: tasks, connections, exec states)
*/
import type { DocSchema } from '../../shared/local-first/document';
// ── Skill type ──
export type Skill = 'facilitation' | 'design' | 'tech' | 'outreach' | 'logistics';
export const SKILL_COLORS: Record<Skill, string> = {
facilitation: '#8b5cf6',
design: '#ec4899',
tech: '#3b82f6',
outreach: '#10b981',
logistics: '#f59e0b',
};
export const SKILL_LABELS: Record<Skill, string> = {
facilitation: 'Facilitation',
design: 'Design',
tech: 'Tech',
outreach: 'Outreach',
logistics: 'Logistics',
};
// ── Commitment ──
export interface Commitment {
id: string;
memberName: string;
hours: number; // 110
skill: Skill;
desc: string;
cyclosMemberId?: string;
createdAt: number;
intentId?: string; // links commitment to its intent
status?: 'active' | 'matched' | 'settled' | 'withdrawn';
ownerDid?: string; // DID of the commitment creator (for notifications)
visibility?: import('../../shared/membrane').ObjectVisibility;
}
// ── Task / Connection / ExecState ──
export interface Task {
id: string;
name: string;
description: string;
needs: Record<string, number>; // skill → hours needed
links: { label: string; url: string }[];
notes: string;
intentFrameId?: string; // links task to solver result that spawned it
visibility?: import('../../shared/membrane').ObjectVisibility;
}
export interface Connection {
id: string;
fromCommitmentId: string;
toTaskId: string;
skill: string;
hours: number; // hours allocated in this connection
status: 'proposed' | 'committed'; // approval state
connectionType?: 'commitment' | 'dependency'; // commitment = resource flow, dependency = structural sequence
}
// ── Project Frame ──
export interface ProjectFrame {
id: string;
title: string;
taskIds: string[];
color?: string; // optional skill-color override
x: number;
y: number;
w: number;
h: number;
}
export interface ExecState {
taskId: string;
steps: Record<string, 'pending' | 'active' | 'done'>;
launchedAt?: number;
}
// ── Documents ──
export interface CommitmentsDoc {
meta: {
module: string;
collection: string;
version: number;
spaceSlug: string;
createdAt: number;
seeded?: boolean;
};
items: Record<string, Commitment>;
}
export interface TasksDoc {
meta: {
module: string;
collection: string;
version: number;
spaceSlug: string;
createdAt: number;
};
tasks: Record<string, Task>;
connections: Record<string, Connection>;
execStates: Record<string, ExecState>;
projectFrames: Record<string, ProjectFrame>;
}
// ── External Time Log (backlog-md integration) ──
export type ExternalTimeLogStatus = 'pending' | 'commitment_created' | 'settled';
export interface ExternalTimeLog {
id: string;
backlogTaskId: string;
backlogTaskTitle: string;
memberName: string;
memberId?: string; // DID
hours: number;
skill: Skill;
note?: string;
loggedAt: number; // unix ms (when work was done)
importedAt: number; // unix ms (when imported to rTime)
status: ExternalTimeLogStatus;
commitmentId?: string; // auto-created commitment ID
}
export interface ExternalTimeLogsDoc {
meta: {
module: string;
collection: string;
version: number;
spaceSlug: string;
createdAt: number;
};
logs: Record<string, ExternalTimeLog>;
}
// ── Weaving overlay (rTasks integration) ──
export interface WeavingOverlay {
rtasksId: string;
needs: Record<string, number>;
canvasX: number;
canvasY: number;
notes: string;
links: { label: string; url: string }[];
intentFrameId?: string;
}
export interface WeavingDoc {
meta: {
module: string;
collection: string;
version: number;
spaceSlug: string;
createdAt: number;
};
boardSlug: string;
weavingOverlays: Record<string, WeavingOverlay>;
connections: Record<string, Connection>;
execStates: Record<string, ExecState>;
projectFrames: Record<string, ProjectFrame>;
}
// ── DocId helpers ──
export function commitmentsDocId(space: string) {
return `${space}:rtime:commitments` as const;
}
export function tasksDocId(space: string) {
return `${space}:rtime:tasks` as const;
}
export function weavingDocId(space: string) {
return `${space}:rtime:weaving` as const;
}
export function externalTimeLogsDocId(space: string) {
return `${space}:rtime:external-time-logs` as const;
}
// ── Schema registrations ──
export const commitmentsSchema: DocSchema<CommitmentsDoc> = {
module: 'rtime',
collection: 'commitments',
version: 1,
init: (): CommitmentsDoc => ({
meta: {
module: 'rtime',
collection: 'commitments',
version: 1,
spaceSlug: '',
createdAt: Date.now(),
},
items: {},
}),
};
export const tasksSchema: DocSchema<TasksDoc> = {
module: 'rtime',
collection: 'tasks',
version: 1,
init: (): TasksDoc => ({
meta: {
module: 'rtime',
collection: 'tasks',
version: 1,
spaceSlug: '',
createdAt: Date.now(),
},
tasks: {},
connections: {},
execStates: {},
projectFrames: {},
}),
};
export const weavingSchema: DocSchema<WeavingDoc> = {
module: 'rtime',
collection: 'weaving',
version: 1,
init: (): WeavingDoc => ({
meta: {
module: 'rtime',
collection: 'weaving',
version: 1,
spaceSlug: '',
createdAt: Date.now(),
},
boardSlug: '',
weavingOverlays: {},
connections: {},
execStates: {},
projectFrames: {},
}),
};
export const externalTimeLogsSchema: DocSchema<ExternalTimeLogsDoc> = {
module: 'rtime',
collection: 'external-time-logs',
version: 1,
init: (): ExternalTimeLogsDoc => ({
meta: {
module: 'rtime',
collection: 'external-time-logs',
version: 1,
spaceSlug: '',
createdAt: Date.now(),
},
logs: {},
}),
};