inspect: accept runner-style structured trail findings · Entire
inspect: accept runner-style structured trail findings
956ae3b→main·
dipree·4w ago·4 files·+209 added/-15 removed
Use the existing Trail PR Review runner output shape as the preferred trail posting format: if the judge output ends with a JSON object containing comments, convert those comments directly to native trail review findings, preserving severity, confidence, and line/range/file locations.
Keep the markdown fallback for custom or human-readable prompts, but enrich split bullets with inferred severity and file:line anchors when possible. Also nudge the judge prompt to put one issue per bullet with severity and file:line pointers so trail output is cleaner even before the fallback runs.
Sessions
77524f2a0762View transcript
Changes
4
cmd/entire/cli
review
Msynthesis_prompt.go+1/-1
Mreview_bridge.go+165/-5
Mreview_bridge_test.go+39/-5
Mtrail_review_cmd.go+4/-4
80 unmodified lines
Output exactly this, nothing else:
- One line: the verdict (approve / approve with nits / request changes) and a one-sentence reason.
- Then a short bullet list of actionable findings, most important first, one issue per bullet, one line each with a file/symbol pointer. Omit the list entirely when nothing is actionable.
- Then a short bullet list of actionable findings, most important first, one issue per bullet, one line each. Start each bullet with [high], [medium], or [low], and include a file:line pointer when you can identify one. Omit the list entirely when nothing is actionable.
No preamble, no section headings, no restating the diff or task, no filler. Be proportional: a clean change is a single line.`)
Mcmd/entire/cli/review/synthesis_prompt.go+1/-1
8 unmodified lines
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"regexp"
"strconv"
"strings"
"github.com/entireio/cli/cmd/entire/cli/agent"
5 unmodified lines
reviewtypes "github.com/entireio/cli/cmd/entire/cli/review/types"
)
const (
reviewTrailGranularityWholeChange = "whole_change"
reviewTrailGranularityFile = "file"
reviewTrailGranularityLine = "line"
reviewTrailGranularityRange = "range"
)
// buildReviewDeps builds the review.Deps struct used by review.NewCommand.
func buildReviewDeps() cliReview.Deps {
return cliReview.Deps{
}
}
// reviewTrailFindingInputs turns a final review verdict into trail findings. If
// the verdict contains multiple top-level bullet findings, post them separately
// so a custom or weak judge prompt cannot create one mega-finding on the trail.
// reviewTrailFindingInputs turns a final review verdict into trail findings.
// It first accepts the runner-style last JSON line format
// {"summary":"","comments":[...]}; when absent, it falls back to splitting
// top-level markdown bullets. This keeps trail output structurally correct even
// when custom judge prompts produce prose.
func reviewTrailFindingInputs(profileName, verdict string) []api.TrailReviewCommentInput {
if inputs, ok := reviewTrailFindingInputsFromJSON(verdict); ok {
return inputs
}
items := splitReviewVerdictFindings(verdict)
if len(items) <= 1 {
return []api.TrailReviewCommentInput{reviewTrailFindingInput(profileName, verdict)}
}
inputs := make([]api.TrailReviewCommentInput, 0, len(items))
for _, item := range items {
inputs = append(inputs, reviewTrailFindingInputWithKind(profileName, item, "finding"))
input := reviewTrailFindingInputWithKind(profileName, item, "finding")
enrichReviewTrailFindingInputFromMarkdown(&input, item)
inputs = append(inputs, input)
}
return inputs
}
func reviewTrailFindingInputWithKind(profileName, text, kind string) api.TrailReviewCommentInput {
body := strings.TrimSpace(text)
return api.TrailReviewCommentInput{
ClientID: generateTrailReviewClientID(),
Body: stringPtr(body),
Location: api.TrailReviewLocationCreateRequest{Granularity: reviewTrailGranularityWholeChange},
}
}
// test functions here...