Thank you for your interest in contributing! Please open an issue or pull request via the GitHub repository.
The plugin is bash-script-based. Hooks live in scripts/; tests in tests/.
./tests/test-hooks.sh # mock-MCP-server tests, no AxonFlow needed
./tests/test-hooks.sh --live # against live AxonFlow on localhost:8080- Keep PRs focused — one feature or fix per PR.
- Update
CHANGELOG.mdunder[Unreleased]for user-visible changes. - Ensure
tests/test-hooks.shis green and the wire-shape contract gate passes. - New AxonFlow-wire-field reads: extend the relevant script's
jqaccesses on$TOOL_RESULT/$SCAN_RESULT. The wire-shape gate's refresh script auto-discovers them via the documented variable patterns; rerunpython3 scripts/wire-shape/refresh.py <specs_dir>and commit the regenerated baseline.
The wire-shape contract gate uses a baseline file (tests/fixtures/wire-shape-baseline.json) to grandfather pre-existing drift findings — the gate fails on any new drift but tolerates the listed entries. Baselines exist to land the gate without a giant cleanup PR; they are not intended to be permanent.
When your PR touches a baselined area, do one of:
- Burn it down. Resolve the drift in this PR (align script with spec, file a platform-side spec PR, or mark as Cat C), regenerate the baseline, and note "burndown:
<entry>" in the PR description. - Justify it. If the drift can't be resolved in this PR (different scope, blocked on a platform spec change, etc.), say so in the PR description in one line.
Reviewers will ask the burndown-or-justify question on PRs that touch baselined areas without addressing them.
The plugin reads MCP-response field shapes from the AxonFlow agent. We track three buckets of drift:
- Canonical wire-bound schemas — gate-zero target.
MCPCheckInputResponse,MCPCheckOutputResponse. Every field the plugin reads on these schemas should trace to the agent OpenAPI spec, and every spec field should ideally be surfaced where useful. Drift here lands on the burndown queue and shrinks over time. - Helper / advisory reads — accept non-zero drift. Internal read variables that aren't AxonFlow-wire (Claude Code's own hook input/output, plugin manifest fields). These are out of scope for the wire-shape gate.
@sdkDerivedfirst-class marker (deferred). When a script reads a field that's a plugin-side derivation rather than a wire field, mark it explicitly. Convention deferred until first real use case lands.
The four AxonFlow SDKs (TS / Python / Go / Java) declare wire-bound types in source code and the gate compares those declarations to the OpenAPI spec. The Claude / Cursor / Codex plugins are bash scripts that read fields directly via jq — there is no typed declaration to walk. The bash gate instead enumerates jq accesses on known MCP-response variables (TOOL_RESULT, SCAN_RESULT) and treats those as the plugin's wire contract.
Bug classes the bash gate catches:
- script reads a field name that the spec doesn't declare → drift
- spec gains a field the script doesn't read → Cat B opportunity
Bug classes specific to TS/Python SDKs (transformer drift, falsey-clobber, sync wrapper signature lag) don't apply to bash plugins by construction — there are no transformers, || is shell-OR (not implicit-truthiness), and there are no sync/async wrappers.
- Open a GitHub issue
- Email: hello@getaxonflow.com