← back to Dw Boardroom Governance
src/agents/president.ts
58 lines
/**
* President Agent — Meeting chair
* Validates agenda, enforces 5-item cap, opens/closes meetings
*/
import { AgendaItem } from '../types';
const MAX_AGENDA_ITEMS = 5;
export interface AgendaValidation {
valid: boolean;
errors: string[];
summary: string;
}
export function validateAgenda(items: AgendaItem[]): AgendaValidation {
const errors: string[] = [];
if (!items || items.length === 0) {
errors.push('Agenda is empty — at least one item required.');
}
if (items && items.length > MAX_AGENDA_ITEMS) {
errors.push(`Agenda exceeds cap of ${MAX_AGENDA_ITEMS} items (received ${items.length}). Trim or defer lower-priority items.`);
}
if (items) {
items.forEach((item, i) => {
if (!item.topic || item.topic.trim().length < 3) {
errors.push(`Item #${i + 1}: Topic too vague or missing.`);
}
if (!item.recommendation) {
errors.push(`Item #${i + 1}: Missing recommendation — every item needs a proposed action.`);
}
if (!item.decisionType || !['A', 'B', 'C'].includes(item.decisionType)) {
errors.push(`Item #${i + 1}: Invalid decision type (must be A, B, or C).`);
}
});
}
return {
valid: errors.length === 0,
errors,
summary: errors.length === 0
? `Agenda approved: ${items.length} item(s), structurally valid.`
: `Agenda rejected: ${errors.length} issue(s) found.`
};
}
export function generateOpeningStatement(meetingType: string, itemCount: number): string {
const time = new Date().toLocaleTimeString('en-US', { timeZone: 'America/Los_Angeles', hour: '2-digit', minute: '2-digit' });
return `This ${meetingType} meeting is called to order at ${time} PT. We have ${itemCount} agenda item(s) to review.`;
}
export function generateClosingStatement(meetingType: string, decisionsCount: number): string {
return `The ${meetingType} meeting is adjourned. ${decisionsCount} decision(s) recorded in the governance ledger.`;
}