Skip to content

feat: add batch CLI and web UI for issue analysis#36

Merged
Kavirubc merged 5 commits intomainfrom
feature/cli-issue-test
Feb 11, 2026
Merged

feat: add batch CLI and web UI for issue analysis#36
Kavirubc merged 5 commits intomainfrom
feature/cli-issue-test

Conversation

@Kavirubc
Copy link
Copy Markdown
Contributor

@Kavirubc Kavirubc commented Feb 10, 2026

Summary

This PR introduces two major features for testing and analyzing issues against the Simili Bot vector database:

  1. Batch CLI Command - Process multiple issues from JSON files
  2. Web UI - Interactive web interface for real-time issue analysis

Both features run in dry-run mode and never make writes to GitHub or the vector database.

Changes

🔧 Batch CLI Command (simili batch)

  • Process arrays of issues from JSON files
  • Support JSON (detailed) and CSV (stakeholder-friendly) output formats
  • Concurrent processing with configurable worker pool
  • Override collection, thresholds, and top-k via CLI flags
  • Extracted reusable ExecutePipeline() function from process command

Use Cases:

  • Test bot logic on historical issues without spamming repos
  • Generate analysis reports for stakeholders
  • Validate similarity search and duplicate detection accuracy
  • Audit quality assessment without requiring write access

Example:

simili batch --file issues.json --out-file results.csv --format csv --workers 5

🌐 Web UI (simili-web)

  • Minimal shadcn-style black/white interface with green/red/yellow accents
  • Real-time issue analysis with similarity search, duplicate detection, quality assessment, and triage
  • REST API with /api/analyze endpoint
  • Embedded static files for single-binary deployment
  • Comprehensive README for developers

Features:

  • Submit issues via web form (title, body, org, repo)
  • View similar issues with similarity scores
  • See duplicate detection with LLM reasoning
  • Get quality scores and improvement suggestions
  • Receive label and transfer recommendations

Usage:

export GEMINI_API_KEY=xxx QDRANT_URL=xxx QDRANT_API_KEY=xxx QDRANT_COLLECTION=xxx
./simili-web
# Open http://localhost:8080

🐛 Bug Fixes

Duplicate Detection Improvements:

  • Fixed issue where related issues were incorrectly marked as duplicates
  • Root cause: Only titles were passed to LLM, not full issue bodies
  • Now extracts and passes full text field from Qdrant payload
  • Rewrote duplicate detection prompt to be more conservative
  • Raised confidence threshold to 0.85
  • Added DuplicateReason field to capture LLM reasoning
  • Updated embedding model to gemini-embedding-001

Before: Issue chain #8640 → #8641 → #8642 incorrectly marked as duplicates
After: Issues correctly identified as related but not duplicates

Testing

Batch CLI

  • ✅ Processed 3 test issues against 4000+ indexed issues
  • ✅ CSV output successfully generated
  • ✅ No VDB writes (indexer step excluded)
  • ✅ Duplicate detection accurate with full body analysis

Web UI

  • ✅ Server starts and serves static files
  • ✅ API endpoint returns proper JSON responses
  • ✅ Dry-run mode enforced (no GitHub writes)
  • ✅ Minimal UI renders correctly across browsers

Documentation

  • ✅ Updated main README with batch CLI usage
  • ✅ Created comprehensive README for simili-web
  • ✅ Added API documentation and troubleshooting guides
  • ✅ Included examples for both CLI and web UI

Breaking Changes

None. All changes are additive.

Checklist

  • Code follows Go best practices and project conventions
  • All commits have proper messages with Co-Authored-By tags
  • Documentation updated for new features
  • Dry-run mode enforced for safety
  • No test files or binaries committed

🤖 Generated with Claude Sonnet 4.5

Summary by CodeRabbit

  • New Features

    • Web UI for analyzing GitHub issues: similarity, duplicate check, quality assessment, label suggestions, and transfer recommendations.
    • Batch CLI command to process many issues from JSON with JSON/CSV outputs and concurrency controls.
    • Analysis responses now include richer similar-issue content and explicit duplicate reasoning.
  • Documentation

    • Added CLI commands docs with examples and an example workflow.
    • Added Web UI documentation, quick-start, API usage, and troubleshooting.

Kavirubc and others added 4 commits February 10, 2026 21:18
Add simili batch command to process multiple issues from JSON files
against the Qdrant vector database in dry-run mode. This enables
testing bot logic on historical data without making any GitHub writes.

Features:
- Process issues from JSON array input
- Support JSON and CSV output formats
- Concurrent processing with worker pool pattern
- Override collection, thresholds, and top-k via flags
- Force dry-run mode to prevent any side effects

Use cases:
- Test bot logic on historical issues
- Generate analysis reports for stakeholders
- Validate similarity search and duplicate detection
- Audit quality assessment without repo write access

Implementation:
- Extracted ExecutePipeline() function for reusability
- Worker pattern following index.go architecture
- Exclude indexer step to prevent VDB writes
- Support configuration overrides via CLI flags

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed duplicate detection incorrectly marking related issues as
duplicates by ensuring full issue bodies are passed to the LLM for
analysis, not just titles.

Changes:
- Add Body field to SimilarIssue struct to store full text
- Extract and populate text field from Qdrant payload
- Pass issue bodies to duplicate detection LLM prompt
- Rewrite duplicate detection prompt to be more conservative
- Distinguish between DUPLICATE vs RELATED issues clearly
- Raise duplicate confidence threshold to 0.85
- Add DuplicateReason field to capture LLM reasoning
- Update embedding model to gemini-embedding-001

Root cause:
Similarity search was retrieving the text field from Qdrant but
discarding it, only passing titles to the duplicate detector. This
caused the LLM to mark issues with similar titles as duplicates even
when their bodies described different problems.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Update documentation to reflect:
- New simili batch command with usage examples
- Improved duplicate detection with body analysis
- Corrected embedding model name to gemini-embedding-001
- CSV/JSON output format examples

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add simili-web command with minimal shadcn-style web interface for
analyzing GitHub issues against the vector database. Provides real-time
analysis results without requiring GitHub write permissions.

Features:
- Interactive web form for submitting issues
- Real-time similarity search against indexed issues
- Duplicate detection with confidence scores and reasoning
- Quality assessment with actionable feedback
- Label suggestions based on issue content
- Transfer recommendations with explanations
- Minimal black/white design with green/red/yellow accents
- Embedded static files for single-binary deployment

Technical details:
- Go HTTP server with embedded static files
- Same pipeline as CLI (dry-run mode enforced)
- REST API with /api/analyze endpoint
- No writes to GitHub or vector database
- Supports collection overrides via env vars

Usage:
  export GEMINI_API_KEY=xxx
  export QDRANT_URL=xxx
  export QDRANT_API_KEY=xxx
  export QDRANT_COLLECTION=xxx
  ./simili-web

Then open http://localhost:8080 in browser.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 10, 2026

📝 Walkthrough

Walkthrough

Adds a Simili web UI and CLI batch command, extracts pipeline execution into a reusable API, enriches similarity/duplicate detection with full-body context and reasoning, and expands embedding configuration keys. Includes frontend assets, backend server, batch processing, tests, and documentation.

Changes

Cohort / File(s) Summary
Configuration
\.simili\.yaml
Added qdrant.embedding keys: model: gemini-embedding-001 and dimensions: 768.
Documentation
README.md, cmd/simili-web/README.md
Added CLI command docs (index/process/batch) and comprehensive Web UI documentation (features, API, architecture, examples).
Web UI Backend
cmd/simili-web/main.go
New HTTP server: serves embedded static UI, /api/analyze and /api/health endpoints, loads config, initializes dependencies (dry-run), builds and runs a reduced pipeline, and returns structured AnalysisResponse.
Web UI Frontend
cmd/simili-web/static/index.html, cmd/simili-web/static/app.js, cmd/simili-web/static/styles.css
Added static dark-themed UI, client-side form and JS to POST analysis requests, dynamic result rendering and styling.
Batch CLI
cmd/simili/commands/batch.go, cmd/simili/commands/batch_test.go
New simili batch command: load issues JSON, worker-pool parallel pipeline execution (dry-run), duplicate-chain resolution, JSON/CSV outputs, config overrides, and extensive tests for loading and formatting.
Pipeline Runner API
cmd/simili/commands/pipeline_runner.go
Extracted and exported ExecutePipeline(...) to run a pipeline with a silent mode; adjusted run flow to return results/errors from the new API.
Core Types
internal/core/pipeline/pipeline.go
Added Body to SimilarIssue and DuplicateReason to Result to carry full-text and LLM reasoning through pipeline results.
Duplicate Detection & Similarity
internal/integrations/gemini/llm.go, internal/integrations/gemini/prompts.go, internal/steps/duplicate_detector.go, internal/steps/similarity.go
Include full issue bodies in LLM inputs; prompt rewritten to better distinguish DUPLICATE vs RELATED, raise duplicate confidence threshold (0.85), store LLM reasoning in results, and make DuplicateResult.SimilarIssues a flexible json.RawMessage.

Sequence Diagram

sequenceDiagram
    participant Browser
    participant WebServer as Web Server
    participant Config as Config Loader
    participant Deps as Dependencies
    participant Pipeline as Pipeline Executor
    participant Qdrant as Qdrant Vector DB
    participant Gemini as Gemini LLM
    participant Response as Response Builder

    Browser->>WebServer: POST /api/analyze (IssueRequest)
    activate WebServer

    WebServer->>Config: Load .simili.yaml and env overrides
    Config-->>WebServer: Config
    WebServer->>Deps: Initialize embedder, vector store, LLM (dry-run)
    Deps-->>WebServer: Dependencies ready

    WebServer->>Pipeline: ExecutePipeline(issue, cfg, deps, steps..., silent=true)
    activate Pipeline

    Pipeline->>Qdrant: Search similar issues
    Qdrant-->>Pipeline: Similar issues + metadata
    Pipeline->>Gemini: Duplicate analysis (includes bodies)
    Gemini-->>Pipeline: DuplicateResult + reasoning

    Pipeline-->>WebServer: Pipeline.Result
    deactivate Pipeline

    WebServer->>Response: Build AnalysisResponse JSON
    Response-->>WebServer: Response
    WebServer-->>Browser: 200 OK + AnalysisResponse
    deactivate WebServer
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

  • simili-bot#34: Implements the requested simili batch CLI and extracts pipeline execution into ExecutePipeline, matching the issue's objectives.

Poem

🐰 I hopped through code and stitched a flow,

Bodies and reasons now ready to show,
Batches march onward, the web listens too,
Qdrant hums softly and Gemini knew,
Pipelines sing — hooray! — a rabbit-made view.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.95% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add batch CLI and web UI for issue analysis' accurately and concisely summarizes the main changes in the pull request, covering both primary additions: the Batch CLI command and Web UI feature.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/cli-issue-test

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
cmd/simili-web/main.go (5)

95-96: Ignored error from fs.Sub could mask embed issues.

The error from fs.Sub is discarded with a blank identifier. If the "static" subdirectory doesn't exist in the embedded filesystem, the server will silently fail to serve static files.

Proposed fix
-	staticFS, _ := fs.Sub(staticFiles, "static")
+	staticFS, err := fs.Sub(staticFiles, "static")
+	if err != nil {
+		log.Fatalf("Failed to access embedded static files: %v", err)
+	}
 	http.Handle("/", http.FileServer(http.FS(staticFS)))

267-271: Use errors.Is() for sentinel error comparison.

Direct comparison with != may fail if the error is wrapped. Use errors.Is() for reliable sentinel error checks.

Proposed fix
+import "errors"
+
 	if err := builtPipeline.Run(pCtx); err != nil {
-		if err != pipeline.ErrSkipPipeline {
+		if !errors.Is(err, pipeline.ErrSkipPipeline) {
 			return nil, err
 		}
 	}

183-192: Missing HTTP status code for JSON decode errors.

When JSON decoding fails, the response is written with status 200 (default) but contains an error payload. Consider setting an appropriate 4xx status code for client errors.

Proposed fix
 	var req IssueRequest
 	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
+		w.WriteHeader(http.StatusBadRequest)
 		if encErr := json.NewEncoder(w).Encode(AnalysisResponse{
 			Success: false,
 			Error:   "Invalid JSON: " + err.Error(),

194-203: Missing HTTP status code for validation errors.

Similar to the JSON decode error, validation failures return status 200 with an error payload. Setting a 4xx status improves API semantics.

Proposed fix
 	// Validate required fields
 	if req.Title == "" {
+		w.WriteHeader(http.StatusBadRequest)
 		if err := json.NewEncoder(w).Encode(AnalysisResponse{
 			Success: false,
 			Error:   "Title is required",

228-236: Pipeline errors should return 5xx status.

Internal pipeline errors currently return status 200 with an error payload. A 500 status would be more appropriate for server-side failures.

Proposed fix
 	// Run pipeline
 	result, err := runPipeline(issue)
 	if err != nil {
+		w.WriteHeader(http.StatusInternalServerError)
 		if encErr := json.NewEncoder(w).Encode(AnalysisResponse{
 			Success: false,
 			Error:   "Pipeline error: " + err.Error(),
cmd/simili-web/static/app.js (1)

111-113: Potential NaN display if Similarity is missing.

If an issue object lacks the Similarity field (undefined), multiplying by 100 yields NaN, displaying "NaN%" to users. Consider defensive handling.

Proposed fix
         issues.forEach(issue => {
-            const score = (issue.Similarity * 100).toFixed(1);
+            const score = ((issue.Similarity || 0) * 100).toFixed(1);
             const stateClass = issue.State === 'open' ? 'status-open' : 'status-closed';
cmd/simili/commands/batch.go (2)

340-350: Redundant nil check on geminiKey.

The check if geminiKey != "" on line 341 is always true because lines 288-290 already return an error if geminiKey is empty. This conditional can be removed.

Proposed fix
 	// Initialize LLM Client
-	if geminiKey != "" {
-		llm, err := gemini.NewLLMClient(geminiKey)
-		if err != nil {
-			return nil, fmt.Errorf("failed to initialize Gemini LLM client: %w", err)
-		}
-		deps.LLMClient = llm
-		if verbose {
-			fmt.Println("✓ Initialized Gemini LLM client")
-		}
+	llm, err := gemini.NewLLMClient(geminiKey)
+	if err != nil {
+		return nil, fmt.Errorf("failed to initialize Gemini LLM client: %w", err)
+	}
+	deps.LLMClient = llm
+	if verbose {
+		fmt.Println("✓ Initialized Gemini LLM client")
 	}

101-103: Consider logging instead of printing warning for flag marking failure.

The MarkFlagRequired error is printed but execution continues. In practice, this error should never occur with valid flag names, but logging rather than printing would be more consistent.

Proposed fix
+import "log"
+
 	if err := batchCmd.MarkFlagRequired("file"); err != nil {
-		fmt.Printf("Warning: Failed to mark file flag as required: %v\n", err)
+		log.Printf("Warning: Failed to mark file flag as required: %v", err)
 	}

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Comment @coderabbitai help to get the list of available commands and usage tips.

@Kavirubc Kavirubc added the enhancement New feature or request label Feb 10, 2026
@Kavirubc
Copy link
Copy Markdown
Contributor Author

Closes #34
Closes #35

This PR implements both the batch CLI processing feature (#34) and the web dashboard for dry-run analysis (#35).

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/steps/duplicate_detector.go (1)

94-98: ⚠️ Potential issue | 🟠 Major

Align code default with LLM prompt threshold.

The LLM prompt in internal/integrations/gemini/prompts.go line 309 instructs the model to use a 0.85 confidence threshold ("ONLY set is_duplicate to true if confidence >= 0.85"), but the code default in internal/steps/duplicate_detector.go line 97 and internal/core/config/config.go line 226 falls back to 0.8. Update the default to 0.85 to match the prompt guidance.

🤖 Fix all issues with AI agents
In `@cmd/simili-web/main.go`:
- Around line 160-163: The JSON encoding calls in handlers like handleHealth
(and the other handlers around lines referenced) ignore errors; update each
json.NewEncoder(w).Encode(...) to capture its returned error, and if non-nil
respond with an appropriate HTTP error and log the failure (e.g., using
log.Printf or the existing logger) before returning. Specifically, in
handleHealth and the handlers that call json.NewEncoder(w).Encode (the ones
noted in the comment), assign the result to err, check if err != nil, write an
http.Error (or set proper status and message), and log the encoding error with
contextual info including the handler name.
- Around line 105-107: The Println call that outputs the stop message includes
an explicit trailing newline which is redundant and triggers go vet; update the
output in main (the fmt.Println("   Press Ctrl+C to stop\n") statement) to
remove the trailing "\n" (either use fmt.Println("   Press Ctrl+C to stop") or
fmt.Print without the extra newline) so that only one newline is emitted; ensure
you modify the fmt.Println invocation near the port/collection prints (the lines
that call fmt.Printf for port and cfg.Qdrant.Collection) to resolve the CI/vet
failure.

In `@cmd/simili-web/static/app.js`:
- Around line 116-123: The issue is that raw issue.URL values are inserted into
the href and can be crafted (e.g., javascript:) to cause XSS; add a helper
function named sanitizeUrl (placed near the existing escapeHtml helper) that
parses the URL with new URL(url, window.location.origin), returns parsed.href
only if parsed.protocol is 'http:' or 'https:', and otherwise returns '#'
(catching parse errors and returning '#'); then replace the template insertion
of ${issue.URL} in the similar-issue anchor with a call to
sanitizeUrl(issue.URL) so only whitelisted http/https links are used as hrefs.

In `@cmd/simili-web/static/index.html`:
- Around line 89-91: The external anchor element that opens in a new tab (the
<a> element with text "Simili Bot" and attribute target="_blank") should include
rel="noopener noreferrer" to prevent tabnabbing and ensure safe behavior; update
that anchor tag to add the rel attribute with both noopener and noreferrer
values while keeping the existing href and target attributes unchanged.

In `@cmd/simili/commands/batch.go`:
- Around line 222-246: The parameter name in loadIssues(filepath string) shadows
the imported path/filepath package; rename the parameter (for example to
filePath, path, inputPath, or filename) and update all references inside
loadIssues to the new name so the function no longer conflicts with the filepath
package and future uses of filepath.Join/etc. will compile correctly.
🧹 Nitpick comments (6)
README.md (1)

165-168: Add language specifier to fenced code block.

The code block is missing a language specifier. Since this shows shell output, consider adding bash or text as the language.

📝 Proposed fix
-```
+```bash
 # 4. Review results
 cat analysis.csv
</details>

</blockquote></details>
<details>
<summary>cmd/simili-web/README.md (1)</summary><blockquote>

`90-112`: **Consider documenting the `Body` field in the API response.**

The `SimilarIssue` struct now includes a `Body` field (per changes in `internal/core/pipeline/pipeline.go`), but it's not shown in the example response. If the API exposes this field, consider adding it to the example for completeness.

</blockquote></details>
<details>
<summary>cmd/simili-web/static/styles.css (1)</summary><blockquote>

`96-185`: **Add explicit focus-visible styles for keyboard accessibility.**  
Hover styles are present, but focus indicators aren’t defined; adding them improves keyboard navigation without altering visual design for mouse users.  

<details>
<summary>Suggested CSS</summary>

```diff
+button[type="submit"]:focus-visible,
+.similar-title a:focus-visible,
+footer a:focus-visible {
+    outline: 2px solid `#fff`;
+    outline-offset: 2px;
+}
cmd/simili/commands/batch_test.go (1)

163-190: Reset package-level flags to avoid cross-test leakage.
These tests mutate global flags; restoring them with t.Cleanup prevents state bleed into other tests in this package.

Suggested change
		t.Run(tt.name, func(t *testing.T) {
+			prevCollection := batchCollection
+			prevThreshold := batchThreshold
+			prevDuplicate := batchDuplicateThresh
+			prevTopK := batchTopK
+			t.Cleanup(func() {
+				batchCollection = prevCollection
+				batchThreshold = prevThreshold
+				batchDuplicateThresh = prevDuplicate
+				batchTopK = prevTopK
+			})
+
			// Set global flags
			batchCollection = tt.collection
			batchThreshold = tt.threshold
			batchDuplicateThresh = tt.duplicateThresh
			batchTopK = tt.topK
cmd/simili/commands/batch.go (2)

296-299: Verbose log may show empty model name.

When cfg.Embedding.Model is not specified in the config, this log will print an empty string, even though NewEmbedder internally defaults to "text-embedding-004". This could confuse users running with --verbose.

💡 Proposed fix
 deps.Embedder = embedder
 if verbose {
-	fmt.Printf("✓ Initialized Gemini Embedder with model: %s\n", cfg.Embedding.Model)
+	model := cfg.Embedding.Model
+	if model == "" {
+		model = "text-embedding-004" // default
+	}
+	fmt.Printf("✓ Initialized Gemini Embedder with model: %s\n", model)
 }

340-350: Redundant nil check for geminiKey.

The check if geminiKey != "" on line 341 is always true at this point, since lines 288-290 already return an error if geminiKey is empty.

🧹 Proposed fix
 // Initialize LLM Client
-if geminiKey != "" {
-	llm, err := gemini.NewLLMClient(geminiKey)
-	if err != nil {
-		return nil, fmt.Errorf("failed to initialize Gemini LLM client: %w", err)
-	}
-	deps.LLMClient = llm
-	if verbose {
-		fmt.Println("✓ Initialized Gemini LLM client")
-	}
+llm, err := gemini.NewLLMClient(geminiKey)
+if err != nil {
+	return nil, fmt.Errorf("failed to initialize Gemini LLM client: %w", err)
+}
+deps.LLMClient = llm
+if verbose {
+	fmt.Println("✓ Initialized Gemini LLM client")
 }

Comment thread cmd/simili-web/main.go Outdated
Comment thread cmd/simili-web/main.go
Comment on lines +160 to +163
func handleHealth(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Check Encode errors to satisfy errcheck and improve reliability.
Lint currently fails because JSON encoding errors are ignored. Handle or log the errors in both handlers.

Proposed fix (apply pattern to all Encode calls)
-	json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
+	if err := json.NewEncoder(w).Encode(map[string]string{"status": "ok"}); err != nil {
+		log.Printf("encode health response failed: %v", err)
+	}
-		json.NewEncoder(w).Encode(AnalysisResponse{
+		if err := json.NewEncoder(w).Encode(AnalysisResponse{
 			Success: false,
 			Error:   "Invalid JSON: " + err.Error(),
-		})
+		}); err != nil {
+			log.Printf("encode analyze error response failed: %v", err)
+		}

Also applies to: 182-187, 192-196, 223-227, 231-242

🧰 Tools
🪛 GitHub Check: Lint

[failure] 162-162:
Error return value of (*encoding/json.Encoder).Encode is not checked (errcheck)

🤖 Prompt for AI Agents
In `@cmd/simili-web/main.go` around lines 160 - 163, The JSON encoding calls in
handlers like handleHealth (and the other handlers around lines referenced)
ignore errors; update each json.NewEncoder(w).Encode(...) to capture its
returned error, and if non-nil respond with an appropriate HTTP error and log
the failure (e.g., using log.Printf or the existing logger) before returning.
Specifically, in handleHealth and the handlers that call
json.NewEncoder(w).Encode (the ones noted in the comment), assign the result to
err, check if err != nil, write an http.Error (or set proper status and
message), and log the encoding error with contextual info including the handler
name.

Comment thread cmd/simili-web/static/app.js
Comment thread cmd/simili-web/static/index.html
Comment thread cmd/simili/commands/batch.go
Fix all issues identified by CodeRabbit review and CI checks:

1. CI/Vet: Remove redundant newline in fmt.Println
   - Line 107 already adds newline, extra \n triggered go vet

2. Errcheck: Handle JSON encoding errors in all handlers
   - Added error checking for all json.Encode() calls
   - Log errors instead of silently ignoring them

3. Security: Sanitize URLs before injecting into href attributes
   - Added sanitizeUrl() function to whitelist http(s) protocols
   - Prevents XSS via javascript: URLs
   - Also added rel="noopener noreferrer" to external links

4. Code quality: Fix parameter shadowing in loadIssues
   - Renamed filepath -> filePath to avoid shadowing imported package

All CI checks should now pass.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[0.1.5v][Feature]: Simple Web Dashboard for Dry run [0.1.5v] Batch Issue Processing CLI

1 participant