Skip to content

simulate(tui): in-TUI scenario save (no overwrite) + copy-to-clipboard; drop export-scenarios subcommand#867

Open
theomonnom wants to merge 34 commits into
mainfrom
theo/sim-tui-feedback
Open

simulate(tui): in-TUI scenario save (no overwrite) + copy-to-clipboard; drop export-scenarios subcommand#867
theomonnom wants to merge 34 commits into
mainfrom
theo/sim-tui-feedback

Conversation

@theomonnom

Copy link
Copy Markdown
Member

No description provided.

…erwrite), copy scenario to clipboard, print generated scenarios path on exit
…n/jobIconStylePtr/jobIcon) into one jobStatusIcon
- Pre-flight: reuse agentfs.CheckSDKVersion (pinned to 1.6.0, the thin-CLI baseline) in startAgent so start/dev/console/simulate fail fast with a clear 'too old, upgrade to ...' instead of a cryptic subprocess error.
- On early exit / failed register/connect, surface the agent's OWN output (the real error) plus the full log path - no string-match guessing of the cause. Wired into simulate (CI + TUI) and console.

Verified against staging with a broken .venv (shows the ModuleNotFoundError) and an old declared SDK (shows the upgrade message).
The agent logs in colored format for the TUI; the temp log file kept the
raw escape sequences.
The header listed every scenario label (bare bullets when labels are
empty) and the job list rendered them all again. Replace it with one
line: '<check> Loaded N scenarios from <file>  <group name>' — the group
name only when set.
'Loaded N scenarios from <file> — <name>' renders as the first (already
done) step in file mode, alongside Starting agent / Creating simulation,
instead of a separate header line.
Log lines were stripped of ANSI codes at scanner ingest, so the TUI
rendered everything colorless. Keep raw lines in memory (bubbletea/
lipgloss render ANSI fine) and strip only where plain text is needed:
the log file, fatal-marker matching, surfaced error excerpts, and CI
stdout.
…e/copy

- agentLauncher owns the agent subprocess around the TUI: a fast ctrl+c
  used to quit before agentStartedMsg was delivered, leaking the worker
  and breaking the next run with "address already in use"
- always save a plain-text run report (the non-TUI output: job results,
  transcripts, room logs, summary) to a temp file, like the agent log
- save scenarios moves to the s key; the prompt is a bordered dialog and
  copy/save confirmations show as a transient toast instead of a bare
  footer line
- drop the duplicated description hint from the footer (the collapsed
  block already says "press d to expand")
q during an active run now asks before cancelling the simulation, so a
misclick can't kill it. y/enter confirms, any other key dismisses;
ctrl+c stays an immediate exit.
The stop-simulation prompt is now a two-button dialog (arrows/tab to
select, enter to confirm, esc to dismiss) defaulting to keep running.
y still confirms directly.
The report was a snapshot of the final results. Replace it with a
runReporter that records the same lines the non-TUI mode prints as the
run progresses (setup steps, run id, generating/running/summarizing
transitions, job progress), then appends the results section on exit.
simLog is now the single source of every non-TUI output line (setup
steps, GitHub group markers, status transitions, results): CI writes it
to the terminal and the TUI's runReporter writes the same calls to the
report file, so the two can't drift.

Exit was slow because Kill gave the worker 5s of SIGINT grace, which a
draining worker never meets; and a second ctrl+c during that window
killed the CLI before SIGKILL, leaking the worker with its port bound.
Shorten the grace to 1s, wait for the post-SIGKILL exit so the port is
free before returning, and ignore SIGINT during TUI cleanup.
A second ctrl+c during cleanup now SIGKILLs the worker and exits
instead of being ignored, so a slow shutdown can still be broken out of
without leaking the worker.

writeChatHistory still wrote to stdout after gaining its writer param,
so transcripts never reached the report file; also drop the 80-char
truncation of tool args/outputs so the report is complete. Rename the
CI simLog var (shadowed log/slog), remove the duplicated agent-logs
line, and trim comments.
Transliterate output glyphs at the writer level so the report file has
no special characters while simLog stays the single source of the
strings. Route the Finish trailer through the same writer.
# Conflicts:
#	cmd/lk/simulate_ci.go
#	cmd/lk/simulate_tui.go
- staticcheck QF1012: fmt.Fprintf(&b, ...) over WriteString(Sprintf)
- drop the gh/plain output split and isGitHubActions gating: group
  markers are a useful delimiter everywhere, and job ids now appear in
  the group titles
- agent health: tolerate 3 not-joined timeouts, require 2 fatal log
  markers (a single one can be an isolated job crash), name the marker
  list pythonFatalMarkers (JS will need its own)
- open the log pane automatically when the agent is detected broken
- prune obvious comments
Comment thread cmd/lk/simulate_ci.go Outdated
}
if config.mode == modeGenerateFromSource && run != nil {
if path, err := writeGeneratedScenariosTemp(run); err == nil && path != "" {
fmt.Fprintf(os.Stderr, "Generated scenarios: %s\n", path)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All print statements should use the new Printer interface. There is a global out instance of it with helpers for debug messages (out.Status(...)) and command output (out.Result(...)). This helps us manage output, respect the --quiet flag, and keep random stuff from cluttering stdout.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done: all simulate prints now go through out — breadcrumbs via Status/Statusf (silenced by --quiet), results and the gh ::error:: annotations via Resultf, the broken-agent note on out.Err (warning-class, never quieted). For the writer-based streaming (simLog, agent-startup log forwarding) I added Printer.StatusWriter(), which returns io.Discard under --quiet.

All direct stdout/stderr prints in the simulate flows now go through
the global Printer: breadcrumbs via Status (silenced by --quiet),
results and gh annotations via Result, the broken-agent note on Err.
simLog takes out.Out and the new Printer.StatusWriter(), which returns
io.Discard under --quiet for writer-based streaming.
WarnWriter and ResultWriter join StatusWriter so streaming code gets
the same gating as the print methods, without reaching into the
Printer's fields.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants