fivocell 4.1.0 → 4.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1830,1017 +1830,1050 @@ const MCP_TOOLS = [
1830
1830
  { name: 'cell_model_recommend', description: 'Get AI model recommendations — which tool works best for which task', inputSchema: { type: 'object', properties: {} } },
1831
1831
  ];
1832
1832
  async function handleMCPToolCall(name, args) {
1833
- switch (name) {
1834
- case 'cell_get_dev_profile': {
1835
- const { getDeveloperProfile } = require('../code-scanner');
1836
- const profile = getDeveloperProfile(args.project);
1837
- if (!profile)
1838
- return { error: 'no profile — run cell scan first' };
1839
- return { project: args.project, profile };
1840
- }
1841
- case 'cell_get_code_patterns': {
1842
- const { getCodePatterns } = require('../code-scanner');
1843
- return { project: args.project, patterns: getCodePatterns(args.project, args.category) };
1844
- }
1845
- case 'cell_deep_scan': {
1846
- const { scanCodebase } = require('../code-scanner');
1847
- const result = scanCodebase(args.dir, args.project || path.basename(args.dir));
1848
- return { project: result.project, filesScanned: result.filesScanned, totalLines: result.totalLines, profile: result.profile, strengths: result.profile.strengths, improvements: result.profile.improvements };
1849
- }
1850
- case 'cell_scan_report': {
1851
- const { getDeveloperProfile, getCodePatterns } = require('../code-scanner');
1852
- const profile = getDeveloperProfile(args.project);
1853
- const patterns = getCodePatterns(args.project);
1854
- return { project: args.project, profile, patterns, patternCount: patterns.length };
1855
- }
1856
- case 'cell_send_signal': {
1857
- const { logError, logDecision, logContext, logStuck } = require('../behavioral-tracker');
1858
- const type = args.type;
1859
- if (type === 'error')
1860
- return logError({ project: args.project, file: args.file, errorType: 'manual', errorMessage: String(args.editedCode || ''), line: 0 });
1861
- if (type === 'decision')
1862
- return logDecision({ project: args.project, file: args.file, decision: String(args.originalCode || ''), approach: String(args.editedCode || ''), worked: true });
1863
- if (type === 'context')
1864
- return logContext({ project: args.project, task: String(args.originalCode || ''), files: [] });
1865
- if (type === 'stuck')
1866
- return logStuck({ project: args.project, file: args.file, description: String(args.originalCode || '') });
1867
- return { recorded: true };
1868
- }
1869
- case 'cell_get_context': {
1870
- const { buildContext, formatContextForTool } = require('../core/prompt-builder');
1871
- const ctx = buildContext(args.project, args.tool);
1872
- const toolName = args.tool || (args.project ? 'claude-code' : undefined);
1873
- return { content: [{ type: 'text', text: formatContextForTool(ctx, toolName) }], context: ctx };
1874
- }
1875
- case 'cell_scan_full_pc': {
1876
- const { scanFullPC } = require('../pc-scanner');
1877
- const result = scanFullPC();
1878
- return { totalProjects: result.totalProjects, totalFiles: result.totalFiles, totalLines: result.totalLines, profile: result.aggregatedProfile };
1879
- }
1880
- case 'cell_behavior_summary': {
1881
- const { getBehaviorSummary } = require('../behavioral-tracker');
1882
- return getBehaviorSummary(args.project);
1883
- }
1884
- case 'cell_log_error': {
1885
- const { logError } = require('../behavioral-tracker');
1886
- return logError({ project: args.project, file: args.file, errorType: args.errorType, errorMessage: args.errorMessage, line: args.line });
1887
- }
1888
- case 'cell_log_fix': {
1889
- const { logErrorFix } = require('../behavioral-tracker');
1890
- logErrorFix({ errorId: args.errorId, fixApplied: args.fixApplied, worked: args.worked, timeToFixMs: args.timeToFixMs });
1891
- return { recorded: true };
1892
- }
1893
- case 'cell_log_decision': {
1894
- const { logDecision } = require('../behavioral-tracker');
1895
- return logDecision({ project: args.project, file: args.file, decision: args.decision, approach: args.approach, worked: args.worked });
1896
- }
1897
- case 'cell_log_context': {
1898
- const { logContext } = require('../behavioral-tracker');
1899
- return logContext({ project: args.project, task: args.task, files: args.files });
1900
- }
1901
- case 'cell_log_stuck': {
1902
- const { logStuck } = require('../behavioral-tracker');
1903
- return logStuck({ project: args.project, file: args.file, description: args.description });
1904
- }
1905
- case 'cell_session_bridge': {
1906
- const { SessionMemory } = require('../core/session-memory');
1907
- const memory = new SessionMemory();
1908
- const project = args.project;
1909
- const tool = args.tool || 'unknown';
1910
- try {
1911
- const lastSession = memory.getLastSessionForProject(project);
1912
- const newSessionId = memory.startSession(tool, project);
1913
- let bridgeContext = '';
1914
- if (lastSession && lastSession.toolName !== tool) {
1915
- const triedApproaches = memory.getRecentApproaches(project, 5);
1916
- const openQuestions = memory.getOpenQuestions(project);
1917
- const hotFiles = memory.getMostTouchedFiles(project, 5);
1918
- const decisions = Array.isArray(lastSession.keyDecisions) ? JSON.stringify(lastSession.keyDecisions) : 'none';
1919
- bridgeContext = formatSessionBridge(lastSession.toolName, tool, lastSession.contextSnapshot, decisions, {
1920
- triedApproaches,
1921
- openQuestions,
1922
- hotFiles,
1923
- });
1924
- }
1925
- const recentSessions = memory.getRecentSessions(3).filter((s) => s.project === project);
1926
- const sessionHistory = recentSessions.map((s) => ({
1927
- tool: s.toolName,
1928
- when: s.startTime,
1929
- files: s.filesTouched,
1930
- decisions: s.keyDecisions,
1931
- }));
1932
- return {
1933
- newSessionId,
1934
- lastSession: lastSession ? {
1935
- tool: lastSession.toolName,
1936
- startedAt: lastSession.startTime,
1937
- context: lastSession.contextSnapshot,
1938
- } : null,
1939
- bridgeContext,
1940
- sessionHistory,
1941
- triedApproaches: memory.getRecentApproaches(project, 5),
1942
- openQuestions: memory.getOpenQuestions(project),
1943
- hotFiles: memory.getMostTouchedFiles(project, 5),
1944
- message: bridgeContext || 'No previous session to bridge. Start a new session!',
1945
- };
1946
- }
1947
- catch (err) {
1948
- const msg = err instanceof Error ? err.message : String(err);
1949
- return { error: `Session bridge failed: ${msg}`, crossedSession: false };
1950
- }
1951
- }
1952
- case 'cell_session_end': {
1953
- const { SessionMemory } = require('../core/session-memory');
1954
- const memory = new SessionMemory();
1955
- const sessionId = args.sessionId;
1956
- try {
1957
- memory.endSession(sessionId, {
1958
- filesTouched: Array.isArray(args.filesTouched) ? args.filesTouched : [],
1959
- keyDecisions: Array.isArray(args.keyDecisions) ? args.keyDecisions : [],
1960
- contextSnapshot: args.contextSnapshot || '',
1961
- });
1962
- return { ended: true, sessionId };
1963
- }
1964
- catch (err) {
1965
- const msg = err instanceof Error ? err.message : String(err);
1966
- return { error: `Session end failed: ${msg}`, ended: false };
1967
- }
1968
- }
1969
- case 'cell_session_log': {
1970
- const { SessionMemory } = require('../core/session-memory');
1971
- const memory = new SessionMemory();
1972
- try {
1973
- const sessionId = args.sessionId || 0;
1974
- const project = args.project || 'unknown';
1975
- if (args.type === 'approach' && args.approach) {
1976
- const id = memory.recordApproach({
1977
- sessionId: sessionId || undefined,
1978
- project,
1979
- approach: args.approach,
1980
- status: args.status || 'tried',
1981
- reason: args.reason,
1982
- });
1983
- return { recorded: 'approach', id };
1833
+ try {
1834
+ switch (name) {
1835
+ case 'cell_get_dev_profile': {
1836
+ const { getDeveloperProfile } = require('../code-scanner');
1837
+ const profile = getDeveloperProfile(args.project);
1838
+ if (!profile)
1839
+ return { error: 'no profile — run cell scan first' };
1840
+ return { project: args.project, profile };
1841
+ }
1842
+ case 'cell_get_code_patterns': {
1843
+ const { getCodePatterns } = require('../code-scanner');
1844
+ return { project: args.project, patterns: getCodePatterns(args.project, args.category) };
1845
+ }
1846
+ case 'cell_deep_scan': {
1847
+ const { scanCodebase } = require('../code-scanner');
1848
+ const result = scanCodebase(args.dir, args.project || path.basename(args.dir));
1849
+ return { project: result.project, filesScanned: result.filesScanned, totalLines: result.totalLines, profile: result.profile, strengths: result.profile.strengths, improvements: result.profile.improvements };
1850
+ }
1851
+ case 'cell_scan_report': {
1852
+ const { getDeveloperProfile, getCodePatterns } = require('../code-scanner');
1853
+ const profile = getDeveloperProfile(args.project);
1854
+ const patterns = getCodePatterns(args.project);
1855
+ return { project: args.project, profile, patterns, patternCount: patterns.length };
1856
+ }
1857
+ case 'cell_send_signal': {
1858
+ const { logError, logDecision, logContext, logStuck } = require('../behavioral-tracker');
1859
+ const type = args.type;
1860
+ if (type === 'error')
1861
+ return logError({ project: args.project, file: args.file, errorType: 'manual', errorMessage: String(args.editedCode || ''), line: 0 });
1862
+ if (type === 'decision')
1863
+ return logDecision({ project: args.project, file: args.file, decision: String(args.originalCode || ''), approach: String(args.editedCode || ''), worked: true });
1864
+ if (type === 'context')
1865
+ return logContext({ project: args.project, task: String(args.originalCode || ''), files: [] });
1866
+ if (type === 'stuck')
1867
+ return logStuck({ project: args.project, file: args.file, description: String(args.originalCode || '') });
1868
+ return { recorded: true };
1869
+ }
1870
+ case 'cell_get_context': {
1871
+ const { buildContext, formatContextForTool } = require('../core/prompt-builder');
1872
+ const ctx = buildContext(args.project, args.tool);
1873
+ const toolName = args.tool || (args.project ? 'claude-code' : undefined);
1874
+ return { content: [{ type: 'text', text: formatContextForTool(ctx, toolName) }], context: ctx };
1875
+ }
1876
+ case 'cell_scan_full_pc': {
1877
+ const { scanFullPC } = require('../pc-scanner');
1878
+ const result = scanFullPC();
1879
+ return { totalProjects: result.totalProjects, totalFiles: result.totalFiles, totalLines: result.totalLines, profile: result.aggregatedProfile };
1880
+ }
1881
+ case 'cell_behavior_summary': {
1882
+ const { getBehaviorSummary } = require('../behavioral-tracker');
1883
+ return getBehaviorSummary(args.project);
1884
+ }
1885
+ case 'cell_log_error': {
1886
+ const { logError } = require('../behavioral-tracker');
1887
+ return logError({ project: args.project, file: args.file, errorType: args.errorType, errorMessage: args.errorMessage, line: args.line });
1888
+ }
1889
+ case 'cell_log_fix': {
1890
+ const { logErrorFix } = require('../behavioral-tracker');
1891
+ logErrorFix({ errorId: args.errorId, fixApplied: args.fixApplied, worked: args.worked, timeToFixMs: args.timeToFixMs });
1892
+ return { recorded: true };
1893
+ }
1894
+ case 'cell_log_decision': {
1895
+ const { logDecision } = require('../behavioral-tracker');
1896
+ return logDecision({ project: args.project, file: args.file, decision: args.decision, approach: args.approach, worked: args.worked });
1897
+ }
1898
+ case 'cell_log_context': {
1899
+ const { logContext } = require('../behavioral-tracker');
1900
+ return logContext({ project: args.project, task: args.task, files: args.files });
1901
+ }
1902
+ case 'cell_log_stuck': {
1903
+ const { logStuck } = require('../behavioral-tracker');
1904
+ return logStuck({ project: args.project, file: args.file, description: args.description });
1905
+ }
1906
+ case 'cell_session_bridge': {
1907
+ const { SessionMemory } = require('../core/session-memory');
1908
+ const memory = new SessionMemory();
1909
+ const project = args.project;
1910
+ const tool = args.tool || 'unknown';
1911
+ try {
1912
+ const lastSession = memory.getLastSessionForProject(project);
1913
+ const newSessionId = memory.startSession(tool, project);
1914
+ let bridgeContext = '';
1915
+ if (lastSession && lastSession.toolName !== tool) {
1916
+ const triedApproaches = memory.getRecentApproaches(project, 5);
1917
+ const openQuestions = memory.getOpenQuestions(project);
1918
+ const hotFiles = memory.getMostTouchedFiles(project, 5);
1919
+ const decisions = Array.isArray(lastSession.keyDecisions) ? JSON.stringify(lastSession.keyDecisions) : 'none';
1920
+ bridgeContext = formatSessionBridge(lastSession.toolName, tool, lastSession.contextSnapshot, decisions, {
1921
+ triedApproaches,
1922
+ openQuestions,
1923
+ hotFiles,
1924
+ });
1925
+ }
1926
+ const recentSessions = memory.getRecentSessions(3).filter((s) => s.project === project);
1927
+ const sessionHistory = recentSessions.map((s) => ({
1928
+ tool: s.toolName,
1929
+ when: s.startTime,
1930
+ files: s.filesTouched,
1931
+ decisions: s.keyDecisions,
1932
+ }));
1933
+ return {
1934
+ newSessionId,
1935
+ lastSession: lastSession ? {
1936
+ tool: lastSession.toolName,
1937
+ startedAt: lastSession.startTime,
1938
+ context: lastSession.contextSnapshot,
1939
+ } : null,
1940
+ bridgeContext,
1941
+ sessionHistory,
1942
+ triedApproaches: memory.getRecentApproaches(project, 5),
1943
+ openQuestions: memory.getOpenQuestions(project),
1944
+ hotFiles: memory.getMostTouchedFiles(project, 5),
1945
+ message: bridgeContext || 'No previous session to bridge. Start a new session!',
1946
+ };
1984
1947
  }
1985
- if (args.type === 'file' && args.filePath) {
1986
- memory.recordFileTouch({ sessionId: sessionId || undefined, project, filePath: args.filePath });
1987
- return { recorded: 'file' };
1948
+ catch (err) {
1949
+ const msg = err instanceof Error ? err.message : String(err);
1950
+ return { error: `Session bridge failed: ${msg}`, crossedSession: false };
1988
1951
  }
1989
- if (args.type === 'question' && args.question) {
1990
- const id = memory.recordQuestion({
1991
- sessionId: sessionId || undefined,
1992
- project,
1993
- question: args.question,
1994
- priority: args.priority || 'medium',
1952
+ }
1953
+ case 'cell_session_end': {
1954
+ const { SessionMemory } = require('../core/session-memory');
1955
+ const memory = new SessionMemory();
1956
+ const sessionId = args.sessionId;
1957
+ try {
1958
+ memory.endSession(sessionId, {
1959
+ filesTouched: Array.isArray(args.filesTouched) ? args.filesTouched : [],
1960
+ keyDecisions: Array.isArray(args.keyDecisions) ? args.keyDecisions : [],
1961
+ contextSnapshot: args.contextSnapshot || '',
1995
1962
  });
1996
- return { recorded: 'question', id };
1963
+ return { ended: true, sessionId };
1997
1964
  }
1998
- if (args.type === 'resolve' && args.questionId) {
1999
- memory.resolveQuestion(args.questionId, args.answer || '');
2000
- return { recorded: 'resolve' };
1965
+ catch (err) {
1966
+ const msg = err instanceof Error ? err.message : String(err);
1967
+ return { error: `Session end failed: ${msg}`, ended: false };
2001
1968
  }
2002
- return { error: 'unknown log type or missing field' };
2003
- }
2004
- catch (err) {
2005
- const msg = err instanceof Error ? err.message : String(err);
2006
- return { error: `Session log failed: ${msg}` };
2007
- }
2008
- }
2009
- case 'cell_session_start': {
2010
- const { SessionMemory } = require('../core/session-memory');
2011
- const memory = new SessionMemory();
2012
- try {
2013
- const project = args.project || 'unknown';
2014
- const tool = args.tool || 'unknown';
2015
- const sessionId = memory.startSession(tool, project);
2016
- return {
2017
- sessionId,
2018
- project,
2019
- tool,
2020
- startedAt: new Date().toISOString(),
2021
- message: `Session ${sessionId} started for ${project} on ${tool}`,
2022
- };
2023
- }
2024
- catch (err) {
2025
- const msg = err instanceof Error ? err.message : String(err);
2026
- return { error: `Session start failed: ${msg}` };
2027
- }
2028
- }
2029
- case 'cell_session_status': {
2030
- const { SessionMemory } = require('../core/session-memory');
2031
- const memory = new SessionMemory();
2032
- try {
2033
- const sessionId = args.sessionId;
2034
- const db = (0, database_1.getDb)();
2035
- const sess = db.prepare('SELECT * FROM sessions WHERE id = ?').get(sessionId);
2036
- if (!sess)
2037
- return { error: 'Session not found', sessionId };
2038
- const files = memory.getSessionFiles(sessionId);
2039
- const approaches = memory.getSessionApproaches(sessionId);
2040
- const isActive = !sess.end_time;
2041
- return {
2042
- sessionId,
2043
- tool: String(sess.tool_name || ''),
2044
- project: String(sess.project || ''),
2045
- startTime: String(sess.start_time || ''),
2046
- endTime: sess.end_time ? String(sess.end_time) : null,
2047
- isActive,
2048
- filesCount: files.length,
2049
- approachesCount: approaches.length,
2050
- files: files.slice(0, 10),
2051
- approaches: approaches.slice(0, 10),
2052
- };
2053
- }
2054
- catch (err) {
2055
- const msg = err instanceof Error ? err.message : String(err);
2056
- return { error: `Session status failed: ${msg}` };
2057
- }
2058
- }
2059
- case 'cell_session_recent': {
2060
- const { SessionMemory } = require('../core/session-memory');
2061
- const memory = new SessionMemory();
2062
- try {
2063
- const project = args.project;
2064
- const limit = args.limit || 10;
2065
- let sessions = memory.getRecentSessions(limit);
2066
- if (project)
2067
- sessions = sessions.filter((s) => s.project === project);
2068
- return {
2069
- count: sessions.length,
2070
- sessions: sessions.slice(0, limit).map((s) => ({
2071
- sessionId: s.id,
2072
- tool: s.toolName,
2073
- project: s.project,
2074
- startTime: s.startTime,
2075
- endTime: s.endTime || null,
2076
- filesCount: s.filesTouched.length,
2077
- decisionsCount: s.keyDecisions.length,
2078
- })),
2079
- };
2080
1969
  }
2081
- catch (err) {
2082
- const msg = err instanceof Error ? err.message : String(err);
2083
- return { error: `Session recent failed: ${msg}` };
2084
- }
2085
- }
2086
- case 'cell_session_recommendations': {
2087
- const { SessionMemory } = require('../core/session-memory');
2088
- const memory = new SessionMemory();
2089
- try {
2090
- const project = args.project || 'unknown';
2091
- const triedApproaches = memory.getRecentApproaches(project, 10);
2092
- const openQuestions = memory.getOpenQuestions(project);
2093
- const hotFiles = memory.getMostTouchedFiles(project, 10);
2094
- const lastSession = memory.getLastSessionForProject(project);
2095
- const avoid = [];
2096
- for (const a of triedApproaches) {
2097
- if (a.status === 'failed') {
2098
- avoid.push({ approach: a.approach, reason: `failed ${a.count}x` });
1970
+ case 'cell_session_log': {
1971
+ const { SessionMemory } = require('../core/session-memory');
1972
+ const memory = new SessionMemory();
1973
+ try {
1974
+ const sessionId = args.sessionId || 0;
1975
+ const project = args.project || 'unknown';
1976
+ if (args.type === 'approach' && args.approach) {
1977
+ const id = memory.recordApproach({
1978
+ sessionId: sessionId || undefined,
1979
+ project,
1980
+ approach: args.approach,
1981
+ status: args.status || 'tried',
1982
+ reason: args.reason,
1983
+ });
1984
+ return { recorded: 'approach', id };
1985
+ }
1986
+ if (args.type === 'file' && args.filePath) {
1987
+ memory.recordFileTouch({ sessionId: sessionId || undefined, project, filePath: args.filePath });
1988
+ return { recorded: 'file' };
1989
+ }
1990
+ if (args.type === 'question' && args.question) {
1991
+ const id = memory.recordQuestion({
1992
+ sessionId: sessionId || undefined,
1993
+ project,
1994
+ question: args.question,
1995
+ priority: args.priority || 'medium',
1996
+ });
1997
+ return { recorded: 'question', id };
2099
1998
  }
2100
- else if (a.status === 'partial') {
2101
- avoid.push({ approach: a.approach, reason: `partial (${a.count}x)` });
1999
+ if (args.type === 'resolve' && args.questionId) {
2000
+ memory.resolveQuestion(args.questionId, args.answer || '');
2001
+ return { recorded: 'resolve' };
2102
2002
  }
2003
+ return { error: 'unknown log type or missing field' };
2004
+ }
2005
+ catch (err) {
2006
+ const msg = err instanceof Error ? err.message : String(err);
2007
+ return { error: `Session log failed: ${msg}` };
2103
2008
  }
2104
- return {
2105
- avoid,
2106
- openQuestions: openQuestions.map((q) => ({ id: q.id, question: q.question, priority: q.priority })),
2107
- hotFiles: hotFiles.slice(0, 5).map((f) => ({ path: f.filePath, touches: f.touchCount })),
2108
- lastSession: lastSession ? {
2109
- tool: lastSession.toolName,
2110
- when: lastSession.endTime,
2111
- context: lastSession.contextSnapshot,
2112
- } : null,
2113
- message: avoid.length > 0
2114
- ? `Don't suggest: ${avoid.map(a => a.approach).slice(0, 3).join(', ')}`
2115
- : 'No anti-repetition data yet',
2116
- };
2117
2009
  }
2118
- catch (err) {
2119
- const msg = err instanceof Error ? err.message : String(err);
2120
- return { error: `Session recommendations failed: ${msg}` };
2010
+ case 'cell_session_start': {
2011
+ const { SessionMemory } = require('../core/session-memory');
2012
+ const memory = new SessionMemory();
2013
+ try {
2014
+ const project = args.project || 'unknown';
2015
+ const tool = args.tool || 'unknown';
2016
+ const sessionId = memory.startSession(tool, project);
2017
+ return {
2018
+ sessionId,
2019
+ project,
2020
+ tool,
2021
+ startedAt: new Date().toISOString(),
2022
+ message: `Session ${sessionId} started for ${project} on ${tool}`,
2023
+ };
2024
+ }
2025
+ catch (err) {
2026
+ const msg = err instanceof Error ? err.message : String(err);
2027
+ return { error: `Session start failed: ${msg}` };
2028
+ }
2121
2029
  }
2122
- }
2123
- case 'cell_list_projects': {
2124
- const { ProjectRegistry } = require('../core/project-registry');
2125
- const registry = new ProjectRegistry();
2126
- try {
2127
- const projects = registry.listProjects();
2128
- return {
2129
- count: projects.length,
2130
- projects: projects.map((p) => ({
2131
- name: p.name,
2132
- path: p.path,
2133
- stack: p.stack,
2134
- fileCount: p.fileCount,
2135
- lastScanAt: p.lastScanAt,
2136
- })),
2137
- };
2030
+ case 'cell_session_status': {
2031
+ const { SessionMemory } = require('../core/session-memory');
2032
+ const memory = new SessionMemory();
2033
+ try {
2034
+ const sessionId = args.sessionId;
2035
+ const db = (0, database_1.getDb)();
2036
+ const sess = db.prepare('SELECT * FROM sessions WHERE id = ?').get(sessionId);
2037
+ if (!sess)
2038
+ return { error: 'Session not found', sessionId };
2039
+ const files = memory.getSessionFiles(sessionId);
2040
+ const approaches = memory.getSessionApproaches(sessionId);
2041
+ const isActive = !sess.end_time;
2042
+ return {
2043
+ sessionId,
2044
+ tool: String(sess.tool_name || ''),
2045
+ project: String(sess.project || ''),
2046
+ startTime: String(sess.start_time || ''),
2047
+ endTime: sess.end_time ? String(sess.end_time) : null,
2048
+ isActive,
2049
+ filesCount: files.length,
2050
+ approachesCount: approaches.length,
2051
+ files: files.slice(0, 10),
2052
+ approaches: approaches.slice(0, 10),
2053
+ };
2054
+ }
2055
+ catch (err) {
2056
+ const msg = err instanceof Error ? err.message : String(err);
2057
+ return { error: `Session status failed: ${msg}` };
2058
+ }
2138
2059
  }
2139
- catch (err) {
2140
- const msg = err instanceof Error ? err.message : String(err);
2141
- return { error: `List projects failed: ${msg}` };
2060
+ case 'cell_session_recent': {
2061
+ const { SessionMemory } = require('../core/session-memory');
2062
+ const memory = new SessionMemory();
2063
+ try {
2064
+ const project = args.project;
2065
+ const limit = args.limit || 10;
2066
+ let sessions = memory.getRecentSessions(limit);
2067
+ if (project)
2068
+ sessions = sessions.filter((s) => s.project === project);
2069
+ return {
2070
+ count: sessions.length,
2071
+ sessions: sessions.slice(0, limit).map((s) => ({
2072
+ sessionId: s.id,
2073
+ tool: s.toolName,
2074
+ project: s.project,
2075
+ startTime: s.startTime,
2076
+ endTime: s.endTime || null,
2077
+ filesCount: s.filesTouched.length,
2078
+ decisionsCount: s.keyDecisions.length,
2079
+ })),
2080
+ };
2081
+ }
2082
+ catch (err) {
2083
+ const msg = err instanceof Error ? err.message : String(err);
2084
+ return { error: `Session recent failed: ${msg}` };
2085
+ }
2142
2086
  }
2143
- }
2144
- case 'cell_get_project': {
2145
- const { ProjectRegistry } = require('../core/project-registry');
2146
- const registry = new ProjectRegistry();
2147
- try {
2148
- const name = args.name || '';
2149
- const project = registry.getProject(name);
2150
- if (!project)
2151
- return { error: 'Project not found', name };
2152
- return {
2153
- name: project.name,
2154
- path: project.path,
2155
- stack: project.stack,
2156
- fileCount: project.fileCount,
2157
- lastScanAt: project.lastScanAt,
2158
- };
2087
+ case 'cell_session_recommendations': {
2088
+ const { SessionMemory } = require('../core/session-memory');
2089
+ const memory = new SessionMemory();
2090
+ try {
2091
+ const project = args.project || 'unknown';
2092
+ const triedApproaches = memory.getRecentApproaches(project, 10);
2093
+ const openQuestions = memory.getOpenQuestions(project);
2094
+ const hotFiles = memory.getMostTouchedFiles(project, 10);
2095
+ const lastSession = memory.getLastSessionForProject(project);
2096
+ const avoid = [];
2097
+ for (const a of triedApproaches) {
2098
+ if (a.status === 'failed') {
2099
+ avoid.push({ approach: a.approach, reason: `failed ${a.count}x` });
2100
+ }
2101
+ else if (a.status === 'partial') {
2102
+ avoid.push({ approach: a.approach, reason: `partial (${a.count}x)` });
2103
+ }
2104
+ }
2105
+ return {
2106
+ avoid,
2107
+ openQuestions: openQuestions.map((q) => ({ id: q.id, question: q.question, priority: q.priority })),
2108
+ hotFiles: hotFiles.slice(0, 5).map((f) => ({ path: f.filePath, touches: f.touchCount })),
2109
+ lastSession: lastSession ? {
2110
+ tool: lastSession.toolName,
2111
+ when: lastSession.endTime,
2112
+ context: lastSession.contextSnapshot,
2113
+ } : null,
2114
+ message: avoid.length > 0
2115
+ ? `Don't suggest: ${avoid.map(a => a.approach).slice(0, 3).join(', ')}`
2116
+ : 'No anti-repetition data yet',
2117
+ };
2118
+ }
2119
+ catch (err) {
2120
+ const msg = err instanceof Error ? err.message : String(err);
2121
+ return { error: `Session recommendations failed: ${msg}` };
2122
+ }
2159
2123
  }
2160
- catch (err) {
2161
- const msg = err instanceof Error ? err.message : String(err);
2162
- return { error: `Get project failed: ${msg}` };
2124
+ case 'cell_list_projects': {
2125
+ const { ProjectRegistry } = require('../core/project-registry');
2126
+ const registry = new ProjectRegistry();
2127
+ try {
2128
+ const projects = registry.listProjects();
2129
+ return {
2130
+ count: projects.length,
2131
+ projects: projects.map((p) => ({
2132
+ name: p.name,
2133
+ path: p.path,
2134
+ stack: p.stack,
2135
+ fileCount: p.fileCount,
2136
+ lastScanAt: p.lastScanAt,
2137
+ })),
2138
+ };
2139
+ }
2140
+ catch (err) {
2141
+ const msg = err instanceof Error ? err.message : String(err);
2142
+ return { error: `List projects failed: ${msg}` };
2143
+ }
2163
2144
  }
2164
- }
2165
- case 'cell_detect_project': {
2166
- const { ProjectRegistry } = require('../core/project-registry');
2167
- const registry = new ProjectRegistry();
2168
- try {
2169
- const cwd = args.cwd || '';
2170
- const detected = registry.detectProjectFromCwd(cwd);
2171
- if (!detected) {
2172
- return { detected: null, cwd, message: 'No matching project found for this path' };
2173
- }
2174
- const project = registry.getProject(detected);
2175
- return {
2176
- detected,
2177
- cwd,
2178
- project: project ? {
2145
+ case 'cell_get_project': {
2146
+ const { ProjectRegistry } = require('../core/project-registry');
2147
+ const registry = new ProjectRegistry();
2148
+ try {
2149
+ const name = args.name || '';
2150
+ const project = registry.getProject(name);
2151
+ if (!project)
2152
+ return { error: 'Project not found', name };
2153
+ return {
2179
2154
  name: project.name,
2155
+ path: project.path,
2180
2156
  stack: project.stack,
2181
2157
  fileCount: project.fileCount,
2182
2158
  lastScanAt: project.lastScanAt,
2183
- } : null,
2184
- message: `Detected project: ${detected}`,
2185
- };
2186
- }
2187
- catch (err) {
2188
- const msg = err instanceof Error ? err.message : String(err);
2189
- return { error: `Detect project failed: ${msg}` };
2190
- }
2191
- }
2192
- case 'cell_register_project': {
2193
- const { ProjectRegistry } = require('../core/project-registry');
2194
- const registry = new ProjectRegistry();
2195
- try {
2196
- const id = registry.registerProject({
2197
- name: args.name || '',
2198
- path: args.path || '',
2199
- stack: args.stack,
2200
- fileCount: args.fileCount,
2201
- });
2202
- return { id, name: args.name, registered: true };
2203
- }
2204
- catch (err) {
2205
- const msg = err instanceof Error ? err.message : String(err);
2206
- return { error: `Register project failed: ${msg}` };
2207
- }
2208
- }
2209
- case 'cell_graph_files': {
2210
- try {
2211
- const project = args.project || '';
2212
- const limit = args.limit || 20;
2213
- const { getFileKnowledgeGraph } = require('../core/knowledge-graph-store');
2214
- const graph = getFileKnowledgeGraph(project);
2215
- return {
2216
- stats: graph.stats,
2217
- topRiskFiles: graph.files.slice(0, limit),
2218
- entryPoints: graph.files.filter((f) => f.isEntryPoint).slice(0, 10),
2219
- sampleDeps: graph.deps.slice(0, limit),
2220
- };
2221
- }
2222
- catch (err) {
2223
- const msg = err instanceof Error ? err.message : String(err);
2224
- return { error: `Graph files failed: ${msg}` };
2225
- }
2226
- }
2227
- case 'cell_graph_blast_radius': {
2228
- try {
2229
- const project = args.project || '';
2230
- const file = args.file || '';
2231
- const { computeBlastRadius } = require('../core/knowledge-graph-store');
2232
- const radius = computeBlastRadius(project, file);
2233
- return radius;
2234
- }
2235
- catch (err) {
2236
- const msg = err instanceof Error ? err.message : String(err);
2237
- return { error: `Blast radius failed: ${msg}` };
2238
- }
2239
- }
2240
- case 'cell_graph_tech': {
2241
- try {
2242
- const project = args.project || '';
2243
- const { getTechProficiency } = require('../core/knowledge-graph-store');
2244
- const techs = getTechProficiency(project);
2245
- const strong = techs.filter((t) => t.proficiencyScore >= 70);
2246
- const learning = techs.filter((t) => t.proficiencyScore < 50);
2247
- return {
2248
- totalTechs: techs.length,
2249
- strong,
2250
- learning,
2251
- all: techs,
2252
- message: strong.length > 0
2253
- ? `Strong in: ${strong.map((t) => t.technology).slice(0, 3).join(', ')}`
2254
- : 'No strong tech tracked yet',
2255
- };
2256
- }
2257
- catch (err) {
2258
- const msg = err instanceof Error ? err.message : String(err);
2259
- return { error: `Graph tech failed: ${msg}` };
2260
- }
2261
- }
2262
- case 'cell_graph_stats': {
2263
- try {
2264
- const project = args.project || '';
2265
- const { getPatternGraphStats, getFileKnowledgeGraph, getTechProficiency } = require('../core/knowledge-graph-store');
2266
- const patternStats = getPatternGraphStats(project);
2267
- const fileGraph = getFileKnowledgeGraph(project);
2268
- const techs = getTechProficiency(project);
2269
- return {
2270
- patternGraph: patternStats,
2271
- fileGraph: fileGraph.stats,
2272
- techCount: techs.length,
2273
- highRiskFiles: fileGraph.files.filter((f) => f.riskScore >= 50).length,
2274
- };
2275
- }
2276
- catch (err) {
2277
- const msg = err instanceof Error ? err.message : String(err);
2278
- return { error: `Graph stats failed: ${msg}` };
2279
- }
2280
- }
2281
- case 'cell_team_silos': {
2282
- try {
2283
- const { detectKnowledgeSilos } = require('../team-collaboration');
2284
- const silos = detectKnowledgeSilos();
2285
- return {
2286
- count: silos.length,
2287
- high: silos.filter((s) => s.riskLevel === 'high').length,
2288
- silos,
2289
- message: silos.length > 0
2290
- ? `${silos.filter((s) => s.riskLevel === 'high').length} high-risk silos detected`
2291
- : 'No knowledge silos detected',
2292
- };
2293
- }
2294
- catch (err) {
2295
- const msg = err instanceof Error ? err.message : String(err);
2296
- return { error: `Team silos failed: ${msg}` };
2297
- }
2298
- }
2299
- case 'cell_team_bus_factor': {
2300
- try {
2301
- const { calculateBusFactor } = require('../team-collaboration');
2302
- return calculateBusFactor();
2303
- }
2304
- catch (err) {
2305
- const msg = err instanceof Error ? err.message : String(err);
2306
- return { error: `Bus factor failed: ${msg}` };
2307
- }
2308
- }
2309
- case 'cell_team_health': {
2310
- try {
2311
- const { getTeamHealth } = require('../team-collaboration');
2312
- return getTeamHealth(args.project || undefined);
2313
- }
2314
- catch (err) {
2315
- const msg = err instanceof Error ? err.message : String(err);
2316
- return { error: `Team health failed: ${msg}` };
2317
- }
2318
- }
2319
- case 'cell_team_onboard': {
2320
- try {
2321
- const { generateOnboardingDoc } = require('../team-collaboration');
2322
- const teamName = args.teamName || 'Team';
2323
- const project = args.project || undefined;
2324
- return generateOnboardingDoc(teamName, project);
2325
- }
2326
- catch (err) {
2327
- const msg = err instanceof Error ? err.message : String(err);
2328
- return { error: `Onboard failed: ${msg}` };
2329
- }
2330
- }
2331
- case 'cell_team_retro': {
2332
- try {
2333
- const { generateSprintRetro } = require('../team-collaboration');
2334
- const days = args.days || 14;
2335
- const project = args.project || undefined;
2336
- return generateSprintRetro(days, project);
2337
- }
2338
- catch (err) {
2339
- const msg = err instanceof Error ? err.message : String(err);
2340
- return { error: `Retro failed: ${msg}` };
2341
- }
2342
- }
2343
- case 'cell_team_handoff': {
2344
- try {
2345
- const { generateHandoff } = require('../team-collaboration');
2346
- return generateHandoff(args.from || '', args.to || '', args.project || '');
2347
- }
2348
- catch (err) {
2349
- const msg = err instanceof Error ? err.message : String(err);
2350
- return { error: `Handoff failed: ${msg}` };
2351
- }
2352
- }
2353
- case 'cell_team_knowledge_transfer': {
2354
- try {
2355
- const { suggestKnowledgeTransfer } = require('../team-collaboration');
2356
- const suggestions = suggestKnowledgeTransfer();
2357
- return {
2358
- count: suggestions.length,
2359
- suggestions,
2360
- message: suggestions.length > 0
2361
- ? `${suggestions.length} transfer pairs suggested`
2362
- : 'No urgent transfers needed',
2363
- };
2364
- }
2365
- catch (err) {
2366
- const msg = err instanceof Error ? err.message : String(err);
2367
- return { error: `Knowledge transfer failed: ${msg}` };
2368
- }
2369
- }
2370
- case 'cell_team_style': {
2371
- try {
2372
- const { composeTeamStyle } = require('../team-collaboration');
2373
- return composeTeamStyle(args.project || undefined);
2374
- }
2375
- catch (err) {
2376
- const msg = err instanceof Error ? err.message : String(err);
2377
- return { error: `Team style failed: ${msg}` };
2378
- }
2379
- }
2380
- case 'cell_team_dashboard': {
2381
- try {
2382
- const { detectKnowledgeSilos, calculateBusFactor, getTeamHealth, composeTeamStyle } = require('../team-collaboration');
2383
- const project = args.project || undefined;
2384
- const silos = detectKnowledgeSilos();
2385
- const busFactor = calculateBusFactor();
2386
- const health = getTeamHealth(project);
2387
- const style = composeTeamStyle(project);
2388
- return {
2389
- silos: { count: silos.length, high: silos.filter((s) => s.riskLevel === 'high').length, top: silos.slice(0, 5) },
2390
- busFactor,
2391
- health,
2392
- style,
2393
- generatedAt: new Date().toISOString(),
2394
- };
2395
- }
2396
- catch (err) {
2397
- const msg = err instanceof Error ? err.message : String(err);
2398
- return { error: `Team dashboard failed: ${msg}` };
2399
- }
2400
- }
2401
- case 'cell_community_stats': {
2402
- try {
2403
- const { getCommunityStats } = require('../core/community-store');
2404
- return getCommunityStats();
2405
- }
2406
- catch (err) {
2407
- const msg = err instanceof Error ? err.message : String(err);
2408
- return { error: `Community stats failed: ${msg}` };
2409
- }
2410
- }
2411
- case 'cell_community_share': {
2412
- try {
2413
- const { shareCommunityPattern, validatePrivacy } = require('../core/community-store');
2414
- const rule = args.rule || '';
2415
- const validation = validatePrivacy(rule);
2416
- if (!validation.safe) {
2417
- return { shared: false, errors: validation.errors, warnings: validation.warnings };
2418
- }
2419
- const result = shareCommunityPattern({
2420
- category: args.category || 'unknown',
2421
- rule,
2422
- language: args.language,
2423
- framework: args.framework,
2424
- successRate: args.successRate,
2425
- });
2426
- return { ...result, warnings: [...validation.warnings, ...result.warnings] };
2427
- }
2428
- catch (err) {
2429
- const msg = err instanceof Error ? err.message : String(err);
2430
- return { error: `Community share failed: ${msg}` };
2431
- }
2432
- }
2433
- case 'cell_community_patterns': {
2434
- try {
2435
- const { getCommunityPatterns } = require('../core/community-store');
2436
- const patterns = getCommunityPatterns({
2437
- category: args.category,
2438
- language: args.language,
2439
- minVotes: args.minVotes,
2440
- limit: args.limit || 20,
2441
- });
2442
- return { count: patterns.length, patterns };
2443
- }
2444
- catch (err) {
2445
- const msg = err instanceof Error ? err.message : String(err);
2446
- return { error: `Community patterns failed: ${msg}` };
2447
- }
2448
- }
2449
- case 'cell_community_vote': {
2450
- try {
2451
- const { voteCommunityPattern } = require('../core/community-store');
2452
- return voteCommunityPattern(args.patternId || '', args.upvote !== false);
2453
- }
2454
- catch (err) {
2455
- const msg = err instanceof Error ? err.message : String(err);
2456
- return { error: `Community vote failed: ${msg}` };
2457
- }
2458
- }
2459
- case 'cell_community_insights': {
2460
- try {
2461
- const { getCommunityInsights } = require('../core/community-store');
2462
- const insights = getCommunityInsights({
2463
- severity: args.severity,
2464
- category: args.category,
2465
- limit: args.limit || 20,
2466
- });
2467
- return { count: insights.length, insights };
2159
+ };
2160
+ }
2161
+ catch (err) {
2162
+ const msg = err instanceof Error ? err.message : String(err);
2163
+ return { error: `Get project failed: ${msg}` };
2164
+ }
2468
2165
  }
2469
- catch (err) {
2470
- const msg = err instanceof Error ? err.message : String(err);
2471
- return { error: `Community insights failed: ${msg}` };
2166
+ case 'cell_detect_project': {
2167
+ const { ProjectRegistry } = require('../core/project-registry');
2168
+ const registry = new ProjectRegistry();
2169
+ try {
2170
+ const cwd = args.cwd || '';
2171
+ const detected = registry.detectProjectFromCwd(cwd);
2172
+ if (!detected) {
2173
+ return { detected: null, cwd, message: 'No matching project found for this path' };
2174
+ }
2175
+ const project = registry.getProject(detected);
2176
+ return {
2177
+ detected,
2178
+ cwd,
2179
+ project: project ? {
2180
+ name: project.name,
2181
+ stack: project.stack,
2182
+ fileCount: project.fileCount,
2183
+ lastScanAt: project.lastScanAt,
2184
+ } : null,
2185
+ message: `Detected project: ${detected}`,
2186
+ };
2187
+ }
2188
+ catch (err) {
2189
+ const msg = err instanceof Error ? err.message : String(err);
2190
+ return { error: `Detect project failed: ${msg}` };
2191
+ }
2472
2192
  }
2473
- }
2474
- case 'cell_community_benchmarks': {
2475
- try {
2476
- const { getBenchmarks } = require('../core/community-store');
2477
- const benchmarks = getBenchmarks({
2478
- category: args.category,
2479
- limit: args.limit || 50,
2480
- });
2481
- return { count: benchmarks.length, benchmarks };
2193
+ case 'cell_register_project': {
2194
+ const { ProjectRegistry } = require('../core/project-registry');
2195
+ const registry = new ProjectRegistry();
2196
+ try {
2197
+ const id = registry.registerProject({
2198
+ name: args.name || '',
2199
+ path: args.path || '',
2200
+ stack: args.stack,
2201
+ fileCount: args.fileCount,
2202
+ });
2203
+ return { id, name: args.name, registered: true };
2204
+ }
2205
+ catch (err) {
2206
+ const msg = err instanceof Error ? err.message : String(err);
2207
+ return { error: `Register project failed: ${msg}` };
2208
+ }
2482
2209
  }
2483
- catch (err) {
2484
- const msg = err instanceof Error ? err.message : String(err);
2485
- return { error: `Community benchmarks failed: ${msg}` };
2210
+ case 'cell_graph_files': {
2211
+ try {
2212
+ const project = args.project || '';
2213
+ const limit = args.limit || 20;
2214
+ const { getFileKnowledgeGraph } = require('../core/knowledge-graph-store');
2215
+ const graph = getFileKnowledgeGraph(project);
2216
+ return {
2217
+ stats: graph.stats,
2218
+ topRiskFiles: graph.files.slice(0, limit),
2219
+ entryPoints: graph.files.filter((f) => f.isEntryPoint).slice(0, 10),
2220
+ sampleDeps: graph.deps.slice(0, limit),
2221
+ };
2222
+ }
2223
+ catch (err) {
2224
+ const msg = err instanceof Error ? err.message : String(err);
2225
+ return { error: `Graph files failed: ${msg}` };
2226
+ }
2486
2227
  }
2487
- }
2488
- case 'cell_community_trends': {
2489
- try {
2490
- const { getTechEvolution } = require('../core/community-store');
2491
- return getTechEvolution();
2228
+ case 'cell_graph_blast_radius': {
2229
+ try {
2230
+ const project = args.project || '';
2231
+ const file = args.file || '';
2232
+ const { computeBlastRadius } = require('../core/knowledge-graph-store');
2233
+ const radius = computeBlastRadius(project, file);
2234
+ return radius;
2235
+ }
2236
+ catch (err) {
2237
+ const msg = err instanceof Error ? err.message : String(err);
2238
+ return { error: `Blast radius failed: ${msg}` };
2239
+ }
2492
2240
  }
2493
- catch (err) {
2494
- const msg = err instanceof Error ? err.message : String(err);
2495
- return { error: `Community trends failed: ${msg}` };
2241
+ case 'cell_graph_tech': {
2242
+ try {
2243
+ const project = args.project || '';
2244
+ const { getTechProficiency } = require('../core/knowledge-graph-store');
2245
+ const techs = getTechProficiency(project);
2246
+ const strong = techs.filter((t) => t.proficiencyScore >= 70);
2247
+ const learning = techs.filter((t) => t.proficiencyScore < 50);
2248
+ return {
2249
+ totalTechs: techs.length,
2250
+ strong,
2251
+ learning,
2252
+ all: techs,
2253
+ message: strong.length > 0
2254
+ ? `Strong in: ${strong.map((t) => t.technology).slice(0, 3).join(', ')}`
2255
+ : 'No strong tech tracked yet',
2256
+ };
2257
+ }
2258
+ catch (err) {
2259
+ const msg = err instanceof Error ? err.message : String(err);
2260
+ return { error: `Graph tech failed: ${msg}` };
2261
+ }
2496
2262
  }
2497
- }
2498
- case 'cell_community_failures': {
2499
- try {
2500
- const { getFailurePatterns } = require('../core/community-store');
2501
- const failures = getFailurePatterns({
2502
- language: args.language,
2503
- limit: args.limit || 10,
2504
- });
2505
- return { count: failures.length, failures };
2263
+ case 'cell_graph_stats': {
2264
+ try {
2265
+ const project = args.project || '';
2266
+ const { getPatternGraphStats, getFileKnowledgeGraph, getTechProficiency } = require('../core/knowledge-graph-store');
2267
+ const patternStats = getPatternGraphStats(project);
2268
+ const fileGraph = getFileKnowledgeGraph(project);
2269
+ const techs = getTechProficiency(project);
2270
+ return {
2271
+ patternGraph: patternStats,
2272
+ fileGraph: fileGraph.stats,
2273
+ techCount: techs.length,
2274
+ highRiskFiles: fileGraph.files.filter((f) => f.riskScore >= 50).length,
2275
+ };
2276
+ }
2277
+ catch (err) {
2278
+ const msg = err instanceof Error ? err.message : String(err);
2279
+ return { error: `Graph stats failed: ${msg}` };
2280
+ }
2506
2281
  }
2507
- catch (err) {
2508
- const msg = err instanceof Error ? err.message : String(err);
2509
- return { error: `Community failures failed: ${msg}` };
2282
+ case 'cell_team_silos': {
2283
+ try {
2284
+ const { detectKnowledgeSilos } = require('../team-collaboration');
2285
+ const silos = detectKnowledgeSilos();
2286
+ return {
2287
+ count: silos.length,
2288
+ high: silos.filter((s) => s.riskLevel === 'high').length,
2289
+ silos,
2290
+ message: silos.length > 0
2291
+ ? `${silos.filter((s) => s.riskLevel === 'high').length} high-risk silos detected`
2292
+ : 'No knowledge silos detected',
2293
+ };
2294
+ }
2295
+ catch (err) {
2296
+ const msg = err instanceof Error ? err.message : String(err);
2297
+ return { error: `Team silos failed: ${msg}` };
2298
+ }
2510
2299
  }
2511
- }
2512
- case 'cell_community_validate': {
2513
- try {
2514
- const { validatePrivacy } = require('../core/community-store');
2515
- return validatePrivacy(args.rule || '');
2300
+ case 'cell_team_bus_factor': {
2301
+ try {
2302
+ const { calculateBusFactor } = require('../team-collaboration');
2303
+ return calculateBusFactor();
2304
+ }
2305
+ catch (err) {
2306
+ const msg = err instanceof Error ? err.message : String(err);
2307
+ return { error: `Bus factor failed: ${msg}` };
2308
+ }
2516
2309
  }
2517
- catch (err) {
2518
- const msg = err instanceof Error ? err.message : String(err);
2519
- return { error: `Community validate failed: ${msg}` };
2310
+ case 'cell_team_health': {
2311
+ try {
2312
+ const { getTeamHealth } = require('../team-collaboration');
2313
+ return getTeamHealth(args.project || undefined);
2314
+ }
2315
+ catch (err) {
2316
+ const msg = err instanceof Error ? err.message : String(err);
2317
+ return { error: `Team health failed: ${msg}` };
2318
+ }
2520
2319
  }
2521
- }
2522
- case 'cell_community_dashboard': {
2523
- try {
2524
- const { getCommunityStats, getTechEvolution, getCommunityInsights, getBenchmarks } = require('../core/community-store');
2525
- const stats = getCommunityStats();
2526
- const trends = getTechEvolution();
2527
- const insights = getCommunityInsights({ severity: 'critical', limit: 5 });
2528
- const benchmarks = getBenchmarks({ limit: 5 });
2529
- return {
2530
- stats,
2531
- trends: trends.slice(0, 10),
2532
- insights,
2533
- benchmarks,
2534
- generatedAt: new Date().toISOString(),
2535
- };
2320
+ case 'cell_team_onboard': {
2321
+ try {
2322
+ const { generateOnboardingDoc } = require('../team-collaboration');
2323
+ const teamName = args.teamName || 'Team';
2324
+ const project = args.project || undefined;
2325
+ return generateOnboardingDoc(teamName, project);
2326
+ }
2327
+ catch (err) {
2328
+ const msg = err instanceof Error ? err.message : String(err);
2329
+ return { error: `Onboard failed: ${msg}` };
2330
+ }
2536
2331
  }
2537
- catch (err) {
2538
- const msg = err instanceof Error ? err.message : String(err);
2539
- return { error: `Community dashboard failed: ${msg}` };
2332
+ case 'cell_team_retro': {
2333
+ try {
2334
+ const { generateSprintRetro } = require('../team-collaboration');
2335
+ const days = args.days || 14;
2336
+ const project = args.project || undefined;
2337
+ return generateSprintRetro(days, project);
2338
+ }
2339
+ catch (err) {
2340
+ const msg = err instanceof Error ? err.message : String(err);
2341
+ return { error: `Retro failed: ${msg}` };
2342
+ }
2540
2343
  }
2541
- }
2542
- case 'cell_usage_decision_log': {
2543
- try {
2544
- const { logDecisionOutcome } = require('../core/usage-intelligence-store');
2545
- return logDecisionOutcome({
2546
- project: args.project || 'unknown',
2547
- technology: args.technology || '',
2548
- reason: args.reason || '',
2549
- outcome: args.outcome || '',
2550
- wasRight: args.wasRight === true,
2551
- confidence: args.confidence,
2552
- });
2344
+ case 'cell_team_handoff': {
2345
+ try {
2346
+ const { generateHandoff } = require('../team-collaboration');
2347
+ return generateHandoff(args.from || '', args.to || '', args.project || '');
2348
+ }
2349
+ catch (err) {
2350
+ const msg = err instanceof Error ? err.message : String(err);
2351
+ return { error: `Handoff failed: ${msg}` };
2352
+ }
2553
2353
  }
2554
- catch (err) {
2555
- const msg = err instanceof Error ? err.message : String(err);
2556
- return { error: `Decision log failed: ${msg}` };
2354
+ case 'cell_team_knowledge_transfer': {
2355
+ try {
2356
+ const { suggestKnowledgeTransfer } = require('../team-collaboration');
2357
+ const suggestions = suggestKnowledgeTransfer();
2358
+ return {
2359
+ count: suggestions.length,
2360
+ suggestions,
2361
+ message: suggestions.length > 0
2362
+ ? `${suggestions.length} transfer pairs suggested`
2363
+ : 'No urgent transfers needed',
2364
+ };
2365
+ }
2366
+ catch (err) {
2367
+ const msg = err instanceof Error ? err.message : String(err);
2368
+ return { error: `Knowledge transfer failed: ${msg}` };
2369
+ }
2557
2370
  }
2558
- }
2559
- case 'cell_usage_decision_patterns': {
2560
- try {
2561
- const { getDecisionPatterns } = require('../core/usage-intelligence-store');
2562
- const patterns = getDecisionPatterns(args.project || 'unknown');
2563
- return {
2564
- count: patterns.length,
2565
- patterns,
2566
- message: patterns.length > 0
2567
- ? `Analyzed ${patterns.length} technology decision patterns`
2568
- : 'Need more decisions (>= 2 per tech) to detect patterns',
2569
- };
2371
+ case 'cell_team_style': {
2372
+ try {
2373
+ const { composeTeamStyle } = require('../team-collaboration');
2374
+ return composeTeamStyle(args.project || undefined);
2375
+ }
2376
+ catch (err) {
2377
+ const msg = err instanceof Error ? err.message : String(err);
2378
+ return { error: `Team style failed: ${msg}` };
2379
+ }
2570
2380
  }
2571
- catch (err) {
2572
- const msg = err instanceof Error ? err.message : String(err);
2573
- return { error: `Decision patterns failed: ${msg}` };
2381
+ case 'cell_team_dashboard': {
2382
+ try {
2383
+ const { detectKnowledgeSilos, calculateBusFactor, getTeamHealth, composeTeamStyle } = require('../team-collaboration');
2384
+ const project = args.project || undefined;
2385
+ const silos = detectKnowledgeSilos();
2386
+ const busFactor = calculateBusFactor();
2387
+ const health = getTeamHealth(project);
2388
+ const style = composeTeamStyle(project);
2389
+ return {
2390
+ silos: { count: silos.length, high: silos.filter((s) => s.riskLevel === 'high').length, top: silos.slice(0, 5) },
2391
+ busFactor,
2392
+ health,
2393
+ style,
2394
+ generatedAt: new Date().toISOString(),
2395
+ };
2396
+ }
2397
+ catch (err) {
2398
+ const msg = err instanceof Error ? err.message : String(err);
2399
+ return { error: `Team dashboard failed: ${msg}` };
2400
+ }
2574
2401
  }
2575
- }
2576
- case 'cell_usage_repeat_mistakes': {
2577
- try {
2578
- const { detectRepeatMistakes } = require('../core/usage-intelligence-store');
2579
- const mistakes = detectRepeatMistakes(args.project || 'unknown');
2580
- return {
2581
- count: mistakes.length,
2582
- critical: mistakes.filter((m) => m.severity === 'critical').length,
2583
- mistakes: mistakes.slice(0, 20),
2584
- message: mistakes.length > 0
2585
- ? `Found ${mistakes.length} repeated error patterns`
2586
- : 'No repeated mistakes — clean track record',
2587
- };
2402
+ case 'cell_community_stats': {
2403
+ try {
2404
+ const { getCommunityStats } = require('../core/community-store');
2405
+ return getCommunityStats();
2406
+ }
2407
+ catch (err) {
2408
+ const msg = err instanceof Error ? err.message : String(err);
2409
+ return { error: `Community stats failed: ${msg}` };
2410
+ }
2588
2411
  }
2589
- catch (err) {
2590
- const msg = err instanceof Error ? err.message : String(err);
2591
- return { error: `Repeat mistakes failed: ${msg}` };
2412
+ case 'cell_community_share': {
2413
+ try {
2414
+ const { shareCommunityPattern, validatePrivacy } = require('../core/community-store');
2415
+ const rule = args.rule || '';
2416
+ const validation = validatePrivacy(rule);
2417
+ if (!validation.safe) {
2418
+ return { shared: false, errors: validation.errors, warnings: validation.warnings };
2419
+ }
2420
+ const result = shareCommunityPattern({
2421
+ category: args.category || 'unknown',
2422
+ rule,
2423
+ language: args.language,
2424
+ framework: args.framework,
2425
+ successRate: args.successRate,
2426
+ });
2427
+ return { ...result, warnings: [...validation.warnings, ...result.warnings] };
2428
+ }
2429
+ catch (err) {
2430
+ const msg = err instanceof Error ? err.message : String(err);
2431
+ return { error: `Community share failed: ${msg}` };
2432
+ }
2592
2433
  }
2593
- }
2594
- case 'cell_usage_ai_stats': {
2595
- try {
2596
- const { getAIInteractionStats } = require('../core/usage-intelligence-store');
2597
- return getAIInteractionStats(args.project || 'unknown');
2434
+ case 'cell_community_patterns': {
2435
+ try {
2436
+ const { getCommunityPatterns } = require('../core/community-store');
2437
+ const patterns = getCommunityPatterns({
2438
+ category: args.category,
2439
+ language: args.language,
2440
+ minVotes: args.minVotes,
2441
+ limit: args.limit || 20,
2442
+ });
2443
+ return { count: patterns.length, patterns };
2444
+ }
2445
+ catch (err) {
2446
+ const msg = err instanceof Error ? err.message : String(err);
2447
+ return { error: `Community patterns failed: ${msg}` };
2448
+ }
2598
2449
  }
2599
- catch (err) {
2600
- const msg = err instanceof Error ? err.message : String(err);
2601
- return { error: `AI stats failed: ${msg}` };
2450
+ case 'cell_community_vote': {
2451
+ try {
2452
+ const { voteCommunityPattern } = require('../core/community-store');
2453
+ return voteCommunityPattern(args.patternId || '', args.upvote !== false);
2454
+ }
2455
+ catch (err) {
2456
+ const msg = err instanceof Error ? err.message : String(err);
2457
+ return { error: `Community vote failed: ${msg}` };
2458
+ }
2602
2459
  }
2603
- }
2604
- case 'cell_usage_productivity': {
2605
- try {
2606
- const { logProductivitySignal, getProductivitySignals } = require('../core/usage-intelligence-store');
2607
- const project = args.project || 'unknown';
2608
- // If signalType + duration provided, log; otherwise just read
2609
- if (args.signalType && args.durationMinutes !== undefined) {
2610
- const result = logProductivitySignal({
2611
- project,
2612
- signalType: args.signalType,
2613
- durationMinutes: args.durationMinutes,
2614
- filesTouched: args.filesTouched || 0,
2615
- contextSwitches: args.contextSwitches || 0,
2460
+ case 'cell_community_insights': {
2461
+ try {
2462
+ const { getCommunityInsights } = require('../core/community-store');
2463
+ const insights = getCommunityInsights({
2464
+ severity: args.severity,
2465
+ category: args.category,
2466
+ limit: args.limit || 20,
2616
2467
  });
2617
- return { logged: true, ...result };
2468
+ return { count: insights.length, insights };
2469
+ }
2470
+ catch (err) {
2471
+ const msg = err instanceof Error ? err.message : String(err);
2472
+ return { error: `Community insights failed: ${msg}` };
2618
2473
  }
2619
- return getProductivitySignals(project, 30);
2620
- }
2621
- catch (err) {
2622
- const msg = err instanceof Error ? err.message : String(err);
2623
- return { error: `Productivity failed: ${msg}` };
2624
2474
  }
2625
- }
2626
- case 'cell_usage_skills': {
2627
- try {
2628
- const { getSkillProgression } = require('../core/usage-intelligence-store');
2629
- return getSkillProgression(args.project || 'unknown');
2475
+ case 'cell_community_benchmarks': {
2476
+ try {
2477
+ const { getBenchmarks } = require('../core/community-store');
2478
+ const benchmarks = getBenchmarks({
2479
+ category: args.category,
2480
+ limit: args.limit || 50,
2481
+ });
2482
+ return { count: benchmarks.length, benchmarks };
2483
+ }
2484
+ catch (err) {
2485
+ const msg = err instanceof Error ? err.message : String(err);
2486
+ return { error: `Community benchmarks failed: ${msg}` };
2487
+ }
2630
2488
  }
2631
- catch (err) {
2632
- const msg = err instanceof Error ? err.message : String(err);
2633
- return { error: `Skill progression failed: ${msg}` };
2489
+ case 'cell_community_trends': {
2490
+ try {
2491
+ const { getTechEvolution } = require('../core/community-store');
2492
+ return getTechEvolution();
2493
+ }
2494
+ catch (err) {
2495
+ const msg = err instanceof Error ? err.message : String(err);
2496
+ return { error: `Community trends failed: ${msg}` };
2497
+ }
2634
2498
  }
2635
- }
2636
- case 'cell_usage_burnout': {
2637
- try {
2638
- const { getBurnoutSignals } = require('../core/usage-intelligence-store');
2639
- return getBurnoutSignals(args.project || 'unknown');
2499
+ case 'cell_community_failures': {
2500
+ try {
2501
+ const { getFailurePatterns } = require('../core/community-store');
2502
+ const failures = getFailurePatterns({
2503
+ language: args.language,
2504
+ limit: args.limit || 10,
2505
+ });
2506
+ return { count: failures.length, failures };
2507
+ }
2508
+ catch (err) {
2509
+ const msg = err instanceof Error ? err.message : String(err);
2510
+ return { error: `Community failures failed: ${msg}` };
2511
+ }
2640
2512
  }
2641
- catch (err) {
2642
- const msg = err instanceof Error ? err.message : String(err);
2643
- return { error: `Burnout check failed: ${msg}` };
2513
+ case 'cell_community_validate': {
2514
+ try {
2515
+ const { validatePrivacy } = require('../core/community-store');
2516
+ return validatePrivacy(args.rule || '');
2517
+ }
2518
+ catch (err) {
2519
+ const msg = err instanceof Error ? err.message : String(err);
2520
+ return { error: `Community validate failed: ${msg}` };
2521
+ }
2644
2522
  }
2645
- }
2646
- case 'cell_usage_dashboard': {
2647
- try {
2648
- const { getUsageDashboard } = require('../core/usage-intelligence-store');
2649
- return getUsageDashboard(args.project || 'unknown');
2523
+ case 'cell_community_dashboard': {
2524
+ try {
2525
+ const { getCommunityStats, getTechEvolution, getCommunityInsights, getBenchmarks } = require('../core/community-store');
2526
+ const stats = getCommunityStats();
2527
+ const trends = getTechEvolution();
2528
+ const insights = getCommunityInsights({ severity: 'critical', limit: 5 });
2529
+ const benchmarks = getBenchmarks({ limit: 5 });
2530
+ return {
2531
+ stats,
2532
+ trends: trends.slice(0, 10),
2533
+ insights,
2534
+ benchmarks,
2535
+ generatedAt: new Date().toISOString(),
2536
+ };
2537
+ }
2538
+ catch (err) {
2539
+ const msg = err instanceof Error ? err.message : String(err);
2540
+ return { error: `Community dashboard failed: ${msg}` };
2541
+ }
2650
2542
  }
2651
- catch (err) {
2652
- const msg = err instanceof Error ? err.message : String(err);
2653
- return { error: `Usage dashboard failed: ${msg}` };
2543
+ case 'cell_usage_decision_log': {
2544
+ try {
2545
+ const { logDecisionOutcome } = require('../core/usage-intelligence-store');
2546
+ return logDecisionOutcome({
2547
+ project: args.project || 'unknown',
2548
+ technology: args.technology || '',
2549
+ reason: args.reason || '',
2550
+ outcome: args.outcome || '',
2551
+ wasRight: args.wasRight === true,
2552
+ confidence: args.confidence,
2553
+ });
2554
+ }
2555
+ catch (err) {
2556
+ const msg = err instanceof Error ? err.message : String(err);
2557
+ return { error: `Decision log failed: ${msg}` };
2558
+ }
2654
2559
  }
2655
- }
2656
- case 'cell_watch_start': {
2657
- try {
2658
- const { startWatcher } = require('../core/live-watcher');
2659
- return startWatcher(args.project || 'unknown', args.dir || process.cwd());
2560
+ case 'cell_usage_decision_patterns': {
2561
+ try {
2562
+ const { getDecisionPatterns } = require('../core/usage-intelligence-store');
2563
+ const patterns = getDecisionPatterns(args.project || 'unknown');
2564
+ return {
2565
+ count: patterns.length,
2566
+ patterns,
2567
+ message: patterns.length > 0
2568
+ ? `Analyzed ${patterns.length} technology decision patterns`
2569
+ : 'Need more decisions (>= 2 per tech) to detect patterns',
2570
+ };
2571
+ }
2572
+ catch (err) {
2573
+ const msg = err instanceof Error ? err.message : String(err);
2574
+ return { error: `Decision patterns failed: ${msg}` };
2575
+ }
2660
2576
  }
2661
- catch (err) {
2662
- const msg = err instanceof Error ? err.message : String(err);
2663
- return { error: `Watch start failed: ${msg}` };
2577
+ case 'cell_usage_repeat_mistakes': {
2578
+ try {
2579
+ const { detectRepeatMistakes } = require('../core/usage-intelligence-store');
2580
+ const mistakes = detectRepeatMistakes(args.project || 'unknown');
2581
+ return {
2582
+ count: mistakes.length,
2583
+ critical: mistakes.filter((m) => m.severity === 'critical').length,
2584
+ mistakes: mistakes.slice(0, 20),
2585
+ message: mistakes.length > 0
2586
+ ? `Found ${mistakes.length} repeated error patterns`
2587
+ : 'No repeated mistakes — clean track record',
2588
+ };
2589
+ }
2590
+ catch (err) {
2591
+ const msg = err instanceof Error ? err.message : String(err);
2592
+ return { error: `Repeat mistakes failed: ${msg}` };
2593
+ }
2664
2594
  }
2665
- }
2666
- case 'cell_watch_stop': {
2667
- try {
2668
- const { stopWatcher } = require('../core/live-watcher');
2669
- return stopWatcher(args.project || 'unknown');
2595
+ case 'cell_usage_ai_stats': {
2596
+ try {
2597
+ const { getAIInteractionStats } = require('../core/usage-intelligence-store');
2598
+ return getAIInteractionStats(args.project || 'unknown');
2599
+ }
2600
+ catch (err) {
2601
+ const msg = err instanceof Error ? err.message : String(err);
2602
+ return { error: `AI stats failed: ${msg}` };
2603
+ }
2670
2604
  }
2671
- catch (err) {
2672
- const msg = err instanceof Error ? err.message : String(err);
2673
- return { error: `Watch stop failed: ${msg}` };
2605
+ case 'cell_usage_productivity': {
2606
+ try {
2607
+ const { logProductivitySignal, getProductivitySignals } = require('../core/usage-intelligence-store');
2608
+ const project = args.project || 'unknown';
2609
+ // If signalType + duration provided, log; otherwise just read
2610
+ if (args.signalType && args.durationMinutes !== undefined) {
2611
+ const result = logProductivitySignal({
2612
+ project,
2613
+ signalType: args.signalType,
2614
+ durationMinutes: args.durationMinutes,
2615
+ filesTouched: args.filesTouched || 0,
2616
+ contextSwitches: args.contextSwitches || 0,
2617
+ });
2618
+ return { logged: true, ...result };
2619
+ }
2620
+ return getProductivitySignals(project, 30);
2621
+ }
2622
+ catch (err) {
2623
+ const msg = err instanceof Error ? err.message : String(err);
2624
+ return { error: `Productivity failed: ${msg}` };
2625
+ }
2674
2626
  }
2675
- }
2676
- case 'cell_watch_status': {
2677
- try {
2678
- const { getWatcherStatus, getActiveWatchers } = require('../core/live-watcher');
2679
- if (args.project) {
2680
- const status = getWatcherStatus(args.project);
2681
- if (!status)
2682
- return { project: args.project, active: false, message: 'No watcher found' };
2683
- const isLive = status.active;
2684
- return { ...status, message: isLive ? 'Live' : 'Stopped' };
2627
+ case 'cell_usage_skills': {
2628
+ try {
2629
+ const { getSkillProgression } = require('../core/usage-intelligence-store');
2630
+ return getSkillProgression(args.project || 'unknown');
2631
+ }
2632
+ catch (err) {
2633
+ const msg = err instanceof Error ? err.message : String(err);
2634
+ return { error: `Skill progression failed: ${msg}` };
2685
2635
  }
2686
- return { active: getActiveWatchers() };
2687
2636
  }
2688
- catch (err) {
2689
- const msg = err instanceof Error ? err.message : String(err);
2690
- return { error: `Watch status failed: ${msg}` };
2637
+ case 'cell_usage_burnout': {
2638
+ try {
2639
+ const { getBurnoutSignals } = require('../core/usage-intelligence-store');
2640
+ return getBurnoutSignals(args.project || 'unknown');
2641
+ }
2642
+ catch (err) {
2643
+ const msg = err instanceof Error ? err.message : String(err);
2644
+ return { error: `Burnout check failed: ${msg}` };
2645
+ }
2691
2646
  }
2692
- }
2693
- case 'cell_watch_events': {
2694
- try {
2695
- const { getLiveEvents } = require('../core/live-watcher');
2696
- return { events: getLiveEvents(args.project || 'unknown', args.limit || 50, args.eventType) };
2647
+ case 'cell_usage_dashboard': {
2648
+ try {
2649
+ const { getUsageDashboard } = require('../core/usage-intelligence-store');
2650
+ return getUsageDashboard(args.project || 'unknown');
2651
+ }
2652
+ catch (err) {
2653
+ const msg = err instanceof Error ? err.message : String(err);
2654
+ return { error: `Usage dashboard failed: ${msg}` };
2655
+ }
2697
2656
  }
2698
- catch (err) {
2699
- const msg = err instanceof Error ? err.message : String(err);
2700
- return { error: `Watch events failed: ${msg}` };
2657
+ case 'cell_watch_start': {
2658
+ try {
2659
+ const { startWatcher } = require('../core/live-watcher');
2660
+ return startWatcher(args.project || 'unknown', args.dir || process.cwd());
2661
+ }
2662
+ catch (err) {
2663
+ const msg = err instanceof Error ? err.message : String(err);
2664
+ return { error: `Watch start failed: ${msg}` };
2665
+ }
2701
2666
  }
2702
- }
2703
- case 'cell_watch_refresh': {
2704
- try {
2705
- const { performAutoRefresh } = require('../core/live-watcher');
2706
- return performAutoRefresh(args.project || 'unknown', args.force === true);
2667
+ case 'cell_watch_stop': {
2668
+ try {
2669
+ const { stopWatcher } = require('../core/live-watcher');
2670
+ return stopWatcher(args.project || 'unknown');
2671
+ }
2672
+ catch (err) {
2673
+ const msg = err instanceof Error ? err.message : String(err);
2674
+ return { error: `Watch stop failed: ${msg}` };
2675
+ }
2707
2676
  }
2708
- catch (err) {
2709
- const msg = err instanceof Error ? err.message : String(err);
2710
- return { error: `Auto-refresh failed: ${msg}` };
2677
+ case 'cell_watch_status': {
2678
+ try {
2679
+ const { getWatcherStatus, getActiveWatchers } = require('../core/live-watcher');
2680
+ if (args.project) {
2681
+ const status = getWatcherStatus(args.project);
2682
+ if (!status)
2683
+ return { project: args.project, active: false, message: 'No watcher found' };
2684
+ const isLive = status.active;
2685
+ return { ...status, message: isLive ? 'Live' : 'Stopped' };
2686
+ }
2687
+ return { active: getActiveWatchers() };
2688
+ }
2689
+ catch (err) {
2690
+ const msg = err instanceof Error ? err.message : String(err);
2691
+ return { error: `Watch status failed: ${msg}` };
2692
+ }
2711
2693
  }
2712
- }
2713
- case 'cell_watch_check': {
2714
- try {
2715
- const { checkIfNeedsRefresh } = require('../core/live-watcher');
2716
- return checkIfNeedsRefresh(args.project || 'unknown');
2694
+ case 'cell_watch_events': {
2695
+ try {
2696
+ const { getLiveEvents } = require('../core/live-watcher');
2697
+ return { events: getLiveEvents(args.project || 'unknown', args.limit || 50, args.eventType) };
2698
+ }
2699
+ catch (err) {
2700
+ const msg = err instanceof Error ? err.message : String(err);
2701
+ return { error: `Watch events failed: ${msg}` };
2702
+ }
2717
2703
  }
2718
- catch (err) {
2719
- const msg = err instanceof Error ? err.message : String(err);
2720
- return { error: `Refresh check failed: ${msg}` };
2704
+ case 'cell_watch_refresh': {
2705
+ try {
2706
+ const { performAutoRefresh } = require('../core/live-watcher');
2707
+ return performAutoRefresh(args.project || 'unknown', args.force === true);
2708
+ }
2709
+ catch (err) {
2710
+ const msg = err instanceof Error ? err.message : String(err);
2711
+ return { error: `Auto-refresh failed: ${msg}` };
2712
+ }
2721
2713
  }
2722
- }
2723
- case 'cell_blindspots_scan': {
2724
- try {
2725
- const { scanDirectoryForBlindSpots } = require('../core/enhanced-blind-spots');
2726
- const dir = args.dir || process.cwd();
2727
- const max = args.maxFiles || 200;
2728
- const spots = scanDirectoryForBlindSpots(dir, max);
2729
- return { directory: dir, scanned: max, count: spots.length, blindSpots: spots };
2714
+ case 'cell_watch_check': {
2715
+ try {
2716
+ const { checkIfNeedsRefresh } = require('../core/live-watcher');
2717
+ return checkIfNeedsRefresh(args.project || 'unknown');
2718
+ }
2719
+ catch (err) {
2720
+ const msg = err instanceof Error ? err.message : String(err);
2721
+ return { error: `Refresh check failed: ${msg}` };
2722
+ }
2730
2723
  }
2731
- catch (err) {
2732
- const msg = err instanceof Error ? err.message : String(err);
2733
- return { error: `Blind spot scan failed: ${msg}` };
2724
+ case 'cell_blindspots_scan': {
2725
+ try {
2726
+ const { scanDirectoryForBlindSpots } = require('../core/enhanced-blind-spots');
2727
+ const dir = args.dir || process.cwd();
2728
+ const max = args.maxFiles || 200;
2729
+ const spots = scanDirectoryForBlindSpots(dir, max);
2730
+ return { directory: dir, scanned: max, count: spots.length, blindSpots: spots };
2731
+ }
2732
+ catch (err) {
2733
+ const msg = err instanceof Error ? err.message : String(err);
2734
+ return { error: `Blind spot scan failed: ${msg}` };
2735
+ }
2734
2736
  }
2735
- }
2736
- case 'cell_blindspots_report': {
2737
- try {
2738
- const { scanDirectoryForBlindSpots, formatBlindSpotReport, summarizeBlindSpots } = require('../core/enhanced-blind-spots');
2739
- const dir = args.dir || process.cwd();
2740
- const max = args.maxFiles || 200;
2741
- const spots = scanDirectoryForBlindSpots(dir, max);
2742
- return {
2743
- directory: dir,
2744
- summary: summarizeBlindSpots(spots),
2745
- report: formatBlindSpotReport(spots),
2746
- blindSpots: spots,
2747
- };
2737
+ case 'cell_blindspots_report': {
2738
+ try {
2739
+ const { scanDirectoryForBlindSpots, formatBlindSpotReport, summarizeBlindSpots } = require('../core/enhanced-blind-spots');
2740
+ const dir = args.dir || process.cwd();
2741
+ const max = args.maxFiles || 200;
2742
+ const spots = scanDirectoryForBlindSpots(dir, max);
2743
+ return {
2744
+ directory: dir,
2745
+ summary: summarizeBlindSpots(spots),
2746
+ report: formatBlindSpotReport(spots),
2747
+ blindSpots: spots,
2748
+ };
2749
+ }
2750
+ catch (err) {
2751
+ const msg = err instanceof Error ? err.message : String(err);
2752
+ return { error: `Blind spot report failed: ${msg}` };
2753
+ }
2748
2754
  }
2749
- catch (err) {
2750
- const msg = err instanceof Error ? err.message : String(err);
2751
- return { error: `Blind spot report failed: ${msg}` };
2755
+ case 'cell_blindspots_summary': {
2756
+ try {
2757
+ const { getCategoryCounts } = require('../core/enhanced-blind-spots');
2758
+ const dir = args.dir || process.cwd();
2759
+ return { directory: dir, byCategory: getCategoryCounts(dir) };
2760
+ }
2761
+ catch (err) {
2762
+ const msg = err instanceof Error ? err.message : String(err);
2763
+ return { error: `Blind spot summary failed: ${msg}` };
2764
+ }
2752
2765
  }
2753
- }
2754
- case 'cell_blindspots_summary': {
2755
- try {
2756
- const { getCategoryCounts } = require('../core/enhanced-blind-spots');
2757
- const dir = args.dir || process.cwd();
2758
- return { directory: dir, byCategory: getCategoryCounts(dir) };
2766
+ case 'cell_predict': {
2767
+ const { generatePredictions } = require('../predictive-engine');
2768
+ return generatePredictions(args.project);
2769
+ }
2770
+ case 'cell_model_track': {
2771
+ const { recordModelInteraction } = require('../cross-model-engine');
2772
+ recordModelInteraction({
2773
+ modelName: args.modelName,
2774
+ taskType: args.taskType,
2775
+ accepted: args.accepted,
2776
+ responseTimeMs: args.responseTimeMs,
2777
+ project: args.project,
2778
+ suggestion: args.suggestion,
2779
+ });
2780
+ return { recorded: true };
2759
2781
  }
2760
- catch (err) {
2761
- const msg = err instanceof Error ? err.message : String(err);
2762
- return { error: `Blind spot summary failed: ${msg}` };
2782
+ case 'cell_model_recommend': {
2783
+ const { getModelRecommendations } = require('../cross-model-engine');
2784
+ return { recommendations: getModelRecommendations() };
2763
2785
  }
2786
+ default:
2787
+ return { error: `unknown tool: ${name}` };
2764
2788
  }
2765
- case 'cell_predict': {
2766
- const { generatePredictions } = require('../predictive-engine');
2767
- return generatePredictions(args.project);
2768
- }
2769
- case 'cell_model_track': {
2770
- const { recordModelInteraction } = require('../cross-model-engine');
2771
- recordModelInteraction({
2772
- modelName: args.modelName,
2773
- taskType: args.taskType,
2774
- accepted: args.accepted,
2775
- responseTimeMs: args.responseTimeMs,
2776
- project: args.project,
2777
- suggestion: args.suggestion,
2778
- });
2779
- return { recorded: true };
2780
- }
2781
- case 'cell_model_recommend': {
2782
- const { getModelRecommendations } = require('../cross-model-engine');
2783
- return { recommendations: getModelRecommendations() };
2784
- }
2785
- default:
2786
- return { error: `unknown tool: ${name}` };
2789
+ }
2790
+ catch (err) {
2791
+ const msg = err instanceof Error ? err.message : String(err);
2792
+ const stack = err instanceof Error ? err.stack : String(err);
2793
+ console.error(`[mcp] tool ${name} threw:`, msg, '\n', stack);
2794
+ return { error: `Tool ${name} failed: ${msg}` };
2787
2795
  }
2788
2796
  }
2789
2797
  app.post('/mcp', async (req, res) => {
2790
- // ─── Security: rate limit + input validation ─────────────────────────
2791
- const { checkRateLimit, getClientId, validateToolArgs, securityHeaders } = require('../core/security');
2792
- for (const [k, v] of Object.entries(securityHeaders()))
2793
- res.setHeader(k, v);
2794
- const clientId = getClientId(req);
2795
- const rl = checkRateLimit(clientId);
2796
- res.setHeader('X-RateLimit-Remaining', String(rl.remaining));
2797
- if (!rl.allowed) {
2798
- res.status(429).json({ jsonrpc: '2.0', id: null, error: { code: -32000, message: `Rate limit exceeded. Retry in ${Math.ceil(rl.resetIn / 1000)}s` } });
2799
- return;
2800
- }
2801
- const rpc = req.body;
2802
- const { method, params, id } = rpc;
2798
+ // Wrap entire handler in try/catch so uncaught errors don't 500 silently
2803
2799
  try {
2804
- // Validate tool args before execution
2805
- if (method === 'tools/call') {
2806
- const validation = validateToolArgs(params?.name || '', params?.arguments);
2807
- if (!validation.valid) {
2808
- res.status(400).json({ jsonrpc: '2.0', id, error: { code: -32602, message: `Invalid arguments: ${validation.reason}` } });
2809
- return;
2810
- }
2800
+ // ─── Security: rate limit + input validation ─────────────────────────
2801
+ const { checkRateLimit, getClientId, validateToolArgs, securityHeaders } = require('../core/security');
2802
+ for (const [k, v] of Object.entries(securityHeaders()))
2803
+ res.setHeader(k, v);
2804
+ const clientId = getClientId(req);
2805
+ const rl = checkRateLimit(clientId);
2806
+ res.setHeader('X-RateLimit-Remaining', String(rl.remaining));
2807
+ if (!rl.allowed) {
2808
+ res.status(429).json({ jsonrpc: '2.0', id: null, error: { code: -32000, message: `Rate limit exceeded. Retry in ${Math.ceil(rl.resetIn / 1000)}s` } });
2809
+ return;
2811
2810
  }
2812
- let result;
2813
- switch (method) {
2814
- case 'initialize':
2815
- result = { protocolVersion: params?.protocolVersion || '2024-11-05', capabilities: { tools: { listChanged: false } }, serverInfo: { name: 'fivo-cell', version: '3.0.0' } };
2816
- break;
2817
- case 'notifications/initialized':
2818
- res.status(204).end();
2819
- return;
2820
- case 'ping':
2821
- result = {};
2822
- break;
2823
- case 'tools/list':
2824
- result = { tools: MCP_TOOLS };
2825
- break;
2826
- case 'tools/call':
2827
- result = await handleMCPToolCall(params?.name || '', params?.arguments || {});
2828
- break;
2829
- default:
2830
- res.status(200).json({ jsonrpc: '2.0', id, error: { code: -32601, message: `Method not found: ${method}` } });
2831
- return;
2811
+ const rpc = req.body || {};
2812
+ const { method, params, id } = rpc;
2813
+ try {
2814
+ // Validate tool args before execution
2815
+ if (method === 'tools/call') {
2816
+ const validation = validateToolArgs(params?.name || '', params?.arguments);
2817
+ if (!validation.valid) {
2818
+ res.status(400).json({ jsonrpc: '2.0', id, error: { code: -32602, message: `Invalid arguments: ${validation.reason}` } });
2819
+ return;
2820
+ }
2821
+ }
2822
+ let result;
2823
+ switch (method) {
2824
+ case 'initialize':
2825
+ result = { protocolVersion: params?.protocolVersion || '2024-11-05', capabilities: { tools: { listChanged: false } }, serverInfo: { name: 'fivo-cell', version: '3.0.0' } };
2826
+ break;
2827
+ case 'notifications/initialized':
2828
+ res.status(204).end();
2829
+ return;
2830
+ case 'ping':
2831
+ result = {};
2832
+ break;
2833
+ case 'tools/list':
2834
+ result = { tools: MCP_TOOLS };
2835
+ break;
2836
+ case 'tools/call':
2837
+ result = await handleMCPToolCall(params?.name || '', params?.arguments || {});
2838
+ break;
2839
+ default:
2840
+ res.status(200).json({ jsonrpc: '2.0', id, error: { code: -32601, message: `Method not found: ${method}` } });
2841
+ return;
2842
+ }
2843
+ res.status(200).json({ jsonrpc: '2.0', id, result });
2844
+ }
2845
+ catch (err) {
2846
+ const message = err instanceof Error ? err.message : String(err);
2847
+ const stack = err instanceof Error ? err.stack : String(err);
2848
+ console.error('[mcp] handler error:', message, '\n', stack);
2849
+ try {
2850
+ res.status(200).json({ jsonrpc: '2.0', id, error: { code: -1, message } });
2851
+ }
2852
+ catch {
2853
+ try {
2854
+ res.status(500).json({ error: 'internal server error' });
2855
+ }
2856
+ catch { /* noop */ }
2857
+ }
2832
2858
  }
2833
- res.status(200).json({ jsonrpc: '2.0', id, result });
2834
2859
  }
2835
2860
  catch (err) {
2836
2861
  const message = err instanceof Error ? err.message : String(err);
2837
- res.status(200).json({ jsonrpc: '2.0', id, error: { code: -1, message } });
2862
+ const stack = err instanceof Error ? err.stack : String(err);
2863
+ process.stderr.write(`[mcp] OUTER handler error: ${message}\n${stack}\n`);
2864
+ try {
2865
+ res.status(500).json({ error: 'internal server error' });
2866
+ }
2867
+ catch { /* noop */ }
2838
2868
  }
2839
2869
  });
2840
2870
  app.use((_req, res) => { res.status(404).json({ error: 'not found' }); });
2841
2871
  app.use((err, _req, res, _next) => {
2842
- console.error('Daemon error:', err.message);
2843
- res.status(500).json({ error: 'internal server error' });
2872
+ console.error('Daemon error:', err.message, '\n', err.stack);
2873
+ try {
2874
+ res.status(500).json({ error: 'internal server error' });
2875
+ }
2876
+ catch { /* noop */ }
2844
2877
  });
2845
2878
  // ─── Self-Healing ──────────────────────────────────────────────────────
2846
2879
  process.on('uncaughtException', (err) => {