Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: tests

# The suite is ~485 offline cases with no network and no paid LLM calls, so it can
# run on every push. Until this existed it ran only when someone remembered to type
# `pytest` (doc/CODE_TOUR.md documents it as a manual step) — tests that nothing runs
# protect nothing.
#
# NOTE: this workflow is a SIGNAL, not a merge gate. Making it blocking needs a branch
# protection rule / ruleset naming the `suite` job as a required status check, which is
# a repository setting and cannot be done from a commit.

on:
push:
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
suite:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.12"

# pytest lives in the `dev` extra; `mcp` is needed for the MCP server tests.
- name: Install
run: pip install -e ".[dev,mcp]"

- name: Unit tests
run: pytest -q

- name: CLI smoke
run: infermatrix-copilot --help

# doctor exits 1 when credentials are absent, which is the expected state in CI.
# The claim under test is "it runs and emits valid JSON", not "it is configured",
# so tolerate 0/1 explicitly rather than piping into a parser — steps run under
# `pipefail`, where the expected exit 1 would fail the step.
- name: doctor emits valid JSON
run: |
infermatrix-copilot doctor --json > doctor.json || [ $? -le 1 ]
python -c "import json; json.load(open('doctor.json'))"

# test_packaged_runtime.py asserts on pyproject's TEXT, so nothing else proves the
# force-include data trees actually ship. Build the artifact and import it from a
# clean venv, where a missing tree cannot be masked by the source checkout.
- name: Wheel ships its runtime data
run: |
pip install build
python -m build --wheel
python -m venv /tmp/clean
/tmp/clean/bin/pip install --quiet dist/*.whl
cd /tmp # import the INSTALLED package, never the source checkout
/tmp/clean/bin/python - <<'PY'
import sys
from infermatrix_copilot.config import _resource_dir, _RESOURCE_MARKERS
# resolve through the production probe and require its marker to exist:
# a present-but-empty directory would satisfy a bare is_dir() check
bad = []
for name, marker in _RESOURCE_MARKERS.items():
d = _resource_dir(name)
if not d.is_dir():
bad.append(f"{name}: {d} missing")
elif not any(m.is_file() for m in d.glob(marker)):
bad.append(f"{name}: {d} has no {marker}")
if bad:
sys.exit("wheel runtime data broken: " + "; ".join(bad))
print("packaged runtime data resolves via _resource_dir:",
", ".join(_RESOURCE_MARKERS))
PY

# Written, tested, and until now invoked only from prose (AGENTS.md, DEVELOPMENT.md).
- name: Knowledge linters
run: |
python knowledge/tools/check_knowledge_tree.py
python knowledge/tools/check_wiki_lint.py
pytest -q knowledge/tools/test_check_knowledge_tree.py \
knowledge/tools/test_check_review_report.py
12 changes: 12 additions & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ python -m build --wheel
确认 wheel 中包含 `knowledge/`、`_runtime/playbooks/`、`_runtime/adapters/` 和
`_runtime/skills/`,不能只验证源码 checkout。

## CI

`.github/workflows/test.yml` 在每次 push 与 PR 上跑上面这些检查:整套 pytest、
`--help` / `doctor` 冒烟、把 wheel 装进干净 venv 验证四棵数据树确实随包发布
(`test_packaged_runtime.py` 只断言 pyproject 的**文本**,证明不了这件事),
以及两个知识树 linter。

**它目前只是信号,不是合并门禁。** 要让它真正挡住合并,需要在
Settings → Branches(或 repository ruleset)里把 `suite` 这个 job 设为
required status check —— 这是仓库设置,任何一次提交都做不到。<!-- TODO(maintainer) -->


## 三条边界

- Direct 使用宿主 Agent 的模型,不在 MCP 内再次调用模型。
Expand Down
Loading
Loading