xone-cli 0.1.1__tar.gz → 0.1.3__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.
- xone_cli-0.1.3/CHANGELOG.md +24 -0
- {xone_cli-0.1.1/src/xone_cli.egg-info → xone_cli-0.1.3}/PKG-INFO +20 -2
- {xone_cli-0.1.1 → xone_cli-0.1.3}/README.md +19 -1
- {xone_cli-0.1.1 → xone_cli-0.1.3}/README.zh-CN.md +19 -1
- {xone_cli-0.1.1 → xone_cli-0.1.3}/docs/feedback/open-source-feedback-ledger.md +2 -0
- xone_cli-0.1.3/docs/install.md +69 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/pyproject.toml +1 -1
- {xone_cli-0.1.1 → xone_cli-0.1.3}/src/xone_cli/__init__.py +1 -1
- {xone_cli-0.1.1 → xone_cli-0.1.3}/src/xone_cli/cli.py +21 -2
- xone_cli-0.1.3/src/xone_cli/open_source_eval.py +226 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/src/xone_cli/tooling.py +39 -4
- {xone_cli-0.1.1 → xone_cli-0.1.3/src/xone_cli.egg-info}/PKG-INFO +20 -2
- {xone_cli-0.1.1 → xone_cli-0.1.3}/src/xone_cli.egg-info/SOURCES.txt +2 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/tests/test_cli.py +6 -2
- {xone_cli-0.1.1 → xone_cli-0.1.3}/tests/test_docs.py +7 -3
- xone_cli-0.1.3/tests/test_open_source_eval.py +139 -0
- xone_cli-0.1.1/CHANGELOG.md +0 -12
- xone_cli-0.1.1/docs/install.md +0 -31
- {xone_cli-0.1.1 → xone_cli-0.1.3}/LICENSE +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/MANIFEST.in +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/docs/product-foundation.md +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/docs/release.md +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/fixtures/open-source-samples/aider.json +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/fixtures/open-source-samples/anthropics-claude-code.json +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/fixtures/open-source-samples/cline.json +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/fixtures/open-source-samples/continue.json +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/fixtures/open-source-samples/desktop-commander-mcp.json +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/fixtures/open-source-samples/docker-mcp-gateway.json +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/fixtures/open-source-samples/github-github-mcp-server.json +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/fixtures/open-source-samples/microsoft-playwright-mcp.json +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/fixtures/open-source-samples/modelcontextprotocol-servers.json +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/fixtures/open-source-samples/openai-codex.json +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/fixtures/open-source-samples/openhands.json +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/fixtures/open-source-samples/upstash-context7.json +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/ops/constraints/main-entry.md +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/ops/constraints/production.md +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/ops/opt-overlay.md +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/ops/skills/evolution.md +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/setup.cfg +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/src/xone_cli/__main__.py +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/src/xone_cli/evidence.py +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/src/xone_cli/lab.py +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/src/xone_cli/model.py +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/src/xone_cli/release.py +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/src/xone_cli/repo_context.py +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/src/xone_cli/risk.py +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/src/xone_cli/runbook.py +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/src/xone_cli.egg-info/dependency_links.txt +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/src/xone_cli.egg-info/entry_points.txt +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/src/xone_cli.egg-info/requires.txt +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/src/xone_cli.egg-info/top_level.txt +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/tests/test_evidence.py +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/tests/test_release.py +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/tests/test_repo_context.py +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/tests/test_risk_lab.py +0 -0
- {xone_cli-0.1.1 → xone_cli-0.1.3}/tests/test_tooling.py +0 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.3
|
|
4
|
+
|
|
5
|
+
- Add `xone eval open-source` for repeatable, sanitized open-source adoption evaluation.
|
|
6
|
+
- Support metadata-only evaluation and optional `--clone-root` shallow public clone evaluation.
|
|
7
|
+
- Keep the evaluator read-only by default and document that it does not run third-party scripts, containers, tests, or project commands.
|
|
8
|
+
|
|
9
|
+
## 0.1.2
|
|
10
|
+
|
|
11
|
+
- Pin `xone doctor --install-plan` to the current recommended X-One tool versions.
|
|
12
|
+
- Add scenario-specific `when` and `next` guidance so first-run users know the next command to try.
|
|
13
|
+
- Keep the unified entrypoint small while making the install plan more actionable.
|
|
14
|
+
|
|
15
|
+
## 0.1.1
|
|
16
|
+
|
|
17
|
+
- Add scenario-based `xone doctor --install-plan` guidance.
|
|
18
|
+
- Let `xone runbook` auto-detect the local repository default branch when `--base` is omitted.
|
|
19
|
+
- Reject remote repository URLs in `xone runbook` with a clone-first message instead of producing a misleading dry run.
|
|
20
|
+
- Expand open-source feedback classifications for adoption evaluation.
|
|
21
|
+
|
|
22
|
+
## 0.1.0
|
|
23
|
+
|
|
24
|
+
- Add the first X-One unified CLI foundation.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xone-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Unified CLI entry point for X-One Agent Evidence Loop workflows.
|
|
5
5
|
Author: X-One-AI
|
|
6
6
|
License-Expression: MIT
|
|
@@ -57,8 +57,18 @@ xone doctor --install-plan
|
|
|
57
57
|
xone runbook --head HEAD --dry-run
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
+
`xone doctor --install-plan` prints scenario-specific install commands with recommended X-One package versions, when to use each scenario, and the next command to try.
|
|
61
|
+
|
|
60
62
|
`xone runbook` auto-detects the local repository default branch. Remote GitHub URLs are not accepted yet; clone the repository first, then pass the local path with `--repo`.
|
|
61
63
|
|
|
64
|
+
For repeatable open-source adoption checks, use the read-only evaluator:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
xone eval open-source --repos repos.txt --output evaluation.md --format markdown
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Add `--clone-root .xone-eval-clones` when you want X-One to shallow-clone public repositories and run only X-One dry-run commands against those local clones. It does not run third-party install scripts, tests, containers, or project commands.
|
|
71
|
+
|
|
62
72
|
`xone-cli` orchestrates these X-One tools:
|
|
63
73
|
|
|
64
74
|
- `agent-pr-evidence`
|
|
@@ -66,13 +76,21 @@ xone runbook --head HEAD --dry-run
|
|
|
66
76
|
- `mcp-risk-index`
|
|
67
77
|
- `ai-incident-lab`
|
|
68
78
|
|
|
79
|
+
Current recommended tool versions:
|
|
80
|
+
|
|
81
|
+
- `agent-pr-evidence 0.4.2`
|
|
82
|
+
- `agent-failure-packet 0.4.2`
|
|
83
|
+
- `mcp-risk-index 0.3.1`
|
|
84
|
+
- `ai-incident-lab 0.2.2`
|
|
85
|
+
|
|
69
86
|
## Boundary
|
|
70
87
|
|
|
71
88
|
- It does not replace the underlying tools.
|
|
72
89
|
- It does not post GitHub comments.
|
|
73
90
|
- It does not modify repositories automatically.
|
|
74
91
|
- It does not make allow/deny runtime enforcement decisions.
|
|
75
|
-
- It does not
|
|
92
|
+
- It does not run third-party project scripts.
|
|
93
|
+
- `xone eval open-source` makes explicit GitHub API and `git clone --depth 1` calls only when requested by the command.
|
|
76
94
|
|
|
77
95
|
## Docs
|
|
78
96
|
|
|
@@ -30,8 +30,18 @@ xone doctor --install-plan
|
|
|
30
30
|
xone runbook --head HEAD --dry-run
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
`xone doctor --install-plan` prints scenario-specific install commands with recommended X-One package versions, when to use each scenario, and the next command to try.
|
|
34
|
+
|
|
33
35
|
`xone runbook` auto-detects the local repository default branch. Remote GitHub URLs are not accepted yet; clone the repository first, then pass the local path with `--repo`.
|
|
34
36
|
|
|
37
|
+
For repeatable open-source adoption checks, use the read-only evaluator:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
xone eval open-source --repos repos.txt --output evaluation.md --format markdown
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Add `--clone-root .xone-eval-clones` when you want X-One to shallow-clone public repositories and run only X-One dry-run commands against those local clones. It does not run third-party install scripts, tests, containers, or project commands.
|
|
44
|
+
|
|
35
45
|
`xone-cli` orchestrates these X-One tools:
|
|
36
46
|
|
|
37
47
|
- `agent-pr-evidence`
|
|
@@ -39,13 +49,21 @@ xone runbook --head HEAD --dry-run
|
|
|
39
49
|
- `mcp-risk-index`
|
|
40
50
|
- `ai-incident-lab`
|
|
41
51
|
|
|
52
|
+
Current recommended tool versions:
|
|
53
|
+
|
|
54
|
+
- `agent-pr-evidence 0.4.2`
|
|
55
|
+
- `agent-failure-packet 0.4.2`
|
|
56
|
+
- `mcp-risk-index 0.3.1`
|
|
57
|
+
- `ai-incident-lab 0.2.2`
|
|
58
|
+
|
|
42
59
|
## Boundary
|
|
43
60
|
|
|
44
61
|
- It does not replace the underlying tools.
|
|
45
62
|
- It does not post GitHub comments.
|
|
46
63
|
- It does not modify repositories automatically.
|
|
47
64
|
- It does not make allow/deny runtime enforcement decisions.
|
|
48
|
-
- It does not
|
|
65
|
+
- It does not run third-party project scripts.
|
|
66
|
+
- `xone eval open-source` makes explicit GitHub API and `git clone --depth 1` calls only when requested by the command.
|
|
49
67
|
|
|
50
68
|
## Docs
|
|
51
69
|
|
|
@@ -30,8 +30,18 @@ xone doctor --install-plan
|
|
|
30
30
|
xone runbook --head HEAD --dry-run
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
`xone doctor --install-plan` 会输出按场景分组的安装命令、推荐的 X-One package 版本、适用时机和下一条可尝试的命令。
|
|
34
|
+
|
|
33
35
|
`xone runbook` 会自动探测本地仓库默认分支。当前还不直接接收远程 GitHub URL;请先 clone 仓库,再用 `--repo` 传本地路径。
|
|
34
36
|
|
|
37
|
+
如果要重复执行开源样本替代真实用户反馈评测,可以使用只读评测入口:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
xone eval open-source --repos repos.txt --output evaluation.md --format markdown
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
当你希望 X-One shallow clone 公开仓库并只运行 X-One dry-run 命令时,增加 `--clone-root .xone-eval-clones`。它不会运行第三方安装脚本、测试、容器或项目命令。
|
|
44
|
+
|
|
35
45
|
`xone-cli` 编排这些 X-One 工具:
|
|
36
46
|
|
|
37
47
|
- `agent-pr-evidence`
|
|
@@ -39,13 +49,21 @@ xone runbook --head HEAD --dry-run
|
|
|
39
49
|
- `mcp-risk-index`
|
|
40
50
|
- `ai-incident-lab`
|
|
41
51
|
|
|
52
|
+
当前推荐工具版本:
|
|
53
|
+
|
|
54
|
+
- `agent-pr-evidence 0.4.2`
|
|
55
|
+
- `agent-failure-packet 0.4.2`
|
|
56
|
+
- `mcp-risk-index 0.3.1`
|
|
57
|
+
- `ai-incident-lab 0.2.2`
|
|
58
|
+
|
|
42
59
|
## 边界
|
|
43
60
|
|
|
44
61
|
- 不替代底层工具。
|
|
45
62
|
- 不自动发布 GitHub 评论。
|
|
46
63
|
- 不自动修改仓库。
|
|
47
64
|
- 不做 runtime allow/deny enforcement。
|
|
48
|
-
-
|
|
65
|
+
- 不运行第三方项目脚本。
|
|
66
|
+
- `xone eval open-source` 只会在用户显式执行该命令时调用 GitHub API 和 `git clone --depth 1`。
|
|
49
67
|
|
|
50
68
|
## 文档
|
|
51
69
|
|
|
@@ -12,6 +12,8 @@ Rules:
|
|
|
12
12
|
|
|
13
13
|
The first ledger entries live in `fixtures/open-source-samples/`.
|
|
14
14
|
|
|
15
|
+
Use `xone eval open-source --repos repos.txt --output evaluation.json --format json` to refresh sanitized evaluation records. Add `--clone-root <dir>` only when shallow public clones are acceptable for the review.
|
|
16
|
+
|
|
15
17
|
| Source | Stars | Forks | Type | Feedback |
|
|
16
18
|
| --- | ---: | ---: | --- | --- |
|
|
17
19
|
| modelcontextprotocol/servers | 87186 | 10998 | mcp-server-examples | catalog-update |
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Install
|
|
2
|
+
|
|
3
|
+
## Local Development
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
python -m pip install -e '.[dev]'
|
|
7
|
+
xone --version
|
|
8
|
+
xone doctor
|
|
9
|
+
xone doctor --install-plan
|
|
10
|
+
xone runbook --head HEAD --dry-run
|
|
11
|
+
xone eval open-source --repos repos.txt --output evaluation.md --format markdown
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## User Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
python -m pip install xone-cli
|
|
18
|
+
xone doctor
|
|
19
|
+
xone doctor --install-plan
|
|
20
|
+
xone runbook --head HEAD --dry-run
|
|
21
|
+
xone eval open-source --repos repos.txt --output evaluation.md --format markdown
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`xone doctor` reports missing X-One tools and shows install guidance.
|
|
25
|
+
|
|
26
|
+
If `xone doctor` reports missing tools, run `xone doctor --install-plan`. The install plan pins the current recommended X-One package versions and shows the first next command for each scenario.
|
|
27
|
+
|
|
28
|
+
Current scenario groups:
|
|
29
|
+
|
|
30
|
+
- `evidence-loop`: install `agent-pr-evidence 0.4.2`, `agent-failure-packet 0.4.2`, `mcp-risk-index 0.3.1`, and `ai-incident-lab 0.2.2`, then run `xone runbook --head HEAD --dry-run`.
|
|
31
|
+
- `mcp-review`: install `mcp-risk-index 0.3.1`, then run `xone risk context --catalog mcp-risk-index.catalog.yml --output mcp-risk-context.md`.
|
|
32
|
+
- `incident-lab`: install `ai-incident-lab 0.2.2`, then run `xone lab evidence-loop --output agent-evidence-loop.md`.
|
|
33
|
+
|
|
34
|
+
`xone runbook` expects a local git repository. To inspect a public repository, clone it first:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
git clone --depth 1 https://github.com/owner/repo
|
|
38
|
+
xone runbook --repo repo --head HEAD --dry-run
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Open-Source Adoption Evaluation
|
|
42
|
+
|
|
43
|
+
Use `xone eval open-source` when you want a repeatable, sanitized surrogate feedback pass over public repositories.
|
|
44
|
+
|
|
45
|
+
Create a repo list:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
openai/codex
|
|
49
|
+
https://github.com/docker/mcp-gateway
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Metadata-only evaluation:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
xone eval open-source --repos repos.txt --output evaluation.json --format json
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Public shallow-clone evaluation:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
xone eval open-source --repos repos.txt --clone-root .xone-eval-clones --output evaluation.md --format markdown
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Safety boundary:
|
|
65
|
+
|
|
66
|
+
- The command records public repository metadata and X-One command summaries.
|
|
67
|
+
- It does not label third-party repositories as safe or unsafe.
|
|
68
|
+
- It does not run third-party install scripts, test scripts, containers, or project commands.
|
|
69
|
+
- `--clone-root` performs `git clone --depth 1` only, then runs X-One dry-run commands against the local clones.
|
|
@@ -9,6 +9,7 @@ from collections.abc import Sequence
|
|
|
9
9
|
from xone_cli import __version__
|
|
10
10
|
from xone_cli.evidence import build_failure_packet, collect_evidence, collect_for_runbook, gate_evidence
|
|
11
11
|
from xone_cli.lab import render_evidence_loop_lab
|
|
12
|
+
from xone_cli.open_source_eval import evaluate_open_source
|
|
12
13
|
from xone_cli.risk import render_risk_context
|
|
13
14
|
from xone_cli.runbook import write_runbook
|
|
14
15
|
from xone_cli.release import print_release_report, verify_release
|
|
@@ -71,6 +72,14 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
71
72
|
verify.add_argument("--smoke", action="store_true")
|
|
72
73
|
verify.add_argument("--json", action="store_true")
|
|
73
74
|
|
|
75
|
+
eval_parser = subparsers.add_parser("eval", help="run safe X-One evaluation workflows")
|
|
76
|
+
eval_subparsers = eval_parser.add_subparsers(dest="eval_command")
|
|
77
|
+
open_source = eval_subparsers.add_parser("open-source", help="evaluate public repositories as surrogate feedback")
|
|
78
|
+
open_source.add_argument("--repos", type=Path, required=True, help="text file containing owner/repo or GitHub URLs")
|
|
79
|
+
open_source.add_argument("--clone-root", type=Path, help="optional directory for shallow public clones")
|
|
80
|
+
open_source.add_argument("--output", type=Path, required=True, help="evaluation output path")
|
|
81
|
+
open_source.add_argument("--format", choices=("json", "markdown"), default="json")
|
|
82
|
+
|
|
74
83
|
runbook = subparsers.add_parser("runbook", help="assemble a local X-One evidence runbook")
|
|
75
84
|
_add_evidence_collection_args(runbook, require_base=False)
|
|
76
85
|
runbook.add_argument("--output", type=Path)
|
|
@@ -145,6 +154,14 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
145
154
|
print_release_report(report, as_json=args.json)
|
|
146
155
|
return 0 if report["ok"] else 1
|
|
147
156
|
|
|
157
|
+
if args.command == "eval" and args.eval_command == "open-source":
|
|
158
|
+
return evaluate_open_source(
|
|
159
|
+
repos_file=args.repos,
|
|
160
|
+
clone_root=args.clone_root,
|
|
161
|
+
output=args.output,
|
|
162
|
+
output_format=args.format,
|
|
163
|
+
)
|
|
164
|
+
|
|
148
165
|
if args.command == "runbook":
|
|
149
166
|
code, report, message = collect_for_runbook(
|
|
150
167
|
repo=args.repo,
|
|
@@ -193,8 +210,10 @@ def _print_doctor(report) -> None:
|
|
|
193
210
|
|
|
194
211
|
def _print_install_plan(profile: str) -> None:
|
|
195
212
|
print("X-One install plan")
|
|
196
|
-
for
|
|
197
|
-
print(f"- {name}: {command}")
|
|
213
|
+
for item in install_plan(profile):
|
|
214
|
+
print(f"- {item['name']}: {item['command']}")
|
|
215
|
+
print(f" when: {item['when']}")
|
|
216
|
+
print(f" next: {item['next']}")
|
|
198
217
|
|
|
199
218
|
|
|
200
219
|
def _add_evidence_collection_args(parser: argparse.ArgumentParser, *, require_base: bool = True) -> None:
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import subprocess
|
|
5
|
+
import urllib.request
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from datetime import date
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from urllib.parse import urlparse
|
|
10
|
+
|
|
11
|
+
from xone_cli.evidence import collect_for_runbook
|
|
12
|
+
from xone_cli.tooling import doctor_status
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
BATCH_SCHEMA_VERSION = "xone.open_source_evaluation_batch.v1"
|
|
16
|
+
RECORD_SCHEMA_VERSION = "xone.open_source_evaluation.v1"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True)
|
|
20
|
+
class EvalRecord:
|
|
21
|
+
source: str
|
|
22
|
+
source_url: str
|
|
23
|
+
snapshot_date: str
|
|
24
|
+
stars: int
|
|
25
|
+
forks: int
|
|
26
|
+
open_issues: int
|
|
27
|
+
default_branch: str
|
|
28
|
+
language: str | None
|
|
29
|
+
commands_run: list[dict]
|
|
30
|
+
sanitization: dict
|
|
31
|
+
decision: str
|
|
32
|
+
|
|
33
|
+
def to_dict(self) -> dict:
|
|
34
|
+
return {
|
|
35
|
+
"schema_version": RECORD_SCHEMA_VERSION,
|
|
36
|
+
"source": self.source,
|
|
37
|
+
"source_url": self.source_url,
|
|
38
|
+
"snapshot_date": self.snapshot_date,
|
|
39
|
+
"stars": self.stars,
|
|
40
|
+
"forks": self.forks,
|
|
41
|
+
"open_issues": self.open_issues,
|
|
42
|
+
"default_branch": self.default_branch,
|
|
43
|
+
"language": self.language,
|
|
44
|
+
"categories": [],
|
|
45
|
+
"xone_tools_used": ["xone-cli"],
|
|
46
|
+
"commands_run": self.commands_run,
|
|
47
|
+
"role_findings": [],
|
|
48
|
+
"sanitization": self.sanitization,
|
|
49
|
+
"decision": self.decision,
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def evaluate_open_source(
|
|
54
|
+
*,
|
|
55
|
+
repos_file: Path,
|
|
56
|
+
output: Path,
|
|
57
|
+
output_format: str,
|
|
58
|
+
clone_root: Path | None = None,
|
|
59
|
+
snapshot_date: date | None = None,
|
|
60
|
+
) -> int:
|
|
61
|
+
snapshot = snapshot_date or date.today()
|
|
62
|
+
sources = read_repo_refs(repos_file)
|
|
63
|
+
records = []
|
|
64
|
+
for source in sources:
|
|
65
|
+
metadata = fetch_github_metadata(source, snapshot)
|
|
66
|
+
commands = [
|
|
67
|
+
{
|
|
68
|
+
"name": "doctor-json",
|
|
69
|
+
"command": "xone doctor --json",
|
|
70
|
+
"mode": "read-only",
|
|
71
|
+
"result": "pass" if doctor_status().ok else "needs-install",
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
if clone_root is None:
|
|
75
|
+
commands.append(
|
|
76
|
+
{
|
|
77
|
+
"name": "runbook-dry-run",
|
|
78
|
+
"command": "xone runbook --repo <local-clone> --head HEAD --dry-run",
|
|
79
|
+
"mode": "read-only",
|
|
80
|
+
"result": "skipped",
|
|
81
|
+
"reason": "clone-root not provided",
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
else:
|
|
85
|
+
try:
|
|
86
|
+
local_repo = clone_repo(metadata, clone_root)
|
|
87
|
+
except Exception as exc:
|
|
88
|
+
commands.append(
|
|
89
|
+
{
|
|
90
|
+
"name": "shallow-clone",
|
|
91
|
+
"command": f"git clone --depth 1 {metadata['source_url']} <clone-root>",
|
|
92
|
+
"mode": "read-only",
|
|
93
|
+
"result": "fail",
|
|
94
|
+
"output_summary": str(exc),
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
else:
|
|
98
|
+
code, _report, message = collect_for_runbook(
|
|
99
|
+
repo=str(local_repo),
|
|
100
|
+
base=None,
|
|
101
|
+
head="HEAD",
|
|
102
|
+
test_logs=[],
|
|
103
|
+
profile="strict",
|
|
104
|
+
dry_run=True,
|
|
105
|
+
)
|
|
106
|
+
commands.append(
|
|
107
|
+
{
|
|
108
|
+
"name": "runbook-dry-run",
|
|
109
|
+
"command": "xone runbook --repo <local-clone> --head HEAD --dry-run",
|
|
110
|
+
"mode": "read-only",
|
|
111
|
+
"result": "pass" if code == 0 else "fail",
|
|
112
|
+
"output_summary": message.strip(),
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
records.append(_record_from_metadata(metadata, commands).to_dict())
|
|
116
|
+
|
|
117
|
+
batch = {
|
|
118
|
+
"schema_version": BATCH_SCHEMA_VERSION,
|
|
119
|
+
"snapshot_date": snapshot.isoformat(),
|
|
120
|
+
"records": records,
|
|
121
|
+
}
|
|
122
|
+
if output_format == "json":
|
|
123
|
+
output.write_text(json.dumps(batch, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
|
124
|
+
else:
|
|
125
|
+
output.write_text(render_markdown(batch), encoding="utf-8")
|
|
126
|
+
print(f"Wrote {len(records)} open-source evaluation records to {output}")
|
|
127
|
+
return 0
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def read_repo_refs(path: Path) -> list[str]:
|
|
131
|
+
refs = []
|
|
132
|
+
for line in path.read_text(encoding="utf-8").splitlines():
|
|
133
|
+
value = line.strip()
|
|
134
|
+
if not value or value.startswith("#"):
|
|
135
|
+
continue
|
|
136
|
+
refs.append(normalize_repo_ref(value))
|
|
137
|
+
return refs
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def normalize_repo_ref(value: str) -> str:
|
|
141
|
+
parsed = urlparse(value)
|
|
142
|
+
if parsed.netloc == "github.com":
|
|
143
|
+
parts = [part for part in parsed.path.split("/") if part]
|
|
144
|
+
if len(parts) >= 2:
|
|
145
|
+
return f"{parts[0]}/{parts[1].removesuffix('.git')}"
|
|
146
|
+
return value.removesuffix(".git")
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def fetch_github_metadata(repo: str, snapshot_date: date) -> dict:
|
|
150
|
+
request = urllib.request.Request(
|
|
151
|
+
f"https://api.github.com/repos/{repo}",
|
|
152
|
+
headers={"Accept": "application/vnd.github+json", "User-Agent": "xone-cli-open-source-eval"},
|
|
153
|
+
)
|
|
154
|
+
with urllib.request.urlopen(request, timeout=20) as response:
|
|
155
|
+
payload = json.load(response)
|
|
156
|
+
return {
|
|
157
|
+
"source": payload["full_name"],
|
|
158
|
+
"source_url": payload["html_url"],
|
|
159
|
+
"snapshot_date": snapshot_date.isoformat(),
|
|
160
|
+
"stars": payload["stargazers_count"],
|
|
161
|
+
"forks": payload["forks_count"],
|
|
162
|
+
"open_issues": payload["open_issues_count"],
|
|
163
|
+
"default_branch": payload["default_branch"],
|
|
164
|
+
"language": payload.get("language"),
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def clone_repo(record: dict, root: Path) -> Path:
|
|
169
|
+
root.mkdir(parents=True, exist_ok=True)
|
|
170
|
+
target = root / record["source"].replace("/", "-")
|
|
171
|
+
if (target / ".git").exists():
|
|
172
|
+
return target
|
|
173
|
+
subprocess.run(
|
|
174
|
+
["git", "clone", "--depth", "1", record["source_url"], str(target)],
|
|
175
|
+
check=True,
|
|
176
|
+
text=True,
|
|
177
|
+
stdout=subprocess.PIPE,
|
|
178
|
+
stderr=subprocess.PIPE,
|
|
179
|
+
)
|
|
180
|
+
return target
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def render_markdown(batch: dict) -> str:
|
|
184
|
+
lines = [
|
|
185
|
+
"# X-One Open-Source Adoption Evaluation",
|
|
186
|
+
"",
|
|
187
|
+
f"Snapshot date: {batch['snapshot_date']}",
|
|
188
|
+
"",
|
|
189
|
+
"| Source | Stars | Forks | Issues | Default Branch | Decision |",
|
|
190
|
+
"|---|---:|---:|---:|---|---|",
|
|
191
|
+
]
|
|
192
|
+
for record in batch["records"]:
|
|
193
|
+
lines.append(
|
|
194
|
+
f"| {record['source']} | {record['stars']} | {record['forks']} | "
|
|
195
|
+
f"{record['open_issues']} | {record['default_branch']} | {record['decision']} |"
|
|
196
|
+
)
|
|
197
|
+
lines.extend(["", "## Command Evidence", ""])
|
|
198
|
+
for record in batch["records"]:
|
|
199
|
+
lines.append(f"### {record['source']}")
|
|
200
|
+
for command in record["commands_run"]:
|
|
201
|
+
lines.append(f"- {command.get('name', command['command'])}: {command['result']}")
|
|
202
|
+
lines.append(f" - command: `{command['command']}`")
|
|
203
|
+
if command.get("output_summary"):
|
|
204
|
+
lines.append(f" - summary: `{command['output_summary']}`")
|
|
205
|
+
lines.append("")
|
|
206
|
+
return "\n".join(lines).rstrip() + "\n"
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def _record_from_metadata(metadata: dict, commands: list[dict]) -> EvalRecord:
|
|
210
|
+
return EvalRecord(
|
|
211
|
+
source=metadata["source"],
|
|
212
|
+
source_url=metadata["source_url"],
|
|
213
|
+
snapshot_date=metadata["snapshot_date"],
|
|
214
|
+
stars=metadata["stars"],
|
|
215
|
+
forks=metadata["forks"],
|
|
216
|
+
open_issues=metadata["open_issues"],
|
|
217
|
+
default_branch=metadata["default_branch"],
|
|
218
|
+
language=metadata.get("language"),
|
|
219
|
+
commands_run=commands,
|
|
220
|
+
sanitization={
|
|
221
|
+
"raw_logs_committed": False,
|
|
222
|
+
"secrets_removed": True,
|
|
223
|
+
"third_party_safety_label_used": False,
|
|
224
|
+
},
|
|
225
|
+
decision="defer-with-reason",
|
|
226
|
+
)
|
|
@@ -24,6 +24,13 @@ PACKAGE_BY_TOOL = {
|
|
|
24
24
|
"ai-incident-lab": "xone-ai-incident-lab",
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
RECOMMENDED_VERSION_BY_TOOL = {
|
|
28
|
+
"agent-pr-evidence": "0.4.2",
|
|
29
|
+
"agent-failure-packet": "0.4.2",
|
|
30
|
+
"mcp-risk-index": "0.3.1",
|
|
31
|
+
"ai-incident-lab": "0.2.2",
|
|
32
|
+
}
|
|
33
|
+
|
|
27
34
|
INSTALL_PLAN_GROUPS = {
|
|
28
35
|
"evidence-loop": (
|
|
29
36
|
"agent-pr-evidence",
|
|
@@ -36,6 +43,21 @@ INSTALL_PLAN_GROUPS = {
|
|
|
36
43
|
"all": REQUIRED_TOOLS,
|
|
37
44
|
}
|
|
38
45
|
|
|
46
|
+
INSTALL_PLAN_GUIDANCE = {
|
|
47
|
+
"evidence-loop": {
|
|
48
|
+
"when": "review an agent PR, create a redacted failure packet, attach MCP risk context, or run a safe local lab",
|
|
49
|
+
"next": "xone runbook --head HEAD --dry-run",
|
|
50
|
+
},
|
|
51
|
+
"mcp-review": {
|
|
52
|
+
"when": "attach evidence-backed MCP risk context without making an allow/deny decision",
|
|
53
|
+
"next": "xone risk context --catalog mcp-risk-index.catalog.yml --output mcp-risk-context.md",
|
|
54
|
+
},
|
|
55
|
+
"incident-lab": {
|
|
56
|
+
"when": "practice the Agent Evidence Loop with safe-local scenarios",
|
|
57
|
+
"next": "xone lab evidence-loop --output agent-evidence-loop.md",
|
|
58
|
+
},
|
|
59
|
+
}
|
|
60
|
+
|
|
39
61
|
|
|
40
62
|
def find_tool(name: str) -> str | None:
|
|
41
63
|
return shutil.which(name)
|
|
@@ -43,18 +65,31 @@ def find_tool(name: str) -> str | None:
|
|
|
43
65
|
|
|
44
66
|
def install_hint(name: str) -> str:
|
|
45
67
|
package = PACKAGE_BY_TOOL.get(name, name)
|
|
46
|
-
|
|
68
|
+
version = RECOMMENDED_VERSION_BY_TOOL.get(name)
|
|
69
|
+
pinned = f"{package}=={version}" if version else package
|
|
70
|
+
return f"python -m pip install {pinned}"
|
|
47
71
|
|
|
48
72
|
|
|
49
|
-
def install_plan(profile: str = "all") -> list[
|
|
73
|
+
def install_plan(profile: str = "all") -> list[dict[str, str]]:
|
|
50
74
|
if profile == "all":
|
|
51
75
|
groups = ("evidence-loop", "mcp-review", "incident-lab")
|
|
52
76
|
else:
|
|
53
77
|
groups = (profile,)
|
|
54
78
|
plan = []
|
|
55
79
|
for group in groups:
|
|
56
|
-
packages = [
|
|
57
|
-
|
|
80
|
+
packages = [
|
|
81
|
+
f"{PACKAGE_BY_TOOL[name]}=={RECOMMENDED_VERSION_BY_TOOL[name]}"
|
|
82
|
+
for name in INSTALL_PLAN_GROUPS[group]
|
|
83
|
+
]
|
|
84
|
+
guidance = INSTALL_PLAN_GUIDANCE[group]
|
|
85
|
+
plan.append(
|
|
86
|
+
{
|
|
87
|
+
"name": group,
|
|
88
|
+
"command": f"python -m pip install {' '.join(packages)}",
|
|
89
|
+
"when": guidance["when"],
|
|
90
|
+
"next": guidance["next"],
|
|
91
|
+
}
|
|
92
|
+
)
|
|
58
93
|
return plan
|
|
59
94
|
|
|
60
95
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xone-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Unified CLI entry point for X-One Agent Evidence Loop workflows.
|
|
5
5
|
Author: X-One-AI
|
|
6
6
|
License-Expression: MIT
|
|
@@ -57,8 +57,18 @@ xone doctor --install-plan
|
|
|
57
57
|
xone runbook --head HEAD --dry-run
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
+
`xone doctor --install-plan` prints scenario-specific install commands with recommended X-One package versions, when to use each scenario, and the next command to try.
|
|
61
|
+
|
|
60
62
|
`xone runbook` auto-detects the local repository default branch. Remote GitHub URLs are not accepted yet; clone the repository first, then pass the local path with `--repo`.
|
|
61
63
|
|
|
64
|
+
For repeatable open-source adoption checks, use the read-only evaluator:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
xone eval open-source --repos repos.txt --output evaluation.md --format markdown
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Add `--clone-root .xone-eval-clones` when you want X-One to shallow-clone public repositories and run only X-One dry-run commands against those local clones. It does not run third-party install scripts, tests, containers, or project commands.
|
|
71
|
+
|
|
62
72
|
`xone-cli` orchestrates these X-One tools:
|
|
63
73
|
|
|
64
74
|
- `agent-pr-evidence`
|
|
@@ -66,13 +76,21 @@ xone runbook --head HEAD --dry-run
|
|
|
66
76
|
- `mcp-risk-index`
|
|
67
77
|
- `ai-incident-lab`
|
|
68
78
|
|
|
79
|
+
Current recommended tool versions:
|
|
80
|
+
|
|
81
|
+
- `agent-pr-evidence 0.4.2`
|
|
82
|
+
- `agent-failure-packet 0.4.2`
|
|
83
|
+
- `mcp-risk-index 0.3.1`
|
|
84
|
+
- `ai-incident-lab 0.2.2`
|
|
85
|
+
|
|
69
86
|
## Boundary
|
|
70
87
|
|
|
71
88
|
- It does not replace the underlying tools.
|
|
72
89
|
- It does not post GitHub comments.
|
|
73
90
|
- It does not modify repositories automatically.
|
|
74
91
|
- It does not make allow/deny runtime enforcement decisions.
|
|
75
|
-
- It does not
|
|
92
|
+
- It does not run third-party project scripts.
|
|
93
|
+
- `xone eval open-source` makes explicit GitHub API and `git clone --depth 1` calls only when requested by the command.
|
|
76
94
|
|
|
77
95
|
## Docs
|
|
78
96
|
|
|
@@ -30,6 +30,7 @@ src/xone_cli/cli.py
|
|
|
30
30
|
src/xone_cli/evidence.py
|
|
31
31
|
src/xone_cli/lab.py
|
|
32
32
|
src/xone_cli/model.py
|
|
33
|
+
src/xone_cli/open_source_eval.py
|
|
33
34
|
src/xone_cli/release.py
|
|
34
35
|
src/xone_cli/repo_context.py
|
|
35
36
|
src/xone_cli/risk.py
|
|
@@ -44,6 +45,7 @@ src/xone_cli.egg-info/top_level.txt
|
|
|
44
45
|
tests/test_cli.py
|
|
45
46
|
tests/test_docs.py
|
|
46
47
|
tests/test_evidence.py
|
|
48
|
+
tests/test_open_source_eval.py
|
|
47
49
|
tests/test_release.py
|
|
48
50
|
tests/test_repo_context.py
|
|
49
51
|
tests/test_risk_lab.py
|
|
@@ -12,7 +12,7 @@ def _fake_tool(bin_dir: Path, name: str, body: str = "echo tool") -> None:
|
|
|
12
12
|
|
|
13
13
|
def test_version_outputs_package_version(capsys):
|
|
14
14
|
assert main(["--version"]) == 0
|
|
15
|
-
assert capsys.readouterr().out.strip() == "xone 0.1.
|
|
15
|
+
assert capsys.readouterr().out.strip() == "xone 0.1.3"
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
def test_doctor_json_reports_required_tools(tmp_path, monkeypatch, capsys):
|
|
@@ -35,9 +35,13 @@ def test_doctor_install_plan_outputs_scenario_commands(capsys):
|
|
|
35
35
|
output = capsys.readouterr().out
|
|
36
36
|
assert "X-One install plan" in output
|
|
37
37
|
assert "evidence-loop" in output
|
|
38
|
-
assert "python -m pip install xone-agent-pr-evidence xone-agent-failure-packet xone-mcp-risk-index xone-ai-incident-lab" in output
|
|
38
|
+
assert "python -m pip install xone-agent-pr-evidence==0.4.2 xone-agent-failure-packet==0.4.2 xone-mcp-risk-index==0.3.1 xone-ai-incident-lab==0.2.2" in output
|
|
39
|
+
assert "when: review an agent PR, create a redacted failure packet, attach MCP risk context, or run a safe local lab" in output
|
|
40
|
+
assert "next: xone runbook --head HEAD --dry-run" in output
|
|
39
41
|
assert "mcp-review" in output
|
|
42
|
+
assert "next: xone risk context --catalog mcp-risk-index.catalog.yml --output mcp-risk-context.md" in output
|
|
40
43
|
assert "incident-lab" in output
|
|
44
|
+
assert "next: xone lab evidence-loop --output agent-evidence-loop.md" in output
|
|
41
45
|
|
|
42
46
|
|
|
43
47
|
def test_runbook_dry_run_is_available(capsys):
|
|
@@ -19,23 +19,27 @@ def test_docs_and_package_metadata_stay_aligned():
|
|
|
19
19
|
assert "xone doctor" in english
|
|
20
20
|
assert "xone doctor --install-plan" in english
|
|
21
21
|
assert "xone runbook --head HEAD --dry-run" in english
|
|
22
|
+
assert "xone eval open-source" in english
|
|
22
23
|
assert "Remote GitHub URLs are not accepted yet" in english
|
|
23
24
|
assert "xone doctor" in chinese
|
|
24
25
|
assert "xone doctor --install-plan" in chinese
|
|
25
26
|
assert "xone runbook --head HEAD --dry-run" in chinese
|
|
27
|
+
assert "xone eval open-source" in chinese
|
|
26
28
|
assert "远程 GitHub URL" in chinese
|
|
27
29
|
assert "git clone --depth 1 https://github.com/owner/repo" in Path("docs/install.md").read_text(encoding="utf-8")
|
|
30
|
+
assert "xone eval open-source --repos repos.txt" in Path("docs/install.md").read_text(encoding="utf-8")
|
|
28
31
|
assert "xone release verify --build --install --smoke" in Path("docs/release.md").read_text(encoding="utf-8")
|
|
29
32
|
assert 'name = "xone-cli"' in pyproject
|
|
30
|
-
assert 'version = "0.1.
|
|
31
|
-
assert __version__ == "0.1.
|
|
32
|
-
assert "## 0.1.
|
|
33
|
+
assert 'version = "0.1.3"' in pyproject
|
|
34
|
+
assert __version__ == "0.1.3"
|
|
35
|
+
assert "## 0.1.3" in changelog
|
|
33
36
|
assert 'xone = "xone_cli.cli:entrypoint"' in pyproject
|
|
34
37
|
assert "python -m pytest -q" in ci
|
|
35
38
|
assert "xone runbook --base HEAD~1 --head HEAD --dry-run" in ci
|
|
36
39
|
assert "environment: testpypi" in publish
|
|
37
40
|
assert "startsWith(github.ref, 'refs/tags/v')" in publish
|
|
38
41
|
assert "doctor --install-plan" in changelog
|
|
42
|
+
assert "recommended X-One tool versions" in changelog
|
|
39
43
|
assert "auto-detect the local repository default branch" in changelog
|
|
40
44
|
assert "Do not make hidden network calls" in production
|
|
41
45
|
assert "Keep top-level commands small" in main_entry
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from datetime import date
|
|
3
|
+
|
|
4
|
+
from xone_cli.cli import main
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_eval_open_source_json_outputs_sanitized_records(tmp_path, monkeypatch):
|
|
8
|
+
repos = tmp_path / "repos.txt"
|
|
9
|
+
repos.write_text("openai/codex\nhttps://github.com/docker/mcp-gateway\n", encoding="utf-8")
|
|
10
|
+
output = tmp_path / "records.json"
|
|
11
|
+
|
|
12
|
+
def fake_metadata(repo, snapshot_date):
|
|
13
|
+
return {
|
|
14
|
+
"source": repo,
|
|
15
|
+
"source_url": f"https://github.com/{repo}",
|
|
16
|
+
"snapshot_date": snapshot_date.isoformat(),
|
|
17
|
+
"stars": 10,
|
|
18
|
+
"forks": 2,
|
|
19
|
+
"open_issues": 1,
|
|
20
|
+
"default_branch": "main",
|
|
21
|
+
"language": "Python",
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
monkeypatch.setattr("xone_cli.open_source_eval.fetch_github_metadata", fake_metadata)
|
|
25
|
+
|
|
26
|
+
assert main(["eval", "open-source", "--repos", str(repos), "--output", str(output), "--format", "json"]) == 0
|
|
27
|
+
|
|
28
|
+
payload = json.loads(output.read_text(encoding="utf-8"))
|
|
29
|
+
assert payload["schema_version"] == "xone.open_source_evaluation_batch.v1"
|
|
30
|
+
assert [record["source"] for record in payload["records"]] == ["openai/codex", "docker/mcp-gateway"]
|
|
31
|
+
assert payload["records"][0]["sanitization"] == {
|
|
32
|
+
"raw_logs_committed": False,
|
|
33
|
+
"secrets_removed": True,
|
|
34
|
+
"third_party_safety_label_used": False,
|
|
35
|
+
}
|
|
36
|
+
assert payload["records"][0]["commands_run"][0]["command"] == "xone doctor --json"
|
|
37
|
+
assert payload["records"][0]["commands_run"][1]["result"] == "skipped"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_eval_open_source_with_clone_root_runs_local_runbook_dry_run(tmp_path, monkeypatch):
|
|
41
|
+
repos = tmp_path / "repos.txt"
|
|
42
|
+
repos.write_text("upstash/context7\n", encoding="utf-8")
|
|
43
|
+
output = tmp_path / "records.md"
|
|
44
|
+
clone_root = tmp_path / "clones"
|
|
45
|
+
|
|
46
|
+
def fake_metadata(repo, snapshot_date):
|
|
47
|
+
return {
|
|
48
|
+
"source": repo,
|
|
49
|
+
"source_url": f"https://github.com/{repo}",
|
|
50
|
+
"snapshot_date": snapshot_date.isoformat(),
|
|
51
|
+
"stars": 20,
|
|
52
|
+
"forks": 3,
|
|
53
|
+
"open_issues": 4,
|
|
54
|
+
"default_branch": "master",
|
|
55
|
+
"language": "TypeScript",
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
def fake_clone(record, root):
|
|
59
|
+
repo = root / "upstash-context7"
|
|
60
|
+
(repo / ".git").mkdir(parents=True)
|
|
61
|
+
(repo / ".git" / "HEAD").write_text("ref: refs/heads/master\n", encoding="utf-8")
|
|
62
|
+
return repo
|
|
63
|
+
|
|
64
|
+
monkeypatch.setattr("xone_cli.open_source_eval.fetch_github_metadata", fake_metadata)
|
|
65
|
+
monkeypatch.setattr("xone_cli.open_source_eval.clone_repo", fake_clone)
|
|
66
|
+
|
|
67
|
+
assert main(
|
|
68
|
+
[
|
|
69
|
+
"eval",
|
|
70
|
+
"open-source",
|
|
71
|
+
"--repos",
|
|
72
|
+
str(repos),
|
|
73
|
+
"--clone-root",
|
|
74
|
+
str(clone_root),
|
|
75
|
+
"--output",
|
|
76
|
+
str(output),
|
|
77
|
+
"--format",
|
|
78
|
+
"markdown",
|
|
79
|
+
]
|
|
80
|
+
) == 0
|
|
81
|
+
|
|
82
|
+
markdown = output.read_text(encoding="utf-8")
|
|
83
|
+
assert "# X-One Open-Source Adoption Evaluation" in markdown
|
|
84
|
+
assert "upstash/context7" in markdown
|
|
85
|
+
assert "runbook-dry-run" in markdown
|
|
86
|
+
assert "--base master" in markdown
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def test_eval_open_source_records_clone_failure_without_crashing(tmp_path, monkeypatch):
|
|
90
|
+
repos = tmp_path / "repos.txt"
|
|
91
|
+
repos.write_text("cline/cline\nopenai/codex\n", encoding="utf-8")
|
|
92
|
+
output = tmp_path / "records.json"
|
|
93
|
+
clone_root = tmp_path / "clones"
|
|
94
|
+
|
|
95
|
+
def fake_metadata(repo, snapshot_date):
|
|
96
|
+
return {
|
|
97
|
+
"source": repo,
|
|
98
|
+
"source_url": f"https://github.com/{repo}",
|
|
99
|
+
"snapshot_date": snapshot_date.isoformat(),
|
|
100
|
+
"stars": 10,
|
|
101
|
+
"forks": 2,
|
|
102
|
+
"open_issues": 1,
|
|
103
|
+
"default_branch": "main",
|
|
104
|
+
"language": "TypeScript",
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
def fake_clone(record, root):
|
|
108
|
+
if record["source"] == "cline/cline":
|
|
109
|
+
raise RuntimeError("clone failed")
|
|
110
|
+
repo = root / "openai-codex"
|
|
111
|
+
(repo / ".git").mkdir(parents=True)
|
|
112
|
+
(repo / ".git" / "HEAD").write_text("ref: refs/heads/main\n", encoding="utf-8")
|
|
113
|
+
return repo
|
|
114
|
+
|
|
115
|
+
monkeypatch.setattr("xone_cli.open_source_eval.fetch_github_metadata", fake_metadata)
|
|
116
|
+
monkeypatch.setattr("xone_cli.open_source_eval.clone_repo", fake_clone)
|
|
117
|
+
|
|
118
|
+
assert main(
|
|
119
|
+
[
|
|
120
|
+
"eval",
|
|
121
|
+
"open-source",
|
|
122
|
+
"--repos",
|
|
123
|
+
str(repos),
|
|
124
|
+
"--clone-root",
|
|
125
|
+
str(clone_root),
|
|
126
|
+
"--output",
|
|
127
|
+
str(output),
|
|
128
|
+
"--format",
|
|
129
|
+
"json",
|
|
130
|
+
]
|
|
131
|
+
) == 0
|
|
132
|
+
|
|
133
|
+
payload = json.loads(output.read_text(encoding="utf-8"))
|
|
134
|
+
assert [record["source"] for record in payload["records"]] == ["cline/cline", "openai/codex"]
|
|
135
|
+
failed_command = payload["records"][0]["commands_run"][1]
|
|
136
|
+
assert failed_command["name"] == "shallow-clone"
|
|
137
|
+
assert failed_command["result"] == "fail"
|
|
138
|
+
assert failed_command["mode"] == "read-only"
|
|
139
|
+
assert payload["records"][1]["commands_run"][1]["name"] == "runbook-dry-run"
|
xone_cli-0.1.1/CHANGELOG.md
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## 0.1.1
|
|
4
|
-
|
|
5
|
-
- Add scenario-based `xone doctor --install-plan` guidance.
|
|
6
|
-
- Let `xone runbook` auto-detect the local repository default branch when `--base` is omitted.
|
|
7
|
-
- Reject remote repository URLs in `xone runbook` with a clone-first message instead of producing a misleading dry run.
|
|
8
|
-
- Expand open-source feedback classifications for adoption evaluation.
|
|
9
|
-
|
|
10
|
-
## 0.1.0
|
|
11
|
-
|
|
12
|
-
- Add the first X-One unified CLI foundation.
|
xone_cli-0.1.1/docs/install.md
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# Install
|
|
2
|
-
|
|
3
|
-
## Local Development
|
|
4
|
-
|
|
5
|
-
```bash
|
|
6
|
-
python -m pip install -e '.[dev]'
|
|
7
|
-
xone --version
|
|
8
|
-
xone doctor
|
|
9
|
-
xone doctor --install-plan
|
|
10
|
-
xone runbook --head HEAD --dry-run
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## User Install
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
python -m pip install xone-cli
|
|
17
|
-
xone doctor
|
|
18
|
-
xone doctor --install-plan
|
|
19
|
-
xone runbook --head HEAD --dry-run
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
`xone doctor` reports missing X-One tools and shows install guidance.
|
|
23
|
-
|
|
24
|
-
If `xone doctor` reports missing tools, install the suggested X-One packages and run it again before using `evidence`, `risk`, or `lab` commands.
|
|
25
|
-
|
|
26
|
-
`xone runbook` expects a local git repository. To inspect a public repository, clone it first:
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
git clone --depth 1 https://github.com/owner/repo
|
|
30
|
-
xone runbook --repo repo --head HEAD --dry-run
|
|
31
|
-
```
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xone_cli-0.1.1 → xone_cli-0.1.3}/fixtures/open-source-samples/github-github-mcp-server.json
RENAMED
|
File without changes
|
{xone_cli-0.1.1 → xone_cli-0.1.3}/fixtures/open-source-samples/microsoft-playwright-mcp.json
RENAMED
|
File without changes
|
{xone_cli-0.1.1 → xone_cli-0.1.3}/fixtures/open-source-samples/modelcontextprotocol-servers.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|