Comprehensive task list derived from SPEC.md. Every feature, configuration option, error handling case, and edge case from the spec is mapped to at least one task.
- Install runtime dependencies — Add
diff(jsdiff)^7.0.0as a runtime dependency inpackage.json. | Status: not_done - Install dev dependencies — Add
typescript,vitest, andeslintas dev dependencies inpackage.json. Ensure versions are compatible with Node.js >=18. | Status: done - Configure ESLint — Create
.eslintrc(or equivalent) with TypeScript support. Configure rules consistent with monorepo conventions. | Status: done - Configure Vitest — Create
vitest.config.tsif needed, or ensure the existingvitest runscript works. Confirm test file discovery pattern matchessrc/__tests__/**/*.test.ts. | Status: done - Create directory structure — Create all directories specified in the file structure:
src/engine/,src/metrics/,src/formatters/,src/input/,src/utils/,src/__tests__/,src/__tests__/engine/,src/__tests__/metrics/,src/__tests__/formatters/,src/__tests__/input/,src/__tests__/fixtures/, andbin/. | Status: not_done - Create CLI binary entry point — Create
bin/ai-diff.jswith a#!/usr/bin/env nodeshebang that requires../dist/cli.js. Add"bin": { "ai-diff": "./bin/ai-diff.js" }topackage.json. | Status: not_done - Configure package.json exports — Ensure
"main","types", and"files"fields are correct. Add"bin"field. Verify"engines"is set to"node": ">=18". | Status: not_done - Add optional peer dependency — Add
model-price-registryas an optional peer dependency inpackage.json. | Status: not_done - Create test fixtures — Create sample fixture files in
src/__tests__/fixtures/:output-gpt4.txt,output-claude.txt,output-gemini.txt,structured-a.json,structured-b.json,comparison-input.json,cassette-v1.json,cassette-v2.json. Populate with realistic sample data. | Status: not_done
- Define LLMOutput interface — In
src/types.ts, define theLLMOutputinterface with fields:text(required string),model(optional string),tokens(optional{ input?: number; output?: number }),cost(optional number),latency(optional number),metadata(optionalRecord<string, unknown>). | Status: done - Define LLMFn type — In
src/types.ts, defineLLMFnas(prompt: string, model: string) => Promise<LLMOutput | string>. | Status: done - Define DiffMode type — In
src/types.ts, defineDiffModeas the union'unified' | 'side-by-side' | 'inline' | 'metrics' | 'json'. | Status: done - Define OutputFormat type — In
src/types.ts, defineOutputFormatas'terminal' | 'json' | 'markdown' | 'plain'. | Status: done - Define DiffOptions interface — In
src/types.ts, defineDiffOptionswith all fields:mode,contextLines,embedFn,pricing,showMetrics,metricsPosition,metrics,width,color,labels. Include JSDoc for each field with default values. | Status: done - Define CompareOptions interface — In
src/types.ts, defineCompareOptionsextendingDiffOptionswith:concurrency,timeout,signal(AbortSignal). | Status: done - Define DiffSegment interface — In
src/types.ts, defineDiffSegmentwithtext(string) andtype('added' | 'removed' | 'unchanged'). | Status: done - Define DiffHunk interface — In
src/types.ts, defineDiffHunkwithlineA(number),lineB(number),segments(DiffSegment[]). | Status: done - Define LengthStats interface — In
src/types.ts, defineLengthStatswithwords,sentences,characters(all numbers). | Status: done - Define DiffMetrics interface — In
src/types.ts, defineDiffMetricswith nestedtokens,cost,latency,similarity,length, andmodelobjects per the spec. | Status: done - Define JsonChange interface — In
src/types.ts, defineJsonChangewithpath(string),type('added' | 'removed' | 'changed'),before(optional unknown),after(optional unknown). | Status: done - Define DiffResult interface — In
src/types.ts, defineDiffResultwith:identical,hunks,jsonChanges,metrics,similarity,outputA,outputB,mode,durationMs,timestamp. | Status: done - Define MultiDiffResult interface — In
src/types.ts, defineMultiDiffResultwith:outputs,pairwise(array of{ indexA, indexB, result }),metricsTable,durationMs,timestamp. | Status: done - Define ComparisonResult interface — In
src/types.ts, defineComparisonResultextendingMultiDiffResultwith:prompt,models,calls(array of{ model, status, output?, error?, latencyMs }). | Status: done
- Implement ANSI color helpers — In
src/utils/ansi.ts, implement color functions:red(),green(),yellow(),cyan(),dim(),bold(),inverse(),strikethrough(),underline(),reset(). Each wraps text in the appropriate ANSI escape codes. | Status: done - Implement color detection — In
src/utils/ansi.ts, implementshouldUseColor()function that returnstrueif stdout is a TTY andNO_COLORenv var is not set. Support override via explicitcoloroption. | Status: done - Implement text tokenization — In
src/utils/text.ts, implementtokenizeWords(text: string): string[]that splits on whitespace, lowercases, and removes punctuation. Used by Jaccard similarity. | Status: done - Implement sentence splitting — In
src/utils/text.ts, implementcountSentences(text: string): numberthat counts sentences by detecting terminal punctuation (.,!,?) followed by whitespace or end of string. | Status: done - Implement word counting — In
src/utils/text.ts, implementcountWords(text: string): numberthat counts whitespace-separated tokens. | Status: done - Implement character counting — In
src/utils/text.ts, implementcountCharacters(text: string): numberthat returns total characters including whitespace. | Status: done - Implement table rendering — In
src/utils/table.ts, implementrenderTable(headers: string[], rows: string[][], options: { unicode: boolean; width?: number }): string. Render a formatted table using Unicode box-drawing characters (or ASCII fallback for non-TTY). Handle column alignment, minimum widths, and maximum table width. | Status: done - Implement terminal width detection — In
src/utils/ansi.tsor a separate utility, implementgetTerminalWidth(): numberusingprocess.stdout.columnswith fallback to 80. | Status: not_done
- Implement token counting — In
src/metrics/tokens.ts, implementestimateTokens(text: string): numberusingMath.ceil(text.length / 4)heuristic. ImplementgetTokenCounts(output: LLMOutput): { input?: number; output: number }that uses provided values or falls back to estimation for output tokens. | Status: done - Implement built-in pricing table — In
src/metrics/pricing.ts, create a static pricing table for common models: GPT-4o, GPT-4o-mini, GPT-3.5-turbo, Claude Opus, Claude Sonnet, Claude Haiku, Gemini Pro, Gemini Flash. Each entry hasinputandoutputper-token prices in USD. | Status: done - Implement model-price-registry integration — In
src/metrics/pricing.ts, implementgetModelPricing(model: string, overrides?: Record<string, { input: number; output: number }>): { input: number; output: number } | undefined. Trymodel-price-registryfirst (via dynamicrequire/importwith try/catch), fall back to built-in table, then to overrides. | Status: not_done - Implement cost estimation — In
src/metrics/cost.ts, implementestimateCost(output: LLMOutput, pricing?: Record<string, { input: number; output: number }>): number | undefined. Return provided cost, or compute from model + tokens + pricing, or return undefined. | Status: done - Implement length statistics — In
src/metrics/length.ts, implementcomputeLengthStats(text: string): LengthStatsreturning{ words, sentences, characters }. | Status: done - Implement metrics orchestrator — In
src/metrics/index.ts, implementcomputeDiffMetrics(outputA: LLMOutput, outputB: LLMOutput, similarity: { jaccard: number; semantic?: number }, options?: DiffOptions): DiffMetrics. Orchestrate token counting, cost estimation, latency comparison, similarity packaging, length stats, and model info into a singleDiffMetricsobject. | Status: done
- Implement text diff (line-level) — In
src/engine/text-diff.ts, implementcomputeLineDiff(textA: string, textB: string): DiffHunk[]usingjsdiff'sdiffLines. Convert jsdiff output toDiffHunk[]with correctlineA,lineB, andDiffSegmentarrays. | Status: done - Implement text diff (word-level within lines) — In
src/engine/text-diff.ts, implement word-level highlighting within changed line pairs. For each pair of removed+added lines, computejsdiff'sdiffWordsand annotate segments with word-level change markers. | Status: done - Implement context line handling — In
src/engine/text-diff.ts, implement context line filtering for unified mode. Given a full set of hunks and acontextLinesvalue (default 3), trim unchanged lines beyond the context window and produce proper hunk boundaries. | Status: done - Implement JSON structural diff — In
src/engine/json-diff.ts, implementcomputeJsonDiff(jsonA: unknown, jsonB: unknown): JsonChange[]. Recursively walk both objects: detect added, removed, and changed keys. Handle nested objects, arrays (by index), and mixed types. ReturnJsonChange[]with dot-notationpathstrings. | Status: done - Implement JSON parse-and-fallback — In
src/engine/json-diff.ts, implement logic to parse both outputs as JSON. If either fails to parse, return a fallback indicator so the caller can fall back to unified text diff with a warning. | Status: done - Implement Jaccard similarity — In
src/engine/similarity.ts, implementcomputeJaccardSimilarity(textA: string, textB: string): number. Tokenize both texts into word sets (lowercase, punctuation removed), compute|intersection| / |union|. Handle edge cases: both empty (return 1.0), one empty (return 0.0). | Status: done - Implement semantic similarity — In
src/engine/similarity.ts, implementcomputeSemanticSimilarity(textA: string, textB: string, embedFn: (text: string) => Promise<number[]>): Promise<number>. Compute embedding vectors for both texts, return cosine similarity:dot(a, b) / (norm(a) * norm(b)). | Status: done - Implement cosine similarity utility — In
src/engine/similarity.ts, implementcosineSimilarity(a: number[], b: number[]): numberfor computing the cosine similarity between two vectors. Handle zero-norm edge case. | Status: done
- Implement
diff()function — Insrc/diff.ts, implement the maindiff(outputA, outputB, options?)function. Normalize string inputs toLLMOutput. Compute text diff (or JSON diff if mode is'json'). Compute Jaccard similarity (and semantic ifembedFnprovided). Compute metrics. Build and returnDiffResultwithidentical,hunks,jsonChanges,metrics,similarity,outputA,outputB,mode,durationMs,timestamp. | Status: done - Implement string-to-LLMOutput normalization — In
src/diff.tsor a utility, implement logic to acceptstring | LLMOutputand normalize toLLMOutput. A plain string becomes{ text: string }. Fill in estimated fields (output tokens via heuristic). | Status: done - Implement
diffOutputs()function — Insrc/multi-diff.ts, implementdiffOutputs(outputs, options?). For N outputs, compute N*(N-1)/2 pairwise diffs. Build ametricsTableobject with one column per output. ReturnMultiDiffResult. | Status: done - Implement metrics table construction — In
src/multi-diff.ts, build themetricsTablefield ofMultiDiffResultwithlabels,outputTokens,inputTokens,costs,latencies,wordCounts,sentenceCounts,characterCountsarrays. | Status: done - Implement
compare()function — Insrc/compare.ts, implementcompare(prompt, models, llmFn, options?). CallllmFnfor each model in parallel usingPromise.allSettled. Wrap each call withperformance.now()timing. Handle failures (record error, continue with remaining). BuildLLMOutputfrom results. CalldiffOutputs()on successful outputs. ReturnComparisonResult. | Status: done - Implement concurrency control for compare() — In
src/compare.ts, implement a semaphore-based concurrency limiter whenoptions.concurrencyis set. Dispatch model calls in batches of the specified size. | Status: done - Implement timeout handling for compare() — In
src/compare.ts, implement per-model-call timeout usingAbortControllerorPromise.racewithsetTimeout. Default timeout: 30,000ms. | Status: done - Implement AbortSignal support for compare() — In
src/compare.ts, respectoptions.signalfor cancellation. If the signal is aborted, cancel pending model calls. | Status: not_done - Implement
formatDiff()function — Insrc/formatters/index.ts, implementformatDiff(result, format)that dispatches to the appropriate formatter (terminal, json, markdown, plain) based on theformatargument. AcceptDiffResult,MultiDiffResult, orComparisonResult. | Status: done
- Implement unified diff formatter — In
src/formatters/terminal.ts, render a unified diff with ANSI colors. Removed lines/words in red, added lines/words in green, unchanged context in default color. Prefix removed lines with-, added lines with+. Show configurable context lines around changes. | Status: done - Implement word-level highlighting in unified mode — In
src/formatters/terminal.ts, within changed lines, highlight specifically changed words using bold + inverse ANSI codes on top of the line-level color (red or green). | Status: done - Implement side-by-side formatter — In
src/formatters/terminal.ts, render two-column output. Detect terminal width, compute column width as(width - 3) / 2. Align paragraphs/lines between columns. Highlight changed words in each column. Wrap long lines. Show vertical separator between columns. | Status: done - Implement side-by-side fallback — In
src/formatters/terminal.ts, if terminal width is below 80 columns, fall back to unified mode and emit a warning message. | Status: not_done - Implement inline diff formatter — In
src/formatters/terminal.ts, render a single merged text with removed words in red with strikethrough and added words in green with underline. | Status: done - Implement metrics-only formatter — In
src/formatters/terminal.ts, render only the metrics comparison table when mode is'metrics'. No text diff output. | Status: done - Implement JSON diff terminal renderer — In
src/formatters/terminal.ts, render JSON structural changes with ANSI colors. Removed keys/values in red, added in green, changed values showing before (red) and after (green). | Status: done - Implement header rendering — In
src/formatters/terminal.ts, render the header: version string, "Comparing: X vs Y", "Mode: Z". Use cyan color for labels. | Status: not_done - Implement footer rendering — In
src/formatters/terminal.ts, render the footer: "Analyzed in Xms". | Status: not_done
- Implement metrics summary table — In
src/formatters/metrics-table.ts, render the metrics comparison table using Unicode box-drawing characters. Columns for each output (labeled by model name or "Output A"/"Output B"). Rows for: output tokens, input tokens, cost, latency, similarity, words, sentences, characters. Show delta and percentage change. | Status: done - Implement metrics table positioning — Support
metricsPositionoption ('top'or'bottom'). WhenshowMetricsis false, omit the table entirely. | Status: not_done - Implement selective metrics display — Support
metricsoption array to control which metric rows are shown (e.g., only['cost', 'latency']). | Status: not_done - Implement delta formatting — Format deltas with sign (e.g.,
+356 (+42%),-260ms,+$0.0018). Color positive cost/token deltas red (more expensive), negative green (cheaper). Color positive latency deltas red (slower), negative green (faster). | Status: done - Implement multi-output metrics table — For
MultiDiffResultandComparisonResult, render a table with one column per output (not just two). Handle N columns dynamically. | Status: not_done
- Implement JSON output formatter — In
src/formatters/json.ts, serialize theDiffResult,MultiDiffResult, orComparisonResultto a JSON string. Include all fields. UseJSON.stringifywith 2-space indentation. | Status: done
- Implement markdown output formatter — In
src/formatters/markdown.ts, render the diff as markdown suitable for PR comments. Use fenced code blocks for diff output, markdown tables for metrics, and headings for structure. | Status: not_done
- Implement plain text output formatter — In
src/formatters/plain.ts, render the same content as the terminal formatter but with all ANSI escape codes stripped. Use ASCII characters for table borders instead of Unicode box-drawing characters. | Status: done
- Implement file input reader — In
src/input/file.ts, implementreadFileInput(filePath: string): LLMOutput. Read file as UTF-8 text. If.jsonextension, attempt to parse asLLMOutputJSON object. If parse succeeds, use metadata. If parse fails, treat raw content as output text. Handle file-not-found and read errors. | Status: not_done - Implement stdin input reader — In
src/input/stdin.ts, implementreadStdinInput(delimiter: string): Promise<[string, string]>. Read all stdin, split by delimiter (default'---'). Delimiter must be on its own line with no leading/trailing whitespace. Validate exactly two parts are found. Return both output strings. | Status: not_done - Implement JSON input reader — In
src/input/json-input.ts, implementreadJsonInput(filePath: string): { a: LLMOutput; b: LLMOutput }. Read and parse a JSON file withaandbfields, each containingLLMOutputdata. Validate required fields. Handle parse errors. | Status: not_done - Implement llm-vcr cassette reader — In
src/input/cassette.ts, implementreadCassette(filePath: string): LLMOutput. Read anllm-vcrcassette JSON file, extract the response text and metadata (model, tokens, etc.). Handle missing fields gracefully. | Status: not_done
- Implement CLI argument parsing — In
src/cli.ts, usenode:util.parseArgsto parse all CLI flags defined in the spec: positional file args,--stdin,--delimiter,--json,--cassette,--prompt,--models,--llm-command,--concurrency,--timeout,--mode,--context,--word-diff,--line-diff,--no-metrics,--metrics-position,--metrics,--format,--width,--color,--no-color,--label-a,--label-b,--version,--help. | Status: not_done - Implement environment variable fallbacks — In
src/cli.ts, readAI_DIFF_MODE,AI_DIFF_WIDTH,NO_COLOR,AI_DIFF_METRICSenvironment variables. CLI flags take precedence over env vars. | Status: not_done - Implement --help output — In
src/cli.ts, render a formatted help message listing all commands, flags, and usage examples. Exit with code 0. | Status: not_done - Implement --version output — In
src/cli.ts, read version frompackage.jsonand print it. Exit with code 0. | Status: not_done - Implement file comparison mode — In
src/cli.ts, when two positional file arguments are provided, read both files usingreadFileInput(), rundiff(), format output usingformatDiff(), print to stdout. | Status: not_done - Implement stdin comparison mode — In
src/cli.ts, when--stdinis set, read from stdin usingreadStdinInput(), rundiff(), format and print. | Status: not_done - Implement JSON input mode — In
src/cli.ts, when--json <file>is set, read the JSON file usingreadJsonInput(), rundiff(), format and print. | Status: not_done - Implement cassette comparison mode — In
src/cli.ts, when--cassetteis provided twice, read both cassettes usingreadCassette(), rundiff(), format and print. | Status: not_done - Implement live comparison mode (CLI) — In
src/cli.ts, when--promptand--modelsare set, construct anllmFnfrom--llm-command(substituting$PROMPTand$MODEL), callcompare(), format and print theComparisonResult. | Status: not_done - Implement --llm-command shell execution — In
src/cli.ts, implement the shell command template execution. Substitute$PROMPTand$MODELin the command string, execute viachild_process.exec, capture stdout as output text. | Status: not_done - Implement exit codes — In
src/cli.ts, exit with code 0 if outputs are identical, code 1 if differences found, code 2 for configuration/usage errors (invalid flags, missing files, file read failure, invalid input). | Status: not_done - Implement CLI error handling — In
src/cli.ts, catch all errors (file not found, invalid JSON, missing required flags, invalid flag values) and print a user-friendly error message to stderr. Exit with code 2. | Status: not_done - Implement non-TTY color handling in CLI — In
src/cli.ts, auto-detect TTY for color. Respect--colorto force on,--no-colorandNO_COLORto force off. Pass the resolvedcoloroption to formatters. | Status: not_done
- Wire up index.ts exports — In
src/index.ts, export all public API functions (diff,diffOutputs,compare,formatDiff) and all public types (LLMOutput,LLMFn,DiffMode,OutputFormat,DiffOptions,CompareOptions,DiffSegment,DiffHunk,LengthStats,DiffMetrics,JsonChange,DiffResult,MultiDiffResult,ComparisonResult). | Status: done
- Test text diff with identical texts — Verify that diffing identical texts produces zero hunks and
identical: true. | Status: done - Test text diff with completely different texts — Verify that diffing unrelated texts produces a single hunk covering entire content. | Status: done
- Test text diff with minor edits — Verify that a few-word change produces precise hunks with correct context lines. | Status: done
- Test text diff context lines — Verify that
contextLinesoption correctly controls the number of surrounding unchanged lines. | Status: done - Test word-level diff within changed lines — Verify that word-level segments are correctly identified within changed line pairs. | Status: done
- Test JSON diff with added keys — Verify detection of keys present in B but not A. | Status: done
- Test JSON diff with removed keys — Verify detection of keys present in A but not B. | Status: done
- Test JSON diff with changed values — Verify detection of keys with different values, with correct
beforeandafter. | Status: done - Test JSON diff with nested objects — Verify recursive comparison of nested objects with correct dot-notation paths. | Status: done
- Test JSON diff with arrays — Verify array comparison by index: added/removed elements at the end, changed elements at matching indices. | Status: done
- Test JSON diff with mixed types — Verify handling when a value changes type (e.g., string to number). | Status: done
- Test JSON diff with invalid JSON fallback — Verify that non-JSON input triggers fallback behavior (not an error). | Status: done
- Test Jaccard similarity with identical texts — Verify returns 1.0. | Status: done
- Test Jaccard similarity with completely different texts — Verify returns 0.0. | Status: done
- Test Jaccard similarity with partially overlapping texts — Verify returns a known expected value. | Status: done
- Test Jaccard similarity with empty strings — Verify correct handling: both empty returns 1.0, one empty returns 0.0. | Status: done
- Test Jaccard case insensitivity — Verify that "Hello World" and "hello world" have similarity 1.0. | Status: done
- Test Jaccard punctuation handling — Verify that punctuation is stripped before comparison. | Status: done
- Test semantic similarity computation — Mock
embedFn, verify cosine similarity is correctly computed. | Status: done - Test cosine similarity edge cases — Test with zero vectors, identical vectors, orthogonal vectors. | Status: done
- Test token count estimation — Verify
Math.ceil(text.length / 4)heuristic produces expected values for various text lengths. | Status: done - Test token count with provided values — Verify that provided
tokens.outputoverrides estimation. | Status: done - Test cost estimation with known pricing — Verify cost computation:
(input * inputPrice) + (output * outputPrice)for a known model. | Status: done - Test cost estimation with provided cost — Verify that provided
costoverrides computation. | Status: done - Test cost estimation with missing pricing — Verify cost is
undefinedwhen model is unknown and no pricing override is provided. | Status: done - Test length statistics — Verify word count, sentence count, and character count for known text inputs. | Status: done
- Test sentence counting edge cases — Verify handling of abbreviations, multiple punctuation marks, and text without terminal punctuation. | Status: done
- Test metrics orchestrator — Verify
computeDiffMetricsassembles all sub-metrics correctly, handles optional fields (latency, cost, input tokens). | Status: done
- Test terminal formatter ANSI codes — Verify that removed text uses red (
\x1b[31m), added text uses green (\x1b[32m), headers use cyan (\x1b[36m). | Status: done - Test terminal formatter non-TTY output — Verify that ANSI codes are omitted when color is disabled. | Status: done
- Test JSON formatter produces valid JSON — Verify that
formatDiff(result, 'json')output is parseable byJSON.parse. | Status: done - Test markdown formatter produces valid markdown — Verify correct use of fenced code blocks, markdown tables, and headings. | Status: not_done
- Test plain formatter has no ANSI codes — Verify that no
\x1b[sequences appear in plain output. | Status: done - Test metrics table rendering — Verify table structure, column alignment, delta formatting. Test with various combinations of available metrics. | Status: done
- Test metrics table with missing data — Verify table renders correctly when latency or cost is unavailable for some outputs. | Status: done
- Test header and footer rendering — Verify version string, comparison labels, mode, and "Analyzed in Xms" footer. | Status: not_done
- Test file input reading — Verify reading a plain text file returns its content as
LLMOutput.text. | Status: not_done - Test file input with JSON format — Verify that a
.jsonfile is parsed asLLMOutputwith metadata. | Status: not_done - Test file input with invalid JSON — Verify that a
.jsonfile with invalid JSON is treated as raw text. | Status: not_done - Test file input with non-existent file — Verify appropriate error is thrown. | Status: not_done
- Test stdin input splitting — Verify splitting by default delimiter
---produces two outputs. | Status: not_done - Test stdin input with custom delimiter — Verify splitting by a custom delimiter. | Status: not_done
- Test stdin input with missing delimiter — Verify error when delimiter is not found. | Status: not_done
- Test JSON input parsing — Verify reading and parsing a structured JSON input file with
aandbfields. | Status: not_done - Test JSON input with missing fields — Verify error when required fields are missing. | Status: not_done
- Test CLI argument parsing — Verify correct parsing of all flags and positional arguments. | Status: not_done
- Test CLI --help flag — Verify help output is printed and exit code is 0. | Status: not_done
- Test CLI --version flag — Verify version is printed and exit code is 0. | Status: not_done
- Test CLI exit code 0 for identical outputs — Create two identical temp files, run CLI, verify exit code 0. | Status: not_done
- Test CLI exit code 1 for different outputs — Create two different temp files, run CLI, verify exit code 1. | Status: not_done
- Test CLI exit code 2 for errors — Run CLI with invalid flags or missing files, verify exit code 2. | Status: not_done
- Test CLI environment variable fallback — Set
AI_DIFF_MODEenv var, verify it is used when--modeflag is not provided. | Status: not_done
- Integration test: identical outputs end-to-end — Diff two identical outputs through the full pipeline. Assert
identical: true, zero hunks, Jaccard similarity 1.0, correct metrics. | Status: done - Integration test: minor edit end-to-end — Diff two outputs differing by a few words. Assert correct hunks, metrics, and similarity score. | Status: done
- Integration test: completely different outputs — Diff two unrelated outputs. Assert low similarity, comprehensive hunks. | Status: not_done
- Integration test: JSON outputs in json mode — Diff two JSON strings in
jsonmode. Assert correctjsonChangesarray. | Status: done - Integration test: multi-output comparison — Compare 3 outputs using
diffOutputs(). Assert 3 pairwise diffs and a correct metrics table. | Status: done - Integration test: live comparison with mock — Mock
llmFn, runcompare(). Verify outputs, diffs, timing, andcallsarray. | Status: done - Integration test: live comparison with failure — Mock
llmFnto fail for one model. Verify the failure is recorded, remaining outputs are compared, and metrics table shows "ERROR". | Status: done - Integration test: file input via CLI — Write temp files, run CLI as subprocess, verify exit code and stdout content. | Status: not_done
- Integration test: stdin input via CLI — Pipe test data to CLI subprocess, verify correct splitting and output. | Status: not_done
- Integration test: non-TTY output — Pipe CLI output to a file, verify no ANSI codes in output. | Status: done
- Integration test: all diff modes — Run
diff()with each mode (unified,side-by-side,inline,metrics,json) and verify output format is correct for each. | Status: done - Integration test: all output formats — Run
formatDiff()with each format (terminal,json,markdown,plain) and verify output correctness. | Status: not_done
- Edge case: empty output string — Diff an empty string against a non-empty string. All content should show as added. | Status: done
- Edge case: two empty outputs — Diff two empty strings. Should be
identical: true, similarity 1.0. | Status: done - Edge case: one empty, one non-empty — Verify all content is marked as additions, similarity is 0.0. | Status: done
- Edge case: whitespace-only output — Diff text that contains only whitespace. Verify reasonable behavior. | Status: done
- Edge case: very long output (100KB+) — Performance test: diff two large outputs and verify completion within reasonable time (< 1 second). | Status: not_done
- Edge case: output containing ANSI escape codes — Verify that ANSI codes in input text do not interfere with diff formatting. | Status: not_done
- Edge case: output containing Unicode — Test with emoji, CJK characters, and RTL text. Verify diff and formatting are correct. | Status: done
- Edge case: JSON mode with non-JSON input — Verify graceful fallback to unified text diff with a warning. | Status: done
- Edge case: live comparison where all model calls fail — Verify appropriate error handling and result structure. | Status: not_done
- Edge case: terminal width below 80 for side-by-side — Verify fallback to unified mode with a warning message. | Status: not_done
- Edge case: missing model pricing data — Verify cost is omitted (not an error) when model is not in pricing table. | Status: done
- Edge case: output with same words in different order — Verify Jaccard similarity is 1.0 (same word sets) but text diff shows changes. | Status: done
- Write README.md — Create a comprehensive README with: package overview, installation instructions, quick start examples, API reference (all exported functions and types), CLI reference (all flags and usage examples), diff mode descriptions with example outputs, metrics explanation, configuration options, integration with other monorepo packages, and link to SPEC.md. | Status: done
- Add JSDoc comments to all public exports — Add JSDoc comments to every exported function, type, and interface in
src/index.ts,src/types.ts,src/diff.ts,src/multi-diff.ts,src/compare.ts, andsrc/formatters/index.ts. | Status: done - Add inline code comments — Add explanatory comments to non-obvious logic: Myers algorithm wrapper, Jaccard computation, cost estimation fallback chain, concurrency limiter, JSON recursive walker. | Status: done
- Verify TypeScript compilation — Run
npm run buildand ensure zero errors. Verifydist/contains.js,.d.ts, and.js.mapfiles for all source files. | Status: done - Verify lint passes — Run
npm run lintand ensure zero warnings/errors. | Status: done - Verify all tests pass — Run
npm run testand ensure all unit, integration, and edge case tests pass. | Status: done - Verify CLI binary works — Run
node bin/ai-diff.js --versionandnode bin/ai-diff.js --help. Verify output is correct. | Status: not_done - Verify package.json is publish-ready — Confirm
name,version,description,main,types,bin,files,keywords,license,engines,publishConfigfields are correct. Add relevant keywords (e.g.,ai,llm,diff,compare,model,tokens,cost). | Status: not_done - Bump version — Bump version in
package.jsonper semver. Since this is initial implementation, version should be0.1.0(already set). | Status: done - Dry-run publish — Run
npm publish --dry-runto verify the package contents and ensure nothing sensitive is included. | Status: not_done