Skip to content

feat(runs): runs list and runs show over the runs root (#94 Q6) - #307

Merged
xaleryb merged 20 commits into
intel:mainfrom
vlad-perevezentsev:feat/runs-list
Oct 31, 2026
Merged

xaleryb merged 20 commits into
intel:mainfrom
vlad-perevezentsev:feat/runs-list

Conversation

@vlad-perevezentsev

Copy link
Copy Markdown
Contributor

Summary

Refs #278, refs #94 (§2.3, Q6). Two new free, read-only commands over the runs root (results/ in the working directory, or DOKIMI_RUNS_DIR):

  • runs list: one row per artifact (schema_version, subject, model, time, path), newest first; --kind (repeatable), --subject, --json. A summary counts every skipped file by reason and names the unreadable ones.
  • runs show PATH: one artifact with its kind, schema check (errors listed), fields, list lengths and neighbouring files; --json.

Writers do not change and nothing is written (no index.jsonl). New package dokimi/runs/ (tracks layer: scan.py, kinds.py, show.py), CLI in commands/runs.py, docs in docs/runs.md. ResultsAggregator is not reused: it reads eval files only, and parses them. Not Fixes #278: grouping by run_id waits for #277.

Four commits, each green on its own: scan, runs list, runs show, docs.

Evidence

$ python cli.py runs list
SCHEMA           SUBJECT                     MODEL              TIME (UTC)         PATH
arms.v1          onetbb                      gpt-6.1-sol        2026-10-29 14:02   arms/onetbb.json
plugin_delta.v1  onetbb                      gpt-6.1-sol        2026-10-28 10:11*  arms/plugin_delta.json
eval.v1          -                           claude-sonnet-5-5  2026-10-28 10:05   onetbb_r7/eval/onetbb.json
answers.v1       onetbb                      gpt-6.1-sol        2026-10-28 09:40   onetbb_r7/answers/onetbb.json
novelty.v1       skill:skills/onetbb-tuning  claude-sonnet-5-5  2026-10-27 18:30   novelty/skill_skills_onetbb-tuning/novelty.json

5 artifacts under results/ (* the file's mtime: the artifact records no time)
skipped: 1 JSON with no leading schema_version, 1 JSON of an unknown schema_version (pairwise.v0: 1), 1 not .json

$ python cli.py runs show arms/onetbb.json
path:       arms/onetbb.json
kind:       arms (arms.v1)
schema:     valid
subject:    onetbb
model:      gpt-6.1-sol
time:       2026-10-29T14:02:11Z
run_id:     - (no artifact records one yet)
size:       3,503 bytes
contents:   arms: 4, answers: 0
next to it: onetbb.md, plugin_delta.json (plugin_delta.v1)

Speed (500 artifacts; scan() in process): 495 small artifacts take 0.04 s. Adding 5 artifacts of 58 MB takes 0.87 s, because each is parsed once. 5 non-artifact JSON files of 50 MB take 0.0002 s, because only their first 256 bytes are read. runs list wall time is 0.8 s and 1.7 s, mostly CLI start-up (dokimi --version 0.76 s), so no cache is needed.

Bad input, run by hand.

  • Exit 2: a DOKIMI_RUNS_DIR that is missing or a file.
  • Exit 0 with "no runs": no results/.
  • Exit 0, counted or listed with the reason, no traceback: an unreadable or unsearchable directory or file, a FIFO, a symlink loop, BOM, empty, list-shaped or too deeply nested JSON, a time out of range, control characters (printed escaped).
  • runs show: exit 0 on a schema-invalid artifact. Exit 2 on a non-artifact, an unknown version, a directory, a FIFO, ../x.json, /etc/passwd, or a truncated file.

Tests. test_runs_scan.py, test_runs_cli.py and test_runs_show.py run offline through the CLI.

  • Every registered kind is found from its fixture with the expected fields, and a test fails if a kind has no row.
  • They also cover each skip reason, head-only detection, ordering, exit codes, --json, and the schema check of a superseded version.

Checks.

  • About 35 mutations, each caught and reverted. Examples: kind read from the full JSON, a wrong subject path, a lost counter, show exiting 1 on an invalid schema, no inside-the-root check.
  • An independent review pass found 3 crashes (an unsearchable directory, a neighbour that cannot be stat'ed, a FIFO) and wrong doc claims. All are fixed in these commits, with tests.
  • Windows (Server 2025, Py 3.13): 80 passed, 9 skipped (POSIX-only cases). \ paths, other drives and ..\ behave as on Linux.
  • make ci-local: 0 failed (10691 passed).

Decisions

Each choice below is in the code already; the link points at it.

Choices that change visible behaviour if revisited

Choices that can only be extended later

  • One row per artifact. No artifact carries a run_id yet, so run_id is null until Artifact envelope for run artifacts, not inputs (#94 B1/B1b) #277.
  • No --verdict: almost no artifact has a verdict before result.v1.
  • Outside the root is not listed: repo-runs/ (no schema_version; R2 moves it), and the default outputs of answers/eval without --run-id, eval panel-score, questions generate|refine, repo reach and tools preference. docs/runs.md names them all.
  • The root comes only from DOKIMI_RUNS_DIR: --root is banned in cli_flags.py. A positional root can come later.
  • The kind comes from the first bytes (runs/scan.py:143): save_artifact writes schema_version first, and only known kinds are parsed. Artifacts saved before refactor(artifacts): write answers, eval and arms through save_artifact #27 are counted as "no leading schema_version".
  • Subject, model and time per kind (runs/kinds.py:35): a table names the field for each kind. Without such a field the column shows -, never a guess from the path. Answers use their records' shared library_name. When an artifact has several values, all are kept, and --subject matches any of them.
  • --subject matches exactly (case-sensitive).
  • show takes a path inside the root: relative to the root, absolute, or from the working directory. Addressing by run_id can come after Artifact envelope for run artifacts, not inputs (#94 B1/B1b) #277.
  • No index.jsonl: the scan is fast enough (Evidence).

These are the defaults this PR picks, not a settled contract: any of them can change here before merge, or move to #94/#278.

Merge Danger

Door: two-way. New commands and package; no existing behaviour or schema changes.

Blast Radius: only the runs group. Shared files get small edits:

  • cli.py: one import and one register.
  • dokimi/__init__.py docstring, the layer table and the CLI snapshot.
  • The flag allowlist: --subject added, with its reason.
  • Docs nav and index.
  • The benchmark's max_docs: 35 → 36, as its spec asks.

Overlap:

Whichever PR merges second makes these edits.

Not in this PR

  • Grouping by run_id, --verdict, runs explain|resume|replay|export|import|rm|gc|baseline, and index.jsonl.
  • cli_output.v1 (F2).

Found while testing, in code this PR does not change:

  • artifacts.stamp() puts schema_version last. As a result, the --json output of repo readiness|environment|budget and tasks inspect, saved under results/, is not listed.
  • questions generate records no product, so --subject cannot find those sets.

Checklist

  • Tests added and pytest passes (10691 passed, 57 skipped)
  • ruff, mypy, and schema checks pass (make ci-local)
  • Docs updated: docs/runs.md, nav and index; docs code-reference test and mkdocs build --strict pass
  • Self-reviewed per AGENTS.md: mutations, bad input, Windows run, an independent review pass
  • No ad-hoc run artifacts committed
  • New files carry the SPDX license header

… first bytes

New package dokimi/runs, in the tracks layer. runs_root() is
DOKIMI_RUNS_DIR when set, else results/ in the working directory, where
most commands write by default. A missing default root means no runs yet;
a DOKIMI_RUNS_DIR that does not exist, or a root that is not a
directory, is an InputError.

scan() walks the root once. save_artifact writes schema_version as the
first key, so a file whose first 256 bytes open with the schema_version
of a registered kind (current or superseded) is an artifact and is
parsed; any other file is counted by why it was skipped (no leading
schema_version, an unknown one, *.tmp, *.rejected, not .json, not a
regular file such as a FIFO, a symlinked directory) and never parsed. A file that cannot be read, or
whose body does not hold the version its head names, is listed as
unreadable with its reason. Artifacts come newest first by the time they
record, by mtime when they record none.

No field is shared by every kind, so dokimi/runs/kinds.py names per
kind where the subject, the model and the time are; a kind without one
reads as empty, never as a guess from the path. A test fails when a
kind of SCHEMA_VERSIONS has no row.

Refs intel#278

Signed-off-by: Vladislav Perevezentsev <vladislav.perevezentsev@intel.com>
dokimi runs list prints one row per artifact under the runs root:
schema_version, subject, model, recorded time (UTC, to the minute; the
file's mtime marked * when the artifact records none) and the path
relative to the root, newest first. Under the table a summary counts the
artifacts, every file skipped by reason (unknown schema_versions by
name) and the unreadable files with the first one's reason.

--kind KIND (repeatable, a kind of SCHEMA_VERSIONS) and --subject (an
exact match on one of the artifact's subjects) filter the rows. --json
prints the rows with the intel#94 field names (schema_version, kind, run_id,
subject, model, generated_at, path, size_bytes; run_id is null until
intel#277) plus root, total, skipped, unknown_versions and unreadable.

A missing default results/ prints "no runs" and exits 0. A
DOKIMI_RUNS_DIR that does not exist or is not a directory, or a results/
that is not a directory, exits 2 through InputError.

--subject is a new local flag, allowlisted with its reason; --kind was
already on the list. The CLI snapshot is regenerated.

Refs intel#278

Signed-off-by: Vladislav Perevezentsev <vladislav.perevezentsev@intel.com>
dokimi runs show PATH prints one artifact: its path, kind and
schema_version, the result of its schema check, subject, model, time
(the file's mtime when the artifact records none), size, the length of
the lists it holds and the entries next to it, each .json one with the
schema_version it opens with (the first 20 named, the rest counted).

PATH is the path runs list prints, relative to the root, or an absolute
or working-directory path that lies inside the root. The document is
checked against the schema of the version it declares, so a superseded
version is checked against its own schema. A failed check prints
"schema: invalid, N errors" and every error and exits 0: showing is not
a gate. A path outside the root, a missing file, a directory, an
entry that is not a regular file (a FIFO), a file that does not open with the
schema_version of a registered kind, or one that does not parse, exits 2.
Control characters in the printed fields are escaped.

--json prints the runs list row fields plus root, schema, schema_valid,
schema_errors, contents, siblings, siblings_total and siblings_error.

The kinds table gains the lists to count per kind; a test checks that
each is a top-level array of the kind's schema.

Refs intel#278

Signed-off-by: Vladislav Perevezentsev <vladislav.perevezentsev@intel.com>
docs/runs.md: what the runs root is and how DOKIMI_RUNS_DIR moves it,
an example of each command, which file counts as an artifact and why
the rest are counted but not read, where subject, model and time come
from, what is not listed yet (no run_id grouping until intel#277; repo-runs/,
answers/ and eval/ written without --run-id, and output flags pointing
outside the root), the --json fields and the exit codes.

The page goes in the mkdocs nav and the docs index, and quickstart's
output layout points to it. The static benchmark's max_docs rises to 36
for the new page, as its spec asks.

Refs intel#278

Signed-off-by: Vladislav Perevezentsev <vladislav.perevezentsev@intel.com>
@vlad-perevezentsev vlad-perevezentsev self-assigned this Oct 30, 2026
@vlad-perevezentsev
vlad-perevezentsev requested a review from a team as a code owner October 30, 2026 14:26
@github-actions github-actions Bot added the cli-interface-change Changes dokimi's user-facing CLI surface label Oct 30, 2026
@github-actions

Copy link
Copy Markdown

CLI interface change detected

This PR changes dokimi's user-facing CLI surface (commands and/or options):

+ added command `dokimi runs`
    + option `--help/-h`
+ added command `dokimi runs list`
    + option `--help/-h`
    + option `--json`
    + option `--kind`
    + option `--subject`
+ added command `dokimi runs show`
    + argument `path`
    + option `--help/-h`
    + option `--json`

Updated on every push; the cli-interface-change label is on while the diff is non-empty.

@exai-bot

exai-bot commented Oct 30, 2026 •

Copy link
Copy Markdown

✅ OpenCodeReview: Review complete: 0 finding(s) across 23 selected item(s).

Review details
  • Commit reviewed: 7b73110 against merge base fde3440
  • Coverage: 23 files in 6 groups
  • Engine: OpenCodeReview v1.13.3, us.openai.gpt-6.1-sol
  • Usage: 477k tokens (258k from cache), 41s
  • Tool calls: 31 (27 file_read, 4 code_search)
  • Runs discovery and inspection implementation and tests: 7 files
  • Runs CLI integration, interface reference, and tests: 7 files
  • Runs user documentation and changelog: 5 files
  • Architecture documentation and import boundaries: 2 files
  • CI workflow configuration: 1 file
  • Benchmark specification: 1 file

Comment thread dokimi/dokimi/commands/runs.py Resolved
Comment thread dokimi/dokimi/commands/runs.py Resolved
Comment thread dokimi/dokimi/runs/show.py Resolved
Comment thread dokimi/dokimi/runs/show.py Resolved
@codecov-commenter

codecov-commenter commented Oct 30, 2026 •

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 98.69110% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.98%. Comparing base (fde3440) to head (7b73110).

Files with missing lines Patch % Lines
dokimi/dokimi/runs/scan.py 97.68% 4 Missing ⚠️
dokimi/dokimi/runs/show.py 98.85% 1 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #307      +/-   ##
==========================================
+ Coverage   93.92%   93.98%   +0.05%     
==========================================
  Files         284      289       +5     
  Lines       36767    37150     +383     
  Branches     6200     6242      +42     
==========================================
+ Hits        34532    34914     +382     
- Misses       1437     1439       +2     
+ Partials      798      797       -1     
Files with missing lines Coverage Δ
dokimi/dokimi/__init__.py 100.00% <ø> (ø)
dokimi/dokimi/cli_routes.py 100.00% <ø> (ø)
dokimi/dokimi/commands/runs.py 100.00% <100.00%> (ø)
dokimi/dokimi/runs/__init__.py 100.00% <100.00%> (ø)
dokimi/dokimi/runs/kinds.py 100.00% <100.00%> (ø)
dokimi/dokimi/runs/show.py 98.85% <98.85%> (ø)
dokimi/dokimi/runs/scan.py 97.68% <97.68%> (ø)

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…t crash

head_version keeps any character but an ASCII control, so an unknown
schema_version could carry a Unicode line separator (U+2028) into the
runs list summary and the runs show error. Both now go through the one
escaping helper, plain(), moved to dokimi/runs/scan.py.

tmpfs keeps an mtime past the year 9999, where datetime.fromtimestamp
raises: the text of runs list and runs show crashed on an untimed
artifact with such an mtime (--json did not). The time column and the
show line now print it as @<seconds>.

Refs intel#278

Signed-off-by: Vladislav Perevezentsev <vladislav.perevezentsev@intel.com>
On Python 3.11-3.13 Path.exists(), is_dir() and is_file() raise
PermissionError for a path under a directory that cannot be searched.
RunsRoot.exists() (a DOKIMI_RUNS_DIR below such a directory) and
runs show's resolve() (an address in such a directory) let it out, and
the command crashed with a traceback and exit 1. Both now raise
InputError with the reason, so the command prints it and exits 2.
Python 3.14 answers False there, and the message is the existing "does
not exist" / "no file"; the tests accept either.

Refs intel#278

Signed-off-by: Vladislav Perevezentsev <vladislav.perevezentsev@intel.com>
runs show checked that the address lay inside the root as spelled, so
results/linked -> /elsewhere let runs show linked/eval.json read a file
outside the root (and list its neighbours), and runs list read a file
symlink that pointed outside. intel#278 lists only what is under the root.

The rule is now the same for both commands: a file is read only when its
real path lies inside the real root. runs list counts a file symlink that
leads out as skipped (linked_outside, "symlinks to files outside the
root (not read)"); runs show exits 2 with "... leads outside the runs
root"; a neighbour that links out is named but its head is not read. A
symlink inside the root, and a root that is itself a symlink, work as
before, and runs show keeps the name the address used. Symlinked
directories are still not walked by runs list.

Refs intel#278

Signed-off-by: Vladislav Perevezentsev <vladislav.perevezentsev@intel.com>
Comment thread dokimi/docs/runs.md Resolved
Comment thread dokimi/dokimi/runs/show.py Resolved
…pened

Two documented behaviours had no test (Codecov on intel#307): runs list
prints a recorded time it cannot parse as written, and runs show exits
2 on an artifact it may not open. The open error now takes its wording
from read_error_reason, as every other read error does; the message is
unchanged.

Refs intel#278

Signed-off-by: Vladislav Perevezentsev <vladislav.perevezentsev@intel.com>
Comment thread dokimi/dokimi/runs/scan.py Resolved
Comment thread dokimi/dokimi/runs/show.py Resolved
…n fail to

docs/runs.md said a file that does not parse is listed as unreadable.
Only a file that opens with a registered schema_version is parsed; a
broken file of no registered kind is counted as skipped. Say so, and that
the text summary names the first unreadable file while --json lists all.

Refs intel#278

Signed-off-by: Vladislav Perevezentsev <vladislav.perevezentsev@intel.com>
cli.main prints an InputError as it is, so a runs show address or a
DOKIMI_RUNS_DIR with a newline or an escape sequence reached stderr raw.
Every message of resolve(), _version(), show(), RunsRoot.exists() and
runs show's missing-root error now names them through plain(); the
paths used to read files are unchanged.

Refs intel#278

Signed-off-by: Vladislav Perevezentsev <vladislav.perevezentsev@intel.com>
Comment thread dokimi/docs/runs.md Resolved
A junction is not a symlink, and os.walk(followlinks=False) still
descends into one on Python 3.11-3.13, so runs list read and listed the
files of a junction that points outside the root (runs show already
refused them by real path), and a junction back into the root would be
walked twice. A directory that is a symlink or a junction (st_reparse_tag
IO_REPARSE_TAG_MOUNT_POINT, which 3.11 reads too) is now pruned before
the walk descends and counted as "symlinked directories and junctions
(not walked)". The test runs on Windows only.

Refs intel#278

Signed-off-by: Vladislav Perevezentsev <vladislav.perevezentsev@intel.com>
resolve() checked the address as the filesystem resolves it, then made
it absolute with os.path.abspath, which folds "link/.." before the
symlink is followed: with results/link -> results/nested/deep,
runs show link/../eval.json checked results/nested/eval.json and read
results/eval.json. The path is now made absolute with Path.absolute(),
which keeps "..", and an address with ".." is shown and read by its
real path.

Refs intel#278

Signed-off-by: Vladislav Perevezentsev <vladislav.perevezentsev@intel.com>
The test nested 100 000 arrays to make json raise RecursionError. On
Python 3.14 the C parser is bounded by the C stack, not the recursion
limit, and parses that document, so the test failed on CI's 3.14 leg
while the scanner was right. The parse now raises RecursionError through
a patched load_document, and the test checks that the file is listed as
unreadable with that reason, on every interpreter.

Refs intel#278

Signed-off-by: Vladislav Perevezentsev <vladislav.perevezentsev@intel.com>
docs/runs.md and the changelog fragment said a file is an artifact when
it opens with a registered schema_version. head_version reads only the
first 256 bytes, so a file whose first key comes later (after 1000
spaces, say) is skipped. Say that; save_artifact's output always fits.

Refs intel#278

Signed-off-by: Vladislav Perevezentsev <vladislav.perevezentsev@intel.com>
Comment thread dokimi/dokimi/runs/show.py Resolved
resolve() accepts an address whose real path is inside the root, and
keeps the spelled path for display. With results/linked -> /elsewhere
and /elsewhere/return.json -> results/real.json, runs show
linked/return.json was accepted, and its neighbours were listed from
/elsewhere: outside file names and schema_versions in the output. When
the spelled directory does not resolve inside the root, the neighbours
now come from the artifact's own (real) directory.

Refs intel#278

Signed-off-by: Vladislav Perevezentsev <vladislav.perevezentsev@intel.com>
Comment thread dokimi/dokimi/runs/show.py Outdated
Comment on lines +76 to +77
if ".." not in spelled.parts and inside(root, spelled): # keep the name runs list prints
return spelled, root.absolute()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

bug · medium
Must-fix: account for .. in the root as well as in the address. For example, from /tmp/work, with an artifact at /tmp/results/e.json, DOKIMI_RUNS_DIR=../results python cli.py runs show /tmp/results/e.json passes the containment checks but returns /tmp/results/e.json alongside /tmp/work/../results. read_artifact() then calls path.relative_to(root), which is lexical and raises ValueError, so a valid artifact exits 2. Use the resolved-path fallback when the absolute root contains .., and add a regression test for an absolute address with a parent-relative runs root.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 34e76e1. Reproduced: from work/ with DOKIMI_RUNS_DIR=../results, runs show <absolute path of results/e.json> exited 2 with the relative_to error, while runs show e.json worked. A .. in the root now takes the real-path branch as a .. in the address does, so both addresses show e.json. Regression test added; the runs tests also pass on Windows.

…h ..

resolve() kept the spelled path when the address had no "..", and
returned it with root.absolute(). For a root such as
DOKIMI_RUNS_DIR=../results that base still holds "..", and
read_artifact's lexical relative_to failed: an absolute address of a
valid artifact exited 2. A ".." in the root now takes the real-path
branch too, so the address is shown relative to the real root.

Refs intel#278

Signed-off-by: Vladislav Perevezentsev <vladislav.perevezentsev@intel.com>

@napetrov napetrov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review at head 34e76e1 (delta 33f8422..34e76e1: bdc14ac, 942ecdf, 2f31691, 34e76e1; no merges of main in the range).

The fix in 34e76e1 holds by probe: with DOKIMI_RUNS_DIR=../results, an absolute address under the root now exits 0 (it exited 2 at 33f8422). Symlinks that lead outside the root are still refused. Neighbour listing from inside the root (2f31691) is covered by its test.

Tests on the head: runs show, runs scan, runs cli, cli flags, cli surface and the import-architecture test pass (208 passed, 2 skipped). ruff check and mypy are clean on the touched runs modules.

The four behaviours I checked are fine, each with a docs note:

  1. stamp writes schema_version last, so results from readiness, environment and budget are not listed by runs list. Docs note: one sentence under "Nothing is dropped silently" saying that such files are skipped as having no leading schema_version.
  2. --subject is a row filter, not an input. Docs note: one sentence next to the --kind/--subject bullet saying it filters rows and selects no subject for other commands.
  3. runs show on a *.rejected file exits 0 and checks the schema, while runs list skips *.rejected by name. Docs note: one sentence in the runs show paragraph saying a *.rejected payload is readable by show and exits 0.
  4. A path through a symlinked directory inside the root works with show, and the path it prints depends on how the root is spelled (as spelled for an absolute root, canonical for a root spelled with ..); runs list never prints the symlinked path. Docs note: one sentence saying the printed path can differ from the runs list path.

One inline nit, still present at this head and not introduced by the delta. Not blocking.

if stamp:
return stamp.strftime("%Y-%m-%d %H:%M")
if artifact.generated_at: # not ISO 8601, or out of range: shown as written
return artifact.generated_at

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: _when returns the raw generated_at string for a time that is not ISO 8601, with no *. The mtime fallback below it carries one. runs list sorts such a row by its file mtime, so a row that prints not a time can sort above a row recorded 2026-10-29 (probe: q1.json with generated_at: "not a time" and today's mtime, against arms/a.json). Suggest marking the raw string too, or showing the mtime with *.

@napetrov napetrov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Checked against #94 (§2.3, Q6, R1–R3, J11, F2) and #278. Aligned overall: runs root results/ + DOKIMI_RUNS_DIR, scan with no index (the index is an optional cache per Q6), pre-envelope files listed (R1), --kind/--subject, exit 2 for bad input, show reads and does not gate, --root banned, #94 field names. "Refs" rather than "Fixes" #278 is right.

Two things to settle before merge, so later stages don't need a breaking change:

  1. runs show positional. Here it is a file path; #94 J11 has runs show $RUN (a run, later with an explain section). Once #277 brings run_id, the same positional would need to take both a run and a file. Could we decide now how a run is named, e.g. runs show RUN plus runs show --artifact PATH, or a documented rule for telling the two apart? Otherwise the switch needs a tombstone later.

  2. --json before cli_output.v1. main has no envelope yet, so this is fine today, but the raw shape (root, artifacts, skipped, ...) becomes something scripts depend on until F2. Please add one line to docs/runs.md saying the shape is pre-envelope and F2 wraps it, keeping the field names.

Nit: the text table heads the column SCHEMA, but the filter is --kind; a KIND column would match the flag.

@napetrov

Copy link
Copy Markdown
Contributor

Heads-up on merge order: this conflicts with #284 (#94 A1) in dokimi/cli.py. #284 turns the top-level command list into a route table with sections and cost labels, so a new runs group becomes one row there (section "runs", cost free) instead of a new add_parser block. #284 is green with every thread answered; if it lands first I can do the rebase of this one's cli.py hunk, or the other way round, whichever the reviewers prefer.

Brings in intel#284 (route table), intel#254 (flag registry, CLI snapshot) and the
cli_routes.v1 artifact from main. Resolved:

- cli.py: runs and data both register; the table lists runs.
- cli_routes.py: runs is a root in "Analysis and data" with runs list and
  runs show as free leaves.
- runs/kinds.py: cli_routes.v1 gets its counted lists, so runs show and runs
  list handle the new artifact kind.
- Tests: the expected route sections, the scan and show kind tables include
  cli_routes.v1.
- cli-interface.json regenerated with make cli-snapshot.

Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
@napetrov

Copy link
Copy Markdown
Contributor

Merged intel/dokimi main (72d7add) into feat/runs-list as one merge commit, b4b0fd6, on top of 34e76e1. No history rewrite.

  • dokimi/cli.py: the conflict kept both registrations, runs and main's data.
  • dokimi/cli_routes.py: runs is a root in "Analysis and data", with runs list and runs show as free leaves.
  • dokimi/runs/kinds.py: main's new cli_routes.v1 artifact gets a kinds row. The scan and show test tables get the matching row, and the route help test expects runs.
  • docs/reference/cli-interface.json regenerated with make cli-snapshot.

Full suite on the merge (py3.13 venv): 11041 passed, 7 skipped. Your commits are unchanged.

Comment on lines +134 to +135
shown = Shown(artifact=artifact, schema=schema, errors=schema_errors(schema, data),
contents=contents(kind, data))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

bug · medium
Must-fix: schema validation can still raise an unhandled RecursionError after JSON loading succeeds. For example, an arms.v1 document with a deeply nested array in model can parse successfully but exceed the recursion limit when jsonschema formats that value for its string-type error. schema_errors() does not catch this, and the CLI catches only InputError/EmptyQuestionError, so runs show emits a traceback instead of a controlled diagnostic. Handle recursion failures around validation too, and add a test covering validation-time recursion (the scan test only covers loading).

@xaleryb

xaleryb commented Oct 31, 2026

Copy link
Copy Markdown
Contributor
  • Ran: full suite, ruff, mypy and bandit on b4b0fd6 (all clean), plus a mutation pass over the new runs guards.
  • Windows junction guard is not covered by CI: test_a_junction_is_counted_and_not_walked (tests/test_runs_scan.py) runs only on Windows, and the windows-smoke job runs only tests/test_cli_help.py tests/test_console_encoding.py. Input: change _JUNCTION_TAG in runs/scan.py to another value -> observed: every job stays green -> expected: a job goes red.
  • Proposal for the author: append tests/test_runs_scan.py tests/test_runs_show.py to the windows-smoke pytest step in .github/workflows/ci.yml, and confirm it is green on windows-latest.
  • No commits from us.
  • Left for the author: the CI line above, and napetrov's open notes (docs sentences, --json pre-envelope line, runs show positional).

Conflicts were additive: keep both the runs root (intel#307) and the backends root (main)
in cli.py, ROOTS/LEAVES of cli_routes.py and the Analysis-and-data help test, runs first.

Signed-off-by: Alexander Rybkin <alexander.rybkin@intel.com>
test_a_junction_is_counted_and_not_walked skips off Windows, so no CI job ran the only test of the runs-root containment on Windows.

Signed-off-by: Alexander Rybkin <alexander.rybkin@intel.com>
@xaleryb

xaleryb commented Oct 31, 2026

Copy link
Copy Markdown
Contributor
  • Merged main after feat(llm): claude-cli provider: run the Q&A track on a logged-in Claude Code CLI #255 (32b0d91). cli.py, cli_routes.py and test_cli_routes.py conflicted, and both sides are kept: runs list/runs show and backends now sit together under "Analysis and data". The CLI snapshot regenerated on Python 3.13 is byte-identical. Full suite, ruff, mypy and bandit pass on Linux.
  • Pushed 391a9f6, which settles the Windows point from the earlier comment: windows-smoke now also runs tests/test_runs_scan.py and tests/test_runs_show.py, so the junction containment test runs in CI. Its result on this push is the check.

Main reached 36 docs with intel#255, and this branch adds docs/runs.md, so the merged tree has 37.

Signed-off-by: Alexander Rybkin <alexander.rybkin@intel.com>
@xaleryb

xaleryb commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

@xaleryb xaleryb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approving 7b73110: CI green, including windows-smoke with the runs tests and benchmark at max_docs 37. The Windows junction point from the earlier comment is covered by 391a9f6.

@xaleryb
xaleryb merged commit 17aecf7 into intel:main Oct 31, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli-interface-change Changes dokimi's user-facing CLI surface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants