Skip to content

[duplicate-code] Duplicate Code: Memory allowed-extensions Parsing in cache_config.go and drive_memory_config.goΒ #67517

Description

@github-actions

πŸ” Duplicate Code Detected: Memory allowed-extensions Parsing Loop

Analysis of commit 2b5c6d4 (#67506)

Assignee: @copilot

Summary

Two memory-subsystem config parsers β€” one for cache-memory and one for drive-memory β€” contain a near-identical loop that reads the allowed-extensions list, validates each entry with isValidFileExtension, and appends it to the entry's AllowedExtensions slice. The bodies differ only by the entry struct type (*CacheMemoryEntry vs *DriveMemoryEntry) and local variable names; the logic, validation, and error message are byte-for-byte identical.

Impact Analysis

  • Maintainability: Any change to extension validation (e.g. allowing a new character class, tightening the error message, or supporting a new config shape) must be made in two places, which is easy to miss.
  • Bug Risk: The two copies can silently drift β€” a fix applied to one memory type but not the other produces inconsistent validation behaviour for cache-memory vs drive-memory.
  • Code Bloat: ~22 lines are duplicated verbatim; repo-memory already uses a different helper (parseRepoMemoryStringList), so the codebase currently has three divergent approaches to the same concept.
Duplication Details

Pattern: allowed-extensions list parse + per-item validation

  • Severity: Medium
  • Occurrences: 2 (plus a third divergent variant in repo_memory.go)
  • Locations:
    • pkg/workflow/cache_config.go β€” parseCacheMemoryAllowedExtensions (lines 272–294)
    • pkg/workflow/drive_memory_config.go β€” parseDriveMemoryAllowedExtensions (lines 148–173)
  • Code Sample (cache_config.go):
    func parseCacheMemoryAllowedExtensions(cacheMap map[string]any, entry *CacheMemoryEntry) error {
        allowedExts, exists := cacheMap["allowed-extensions"]
        if !exists {
            return nil
        }
        extArray, ok := allowedExts.([]any)
        if !ok {
            return nil
        }
        entry.AllowedExtensions = make([]string, 0, len(extArray))
        for _, ext := range extArray {
            extStr, ok := ext.(string)
            if !ok {
                continue
            }
            if !isValidFileExtension(extStr) {
                return fmt.Errorf("invalid allowed-extension %q: must start with '.' followed by alphanumeric characters only (e.g. .json)", extStr)
            }
            entry.AllowedExtensions = append(entry.AllowedExtensions, extStr)
        }
        return nil
    }
  • Code Sample (drive_memory_config.go, functionally identical):
    func parseDriveMemoryAllowedExtensions(raw map[string]any, entry *DriveMemoryEntry) error {
        value, exists := raw["allowed-extensions"]
        if !exists {
            return nil
        }
        values, ok := value.([]any)
        if !ok {
            return nil
        }
        entry.AllowedExtensions = make([]string, 0, len(values))
        for _, value := range values {
            extension, ok := value.(string)
            if !ok {
                continue
            }
            if !isValidFileExtension(extension) {
                return fmt.Errorf("invalid allowed-extension %q: must start with '.' followed by alphanumeric characters only (e.g. .json)", extension)
            }
            entry.AllowedExtensions = append(entry.AllowedExtensions, extension)
        }
        return nil
    }

Refactoring Recommendations

  1. Extract a shared helper that returns the parsed slice

    • Add e.g. parseMemoryAllowedExtensions(configMap map[string]any) ([]string, error) (suggested home: pkg/workflow/memory_validation_config.go, alongside the other shared memory helpers, or cache_config.go since isValidFileExtension already lives there).
    • Have both callers assign the result: exts, err := parseMemoryAllowedExtensions(m); entry.AllowedExtensions = exts.
    • Returning the slice (rather than mutating a typed *Entry) avoids coupling the helper to either struct type and lets repo-memory adopt it too.
    • Estimated effort: ~1 hour (small, mechanical, well covered by existing cache_memory_*_test.go / drive_memory_test.go).
    • Benefits: single source of truth for extension validation and the shared error message; removes drift risk between memory types.
  2. (Optional) Converge repo-memory

    • Evaluate whether parseRepoMemoryStringList for allowed-extensions can route through the same helper so all three memory types validate extensions identically.

Implementation Checklist

  • Review duplication findings
  • Extract shared parseMemoryAllowedExtensions helper
  • Update cache_config.go and drive_memory_config.go to call it
  • (Optional) Converge repo_memory.go onto the helper
  • Run make fmt and make test-unit
  • Verify no functionality broken
Analysis Metadata
  • Analyzed Files: memory-subsystem source files under pkg/workflow/ (cache/drive/repo/comment/validation)
  • Detection Method: Serena semantic code analysis + pattern search
  • Commit: 2b5c6d4
  • Scope note: repository is a single squashed commit, so analysis focused on the commit's stated theme (memory schema contract + safe-output runtime)

Generated by πŸ” Duplicate Code Detector Β· pi Β· opus48 Β· 104.2 AIC Β· βŒ– 45.4 AIC Β· ⊞ 1.5K Β· β—·

  • expires on Oct 12, 2026, 1:56 PM UTC-08:00

Activity

  1. github-actions commented on Oct 10, 2026

    @github-actions
    ContributorAuthor

    πŸͺ Issue Monster selected this for Copilot

    I've identified this issue as a good candidate for automated resolution and requested assignment to the Copilot coding agent.

    If assignment succeeds, the Copilot coding agent will analyze the issue and create a pull request with the fix.

    Om nom nom! πŸͺ

    πŸͺ Om nom nom by Issue Monster Β· pi Β· gpt54 Β· 13.5 AIC Β· βŒ– 8.13 AIC Β· ⊞ 12.4K Β· β—·

  2. github-actions commented on Oct 10, 2026

    @github-actions
    ContributorAuthor

    πŸͺ Issue Monster selected this for Copilot

    I've identified this issue as a good candidate for automated resolution and requested assignment to the Copilot coding agent.

    If assignment succeeds, the Copilot coding agent will analyze the issue and create a pull request with the fix.

    Om nom nom! πŸͺ

    πŸͺ Om nom nom by Issue Monster Β· pi Β· gpt54 Β· 11 AIC Β· βŒ– 6.63 AIC Β· ⊞ 12.4K Β· β—·

  3. github-actions commented on Oct 10, 2026

    @github-actions
    ContributorAuthor

    πŸͺ Issue Monster selected this for Copilot

    I've identified this issue as a good candidate for automated resolution and requested assignment to the Copilot coding agent.

    If assignment succeeds, the Copilot coding agent will analyze the issue and create a pull request with the fix.

    Om nom nom! πŸͺ

    πŸͺ Om nom nom by Issue Monster Β· pi Β· gpt54 Β· 10.8 AIC Β· βŒ– 6.77 AIC Β· ⊞ 12.5K Β· β—·

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions