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
35 changes: 0 additions & 35 deletions .github/workflows/hyper-v-control.yml

This file was deleted.

65 changes: 65 additions & 0 deletions .github/workflows/marketplace.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Marketplace CI
on:
pull_request:
branches: [main]
workflow_dispatch:
concurrency:
group: marketplace-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
catalog:
runs-on: ubuntu-latest
outputs:
windows: ${{ steps.plan.outputs.windows }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Check marketplace contracts
run: python scripts/check-marketplace.py
- name: Validate complete plugin packaging
run: python scripts/test-plugin-packaging.py
- name: Select component validation
id: plan
run: python scripts/ci-plan.py
windows:
needs: catalog
if: needs.catalog.outputs.windows == 'true'
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.401'
cache: true
cache-dependency-path: src/HyperVControl/packages.lock.json
- name: Build self-contained EXE and plugin
shell: pwsh
run: ./scripts/build-hyperv-control.ps1
- name: Verify pinned runtime reproducibility
shell: pwsh
run: git diff --exit-code -- plugins/hyper-v-control/runtime.json
- name: Unit and stdio protocol validation
shell: pwsh
run: |
dotnet run --project tests/HyperVControl.Tests -c Release -- unit $PWD
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
dotnet run --project tests/HyperVControl.Tests -c Release -- smoke $PWD
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
./scripts/test-release-isolation.ps1
exit $LASTEXITCODE
- uses: actions/upload-artifact@v4
if: github.event_name == 'workflow_dispatch'
with:
name: hyper-v-control-win-x64
if-no-files-found: error
path: |
build/hyperv-control/release/hyper-v-control-win-x64-v*.exe
build/hyperv-control/release/hyper-v-control-plugin-v*-win-x64.zip
build/hyperv-control/release/hyper-v-control-v*-release.json
build/hyperv-control/release/hyper-v-control-v*-SHA256SUMS.txt
54 changes: 54 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Maintaining and extending the marketplace

Each plugin is an independent product. Keep its installed files self-contained, its dependencies explicit, and its releases separate. Shared code belongs at the repository level only when multiple plugins actually use it.

## Repository map

| Location | Responsibility |
| --- | --- |
| `.agents/plugins/marketplace.json` | Discovery catalog: plugin IDs, locations, and categories |
| `plugins/<id>/` | Installable package: manifest, skill, user documentation, helpers, and licenses |
| `src/<Product>/` | Native application or MCP implementation; currently Hyper-V Control |
| `tests/<Product>.Tests/` | Native protocol and behavior validation |
| `scripts/` | Maintainer builds, packaging, and repository checks; never an installed plugin dependency |
| `docs/` | Build/release procedures and recorded validation evidence |
| `sources/`, `patches/`, `bundle.lock.json` | Pinned Rizin upstream sources, compatibility patches, and build dependencies |
| `build/` | Ignored generated files, downloads, binaries, and local experiment output |

The older `build-bundle`, `package-bundle`, and `verify-bundle` scripts belong to the Rizin runtime. Hyper-V uses `build-hyperv-control.ps1`. New component-specific tooling should use explicit names or its own subdirectory; do not add unrelated behavior to the Rizin builders.

Within Hyper-V Control, `HyperVTools*` exposes the MCP contract, `Services/` owns host/guest operations and resource lifetimes, and `Extracted/` contains adapted RaivenX functionality. Keep protocol handling out of the extracted layer. Changes to VM state, credentials, elevation, or debugger lifetime need behavior tests at their corresponding boundary.

## Sources of truth

- Edit `plugins/<id>/plugin.json` for plugin identity, version, and interface metadata. Run `python scripts/check-marketplace.py --sync` to generate `.codex-plugin/plugin.json`; do not maintain the compatibility copy independently.
- Compiled downloads use the plugin's `runtime.json` for the exact artifact and hash. Rizin's independently versioned runtime and build inputs are in `bundle.lock.json`. Keep dependency versions in metadata and lockfiles.
- Hyper-V's project, CLI, and protocol versions must match its plugin manifest. The repository checker rejects partial updates; the build verifies the executable version and runtime hash.
- README files explain purpose, setup, and usage. Keep current version numbers, release dates, and changelogs out of them. The [download catalog](docs/releases.md#release-index) is the maintained entrypoint for current releases.
- Skills explain how an agent should choose tools and interpret results. Put detailed task procedures in their `references/` directory and scripts needed at runtime inside the plugin.
- Record experiments in validation reports. Imported Frida material under `references/legacy/` and `docs/migration/` is historical evidence, not the maintained entrypoint; preserve its provenance and licenses.

Links inside distributed plugin documentation must resolve inside that plugin or use an absolute repository/web URL. A relative link to `../../docs/` works in a checkout but breaks when the plugin ZIP is extracted.

## Add a plugin

1. Choose a stable lowercase ID and create `plugins/<id>/` with `plugin.json`, `README.md`, `LICENSE`, and `skills/<skill-id>/SKILL.md`. Keep plugin content in English. Add only the references, assets, and helpers that the installed plugin needs.
2. Add a local catalog entry pointing to `./plugins/<id>`, then run the manifest sync/check command. New catalog plugins are discovered by the checker automatically.
3. If it needs a native executable, put its source and tests under `src/` and `tests/`. Give it a dedicated builder, verified installer, and versioned installation directory. A source-only skill/CLI plugin does not need an MCP server or binary release.
4. Add component-specific validation to the existing PR workflow. Keep expensive job selection in `scripts/ci-plan.py`; extend it for the component's actual inputs. Do not introduce a second push or tag workflow for the same checks.
5. Test an extracted package in a fresh directory. It must work without the repository checkout, another plugin, or a developer's absolute paths. Follow the [release guide](docs/releases.md) for publication and asset naming.

## Check a change

```powershell
python scripts/check-marketplace.py
python scripts/test-plugin-packaging.py
```

These fast checks validate the catalog, compatibility manifests, bundled skill paths, runtime pins, README policy, entrypoint links, and Rizin plugin packaging. They do not install plugin dependencies or operate a VM.

The single PR workflow runs these checks for all changes. It runs Windows build/protocol/installer checks only when their inputs change. Pure documentation changes avoid native builds, newer commits cancel obsolete runs, and merging or tagging does not repeat CI. Use a manual workflow run when downloadable build artifacts are needed.

For behavior changes, also run the affected component's documented tests: [Hyper-V Control](plugins/hyper-v-control/README.md#development-and-validation), [Rizin](docs/build.md), [Frida](scripts/frida-use-experiments/README.md), or [Capstone](plugins/capstone-binary-patching/README.md#validation-and-boundaries). Live tests must have a defined target, restoration plan, and recorded limits; CI never discovers and operates on a developer's VMs automatically.

Before removing a release, check both runtime installers and build lockfiles for references. Preserve active dependencies first. Published primary EXEs and ZIPs are immutable; publish changed bytes under a new version. Documentation-only edits do not require rebuilding an unchanged runtime.
Loading
Loading