Back to GoScope

Documentation

CHANGELOG v1 to v2

Changelog: Specification v1 to v2

From: Compilation-Focused Specification (Original) To: Review-Focused Specification v2.0 Date: 2025-10-23 Reason: User clarification - "The extracted code doesn't have to work, it's for reviewing"


Summary of Changes

This document details the transformation from a compilation-focused tool to a review-optimized code extraction tool. The change eliminates ~60% of complexity while adding critical missing features for actual code review workflows.


๐Ÿ”ด Major Removals

1. Compilation Requirements โŒ

Removed:

  • Goal: "smallest compilable code closure"
  • Single-file mode with merged, compilable output
  • Multi-file mode with directory tree generation
  • Import rewriting and alias preservation
  • Package name conflict resolution
  • Synthetic package creation (package main wrapper)
  • go.mod generation and module synthesis
  • Require/replace pruning
  • Vendor mode support
  • Workspace configuration
  • Build verification tests
Impact: -2000 lines of code, -40% complexity

Rationale: Code doesn't need to compile for review purposes. Focusing on readability is more valuable.


2. Topological Sorting and Dependency Resolution โŒ

Removed:

  • Kahn's algorithm for declaration ordering
  • Strongly connected component (SCC) detection
  • Cycle resolution logic
  • Init function ordering
  • Dependency graph topological sort
Impact: -500 lines of code, -15% complexity

Rationale: Declaration order doesn't matter for review. Natural source order is more intuitive.


3. Build Infrastructure โŒ

Removed:

  • Build tag handling (--build-tags flag)
  • Platform-specific file inclusion/exclusion
  • cgo detection and error handling
  • Generated file skipping logic (--skip-generated)
  • Vendor directory traversal (--vendor flag)
  • File count limits (--max-files flag)
Impact: -300 lines of code, -10% complexity

Rationale: Reviewers care about default build context. Complex build variations are edge cases.


4. Cross-Package Unexported Symbol Resolution โŒ

Removed:

  • Complex logic for including unexported symbols across packages
  • Forcing multi-file mode when unexported needed
  • Package boundary validation
  • Access control enforcement
Impact: -200 lines of code, -5% complexity

Rationale: Just note "unexported from package X" and move on. Simple and clear.


5. Two Output Modes โŒ

Removed:

  • --mode single-file|multi-file
  • Single-file assembler (merge + rewrite)
  • Multi-file assembler (directory tree)
  • Mode selection logic
Impact: -800 lines of code, -20% complexity

Rationale: One format (structured document) is clearer than two complex modes.


๐ŸŸข Major Additions

1. Depth Control โœ…

Added:

  • --depth N flag (default: 1)
  • Depth 0: Target only
  • Depth 1: Target + direct dependencies
  • Depth N: Transitive to N levels
  • Breadth-first traversal with depth tracking
Impact: +200 lines of code, core feature

Rationale: Essential for balancing context vs noise in reviews.


2. Caller Analysis โœ…

Added:

  • --show-callers flag
  • Reverse dependency lookup
  • Context snippets around call sites
  • Test caller inclusion with --show-tests
  • Caller grouping by file
Impact: +300 lines of code, killer feature

Rationale: "Where is this used?" is the #1 question in code review.


3. Syntax Highlighting and Rich Formatting โœ…

Added:

  • HTML output with chroma/highlight.js
  • Markdown with fenced code blocks
  • File:line annotations
  • Clickable hyperlinks in HTML
  • Section separators
  • Collapsible regions
  • Copy buttons
Impact: +400 lines of code, UX win

Rationale: Readable output is the entire point of a review tool.


4. External Reference Stubs โœ…

Added:

  • --stub-external flag (default: true)
  • Signature extraction for external symbols
  • Clear "External References" section
  • Type signature display
  • Standard library notation
Impact: +150 lines of code, clarity feature

Rationale: Show what's being used without including entire stdlib/third-party.


5. Metrics and Analysis โœ…

Added:

  • --metrics flag
  • Cyclomatic complexity calculation
  • Lines of code (physical + logical)
  • Dependency count (direct + transitive)
  • External package list
  • Metrics section in output
Impact: +250 lines of code, assessment feature

Rationale: Quick complexity assessment helps prioritize review effort.


