Skip to content

hamanpaul/testpilot-core

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

73 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TestPilot

English繁體中文


TestPilot Core architecture overview

Install

This README is the canonical install reference. For online install (managed venv, newest API-compatible core/plugins; serialwrap pinned), see Quick Start. For offline environments or update procedures, see Managed Install and Update. After any install or update, run testpilot --verify-install to confirm health.

Usage

testpilot is the host runtime; test capabilities are provided by plugins. Use testpilot list-plugins to see installed plugins and testpilot run <plugin> to drive them.

Version

The canonical project version is VERSION; release tags use vX.Y.Z. testpilot --version also inventories every installed testpilot.plugins entry point so operators can see the effective core/plugin/API combination:

TestPilot <core-version> (<source-ref>)
  plugin wifi_llapi <plugin-version> (api <api-version>)

English

Plugin-based test automation framework for embedded device verification (prplOS / OpenWrt).

This repository is TestPilot core: the deterministic verdict kernel, the plugin SDK (testpilot.api), the CLI host, transports, schema, and reporting. It ships the plugin scaffold under plugins/_template/ but no concrete test plugins. Real plugins (for example wifi_llapi and brcm_fw_upgrade) live in their own repositories and register themselves through the testpilot.plugins entry-point group.

Overview

TestPilot is a plugin-based test automation framework for prplOS / OpenWrt embedded devices. The architecture splits into two planes:

  • Deterministic verdict kernel — test execution, evidence collection, pass/fail verdicts, and report projection.
  • Copilot SDK control plane — per-case session foundation, lifecycle hooks, advisory audit, tiered environment recovery, and extension surfaces such as custom agents / skills / selective MCP.

Core principle: the Copilot SDK handles the control plane; it does NOT decide the final verdict.

Current landed control-plane subset today:

  • per-case runner selection with selection_trace
  • best-effort per-case Copilot session foundation
  • lifecycle hook dispatch (pre_case, post_case, pre_step, post_step, on_failure, on_retry)
  • advisory collection plus tier-1 deterministic remediation and opt-in tier-2 one-shot planning between retry attempts

Tier-2 is reached only after the configured consecutive tier-1 failures. Core builds a bounded, tool-denied one-shot prompt from the plugin's advertised environment capabilities; the plugin executes the validated plan, then core forces deterministic verify_env. The agent never receives verdict authority or permission to rewrite case semantics. Every intervention is marked agent_recovered and retained in bounded/redacted case and run audit artifacts; the marker means the agent intervened, not that the verification gate passed. See Tier-2 Environment Recovery Design.

Custom agents / skills / MCP remain extension surfaces in the current codebase rather than default hot-path runtime wiring.

Prerequisites

  • Python 3.11+
  • git
  • uv — Python package manager, preferred by the installer
  • serialwrap — UART serial multiplexer for DUT / STA communication; managed installs install/update it automatically

Developer checkouts that manage serialwrap manually can still set the binary path via environment variable:

export SERIALWRAP_BIN=/path/to/serialwrap

Or add to configs/testbed.yaml:

testbed:
  serialwrap_binary: /path/to/serialwrap

Resolution order: SERIALWRAP_BIN env var → testbed.yaml config → error exit.

Quick Start

Online one-click install (requires a fine-grained read-only PAT with contents: read for hamanpaul/testpilot-core and all plugin repos):

TESTPILOT_INSTALL_TOKEN=<fine-grained read-only PAT> bash scripts/install.sh
testpilot --verify-install
testpilot list-plugins

Install only a subset of plugins with --plugins:

TESTPILOT_INSTALL_TOKEN=<PAT> bash scripts/install.sh --plugins wifi_llapi

Once installed, list and run plugins:

testpilot list-plugins
testpilot list-cases <plugin>
testpilot run <plugin>

When a plugin context is resolved, the CLI auto-stages plugins/<plugin>/testbed.yaml.example into configs/testbed.yaml, so each run starts from that plugin's shipped testbed shape with no leakage between plugins. Edit configs/testbed.yaml to match your lab — note that switching to a different plugin will overwrite it.

Managed Install and Update

The supported QC/TEST install uses a managed venv (no git checkout). Online install resolves the newest API-compatible core and plugin releases; serialwrap stays pinned in install-manifest.yaml. An offline bundle is an exact, SHA256-verified snapshot. Pin any component explicitly with --plugins <name>@<version> (or by adding a version: back to the manifest):

~/.local/share/testpilot/.venv   # managed runtime virtualenv
~/.local/bin/testpilot           # wrapper, no activation required
~/.agents/skills/testpilot-normal-test

Online install — downloads wheels via gh release download using a fine-grained PAT:

TESTPILOT_INSTALL_TOKEN=<fine-grained read-only PAT> bash scripts/install.sh

Offline install — build a bundle on a networked Linux box with scripts/build-bundle.sh, then transfer and install on the air-gapped machine:

# Build on a networked machine:
bash scripts/build-bundle.sh

# Install on the offline machine (verifies SHA256SUMS, installs with --no-index):
bash scripts/install.sh --offline testpilot-bundle-<ver>-linux-<arch>-cp<XY>.tar.gz

Update and verify:

testpilot --update            # reinstalls newest-compatible core/plugins (serialwrap pinned), reconciles plugins
testpilot --verify-install    # report install health

--update snapshots the environment first; if the post-update verify fails it rolls back offline only (pip install --no-index --find-links against the local wheel cache the installer preserves under ${TESTPILOT_HOME:-~/.local/share/testpilot}/.wheel-cache) — it never reaches a public index. If the cached wheels are insufficient, rollback fails loudly and asks you to reinstall from a known-good bundle via install.sh --offline.

CLI Entry Points

Use the installed testpilot command for normal operation. Developer checkouts can still use python -m testpilot.cli when debugging the repository.

Plugin-owned CLI commands are registered from installed plugin packages when testpilot.cli is imported. --root <path> selects the runtime project root for cases/configs/reports; it does not dynamically replace the registered plugin CLI surface with commands from <path>/plugins.

The core host commands are:

testpilot --version
testpilot list-plugins
testpilot list-cases <plugin>
testpilot run <plugin>

Usage: testpilot [OPTIONS] COMMAND [ARGS]...

TestPilot — plugin-based test automation for embedded devices.

Options: --version Show version and exit. -v, --verbose Enable debug logging. --root DIRECTORY Project root directory. --update REF Reinstall and reconcile the managed wheel install from its pinned manifest, then exit. REF is accepted but cross- version update is not yet implemented; the currently- pinned set is reinstalled. --verify-install Report managed install health and exit. --help Show this message and exit.

Commands: install-doctor Check manifest plugin API-compat against installed core... list-cases List test cases for a plugin. list-plugins List available test plugins. run Run tests for a plugin.

Usage: testpilot [OPTIONS] COMMAND [ARGS]...

TestPilot — plugin-based test automation for embedded devices.

Options: --version Show version and exit. -v, --verbose Enable debug logging. --root DIRECTORY Project root directory. --update REF Reinstall and reconcile the managed wheel install from its pinned manifest, then exit. REF is accepted but cross- version update is not yet implemented; the currently- pinned set is reinstalled. --verify-install Report managed install health and exit. --help Show this message and exit.

Commands: install-doctor Check manifest plugin API-compat against installed core... list-cases List test cases for a plugin. list-plugins List available test plugins. run Run tests for a plugin.

Repository skills for agent-assisted workflows live under skills/.

Azure OpenAI (BYOK)

TestPilot core automatically uses Azure when all required values are present. Without an API key it runs in deterministic/no-agent mode; a key without an endpoint or deployment produces a non-blocking misconfiguration notice. If COPILOT_PROVIDER_TYPE is set to a non-azure value, core also treats the runtime as misconfigured and emits the same redacted notice.

export COPILOT_PROVIDER_BASE_URL=https://your-resource.openai.azure.com
export COPILOT_PROVIDER_API_KEY='<set in shell profile or secret store>'
export COPILOT_MODEL=your-deployment-name
export COPILOT_PROVIDER_AZURE_API_VERSION=2024-10-21
testpilot run <plugin_name>

COPILOT_PROVIDER_TYPE is not an enable switch; core constructs only the Azure provider and rejects non-azure values as misconfiguration. Azure deployment selection is independent of plugin runner labels. Per-case planning is advisory, tier-2 recovery requires plugin opt-in, and deterministic remediation remains plugin-owned. Core-owned usage and observational benefit metrics are written under artifact_dir/agent_usage; shared run-analysis tokens are not allocated to cases. Custom/skeleton runners report unsupported_execution_path and make no core model calls.

Writing a Plugin

Copy the SDK scaffold and register it from your plugin package:

cp -r plugins/_template plugins/my_plugin
[project.entry-points."testpilot.plugins"]
my_plugin = "plugins.my_plugin.plugin:Plugin"
uv pip install -e .
testpilot list-plugins

