preflight-check-cli 1.0.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.
- preflight_check_cli-1.0.1/.dockerignore +21 -0
- preflight_check_cli-1.0.1/.gitattributes +21 -0
- preflight_check_cli-1.0.1/.github/workflows/ci.yml +60 -0
- preflight_check_cli-1.0.1/.github/workflows/publish.yml +89 -0
- preflight_check_cli-1.0.1/.gitignore +29 -0
- preflight_check_cli-1.0.1/Dockerfile +58 -0
- preflight_check_cli-1.0.1/LICENSE +21 -0
- preflight_check_cli-1.0.1/PKG-INFO +470 -0
- preflight_check_cli-1.0.1/README.md +412 -0
- preflight_check_cli-1.0.1/docs/ARCHITECTURE.md +303 -0
- preflight_check_cli-1.0.1/docs/HANDOVER.md +328 -0
- preflight_check_cli-1.0.1/docs/KNOWLEDGE.md +223 -0
- preflight_check_cli-1.0.1/docs/OVERVIEW.md +192 -0
- preflight_check_cli-1.0.1/docs/PITFALLS.md +270 -0
- preflight_check_cli-1.0.1/docs/PLAN.md +581 -0
- preflight_check_cli-1.0.1/docs/PROGRESS.md +2379 -0
- preflight_check_cli-1.0.1/docs/RULES.md +444 -0
- preflight_check_cli-1.0.1/docs/STATUS.md +317 -0
- preflight_check_cli-1.0.1/pyproject.toml +207 -0
- preflight_check_cli-1.0.1/scripts/check.ps1 +63 -0
- preflight_check_cli-1.0.1/scripts/check_claims_accuracy.py +124 -0
- preflight_check_cli-1.0.1/scripts/measure_claims.py +152 -0
- preflight_check_cli-1.0.1/scripts/run_tests_in_container.sh +40 -0
- preflight_check_cli-1.0.1/scripts/setup.ps1 +129 -0
- preflight_check_cli-1.0.1/src/preflight_check/__init__.py +5 -0
- preflight_check_cli-1.0.1/src/preflight_check/cli.py +1315 -0
- preflight_check_cli-1.0.1/src/preflight_check/core/__init__.py +1 -0
- preflight_check_cli-1.0.1/src/preflight_check/core/claims.py +468 -0
- preflight_check_cli-1.0.1/src/preflight_check/core/interact.py +212 -0
- preflight_check_cli-1.0.1/src/preflight_check/core/models.py +530 -0
- preflight_check_cli-1.0.1/src/preflight_check/core/registry.py +698 -0
- preflight_check_cli-1.0.1/src/preflight_check/core/release.py +328 -0
- preflight_check_cli-1.0.1/src/preflight_check/core/report.py +284 -0
- preflight_check_cli-1.0.1/src/preflight_check/core/specs.py +483 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/__init__.py +77 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/broken-agent/.gitignore +3 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/broken-agent/ROLLBACK.md +9 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/broken-agent/RUNBOOK.md +13 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/broken-agent/agent.py +27 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/broken-agent/config.py +1 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/broken-agent/llm.py +7 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/broken-agent/models.py +13 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/broken-agent/tests/test_agent.py +2 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/broken-agent/tests/test_e2e_demo.py +2 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/broken-agent/tests/test_integration_flow.py +2 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/broken-agent/tests/test_smoke.py +2 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/broken-agent/tools.py +3 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/clean-agent/.gitignore +3 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/clean-agent/ROLLBACK.md +9 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/clean-agent/RUNBOOK.md +13 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/clean-agent/agent.py +65 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/clean-agent/config.py +3 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/clean-agent/llm.py +19 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/clean-agent/models.py +23 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/clean-agent/tests/test_agent.py +2 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/clean-agent/tests/test_e2e_demo.py +2 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/clean-agent/tests/test_integration_flow.py +2 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/clean-agent/tests/test_smoke.py +2 -0
- preflight_check_cli-1.0.1/src/preflight_check/demo/clean-agent/tools.py +7 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/__init__.py +12 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/adapters/__init__.py +30 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/adapters/base.py +395 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/adapters/gitleaks.py +135 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/adapters/pip_audit.py +136 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/adapters/ruff_tool.py +147 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/agent_analysis.py +614 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/agent_checks.py +997 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/ast_checks.py +397 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/base.py +193 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/cross_checks.py +506 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/derive.py +182 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/engine.py +137 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/generic.py +224 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/ignore.py +104 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/probe.py +323 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/registry.py +96 -0
- preflight_check_cli-1.0.1/src/preflight_check/detect/repo.py +338 -0
- preflight_check_cli-1.0.1/src/preflight_check/interact/__init__.py +61 -0
- preflight_check_cli-1.0.1/src/preflight_check/interact/questions.py +159 -0
- preflight_check_cli-1.0.1/src/preflight_check/interact/store.py +109 -0
- preflight_check_cli-1.0.1/src/preflight_check/interact/waiver.py +190 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/claims/verification.yaml +119 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/docs/roles.yaml +312 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/invariants/no-duplicate.yaml +6 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/invariants/no-leak.yaml +6 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/invariants/no-loss.yaml +6 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/invariants/no-overrun.yaml +8 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/invariants/no-unauthorized.yaml +7 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/invariants/ordering.yaml +7 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/mechanisms/cache.yaml +43 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/mechanisms/external-api.yaml +50 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/mechanisms/llm-call.yaml +81 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/mechanisms/long-connection.yaml +52 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/mechanisms/message-queue.yaml +56 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/mechanisms/multi-region.yaml +46 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/mechanisms/object-storage.yaml +50 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/mechanisms/relational-db.yaml +67 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/mechanisms/scheduled-job.yaml +42 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/mechanisms/search-index.yaml +37 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/profiles/agent-enterprise.yaml +11 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/profiles/cli-oss.yaml +9 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/profiles/saas-consumer.yaml +29 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/profiles/saas-enterprise.yaml +25 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/questions/questions.yaml +113 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/config-name-drift.yaml +42 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/cost-from-price-table.yaml +43 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/env-not-ignored.yaml +40 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/exception-swallowed.yaml +36 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/hardcoded-secret.yaml +35 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/leaked-secret.yaml +34 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/model-name-scattered.yaml +33 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/no-budget-breaker.yaml +40 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/no-context-guard.yaml +40 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/no-eval-fingerprint.yaml +42 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/no-evidence-check.yaml +41 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/no-loss-backlog-recovery.yaml +42 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/no-output-limit.yaml +36 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/no-request-timeout.yaml +49 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/no-rollback-plan.yaml +39 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/no-runbook.yaml +31 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/no-test-layer.yaml +53 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/output-field-has-default.yaml +43 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/plain-text-ends-session.yaml +39 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/static-defect.yaml +34 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/tests-hit-network.yaml +48 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/tool-exception-uncaught.yaml +36 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/tool-output-unbounded.yaml +34 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/truncation-without-notice.yaml +44 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/unbounded-loop.yaml +47 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/unbounded-parallel-tools.yaml +31 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/unpinned-dependency-upper-bound.yaml +40 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/unvalidated-model-output.yaml +42 -0
- preflight_check_cli-1.0.1/src/preflight_check/knowledge/rules/vulnerable-dependency.yaml +29 -0
- preflight_check_cli-1.0.1/src/preflight_check/runtime/__init__.py +56 -0
- preflight_check_cli-1.0.1/src/preflight_check/runtime/budget.py +133 -0
- preflight_check_cli-1.0.1/src/preflight_check/runtime/cache.py +165 -0
- preflight_check_cli-1.0.1/src/preflight_check/runtime/llm.py +484 -0
- preflight_check_cli-1.0.1/src/preflight_check/runtime/paths.py +66 -0
- preflight_check_cli-1.0.1/src/preflight_check/runtime/trace.py +118 -0
- preflight_check_cli-1.0.1/src/preflight_check/understand/__init__.py +25 -0
- preflight_check_cli-1.0.1/src/preflight_check/understand/claims.py +891 -0
- preflight_check_cli-1.0.1/src/preflight_check/understand/discover.py +209 -0
- preflight_check_cli-1.0.1/src/preflight_check/understand/guard.py +389 -0
- preflight_check_cli-1.0.1/src/preflight_check/understand/mapping.py +193 -0
- preflight_check_cli-1.0.1/src/preflight_check/understand/verify.py +528 -0
- preflight_check_cli-1.0.1/tests/conftest.py +44 -0
- preflight_check_cli-1.0.1/tests/fake_tool.py +86 -0
- preflight_check_cli-1.0.1/tests/ground_truth/fivewhys_labels.yaml +310 -0
- preflight_check_cli-1.0.1/tests/repo_fixtures.py +614 -0
- preflight_check_cli-1.0.1/tests/rule_fixtures.py +545 -0
- preflight_check_cli-1.0.1/tests/sample_knowledge.py +99 -0
- preflight_check_cli-1.0.1/tests/test_acceptance_s1.py +309 -0
- preflight_check_cli-1.0.1/tests/test_acceptance_s3.py +305 -0
- preflight_check_cli-1.0.1/tests/test_adapters.py +437 -0
- preflight_check_cli-1.0.1/tests/test_adapters_smoke.py +150 -0
- preflight_check_cli-1.0.1/tests/test_claims.py +981 -0
- preflight_check_cli-1.0.1/tests/test_cli.py +283 -0
- preflight_check_cli-1.0.1/tests/test_cli_run.py +179 -0
- preflight_check_cli-1.0.1/tests/test_detect_registry.py +214 -0
- preflight_check_cli-1.0.1/tests/test_discipline.py +419 -0
- preflight_check_cli-1.0.1/tests/test_discover.py +248 -0
- preflight_check_cli-1.0.1/tests/test_engine.py +315 -0
- preflight_check_cli-1.0.1/tests/test_field_defaults.py +121 -0
- preflight_check_cli-1.0.1/tests/test_guard.py +237 -0
- preflight_check_cli-1.0.1/tests/test_models.py +288 -0
- preflight_check_cli-1.0.1/tests/test_modularity.py +553 -0
- preflight_check_cli-1.0.1/tests/test_probe.py +371 -0
- preflight_check_cli-1.0.1/tests/test_registry.py +447 -0
- preflight_check_cli-1.0.1/tests/test_release.py +286 -0
- preflight_check_cli-1.0.1/tests/test_repo.py +195 -0
- preflight_check_cli-1.0.1/tests/test_report.py +277 -0
- preflight_check_cli-1.0.1/tests/test_review.py +577 -0
- preflight_check_cli-1.0.1/tests/test_rule_fixtures.py +208 -0
- preflight_check_cli-1.0.1/tests/test_schema_errors.py +307 -0
- preflight_check_cli-1.0.1/tests/test_verify.py +457 -0
- preflight_check_cli-1.0.1/tests/test_workflows.py +228 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# 构建镜像时**不需要**的东西。
|
|
2
|
+
#
|
|
3
|
+
# 为什么值得单独写:不写的话 `.venv/` 和 `.git/` 会一起进构建上下文 ——
|
|
4
|
+
# 前者几百兆、后者带着全部历史,而它们对镜像内容毫无影响。
|
|
5
|
+
# 在慢网络上这一条能省掉几分钟。
|
|
6
|
+
|
|
7
|
+
.git
|
|
8
|
+
.github
|
|
9
|
+
.venv
|
|
10
|
+
venv
|
|
11
|
+
__pycache__
|
|
12
|
+
*.pyc
|
|
13
|
+
.pytest_cache
|
|
14
|
+
.mypy_cache
|
|
15
|
+
.ruff_cache
|
|
16
|
+
tests
|
|
17
|
+
docs
|
|
18
|
+
scripts
|
|
19
|
+
*.egg-info
|
|
20
|
+
dist
|
|
21
|
+
build
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# 换行符统一成 LF。
|
|
2
|
+
#
|
|
3
|
+
# 为什么必须有这个文件:CI 同时在 ubuntu 和 windows 上跑(见 .github/workflows/ci.yml)。
|
|
4
|
+
# 如果仓库里存的是 CRLF、而检出时又按平台转换,两边看到的**字节**就不一样 ——
|
|
5
|
+
# 任何基于文件内容的比较(指纹、快照、golden file)都会一边绿一边红。
|
|
6
|
+
#
|
|
7
|
+
# 这个坑在 fivewhys 上真实发生过:`open("w")` 在 Windows 默认把 \n 转成 CRLF,
|
|
8
|
+
# 于是同一份数据在 Windows 和 Linux 上算出不同的 SHA-256,
|
|
9
|
+
# 「可复现」退化成了「在我机器上可复现」。
|
|
10
|
+
* text=auto eol=lf
|
|
11
|
+
|
|
12
|
+
# 二进制文件不要碰
|
|
13
|
+
*.png binary
|
|
14
|
+
*.jpg binary
|
|
15
|
+
*.gif binary
|
|
16
|
+
*.ico binary
|
|
17
|
+
*.woff binary
|
|
18
|
+
*.woff2 binary
|
|
19
|
+
|
|
20
|
+
# PowerShell 脚本在 Windows 上用 LF 也能正常执行(pwsh 5+/7 都行),
|
|
21
|
+
# 不特殊处理 —— 统一比方便重要。
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
# 每次 push / PR 都跑。这是纪律 D1 的自动化版本:
|
|
4
|
+
# 阶段测试可能忘记跑,CI 不会。
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
pull_request:
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
# ⚠️ publish.yml 用 `uses:` **复用**这个工作流,而被复用的工作流必须声明
|
|
11
|
+
# workflow_call。少这一行的表现是隐蔽的:本地全部测试依然全绿、YAML 也合法,
|
|
12
|
+
# 只有真推 tag 时整个发布运行会在**校验阶段**失败(verify 任务连启动都不会)。
|
|
13
|
+
# 守它的是 tests/test_workflows.py::test_a_reused_workflow_declares_workflow_call
|
|
14
|
+
workflow_call:
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
check:
|
|
18
|
+
runs-on: ${{ matrix.os }}
|
|
19
|
+
strategy:
|
|
20
|
+
fail-fast: false
|
|
21
|
+
matrix:
|
|
22
|
+
# 开发机是 Windows(本地路径 / 换行符 / 编码的坑都在那里),
|
|
23
|
+
# 但 CI 跑 Linux 才能证明代码本身不依赖平台。
|
|
24
|
+
# 两个都跑:只要有一个绿,就不能说是"环境问题"。
|
|
25
|
+
os: [ubuntu-latest, windows-latest]
|
|
26
|
+
# ⚠️ **三个版本都要跑,因为 `pyproject.toml` 的 classifiers 里
|
|
27
|
+
# 声明了三个。**
|
|
28
|
+
#
|
|
29
|
+
# 最初的写法是只跑首尾两个(3.11 + 3.13)—— 那是常见的省成本做法,
|
|
30
|
+
# 而它有一个具体的后果:**3.12 被声明支持,却从没被测试过。**
|
|
31
|
+
# 一条读 classifiers 的测试立刻抓到了这个不一致。
|
|
32
|
+
#
|
|
33
|
+
# 两种修法都成立:要么别声明 3.12,要么测它。
|
|
34
|
+
# 选后者 —— 3.12 是真实在用的版本,而"只在 3.12 上坏"这种事
|
|
35
|
+
# 恰恰是最难在事后解释的。
|
|
36
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
37
|
+
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
|
+
|
|
41
|
+
- uses: actions/setup-python@v5
|
|
42
|
+
with:
|
|
43
|
+
python-version: ${{ matrix.python-version }}
|
|
44
|
+
|
|
45
|
+
- name: 安装
|
|
46
|
+
run: |
|
|
47
|
+
python -m pip install --upgrade pip
|
|
48
|
+
python -m pip install -e ".[dev]"
|
|
49
|
+
|
|
50
|
+
- name: 代码风格
|
|
51
|
+
run: python -m ruff check .
|
|
52
|
+
|
|
53
|
+
- name: 格式检查
|
|
54
|
+
run: python -m ruff format --check .
|
|
55
|
+
|
|
56
|
+
- name: 测试
|
|
57
|
+
run: python -m pytest
|
|
58
|
+
|
|
59
|
+
- name: 类型检查
|
|
60
|
+
run: python -m mypy src
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
name: publish
|
|
2
|
+
|
|
3
|
+
# 打 tag 就发布 —— **不需要任何 token**。
|
|
4
|
+
#
|
|
5
|
+
# ## 为什么用可信发布(Trusted Publishing)而不是 API token
|
|
6
|
+
#
|
|
7
|
+
# 一个存在 GitHub Secrets 里的 PyPI token 是一个**长期凭证**:
|
|
8
|
+
# 它不会过期、泄漏了很难发现、而且它能发布的包不止这一个。
|
|
9
|
+
#
|
|
10
|
+
# 可信发布走的是 OIDC:GitHub 临时签一个短命的身份断言,
|
|
11
|
+
# PyPI 校验"这次上传确实来自这个仓库的这个工作流"。
|
|
12
|
+
# 结果是**没有可以泄漏的秘密**,而且 PyPI 页面上会显示构建来源
|
|
13
|
+
# (attestation),别人能验证这个包是从哪段代码构建出来的。
|
|
14
|
+
#
|
|
15
|
+
# 要启用它,先在 PyPI 上登记一个发布者。项目**还不存在**的时候,是在账号设置里
|
|
16
|
+
# 加一个 "pending publisher"(不是项目设置 —— 项目要等第一次上传才被创建):
|
|
17
|
+
# PyPI Project Name: preflight-check-cli
|
|
18
|
+
# Owner: lddd1026 Repository: preflight
|
|
19
|
+
# Workflow: publish.yml Environment: pypi
|
|
20
|
+
#
|
|
21
|
+
# ⚠️ 项目名写错不是"报个错就算了":PyPI 会先按登记的名字把项目建出来,
|
|
22
|
+
# 再发现上传的元数据名字对不上,于是你会得到一个名字写错的空项目,
|
|
23
|
+
# 得手动删掉再重建登记。而版本号/文件名一旦用过就不能复用。
|
|
24
|
+
#
|
|
25
|
+
# ## 为什么先跑一遍测试
|
|
26
|
+
#
|
|
27
|
+
# 发布是不可逆的:PyPI 上的一个版本号不能被复用,删掉也没用
|
|
28
|
+
# (别人已经装了)。所以这个工作流**先跑 check,绿了才发布**。
|
|
29
|
+
on:
|
|
30
|
+
push:
|
|
31
|
+
tags: ["v*"]
|
|
32
|
+
workflow_dispatch:
|
|
33
|
+
|
|
34
|
+
jobs:
|
|
35
|
+
# ⚠️ 复用 ci.yml 的那套检查,而不是重写一遍 ——
|
|
36
|
+
# 两份定义会漂移,而漂移之后"发布前跑了什么"就成了一个问题。
|
|
37
|
+
verify:
|
|
38
|
+
uses: ./.github/workflows/ci.yml
|
|
39
|
+
|
|
40
|
+
build:
|
|
41
|
+
needs: verify
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v4
|
|
45
|
+
- uses: actions/setup-python@v5
|
|
46
|
+
with:
|
|
47
|
+
python-version: "3.13"
|
|
48
|
+
|
|
49
|
+
- name: 构建 sdist 和 wheel
|
|
50
|
+
run: |
|
|
51
|
+
python -m pip install --upgrade build
|
|
52
|
+
python -m build
|
|
53
|
+
|
|
54
|
+
# 这一步**必须**在发布前跑:twine check 会告诉你
|
|
55
|
+
# README 在 PyPI 上渲染会不会报错、元数据是不是合法。
|
|
56
|
+
# 而这两件事在上传之后才发现就晚了 —— 版本号已经用掉了。
|
|
57
|
+
- name: 校验元数据和 README 渲染
|
|
58
|
+
run: |
|
|
59
|
+
python -m pip install --upgrade twine
|
|
60
|
+
python -m twine check dist/*
|
|
61
|
+
|
|
62
|
+
# 让"包里到底有什么"在 CI 日志里可见 —— 出问题时不用重新构建
|
|
63
|
+
- name: 列出 wheel 内容
|
|
64
|
+
run: python -m zipfile --list dist/*.whl | head -40
|
|
65
|
+
|
|
66
|
+
- uses: actions/upload-artifact@v4
|
|
67
|
+
with:
|
|
68
|
+
name: dist
|
|
69
|
+
path: dist/
|
|
70
|
+
|
|
71
|
+
publish:
|
|
72
|
+
needs: build
|
|
73
|
+
runs-on: ubuntu-latest
|
|
74
|
+
# ⚠️ environment 是**人在回路**的那一步:在 GitHub 上把它配成需要
|
|
75
|
+
# 人工批准,于是一次误打的 tag 也不会直接推到 PyPI。
|
|
76
|
+
environment: pypi
|
|
77
|
+
permissions:
|
|
78
|
+
# 这两项是可信发布的要求:id-token 用来签 OIDC 断言,
|
|
79
|
+
# attestations 让 PyPI 能把构建来源写进 provenance。
|
|
80
|
+
id-token: write
|
|
81
|
+
attestations: write
|
|
82
|
+
contents: read
|
|
83
|
+
steps:
|
|
84
|
+
- uses: actions/download-artifact@v4
|
|
85
|
+
with:
|
|
86
|
+
name: dist
|
|
87
|
+
path: dist/
|
|
88
|
+
|
|
89
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# ---- Python ----
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
build/
|
|
6
|
+
dist/
|
|
7
|
+
.venv/
|
|
8
|
+
|
|
9
|
+
# ---- 工具缓存(这些会落在项目目录里)----
|
|
10
|
+
.pytest_cache/
|
|
11
|
+
.mypy_cache/
|
|
12
|
+
.ruff_cache/
|
|
13
|
+
.coverage
|
|
14
|
+
htmlcov/
|
|
15
|
+
|
|
16
|
+
# ---- preflight 自己的运行时产物 ----
|
|
17
|
+
# 检查结果落盘的位置。它是运行时数据,不是源码。
|
|
18
|
+
.preflight/
|
|
19
|
+
|
|
20
|
+
# ---- 环境与密钥 ----
|
|
21
|
+
.env
|
|
22
|
+
*.env
|
|
23
|
+
!.env.example
|
|
24
|
+
|
|
25
|
+
# ---- 编辑器 / 系统 ----
|
|
26
|
+
.vscode/
|
|
27
|
+
.idea/
|
|
28
|
+
Thumbs.db
|
|
29
|
+
desktop.ini
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# preflight 的干净容器 —— **S8 的"干净环境测试"就是靠它做的**。
|
|
2
|
+
#
|
|
3
|
+
# ## 这个 Dockerfile 同时也是 CI 的替身
|
|
4
|
+
#
|
|
5
|
+
# 项目从 S0 起就配了 Ubuntu + Windows 双平台的 CI,但它**一次都没跑过**
|
|
6
|
+
# (没有 remote)。而"只在 Windows 上验证过"这件事的风险是具体的:
|
|
7
|
+
# 路径分隔符、换行符、编码、文件权限 —— 每一个都可能在 Linux 上炸。
|
|
8
|
+
#
|
|
9
|
+
# 所以这个容器不是"顺便加的",它是**唯一真正验证过 Linux 的手段**。
|
|
10
|
+
# 跑一次 `docker build && docker run` 比"等 CI 配好"快得多。
|
|
11
|
+
#
|
|
12
|
+
# ## 为什么基础镜像选 slim 而不是 alpine
|
|
13
|
+
#
|
|
14
|
+
# alpine 用 musl libc,而 Python 生态里不少 wheel 只有 manylinux 版本 ——
|
|
15
|
+
# 装的时候会退化成源码编译,慢且容易缺构建依赖。
|
|
16
|
+
# 这个镜像的目的不是"最小",是"干净"。
|
|
17
|
+
|
|
18
|
+
FROM python:3.13-slim
|
|
19
|
+
|
|
20
|
+
# 不让 Python 写 .pyc、不让它缓冲输出 —— 容器里的标准做法。
|
|
21
|
+
# 缓冲会让日志在崩溃时丢掉最后几行,而那几行常常正是原因。
|
|
22
|
+
ENV PYTHONDONTWRITEBYTECODE=1 \
|
|
23
|
+
PYTHONUNBUFFERED=1
|
|
24
|
+
|
|
25
|
+
WORKDIR /app
|
|
26
|
+
|
|
27
|
+
# 先只拷元数据和源码 —— 让 pip 的层缓存有意义
|
|
28
|
+
#
|
|
29
|
+
# ⚠️ **`LICENSE` 不是可选的。** `pyproject.toml` 里写了
|
|
30
|
+
# `license = { file = "LICENSE" }`,构建元数据时会去读那个文件 ——
|
|
31
|
+
# 没拷进来就直接
|
|
32
|
+
#
|
|
33
|
+
# OSError: License file does not exist: LICENSE
|
|
34
|
+
#
|
|
35
|
+
# 而本地构建永远发现不了(那个文件就在旁边)。
|
|
36
|
+
# 又一次是"干净环境"才暴露出来的问题 —— 这一轮里第三次了。
|
|
37
|
+
# 现在有一条测试守着这份清单(`test_the_dockerfile_copies_everything_the_build_needs`)。
|
|
38
|
+
COPY pyproject.toml README.md LICENSE ./
|
|
39
|
+
COPY src ./src
|
|
40
|
+
|
|
41
|
+
# ⚠️ **不装 `[tools]` / `[llm]`**。
|
|
42
|
+
#
|
|
43
|
+
# 两个理由:
|
|
44
|
+
# 1. 镜像要能**离线跑出 demo**,装 litellm 是几十兆的浪费
|
|
45
|
+
# 2. 那两组本来就是可选的 —— 不装时对应规则明确报"跳过",
|
|
46
|
+
# 这正是适配器层的设计。把它装上去反而演示不了这个行为
|
|
47
|
+
# ⚠️ 显式的重试参数不是可选项。
|
|
48
|
+
#
|
|
49
|
+
# 实测:默认设置(15 秒超时、5 次重试)在这台机器上拉 `rich` 时反复超时 ——
|
|
50
|
+
# 而 pip 的默认重试是**指数退避**的,5 次之后直接失败。
|
|
51
|
+
#
|
|
52
|
+
# 60 秒超时 + 10 次重试把这一类抖动吸收掉。它不掩盖真正的问题
|
|
53
|
+
# (包不存在、版本冲突),只是不让"网络抖一下"变成"镜像构建不了"。
|
|
54
|
+
RUN pip install --no-cache-dir --retries 10 --timeout 60 .
|
|
55
|
+
|
|
56
|
+
# 随包发布的 demo 素材在 src/preflight/demo/ 里,`preflight-check demo` 用它 ——
|
|
57
|
+
# **不配 API Key、不联网**就能看到 broken-agent vs clean-agent 的对比。
|
|
58
|
+
CMD ["preflight-check", "demo"]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 刘达
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|