feat(trail): add --debug-dir to tune for inspecting prompt and response · Entire

feat(trail): add --debug-dir to tune for inspecting prompt and response

5555d40→main·

Soph·3w ago·2 files·+48 added/-2 removed

`entire trail tune --debug-dir

` writes the assembled prompt (prompt.txt)
and, in --run mode, the raw model response (response.txt) to . This makes
it possible to debug why a runner was skipped or tailored oddly: prompt.txt
shows exactly what signal the model received (the gathered-context block),
response.txt shows exactly what it returned before validation/parsing. Writes
are best-effort — failures warn rather than abort the run.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

Sessions

7a31299a7258View transcript

Changes

2

  • cmd/entire/cli

  • Mtrail_tune_cmd.go+29/-2

  • Mtrail_tune_init_test.go+19

18 unmodified lines

19
20
21
22
23
24
25
3 unmodified lines

29
30
31
32
33
34
35
27 unmodified lines

63
64
65
66
67
68
69
8 unmodified lines

78
79
80
81
82
83
84
85
25 unmodified lines

111
112
113
114
115
116
117
118
119
120
3 unmodified lines

124
125
126
118
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
1 unmodified line

147
148
149
126
150
151
152
153
16 unmodified lines

170
171
172
173
174
175
176
177
178

18 unmodified lines

runner       string // optional: limit to one runner (id, with or without "trail-")
    run          bool   // headless apply vs. print prompt
    assumeYes    bool   // skip the create-defaults confirmation
    debugDir     string // if set, dump prompt.txt (+ response.txt on --run) here
    sources      []string
    limit        int
    insecureHTTP bool
3 unmodified lines

var (
        run       bool
        assumeYes bool
        debugDir  string
        sources   []string
        limit     int
    )
27 unmodified lines

runner:       runner,
            run:          run,
            assumeYes:    assumeYes,
            debugDir:     debugDir,
            sources:      sources,
            limit:        limit,
            insecureHTTP: trailInsecureHTTP(cmd),
8 unmodified lines

cmd.Flags().IntVar(&limit, "limit", 20, "How many recent PRs/issues/trails to sample")
    cmd.Flags().BoolVarP(&assumeYes, "yes", "y", false,
        "Skip the confirmation when creating the default runner set in a repo that has none")
    cmd.Flags().StringVar(&debugDir, "debug-dir", "",
        "Write the assembled prompt (prompt.txt) and, with --run, the raw model response (response.txt) to this directory for debugging")

return cmd
}
25 unmodified lines

brief := gatherTuningContext(ctx, errW, repoRoot, src, opts.limit, opts.insecureHTTP)
    prompt := buildTunePrompt(brief, runners)

if opts.debugDir != "" {
        writeTuneDebug(errW, opts.debugDir, "prompt.txt", prompt)
    }

if !opts.run {
        fmt.Fprintln(w, prompt)
        if len(created) > 0 {
3 unmodified lines

return nil
    }

return applyTuneWithAgent(ctx, w, errW, runners, prompt, created)
    return applyTuneWithAgent(ctx, w, errW, runners, prompt, created, opts.debugDir)
}

// writeTuneDebug best-effort writes content to <dir>/<name> for debugging,
// reporting any failure as a warning rather than failing the command.
func writeTuneDebug(errW io.Writer, dir, name, content string) {
    if err := os.MkdirAll(dir, 0o755); err != nil { //nolint:gosec // user-specified debug dir
        fmt.Fprintf(errW, "warning: debug dir %s: %v\n", dir, err)
        return
    }
    path := filepath.Join(dir, name)
    if err := os.WriteFile(path, []byte(content), 0o644); err != nil { //nolint:gosec // local debug artifact
        fmt.Fprintf(errW, "warning: writing %s: %v\n", path, err)
        return
    }
    fmt.Fprintf(errW, "debug: wrote %s\n", path)
}

// applyTuneWithAgent runs the prompt through the configured summary provider
1 unmodified line

// surgically rewrites each runner file's prompt.template in place. createdIDs
// are runners onboarding just scaffolded from defaults; any of those left
// un-tailored is flagged so it isn't committed as if it were repo-specific.
func applyTuneWithAgent(ctx context.Context, w, errW io.Writer, runners []tuneRunner, prompt string, createdIDs []string) error {
func applyTuneWithAgent(ctx context.Context, w, errW io.Writer, runners []tuneRunner, prompt string, createdIDs []string, debugDir string) error {
    // Reuse the summary-provider resolution (selection + persistence), but pull
    // the raw TextGenerator rather than provider.Generator: the latter is a
    // summarize.Generator that turns a transcript Input into a checkpoint
16 unmodified lines

if err != nil {
        return fmt.Errorf("agent run failed: %w", err)
    }
    if debugDir != "" {
        writeTuneDebug(errW, debugDir, "response.txt", out)
    }

templates, err := parseTuneOutput(out)
    if err != nil {