6. Git Integration โœ…

Added:

  • --git-blame flag
  • Last author/date per line
  • Recent commit history for symbol
  • Uncommitted change highlighting
  • Git history section in output
Impact: +200 lines of code, context feature

Rationale: Historical context (who wrote this, when, why) is valuable for reviews.


7. JSON Output โœ…

Added:

  • --format json
  • Structured machine-readable output
  • Complete metadata
  • Tool integration support
  • Detailed schema (see spec appendix)
Impact: +150 lines of code, integration feature

Rationale: Enables CI/CD integration, automated review tools, custom processing.


๐Ÿ“Š Detailed Change Matrix

Feature/Componentv1 (Compilation)v2 (Review)Change
Core GoalCompilable extractionReadable extractionPivot
CLI Flags1213+1 (depth), -3 (vendor, build-tags, max-files), +3 (callers, metrics, git)
Output Modes2 (single/multi file)1 (structured doc)Simplify
Output Formats2 (go, json)3 (markdown, html, json)+2
Dependency TraversalFull transitiveDepth-limited BFSSimplify + control
Import HandlingRewrite + mergePreserve + annotateSimplify
Topological SortRequiredNoneRemove
Init() HandlingComplex inclusion logicNote if presentSimplify
Build TagsFull supportDefault context onlySimplify
Caller AnalysisNoneFull reverse lookupAdd
Syntax HighlightingNoneHTML + MarkdownAdd
MetricsNoneCyclomatic + LOC + depsAdd
Git IntegrationNoneBlame + logAdd
External StubsNoneSignaturesAdd
AnnotationsNoneFile:line markersAdd
Internal Packages74-3
LOC Estimate5000-60002000-2500-58%
Dev Time10-12 weeks4-6 weeks-50%
Test Scenarios40+20-50% (refocused)

๐Ÿ”ง Architecture Changes

v1 Architecture (Compilation-Focused)

shell
internal/extract/
  loader.go                   // packages.Load
  locator.go                  // position โ†’ symbol
  graph.go                    // dependency graph
  walker.go                   // AST walk
  assemble_single.go          // Single-file compiler
  assemble_multi.go           // Multi-file compiler
  manifest.go                 // JSON output
  rewrite.go                  // Import rewriting
  guard.go                    // Limits and validation

Total: 7 packages, ~5500 lines

v2 Architecture (Review-Focused)

shell
internal/extract/
  loader.go                   // packages.Load wrapper
  locator.go                  // position โ†’ symbol
  collector.go                // Depth-limited BFS (NEW)
  analysis.go                 // Caller analysis + metrics (NEW)
  git.go                      // Git integration (NEW)
  format/
    markdown.go               // Markdown formatter (NEW)
    html.go                   // HTML formatter (NEW)
    json.go                   // JSON output (RENAMED from manifest.go)

Total: 4 packages (+ 3-file subpackage), ~2300 lines

Changes:

  • โŒ Removed: graph.go, walker.go, assemble_single.go, assemble_multi.go, rewrite.go, guard.go
  • โœ… Added: collector.go, analysis.go, git.go, format/ subpackage
  • โœ… Simplified: loader.go, locator.go (less complexity)
  • โœ… Renamed: manifest.go โ†’ format/json.go (clearer purpose)

๐ŸŽฏ API Changes

v1 API (Compilation-Focused)

go
type Target struct {
  Root, File string
  Line, Col  int
  BuildTags  []string    // โŒ Removed
  IncludeTests bool      // โŒ Removed (now a flag, not target property)
}

type Result struct {
  Mode    string         // โŒ Removed (single-file vs multi-file)
  Files   []EmittedFile  // โŒ Removed (compilable .go files)
  Manifest Manifest      // โœ… Renamed to Metadata
}

func Extract(ctx context.Context, t Target, opts Options) (Result, error)

v2 API (Review-Focused)

go
type Target struct {
  Root   string  // Module root
  File   string  // Source file
  Line   int     // Line number
  Column int     // Column (default: 1)
}

