recx-cli 0.0.4__tar.gz → 0.1.1__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.
Files changed (80) hide show
  1. {recx_cli-0.0.4 → recx_cli-0.1.1}/.gitignore +3 -0
  2. {recx_cli-0.0.4 → recx_cli-0.1.1}/PKG-INFO +46 -6
  3. {recx_cli-0.0.4 → recx_cli-0.1.1}/README.md +45 -5
  4. {recx_cli-0.0.4 → recx_cli-0.1.1}/pyproject.toml +2 -1
  5. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/SPEC.md +8 -2
  6. recx_cli-0.1.1/spec/index.schema.json +653 -0
  7. {recx_cli-0.0.4 → recx_cli-0.1.1}/src/recx_cli/check.py +47 -6
  8. recx_cli-0.1.1/src/recx_cli/cli.py +215 -0
  9. recx_cli-0.1.1/src/recx_cli/drift.py +312 -0
  10. {recx_cli-0.0.4 → recx_cli-0.1.1}/src/recx_cli/hook.py +37 -9
  11. recx_cli-0.1.1/src/recx_cli/index.py +65 -0
  12. recx_cli-0.1.1/src/recx_cli/index_cache.py +261 -0
  13. recx_cli-0.1.1/src/recx_cli/match.py +260 -0
  14. recx_cli-0.1.1/src/recx_cli/search-result.schema.json +300 -0
  15. recx_cli-0.1.1/src/recx_cli/search.py +162 -0
  16. recx_cli-0.1.1/tests/fixtures/search/anomr.yaml +30 -0
  17. recx_cli-0.1.1/tests/fixtures/search/argwise.yaml +44 -0
  18. recx_cli-0.1.1/tests/fixtures/search/confyaml.yaml +29 -0
  19. recx_cli-0.1.1/tests/fixtures/search/cronexpr.yaml +28 -0
  20. recx_cli-0.1.1/tests/fixtures/search/feedparse.yaml +47 -0
  21. recx_cli-0.1.1/tests/fixtures/search/feedwatch.yaml +42 -0
  22. recx_cli-0.1.1/tests/fixtures/search/kustomize-secrets.yaml +27 -0
  23. recx_cli-0.1.1/tests/fixtures/search/mcp-sqlite.yaml +30 -0
  24. recx_cli-0.1.1/tests/fixtures/search/mdhtml.yaml +40 -0
  25. recx_cli-0.1.1/tests/fixtures/search/mdlint.yaml +38 -0
  26. recx_cli-0.1.1/tests/fixtures/search/nextver.yaml +27 -0
  27. recx_cli-0.1.1/tests/fixtures/search/patient.yaml +29 -0
  28. recx_cli-0.1.1/tests/fixtures/search/pdfmine.yaml +42 -0
  29. recx_cli-0.1.1/tests/fixtures/search/pr-labeler.yaml +26 -0
  30. recx_cli-0.1.1/tests/fixtures/search/quickjson.yaml +28 -0
  31. recx_cli-0.1.1/tests/fixtures/search/schemacheck.yaml +29 -0
  32. recx_cli-0.1.1/tests/fixtures/search/sealbox.yaml +28 -0
  33. recx_cli-0.1.1/tests/fixtures/search/sitemapgen.yaml +27 -0
  34. recx_cli-0.1.1/tests/fixtures/search/slack-notify.yaml +26 -0
  35. recx_cli-0.1.1/tests/fixtures/search/steadyhttp.yaml +30 -0
  36. recx_cli-0.1.1/tests/fixtures/search/tablecheck.yaml +28 -0
  37. recx_cli-0.1.1/tests/fixtures/search/thumbsmith.yaml +28 -0
  38. recx_cli-0.1.1/tests/fixtures/search/tokencheck.yaml +29 -0
  39. recx_cli-0.1.1/tests/fixtures/search/tollgate.yaml +41 -0
  40. recx_cli-0.1.1/tests/fixtures/search/yamlguard.yaml +39 -0
  41. recx_cli-0.1.1/tests/search_cases.yaml +200 -0
  42. {recx_cli-0.0.4 → recx_cli-0.1.1}/tests/test_check.py +59 -0
  43. recx_cli-0.1.1/tests/test_crawler_core.py +497 -0
  44. recx_cli-0.1.1/tests/test_crawler_github.py +529 -0
  45. recx_cli-0.1.1/tests/test_crawler_main.py +139 -0
  46. recx_cli-0.1.1/tests/test_drift.py +851 -0
  47. {recx_cli-0.0.4 → recx_cli-0.1.1}/tests/test_hook.py +10 -0
  48. recx_cli-0.1.1/tests/test_index.py +162 -0
  49. recx_cli-0.1.1/tests/test_index_cache.py +209 -0
  50. recx_cli-0.1.1/tests/test_match.py +441 -0
  51. recx_cli-0.1.1/tests/test_search.py +412 -0
  52. recx_cli-0.0.4/src/recx_cli/cli.py +0 -111
  53. recx_cli-0.0.4/src/recx_cli/drift.py +0 -178
  54. recx_cli-0.0.4/tests/test_drift.py +0 -424
  55. {recx_cli-0.0.4 → recx_cli-0.1.1}/LICENSE +0 -0
  56. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/evidence-without-run.yaml +0 -0
  57. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/extension-value-not-scalar.yaml +0 -0
  58. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/http-url.yaml +0 -0
  59. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/license-not-permissive.yaml +0 -0
  60. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/missing-capabilities.yaml +0 -0
  61. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/multiline-summary.yaml +0 -0
  62. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/package-without-purl.yaml +0 -0
  63. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/path-escapes-repo.yaml +0 -0
  64. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/unknown-key.yaml +0 -0
  65. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/unknown-version.yaml +0 -0
  66. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid-rules/rule1-duplicate-evidence-id.yaml +0 -0
  67. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid-rules/rule1-duplicate-module-id.yaml +0 -0
  68. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid-rules/rule2-covers-unknown-module.yaml +0 -0
  69. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid-rules/rule2-requires-unknown-module.yaml +0 -0
  70. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid-rules/rule5-over-64-kib.yaml +0 -0
  71. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid-rules/rule6-anchor-alias.yaml +0 -0
  72. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid-rules/rule6-duplicate-key.yaml +0 -0
  73. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid-rules/rule6-merge-key.yaml +0 -0
  74. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/valid/full.yaml +0 -0
  75. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/valid/minimal.yaml +0 -0
  76. {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/recx.schema.json +0 -0
  77. {recx_cli-0.0.4 → recx_cli-0.1.1}/src/recx_cli/__init__.py +0 -0
  78. {recx_cli-0.0.4 → recx_cli-0.1.1}/src/recx_cli/__main__.py +0 -0
  79. {recx_cli-0.0.4 → recx_cli-0.1.1}/src/recx_cli/evidence.py +0 -0
  80. {recx_cli-0.0.4 → recx_cli-0.1.1}/tests/test_evidence.py +0 -0
@@ -22,3 +22,6 @@ KYOSEI_ISSUE.md
22
22
  CLAUDE.md
23
23
  CLAUDE.local.md
24
24
  .kyosei
25
+
26
+ # internal working documents (subagent drafts, raw proposals); local only
27
+ docs/internal/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: recx-cli
3
- Version: 0.0.4
3
+ Version: 0.1.1
4
4
  Summary: Validator for RECX.yaml manifests: the recx check command.
5
5
  Project-URL: Homepage, https://github.com/jbmv/recx
6
6
  Project-URL: Repository, https://github.com/jbmv/recx
@@ -38,8 +38,11 @@ than write it again, recording where it came from in its own project's manifest.
38
38
 
39
39
  Taking part is meant to cost a repository little. One prompt produces a complete, valid
40
40
  manifest, and the Claude Code plugin checks it whenever a session ends, so it stays valid as
41
- the code changes. No hosted service is involved, because the fixed filename serves as the index.
42
- On GitHub, manifests can be found by searching code for `path:/(^|\/)recx\.ya?ml$/i`.
41
+ the code changes. No hosted service is involved. The fixed filename and the GitHub topic `recx`
42
+ serve as the index, and a scheduled workflow in this repository collects the valid manifests it
43
+ finds into a static file each day. In GitHub's web interface, manifests can also be found by
44
+ searching code for `path:/(^|\/)recx\.ya?ml$/i`; GitHub's code search API does not accept that
45
+ regular expression.
43
46
 
44
47
  ## The manifest
45
48
 
@@ -70,22 +73,59 @@ anything listed can be reused without asking.
70
73
  - **Any other agent:** paste the prompt in [ADOPT.md](ADOPT.md).
71
74
  - **By hand:** start from the example above, then run `uvx --from recx-cli recx check`.
72
75
 
76
+ Then add the GitHub topic `recx` to the repository, so the daily index finds it promptly.
77
+
78
+ The plugin's hook runs when a session or one of its subagents stops (Claude Code's Stop and
79
+ SubagentStop events). It blocks on an invalid manifest, and it reminds, without blocking, when
80
+ files under a module's `path` changed during the session while RECX.yaml did not. A commit can
81
+ record that module entries were checked against its tree with a trailer such as
82
+ `Recx-Checked: lib, cli`; the reminder then disregards that commit's changes to those modules
83
+ and the changes of the session's commits it descends from. `RECX_DRIFT_REMINDER=off` turns
84
+ the reminder off. The [manifest skill](plugin/skills/manifest/SKILL.md) describes both in full.
85
+
86
+ ## Searching
87
+
88
+ ```sh
89
+ recx search "retry an http request with exponential backoff"
90
+ recx search parse rss feeds --language python --json
91
+ recx show OWNER/NAME
92
+ ```
93
+
94
+ `recx search` downloads the published index (https://jbmv.github.io/recx/v1/index.json),
95
+ caches it for six hours, and ranks entries by keyword overlap with the query, weighting
96
+ capabilities above summaries and descriptions. It returns every entry that shares a term with
97
+ the query, ordered by score, and leaves the judgement of relevance to the agent reading the
98
+ results. `--json` gives the structured form a tool or agent should use, and the same result is
99
+ available from Python as `recx_cli.search.search()`. `recx show` prints one indexed entry in
100
+ full. Neither command needs a GitHub token or runs anything from a repository.
101
+
102
+ Every result is written by the repository's author and has been checked only against the
103
+ schema. The output says so in a fixed `notice`, and the JSON lists the author-written paths in
104
+ `untrusted`. The index never contains a manifest's `setup` or `run` commands. Before reusing
105
+ anything, read the repository's licence file and its current `RECX.yaml`, and run its evidence
106
+ only in a sandbox. [docs/integrating.md](docs/integrating.md) explains how to call search from
107
+ another tool, and [docs/design/search.md](docs/design/search.md) describes the index, the crawler
108
+ and the ranking in full.
109
+
73
110
  ## What's here
74
111
 
75
112
  | | |
76
113
  |---|---|
77
114
  | [spec/](spec/) | The spec, its JSON Schema, and valid and invalid example manifests |
78
- | `recx-cli` on PyPI | `recx check`, the validator (`pip install recx-cli`) |
115
+ | `recx-cli` on PyPI | `recx check`, `recx evidence`, `recx search` and `recx show` (`pip install recx-cli`) |
79
116
  | `@jbmv/recx` on npm | The schema and examples, for JavaScript tooling |
80
117
  | [plugin/](plugin/) | The Claude Code plugin; this repository is its marketplace |
118
+ | [crawler/](crawler/) | The daily crawler that builds the search index, run by a scheduled workflow |
119
+ | [docs/design/](docs/design/) | Design documents |
81
120
  | [RECX.yaml](RECX.yaml) | recx's own manifest |
82
121
 
83
122
  ## Status
84
123
 
85
124
  Experimental. The spec is a v0.1 draft and may change before 1.0; every manifest states the
86
125
  version it was written against. `recx check` enforces the whole spec except rule 4, that the
87
- license file matches `license`. The manifest, the validator and the plugin exist; search, the
88
- second part described above, is not built yet.
126
+ license file matches `license`; the search crawler applies it as far as GitHub's licence
127
+ detection allows. Search is in its first version: it ranks by keywords, has no synonym handling,
128
+ and has no MCP server yet.
89
129
 
90
130
  ## Kyosei
91
131
 
@@ -24,8 +24,11 @@ than write it again, recording where it came from in its own project's manifest.
24
24
 
25
25
  Taking part is meant to cost a repository little. One prompt produces a complete, valid
26
26
  manifest, and the Claude Code plugin checks it whenever a session ends, so it stays valid as
27
- the code changes. No hosted service is involved, because the fixed filename serves as the index.
28
- On GitHub, manifests can be found by searching code for `path:/(^|\/)recx\.ya?ml$/i`.
27
+ the code changes. No hosted service is involved. The fixed filename and the GitHub topic `recx`
28
+ serve as the index, and a scheduled workflow in this repository collects the valid manifests it
29
+ finds into a static file each day. In GitHub's web interface, manifests can also be found by
30
+ searching code for `path:/(^|\/)recx\.ya?ml$/i`; GitHub's code search API does not accept that
31
+ regular expression.
29
32
 
30
33
  ## The manifest
31
34
 
@@ -56,22 +59,59 @@ anything listed can be reused without asking.
56
59
  - **Any other agent:** paste the prompt in [ADOPT.md](ADOPT.md).
57
60
  - **By hand:** start from the example above, then run `uvx --from recx-cli recx check`.
58
61
 
62
+ Then add the GitHub topic `recx` to the repository, so the daily index finds it promptly.
63
+
64
+ The plugin's hook runs when a session or one of its subagents stops (Claude Code's Stop and
65
+ SubagentStop events). It blocks on an invalid manifest, and it reminds, without blocking, when
66
+ files under a module's `path` changed during the session while RECX.yaml did not. A commit can
67
+ record that module entries were checked against its tree with a trailer such as
68
+ `Recx-Checked: lib, cli`; the reminder then disregards that commit's changes to those modules
69
+ and the changes of the session's commits it descends from. `RECX_DRIFT_REMINDER=off` turns
70
+ the reminder off. The [manifest skill](plugin/skills/manifest/SKILL.md) describes both in full.
71
+
72
+ ## Searching
73
+
74
+ ```sh
75
+ recx search "retry an http request with exponential backoff"
76
+ recx search parse rss feeds --language python --json
77
+ recx show OWNER/NAME
78
+ ```
79
+
80
+ `recx search` downloads the published index (https://jbmv.github.io/recx/v1/index.json),
81
+ caches it for six hours, and ranks entries by keyword overlap with the query, weighting
82
+ capabilities above summaries and descriptions. It returns every entry that shares a term with
83
+ the query, ordered by score, and leaves the judgement of relevance to the agent reading the
84
+ results. `--json` gives the structured form a tool or agent should use, and the same result is
85
+ available from Python as `recx_cli.search.search()`. `recx show` prints one indexed entry in
86
+ full. Neither command needs a GitHub token or runs anything from a repository.
87
+
88
+ Every result is written by the repository's author and has been checked only against the
89
+ schema. The output says so in a fixed `notice`, and the JSON lists the author-written paths in
90
+ `untrusted`. The index never contains a manifest's `setup` or `run` commands. Before reusing
91
+ anything, read the repository's licence file and its current `RECX.yaml`, and run its evidence
92
+ only in a sandbox. [docs/integrating.md](docs/integrating.md) explains how to call search from
93
+ another tool, and [docs/design/search.md](docs/design/search.md) describes the index, the crawler
94
+ and the ranking in full.
95
+
59
96
  ## What's here
60
97
 
61
98
  | | |
62
99
  |---|---|
63
100
  | [spec/](spec/) | The spec, its JSON Schema, and valid and invalid example manifests |
64
- | `recx-cli` on PyPI | `recx check`, the validator (`pip install recx-cli`) |
101
+ | `recx-cli` on PyPI | `recx check`, `recx evidence`, `recx search` and `recx show` (`pip install recx-cli`) |
65
102
  | `@jbmv/recx` on npm | The schema and examples, for JavaScript tooling |
66
103
  | [plugin/](plugin/) | The Claude Code plugin; this repository is its marketplace |
104
+ | [crawler/](crawler/) | The daily crawler that builds the search index, run by a scheduled workflow |
105
+ | [docs/design/](docs/design/) | Design documents |
67
106
  | [RECX.yaml](RECX.yaml) | recx's own manifest |
68
107
 
69
108
  ## Status
70
109
 
71
110
  Experimental. The spec is a v0.1 draft and may change before 1.0; every manifest states the
72
111
  version it was written against. `recx check` enforces the whole spec except rule 4, that the
73
- license file matches `license`. The manifest, the validator and the plugin exist; search, the
74
- second part described above, is not built yet.
112
+ license file matches `license`; the search crawler applies it as far as GitHub's licence
113
+ detection allows. Search is in its first version: it ranks by keywords, has no synonym handling,
114
+ and has no MCP server yet.
75
115
 
76
116
  ## Kyosei
77
117
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "recx-cli"
7
- version = "0.0.4"
7
+ version = "0.1.1"
8
8
  description = "Validator for RECX.yaml manifests: the recx check command."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -38,3 +38,4 @@ include = ["/src", "/spec", "/tests", "/README.md", "/LICENSE", "/pyproject.toml
38
38
 
39
39
  [tool.pytest.ini_options]
40
40
  testpaths = ["tests"]
41
+ pythonpath = ["."] # lets tests import the crawler/ package, which is not in the wheel
@@ -32,8 +32,14 @@ recx's own validator checks both.
32
32
 
33
33
  - The filename is exactly `RECX.yaml`, at the repository root. There is one per repository.
34
34
  That fixed name is what makes manifests findable: searching code for the filename returns
35
- only manifests. On GitHub, signed in, search code for `path:/(^|\/)recx\.ya?ml$/i`. That
36
- query also catches misspellings, so keep only root-level files named exactly `RECX.yaml`.
35
+ only manifests. In GitHub's web interface, signed in, search code for
36
+ `path:/(^|\/)recx\.ya?ml$/i`; the query also catches misspellings, so keep only root-level
37
+ files named exactly `RECX.yaml`. GitHub's code search API does not accept regular
38
+ expressions, so a program searches for `filename:RECX.yaml path:/` and applies the same
39
+ filter.
40
+ - A repository with a manifest should also carry the GitHub topic `recx`. Code search indexes
41
+ new and small repositories slowly, and sometimes not at all; repository topics become
42
+ searchable quickly.
37
43
  - It is UTF-8 YAML 1.2. JSON is valid YAML, so a tool may write JSON into it.
38
44
  - It is at most 64 KiB.
39
45
  - It uses no anchors (`&`), aliases (`*`) or merge keys (`<<`), and no mapping repeats a key.