Reference implementation for the Phoenix Architecture. Work in progress. aicoding.leaflet.pub/
ai coding crazy
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: phoenix ingest --verbose shows line-level text diff

Shows exactly which lines were added/removed/changed within each
modified clause. Green + for new lines, red - for removed lines.
Without --verbose, just shows the clause section path.

+33 -2
+33 -2
src/cli.ts
··· 741 741 function cmdIngest(args: string[]): void { 742 742 const { projectRoot, phoenixDir } = requirePhoenixRoot(); 743 743 const specStore = new SpecStore(phoenixDir); 744 + const verbose = args.includes('-v') || args.includes('--verbose'); 745 + const filteredArgs = args.filter(a => a !== '-v' && a !== '--verbose'); 744 746 745 747 let files: string[]; 746 - if (args.length === 0) { 748 + if (filteredArgs.length === 0) { 747 749 files = findSpecFiles(projectRoot); 748 750 if (files.length === 0) { 749 751 console.log(yellow('⚠ No spec files found. Provide a path or add files to spec/.')); ··· 790 792 for (const d of diffs) { 791 793 if (d.diff_type === DiffType.UNCHANGED) continue; 792 794 const pathLabel = d.section_path_after?.join(' > ') || d.section_path_before?.join(' > ') || ''; 793 - const preview = (d.clause_after?.normalized_text || d.clause_before?.normalized_text || '').slice(0, 80); 794 795 const icon = d.diff_type === DiffType.ADDED ? green('+') : d.diff_type === DiffType.REMOVED ? red('-') : yellow('~'); 795 796 console.log(` ${icon} ${pathLabel}`); 797 + 798 + if (verbose && d.diff_type === DiffType.MODIFIED && d.clause_before && d.clause_after) { 799 + // Show line-level diff of the raw text 800 + const beforeLines = d.clause_before.raw_text.split('\n'); 801 + const afterLines = d.clause_after.raw_text.split('\n'); 802 + const beforeSet = new Set(beforeLines.map(l => l.trim())); 803 + const afterSet = new Set(afterLines.map(l => l.trim())); 804 + for (const line of afterLines) { 805 + if (!beforeSet.has(line.trim()) && line.trim()) { 806 + console.log(` ${green('+ ' + line.trim())}`); 807 + } 808 + } 809 + for (const line of beforeLines) { 810 + if (!afterSet.has(line.trim()) && line.trim()) { 811 + console.log(` ${red('- ' + line.trim())}`); 812 + } 813 + } 814 + } else if (verbose && d.diff_type === DiffType.ADDED && d.clause_after) { 815 + const lines = d.clause_after.raw_text.split('\n').filter(l => l.trim()); 816 + for (const line of lines.slice(0, 5)) { 817 + console.log(` ${green('+ ' + line.trim())}`); 818 + } 819 + if (lines.length > 5) console.log(` ${dim(`... and ${lines.length - 5} more lines`)}`); 820 + } else if (verbose && d.diff_type === DiffType.REMOVED && d.clause_before) { 821 + const lines = d.clause_before.raw_text.split('\n').filter(l => l.trim()); 822 + for (const line of lines.slice(0, 5)) { 823 + console.log(` ${red('- ' + line.trim())}`); 824 + } 825 + if (lines.length > 5) console.log(` ${dim(`... and ${lines.length - 5} more lines`)}`); 826 + } 796 827 } 797 828 } else { 798 829 console.log(` ${green('✔')} ${docId} → ${result.clauses.length} clauses ${dim('(no changes)')}`);