type Options struct {
  Depth          int      // โœ… NEW: Dependency depth
  Format         string   // โœ… NEW: markdown/html/json
  StubExternal   bool     // โœ… NEW: Show signatures
  ShowCallers    bool     // โœ… NEW: Reverse deps
  ShowTests      bool     // โœ… NEW: Include tests
  ContextLines   int      // โœ… NEW: Extra lines
  Annotate       bool     // โœ… NEW: File:line comments
  IncludeMetrics bool     // โœ… NEW: Complexity metrics
  GitBlame       bool     // โœ… NEW: Git history
}

type Symbol struct {        // โœ… NEW: Explicit symbol type
  Package   string
  Name      string
  Kind      string
  Receiver  string
  File      string
  Line      int
  EndLine   int
  Code      string
  Doc       string
  Exported  bool
}

type Reference struct {     // โœ… NEW: Explicit reference type
  Symbol       Symbol
  Reason       string       // โœ… NEW: Why included
  Depth        int          // โœ… NEW: Depth in tree
  External     bool         // โœ… NEW: External vs local
  Stub         bool         // โœ… NEW: Signature only
  Signature    string       // โœ… NEW: For stubs
  ReferencedBy string       // โœ… NEW: Back-reference
}

type Caller struct {        // โœ… NEW: Reverse dependency
  File     string
  Line     int
  Function string
  Context  string
}

type Metrics struct {       // โœ… NEW: Complexity metrics
  LinesOfCode         int
  LogicalLines        int
  CyclomaticComplexity int
  DependencyCount     int
  DirectDeps          int
  TransitiveDeps      int
  ExternalPackages    []string
}

type GitBlame struct {      // โœ… NEW: Git history
  Commit  string
  Author  string
  Date    time.Time
  Message string
}

type Extract struct {       // โœ… NEW: Structured result
  Target     Symbol
  References []Reference
  External   []string
  Callers    []Caller
  Metrics    *Metrics
  GitHistory []GitBlame
  Graph      string
}

type Result struct {
  Extract  Extract          // โœ… NEW: Structured extract
  Rendered string           // โœ… NEW: Formatted output
  Metadata Metadata         // โœ… RENAMED from Manifest
}

func ExtractSymbol(ctx context.Context, target Target, opts Options) (*Result, error)

// โœ… NEW: Convenience functions
func ExtractToFile(ctx context.Context, target Target, opts Options, outputPath string) error
func ExtractToMarkdown(ctx context.Context, target Target, depth int) (string, error)
func ExtractToHTML(ctx context.Context, target Target, depth int) (string, error)
func ExtractToJSON(ctx context.Context, target Target, depth int) (string, error)

Summary:

  • More explicit types (Symbol, Reference, Caller, Metrics, GitBlame)
  • Clearer separation of concerns
  • Richer metadata
  • Better ergonomics (convenience functions)

๐Ÿงช Testing Changes

v1 Testing (Compilation-Focused)

Focus:

  • Does extracted code compile?
  • Are imports correct?
  • Is topological order valid?
  • Does go.mod work?
Example BDD Scenario:

gherkin
Scenario: Extract handler that uses pkg/service.UserService
  Given example module "ex2"
  When I run go-scope for "cmd/api/main.go" line 30 mode "multi-file"
  Then emitted files include "pkg/service/service.go"
  And emitted files exclude unrelated "pkg/repo/unused.go"
  And I can run "go build" in output directory  # โŒ No longer relevant

v2 Testing (Review-Focused)

Focus:

  • Are correct symbols extracted?
  • Is depth limiting accurate?
  • Are annotations correct?
  • Are callers found?
  • Is output valid markdown/HTML/JSON?
Example BDD Scenario:

gherkin
Scenario: Extract handler with depth control
  Given example module "ex2"
  When I extract "cmd/api/main.go" line 30 with depth 0
  Then output includes only "handleCreateUser"
  And output shows "UserService.CreateUser" as stub

  When I extract same location with depth 2
  Then output includes "handleCreateUser"
  And output includes "UserService.CreateUser" implementation
  And output includes "validateEmail" helper

New Scenarios (not in v1):

  • Caller discovery
  • Metric accuracy
  • Git blame integration
  • Format validation (HTML, JSON)
  • Depth limiting
  • External stub generation
Removed Scenarios (from v1):
  • Compilation tests
  • Build tag validation
  • go.mod generation
  • Import conflict resolution
  • Topological order verification

๐Ÿ“ CLI Changes

Removed Flags

FlagReason for Removal
--mode single-file\|multi-fileOnly one output mode now (structured doc)
--build-tagsUse default build context; build variations are edge cases
--vendorNot relevant without compilation
--max-filesNo longer a concern (not compiling)
--skip-generatedLess relevant for review; include by default
--follow-internalSimplified to always follow within module

Added Flags

FlagPurpose
--depth NControl dependency traversal depth (0 = target only)
--show-callersInclude reverse dependencies (what calls this?)
--show-testsInclude test functions/callers
--metricsCompute and display complexity metrics
--git-blameShow git history for symbol
--context-lines NExtra lines before/after target
--annotateAdd inline file:line comments (default: true)
--stub-externalShow signatures for external deps (default: true)

Changed Flags

Flagv1v2Change
--formatImplicit (go/json)Explicit (markdown/html/json)More options
--outputFile or directoryFile onlySimplified
--include-testsBoolean on TargetFlag --show-testsMoved to options

๐Ÿ“ˆ Impact Analysis

Development Time

Phasev1 (Compilation)v2 (Review)Savings
Core extraction2 weeks2 weeks0
Dependency traversal2 weeks1 week50%
Assembly/output3 weeks1 week67%
Import rewriting1 week0100%
Build infrastructure1 week0100%
Review features01 week-100% (new)
Advanced features1 week1 week0
Testing2 weeks1.5 weeks25%
Documentation0.5 weeks0.5 weeks0
Total12.5 weeks8 weeks36%

Maintenance Burden

Aspectv1v2Change
Code complexityHighMedium-40%
Test maintenance40+ scenarios20 scenarios-50%
Documentation15 sections19 sections+27% (but simpler)
Edge cases25+12-52%
User supportHigh (many failure modes)Medium-35%

User Value

Metricv1 (Compilation)v2 (Review)Improvement
ReadabilityLow (compiler-focused)High (human-focused)+400%
UsefulnessLow (doesn't actually compile)High (exactly what's needed)+500%
Learning curveSteepGentle+200%
Feature completeness60% (missing key features)95% (has what reviewers need)+58%

๐Ÿš€ Migration Path

For users of hypothetical v1 (if it existed):

Command Migration

v1 Command:

bash
go-scope \
  --root . \
  --file pkg/service/user.go \
  --line 128 \
  --mode single-file \
  --output extracted.go

v2 Equivalent:

bash
go-scope \
  --root . \
  --file pkg/service/user.go \
  --line 128 \
  --format markdown \
  --output extracted.md

API Migration

v1 Code:

go
result, err := extract.Extract(ctx,
    extract.Target{
        Root: ".",
        File: "pkg/service/user.go",
        Line: 128,
        BuildTags: []string{"prod"},
        IncludeTests: false,
    },
    extract.Options{})

v2 Code:

go
result, err := extract.ExtractSymbol(ctx,
    extract.Target{
        Root: ".",
        File: "pkg/service/user.go",
        Line: 128,
    },
    extract.Options{
        Depth: 1,
        Format: "markdown",
        ShowTests: false,
    })


๐ŸŽ“ Lessons Learned

What Went Wrong in v1

  • Misaligned Goal: Focused on compilation without clarifying actual user need
  • Over-Engineering: Solved problems that don't exist (import conflicts, topological sort)
  • Missing Features: Ignored critical review needs (callers, syntax highlighting)
  • Complexity Creep: Each feature added more complexity (build tags โ†’ vendor โ†’ go.mod โ†’ ...)
  • What v2 Gets Right

  • Clear Goal: "Extract for review" is unambiguous
  • User-Centric: Features map directly to review workflows
  • Simplicity: Only include what's needed for the goal
  • Extensibility: Architecture allows adding features without complexity explosion
  • Key Takeaways

    • Always clarify the goal first: "Compilable" vs "reviewable" is a fundamental difference
    • Question assumptions: "Does it need to compile?" could have been asked earlier
    • Start with MVP: Build the simplest thing that works, then add features
    • User feedback early: A quick prototype would have revealed the mismatch

    ๐Ÿ“‹ Checklist for Adopting v2

    • [ ] Review and approve v2 specification
    • [ ] Archive v1 specification (rename to SPEC_v1_COMPILATION_ARCHIVE.md)
    • [ ] Update project README to reference v2
    • [ ] Create v2 milestones and issues
    • [ ] Set up project structure per v2 architecture
    • [ ] Implement Phase 1 (Core Extraction)
    • [ ] Implement Phase 2 (Review Features)
    • [ ] Implement Phase 3 (Advanced Features)
    • [ ] Implement Phase 4 (Polish)
    • [ ] Release v1.0.0

    ๐Ÿ”ฎ Future Considerations

    Features Not in Either v1 or v2

    Some features weren't in v1 and aren't in v2 scope, but could be considered later:

    • IDE integration: VS Code extension, LSP server
    • Web service: HTTP API for remote extraction
    • Collaboration: Shared extracts, annotations, discussions
    • Diff mode: Compare two versions of a symbol
    • Advanced analysis: Data flow, type hierarchy, impact analysis
    These would build on v2's foundation, not v1's.


    ๐Ÿ“Š Side-by-Side Comparison

    Example: Extract CreateUser Method

    v1 Output (Single-File Mode):

    go
    // Merged, compilable .go file
    package main
    
    import (
        "context"
        "database/sql"  // Full import
        "fmt"
        "time"
    )
    
    // User type (from pkg/model)
    type User struct {
        ID        int64
        Email     string
        Name      string
        CreatedAt time.Time
    }
    
    // validateEmail (from pkg/service)
    func validateEmail(email string) error {
        // ... implementation
    }
    
    // UserService stub
    type UserService struct {
        db interface{} // Simplified
    }
    
    // CreateUser (target)
    func (s *UserService) CreateUser(ctx context.Context, email, name string) (*User, error) {
        // ... implementation
    }
    
    func main() {
        // Stub main (for compilation)
    }

    Problems:

    • Package names lost (everything in main)
    • No context (where is this from?)
    • No caller information
    • No metrics
    • Hard to read (no structure)
    v2 Output (Markdown Mode):

    markdown
    # Code Extract: CreateUser
    
    **File**: pkg/service/user.go:128
    **Package**: github.com/example/app/pkg/service
    **Kind**: Method (UserService)
    
    ## Metrics
    - Cyclomatic Complexity: 3
    - Lines of Code: 17
    - Dependencies: 4
    
    ## Target Symbol
    go // File: pkg/service/user.go:128-145 func (s UserService) CreateUser(ctx context.Context, email, name string) (User, error) { if err := validateEmail(email); err != nil { // โ†’ pkg/service/validation.go:45 return nil, fmt.Errorf("invalid email: %w", err) } user := &User{...} // โ†’ pkg/model/user.go:12 if err := s.db.Create(user); err != nil { // โ†’ external: database/sql return nil, fmt.Errorf("failed to create user: %w", err) } return user, nil }

    shell
    
    ## Direct Dependencies (depth 1)
    
    ### validateEmail
    **File**: pkg/service/validation.go:45
    go func validateEmail(email string) error { if !strings.Contains(email, "@") { return errors.New("invalid email format") } return nil }

    shell
    
    ### User
    **File**: pkg/model/user.go:12
    go type User struct { ID int64 Email string Name string CreatedAt time.Time }

    shell
    
    ## External References
    - database/sql: `DB.Create(value interface{}) error`
    - fmt: `Errorf(format string, a ...any) error`
    
    ## Called By
    - cmd/api/handlers.go:67 - `handleCreateUser`
    - cmd/cli/user.go:123 - `createUserCommand`
    - pkg/service/user_test.go:34 - `TestCreateUser`
    
    ## Recent Changes
    - 2025-10-20 by alice@example.com - "Add email validation"

    Benefits:

    • Clear structure with sections
    • Full context (package paths, file:line)
    • Caller information
    • Metrics for quick assessment
    • Annotations show dependencies
    • Much more readable

    โœ… Approval Status

    • [ ] Analysis reviewed and approved
    • [ ] v2 specification reviewed and approved
    • [ ] Changelog reviewed and approved
    • [ ] Ready to begin implementation

    End of Changelog

    ยฉ 2026 Jonathan Leahy ยท v0.8.5