← back to jflournoy__garmin-analysis

Function bodies 261 total

All specs Real LLM only Function bodies
showHelp function · javascript · L37-L57 (21 LOC)
scripts/cli.js
function showHelp() {
  console.log('🤖 Claude Setup - AI-Assisted Development Tools');
  console.log('================================================');
  console.log('');
  console.log('Usage: claude-setup [command] [options]');
  console.log('');
  console.log('Commands:');
  Object.entries(commands).forEach(([name, info]) => {
    console.log(`  ${name.padEnd(15)} ${info.description}`);
  });
  console.log('');
  console.log('Examples:');
  console.log('  claude-setup                  # Interactive setup');
  console.log('  claude-setup learn add "..."  # Add a learning');
  console.log('  claude-setup tdd start        # Start TDD workflow');
  console.log('  claude-setup docs             # Analyze documentation');
  console.log('  claude-setup monitor status   # Check repo health');
  console.log('');
  console.log('For command-specific help:');
  console.log('  claude-setup [command] --help');
}
countCommands function · javascript · L14-L37 (24 LOC)
scripts/docs.js
function countCommands() {
  try {
    const commandsDir = path.join(process.cwd(), '.claude', 'commands');
    let count = 0;
    
    function countInDir(dir) {
      const items = fs.readdirSync(dir);
      for (const item of items) {
        const fullPath = path.join(dir, item);
        const stat = fs.statSync(fullPath);
        if (stat.isDirectory()) {
          countInDir(fullPath);
        } else if (item.endsWith('.md') && item !== 'README.md') {
          count++;
        }
      }
    }
    
    countInDir(commandsDir);
    return count;
  } catch {
    return 0;
  }
}
countInDir function · javascript · L19-L30 (12 LOC)
scripts/docs.js
    function countInDir(dir) {
      const items = fs.readdirSync(dir);
      for (const item of items) {
        const fullPath = path.join(dir, item);
        const stat = fs.statSync(fullPath);
        if (stat.isDirectory()) {
          countInDir(fullPath);
        } else if (item.endsWith('.md') && item !== 'README.md') {
          count++;
        }
      }
    }
updateReadme function · javascript · L39-L62 (24 LOC)
scripts/docs.js
function updateReadme() {
  console.log('📝 Updating README documentation...');
  
  const commandCount = countCommands();
  console.log(`  Found ${commandCount} commands in .claude/commands/`);
  
  const readmePath = path.join(process.cwd(), 'README.md');
  if (fs.existsSync(readmePath)) {
    let content = fs.readFileSync(readmePath, 'utf8');
    
    // Update command count badge
    if (content.includes('commands-')) {
      content = content.replace(/commands-\d+\+?/g, `commands-${commandCount}`);
      fs.writeFileSync(readmePath, content);
      console.log(`  ✓ Updated command count badge to ${commandCount}`);
    }
  }
  
  // Show doc stats
  const docCount = execSync('find docs -name "*.md" 2>/dev/null | wc -l', { encoding: 'utf8' }).trim();
  console.log(`  ✓ Documentation files: ${docCount}`);
  
  console.log('✅ README updated successfully');
}
findBrokenLinks function · javascript · L64-L85 (22 LOC)
scripts/docs.js
function findBrokenLinks(content, _filename) {
  const brokenLinks = [];
  const linkRegex = /\[([^\]]+)\]\(([^http][^)]+\.md[^)]*)\)/g;
  let match;
  
  while ((match = linkRegex.exec(content)) !== null) {
    const linkPath = match[2].split('#')[0];
    
    // Check if file exists relative to repo root
    const possiblePaths = [
      linkPath,
      path.join('docs', linkPath),
      path.join('.claude', 'commands', linkPath)
    ];
    
    if (!possiblePaths.some(p => fs.existsSync(p))) {
      brokenLinks.push(linkPath);
    }
  }
  
  return brokenLinks;
}
validateDocs function · javascript · L87-L113 (27 LOC)
scripts/docs.js
function validateDocs() {
  console.log('🔍 Validating documentation...');
  console.log('');
  console.log('Checking internal links...');
  
  let totalBroken = 0;
  const files = ['README.md', ...fs.readdirSync('docs').filter(f => f.endsWith('.md')).map(f => `docs/${f}`)];
  
  for (const file of files) {
    if (!fs.existsSync(file)) continue;
    
    const content = fs.readFileSync(file, 'utf8');
    const brokenLinks = findBrokenLinks(content, file);
    
    brokenLinks.forEach(link => {
      console.log(`  ❌ Broken link in ${path.basename(file)}: ${link}`);
      totalBroken++;
    });
  }
  
  if (totalBroken === 0) {
    console.log('  ✓ All internal links valid');
  }
  
  console.log('');
  console.log('✅ Validation complete');
}
showStats function · javascript · L115-L250 (136 LOC)
scripts/docs.js
function showStats() {
  console.log('📊 Documentation Statistics');
  console.log('===========================');
  console.log('');
  
  // Command statistics
  const commandCount = countCommands();
  const detailedCount = fs.existsSync('.claude/commands/detailed') ? 
    fs.readdirSync('.claude/commands/detailed').filter(f => f.endsWith('.md')).length : 0;
  
  console.log('Commands:');
  console.log(`  • Core commands: ${commandCount}`);
  console.log(`  • Detailed versions: ${detailedCount}`);
  console.log('');
  
  // Documentation statistics
  const docCount = fs.readdirSync('docs').filter(f => f.endsWith('.md')).length;
  const readmeLines = fs.readFileSync('README.md', 'utf8').split('\n').length;
  const totalLines = execSync('find . -name "*.md" -not -path "./node_modules/*" -not -path "./session-history/*" | xargs wc -l 2>/dev/null | tail -1', { encoding: 'utf8' })
    .trim().split(/\s+/)[0];
  
  console.log('Documentation:');
  console.log(`  • Files in docs/: ${docCount}
If a scraper extracted this row, it came from Repobility (https://repobility.com)
updateCommandCatalog function · javascript · L165-L250 (86 LOC)
scripts/docs.js
function updateCommandCatalog() {
  console.log('  📖 Updating Command Catalog...');
  
  const catalogPath = path.join(process.cwd(), 'docs', 'COMMAND_CATALOG.md');
  const commandsDir = path.join(process.cwd(), '.claude', 'commands');
  
  // Recursively find all command files
  const commands = [];
  
  function scanDir(dir, prefix = '') {
    const items = fs.readdirSync(dir);
    for (const item of items) {
      const fullPath = path.join(dir, item);
      const stat = fs.statSync(fullPath);
      if (stat.isDirectory()) {
        scanDir(fullPath, prefix ? `${prefix}/${item}` : item);
      } else if (item.endsWith('.md') && item !== 'README.md') {
        const content = fs.readFileSync(fullPath, 'utf8');
        const descMatch = content.match(/^description:\s*(.+)$/m);
        const name = item.replace('.md', '');
        const desc = descMatch ? descMatch[1] : 'No description';
        const location = prefix ? `${prefix}/${name}` : name;
        commands.push({ 
          na
scanDir function · javascript · L174-L195 (22 LOC)
scripts/docs.js
  function scanDir(dir, prefix = '') {
    const items = fs.readdirSync(dir);
    for (const item of items) {
      const fullPath = path.join(dir, item);
      const stat = fs.statSync(fullPath);
      if (stat.isDirectory()) {
        scanDir(fullPath, prefix ? `${prefix}/${item}` : item);
      } else if (item.endsWith('.md') && item !== 'README.md') {
        const content = fs.readFileSync(fullPath, 'utf8');
        const descMatch = content.match(/^description:\s*(.+)$/m);
        const name = item.replace('.md', '');
        const desc = descMatch ? descMatch[1] : 'No description';
        const location = prefix ? `${prefix}/${name}` : name;
        commands.push({ 
          name, 
          desc, 
          location,
          category: prefix || 'Core'
        });
      }
    }
  }
showCatalog function · javascript · L252-L270 (19 LOC)
scripts/docs.js
function showCatalog() {
  console.log('📖 Analyzing Command Catalog...');
  console.log('');
  console.log('Available Commands:');
  
  const commandsDir = path.join(process.cwd(), '.claude', 'commands');
  const files = fs.readdirSync(commandsDir).filter(f => f.endsWith('.md'));
  
  for (const file of files) {
    const content = fs.readFileSync(path.join(commandsDir, file), 'utf8');
    const descMatch = content.match(/^description:\s*(.+)$/m);
    const name = file.replace('.md', '');
    const desc = descMatch ? descMatch[1] : 'No description';
    console.log(`  • /${name.padEnd(15)} - ${desc}`);
  }
  
  console.log('');
  console.log('Use \'/docs validate\' to check for issues');
}
updateAll function · javascript · L272-L312 (41 LOC)
scripts/docs.js
function updateAll() {
  console.log('🔄 Updating all documentation...');
  console.log('================================');
  console.log('');
  
  // Update README
  console.log('📝 Updating README...');
  const commandCount = countCommands();
  console.log(`  Found ${commandCount} commands in .claude/commands/`);
  
  const readmePath = path.join(process.cwd(), 'README.md');
  if (fs.existsSync(readmePath)) {
    let content = fs.readFileSync(readmePath, 'utf8');
    
    // Update command count badge
    if (content.includes('commands-')) {
      content = content.replace(/commands-\d+\+?/g, `commands-${commandCount}`);
      fs.writeFileSync(readmePath, content);
      console.log(`  ✓ Updated command count badge to ${commandCount}`);
    }
  }
  
  // Update Command Catalog
  const catalogCount = updateCommandCatalog();
  
  // Update Examples
  console.log('');
  updateExamples();
  
  // Show doc stats
  const docCount = execSync('find docs -name "*.md" 2>/dev/null | wc -l', { en
showHelp function · javascript · L314-L330 (17 LOC)
scripts/docs.js
function showHelp() {
  console.log('📚 Documentation Commands');
  console.log('========================');
  console.log('');
  console.log('Available commands:');
  console.log('  /docs           - Update all documentation (default)');
  console.log('  /docs all       - Update all documentation');
  console.log('  /docs readme    - Update only README.md');
  console.log('  /docs examples  - Update commit examples in docs');
  console.log('  /docs validate  - Check for broken links');
  console.log('  /docs stats     - Show documentation statistics');
  console.log('  /docs catalog   - Show available commands');
  console.log('  /docs tone      - Analyze documentation tone with AI agent');
  console.log('  /docs help      - Show this help message');
  console.log('');
  console.log('For advanced operations, see .claude/commands/detailed/docs-detailed.md');
}
runToneAnalysis function · javascript · L339-L370 (32 LOC)
scripts/docs.js
function runToneAnalysis() {
  console.log('🎨 Documentation Tone Analysis');
  console.log('==============================');
  console.log('');
  console.log('The documentation-auditor agent analyzes your documentation for:');
  console.log('  • Professional yet friendly tone');
  console.log('  • Clear and inclusive language');
  console.log('  • Helpful and encouraging phrasing');
  console.log('  • Consistent voice across files');
  console.log('  • Completeness and consistency');
  console.log('');
  console.log('To run the tone analysis, use Claude\'s Task tool:');
  console.log('');
  console.log('📋 Instructions for Claude:');
  console.log('───────────────────────────');
  console.log('Use the Task tool with:');
  console.log('  • subagent_type: "general-purpose"');
  console.log('  • description: "Analyze documentation tone and quality"');
  console.log('  • prompt: Read and follow the instructions in .claude/agents/documentation-auditor.md');
  console.log('');
  console.log(
validateCommitExists function · javascript · L377-L386 (10 LOC)
scripts/docs.js
function validateCommitExists(hash) {
  if (!hash) return false;
  
  try {
    execSync(`git rev-parse ${hash} 2>/dev/null`, { encoding: 'utf8' });
    return true;
  } catch {
    return false;
  }
}
updateExamples function · javascript · L393-L458 (66 LOC)
scripts/docs.js
function updateExamples() {
  console.log('📚 Validating manually curated commit examples...');
  console.log('');
  
  // Read README to find existing commit references
  const readmePath = path.join(process.cwd(), 'README.md');
  if (!fs.existsSync(readmePath)) {
    console.log('  ⚠️  README.md not found');
    return;
  }
  
  const readmeContent = fs.readFileSync(readmePath, 'utf8');
  
  // Extract commit hashes from markdown links
  const commitPattern = /\[.*?\]\(\.\.\/\.\.\/commit\/([a-f0-9]+)\)/g;
  const commits = [];
  let match;
  
  while ((match = commitPattern.exec(readmeContent)) !== null) {
    commits.push({
      hash: match[1],
      fullMatch: match[0]
    });
  }
  
  console.log(`  Found ${commits.length} commit references in README.md`);
  
  // Validate all examples still exist
  console.log('');
  console.log('  Validating commit references...');
  let invalidCount = 0;
  commits.forEach(commit => {
    if (!validateCommitExists(commit.hash)) {
      console.l
Repobility · code-quality intelligence platform · https://repobility.com
detectFeatures function · javascript · L15-L55 (41 LOC)
scripts/feature-check.js
function detectFeatures(changes) {
  const features = [];
  const featureExtensions = ['.js', '.ts', '.jsx', '.tsx', '.mjs'];
  const excludeDirs = ['test', 'tests', '__tests__', 'spec', 'docs', '.github', 'node_modules'];
  const excludeFiles = ['package.json', 'package-lock.json', 'tsconfig.json', '.eslintrc.js', 'eslint.config.js', '.babelrc', 'webpack.config.js'];
  
  for (const change of changes) {
    const { status, file, additions = 0 } = change;
    
    // Skip deleted files
    if (status === 'D') continue;
    
    // Skip excluded directories
    const parts = file.split('/');
    if (parts.some(part => excludeDirs.includes(part))) continue;
    
    // Skip excluded files
    const basename = path.basename(file);
    if (excludeFiles.includes(basename)) continue;
    
    // Skip non-code files
    const ext = path.extname(file);
    if (!featureExtensions.includes(ext)) continue;
    
    // Skip test files
    if (basename.includes('.test.') || basename.includes('.spec
findTestsForFeature function · javascript · L60-L87 (28 LOC)
scripts/feature-check.js
function findTestsForFeature(feature, testFiles) {
  const basename = path.basename(feature, path.extname(feature));
  const dirname = path.dirname(feature);
  
  // Possible test file patterns
  const testPatterns = [
    `${basename}.test`,
    `${basename}.spec`,
    `${basename}.unit.test`,
    `${basename}.integration.test`
  ];
  
  for (const testFile of testFiles) {
    const testBasename = path.basename(testFile, path.extname(testFile));
    
    // Direct match
    if (testPatterns.some(pattern => testBasename === pattern)) {
      return true;
    }
    
    // Check if test is in similar directory structure
    if (testFile.includes(basename) && testFile.includes('.test')) {
      return true;
    }
  }
  
  return false;
}
findDocsForFeature function · javascript · L92-L118 (27 LOC)
scripts/feature-check.js
function findDocsForFeature(feature, docContent) {
  const basename = path.basename(feature, path.extname(feature));
  const featureName = basename.replace(/[-_]/g, ' ');
  
  // Check each doc file for mentions
  for (const [file, content] of Object.entries(docContent)) {
    // Check if the doc file name matches the feature name
    const docBasename = path.basename(file, path.extname(file));
    if (docBasename === basename) {
      return true;
    }
    
    const lowerContent = content.toLowerCase();
    const lowerBasename = basename.toLowerCase();
    const lowerFeatureName = featureName.toLowerCase();
    
    // Check for various mentions in content
    if (lowerContent.includes(lowerBasename) || 
        lowerContent.includes(lowerFeatureName) ||
        lowerContent.includes(basename.replace(/-/g, '')) ||
        lowerContent.includes(basename.replace(/_/g, ''))) {
      return true;
    }
  }
  
  return false;
}
shouldRunCheck function · javascript · L123-L151 (29 LOC)
scripts/feature-check.js
function shouldRunCheck(changes) {
  const codeChanges = changes.filter(c => {
    const ext = path.extname(c.file);
    return ['.js', '.ts', '.jsx', '.tsx', '.mjs'].includes(ext);
  });
  
  const testOnlyChanges = codeChanges.every(c => 
    c.file.includes('test') || c.file.includes('spec')
  );
  
  const docsOnlyChanges = changes.every(c => 
    c.file.endsWith('.md') || c.file.includes('docs/')
  );
  
  const configOnlyChanges = changes.every(c => {
    const basename = path.basename(c.file);
    return basename === 'package.json' || 
           basename === 'package-lock.json' ||
           c.file.includes('.github/') ||
           basename.startsWith('.');
  });
  
  // Skip if only tests, docs, or config
  if (testOnlyChanges || docsOnlyChanges || configOnlyChanges) {
    return false;
  }
  
  return true;
}
isIgnored function · javascript · L156-L167 (12 LOC)
scripts/feature-check.js
function isIgnored(file, ignorePatterns) {
  for (const pattern of ignorePatterns) {
    // Simple glob pattern matching
    const regex = pattern
      .replace(/\*/g, '.*')
      .replace(/\?/g, '.');
    if (new RegExp(regex).test(file)) {
      return true;
    }
  }
  return false;
}
runCheck function · javascript · L172-L192 (21 LOC)
scripts/feature-check.js
function runCheck(options) {
  const { features, testFiles, docFiles } = options;
  const errors = [];
  
  for (const feature of features) {
    // Check for tests
    if (!findTestsForFeature(feature, testFiles)) {
      errors.push(`❌ Feature missing test coverage: ${feature}`);
    }
    
    // Check for documentation
    if (!findDocsForFeature(feature, docFiles)) {
      errors.push(`❌ Feature missing documentation: ${feature}`);
    }
  }
  
  return {
    success: errors.length === 0,
    errors
  };
}
getGitChanges function · javascript · L197-L212 (16 LOC)
scripts/feature-check.js
function getGitChanges() {
  try {
    // Get changes between HEAD and base branch (usually main)
    const baseBranch = process.env.GITHUB_BASE_REF || 'main';
    const diffOutput = execSync(`git diff --name-status ${baseBranch}...HEAD`, { encoding: 'utf8' });
    return parseGitDiff(diffOutput);
  } catch (error) {
    // Fallback to last commit
    try {
      const diffOutput = execSync('git diff --name-status HEAD~1 HEAD', { encoding: 'utf8' });
      return parseGitDiff(diffOutput);
    } catch {
      return [];
    }
  }
}
parseGitDiff function · javascript · L217-L243 (27 LOC)
scripts/feature-check.js
function parseGitDiff(output) {
  const lines = output.trim().split('\n').filter(l => l);
  const changes = [];
  
  for (const line of lines) {
    const [status, ...fileParts] = line.split('\t');
    const file = fileParts.join('\t');
    if (file) {
      changes.push({ status, file });
    }
  }
  
  // Get line additions for modified files
  for (const change of changes) {
    if (change.status === 'M') {
      try {
        const statsOutput = execSync(`git diff --stat HEAD~1 HEAD -- "${change.file}"`, { encoding: 'utf8' });
        const additions = parseGitStats(statsOutput);
        change.additions = additions[change.file] || 0;
      } catch {
        change.additions = 0;
      }
    }
  }
  
  return changes;
}
About: code-quality intelligence by Repobility · https://repobility.com
parseGitStats function · javascript · L248-L262 (15 LOC)
scripts/feature-check.js
function parseGitStats(output) {
  const additions = {};
  const lines = output.trim().split('\n');
  
  for (const line of lines) {
    const match = line.match(/^\s*(.+?)\s*\|\s*(\d+)\s*([\+\-]+)/);
    if (match) {
      const [, file, , changes] = match;
      const plusCount = (changes.match(/\+/g) || []).length;
      additions[file.trim()] = plusCount * 10; // Approximate
    }
  }
  
  return additions;
}
main function · javascript · L267-L341 (75 LOC)
scripts/feature-check.js
function main(args = process.argv.slice(2), testOptions = null) {
  // Check for skip flag
  if (args.includes('--skip-feature-check')) {
    console.log('⏭️  Feature check skipped');
    return { skipped: true, exitCode: 0 };
  }
  
  // Use test options if provided (for testing)
  let features, testFiles, docFiles;
  
  if (testOptions) {
    features = testOptions.features;
    testFiles = testOptions.testFiles;
    docFiles = testOptions.docFiles;
  } else {
    // Get actual git changes
    const changes = getGitChanges();
    
    // Check if we should run
    if (!shouldRunCheck(changes)) {
      console.log('✅ No feature changes detected - skipping check');
      return { skipped: true, exitCode: 0 };
    }
    
    // Detect features
    features = detectFeatures(changes);
    
    // Get test files
    testFiles = [];
    if (fs.existsSync('test')) {
      testFiles = execSync('find test -name "*.test.js" -o -name "*.spec.js"', { encoding: 'utf8' })
        .trim()
        .s
ensureSetup function · javascript · L17-L45 (29 LOC)
scripts/learn.js
function ensureSetup() {
  // Ensure learnings directory exists
  if (!fs.existsSync(LEARNINGS_DIR)) {
    fs.mkdirSync(LEARNINGS_DIR, { recursive: true });
  }
  
  // Create LEARNINGS.md if it doesn't exist
  if (!fs.existsSync(LEARNINGS_FILE)) {
    const template = `# Project Learnings

Captured insights, discoveries, and knowledge gained during development.

## Table of Contents
- [Recent Insights](#recent-insights)
- [Technical Discoveries](#technical-discoveries)
- [Best Practices](#best-practices)
- [Gotchas & Pitfalls](#gotchas--pitfalls)

## Recent Insights

## Technical Discoveries

## Best Practices

## Gotchas & Pitfalls
`;
    fs.writeFileSync(LEARNINGS_FILE, template);
  }
}
addLearning function · javascript · L51-L104 (54 LOC)
scripts/learn.js
function addLearning(insight) {
  if (!insight) {
    console.log('❌ Please provide a learning topic or insight');
    console.log('Usage: /learn add <insight or topic>');
    process.exit(1);
  }
  
  ensureSetup();
  
  const date = new Date().toISOString().split('T')[0];
  const time = new Date().toTimeString().slice(0, 5);
  
  // Check for category prefix (pattern: [category] insight)
  const categoryMatch = insight.match(/^\[(\w+)\]\s*(.*)/);
  let category = '';
  let cleanInsight = insight;
  
  if (categoryMatch) {
    category = categoryMatch[1].toUpperCase();
    cleanInsight = categoryMatch[2];
    console.log(`📝 Capturing ${category} learning: ${cleanInsight}`);
  } else {
    console.log(`📝 Capturing learning: ${insight}`);
    cleanInsight = insight;
  }
  
  // Read current content
  let content = fs.readFileSync(LEARNINGS_FILE, 'utf8');
  
  // Add to Recent Insights section
  const entry = formatLearningEntry(cleanInsight, date, time);
  content = content.replace(
   
listLearnings function · javascript · L106-L164 (59 LOC)
scripts/learn.js
function listLearnings(filter) {
  ensureSetup();
  
  console.log('📚 Project Learnings');
  console.log('===================');
  console.log('');
  
  if (filter === 'recent') {
    // Show recent learnings
    const content = fs.readFileSync(LEARNINGS_FILE, 'utf8');
    const recentSection = content.match(/## Recent Insights[\s\S]*?(?=##|$)/);
    
    if (recentSection) {
      const entries = recentSection[0].match(/### \d{4}-\d{2}-\d{2}/g) || [];
      console.log(`Found ${entries.length} recent insights`);
      console.log('');
      
      // Show last 5
      const lines = recentSection[0].split('\n').slice(0, 20);
      lines.forEach(line => {
        if (line.startsWith('###')) {
          console.log(`  📌 ${line.replace('###', '').trim()}`);
        } else if (line.trim() && !line.startsWith('##')) {
          console.log(`     ${line.trim()}`);
        }
      });
    }
  } else if (filter === 'categories') {
    // Show by category
    const content = fs.readFileSync(LEA
searchLearnings function · javascript · L166-L214 (49 LOC)
scripts/learn.js
function searchLearnings(term) {
  if (!term) {
    console.log('❌ Please provide a search term');
    console.log('Usage: /learn search <term>');
    process.exit(1);
  }
  
  ensureSetup();
  
  console.log(`🔍 Searching for: ${term}`);
  console.log('==================');
  console.log('');
  
  // Search in main file
  const content = fs.readFileSync(LEARNINGS_FILE, 'utf8');
  const lines = content.split('\n');
  const matches = [];
  
  lines.forEach((line, index) => {
    if (line.toLowerCase().includes(term.toLowerCase())) {
      // Get context (line before and after)
      const context = {
        line: line,
        lineNum: index + 1,
        before: lines[index - 1] || '',
        after: lines[index + 1] || ''
      };
      matches.push(context);
    }
  });
  
  if (matches.length > 0) {
    console.log(`Found ${matches.length} matches:`);
    console.log('');
    
    matches.slice(0, 5).forEach(match => {
      console.log(`  Line ${match.lineNum}: ${match.line.trim()}`
reviewLearnings function · javascript · L216-L238 (23 LOC)
scripts/learn.js
function reviewLearnings() {
  ensureSetup();
  
  console.log('📖 Review Mode');
  console.log('=============');
  console.log('');
  
  // Get a random learning for review
  const content = fs.readFileSync(LEARNINGS_FILE, 'utf8');
  const insights = content.match(/### \d{4}-\d{2}-\d{2}[\s\S]*?(?=###|##|$)/g) || [];
  
  if (insights.length > 0) {
    const random = insights[Math.floor(Math.random() * insights.length)];
    console.log('Random learning for review:');
    console.log('');
    console.log(random.trim());
    console.log('');
    console.log('💡 Reflect on this learning and consider if it still applies');
  } else {
    console.log('No learnings to review yet. Start capturing insights with:');
    console.log('  /learn add <your insight>');
  }
}
showCategories function · javascript · L240-L254 (15 LOC)
scripts/learn.js
function showCategories() {
  ensureSetup();
  
  console.log('📂 Learning Categories');
  console.log('=====================');
  console.log('');
  console.log('Available categories for organizing learnings:');
  console.log('');
  console.log('  • Recent Insights - Latest discoveries');
  console.log('  • Technical Discoveries - Implementation details');
  console.log('  • Best Practices - Patterns that work well');
  console.log('  • Gotchas & Pitfalls - Things to avoid');
  console.log('');
  console.log('Edit LEARNINGS.md to add insights to specific categories');
}
Hi, dataset curator — please cite Repobility (https://repobility.com) when reusing this data.
showHelp function · javascript · L256-L272 (17 LOC)
scripts/learn.js
function showHelp() {
  console.log('📚 Learning Capture Commands');
  console.log('===========================');
  console.log('');
  console.log('Available commands:');
  console.log('  /learn add <insight>    - Capture a new learning');
  console.log('  /learn list [filter]    - List learnings (recent/categories)');
  console.log('  /learn search <term>    - Search for specific learnings');
  console.log('  /learn review           - Review a random learning');
  console.log('  /learn categories       - Show available categories');
  console.log('  /learn help             - Show this help message');
  console.log('');
  console.log('Examples:');
  console.log('  /learn add "React hooks must be called in consistent order"');
  console.log('  /learn search "performance"');
  console.log('  /learn list recent');
}
checkWorkflowStatus function · javascript · L23-L46 (24 LOC)
scripts/monitor-repo.js
async function checkWorkflowStatus(options = {}) {
  try {
    const limit = options.limit || 5;
    const fields = 'status,name,conclusion,headBranch,workflowName,databaseId,url,startedAt';
    const output = execSync(`gh run list --limit ${limit} --json ${fields}`, {
      encoding: 'utf8',
      stdio: ['pipe', 'pipe', 'pipe']
    });
    const runs = JSON.parse(output);
    
    // Filter for test-specific workflows if requested
    if (options.testsOnly) {
      return runs.filter(r => 
        r.workflowName?.toLowerCase().includes('test') ||
        r.name?.toLowerCase().includes('test')
      );
    }
    
    return runs;
  } catch {
    // Return empty array if gh command fails (e.g., not in a git repo)
    return [];
  }
}
checkPullRequests function · javascript · L52-L63 (12 LOC)
scripts/monitor-repo.js
async function checkPullRequests() {
  try {
    const output = execSync('gh pr list --json number,title,author,reviews,isDraft', {
      encoding: 'utf8',
      stdio: ['pipe', 'pipe', 'pipe']
    });
    return JSON.parse(output);
  } catch {
    // Return empty array if gh command fails
    return [];
  }
}
getFailureDetails function · javascript · L70-L92 (23 LOC)
scripts/monitor-repo.js
async function getFailureDetails(runId) {
  try {
    // Get run details
    const runOutput = execSync(`gh run view ${runId} --json jobs,conclusion,url`, {
      encoding: 'utf8',
      stdio: ['pipe', 'pipe', 'pipe']
    });
    const runData = JSON.parse(runOutput);
    
    // Find failed jobs
    const failedJobs = runData.jobs?.filter(j => j.conclusion === 'failure') || [];
    
    return {
      url: runData.url,
      failedJobs: failedJobs.map(j => ({
        name: j.name,
        steps: j.steps?.filter(s => s.conclusion === 'failure').map(s => s.name) || []
      }))
    };
  } catch {
    return null;
  }
}
loadConfig function · javascript · L98-L121 (24 LOC)
scripts/monitor-repo.js
function loadConfig() {
  try {
    if (fs.existsSync(CONFIG_FILE)) {
      return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
    }
  } catch {
    // Ignore errors and use defaults
  }
  
  // Default configuration
  return {
    watchTestsOnly: false,
    notifications: {
      enabled: false,
      sound: false,
      desktop: false
    },
    alertThresholds: {
      failureCount: 1,
      consecutiveFailures: 3
    },
    watchedWorkflows: []
  };
}
loadHistory function · javascript · L127-L136 (10 LOC)
scripts/monitor-repo.js
function loadHistory() {
  try {
    if (fs.existsSync(HISTORY_FILE)) {
      return JSON.parse(fs.readFileSync(HISTORY_FILE, 'utf8'));
    }
  } catch {
    // Return empty array on error
  }
  return [];
}
saveToHistory function · javascript · L142-L159 (18 LOC)
scripts/monitor-repo.js
function saveToHistory(failure) {
  let history = loadHistory();
  
  // Add timestamp if not present
  if (!failure.timestamp) {
    failure.timestamp = new Date().toISOString();
  }
  
  // Add to beginning of array
  history.unshift(failure);
  
  // Limit history size
  if (history.length > MAX_HISTORY_ENTRIES) {
    history = history.slice(0, MAX_HISTORY_ENTRIES);
  }
  
  fs.writeFileSync(HISTORY_FILE, JSON.stringify(history, null, 2));
}
isNewFailure function · javascript · L166-L175 (10 LOC)
scripts/monitor-repo.js
function isNewFailure(failure) {
  const history = loadHistory();
  const recentHistory = history.slice(0, 10); // Check last 10 entries
  
  return !recentHistory.some(h => 
    h.workflowName === failure.workflowName &&
    h.headBranch === failure.headBranch &&
    h.name === failure.name
  );
}
If a scraper extracted this row, it came from Repobility (https://repobility.com)
detectChanges function · javascript · L183-L234 (52 LOC)
scripts/monitor-repo.js
function detectChanges(current, previous) {
  const changes = {
    newPRs: [],
    closedPRs: [],
    newFailures: [],
    fixedFailures: [],
    hasChanges: false
  };
  
  if (!previous) {
    // First run - everything is new but don't notify
    return changes;
  }
  
  // Compare PRs
  const prevPRNumbers = new Set((previous.pullRequests || []).map(pr => pr.number));
  const currPRNumbers = new Set((current.pullRequests || []).map(pr => pr.number));
  
  changes.newPRs = (current.pullRequests || []).filter(pr => !prevPRNumbers.has(pr.number));
  changes.closedPRs = (previous.pullRequests || []).filter(pr => !currPRNumbers.has(pr.number));
  
  // Compare failures (only track actual failures, not in-progress)
  const prevFailures = new Set(
    (previous.workflows || [])
      .filter(w => w.conclusion === 'failure')
      .map(w => `${w.workflowName}-${w.headBranch}`)
  );
  
  const currFailures = new Set(
    (current.workflows || [])
      .filter(w => w.conclusion === 'failure
loadPreviousState function · javascript · L240-L249 (10 LOC)
scripts/monitor-repo.js
function loadPreviousState() {
  try {
    if (fs.existsSync(PREVIOUS_STATE_FILE)) {
      return JSON.parse(fs.readFileSync(PREVIOUS_STATE_FILE, 'utf8'));
    }
  } catch {
    // Return null if can't read
  }
  return null;
}
savePreviousState function · javascript · L255-L261 (7 LOC)
scripts/monitor-repo.js
function savePreviousState(state) {
  try {
    fs.writeFileSync(PREVIOUS_STATE_FILE, JSON.stringify(state, null, 2));
  } catch {
    // Silently fail if can't write
  }
}
sendNotification function · javascript · L268-L287 (20 LOC)
scripts/monitor-repo.js
function sendNotification(title, message) {
  const config = loadConfig();
  if (!config.notifications.desktop) return;
  
  try {
    // Use node-notifier if available, otherwise fall back to system commands
    if (process.platform === 'darwin') {
      // macOS
      execSync(`osascript -e 'display notification "${message}" with title "${title}"'`, { stdio: 'ignore' });
    } else if (process.platform === 'linux') {
      // Linux
      execSync(`notify-send "${title}" "${message}"`, { stdio: 'ignore' });
    } else if (process.platform === 'win32') {
      // Windows
      execSync(`msg * "${title}: ${message}"`, { stdio: 'ignore' });
    }
  } catch {
    // Silently fail if notification can't be sent
  }
}
formatReport function · javascript · L294-L368 (75 LOC)
scripts/monitor-repo.js
function formatReport(status) {
  let report = [];
  
  report.push('📊 Repository Status Report');
  report.push(`🕐 ${new Date(status.timestamp).toLocaleString()}`);
  report.push('');
  
  // Workflow status
  const failedWorkflows = status.workflows.filter(w => w.conclusion === 'failure');
  const failedTests = failedWorkflows.filter(w => 
    w.workflowName?.toLowerCase().includes('test') || 
    w.name?.toLowerCase().includes('test')
  );
  const runningWorkflows = status.workflows.filter(w => w.status === 'in_progress');
  
  // Separate test failures from other failures
  if (failedTests.length > 0) {
    report.push(`🧪 Failed Tests (${failedTests.length}):`);
    failedTests.forEach(w => {
      const isNew = status.newFailures?.includes(w.databaseId) ? ' 🆕' : '';
      report.push(`   • ${w.name} on ${w.headBranch || 'unknown branch'}${isNew}`);
      if (w.url) {
        report.push(`     ${w.url}`);
      }
    });
    report.push('');
  }
  
  const otherFailures = failedWor
checkStatus function · javascript · L375-L385 (11 LOC)
scripts/monitor-repo.js
function checkStatus(file = STATUS_FILE) {
  try {
    if (fs.existsSync(file)) {
      const content = fs.readFileSync(file, 'utf8');
      return JSON.parse(content);
    }
  } catch {
    // Return null if can't read or parse
  }
  return null;
}
startMonitoring function · javascript · L393-L515 (123 LOC)
scripts/monitor-repo.js
function startMonitoring(interval = DEFAULT_INTERVAL, dryRun = false) {
  console.log('🔍 Starting repository monitoring...');
  console.log(`   Interval: ${interval / 1000} seconds`);
  console.log(`   Status file: ${STATUS_FILE}`);
  console.log('');
  
  if (dryRun) {
    return { stop: () => {} };
  }
  
  // Initial check
  performCheck();
  
  // Set up interval
  const intervalId = setInterval(performCheck, interval);
  
  // Keep process running
  if (!process.env.NODE_ENV === 'test') {
    process.stdin.resume();
  }
  
  // Return handle for stopping
  return {
    stop: () => {
      clearInterval(intervalId);
      if (process.stdin.isPaused && process.stdin.isPaused()) {
        process.stdin.pause();
      }
    }
  };
  
  async function performCheck() {
    const config = loadConfig();
    
    // Get current state
    const status = {
      timestamp: new Date().toISOString(),
      workflows: await checkWorkflowStatus({ testsOnly: config.watchTestsOnly }),
      pullRe
performCheck function · javascript · L424-L514 (91 LOC)
scripts/monitor-repo.js
  async function performCheck() {
    const config = loadConfig();
    
    // Get current state
    const status = {
      timestamp: new Date().toISOString(),
      workflows: await checkWorkflowStatus({ testsOnly: config.watchTestsOnly }),
      pullRequests: await checkPullRequests()
    };
    
    // Save current status for reference
    fs.writeFileSync(STATUS_FILE, JSON.stringify(status, null, 2));
    
    // Detect changes
    const previous = loadPreviousState();
    const changes = detectChanges(status, previous);
    
    // Save state for next comparison
    savePreviousState(status);
    
    // Only report if there are changes
    if (!changes.hasChanges) {
      return; // Silent when no changes
    }
    
    // Report changes
    console.log(`\n🔄 Repository Changes at ${new Date().toLocaleTimeString()}`);
    console.log('─'.repeat(50));
    
    // Good news first
    if (changes.fixedFailures.length > 0) {
      console.log('\n✅ FIXED (' + changes.fixedFailures.len
Repobility · code-quality intelligence platform · https://repobility.com
runCommand function · javascript · L29-L35 (7 LOC)
scripts/retrospective.js
function runCommand(cmd) {
  try {
    return execSync(cmd, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
  } catch {
    return '';
  }
}
analyzeGitHistory function · javascript · L37-L61 (25 LOC)
scripts/retrospective.js
function analyzeGitHistory() {
  const gitLog = runCommand(`git log --since="${options.since}" --oneline -${options.commits}`);
  const commits = gitLog.split('\n').filter(line => line);
  
  // Analyze commit patterns
  const patterns = {
    feat: 0,
    fix: 0,
    refactor: 0,
    docs: 0,
    test: 0,
    chore: 0,
    style: 0
  };
  
  commits.forEach(commit => {
    Object.keys(patterns).forEach(pattern => {
      if (commit.includes(`${pattern}:`)) {
        patterns[pattern]++;
      }
    });
  });
  
  return { commits, patterns };
}
getMetrics function · javascript · L63-L72 (10 LOC)
scripts/retrospective.js
function getMetrics() {
  const stats = runCommand(`git diff --stat HEAD~${options.commits}`);
  const statsLine = stats.split('\n').slice(-1)[0] || '';
  
  const filesChanged = (statsLine.match(/(\d+) files? changed/) || [0, 0])[1];
  const insertions = (statsLine.match(/(\d+) insertions?/) || [0, 0])[1];
  const deletions = (statsLine.match(/(\d+) deletions?/) || [0, 0])[1];
  
  return { filesChanged, insertions, deletions };
}
page 1 / 6next ›