Features
-
analyze: Add --code filter to code subcommand (4bfc339)
--coderestricts the result to the given diagnostic codes (e.g.
KeywordNotFound), repeatable and comma-separated, matched
case-insensitively like the modifiers. Unlike-mi "*"+ re-include, it
filters without changing the severity of what remains. It affects the
output, summary and exit code, and combines with --severity using AND. -
analyze: Add --severity filter to code subcommand (f565c16)
--severityrestricts the analysis result to the listed severities
(repeatable and comma-separated; error/warn/info/hint). Filtered-out
severities are dropped from the output, the summary counts and the exit
code alike, so all three stay consistent. It's orthogonal to
--exit-code-mask (which only masks the exit code) and complements the
diagnostic modifiers (which remap rather than filter). -
analyze: Add SARIF, GitHub and GitLab output formats (7103836)
robotcode analyze codegains a local--output-formatflag (overrides
the global--formatfor this command) with these values:-
concise(default): the human-readable text output -
json/json-indent: structured result (diagnostics + summary) -
sarif: SARIF 2.1.0 log for GitHub code scanning and other consumers -
github: GitHub Actions workflow annotations (::error file=...) -
gitlab: GitLab Code Quality report (JSON array)
--output-file FILEwrites the report to a file instead of stdout (for
the json/json-indent/sarif/github/gitlab formats), which is handy for CI
artifact upload. A missing target directory raises a clear UsageError and
other I/O errors surface as a ClickException instead of a traceback.Mapping details shared across the machine formats:
- LSP 0-based ranges become the 1-based positions SARIF/GitHub expect
- severities collapse onto each format's levels (e.g. SARIF error/warning/
note, GitHub error/warning/notice, GitLab major/minor/info) - artifact paths are POSIX and relative to the project root (what the CI
integrations expect);--full-pathsswitches to absolute paths - SARIF and GitLab results carry a stable fingerprint (independent of line
number) so alerts survive unrelated edits - GitHub property/message values are escaped per the @actions/toolkit rules
-
-
analyze: Add JSON output and --full-paths to code subcommand (fc76cf3)
robotcode --format json analyze code(and--format json_indent) now
emit a structured result instead of falling back to plain text:-
diagnostics: a map of source path to LSP diagnostics, using the same
shape as thediscover/resultscommands so editor and CI integrations
can reuse their parsers. Workspace-level diagnostics key on ".". -
summary: file count and per-severity totals.
The JSON always carries the full diagnostic message (tracebacks included);
--show-tracebacksonly affects the text output.New
--full-paths/--no-full-pathsflag (mirroringdiscover) switches
between root-relative and absolute paths in both text and JSON output.
JSON keys are always rendered POSIX-style for cross-platform stability. -
-
analyze: Polish code subcommand output (1049b79)
- Output is now sorted by (file, line, column) so warnings and errors
appear in source order instead of mixed by analyzer pass. - Severity is rendered as a full word, e.g.
[ERROR]instead of[E],
matching the convention from Robocop, ruff, mypy and friends. - Robot Framework's appended Python tracebacks and PYTHONPATH dumps are
no longer printed by default; the new--show-tracebacksflag opts
back into the full message. - Multi-line diagnostic messages (e.g.
MultipleKeywordslisting the
alternative names) are re-indented with a consistent prefix. - Related-information entries are prefixed with
->to set them apart
visually, and they fall back to(see related location)when Robot
Framework provides no secondary message.
- Output is now sorted by (file, line, column) so warnings and errors
-
cli: Detect GitHub Copilot agent sessions (dbc5603)
Adds two markers to the AI-agent auto-detection so terminal commands
invoked from Copilot get the same clean-output defaults (no color,
no pager, REPL plain backend) as sessions from Claude Code, Cursor,
Codex, and friends:- COPILOT_AGENT — set by VS Code Copilot Chat / agent mode in
terminals launched via run_in_terminal
(microsoft/vscode#311734). - COPILOT_AGENT_SESSION_ID — set on every shell command and MCP
server the standalone GitHub Copilot CLI spawns (>= 0.0.429).
- COPILOT_AGENT — set by VS Code Copilot Chat / agent mode in
-
cli: Adapt automatically to AI agent sessions (8b34a33)
When
robotcodeis invoked from inside an AI agent (Claude Code,
Cursor, Copilot CLI, OpenCode, Codex, Gemini, …) it now drops
coloured output, the pager, and the REPL's interactive prompt
features — so the agent sees clean line-by-line text instead of
ANSI escapes and popup ghosts.Explicit flags and the usual environment variables (
NO_COLOR,
FORCE_COLOR,ROBOTCODE_REPL_PLAIN,ROBOTCODE_REPL_BACKEND)
still override the detection.ROBOTCODE_NO_AI_AGENT=1opts out
when you want the full experience anyway;ROBOTCODE_FORCE_AI_AGENT=1
turns the agent-mode on for local repros. -
cli: Auto-detect when to emit colors, honor NO_COLOR and FORCE_COLOR (4bbf944)
ANSI escape codes no longer leak into piped output, files, log captures or
CI artefacts — colors are auto-disabled when stdout/stderr isn't a TTY.
The NO_COLOR and FORCE_COLOR environment variables are now respected.
stdout and stderr are decided independently, so warnings keep their colour
when stdout is piped but stderr is still on the terminal. Explicit--color
/--no-colorstill override everything. -
discover: Show a diagnostics summary, full list only on demand (4b96656)
robotcode discoverno longer prints Robot's parsing errors and warnings
by default. When a suite has parse issues, a compactDiagnosticssection
with the error/warning counts now appears after the statistics, separate
from the discovery statistics.Pass
--diagnosticsto list the full messages; they are printed before
the discovered results, with file paths shown the same project-relative
way as the rest of the output. The machine-readable JSON output keeps
including the full diagnostics regardless, so editors are unaffected. -
discover:
robotcode discoverTEXT output is now markdown (a7ef8bc)robotcode discoversubcommands now emit markdown for human
output. On a coloured TTY rich renders it to themed ANSI and
pages if needed; in a pipe (or with --no-color) the raw markdown
is emitted verbatim. JSON output is unchanged.- info renders as a field/value table.
- files, suites, tests, tasks emit as bullet lists; tags shows
one bullet per tag with nested tests/tasks when --tests / --tasks
is on. - all keeps the workspace → suites → tests tree as a nested
markdown list, each level indented two spaces. - Statistics blocks are markdown tables.
The generic markdown helpers used by results — md_table,
bold_status, path_paren, display_width, the search highlighter
— move fromresults/_render.pyto a shared
cli/_markdown.pyso both commands import them from one place.Same commit aligns the existing results renderer on the new
label convention: bold is reserved for entities (test/suite
/tag names, status); italic marks labels (Tags, Total,
Extracted, Summary, metadata keys);(path:line)references
are wrapped in inline-code spans so they read as code tokens. -
docs: Add interactive hero image carousel with responsive lightbox (edd6d22)
-
language-server: Use the SemanticModel for the "Create Keyword" and "Assign Result to Variable" code actions (6a3d5a3)
When the experimental SemanticAnalyzer is enabled, the "Create Keyword"
quick fix (offered for unknown keywords) and the "Assign keyword result
to variable" refactor read the keyword call's namespace, library entry
and assignment state from the SemanticModel instead of walking the AST
and re-resolving via ModelHelper. Output unchanged — covered by
dedicated equivalence test files for both code actions. -
language-server: Use the SemanticModel for the "Open Documentation" code action (0768c84)
When the experimental SemanticAnalyzer is enabled, the "Open Documentation"
code action reads the pre-resolved keyword data and SemanticTokens from
the model instead of looking the keyword up again on every request.
Output is unchanged — verified by the existing E2E suite under both paths
and a new equivalence test file. -
language-server: Use the SemanticModel for signature help (9415e86)
When the experimental SemanticAnalyzer is enabled, signature help reads
the pre-resolved keyword data from the SemanticModel instead of looking
the keyword up again on every request. Output is unchanged — verified by
running the existing regression suite under both paths and a dedicated
equivalence test file. -
repl: Suggest the setting-import aliases in tab-completion (6507af5)
Typing at the prompt now suggests
Library,Resource, andVariablesnext to the keywords, and completing their argument offers the same libraries, resources, and variable files asImport Library/Import Resource/Import Variables— so the Settings-style aliases are as discoverable as the keywords they stand for. Offered only at the interactive prompt, where they apply. -
repl: Make the interactive shell and debugger more consistent (1a11c80)
Several rough edges in the interactive shell and its command-line debugger are smoothed out, so it behaves consistently — both with the rest of Robot Framework and within itself:
-
Failures behave like a shell, not a debugger. A failing keyword prints its error and leaves you at the prompt; the debugger only steps in when asked for, and switching it off keeps your breakpoints so switching it back on picks up where you were. (
robotcode robot-debugis unchanged for debugging a real run.) -
Imports work like they do in a suite. Write
Library,Resource, orVariablesat the prompt just as under*** Settings ***; saved sessions keep that familiar layout. - The debugger speaks one language. Its commands and messages now follow one short, uniform style instead of a mix of phrasings and cryptic notes.
-
Failures behave like a shell, not a debugger. A failing keyword prints its error and leaves you at the prompt; the debugger only steps in when asked for, and switching it off keeps your breakpoints so switching it back on picks up where you were. (
-
repl: Add an interactive command-line debugger (8e62733)
Debug Robot Framework runs straight from the terminal — pause a run, see
where you are, inspect and change state, run keywords in the live context,
and step through execution, no editor required. It's the scriptable,
terminal-native counterpart to the VS Code extension's graphical debugger.-
Two ways in.
robotcode robot-debug <paths>(aliasrun-debug) runs a
real suite through the normal runner with the debugger attached — same
output, options and arguments asrobotcode robot, and the run keeps
streaming as you step, continue or detach.robotcode repl(aliasshell)
now has the debugger built in too, so breakpoints fire while you try
keywords at the prompt. -
Pause where you want. Line and keyword breakpoints (
--break login.robot:42,--break "Open Browser"), an embeddedBreakpointstep in
a.robotfile,--stop-on-entry, and breaking on failures (uncaught
failures by default, plus--break-on-all-exceptions,--break-on-failed-test
and--break-on-failed-suite). Every stop shows why, which keyword, and where. -
Step through it.
.step/.next/.return/.continue/.until, plus
.detach(stop debugging but let the run finish) and.abort(end it now). -
Inspect and change state. Walk the call stack (
.where/.up/.down/
.frame), list variables by scope (.vars), evaluate in the selected frame
(.print/.pprint/.whatis), auto-show expressions at every stop
(.display), set variables (.set), and run any keyword right at the prompt
in the paused context. -
Manage breakpoints live. List them and add conditional, one-shot,
logpoint or command-list breakpoints; set conditions, ignore N hits, delete,
and disable/enable by number (.breakpoints/.condition/.ignore/.delete/
.disable/.enable/.commands/.tbreak). Arm exception breakpoints on the
fly with.catch. -
Read source and docs in place.
.listshows the source at the stop,
.source <kw>a named keyword's definition; the full shell command set
(.kw,.doc,.imports,.save, …) works at the debug prompt too. On the
rich prompt these open in a scrollable full-screen viewer with search and
links; on the plain prompt they print inline. -
Built for humans and agents alike. Context-aware completion, syntax
highlighting, persistent history and multi-line editing on the rich prompt;
--plain(or--backend/ROBOTCODE_REPL_*) gives a bare prompt that reads
commands from stdin, and the rich prompt falls back to plain automatically on
piped input — so the debugger drives cleanly from scripts, CI or AI agents. - Long commands accept any unambiguous prefix; one-letter aliases mirror pdb.
-
Two ways in.
-
repl: Browse and search keywords from .kw (a884736)
.kwdoes more than show a single keyword now. With no argument it
lists every keyword you have imported, grouped by the library or
resource it comes from. With text that isn't an exact keyword name it
lists the keywords whose name contains that text, so you can find a
keyword without remembering its full name or leaving the REPL. Giving an
exact keyword name still shows that keyword's full documentation as
before.In the interactive documentation viewer the listed keyword names are
links: Tab to one and press Enter to open its documentation, and press
[to go back to the list — the same navigation the cross-reference
links inside a library page already use. On the plain backend the list
comes back as text. -
repl: Document imported resources and aliased/argument libraries in .doc and .kw (3d1665d)
The
.docand.kwcommands show documentation for the libraries,
resources, and keywords you are working with in the REPL. They now cover
everything the current session has imported and match how it was imported..docdocuments imported resource files, not just libraries — the
resource introduction plus every keyword with its arguments and
description. It also works for libraries that were imported with
arguments, which previously could not be shown. Libraries and resources
are addressed by the name they were imported under, so a library imported
with an alias (AS, or the olderWITH NAME) is found by that alias..kwaccepts the explicitOwner.Keywordform, e.g..kw BuiltIn.Log,
to pick a specific keyword when the same name is provided by more than one
import; names resolve the same way they do in a suite. It now also shows
full documentation for resource keywords, including the argument table.Running
.docor.kwon something you haven't imported tells you it
isn't loaded instead of showing an empty page. The built-in help for both
commands has been rewritten to read as user help rather than internal notes. -
repl: Show a startup banner (73eb26a)
When the REPL starts in an interactive terminal it now prints a
Python-style banner with the RobotCode, Robot Framework, and Python
versions, plus a hint about.helpand.exit. The banner is skipped
when stdin is piped/redirected or when running--fileswithout
--inspect. -
repl: Documentation viewer and themed prompt out of the box (dda4258)
.help,.kw, and.doc(or F1 for help) open a built-in
documentation viewer — a tiny terminal browser for Robot Framework
docs without leaving your REPL session.- Search with
/, jump between matches withn/N. - Click a link, or use Tab/Shift-Tab to step between them. Anchor
links jump to the right section, web links open in your browser. - Walk back and forward through your reading history with
[and]. - Scroll with the mouse wheel, or with j/k, PgUp/PgDn, g/G.
- Pages use the same renderer the editor shows on hover: signature,
argument table with types and defaults, tags, docstring, headings,
lists, tables, code blocks.
A single color theme covers the prompt, syntax highlighting, log
lines (INFO,WARN,ERROR, …), and the documentation viewer.prompt_toolkitandrichare bundled withrobotcode-repl, so the
rich prompt experience is available out of the box.--plain(or
--backend=plain) is available for AI-agent sessions and pipe
workflows that need clean stdin/stdout. - Search with
-
repl: Same prompt experience on Linux, macOS, and Windows (f8b8b15)
The interactive REPL ships with a single editor that behaves the
same way on every platform. Install the[prompt-toolkit]extra
to enable it:pip install 'robotcode-repl[prompt-toolkit]'You get a completion popup, syntax highlighting, signature toolbar,
persistent history and Ctrl-R search. Without the extra the prompt
degrades to a plaininput()line read.The previously implemented readline-based path has been removed —
its behaviour differed too much across platforms and had platform-
specific bugs that weren't worth maintaining. -
repl: --backend flag to force a specific input backend (372afca)
Lets you exercise the readline (or plain) code path without
uninstalling the prompt_toolkit extra:robotcode repl --backend=readline -
repl: Dot-commands, ${_} last-result, signature hints, session export (75cbdfd)
A grab-bag of power-user features for the interactive REPL:
- Dot-commands intercepted before Robot's parser sees them —
.help
(with per-command drill-down via.help <cmd>),.imports,.vars,
.kw <name>,.doc <library>,.history/.history clear/.history del <N>,.cwd,.clear,.save [-a] [-t name] <file>,.exit.
Help text on each command documents its flags and shows examples. -
${_}mirrors the last keyword's non-None return value, like Python's
interactive_. Works in the next argument with no${tmp}=step. - F1 invokes
.helpfrom the prompt; Ctrl-R reverse-search now
documented (was already wired via prompt_toolkit defaults). - Bottom row shows the active keyword's signature with the current
argument highlighted when the cursor sits in an argument cell.
Named-arg syntax (html=True) follows the spec position, not the
positional cell index. Outside an argument cell the row is hidden so
the prompt stays uncluttered. - Embedded-argument completion:
Literal[...]-typed parameters on
RF 7+ expose their allowed values as completion candidates after
name=. Silently no-ops on RF 5/6. -
.savewrites the session to a runnable.robotfile with imports
hoisted into a*** Settings ***section.
All features are prompt_toolkit-aware where it matters but degrade
cleanly on the readline and plain backends. - Dot-commands intercepted before Robot's parser sees them —
-
repl: Session-context toolbar + completion/popup polish (7e0c881)
Adds the bottom-toolbar feature from the original plan plus the
last round of UX polish on the prompt_toolkit candidate popup
that we shaved down through testing:-
Bottom toolbar shows the running RF version and the cwd at
all times — orientation info that's useful when juggling several
venvs / project directories. -
Esc closes the candidate popup and reverts any preview text
that arrow-navigation had pinned, restoring the user's literal
pre-popup buffer. Bound only when the popup is open
(has_completionsfilter) so Esc keeps its Alt-chord prefix
role everywhere else. -
Enter on a highlighted candidate accepts it (popup closes,
preview becomes permanent). For keyword completions Enter also
cleans up the cell — deletes any leftover text after the cursor
in the same cell (so a mid-cell completion replaces the whole
keyword) and appends a cell separator if no argument follows. -
Tab is smart: cycles through the popup when one is open,
inserts a cell separator in argument context, opens the popup
otherwise. -
Multi-line history survives a session restart as one entry
(newlines are escaped to\\non disk so the file stays
readline-compatible). -
Mid-keyword preview renders cleanly —
${Lo}cursor before
o, pickingLog To Consolenow showsLog To Console, not
Log To Consoleog(we trim the forward-cell tail from the
state'soriginal_documentbefore prompt_toolkit applies the
preview). -
TEXT_FRAGMENT in compound variable lookups (
${PREFIX_${X}})
renders with the variable-name colour, not the argument colour,
so the eye reads the whole concatenated name as one identifier. -
EOL / EOS tokens from Robot's tokenizer are dropped from the
rendered fragments —\\ninside a fragment would otherwise show
as^Jat the end of every multi-line buffer line. -
Trailing whitespace is padded out to the document's actual
length so the cursor stays in sync with the buffer (was sticking
at column 0 when the user kept typing spaces). -
_completion.pyis consolidated —candidates_for()is now
a thin projection overcandidates_for_rich(), ~200 lines of
duplicated helpers removed (was an artefact of how the rich
variant was added in the previous commit). -
CELL_SEPARATOR+find_cell_end()added to
_completion.pyas named constants and a shared helper, used by
the smart-Tab / Enter-cleanup paths.
-
Bottom toolbar shows the running RF version and the cwd at
-
repl: Doc hints next to completion popup candidates (c891215)
The
prompt-toolkitcandidate popup now shows a short context line
next to each candidate (prompt_toolkit'sdisplay_meta), so you
know what a candidate is before picking it:-
Keywords: first line of the keyword's docstring next to the
name (Log a message with the given levelnext toLog, etc.) -
Library / resource / variables imports: the discovery kind —
MODULE_INTERNALfor built-ins,MODULEfor third-party,
RESOURCEfor.resourcefiles,FILEfor filesystem hits -
Variables (
${…}/@{…}/&{…}):repr(value)[:40]of the
current value in the live suite scope -
Environment variables (
%{…}):repr(os.environ[name])[:40]
Backed by a new
candidates_for_rich()API parallel to the
existingcandidates_for()— keeps the readline backend's path
zero-cost (it can't render two-column popups anyway). Works on
RF 5/6/7+ with the same attribute-name version-switch
(short_doc↔shortdoc) the rest of the package already uses. -
Keywords: first line of the keyword's docstring next to the
-
repl: Robot-aware syntax highlighting at the prompt (a35b252)
When the
prompt-toolkitextra is installed, the prompt now paints
Robot Framework syntax in colour. Keywords, arguments, assigns,
comments, block constructs (FOR,IF,END, …), BDD prefixes
(Given,When,Then, … plus localised variants from RF 6+) and
variables all render distinctly.Variables decompose to the part level: sigil and braces, base name,
type hints (${age: int}), default values (%{HOME=default}),
subscripts (${dict}[key]), nested forms (${${inner}}), and
inline-Python expressions (${{expr}}) all get their own colour.The highlighter uses Robot's own production tokenizer
(robot.api.get_tokens) plus therobotcodesemantic analyzer's
variable decomposer — the same code path the RobotCode VS Code
extension uses for semantic-token rendering. Colour assignments
mirror the LSP semantic-token mapping, so the REPL prompt and the
VS Code editor use a consistent palette.No additional dependency: Robot is already required by
robotcode-repl, and the variable decomposer ships with
robotcode-robot. Works on RF 5, 6, and 7+ (BDD-prefix
localisation requires RF 6+; English defaults apply on RF 5). -
repl: Multi-line buffer with block-aware auto-indent (8cfcc4c)
When you open a Robot block (
FOR,WHILE,IF,TRY,GROUP),
the next line of input is auto-indented to the matching depth.
ENDpops one level. Nested blocks stack —IFinsideFORlands
at depth 2.Behaviour differs slightly between backends:
-
readline (always available): each continuation line is its own
input()call. The...prompt seeds the buffer with the right
number of spaces viaset_pre_input_hook. You type from there. -
prompt-toolkit (with the optional extra): one multi-line
buffer per top-level statement. Plain Enter is smart — submits
when the block is balanced, otherwise inserts a newline +
auto-indent so you keep typing inside. Alt-Enter (Esc
Enter) and Ctrl-J always insert a newline + auto-indent,
even when balanced. Cursor-Up/Down navigates inside the buffer.
Shift-Enter is intentionally not bound — most terminals can't
deliver it distinctly from plain Enter. Alt-Enter and Ctrl-J cover
the use case portably. -
readline (always available): each continuation line is its own
-
repl:
--plainflag to skip all prompt enhancements (bf9fc5b)robotcode repl --plain(orROBOTCODE_REPL_PLAIN=1) bypasses the
prompt-toolkit / readline cascade and falls back to a bareinput()
call — no history, no Tab-completion, no candidate popup, no
auto-suggest, no syntax highlighting.Recommended for:
- AI-agent invocations where ANSI escapes from the candidate popup
would corrupt the stdout capture the agent reads back - Automation pipelines and CI that pipe input via heredoc
- Wrapper scripts that need a deterministic, side-effect-free prompt
--plainand--no-historyare orthogonal — plain mode has no
history file anyway, but combining the two is safe and does not
raise. - AI-agent invocations where ANSI escapes from the candidate popup
-
repl: Live as-you-type completion with prompt_toolkit (b449e1b)
pip install 'robotcode-repl[prompt-toolkit]'swaps the readline
frontend for one driven byPromptSession:-
Live candidate popup under the cursor as you type — no Tab
needed (though Tab still works). Arrow-keys pick, Enter accepts.
The verboseImport Library Foo/Import Library Barrow
layout is replaced by just the labels. -
Fish-style auto-suggest — last matching line you typed shows
greyed-out behind the cursor, right-arrow accepts it. -
Ctrl-R reverse search with a dedicated UI, bracket auto-match,
multi-line cursor movement inside open blocks.
The completer runs in a background thread (
complete_in_thread=True)
so the popup never blocks the UI, and Robot's expensive
complete_*_import(None, …)filesystem /sys.pathdiscovery is
cached for the session — even with hundreds of importable modules,
only the first keystroke pays the walk cost.Candidate sourcing reuses the same Robot-aware logic the readline
backend uses, and the history file is shared on disk between the
two backends — swapping extras (or having neither) doesn't lose
arrow-up recall. -
Live candidate popup under the cursor as you type — no Tab
-
repl: Tab completion for keywords, variables, imports (72cdbc2)
Tab now completes Robot-aware:
- keyword names at the start of a cell, sourced from every loaded
library and imported resource (case + whitespace + underscore
insensitive — matches Robot's own resolution rules) -
${...}/@{...}/&{...}variables from the live suite scope,
and%{...}environment variables from the process environment -
Import Libraryarguments — plain identifiers (Coll<Tab>→
Collections), dotted module paths (robot.libraries.Coll<Tab>→
robot.libraries.Collections), and filesystem paths (./libs/My<Tab>
→./libs/MyLib.py) -
Import Resourcearguments —.robot/.resourcefiles only -
Import Variablesarguments —.py/.yaml/.yml/.json
variable files plus discoverable variables modules
Works across Robot Framework 5, 6, and 7+.
On Pythons whose stdlib
readlineis backed by libedit (macOS system
Python, some uv / python-build-standalone builds), install the
gnureadlineextra for full GNU readline behaviour:
pip install robotcode-repl[gnureadline]. - keyword names at the start of a cell, sourced from every loaded
-
repl:
--no-historyflag for ephemeral sessions (1c28b57)robotcode repl --no-historyskips loading and saving the persistent
history file. Arrow-up still recalls lines from the current session;
nothing leaks across sessions. Useful for AI-agent invocations, quick
spike sessions, or working with secrets you don't want sitting in
.robotcode_cache/repl_history. Also picked up from the
ROBOTCODE_REPL_NO_HISTORYenv var, which is handier when the REPL
is launched by a wrapper script. -
repl: Fish-style history dedup and configurable size (1c93402)
Re-running a command that's already in the history no longer leaves
the older copy behind — only the most recent invocation survives, so
arrow-up cycles through unique commands (the same behaviour fish
shell ships). Legacy history files with duplicates are cleaned up on
first load.The buffer size is now configurable via the
ROBOTCODE_REPL_HISTORY_SIZE
environment variable; default stays at 1000 entries. -
repl: Persistent line history across sessions (9c99f43)
robotcode replnow remembers the lines you typed and recalls them
with Pfeil-hoch / Ctrl-R, just like Python's own shell or bash. The
history file lands in your project's.robotcode_cache/when one is
detected, otherwise in the per-user cache directory.ROBOTCODE_CACHE_DIR
overrides both. -
results:
robotcode resultsTEXT output is now markdown (4b94d66)robotcode resultssubcommands now emit markdown for human
output. On a coloured TTY rich renders it to themed ANSI and
pages if needed; in a pipe (or with --no-color) the raw
markdown is emitted verbatim — ideal for pasting into PRs,
Slack, or feeding to an LLM. JSON output is unchanged.- summary, show, log, stats and diff open with a markdown
heading and lay out content as tables, bullet lists,
blockquotes for failure messages, and inline code for log
output. - Each status shows both an icon and the bold word
(✅ PASS, ❌ FAIL, ⏭ SKIP, ⏸ NOT RUN, ⚪ NOT SET). summary
and stats tables are column-padded so the raw markdown stays
aligned undercat/less. - log renders each test body as a nested list: keywords,
control flow (FOR, WHILE, IF, TRY, VAR, GROUP), setups and
teardowns. Argument values appear as inline-code spans;
failure messages as blockquotes between a keyword and its
children. Log output renders as- `[INFO] text`;
multi-line messages get a fenced code block. - Artefacts attached to log messages render as markdown:
images asso GitHub, Slack and VS Code show
them inline; other files as[path](url)so OSC 8-aware
terminals (rich, wezterm, iTerm2) make them clickable. Link
targets prefer paths relative to cwd and fall back to
file://URLs when the artefact lives outside cwd;
--full-pathsforcesfile://URLs everywhere.
- summary, show, log, stats and diff open with a markdown
-
results: Unify failure vocabulary across results subcommands (e3a0bd3)
summaryuses--failed/--no-failedfor the failures listing (with
failedas the matching JSON field), lining the wording up with
--status faileverywhere else.show,log, andstatsgain--failed,--passed, and
--skippedas additive shortcuts for--status fail|pass|skip.
They stack with each other and with--status, so
results show --failed --skippedis--status fail --status skip
without the typing. -
robot: Enable bottom-up navigation in the SemanticModel (a87fc79)
Every SemanticNode now carries a
parentback-pointer, so LSP features
that start from a token or statement can walk up to the enclosing block,
section, or definition without re-querying the model by line. Comes with
helpersenclosing_definition_block,enclosing_block_of_kind,
enclosing_section, andpath_from_rootonSemanticModel.Parent is typed as
SemanticNode(notSemanticBlock) so it can also
point at a Statement —RunKeywordCallStatement.inner_callsare
parented to their outer Run-Keyword statement. -
robot: Pre-resolve more semantic data so LSP features can read it once (be36e61)
Inlay Hints now read from the SemanticModel instead of doing a second
analysis pass. The model gains a real block hierarchy (FOR/WHILE/IF/TRY/
GROUP), pre-resolved init keyword docs on Library/Variables imports,
and consolidated header-token construction so future LSP feature
migrations stop re-walking the AST.The old AST-walk path stays as fallback while
robotcode.experimental.semanticModelis off; both paths must produce
identical hints (covered by parametrized equivalence tests across all
supported RF versions). -
robot: Implement cross-platform file locking for data cache (8ae4aec)
Replace the Unix-only flock-based locking with a platform-dispatched
implementation using LockFileEx/UnlockFileEx (Windows) and fcntl.flock
(Unix/macOS). The Windows path previously had no-op early returns,
meaning the exclusive lock used bycache pruneprovided no actual
protection on Windows. -
robot: Introduce SemanticModel for richer Robot Framework analysis (Part 1) (23a538c)
Introduce the first part of an opt-in SemanticModel that provides deeper
static analysis of Robot Framework files, available behind a feature flag.Enable via robot.toml:
[tool.robotcode-analyze] semantic-model = trueor in VS Code settings:
"robotcode.experimental.semanticModel": true- Nested variable resolution: variables like ${DICT_${key}} are now
statically resolved where possible, with diagnostics when resolution
fails - Richer semantic highlighting: token classification driven by the
semantic model instead of syntactic heuristics - RF 7.4 type hint support: KeywordName/KeywordArgument annotations are
recognized for run-keyword detection - Log output to verify which analyzer is active
- Robust deserialization of cached library data when new fields are added
The SemanticModel is disabled by default. Further parts will add
additional LSP feature migrations and extended analysis capabilities. - Nested variable resolution: variables like ${DICT_${key}} are now
-
runner: Extend
results&discoversearch and addlog --keyword-info/--suite-info(9559316)--search/--search-regexreach more places now. On top of the
existing test name / body / tags targets, they also hit:- every executed keyword's
[Documentation],[Tags]and[Timeout]
— answer questions like "which tests touched a keyword taggedslow"
or "which tests called a keyword whose docstring mentions
rate-limiting". - any ancestor suite's
DocumentationorMetadata— a hit on a
suite-level field keeps every test underneath, so
--search "API tests"picks up every test in a suite whose
docstring reads "API tests" without enumerating names.
Both rules apply to
resultsanddiscoveralike.results loggains two opt-in views (default off — the plain log
stays compact):-
--keyword-infoprints each executed keyword's[Documentation],
[Tags]and[Timeout]under its header, so the log shows what
each keyword is, not just what it was called with. -
--suite-infogroups tests under aSuite:header that carries
the suite's name, source, status,DocumentationandMetadata
— useful when scanning a multi-suite run to see at a glance which
suite a test belongs to and what it's about.
They compose:
log --suite-info --keyword-infogives a structured
view that mirrors the layout of the original.robotfiles. - every executed keyword's
-
runner: Add
--search/--search-regextodiscovercommands (ce8c783)discover all/tests/tasks/suites/tags/filesnow
support the same search flags as theresultsfamily. Filtering runs
through aSearchModifierSuiteVisitor wired into the existing
prerunmodifierslot, so theCollectoronly ever sees the surviving
tree — statistics, ancestor suites and the tag aggregate fall out of
that automatically.Search targets per test: name, full name, source path, documentation,
template, timeout, tags (normalisation-aware), and the full body —
keyword names, arguments, assigned variables, FOR/WHILE/IF conditions,
VAR/RETURN values, EXCEPT patterns, GROUP names, plus setup/teardown.
TEXT output highlights matches in name/source/tags/path; JSON output
echoes the pattern infiltersApplied.To avoid duplication, the search infrastructure moves into a shared
runner/cli/_search.pymodule:SearchMatcher(with a model-agnostic
matches_bodymethod that walks bothrobot.runningandrobot.result
body trees via duck-typing),make_search_matcher,make_highlighter
and the newSearchModifier.results.pyand_render.pyswitch to
the shared module and drop their local copies. -
runner: Add the standard result filters to
results diff(a10f6ce)results diffnow accepts the same filter options as the otherresults
subcommands:--status,-i/--include,-e/--exclude,-s/--suite,
-t/--test,-bl/--by-longname,-ebl/--exclude-by-longname, plus
--search/--search-regex. Each filter is applied identically to
both baseline and current before the diff, so the comparison can be
scoped to a single suite, tag pattern, name, or message snippet:robotcode results diff baseline.xml -s "MyProject.Login" robotcode results diff baseline.xml -i smoke robotcode results diff baseline.xml --search TimeoutError robotcode results diff baseline.xml -bl "MyProject.Login.Bad Password"DiffResultgains afiltersAppliedfield (additive, optional) so the
JSON output records the filters in the same shape used by the other
result models. -
runner: Add
-bl/--by-longnameand-ebl/--exclude-by-longnameto results filters (33697cb)robotcode resultsnow accepts long-name filters alongside the existing
--status,-i/--include,-e/--exclude,-s/--suite,-t/--test
options. Pick a specific test or suite by its full long name (exact
match), or exclude a branch of the tree the same way:robotcode results show -bl "MyProject.Login.Bad Password" robotcode results summary -ebl "MyProject.Slow Suite" robotcode results stats --by tag -bl "MyProject.Smoke" robotcode results log -bl "MyProject.Login" -bl "MyProject.Logout"Both options compose with the existing filters and
--search/
--search-regex, and surface in JSONfiltersAppliedasby-longname
/exclude-by-longnamefor CI consumption. Available onsummary,
show,log, andstats.Along the way, trimmed redundant "repeat for OR" notes from option help
texts — Click already shows the*marker on repeatable options. -
runner: Split
--searchand--search-regex, add tosummaryandstats(89c2952)--search-regexis now a standalone option that accepts a pattern instead
of a boolean flag — you no longer have to spell out both--search TEXT --search-regex. The two options are mutually exclusive:-
--search TEXT— case-insensitive substring match (open browser,
TimeoutError, …) -
--search-regex PATTERN— Python regex, honoured as written. Use
(?i)patternfor case-insensitive matching, just like in any regex
engine.
Both options now work on
summary,show,log, andstats, so the
same search vocabulary applies across the wholeresultsfamily:robotcode results summary --search TimeoutError robotcode results stats --by tag --search Browser robotcode results show --search-regex "AssertionError.*" robotcode results log --search "Open Browser"Search traverses the raw output tree (test attributes plus keyword names,
arguments, and log messages), so a single search reaches into the
execution body without first materialising the full per-test log. -
-
runner: Add
results difffor comparing two runs (bbdcf33)results diff BASELINE [CURRENT]compares twooutput.xml/output.json
files and reports tests whose status changed, plus tests that appeared or
disappeared between the runs. Categories:- New failures — passed in baseline, fails in current
- New passes — failed or skipped in baseline, passes in current
- Status changes — any other status flip
- Added — only in current
- Removed — only in baseline
If
CURRENTis omitted, it falls back to the active profile's auto-
discovered output file, so the common pattern isrobotcode results diff /path/to/baseline.xmlafter the latest run. Use--only new-failures
(repeatable) to narrow the view; combined with--format jsonthis gives
CI pipelines a clean signal for PR feedback without parsingoutput.xml
themselves.Exit code is always 0 — the command is for inspection, not gating.
-
runner: Add
--search/--search-regextoresults showandlog(1e90209)results logandresults shownow accept--search TEXTto narrow the
output to tests that mention the given text — searched across test name,
failure message, keyword names, keyword arguments, and log messages.
Case-insensitive substring match by default; pass--search-regexto use
a Python regular expression instead.In
log's TEXT output, every match is highlighted with a yellow background
so the relevant lines stand out at a glance — handy for tracking down
which test triggered a particularTimeoutErrorwithout reopening
log.html. JSON output records the search pattern infiltersAppliedfor
auditability but stays free of markup.--searchcomposes with the existing filters (--status,-i/-e/-s/-t),
so combinations like "failures that mentionAssertionError" or "smoke
tests whereOpen Browserwas called" come naturally. -
runner: Add
results statssubcommand (d1fa30f)results statsaggregates a finished run by--by tag,--by suite, or
--by status— the same dimensionsreport.htmlexposes in its
"Statistics by Tag" / "Statistics by Suite" panels. Repeat--byto render
multiple sections in one call.Each section is a table with pass/fail/skip counts and total elapsed time
per group, sorted by failures (descending) by default. Switch to--sort elapsed,--sort total, or--sort name, and limit rows with--top N.
The standard--status,-i/--include,-e/--exclude,-s/--suite,
-t/--testfilters narrow the test set before aggregation, so combinations
like "tag stats for the smoke suite, top 10 by failures" come out of the
box.JSON output exposes a stable
StatsResult/StatsSection/StatsGroup
schema for CI consumption. -
runner: Add
--sortand--reversetoresults show(e4d693c)results showcan now sort tests byname,suite,status,elapsed,
orstartbefore display. Pair with--top Nfor triage views like "the
slowest 10 tests" or "failures first".--reverseflips the order; without
--sort, execution order is preserved (the existing behaviour).statusorders FAIL → SKIP → PASS → NOT RUN (matchingreport.html's
custom sort), andelapseddefaults to longest-first so the most expensive
tests bubble to the top. A dim footer lineSorted by FIELD (desc)is
emitted in TEXT mode when a sort is active; JSON output reflects the order
in thetestsarray. -
runner: Unify
results logfilters and add--max-depth(02bb47b)results lognow uses the same filter options asresults showandresults summary— pick tests by--status,-i/--include,-e/--exclude,
-s/--suite, or-t/--test. The oldTEST_PATTERNpositional and
--failures-onlyflag are gone; use-t "*Login*"and--status fail
instead.A new
--max-depth Ncollapses deeply nested keyword calls. The keyword
header still prints, and a dim… N hidden (--max-depth N)marker takes the
place of the body so nothing disappears silently. Default0keeps the
behaviour unchanged (full tree). The previous--keywords/--no-keywords
toggle is dropped — without keyword grouping the output overlapped with
results show.See docs/03_reference/cli.md for the refreshed
option reference. -
runner: Add
resultscommand to inspect Robot Framework runs (cf67abf)After running tests,
robotcode resultslets you explore the output
without openingreport.htmlor re-running the suite — handy for CI
logs, agent-driven workflows, and quick failure inspection from the
terminal.Three subcommands:
-
robotcode results summary— overall status, pass/fail/skip counts,
run duration, and the total number of error and warning messages.
--failuresadds the list of failed tests above the counts. -
robotcode results show— one line per test with its status, source
link, and failure message. Filter by status, tags, suite or test
name pattern. -
robotcode results log— the full execution tree: every keyword
call, control structure, and log message, just like Robot's
report.htmlbut in your terminal.--failures-only,--level WARN,--extract DIR(pulls out screenshots and embedded
artefacts), and more.
The output file is auto-discovered from your active
robot.toml
profile; override with-o/--output PATH. Test names carry a
(path:line)suffix that VS Code's integrated terminal turns into a
clickable goto-source link. Pass--format json(ortoml) for a
structured, agent-friendly payload.See
docs/03_reference/cli.mdandrobotcode results --helpfor the
full reference. -
-
vscode: Add commands to register the chat plugins marketplace (0e2b02f)
Two new Command Palette commands let you pull the RobotCode chat
plugins marketplace into VS Code without editing settings by hand:- "RobotCode: Add Chat Plugins Marketplace"
- "RobotCode: Remove Chat Plugins Marketplace"
They add or remove robotcodedev/robotframework-agent-plugins in the
user-levelchat.plugins.marketplacessetting, so GitHub Copilot Chat
can discover and install RobotCode plugins (and future ones from that
marketplace). This is the marketplace route — separate from the plugin
the extension already bundles viacontributes.chatPlugins.If you install the robotcode plugin from the marketplace, disable the
bundled one by turning offrobotcode.ai.enableChatPluginsto avoid
running two copies of the same plugin.Only the applicable command is shown: Add when the marketplace is not
registered, Remove when it is. Removing also clears the entry when it
was added as a GitHub URL rather than the owner/repo shorthand. -
vscode: Bundle AI chat plugins (4018a4f)
The extension now bundles chat plugins for GitHub Copilot Chat in VS Code.
When enabled, the agent uses the project'srobotcodeCLI to answer Robot
Framework questions and run tasks, honoring the project'srobot.toml,
profiles, and Python environment.For example:
-
"run the smoke tests with the ci profile" runs them through the
selected profile and reports pass/fail counts -
"why did Login Works fail?" inspects the existing run results instead
of loadingoutput.xmlinto the chat -
"what tests and tags exist?" uses
robotcode discover, which resolves
the real set (paths, profiles, variables, pre-run modifiers) rather than
grepping.robotfiles -
"what arguments does this keyword take?" looks it up with
libdoc
against the installed libraries and local resources - "try this keyword" runs it in the REPL
Enabled by default; toggle with
robotcode.ai.enableChatPlugins.For other AI agents (Claude Code, Codex, and other Open-Plugin-compatible
tools), the same plugins are published as a marketplace:
https://github.com/robotcodedev/robotframework-agent-plugins -
"run the smoke tests with the ci profile" runs them through the
-
vscode: Disable chat language model tools by default (3c47b48)
RobotCode now includes a
robotcodeCLI-based chat plugin for chat assistance. They use the same CLI workflows RobotCode users already know for setup, configuration, profiles, discovery, analysis, test runs, result inspection, and REPL usage.The existing VS Code Chat language model tools are now turned off by default. They provide chat access to RobotCode information such as keyword documentation, library documentation, document imports, and environment details.
Users who still need these tools can enable
robotcode.ai.enableLanguageModelTools.The setting remains visible in VS Code for now and notes that the language model tools are planned for deprecation and later removal.
-
vscode: Add global setting to disable What's New notification (fa03c08)
Allow users to turn off the update notification that appears after
RobotCode has been updated. The newrobotcode.showWhatsNewOnUpdate
setting can be found in the global VS Code settings under
RobotCode > General. -
Add inline documentation and examples to robot.toml.json (825f891)
Users now get rich documentation directly in their editor when editing
robot.toml configurations through JSON schema integration. The schema works
seamlessly with the Even Better TOML VS Code extension
(https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml),
which is powered by Taplo.Enhancements to robot.toml.json:
- Comprehensive inline documentation (markdownDescription) for every field
- TOML code examples extracted from configuration docs
- Direct links to RobotCode documentation via Taplo integration
- Full compatibility with Even Better TOML and other Taplo-based editors
Improvements to schema generator:
- Complete type hints for all inner functions
- Detailed docstrings for better code clarity
- More robust TOML code block extraction regex
Bug Fixes
-
analysis: Respect diagnosticMode for workspace files (d2f8114)
Diagnostics for closed workspace files could appear (or be suppressed)
inconsistently in openFilesOnly mode, depending on which file the
workspace diagnostics loop happened to iterate last.Also clarify the diagnosticMode description so it no longer implies
that background analysis is restricted -- the setting only controls
which files diagnostics are reported for. -
analyze: Run unused diagnostics through the diagnostic modifier (f13b678)
collect_unused_keywords/collect_unused_variablesreturned their
diagnostics directly, bypassing the diagnostic modifier. As a result the
KeywordNotUsed/VariableNotUseddiagnostics could not be ignored or
restyled via-mi/-mXor# robotcode:comments, unlike every other
diagnostic. Pass their result throughmodify_diagnostics, the same way
collect_diagnosticsdoes. -
analyze: Tighten path filtering and refine code output (b0b8820)
- Path arguments to
robotcode analyze codeare now matched segment-wise:
passingtests/apino longer pulls in siblings liketests/api_v2. - Workspace-level diagnostics (e.g. variable/library import errors) are
now prefixed with.:instead of being printed without any source
marker; their related-information lines keep their line/column. - The summary line picks its color from the highest severity present
(red/yellow/blue/cyan) instead of only highlighting errors. - Unused-keyword/variable collectors are only registered when
--collect-unusedis set, and empty document reports from the
analysis pass are no longer emitted.
- Path arguments to
-
analyze: Ignore intentionally unused variables in CLI diagnostics (9cba5b0)
Treat variable names starting with "_" as intentionally unused in CLI unused-variable diagnostics, matching the language server behavior.
-
bundled: Quote arguments in robotcode script to handle spaces correctly (4311747)
-
config: Allow "NONE" string for max-error-lines in robot.toml (6f2e5e1)
You can now set max-error-lines = "NONE" to show the full error
message, matching Robot Framework's --maxerrorlines NONE. Integers
keep working as before; any other string is rejected with a clear
error. -
discover: Render arbitrarily deep suite trees in markdown output (3825939)
robotcode discover all(and any other markdown output) now renders
the full workspace tree no matter how deeply suites are nested.
Previously, projects nested past ~8 levels had everything below the
limit silently dropped — including the trailing## Statistics
block — because rich's markdown parser caps nesting at 20 and every
list level consumes two of that budget.Markdown is now rendered through a parser configured for deep
nesting, so the whole tree and its statistics always appear. Headings
are left-aligned and tables render without the extra blank lines rich
inserts by default.rich is now a direct dependency of the plugin package (the lowest
package that renders markdown); the repl package picks it up
transitively instead of declaring it separately. -
docs: Fix sidebar links treated as external URLs (9b393ec)
vitepress-sidebar generates base:"/" with links starting with "/",
causing VitePress to produce protocol-relative URLs ("//path") that
browsers interpret as external links. Remove the redundant base:"/"
from the root sidebar group so absolute links resolve correctly. -
language-server: Honor semantic model setting changes (782d83d)
-
packages: Pin internal robotcode dependencies to exact version (7e4e9f2)
Updating a single robotcode package now pulls the matching versions of
its robotcode dependencies along with it. Previously the inter-package
dependencies were unconstrained, so upgrading one package could leave
its siblings on an older release and break the installation.The pins are kept in sync automatically on each release.
-
plugin: Suppress mypy type-arg warning on click.ParamType subclass (ecf88e7)
A recent mypy / click version bump started flagging
AddressPortParamType(click.ParamType)as 'Missing type arguments
for generic type ParamType'. Suppress with# type: ignore[type-arg]
inline — the class deliberately omits the type parameter because the
value shape is heterogenous (parsed byconvert). -
plugin: Make click help-text generation deterministic (b45757c)
The
MutuallyExclusiveOptionhelp text joined aSet[str]and
EnumChoicereturnedset(choices).difference(excluded)— both
produced non-deterministic ordering, so regeneratingcli.mdalways
re-shuffled the option lists. Sort the mutex set; preserve enum
definition order via a list comprehension. Regeneratecli.mdso the
typo fix from eeb8979 actually lands in the docs and the option
ordering is stable across future runs. -
repl: Handle all return-value assignment forms in completion and argument hints (bad6e14)
Keyword completion and the status-bar argument hint now work after any return-value assignment Robot Framework allows — including item assignment (
${x}[0],${d}[key]) and type hints (${x: int}), not just a plain${x} =. The keyword is resolved with Robot Framework's own variable parser, so the REPL matches real assignment syntax exactly. The status-bar hint, which previously showed nothing once an assignment was present, is fixed too. -
repl: Keep keyword completion working after a return-value assignment (dc5d0be)
Starting a line with a return-value assignment —
${result}= Some Keyword, or several targets like${a} ${b}= …— no longer turns off keyword completion in the keyword cell. Completion and Tab now skip the assignment targets and complete the keyword (and then its arguments) just as they would without an assignment. -
repl: Prevent multiple concurrent REPL executions (1edfe13)
-
repl: ${_} now mirrors every keyword result, including None (45ec8fa)
In the REPL,
${_}holds the result of the last keyword. Previously
keywords that return None (such asLog) left${_}untouched, so the
most natural first step —Log hellothenLog ${_}— failed with
"Variable '${_}' not found".${_}now always reflects the most recent keyword and is set to None
when a keyword returns nothing. It's also seeded to None at startup, so
${_}resolves even before the first keyword runs. -
repl: Resolve relative import paths against the working directory (8a34747)
Imports such as
Import Resource foo/my.resourcetyped at the REPL
prompt now resolve relative to the REPL's working directory, just like
the same import does in a.robotfile. Previously such imports only
worked when the path was absolute, prefixed with${CURDIR}/, or
reachable via the module search path.This matches Robot Framework's own resolution since RF 7.4. The REPL
docs also note that on RF < 7.4 bare relative paths still fail (RF
itself doesn't resolve them that way on those versions); use
${CURDIR}/...or put the directory on the module search path
instead. -
repl: Keep REPL startup working on pyreadline3 (Windows) (7ba1a01)
robotcode replcrashed on startup on Windows when launched against
pyreadline3and a history file that still had legacy duplicates —
pyreadline3 doesn't exposeremove_history_item, so the dedup pass
tripped on AttributeError before the prompt ever appeared.History dedup and
.history del <N>now feature-detect
remove_history_itemand fall back to aclear_history+ re-add_history
rebuild when the running readline shim doesn't expose it. CPython's
GNU readline path is unchanged. -
repl: Preserve backslashes in dot-command argument paths (ed2b91a)
.save C:\Users\…\scratch.robotmangled the path on Windows because
shlex.splitconsumes backslashes as escape characters. Switch to a
custom shlex withescape=""so paths arrive intact while shell-style
quoting (for spaces in paths) still works. -
repl:
-d/--outputdirwas silently ignored (06bc85d)robotcode repl -d ./results -o output.xmlused to write the file
into the working directory instead of./results. The directory now
honours-d, theoutput-dirsetting inrobot.toml, androbot's
default precedence in that order. Bothreplandrepl-serverare
fixed. -
repl, repl-server:
-v/--variableand-V/--variablefilenow work (7ecdd82)Both flags on
robotcode replandrobotcode repl-serverwere broken
—-v BASE_URL:stagingdid not register the variable, and-V vars.yaml
did not load the file. They now behave the same as the matchingrobot
flags:-vsets inline name/value pairs,-Vreads variables from
.yaml/.py/.jsonfiles. Repeat either flag to set multiple at
once. -
robot: Fix Run Keyword If nested run keyword handling in all branches (1d283aa)
All three Run Keyword If branches (IF, ELSE, ELSE IF) now use
skip_args() + _analyze_keyword_call(analyze_run_keywords=True)
so nested run keywords receive only branch-local tokens instead
of consuming ELSE/ELSE IF markers. -
robot: Correct type-hint handling in semantic analyzer (ecfde21)
strip variable type hints only in declaration contexts
preserve typed names in usage lookups
resolve nested typed variable declarations correctly
stop splitting type hints on additional colons in tokenizer
add regression tests for variables, VAR, assignments and arguments -
runner: Keep
relSourceinresultsJSON regardless of--full-paths(e4ff456)Aligns
resultswithdiscover, which always carries bothsource
(absolute) andrelSourcein its JSON output. Two changes:-
_make_test_item/_make_diff_change/LogTeststop conditionally
settingrel_source=Nonewhen--full-pathsis on. The flag is now
purely a TEXT-rendering hint. -
_rel_to_cwdfalls back to the original path (instead ofNone)
when the source isn't anchored under cwd, mirroring
discover.get_rel_source. Consumers like the VS Code extension can
now rely onrelSourcebeing present wheneversourceis.
_make_diff_changeand_make_test_itemno longer takefull_paths,
since the parameter became unused after the change. Call sites updated.Plus acceptance tests covering the harmonised behaviour on
summary,
show,loganddiff, and a TEXT-only--full-pathstest on
discover tags(the last subcommand without coverage). -
-
runner: Chdir into root_folder in
discover files(b92acdc)The other
discoversubcommands wrap their work in
with app.chdir(root_folder)viahandle_options, soget_rel_source
produces paths relative to the project root.discover filesskipped
that step, which made its default (non---full-paths) output depend on
the caller's process cwd: if cwd was outside the project, paths fell
back to absolute, breaking the documented semantics.Wrap the body in the same chdir context so the output is consistent
with the rest ofdiscover. Also flips a fragiletest_files_default_ relativefrom ordering-dependent (it would fail in the full suite
when an earlier test left cwd in a tmp dir) to robust. -
runner: Honour subcommand semantics in
discoverJSON output (0f26a3f)Two
discoversubcommands silently differed between their TEXT and
JSON renderers because the type filter only ran in the TEXT path:-
discover tests -f jsonreturned every item in
collector.test_and_tasks— i.e. tasks slipped in too, even though
the TEXT render correctly filtered totype == "test". Same shape
bug ondiscover tasks. Filter the list before handing it to
ResultItemso JSON and TEXT agree. -
discover tags --not-normalized -f jsonignored the flag and always
returned the normalised tag dict; only the TEXT path consulted
--normalized. Pick the right collector dict (tagsvs
normalized_tags) for both renderers.
Both surfaced while wiring up the new discover acceptance tests.
-
-
runner: Page
discoveroutput through a single pager invocation (069c34e)Each
discoversubcommand opened the system pager multiple times in
sequence — once for the main listing, then once for the statistics block
(and once per key fordiscover info). The fix routes everything through
a singleecho_via_pagercall so the user only sees one pager instance. -
runner: Normalise tags in
resultscommands (8f93500)Robot Framework treats tags as equal when they differ only in case,
whitespace, or underscores (Bug 1≡bug_1≡Bug1). The new
resultscommands didn't honour that:-
stats --by tagshowed each spelling variant as its own bucket,
even though they referred to the same semantic tag. -
tests[].tagsinshow/summary --failuresechoed the raw form
from the result file, so the same tag could appear with different
spellings on different tests. -
--search/--search-regexagainst tags compared the raw strings,
so--search "bug 1"missed tests literally taggedbug_1. -
filtersApplied.include/excludeechoed the user input verbatim, which
didn't reflect how Robot actually interpreted the pattern.
Every tag-handling spot now uses Robot's
normalize(..., ignore="_"):- Stats buckets group by the normalised form and display the normalised
label too. -
_make_test_itememits already-normalised tags in JSON / TEXT. -
_SearchMatchercarries a separate tag-aware predicate that
normalises both haystack and needle (substring) or just the haystack
(regex). -
_canonical_tag_patternnormalises plain single-tag patterns in
filtersApplied; patterns containing an uppercaseAND/OR/
NOToperator are echoed verbatim because each operand would need
individual normalisation.
Tests added: stats merges equivalent tags into one bucket;
show
emits normalisedtags;--searchis normalisation-aware against
tags;filtersAppliedechoes the canonical pattern form. The
tagged.robotfixture grew three new tests (norm tag,norm_tag,
NormTag) so the regression case is exercised end-to-end. -
-
runner: Make
resultscommands work against older Robot Framework outputs (20bb597)robotcode resultsfailed onoutput.xmlfiles generated by Robot
Framework 5 and 6 — the older models use different attribute names than
RF 7 (elapsedtimevselapsed_time,starttime/endtimeas the
YYYYMMDD HH:MM:SS.fffstring, novariablesonWhileIteration, …).Each accessor now falls back to the legacy spelling and the iteration
helper limits loop-variable lookups toForIterationviaisinstance,
sosummary,show,log,stats, anddiffproduce identical
output regardless of which Robot version wrote the file. Timestamps in
the legacy string format are normalised to ISO 8601 in the JSON
contract.Smoke-tested across RF 5.0, 6.0, 7.0, 7.3, and 7.4.
-
runner: Escape
<errors>inresults loghelp to prevent VitePress build error (7dc79ef)The
--execution-messageshelp text contained a raw<errors>tag that
VitePress' Vue parser interpreted as an unclosed HTML element, breaking
the generatedcli.mddocs page. Wrap it in backticks so it renders as
inline code and is ignored by the template compiler. -
schema: Revert robot.toml json-schema, because older versions of robotcode need this (fafb168)
-
vscode: Let Tab accept Copilot inline edit suggestions (f724aa2)
When "4 Spaces Tab" was enabled, pressing Tab inserted four spaces
instead of accepting or jumping to Copilot's inline edit (Next Edit)
suggestions. Tab now yields to those suggestions and only inserts
spaces when none is pending. -
vscode: Update stale RF version UI strings from 4.1 to 5.0 (#605) (f846483)
The quick-pick dialog shown when environment validation fails still
referenced 'robotframework version 4.1 or higher' in both the
'Select Python Interpreter' detail and the 'Retry' detail text.
The actual enforced minimum has been 5.0 since commit 02cf495
(refactor: introduce RF_VERSION constant and remove RF < 5.0 dead code).
Documentation
-
analyze: Document the
-mi "*"allow-list pattern (b5b2444)Show that
*matches every code, so-mi "*"plus re-introducing
specific codes builds an allow-list — and point out it remaps severity,
unlike the --code filter. -
analyze: Document the --code filter (e72ac55)
Fold --code into the "reporting only some diagnostics" section next to
--severity, noting that both filter (rather than remap) and combine with
AND. -
analyze: Document --severity filter and unused diagnostic control (2da8116)
- describe the new --severity output filter alongside the modifiers
- note that KeywordNotUsed/VariableNotUsed can now be remapped or
ignored like any other diagnostic
-
analyze: Streamline and correct analyze-code guide (0272ab9)
- drop the flag table; defer to the CLI reference
- move the JSON reference to the end
- trim implementation internals from the SARIF section and give every
output format a consistent invocation + example - note that the CI examples assume project setup via its package manager
- fix a dead anchor link
Corrections after review:
- no paths analyzes/reports the whole project, not the profile's default
paths; paths/--filter narrow the reported per-file diagnostics while
import/library resolution always covers the whole project - explain why --collect-unused is opt-in (needs whole-project reference
data, extra pass, slower with many keywords/variables) - note that a real run or discovery can surface errors static analysis
misses (suite-wide checks like duplicate test names, PreRunModifier) - show how to read the bitwise exit code from the shell
-
analyze: Document CI workflows, drop scratch workflow (fcb0caa)
Replace the fragmentary CI snippets in the analyze-code guide with full,
copy-pasteable workflows for GitHub code scanning (SARIF upload), GitHub
inline annotations, and GitLab Code Quality — including the
security-events: writepermission and current action versions
(checkout@v5, upload-sarif@v4) that the manual trial surfaced.Remove the throwaway .github/workflows/analyze-code.yml now that the
examples live in the documentation. -
analyze: Add reference guide for analyze code (095b52a)
Add a task-oriented guide for
robotcode analyze codeunder
docs/03_reference, in the style of the discover/results guides: what it
checks, severities and diagnostic modifiers, exit codes and masks, all
output formats (concise, json, sarif, github, gitlab), a flag reference,
JSON/SARIF/GitHub/GitLab output references, CI recipes, and the cache
subcommands. Link it from the reference index. -
cli: Enhance command options documentation for severity and code filters (422d466)
-
cli: Document core, results and testdoc commands (b48a58d)
Add the missing commands to the package overview: the core
robotcodepackage now listsconfigandprofiles, and the runner
package listsresultsandtestdoc. Close the reference with help
hints and links to the related configuration, discovery, results and
REPL pages. -
config: Show TOML examples in robot.toml reference (c53da77)
The "Examples:" blocks were carried over verbatim from Robot
Framework's CLI help, so they showed --flags instead of TOML.
Add a curated TOML_EXAMPLES map in generate_rf_options.py (with
extend- prefix rewriting for extend-* variants) and regenerate
model.py and config.md. -
contributing: Add agent workflow guide and update contribution guide (9a024a2)
-
contributing: Clarify DCO vs GPG signing and unify branding (a1f116d)
Reference the DCO in the CONTRIBUTING Legal Notice and recommend
git commit -s. Clarify in both places that the DCO sign-off is
separate from the GPG/SSH commit signature (git commit -S) required
for merges.In AI_POLICY.md, drop the duplicated DCO statement and link to the
Legal Notice instead. Align the PR template's tests/lint/signed-commits
bullets with the CONTRIBUTING checklist, and unify the project name
spelling to "RobotCode" across the three files (URLs and CLI names
unchanged). -
contributing: Add AI policy and refine contribution guide (688e6ae)
Add a project-wide AI and Automated Contribution Policy (AI_POLICY.md)
covering human responsibility, disclosure, low-context submissions, and
enforcement.Restructure CONTRIBUTING.md:
- new "Project-Wide Rules" section linking the AI policy and the
payment/bounty rule - add a pre-commit hooks section (uvx / uv tool install / pipx)
- mention uv / uvx alongside pipx for installing hatch
- rewrite the Running Tests section: `hatch run test:test` as the
recommended default, correct RF versions (5.0–7.4) and matrix size
(5×8=40), clarify that bare `hatch run test` only runs in the
default env - consolidate PR guidelines into a PR checklist + description +
review process, referencing the new PR template - fix TOC duplicates and the empty Payment link
Add a GitHub pull request template with checklist and AI/tooling
disclosure block, and add the same disclosure block to the bug,
enhancement, and question issue templates. - new "Project-Wide Rules" section linking the AI policy and the
-
home: Refresh landing page (8dc70e0)
Mirrors the reworked README pitch: tightened hero, consolidated feature
cards, and a "Sponsor RobotCode" section with Individual/Corporate split.Adds a RandomTagline component, analogous to RandomHeroImage, so the
hero tagline rotates randomly on each page load. -
news: Add v2.6.0 release notes (7d6a701)
-
readme: Restructure and refresh (69c881b)
- Sharpen What-is intro with Foundation / Core-Team partnership note
- Restructure Key Features into Editor/IDE, Configuration, Command line
groups with marketing-oriented bullets - Tighten Requirements (correct VS Code 1.108 / IntelliJ 2025.3,
prominent LSP-editor note) - Add Command Line installation block for CI / non-IDE users
- Fix broken doc links (troubleshooting page never existed,
/support/ → /05_contributing/) - Split Sponsor RobotCode and Get Involved into separate sections
-
repl: Clarify REPL scripts are body-only .robotrepl files, not full suites (a169d86)
Reword the file-execution section so it no longer implies a full
.robot
suite can be run. These inputs are REPL scripts — a test-case body only,
with no*** Settings ***/*** Test Cases ***sections — and use the
.robotrepl/.robotscriptextension instead of.robot. A file with
section headers fails with "No keyword with name '*** Settings ***'
found"; import libraries and resources from inside the body with
Import Library/Import Resource.Also note that
.saveonly guarantees the export parses cleanly —
REPL-only variables like ${_} still need an edit to run standalone — and
tidy up wording, hyphenation, and a duplicated shortcuts list. -
repl: Document the prompt-toolkit extra (2660b7b)
New section in the REPL reference covers:
- the
prompt-toolkitextra (pip install 'robotcode-repl[prompt-toolkit]')
and the upgrades it lights up — live as-you-type candidate popup,
fish-style auto-suggest, Ctrl-R reverse search UI, bracket
auto-match, multi-line cursor movement - the threaded completer + session cache that keep the popup
responsive even with hundreds of importable modules onsys.path - the fact that history is shared on disk between backends, so
swapping extras doesn't lose arrow-up recall - the
[prompt-toolkit,gnureadline]combined extras as a sensible
setup for libedit-backed Pythons
- the
-
repl: Document history persistence and tab completion (1374da7)
New "Prompt features" section in the REPL reference covers:
- where the history file lives (project
.robotcode_cache/vs. the
per-user cache directory,ROBOTCODE_CACHE_DIRoverride), how the
fish-style dedup behaves, and the--no-history/
ROBOTCODE_REPL_NO_HISTORY/ROBOTCODE_REPL_HISTORY_SIZE
escape hatches - what Tab completes — keywords from loaded libraries and imported
resources, suite-scope variables (${...}/@{...}/&{...}),
%{...}environment variables, and the threeImportarguments
with plain / dotted / filesystem prefixes - the
gnureadlineextra for macOS' system Python and
python-build-standaloneinterpreters (uv/rye/ …) where the
stdlibreadlineis libedit-backed and Tab would otherwise be
degraded
Also adds the REPL reference to the index page.
- where the history file lives (project
-
repl, repl-server: Correct misleading
--sourcehelp text (87402e3)The flag only uses the parent directory of
FILEas the REPL's
working directory — it does not read or write the file, and does not
set a suite name. -
runner: Task-oriented guide for
robotcode discover(f69fd9a)A new
discovering-tests.mdpage covers thediscoverfamily the same
wayanalyzing-results.mdcoversresults. It walks every subcommand
from the terminal perspective —all,tests,tasks,suites,
tags,files,info— with examples and flag tables, then the
shared Robot-native filters and--search/--search-regex
behaviour, and finally the full JSON schema reference for scripts,
CI pipelines, and editor integrations (TestItem,ResultItem,
TagsResult,Info,diagnostics,filtersApplied) plus a set of
jq-based CI recipes for sharding, tag reports, and parse-error gates. -
runner: Cover extended search and
results log --keyword-info/--suite-info(a7395f6)-
analyzing-results.md: search-target list mentions test
doc/template/timeout, keyword [Documentation]/[Tags]/[Timeout]
(result-tree-only), and ancestor-suite Documentation/Metadata. New
--keyword-info and --suite-infosubsection explains what each flag
adds to TEXT and JSON, with a combined example.logJSON schema
shows the newsuitesarray and per-testsuitecross-reference plus
a table for the keyword doc/tags/timeout fields. -
cli.md: regenerated fromhatch run create-cmd-line-docsto pick
up the new--keyword-info/--suite-infoflags onresults log
and the updated--searchhelp text acrossresultsanddiscover.
-
-
runner: Fix "releative" typo in
discover --help(eeb8979) -
website: Use bundler module resolution (dd6f358)
-
website: Improve hero image navigation (09a8975)
-
Split REPL reference into shell and command-line debugger pages (7f0577f)
The REPL reference mixed the interactive shell with the command-line
debugger. It is now two pages:- "Interactive Robot Framework with robotcode repl" — the shell.
- "Command-line debugging with robotcode robot-debug" — a dedicated page
for the debugger: ways to pause a run (line, keyword, embedded
Breakpoint keyword, exceptions, stop-on-entry), the debug command set
(stepping, call stack, inspecting and setting variables, breakpoint
management, exception filters, log-and-continue), a worked example with
the embedded Breakpoint keyword, and how it relates to the VS Code
debugger.
Other improvements:
- Each command reference page now states which optional package to
install to run it: robotcode[repl], [runner], or [analyze]. - The CLI reference now documents robotcode robot-debug (alias run-debug)
and lists it under the repl package. - Fixed the .doc command description: it shows documentation for
libraries and resources the session has imported, not on demand.
-
Add "Working with AI Agents" reference page (e7c8d68)
Describe how RobotCode lets AI coding agents work through the project's
own robotcode CLI instead of guessing:- the chat plugin (a skill) and what it teaches the agent — discover,
libdoc, REPL, results, analyze on the resolved project - the bundled VS Code plugin and its enableChatPlugins toggle, plus the
extension shipping the robotcode CLI on the integrated terminal PATH - installing the plugin in other agents via the Open Plugins marketplace
- recommended project-context setup (AGENTS.md / CLAUDE.md): environment,
library init steps, the system under test, conventions - the CLI's AI-agent detection and its override env vars/flags
- troubleshooting
- the chat plugin (a skill) and what it teaches the agent — discover,
-
Refine contribution guide and AI policy (b93cbf6)
- AI_POLICY: welcoming, principle-led intro; clarify that what
matters is human ownership, not whether an autonomous agent was
involved; frame the purpose around protecting maintainer time,
which is what ultimately keeps RobotCode sustainable - CONTRIBUTING: add a "find your path" orientation block and a
warmer Project-Wide Rules intro; lead commit-signing setup with
the low-effort SSH path; document that documentation-only changes
need neither the test matrix nor linting (there is no Markdown
linter); remove decorative emoji - PULL_REQUEST_TEMPLATE: mark the tests and linting checks N/A for
documentation-only / non-code changes
- AI_POLICY: welcoming, principle-led intro; clarify that what
-
Add
resultsanalysis guide (ebb2d12)A task-oriented user guide for the
robotcode resultsfamily of
commands, split into two parts:-
Using the commands — what each subcommand does in the terminal,
its useful flags, sort/filter semantics, and the pager / colour
handling. Recipes for the common day-to-day questions: "what
failed", "which test took longest", "drill into one test",
"regression vs main". -
JSON reference — schema rules (omitted vs
nullvs[]),
per-subcommand JSON shape, the body-item-type vocabulary used by
log, thefiltersAppliedecho, and CI/jq recipes for pass-fail
gates, slow-test reports, notification payloads and artefact
gathering. Includes a note specifically for AI-driven workflows on
why streaming the focused JSON beats parsing rawoutput.xml.
Also linked from the reference index page.
-
Using the commands — what each subcommand does in the terminal,
-
Update json schema for robot.toml validations (6d4fd6d)
Performance
-
vscode: Smoother test explorer refreshes and live test updates (bc488d0)
The Test Explorer used to flicker on every keystroke when the tree was
expanded, slow to a crawl during multi-file edits (e.g. when an AI agent
applies many edits at once), and sometimes show "AbortError" as a
workspace entry at startup. Newly added or removed tests didn't appear
in the tree until the refresh button was pressed.What's different now:
- The tree only re-renders when the discovered tests actually change;
identical re-discoveries leave the UI untouched. - One refresh runs at a time — newer edits cancel the in-flight
subprocess instead of queuing up behind it. - Many edits in a short window collapse into a single workspace refresh.
- External file changes no longer collapse expanded tree nodes.
- Tests added or removed in a saved file appear/disappear immediately.
- A workspace refresh no longer runs a redundant per-document discover
for every open file.
Also fixes a non-deterministic tag order from the discover command so
the TS side can reliably detect real tag changes. - The tree only re-renders when the discovered tests actually change;
Refactor
-
diagnostics: Unify number-literal detection helpers (4dcb22f)
Replace the direct
robot.variables.finders.NumberFinderdependency and
the two duplicated_try_resolve_number_literalstatic methods with
sharedtry_resolve_number_literal/is_number_literalhelpers in
robot.utils.variables, consumed frommodel_helper,namespace_analyzer
and the semanticanalyzer. -
language-server: Pure SemanticModel for signature help and code action (2a4e728)
Both LSP feature paths now read everything off the SemanticModel — no
RF AST walks, no ModelHelper position helpers. SemanticToken carries a
precomputed LSP Range so consumers can use native operators
(pos in tok.range,range in tok.range,tok.range.extend(...))
instead of per-coordinate arithmetic. Output unchanged. -
repl: Unify the setting-alias flag and tidy completion internals (c3d50fe)
Review follow-up, no behaviour change:
- Use one name,
setting_import_aliases, for the flag everywhere (it was
include_setting_aliasesoncandidates_for_rich). - Make
_RobotCompleter's flag public so the_smart_tabkey binding reads it
off the active completer without reaching into a private attribute. - Move the assignment-target helpers above their first caller so there is no
forward reference. - Add completer-level tests: the
>>>completer forwards the flag into the
candidate service, and Tab after a setting alias opens completion instead of
inserting a cell separator.
- Use one name,
-
runner: Extract
discoverdata models and aligninfoJSON casing (95c119b)The
TestItem/ResultItem/Statistics/TagsResult/Info
classes move out ofdiscover.pyinto a dedicated_models.py,
matching the layout theresultsfamily already uses.discover.py
imports them from there, keeping the command file focused on click
wiring and traversal.Infowas the onlydiscovermodel withoutCamelSnakeMixin, so
discover infowas emittingrobot_version_string/python_version_string
/system_version/robot_envwhile every otherdiscoverand
resultsJSON key was already camelCase. It now uses the mixin too,
so-f json discover info(and the TEXT key:value rendering) speaks
the samerobotVersionString/pythonVersionString/systemVersion
/robotEnvshape as the rest. Tests and the reference docs follow. -
runner: Adopt SuiteVisitor for body traversal in
_search(000f2e9)Replace
_body_matches' manual recursion + string-baseditem.type
dispatch with aSuiteVisitorsubclass that overrides onestart_Xper
body-item type. Robot's own visitor handles the recursion; returning
Falsefrom each hook short-circuits the rest of the traversal once a
match is found.This drops every
getattrin the file: the fully-qualified keyword name
comes from the inheritedKeyword.nameproperty (which already composes
libname.kwnameon RF <7 result trees), result-tree-only.messageis
guarded withisinstance(item, StatusMixin),template(running-model
only) is guarded withisinstance(test, RunningTestCase), and the
For.assignvsFor.variablesrename is handled by one top-level
RF_VERSIONgate. RF 7+Var/Group/Errortypes come in via a
TYPE_CHECKINGimport with# type: ignore[attr-defined,unused-ignore].As a side-effect
Error.valuesis now part of the searched fields —
the old type-string dispatch silently skipped Error items. -
runner: Adopt ResultVisitor for body traversal in
results(5e5c88f)Replace manual body recursion (
_collect_test_body's build-pattern and
_count_all_messages' inlinewalk) withResultVisitorsubclasses that
override the per-typeend_Xmethods Robot's dispatch already provides.
This removes the string-baseditem.typechecks, eliminates the
remaininggetattrcalls on stable Robot attributes, and lets every body
item flow through one well-typed code path.Side cleanups in the same pass: hoist RF-version-conditional access
(kwname/libnamevsname/owner,For.assignvsFor.variables,
Result.elapsed_timevselapsedtime,StatusMixintime fields) into
top-level helpers gated onRF_VERSION, switch theVar/Group/Error
imports to aTYPE_CHECKING-only# type: ignore[attr-defined,unused-ignore]
form, and drop_eval_str— the profile is already evaluated before it
reaches this code, andStringExpression.__str__covers the rest. -
runner: Drop more
Anyfromresults.py(15 → 6) (8b4f059)Three more rounds of tightening on top of the previous pass:
_eval_str/_isoacceptobject(we use genericisinstance/
getattr/str()on them, no type-specific access)._make_message_entrytakesMessage— it's only called for
MESSAGE-typed body items, so the static type is precise._start_time/_end_timenow returnOptional[object](forwarded
unchanged to_iso, which acceptsobject).- The four RF-version-gated helpers (
_iter_all_tests,
_get_full_name,_keyword_name_and_owner,_loop_variables) get
properTestSuite/TestCaseparameters where the polymorphism
isn't on the input type. Internally they usegetattrfor the
attributes whose existence depends on the runtime RF version, so
mypy stays happy across the whole RF matrix without# type: ignore. Same behaviour, just less guesswork at call sites.
Anyremains on the six positions where it's the only honest answer:
the heterogeneous body-item helpers (_keyword_name_and_owner,
_loop_variables,_elapsed_seconds,_start_time,_end_time,
innerbuild). Each item type carries different attributes; we
dispatch bytypestring andgetattr. Typing them as a Union of 9+
result-tree classes would be heavier than the type safety it provides. -
runner: Replace
Anywith proper Robot types inresults.py(e70314f)Twenty-one stable-API positions get real type hints.
Anysurvives only
where it's genuinely the right answer:- The four RF-version-gated helpers (
_iter_all_tests,
_get_full_name,_keyword_name_and_owner,_loop_variables) —
each branch accesses attributes that exist only on the matching RF
version, and mypy sees only the installed one. - Body-item helpers and the inner
build(item)in_collect_test_body
— body items are aKeyword | For | If | Try | While | Var | Return | Group | Messageunion and we dispatch bygetattr(item, "type"). _elapsed_seconds/_start_time/_end_time— called on suites,
tests and keywords; truly polymorphic._iso,_eval_str,msg— string-or-something accepting helpers.
For everything else, the actual Robot class lands in the signature:
TestSuiteandTestCasefromrobot.result,Resultfor the loaded
execution result,ExecutionErrorsfor the errors collection,
RobotBaseProfilefor the resolved profile, andSuiteVisitorfor the
modifier list. No behaviour change; mypy is happy on every RF version
in the matrix. - The four RF-version-gated helpers (
-
runner: Collapse
resultsfilter pipeline into a single pass (93c3cf6)Every
resultssubcommand used to filter twice: first delegating
include/exclude/suite/test toTestSuite.filter()via
_apply_tree_filters, then re-walking the (still-full) tree inline to
apply--statusand--search. The matcher and the status-set lived
in each command body; helpers like_collect_counts/
_collect_failurestook the matcher and status filters as parameters.Collapse that into one pre-pass and one pre-pass only:
- Add a
ByStatusSuiteVisitorin_search.py(Robot has no native
status filter, so this stays ours, but in the same shape as
ByLongName/SearchModifier). - Extend
_apply_tree_filtersto also acceptstatus_filtersand the
search matcher, bundling every project-specific filter into a single
ModelModifierpass that visits the tree once. - After the pre-pass, every surviving test has cleared every filter, so
_collect_countsand_collect_failuresshrink to a plain tally /
[t for t in suite ... if t.status == "FAIL"]. The
_normalise_statuses/_raw_test_search_matcheshelpers and the
_STATUS_KEY_MAPconstant lose their last callers and go away too. - One subtle behaviour shift: search now matches
test.nameand
test.longnameseparately (viaSearchModifier), where the old
_raw_test_search_matchesonly saw the full name. That's a strict
superset — an anchored regex like^Pass.*now matches a test
literally namedPassing Test Three. Updated
test_search_regex_anchors_and_alternationto pick a pattern that
matches no field instead of relying on the old narrower contract.
- Add a
-
runner: Polish
results statsUX and docstrings (36e3996)--bynow displays the actual choices ([tag|suite|status]) in--help
instead of the placeholderDIMENSIONmetavar, so the allowed values
are discoverable without reading the docs.stats --by suitegroups by the suite's full name (e.g.
MyProject.Login) rather than the bare leaf name. Suites that share an
end name in different parts of the tree are now distinguished.- Drop internal
report.html/ "Mirrors X" justifications from
user-facing docstrings — that's plan-rationale, not help text.
-
tests: Standardize on pytest-mock and shared analyzer fixtures (441618c)
Replaces direct unittest.mock usage with the project's existing
pytest-mock convention so tests are stricter (autospec) and new tests
need less boilerplate. -
Drop three orphaned private symbols (38a7995)
Dead code surfaced by an unused-symbol sweep across
packages/:_BRANCHES(repl/_indent.py): a frozenset that was only there
to document which Robot keywords (ELSE,ELSE IF,EXCEPT,
FINALLY) the indent counter ignores. Replaced with a short
inline comment — same self-documenting effect, no orphan symbol._split_comma(analyze/code/cli.py): a click callback added
alongside the--xm/--xeexit-code-mask options, then
superseded by_parse_exit_code_maskand never wired up._cancel_all_running_tasks(core/concurrent.py): originally
the publiccancel_running_callables; the FutureEx → Task
rename privatised it but no caller followed.