recx-cli 0.0.3__tar.gz → 0.1.0__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 (78) hide show
  1. {recx_cli-0.0.3 → recx_cli-0.1.0}/.gitignore +3 -0
  2. {recx_cli-0.0.3 → recx_cli-0.1.0}/PKG-INFO +37 -6
  3. {recx_cli-0.0.3 → recx_cli-0.1.0}/README.md +36 -5
  4. {recx_cli-0.0.3 → recx_cli-0.1.0}/pyproject.toml +2 -1
  5. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/SPEC.md +8 -2
  6. recx_cli-0.1.0/spec/index.schema.json +653 -0
  7. {recx_cli-0.0.3 → recx_cli-0.1.0}/src/recx_cli/check.py +47 -6
  8. recx_cli-0.1.0/src/recx_cli/cli.py +215 -0
  9. recx_cli-0.1.0/src/recx_cli/drift.py +178 -0
  10. {recx_cli-0.0.3 → recx_cli-0.1.0}/src/recx_cli/hook.py +67 -21
  11. recx_cli-0.1.0/src/recx_cli/index.py +65 -0
  12. recx_cli-0.1.0/src/recx_cli/index_cache.py +261 -0
  13. recx_cli-0.1.0/src/recx_cli/match.py +260 -0
  14. recx_cli-0.1.0/src/recx_cli/search-result.schema.json +300 -0
  15. recx_cli-0.1.0/src/recx_cli/search.py +162 -0
  16. recx_cli-0.1.0/tests/fixtures/search/anomr.yaml +30 -0
  17. recx_cli-0.1.0/tests/fixtures/search/argwise.yaml +44 -0
  18. recx_cli-0.1.0/tests/fixtures/search/confyaml.yaml +29 -0
  19. recx_cli-0.1.0/tests/fixtures/search/cronexpr.yaml +28 -0
  20. recx_cli-0.1.0/tests/fixtures/search/feedparse.yaml +47 -0
  21. recx_cli-0.1.0/tests/fixtures/search/feedwatch.yaml +42 -0
  22. recx_cli-0.1.0/tests/fixtures/search/kustomize-secrets.yaml +27 -0
  23. recx_cli-0.1.0/tests/fixtures/search/mcp-sqlite.yaml +30 -0
  24. recx_cli-0.1.0/tests/fixtures/search/mdhtml.yaml +40 -0
  25. recx_cli-0.1.0/tests/fixtures/search/mdlint.yaml +38 -0
  26. recx_cli-0.1.0/tests/fixtures/search/nextver.yaml +27 -0
  27. recx_cli-0.1.0/tests/fixtures/search/patient.yaml +29 -0
  28. recx_cli-0.1.0/tests/fixtures/search/pdfmine.yaml +42 -0
  29. recx_cli-0.1.0/tests/fixtures/search/pr-labeler.yaml +26 -0
  30. recx_cli-0.1.0/tests/fixtures/search/quickjson.yaml +28 -0
  31. recx_cli-0.1.0/tests/fixtures/search/schemacheck.yaml +29 -0
  32. recx_cli-0.1.0/tests/fixtures/search/sealbox.yaml +28 -0
  33. recx_cli-0.1.0/tests/fixtures/search/sitemapgen.yaml +27 -0
  34. recx_cli-0.1.0/tests/fixtures/search/slack-notify.yaml +26 -0
  35. recx_cli-0.1.0/tests/fixtures/search/steadyhttp.yaml +30 -0
  36. recx_cli-0.1.0/tests/fixtures/search/tablecheck.yaml +28 -0
  37. recx_cli-0.1.0/tests/fixtures/search/thumbsmith.yaml +28 -0
  38. recx_cli-0.1.0/tests/fixtures/search/tokencheck.yaml +29 -0
  39. recx_cli-0.1.0/tests/fixtures/search/tollgate.yaml +41 -0
  40. recx_cli-0.1.0/tests/fixtures/search/yamlguard.yaml +39 -0
  41. recx_cli-0.1.0/tests/search_cases.yaml +200 -0
  42. {recx_cli-0.0.3 → recx_cli-0.1.0}/tests/test_check.py +59 -0
  43. recx_cli-0.1.0/tests/test_crawler_core.py +497 -0
  44. recx_cli-0.1.0/tests/test_crawler_github.py +529 -0
  45. recx_cli-0.1.0/tests/test_crawler_main.py +139 -0
  46. recx_cli-0.1.0/tests/test_drift.py +424 -0
  47. {recx_cli-0.0.3 → recx_cli-0.1.0}/tests/test_hook.py +10 -0
  48. recx_cli-0.1.0/tests/test_index.py +162 -0
  49. recx_cli-0.1.0/tests/test_index_cache.py +209 -0
  50. recx_cli-0.1.0/tests/test_match.py +441 -0
  51. recx_cli-0.1.0/tests/test_search.py +412 -0
  52. recx_cli-0.0.3/src/recx_cli/cli.py +0 -104
  53. {recx_cli-0.0.3 → recx_cli-0.1.0}/LICENSE +0 -0
  54. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid/evidence-without-run.yaml +0 -0
  55. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid/extension-value-not-scalar.yaml +0 -0
  56. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid/http-url.yaml +0 -0
  57. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid/license-not-permissive.yaml +0 -0
  58. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid/missing-capabilities.yaml +0 -0
  59. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid/multiline-summary.yaml +0 -0
  60. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid/package-without-purl.yaml +0 -0
  61. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid/path-escapes-repo.yaml +0 -0
  62. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid/unknown-key.yaml +0 -0
  63. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid/unknown-version.yaml +0 -0
  64. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid-rules/rule1-duplicate-evidence-id.yaml +0 -0
  65. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid-rules/rule1-duplicate-module-id.yaml +0 -0
  66. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid-rules/rule2-covers-unknown-module.yaml +0 -0
  67. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid-rules/rule2-requires-unknown-module.yaml +0 -0
  68. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid-rules/rule5-over-64-kib.yaml +0 -0
  69. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid-rules/rule6-anchor-alias.yaml +0 -0
  70. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid-rules/rule6-duplicate-key.yaml +0 -0
  71. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/invalid-rules/rule6-merge-key.yaml +0 -0
  72. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/valid/full.yaml +0 -0
  73. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/examples/valid/minimal.yaml +0 -0
  74. {recx_cli-0.0.3 → recx_cli-0.1.0}/spec/recx.schema.json +0 -0
  75. {recx_cli-0.0.3 → recx_cli-0.1.0}/src/recx_cli/__init__.py +0 -0
  76. {recx_cli-0.0.3 → recx_cli-0.1.0}/src/recx_cli/__main__.py +0 -0
  77. {recx_cli-0.0.3 → recx_cli-0.1.0}/src/recx_cli/evidence.py +0 -0
  78. {recx_cli-0.0.3 → recx_cli-0.1.0}/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.3
3
+ Version: 0.1.0
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,50 @@ 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
+ ## Searching
79
+
80
+ ```sh
81
+ recx search "retry an http request with exponential backoff"
82
+ recx search parse rss feeds --language python --json
83
+ recx show OWNER/NAME
84
+ ```
85
+
86
+ `recx search` downloads the published index (https://jbmv.github.io/recx/v1/index.json),
87
+ caches it for six hours, and ranks entries by keyword overlap with the query, weighting
88
+ capabilities above summaries and descriptions. It returns every entry that shares a term with
89
+ the query, ordered by score, and leaves the judgement of relevance to the agent reading the
90
+ results. `--json` gives the structured form a tool or agent should use, and the same result is
91
+ available from Python as `recx_cli.search.search()`. `recx show` prints one indexed entry in
92
+ full. Neither command needs a GitHub token or runs anything from a repository.
93
+
94
+ Every result is written by the repository's author and has been checked only against the
95
+ schema. The output says so in a fixed `notice`, and the JSON lists the author-written paths in
96
+ `untrusted`. The index never contains a manifest's `setup` or `run` commands. Before reusing
97
+ anything, read the repository's licence file and its current `RECX.yaml`, and run its evidence
98
+ only in a sandbox. [docs/design/search.md](docs/design/search.md) describes the index, the
99
+ crawler and the ranking in full.
100
+
73
101
  ## What's here
74
102
 
75
103
  | | |
76
104
  |---|---|
77
105
  | [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`) |
106
+ | `recx-cli` on PyPI | `recx check`, `recx evidence`, `recx search` and `recx show` (`pip install recx-cli`) |
79
107
  | `@jbmv/recx` on npm | The schema and examples, for JavaScript tooling |
80
108
  | [plugin/](plugin/) | The Claude Code plugin; this repository is its marketplace |
109
+ | [crawler/](crawler/) | The daily crawler that builds the search index, run by a scheduled workflow |
110
+ | [docs/design/](docs/design/) | Design documents |
81
111
  | [RECX.yaml](RECX.yaml) | recx's own manifest |
82
112
 
83
113
  ## Status
84
114
 
85
115
  Experimental. The spec is a v0.1 draft and may change before 1.0; every manifest states the
86
116
  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.
117
+ license file matches `license`; the search crawler applies it as far as GitHub's licence
118
+ detection allows. Search is in its first version: it ranks by keywords, has no synonym handling,
119
+ and has no MCP server yet.
89
120
 
90
121
  ## Kyosei
91
122
 
@@ -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,50 @@ 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
+ ## Searching
65
+
66
+ ```sh
67
+ recx search "retry an http request with exponential backoff"
68
+ recx search parse rss feeds --language python --json
69
+ recx show OWNER/NAME
70
+ ```
71
+
72
+ `recx search` downloads the published index (https://jbmv.github.io/recx/v1/index.json),
73
+ caches it for six hours, and ranks entries by keyword overlap with the query, weighting
74
+ capabilities above summaries and descriptions. It returns every entry that shares a term with
75
+ the query, ordered by score, and leaves the judgement of relevance to the agent reading the
76
+ results. `--json` gives the structured form a tool or agent should use, and the same result is
77
+ available from Python as `recx_cli.search.search()`. `recx show` prints one indexed entry in
78
+ full. Neither command needs a GitHub token or runs anything from a repository.
79
+
80
+ Every result is written by the repository's author and has been checked only against the
81
+ schema. The output says so in a fixed `notice`, and the JSON lists the author-written paths in
82
+ `untrusted`. The index never contains a manifest's `setup` or `run` commands. Before reusing
83
+ anything, read the repository's licence file and its current `RECX.yaml`, and run its evidence
84
+ only in a sandbox. [docs/design/search.md](docs/design/search.md) describes the index, the
85
+ crawler and the ranking in full.
86
+
59
87
  ## What's here
60
88
 
61
89
  | | |
62
90
  |---|---|
63
91
  | [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`) |
92
+ | `recx-cli` on PyPI | `recx check`, `recx evidence`, `recx search` and `recx show` (`pip install recx-cli`) |
65
93
  | `@jbmv/recx` on npm | The schema and examples, for JavaScript tooling |
66
94
  | [plugin/](plugin/) | The Claude Code plugin; this repository is its marketplace |
95
+ | [crawler/](crawler/) | The daily crawler that builds the search index, run by a scheduled workflow |
96
+ | [docs/design/](docs/design/) | Design documents |
67
97
  | [RECX.yaml](RECX.yaml) | recx's own manifest |
68
98
 
69
99
  ## Status
70
100
 
71
101
  Experimental. The spec is a v0.1 draft and may change before 1.0; every manifest states the
72
102
  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.
103
+ license file matches `license`; the search crawler applies it as far as GitHub's licence
104
+ detection allows. Search is in its first version: it ranks by keywords, has no synonym handling,
105
+ and has no MCP server yet.
75
106
 
76
107
  ## Kyosei
77
108
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "recx-cli"
7
- version = "0.0.3"
7
+ version = "0.1.0"
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.