verifaied 0.25.0.dev53__tar.gz → 0.28.0.dev71__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/.gitignore +7 -1
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/PKG-INFO +57 -11
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/README.md +56 -10
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/pyproject.toml +1 -1
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/cli.py +133 -1
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/recorder_driver.js +5 -5
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/recorder_refs.js +8 -8
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/repo_config.py +168 -23
- verifaied-0.28.0.dev71/src/verifaied/skill/SKILL.md +168 -0
- verifaied-0.28.0.dev71/src/verifaied/skill/reference/commands.md +194 -0
- verifaied-0.28.0.dev71/src/verifaied/skillcmd.py +147 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/testcmd.py +179 -21
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_repo_config.py +133 -5
- verifaied-0.28.0.dev71/tests/test_skill_parity.py +181 -0
- verifaied-0.28.0.dev71/tests/test_skillcmd.py +347 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_testcmd.py +358 -17
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/uv.lock +2 -2
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/LICENSE +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/__init__.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/__main__.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/agent_mcp.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/agent_steps.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/analyzer.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/audit.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/client.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/config.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/failure_text.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/instrument.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/instrument_snippets.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/instrumenter.js +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/instrumenter.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/prompts.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/proxy.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/record.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/recorder_observer.js +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/recorder_picker.js +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/recorder_spec.js +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/run_reporter.js +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/source_index.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/stepcheck.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/subprocess_util.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/suite_report.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/uploader.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/src/verifaied/varcmd.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/__init__.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/conftest.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_agent_mcp.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_audit.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_check.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_check_done.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_clear_manual.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_cli.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_client.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_config.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_instrument.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_instrument_detect.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_instrument_snippets.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_instrumenter.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_prompt_parity.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_proxy.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_record.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_reporter_parity.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_source_index.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_stepcheck_parity.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_suite_report.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_uploader.py +0 -0
- {verifaied-0.25.0.dev53 → verifaied-0.28.0.dev71}/tests/test_varcmd.py +0 -0
|
@@ -69,12 +69,18 @@ TODO.md
|
|
|
69
69
|
*.tsbuildinfo
|
|
70
70
|
|
|
71
71
|
# Parallel worktrees. `.worktree.mk` is the per-checkout port/project block
|
|
72
|
-
#
|
|
72
|
+
# `.agent/worktree-setup.sh` generates (`.env.worktree`, its shell twin, is
|
|
73
73
|
# already covered by `**/.env.*` above). `.mcp.json` carries a live
|
|
74
74
|
# `vr_live_…` bearer token — it is machine-local config, never repo config.
|
|
75
75
|
.worktree.mk
|
|
76
76
|
.mcp.json
|
|
77
77
|
|
|
78
|
+
# The coordinator's marker for the tree it is standing in: which slot it
|
|
79
|
+
# claims, and whether its build ever finished. Written per checkout, read
|
|
80
|
+
# by the daemon, meaningless anywhere else. Everything else in `.agent/` is
|
|
81
|
+
# committed on purpose.
|
|
82
|
+
.agent/worktree.json
|
|
83
|
+
|
|
78
84
|
# Beads / Dolt files (added by bd init)
|
|
79
85
|
.dolt/
|
|
80
86
|
*.db
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: verifaied
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.28.0.dev71
|
|
4
4
|
Summary: Find what's untested in your code — locally, no account required
|
|
5
5
|
Project-URL: Homepage, https://pypi.org/project/verifaied/
|
|
6
6
|
Author: Kyle Richards
|
|
@@ -425,6 +425,11 @@ verifaied test run --all
|
|
|
425
425
|
# Point any of them at another configured environment.
|
|
426
426
|
verifaied test run --all --env stage
|
|
427
427
|
|
|
428
|
+
# How much of the run's clock goes on making the video watchable.
|
|
429
|
+
# `fast` (the default) marks what each step clicks and moves on;
|
|
430
|
+
# `watch` lingers on every action; `off` records without annotations.
|
|
431
|
+
verifaied test run "Settings/API tokens" --video watch
|
|
432
|
+
|
|
428
433
|
# What's recorded, and how each last went on this branch.
|
|
429
434
|
verifaied test list
|
|
430
435
|
|
|
@@ -918,11 +923,18 @@ it — the CLI finds the first one that has it, and `--runner-dir`
|
|
|
918
923
|
overrides). This is Node Playwright, not the Python `verifaied[audit]`
|
|
919
924
|
extra.
|
|
920
925
|
|
|
921
|
-
**`test record` and `test studio`
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
+
**`test record` and `test studio` need `@playwright/test` 1.60 or later.**
|
|
927
|
+
Recording is driven by our own Node program through public Playwright API
|
|
928
|
+
— the selector generator behind `PWDEBUG=console`, the AI-mode
|
|
929
|
+
accessibility snapshot and the `aria-ref=` selectors its refs resolve
|
|
930
|
+
through — and every recording ends in a replay, whose video marks what
|
|
931
|
+
was clicked with `video.show`. 1.60 is where the last of those shipped,
|
|
932
|
+
so it is a floor and not an allowlist: anything newer is allowed, and
|
|
933
|
+
anything older is refused rather than opening a browser that would
|
|
934
|
+
record nothing. `test run` stays ungated. Below 1.60 the annotation is
|
|
935
|
+
not available, so set `replay_show_actions_ms = 0` and
|
|
936
|
+
`replay_video_step_banner = false` there — that writes exactly the
|
|
937
|
+
config the CLI wrote before this option existed.
|
|
926
938
|
|
|
927
939
|
### Exit codes
|
|
928
940
|
|
|
@@ -961,12 +973,46 @@ and `--no-replay` to skip the replay. `run` takes `--all` in place of a
|
|
|
961
973
|
test name. `studio` takes `--no-replay` and takes no test name at all —
|
|
962
974
|
what it records is whatever the web asks for.
|
|
963
975
|
|
|
976
|
+
## `verifaied skill install` — hand the loop to your agent
|
|
977
|
+
|
|
978
|
+
The CLI ships the agent skill for using it. One command writes it where a
|
|
979
|
+
coding agent will find it:
|
|
980
|
+
|
|
981
|
+
```bash
|
|
982
|
+
verifaied skill install # this project: .claude/skills/verifaied
|
|
983
|
+
verifaied skill install --user # every project: ~/.claude/skills/verifaied
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
The skill teaches the loop below — run the tests with coverage, `verifaied
|
|
987
|
+
upload`, `verifaied check-done`, fix what comes back, repeat until done — plus
|
|
988
|
+
the vitest/Istanbul requirement for TypeScript, the recorder for browser
|
|
989
|
+
flows, `verifaied audit`, and the rules that keep the loop honest (no lowered
|
|
990
|
+
thresholds, no `# pragma: no cover`, no `xfail` over a real failure).
|
|
991
|
+
|
|
992
|
+
`install` with no flags writes into the **repository root** you are standing
|
|
993
|
+
in, so running it from a subdirectory still lands the skill where your agent
|
|
994
|
+
looks for it. Outside a repository it writes into the current directory.
|
|
995
|
+
|
|
996
|
+
Because it ships inside this package, the skill can never describe a command
|
|
997
|
+
the installed CLI does not have. It is two files, `SKILL.md` and a command
|
|
998
|
+
reference the agent opens only when it needs a flag, and they land in a
|
|
999
|
+
`verifaied` folder inside the skills directory — yours to read and, in the
|
|
1000
|
+
project-local case, to commit for the rest of the team.
|
|
1001
|
+
|
|
1002
|
+
Re-running the command writes nothing when the installed copy already matches.
|
|
1003
|
+
A copy that differs, because you edited it or because you have since upgraded
|
|
1004
|
+
the CLI, is left alone until you pass `--force`, which replaces the files
|
|
1005
|
+
verifAIed ships and never removes anything you added alongside them. Install
|
|
1006
|
+
somewhere else entirely with `--dir <path>`.
|
|
1007
|
+
|
|
1008
|
+
Exit codes: `0` installed, updated, or already up to date; `1` usage error
|
|
1009
|
+
(`--user` with `--dir`, or a differing copy without `--force`).
|
|
1010
|
+
|
|
964
1011
|
## Agent loop
|
|
965
1012
|
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
`.github/copilot-instructions.md`) so it self-corrects on every change.
|
|
1013
|
+
Agents that do not read `.claude/skills/` want the same loop in their
|
|
1014
|
+
instructions file (`CLAUDE.md`, `AGENTS.md`, `.cursorrules`, `GEMINI.md`,
|
|
1015
|
+
`.github/copilot-instructions.md`), so they self-correct on every change.
|
|
970
1016
|
|
|
971
1017
|
The easiest way is to let your agent write that loop into the rules
|
|
972
1018
|
file for you. Paste the prompt below into your agent — it will inspect
|
|
@@ -1046,7 +1092,7 @@ After implementing or modifying any code in this repo, run this loop until verif
|
|
|
1046
1092
|
```
|
|
1047
1093
|
2. Upload the results to verifAIed:
|
|
1048
1094
|
```
|
|
1049
|
-
verifaied upload
|
|
1095
|
+
verifaied upload --junit junit.xml
|
|
1050
1096
|
```
|
|
1051
1097
|
3. Ask if you're done: call the `check_done` tool on the verifAIed MCP server (or run `verifaied check-done`). It returns `{done, status, gaps}` for this branch — failing tests plus untested/partially-covered functions among the ones you changed.
|
|
1052
1098
|
4. If `done` is true, stop — the branch is covered.
|
|
@@ -379,6 +379,11 @@ verifaied test run --all
|
|
|
379
379
|
# Point any of them at another configured environment.
|
|
380
380
|
verifaied test run --all --env stage
|
|
381
381
|
|
|
382
|
+
# How much of the run's clock goes on making the video watchable.
|
|
383
|
+
# `fast` (the default) marks what each step clicks and moves on;
|
|
384
|
+
# `watch` lingers on every action; `off` records without annotations.
|
|
385
|
+
verifaied test run "Settings/API tokens" --video watch
|
|
386
|
+
|
|
382
387
|
# What's recorded, and how each last went on this branch.
|
|
383
388
|
verifaied test list
|
|
384
389
|
|
|
@@ -872,11 +877,18 @@ it — the CLI finds the first one that has it, and `--runner-dir`
|
|
|
872
877
|
overrides). This is Node Playwright, not the Python `verifaied[audit]`
|
|
873
878
|
extra.
|
|
874
879
|
|
|
875
|
-
**`test record` and `test studio`
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
+
**`test record` and `test studio` need `@playwright/test` 1.60 or later.**
|
|
881
|
+
Recording is driven by our own Node program through public Playwright API
|
|
882
|
+
— the selector generator behind `PWDEBUG=console`, the AI-mode
|
|
883
|
+
accessibility snapshot and the `aria-ref=` selectors its refs resolve
|
|
884
|
+
through — and every recording ends in a replay, whose video marks what
|
|
885
|
+
was clicked with `video.show`. 1.60 is where the last of those shipped,
|
|
886
|
+
so it is a floor and not an allowlist: anything newer is allowed, and
|
|
887
|
+
anything older is refused rather than opening a browser that would
|
|
888
|
+
record nothing. `test run` stays ungated. Below 1.60 the annotation is
|
|
889
|
+
not available, so set `replay_show_actions_ms = 0` and
|
|
890
|
+
`replay_video_step_banner = false` there — that writes exactly the
|
|
891
|
+
config the CLI wrote before this option existed.
|
|
880
892
|
|
|
881
893
|
### Exit codes
|
|
882
894
|
|
|
@@ -915,12 +927,46 @@ and `--no-replay` to skip the replay. `run` takes `--all` in place of a
|
|
|
915
927
|
test name. `studio` takes `--no-replay` and takes no test name at all —
|
|
916
928
|
what it records is whatever the web asks for.
|
|
917
929
|
|
|
930
|
+
## `verifaied skill install` — hand the loop to your agent
|
|
931
|
+
|
|
932
|
+
The CLI ships the agent skill for using it. One command writes it where a
|
|
933
|
+
coding agent will find it:
|
|
934
|
+
|
|
935
|
+
```bash
|
|
936
|
+
verifaied skill install # this project: .claude/skills/verifaied
|
|
937
|
+
verifaied skill install --user # every project: ~/.claude/skills/verifaied
|
|
938
|
+
```
|
|
939
|
+
|
|
940
|
+
The skill teaches the loop below — run the tests with coverage, `verifaied
|
|
941
|
+
upload`, `verifaied check-done`, fix what comes back, repeat until done — plus
|
|
942
|
+
the vitest/Istanbul requirement for TypeScript, the recorder for browser
|
|
943
|
+
flows, `verifaied audit`, and the rules that keep the loop honest (no lowered
|
|
944
|
+
thresholds, no `# pragma: no cover`, no `xfail` over a real failure).
|
|
945
|
+
|
|
946
|
+
`install` with no flags writes into the **repository root** you are standing
|
|
947
|
+
in, so running it from a subdirectory still lands the skill where your agent
|
|
948
|
+
looks for it. Outside a repository it writes into the current directory.
|
|
949
|
+
|
|
950
|
+
Because it ships inside this package, the skill can never describe a command
|
|
951
|
+
the installed CLI does not have. It is two files, `SKILL.md` and a command
|
|
952
|
+
reference the agent opens only when it needs a flag, and they land in a
|
|
953
|
+
`verifaied` folder inside the skills directory — yours to read and, in the
|
|
954
|
+
project-local case, to commit for the rest of the team.
|
|
955
|
+
|
|
956
|
+
Re-running the command writes nothing when the installed copy already matches.
|
|
957
|
+
A copy that differs, because you edited it or because you have since upgraded
|
|
958
|
+
the CLI, is left alone until you pass `--force`, which replaces the files
|
|
959
|
+
verifAIed ships and never removes anything you added alongside them. Install
|
|
960
|
+
somewhere else entirely with `--dir <path>`.
|
|
961
|
+
|
|
962
|
+
Exit codes: `0` installed, updated, or already up to date; `1` usage error
|
|
963
|
+
(`--user` with `--dir`, or a differing copy without `--force`).
|
|
964
|
+
|
|
918
965
|
## Agent loop
|
|
919
966
|
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
`.github/copilot-instructions.md`) so it self-corrects on every change.
|
|
967
|
+
Agents that do not read `.claude/skills/` want the same loop in their
|
|
968
|
+
instructions file (`CLAUDE.md`, `AGENTS.md`, `.cursorrules`, `GEMINI.md`,
|
|
969
|
+
`.github/copilot-instructions.md`), so they self-correct on every change.
|
|
924
970
|
|
|
925
971
|
The easiest way is to let your agent write that loop into the rules
|
|
926
972
|
file for you. Paste the prompt below into your agent — it will inspect
|
|
@@ -1000,7 +1046,7 @@ After implementing or modifying any code in this repo, run this loop until verif
|
|
|
1000
1046
|
```
|
|
1001
1047
|
2. Upload the results to verifAIed:
|
|
1002
1048
|
```
|
|
1003
|
-
verifaied upload
|
|
1049
|
+
verifaied upload --junit junit.xml
|
|
1004
1050
|
```
|
|
1005
1051
|
3. Ask if you're done: call the `check_done` tool on the verifAIed MCP server (or run `verifaied check-done`). It returns `{done, status, gaps}` for this branch — failing tests plus untested/partially-covered functions among the ones you changed.
|
|
1006
1052
|
4. If `done` is true, stop — the branch is covered.
|
|
@@ -45,7 +45,20 @@ from verifaied.instrument import run_instrument
|
|
|
45
45
|
from verifaied.prompts import build_prompt, format_line_ranges
|
|
46
46
|
from verifaied.proxy import DEFAULT_PROXY_PORT
|
|
47
47
|
from verifaied.record import DEFAULT_INTERVAL, DEFAULT_PORT, run_record
|
|
48
|
-
from verifaied.repo_config import
|
|
48
|
+
from verifaied.repo_config import (
|
|
49
|
+
CONFIG_PATH,
|
|
50
|
+
ENV_KEY,
|
|
51
|
+
SECTION,
|
|
52
|
+
RepoConfigError,
|
|
53
|
+
VideoProfile,
|
|
54
|
+
)
|
|
55
|
+
from verifaied.skillcmd import (
|
|
56
|
+
SKILL_NAME,
|
|
57
|
+
SkillInstallError,
|
|
58
|
+
detect_project_root,
|
|
59
|
+
install_skill,
|
|
60
|
+
resolve_skills_dir,
|
|
61
|
+
)
|
|
49
62
|
from verifaied.testcmd import (
|
|
50
63
|
RecordedTestError,
|
|
51
64
|
parse_test_ref,
|
|
@@ -85,6 +98,13 @@ var_app = typer.Typer(
|
|
|
85
98
|
)
|
|
86
99
|
app.add_typer(var_app, name="var")
|
|
87
100
|
|
|
101
|
+
skill_app = typer.Typer(
|
|
102
|
+
add_completion=False,
|
|
103
|
+
no_args_is_help=True,
|
|
104
|
+
help="The agent skill that teaches a coding agent to drive verifAIed.",
|
|
105
|
+
)
|
|
106
|
+
app.add_typer(skill_app, name="skill")
|
|
107
|
+
|
|
88
108
|
console = Console()
|
|
89
109
|
err_console = Console(stderr=True)
|
|
90
110
|
|
|
@@ -1758,6 +1778,16 @@ def test_record_command(
|
|
|
1758
1778
|
"--token",
|
|
1759
1779
|
help=f"API token (vr_live_...). Defaults to ${ENV_API_TOKEN}.",
|
|
1760
1780
|
),
|
|
1781
|
+
video: VideoProfile | None = typer.Option(
|
|
1782
|
+
None,
|
|
1783
|
+
"--video",
|
|
1784
|
+
help=(
|
|
1785
|
+
"How the replay that follows this recording should be paced. "
|
|
1786
|
+
"`fast` marks each click and moves on; `watch` lingers on "
|
|
1787
|
+
"every action; `off` records without annotations. Overrides "
|
|
1788
|
+
"replay_show_actions_ms / replay_slow_mo_ms for this run."
|
|
1789
|
+
),
|
|
1790
|
+
),
|
|
1761
1791
|
) -> None:
|
|
1762
1792
|
"""Record one flow from the terminal, without a studio running.
|
|
1763
1793
|
|
|
@@ -1850,6 +1880,7 @@ def test_record_command(
|
|
|
1850
1880
|
# No `--pre` means "leave the stored chain alone", which is a
|
|
1851
1881
|
# different instruction from "compose with nothing".
|
|
1852
1882
|
pre=list(pre) or None,
|
|
1883
|
+
video=video.value if video is not None else None,
|
|
1853
1884
|
)
|
|
1854
1885
|
except (RecordedTestError, UploaderError) as e:
|
|
1855
1886
|
err_console.print(f"[red]VerifAIed error[/red]: {e}")
|
|
@@ -1969,6 +2000,16 @@ def test_run_command(
|
|
|
1969
2000
|
"--token",
|
|
1970
2001
|
help=f"API token (vr_live_...). Defaults to ${ENV_API_TOKEN}.",
|
|
1971
2002
|
),
|
|
2003
|
+
video: VideoProfile | None = typer.Option(
|
|
2004
|
+
None,
|
|
2005
|
+
"--video",
|
|
2006
|
+
help=(
|
|
2007
|
+
"How the video should be paced. `fast` (the default) marks "
|
|
2008
|
+
"each click and moves on; `watch` lingers on every action; "
|
|
2009
|
+
"`off` records without annotations. Overrides "
|
|
2010
|
+
"replay_show_actions_ms / replay_slow_mo_ms for this run."
|
|
2011
|
+
),
|
|
2012
|
+
),
|
|
1972
2013
|
) -> None:
|
|
1973
2014
|
"""Replay a recorded test, capturing video, trace and coverage.
|
|
1974
2015
|
|
|
@@ -2024,6 +2065,7 @@ def test_run_command(
|
|
|
2024
2065
|
proxy=proxy,
|
|
2025
2066
|
proxy_target=proxy_target,
|
|
2026
2067
|
proxy_port=proxy_port,
|
|
2068
|
+
video=video.value if video is not None else None,
|
|
2027
2069
|
)
|
|
2028
2070
|
except (RecordedTestError, UploaderError) as e:
|
|
2029
2071
|
err_console.print(f"[red]VerifAIed error[/red]: {e}")
|
|
@@ -2406,3 +2448,93 @@ def var_unset_command(
|
|
|
2406
2448
|
"the environment variable it named is still exported wherever you "
|
|
2407
2449
|
"set it.[/dim]"
|
|
2408
2450
|
)
|
|
2451
|
+
|
|
2452
|
+
|
|
2453
|
+
def _display_path(path: Path) -> str:
|
|
2454
|
+
"""The shortest honest way to write a path: relative to cwd when it is under it."""
|
|
2455
|
+
try:
|
|
2456
|
+
return str(path.relative_to(Path.cwd()))
|
|
2457
|
+
except ValueError:
|
|
2458
|
+
return str(path)
|
|
2459
|
+
|
|
2460
|
+
|
|
2461
|
+
@skill_app.command("install")
|
|
2462
|
+
def skill_install_command(
|
|
2463
|
+
user: bool = typer.Option(
|
|
2464
|
+
False,
|
|
2465
|
+
"--user",
|
|
2466
|
+
help=(
|
|
2467
|
+
"Install into ~/.claude/skills/ — every repository on this "
|
|
2468
|
+
"machine — instead of this project's .claude/skills/."
|
|
2469
|
+
),
|
|
2470
|
+
),
|
|
2471
|
+
directory: Path | None = typer.Option(
|
|
2472
|
+
None,
|
|
2473
|
+
"--dir",
|
|
2474
|
+
"-d",
|
|
2475
|
+
help=(
|
|
2476
|
+
"The skills directory to install into, if it is neither this "
|
|
2477
|
+
"project's nor your home one. The skill lands in a "
|
|
2478
|
+
f"`{SKILL_NAME}` folder inside it."
|
|
2479
|
+
),
|
|
2480
|
+
),
|
|
2481
|
+
force: bool = typer.Option(
|
|
2482
|
+
False,
|
|
2483
|
+
"--force",
|
|
2484
|
+
"-f",
|
|
2485
|
+
help="Overwrite an installed copy whose files differ from this one's.",
|
|
2486
|
+
),
|
|
2487
|
+
) -> None:
|
|
2488
|
+
"""Install the verifAIed skill, so your coding agent knows how to drive this.
|
|
2489
|
+
|
|
2490
|
+
The skill ships inside this CLI, so it always describes the commands
|
|
2491
|
+
you actually have. It teaches an agent the loop — run the tests with
|
|
2492
|
+
coverage, `verifaied upload`, `verifaied check-done`, fix what comes
|
|
2493
|
+
back, repeat until done — and the rules that keep the loop honest.
|
|
2494
|
+
|
|
2495
|
+
verifaied skill install # this project: .claude/skills/verifaied
|
|
2496
|
+
verifaied skill install --user # every project: ~/.claude/skills/verifaied
|
|
2497
|
+
|
|
2498
|
+
"This project" is the root of the repository you are standing in — run
|
|
2499
|
+
it from a subdirectory and the skill still lands where your agent will
|
|
2500
|
+
look for it.
|
|
2501
|
+
|
|
2502
|
+
Re-running it writes nothing when the installed copy already matches.
|
|
2503
|
+
A copy that differs — because you edited it, or because you have since
|
|
2504
|
+
upgraded the CLI — is left alone until you pass --force, which replaces
|
|
2505
|
+
the files verifAIed ships and never removes anything you added
|
|
2506
|
+
alongside them.
|
|
2507
|
+
|
|
2508
|
+
Exit codes:
|
|
2509
|
+
|
|
2510
|
+
0 installed, updated, or already up to date
|
|
2511
|
+
1 usage error (--user with --dir, or a differing copy without --force)
|
|
2512
|
+
"""
|
|
2513
|
+
try:
|
|
2514
|
+
skills_dir = resolve_skills_dir(
|
|
2515
|
+
user=user,
|
|
2516
|
+
dest=directory,
|
|
2517
|
+
cwd=detect_project_root(Path.cwd()),
|
|
2518
|
+
home=Path.home(),
|
|
2519
|
+
)
|
|
2520
|
+
result = install_skill(skills_dir=skills_dir, force=force)
|
|
2521
|
+
except SkillInstallError as e:
|
|
2522
|
+
err_console.print(f"[red]VerifAIed error[/red]: {escape(str(e))}")
|
|
2523
|
+
raise typer.Exit(code=1) from e
|
|
2524
|
+
|
|
2525
|
+
where = escape(_display_path(result.path))
|
|
2526
|
+
if result.state == "unchanged":
|
|
2527
|
+
console.print(
|
|
2528
|
+
f"[green]Up to date[/green] — the verifAIed skill is already at "
|
|
2529
|
+
f"[bold]{where}[/bold] ({len(result.unchanged)} file(s))."
|
|
2530
|
+
)
|
|
2531
|
+
return
|
|
2532
|
+
|
|
2533
|
+
verb = "Updated" if result.state == "updated" else "Installed"
|
|
2534
|
+
console.print(f"[green]{verb}[/green] the verifAIed skill → [bold]{where}[/bold]")
|
|
2535
|
+
for rel in result.written:
|
|
2536
|
+
console.print(f" {escape(rel)}")
|
|
2537
|
+
console.print(
|
|
2538
|
+
f"\n[dim]Your coding agent picks it up on its next session — ask it to "
|
|
2539
|
+
f"use the {SKILL_NAME} skill.[/dim]"
|
|
2540
|
+
)
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
// and derives nothing from it: the spec goes out verbatim and Python
|
|
49
49
|
// owns the single parser, so the two halves can never drift.
|
|
50
50
|
//
|
|
51
|
-
// Every Playwright API below is public and
|
|
52
|
-
// the Python side gates recording on a version **floor** rather than
|
|
53
|
-
// allowlist. Two startup probes still run — the console API and the AI
|
|
51
|
+
// Every Playwright API below is public and available from 1.59, which is
|
|
52
|
+
// why the Python side gates recording on a version **floor** rather than
|
|
53
|
+
// an allowlist. Two startup probes still run — the console API and the AI
|
|
54
54
|
// snapshot mode — because a browser that opened without either would
|
|
55
55
|
// record nothing while looking like it worked.
|
|
56
56
|
//
|
|
@@ -739,7 +739,7 @@ async function main() {
|
|
|
739
739
|
);
|
|
740
740
|
}
|
|
741
741
|
// The assistant's whole view of the page is an AI-mode snapshot, and
|
|
742
|
-
// every element it names is a ref out of one. Public API
|
|
742
|
+
// every element it names is a ref out of one. Public API from 1.59, but
|
|
743
743
|
// probed because the failure mode of a build without it is a snapshot
|
|
744
744
|
// with no refs — and an assistant that can see the page and never touch
|
|
745
745
|
// anything on it.
|
|
@@ -1384,7 +1384,7 @@ async function main() {
|
|
|
1384
1384
|
* snapshot measures two seconds of blocked main thread on a
|
|
1385
1385
|
* 92k-node app — and the only thing that reads the tree is the
|
|
1386
1386
|
* studio's assistant, so the CLI says when somebody is going to.
|
|
1387
|
-
* `page.ariaSnapshot()` is public API
|
|
1387
|
+
* `page.ariaSnapshot()` is public API from 1.59 and needs no probe; the
|
|
1388
1388
|
* worst it can do is throw on a page that navigated mid-read, which
|
|
1389
1389
|
* reports `page: null` and costs the next beat.
|
|
1390
1390
|
*/
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
// same one the recorder writes for a click. What the browser runs is what
|
|
13
13
|
// the spec saves.
|
|
14
14
|
//
|
|
15
|
-
// How refs behave
|
|
16
|
-
// cached ON THE ELEMENT and reused across snapshots while its
|
|
17
|
-
// accessible name hold, so an element keeps its number as the
|
|
18
|
-
// around it — but the counter lives in the document's injected
|
|
19
|
-
// starts again at e1 after a cross-document navigation, where
|
|
20
|
-
// number can name a different element on a similar page. So a
|
|
21
|
-
// against an earlier snapshot is trusted when the document is
|
|
22
|
-
// its role and name still match, and refused otherwise.
|
|
15
|
+
// How refs behave from 1.59 onward, because the checks below rest on it:
|
|
16
|
+
// a ref is cached ON THE ELEMENT and reused across snapshots while its
|
|
17
|
+
// role and accessible name hold, so an element keeps its number as the
|
|
18
|
+
// page moves around it — but the counter lives in the document's injected
|
|
19
|
+
// script and starts again at e1 after a cross-document navigation, where
|
|
20
|
+
// the same number can name a different element on a similar page. So a
|
|
21
|
+
// ref written against an earlier snapshot is trusted when the document is
|
|
22
|
+
// the same and its role and name still match, and refused otherwise.
|
|
23
23
|
//
|
|
24
24
|
// Everything here is string work: finding the refs a line names, reading
|
|
25
25
|
// what a ref stood for in a given snapshot, checking one line's identity
|