Implement the PluginBase contract (declare api_version, name, discover_cases(), execute_step(), evaluate(); override optional hooks such as setup_env(), verify_env(), teardown(), create_reporter(), create_runner(), and register_cli() as needed). Plugins import the public SDK surface from testpilot.api; they must not reach into testpilot.core, testpilot.schema, testpilot.reporting, testpilot.transport, or testpilot.runtime internals. See plugins/_template/README.md for the full contract and optional hook table.

For a complete, runnable reference (installable + discoverable via testpilot.plugins), see examples/sample_echo/ and its README.

Project Structure

src/testpilot/
  api/        # public plugin SDK surface (testpilot.api)
  core/       # orchestrator, plugin_base, plugin_loader, testbed_config
  reporting/  # reporter and report helpers
  transport/  # transport abstractions
  schema/     # YAML case schema validation
  runtime/    # run backend
plugins/
  _template/  # plugin SDK scaffold (not discoverable on its own)
configs/      # operator-local effective testbed.yaml (auto-staged by CLI; git-ignored)
docs/         # plan, todos, phase docs
scripts/      # utility scripts (install, policy_cli_help, gen_cases)
skills/       # repository agent skills
tests/        # core test suite

Versioning and Release

The canonical project version lives in VERSION; pyproject.toml and src/testpilot/__init__.py mirror it and must stay identical. Release tags use Semantic Versioning vX.Y.Z. User-facing pull requests should update CHANGELOG.md under Unreleased, or explicitly record why no changelog entry is needed. testpilot --version prints this core version followed by every installed plugin distribution version and declared SDK API version; a broken plugin metadata record is shown as unknown without hiding the remaining inventory.


繁體中文

針對嵌入式裝置驗證(prplOS / OpenWrt)的 plugin 化測試自動化框架。

本 repo 是 TestPilot core:deterministic verdict kernel、plugin SDK (testpilot.api)、CLI host、transport、schema 與 reporting。它內含 plugins/_template/ plugin 骨架,但不含任何具體測試 plugin。真正的 plugin (例如 wifi_llapibrcm_fw_upgrade)各自存在於獨立 repo,透過 testpilot.plugins entry-point group 自我註冊。

概觀

TestPilot 是針對 prplOS / OpenWrt 嵌入式裝置的 plugin 化測試自動化框架,架構分為兩個平面:

  • Deterministic verdict kernel — 測試執行、證據蒐集、pass/fail 判定與報表投影。
  • Copilot SDK control plane — per-case session foundation、lifecycle hooks、advisory audit、分層環境修復,以及 custom agents / skills / 選擇性 MCP 等擴充面。

核心原則:Copilot SDK 負責 control plane;它不決定最終 verdict。

tier-1 先執行 plugin 的 deterministic allowlist 修復;只有達到設定的連續失敗門檻, 才會在 retry 間隙 opt-in 升級 tier-2。core 以 plugin 宣告的 environment capability catalog 建立 bounded、tool-denied one-shot prompt,plugin 執行通過 schema/budget 的 plan 後,core 一律強制重跑 deterministic verify_env。agent 不具 verdict 權限,也 不能改 case semantics。任何介入都以 agent_recovered 標記並寫入已去敏、有上限的 case/run audit;該標記只代表 agent 曾介入,不代表 verify gate 已通過。詳見 Tier-2 Environment Recovery Design

前置需求

  • Python 3.11+
  • git
  • uv — 安裝器優先採用的 Python 套件管理器
  • serialwrap — DUT / STA 通訊用的 UART serial multiplexer;managed install 會自動安裝/更新

手動管理 serialwrap 的開發者 checkout 可用環境變數指定路徑:

export SERIALWRAP_BIN=/path/to/serialwrap

解析順序:SERIALWRAP_BIN 環境變數 → testbed.yaml 設定 → 失敗結束。

快速開始

線上一鍵安裝(需要 fine-grained read-only PAT,具備 hamanpaul/testpilot-core 及所有 plugin repo 的 contents: read 權限):

TESTPILOT_INSTALL_TOKEN=<fine-grained read-only PAT> bash scripts/install.sh
testpilot --verify-install
testpilot list-plugins

透過 --plugins 只安裝部分 plugin:

TESTPILOT_INSTALL_TOKEN=<PAT> bash scripts/install.sh --plugins wifi_llapi

安裝後,列出並執行 plugin:

testpilot list-plugins
testpilot list-cases <plugin>
testpilot run <plugin>

Managed Install 與 Update

