diff --git a/src/index.ts b/src/index.ts index 51a3326..9f94457 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,6 +26,7 @@ import { taskDelegations, taskDelegationQuery } from './tools/delegations.js'; import { projectLock, projectUnlock, projectLockStatus, projectContext } from './tools/locks.js'; import { versionAdd, versionList, versionShow, versionUpdate, versionRelease, versionAssignTask } from './tools/versions.js'; import { taskCommitAdd, taskCommitRemove, taskCommitsList, taskLinkCommits, sessionTasks } from './tools/commits.js'; +import { changelogAdd, changelogSinceSession, changelogList } from './tools/changelog.js'; import { componentRegister, componentList, @@ -287,6 +288,17 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { }); break; + // Infrastructure Changelog + case 'changelog_add': + result = await changelogAdd(a as any); + break; + case 'changelog_since_session': + result = await changelogSinceSession(a as any); + break; + case 'changelog_list': + result = await changelogList(a.days_back, a.limit); + break; + // Impact Analysis case 'component_register': result = JSON.stringify(await componentRegister(a.id, a.name, a.type, { diff --git a/src/tools/changelog.ts b/src/tools/changelog.ts new file mode 100644 index 0000000..1d821b2 --- /dev/null +++ b/src/tools/changelog.ts @@ -0,0 +1,116 @@ +import { query, queryOne } from '../db.js'; + +interface ChangelogAddArgs { + date: string; // YYYY-MM-DD + title: string; + change_description: string; + impact: string; + actions_required?: string; + session_id?: string; + task_ids?: string[]; +} + +interface ChangelogSinceSessionArgs { + project: string; // To find last session for this project +} + +/** + * Add infrastructure changelog entry + */ +export async function changelogAdd(args: ChangelogAddArgs): Promise { + const { date, title, change_description, impact, actions_required, session_id, task_ids } = args; + + await query( + `INSERT INTO infrastructure_changelog + (date, title, change_description, impact, actions_required, session_id, task_ids) + VALUES ($1, $2, $3, $4, $5, $6, $7) + ON CONFLICT (date, title) DO NOTHING`, + [date, title, change_description, impact, actions_required || null, session_id || null, task_ids || null] + ); + + return `Changelog entry added: ${date} - ${title}`; +} + +/** + * Get infrastructure changes since last session for a project + * Returns changes between last session end and now + */ +export async function changelogSinceSession(args: ChangelogSinceSessionArgs): Promise { + const { project } = args; + + // Find last completed session for this project + const lastSession = await queryOne<{ ended_at: string }>( + `SELECT ended_at + FROM sessions + WHERE project = $1 AND status = 'completed' AND ended_at IS NOT NULL + ORDER BY ended_at DESC + LIMIT 1`, + [project] + ); + + if (!lastSession || !lastSession.ended_at) { + // No previous session - show last 7 days as fallback + const changes = await query( + `SELECT date, title, change_description, impact, actions_required + FROM infrastructure_changelog + WHERE date >= CURRENT_DATE - INTERVAL '7 days' + ORDER BY date DESC`, + [] + ); + + if (changes.length === 0) { + return '📋 **Infrastructure Changes:** None in last 7 days (no previous session found)'; + } + + let output = '📋 **Infrastructure Changes (last 7 days, no previous session):**\n'; + changes.forEach((c: any) => { + output += ` • ${c.date}: ${c.title}\n`; + }); + return output; + } + + // Query changes since last session ended + const changes = await query( + `SELECT date, title, change_description, impact, actions_required, task_ids + FROM infrastructure_changelog + WHERE created_at > $1 + ORDER BY date DESC`, + [lastSession.ended_at] + ); + + if (changes.length === 0) { + const lastDate = new Date(lastSession.ended_at).toISOString().split('T')[0]; + return `📋 **Infrastructure Changes:** None since last session (${lastDate})`; + } + + const lastDate = new Date(lastSession.ended_at).toISOString().split('T')[0]; + let output = `📋 **Infrastructure Changes (since ${lastDate}):**\n`; + changes.forEach((c: any) => { + output += ` • ${c.date}: ${c.title}\n`; + }); + return output; +} + +/** + * List recent infrastructure changes (fallback, time-based) + */ +export async function changelogList(days_back = 7, limit = 20): Promise { + const changes = await query( + `SELECT date, title, change_description, impact, actions_required, task_ids + FROM infrastructure_changelog + WHERE date >= CURRENT_DATE - INTERVAL '${days_back} days' + ORDER BY date DESC + LIMIT $1`, + [limit] + ); + + if (changes.length === 0) { + return `📋 **Infrastructure Changes:** None in last ${days_back} days`; + } + + let output = `📋 **Infrastructure Changes (last ${days_back} days):**\n`; + changes.forEach((c: any) => { + output += ` • ${c.date}: ${c.title}\n`; + }); + return output; +} diff --git a/src/tools/index.ts b/src/tools/index.ts index a2ddf75..44725b3 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -389,6 +389,47 @@ export const toolDefinitions = [ }, }, + // Infrastructure Changelog Tools + { + name: 'changelog_add', + description: 'Add infrastructure change entry for session awareness', + inputSchema: { + type: 'object', + properties: { + date: { type: 'string', description: 'Change date (YYYY-MM-DD)' }, + title: { type: 'string', description: 'Short title (max 100 chars)' }, + change_description: { type: 'string', description: 'What changed' }, + impact: { type: 'string', description: 'Effects on existing infrastructure' }, + actions_required: { type: 'string', description: 'Steps developers need to take (optional)' }, + session_id: { type: 'string', description: 'Session that implemented change (optional)' }, + task_ids: { type: 'array', items: { type: 'string' }, description: 'Related task IDs (optional)' }, + }, + required: ['date', 'title', 'change_description', 'impact'], + }, + }, + { + name: 'changelog_since_session', + description: 'Get infrastructure changes since last session for a project. Use at session start.', + inputSchema: { + type: 'object', + properties: { + project: { type: 'string', description: 'Project key (e.g., CF, VPN) to find last session' }, + }, + required: ['project'], + }, + }, + { + name: 'changelog_list', + description: 'List recent infrastructure changes by time period (fallback)', + inputSchema: { + type: 'object', + properties: { + days_back: { type: 'number', description: 'Days to look back (default: 7)' }, + limit: { type: 'number', description: 'Max results (default: 20)' }, + }, + }, + }, + // Project Lock Tools { name: 'project_lock',