# trail: hydrate selected text for line findings

## Sessions

5c43253dac13View transcript

## Changes

4

- cmd/entire/cli

- Mreview_bridge.go+14/-7

- Mreview_bridge_test.go+4/-1

- Mtrail_review_cmd.go+91

- Mtrail_review_cmd_test.go+76

```
163 unmodified lines

163 unmodified lines

}

func reviewTrailLocationFromJSON(loc reviewTrailJSONLocation) api.TrailReviewLocationCreateRequest {
	filePath := strings.TrimSpace(loc.FilePath)
	withSelectedText := func(req api.TrailReviewLocationCreateRequest) api.TrailReviewLocationCreateRequest {
		if strings.TrimSpace(loc.SelectedText) != "" {
			req.SelectedText = stringPtr(loc.SelectedText)
		}
		return req
	}
	switch strings.ToLower(strings.TrimSpace(loc.Granularity)) {
	case reviewTrailGranularityLine:
		if filePath != "" && loc.StartLine > 0 {
			return api.TrailReviewLocationCreateRequest{Granularity: reviewTrailGranularityLine, FilePath: stringPtr(filePath), StartLine: &loc.StartLine}
			return withSelectedText(api.TrailReviewLocationCreateRequest{Granularity: reviewTrailGranularityLine, FilePath: stringPtr(filePath), StartLine: &loc.StartLine})
		}
	case reviewTrailGranularityRange:
		if filePath != "" && loc.StartLine > 0 && loc.EndLine > loc.StartLine {
			return api.TrailReviewLocationCreateRequest{Granularity: reviewTrailGranularityRange, FilePath: stringPtr(filePath), StartLine: &loc.StartLine, EndLine: &loc.EndLine}
			return withSelectedText(api.TrailReviewLocationCreateRequest{Granularity: reviewTrailGranularityRange, FilePath: stringPtr(filePath), StartLine: &loc.StartLine, EndLine: &loc.EndLine})
		}
		if filePath != "" && loc.StartLine > 0 {
			return api.TrailReviewLocationCreateRequest{Granularity: reviewTrailGranularityLine, FilePath: stringPtr(filePath), StartLine: &loc.StartLine}
			return withSelectedText(api.TrailReviewLocationCreateRequest{Granularity: reviewTrailGranularityLine, FilePath: stringPtr(filePath), StartLine: &loc.StartLine})
		}
	case reviewTrailGranularityFile:
		if filePath != "" {

Mcmd/entire/cli/review_bridge.go+14/-7

```
109 unmodified lines

109 unmodified lines

func TestReviewTrailFindingInputsAcceptsRunnerStyleJSONLastLine(t *testing.T) {
	verdict := `Intermediate prose that should be ignored for posting.
{"summary":"","comments":[{"severity":"high","confidence":0.92,"body":"` + "`" + `daytona.ts` + "`" + ` rejects public repos without a token; allow public clones or mint a token.","location":{"granularity":"line","file_path":"daytona.ts","start_line":901}},{"severity":"P2","confidence":0.7,"body":"Delete failures are swallowed, orphaning provider snapshots.","location":{"granularity":"range","file_path":"daytona.ts","start_line":966,"end_line":970}}]}`
	inputs := reviewTrailFindingInputs("general", verdict)
	if len(inputs) != 2 {

if inputs[0].Location.Granularity != reviewTrailGranularityLine || inputs[0].Location.FilePath == nil || *inputs[0].Location.FilePath != "daytona.ts" || inputs[0].Location.StartLine == nil || *inputs[0].Location.StartLine != 901 {
	
t.Fatalf("location[0] = %+v, want daytona.ts:901", inputs[0].Location)
	}
	if inputs[0].Location.SelectedText == nil || *inputs[0].Location.SelectedText != "return err" {
	
t.Fatalf("selected_text[0] = %v, want preserved JSON selected_text", inputs[0].Location.SelectedText)
	}
	if inputs[1].Severity == nil || *inputs[1].Severity != "medium" {
	
t.Fatalf("severity[1] = %v, want normalized medium", inputs[1].Severity)
	}
}

func TestPrepareTrailReviewCommentInputsForCreateDowngradesUnselectableLine(t *testing.T) {
	// Testing prepared inputs downgrades unselectable line.
}

func TestCreateTrailReviewFindingSurfacesBatchError(t *testing.T) {
	// Testing batch error surfaces.
}