支援的 QC/TEST 安裝採用 managed venv 加 pinned wheels(不再使用 git checkout):

~/.local/share/testpilot/.venv   # managed runtime virtualenv
~/.local/bin/testpilot           # wrapper,免 activate
~/.agents/skills/testpilot-normal-test

線上安裝

TESTPILOT_INSTALL_TOKEN=<fine-grained read-only PAT> bash scripts/install.sh

離線安裝(先在有網路的 Linux 機器以 scripts/build-bundle.sh 建置 bundle, 再傳至目標機器):

# 有網路機器上建置:
bash scripts/build-bundle.sh

# 離線機器上安裝(驗證 SHA256SUMS,以 --no-index 安裝):
bash scripts/install.sh --offline testpilot-bundle-<ver>-linux-<arch>-cp<XY>.tar.gz

更新與驗證:

testpilot --update            # 重解析 manifest、重裝 pinned wheels、同步 plugin
testpilot --verify-install    # 回報安裝狀態

--update 會先快照環境;若更新後 verify 失敗,rollback 只走離線 (以 pip install --no-index --find-links 對安裝器保存在 ${TESTPILOT_HOME:-~/.local/share/testpilot}/.wheel-cache 的本地 wheel cache 重裝), 絕不連到 public index。若 cache 內 wheel 不足,rollback 會明確失敗並提示改用 install.sh --offline 從已知良好的 bundle 重裝。

CLI 進入點

正常操作使用已安裝的 testpilot 指令;開發者 checkout 在除錯 repo 時仍可使用 python -m testpilot.cli。Plugin 專屬的 CLI 指令是在 import testpilot.cli 時由已安裝的 plugin 套件註冊。--root <path> 只選擇 runtime project root (cases/configs/reports),不會用 <path>/plugins 的指令動態替換已註冊的 plugin CLI 介面。

核心 host 指令:

testpilot --version
testpilot list-plugins
testpilot list-cases <plugin>
testpilot run <plugin>

Azure OpenAI(BYOK)

當 Azure endpoint、API key 與 deployment 都存在時,TestPilot core 自動啟用 Azure;沒有 key 時使用 deterministic/no-agent mode,缺少其他欄位只會產生 非阻斷的 misconfigured notice;若 COPILOT_PROVIDER_TYPE 被設成非 azure 值,也會被視為 misconfigured。COPILOT_PROVIDER_TYPE 不作為啟用開關,core 只建立 Azure provider。

export COPILOT_PROVIDER_BASE_URL=https://your-resource.openai.azure.com
export COPILOT_PROVIDER_API_KEY='<set in shell profile or secret store>'
export COPILOT_MODEL=your-deployment-name
export COPILOT_PROVIDER_AZURE_API_VERSION=2024-10-21
testpilot run <plugin_name>

每案 planning 僅供 advisory;tier-2 需 plugin opt-in,deterministic remediation 仍由 plugin 負責。core 報表位於 artifact_dir/agent_usage,共享 run-end analysis token 不分攤到個案;custom/skeleton path 回報 unsupported_execution_path 且不呼叫 core model。效益指標為 observational, 不宣稱因果 uplift/regression。

撰寫 Plugin

複製 SDK 骨架並從你的 plugin 套件註冊:

cp -r plugins/_template plugins/my_plugin
[project.entry-points."testpilot.plugins"]
my_plugin = "plugins.my_plugin.plugin:Plugin"
uv pip install -e .
testpilot list-plugins

實作 PluginBase 契約(宣告 api_versionnamediscover_cases()execute_step()evaluate();視需要覆寫 setup_env()verify_env()teardown()create_reporter()create_runner()register_cli() 等選用 hook)。Plugin 從 testpilot.api 匯入公開 SDK 介面,不得直接 reach 進 testpilot.core / schema / reporting / transport / runtime 內部。完整 契約與選用 hook 對照表見 plugins/_template/README.md

版本與發布

canonical 版本位於 VERSIONpyproject.tomlsrc/testpilot/__init__.py 為鏡像,必須一致。release tag 採 Semantic Versioning vX.Y.Z。對外 PR 應更新 CHANGELOG.mdUnreleased,或明確記錄 為何不需 changelog entry。testpilot --version 會在 core 版本後列出所有已安裝 plugin 的 distribution version 與宣告的 SDK API version;單一 plugin metadata 損壞時以 unknown 顯示,不會阻斷其餘 inventory。

About

TestPilot core (plugin SDK + runtime; split from hamanpaul/testpilot)

Resources

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages