Skip to content

Extract shared chunked-analyzer helper: the loop is duplicated across the daemon and CLI paths #47

Description

@vnovick

Summary

depsanalysis.RunAgentPass has two callers, and the chunk / scope-edges / fail-atomically / dedupe loop around it is now duplicated between them:

  • cmd/itervox/deps_analyzer_service.go — the daemon's async POST /api/v1/deps/analyze path
  • cmd/itervox/init_deps_analysis.go — the one-shot itervox init / itervox deps analyze path

Why this is worth tracking rather than shrugging at

This exact duplication already caused a bug. When chunking was added (#43), only the daemon path got it. The CLI path kept sending the entire backlog and the entire tracker-edge list in one unbounded turn — the headline defect the work existed to fix — and it survived a full task-level review because nothing connected the two call sites. It was caught only by a cross-cutting review that went looking for other callers.

The two copies have already drifted, though so far only in observability:

daemon path CLI path
clamp / ChunkIssues / ScopeTrackerEdges / ctx.Err() gate / fail-atomically / DedupeInferredEdges ✅ identical
LogDir agentLogDir/deps-analyzer ""
per-chunk failure log WARN with profile + chunk + total none
run-start log (issues / edges / chunks) present absent
blind-spot logger s.logger (component=deps_analyzer) slog.Default() (no component)
empty backlog implicit (ChunkIssues → nil → empty sidecar) explicit early return

The semantic core is in sync. The instrumentation is not, which means a CLI-path chunk failure is materially harder to diagnose than a daemon-path one.

Current mitigation

Both files now carry a bidirectional comment naming the other by path and stating they must stay in sync — added specifically because the original follow-up note lived in a git-ignored scratch directory and would have disappeared at merge.

That is a speed bump, not a fix.

Proposed

Extract a shared helper, roughly:

func RunChunkedAgentPass(
    ctx context.Context,
    input AgentPassInput,          // Issues/TrackerEdges filled per chunk by the helper
    issues []AnalyzerIssue,
    trackerEdges []TrackerEdge,
    chunkSize int,
    onChunkDone func(done, total int),
) ([]InferredEdge, error)

The two sites genuinely differ — one has a JobManager and a progress callback, one has neither — which is why this was not done inline at the time. onChunkDone is the seam that absorbs that difference.

If a third caller of RunAgentPass appears before this extraction, extract first rather than adding a third copy.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions