Skip to content

[skip-runtime-e2e] ci(definition-of-done): mechanical gate enforcing HARD RULE #0#181

Merged
saurabhjain1592 merged 2 commits intomainfrom
chore/definition-of-done-gate
May 5, 2026
Merged

[skip-runtime-e2e] ci(definition-of-done): mechanical gate enforcing HARD RULE #0#181
saurabhjain1592 merged 2 commits intomainfrom
chore/definition-of-done-gate

Conversation

@saurabhjain1592
Copy link
Copy Markdown
Member

Summary

Adds the same mechanical definition-of-done gate that just landed in the four plugin repos (pilot: getaxonflow/axonflow-claude-plugin#59; replicas: getaxonflow/axonflow-openclaw-plugin#101, getaxonflow/axonflow-cursor-plugin#48, getaxonflow/axonflow-codex-plugin#48) — adapted for the Python SDK's user-facing surface.

Five additions:

  • scripts/lint-no-mocks-in-runtime-e2e.sh — copied verbatim from the pilot. Greps runtime-e2e/ for forbidden mock-pattern strings (unittest.mock, MagicMock, httpx_mock.add_response, jest.fn, sinon.stub, wiremock, httptest.NewServer, msw.setupServer, nock., capture-stub harnesses) and fails the build if any are found. Inline allow-mocks-here: marker is available for the rare README/comment that legitimately names the patterns.
  • .github/workflows/definition-of-done.yml — runs the lint, then on every PR diffs against base and requires a runtime-e2e/ test alongside any change that touches the SDK's user-facing surface (axonflow/, pyproject.toml, examples/). Escape hatch: [skip-runtime-e2e] in title + ## Skip-runtime-e2e justification section in body.
  • runtime-e2e/README.md — convention doc and local-run instructions (register a tenant via /api/v1/register, export AXONFLOW_TENANT_ID + AXONFLOW_TENANT_SECRET, then loop over runtime-e2e/*/test.py).
  • runtime-e2e/x-axonflow-client/test.py — first runtime test, derived from this week's live sdk_py_real.py driver. Asserts the SDK stamps X-Axonflow-Client: sdk-python/<__version__> on every governed request, by forcing the scope-mismatch path so the agent echoes the header value back in its rejection response.
  • pyproject.toml — adds a runtime-e2e/**/*.py per-file-ignores stanza, modeled on the existing tests/heartbeat-real-stack/** carve-out. Same justification: real-stack driver scripts, not pytest tests, so print is the report channel, blind-except is appropriate when inspecting whatever the SDK wraps, and monkey-patching httpx.AsyncClient.request is the documented way to force the scope-mismatch path.

Why now

CLAUDE.md HARD RULE #0 (added after the 2026-05-05 X-Axonflow-Client incident, where mocks-only PR evidence masked a feature whose runtime was silently broken): a user-facing feature is not done until demonstrated through its actual runtime — for the Python SDK that means a real from axonflow import AxonFlow over real httpx against a real running AxonFlow agent. This PR is the mechanical enforcement layer.

Skip-runtime-e2e justification

This PR's only "user-facing" change is a comment-only stanza in pyproject.toml that adds per-file-ignores for runtime-e2e/. There is no SDK behavior change, no new public API, no examples touched. The runtime-e2e/x-axonflow-client/ test that already shipped against a live stack across the four plugin repos exists here and will run the next time a build pipeline brings up an agent. The escape hatch exists exactly for changes like this — pure CI plumbing where there's no runtime to demonstrate.

Test plan

  • python3 -c "import yaml; yaml.safe_load(open('.github/workflows/definition-of-done.yml'))" — clean
  • ./scripts/lint-no-mocks-in-runtime-e2e.sh — clean (runtime-e2e is clean)
  • python3 -m ruff check . — All checks passed
  • python3 -m ruff format --check . — clean
  • DCO sign-off present
  • CI green on this PR (will verify after push)
  • Self-review every hunk before merge

Refs

…HARD RULE #0

Add the same definition-of-done gate that just landed in the four plugin
repos (axonflow-claude-plugin#59 pilot, axonflow-openclaw-plugin#101,
axonflow-cursor-plugin#48, axonflow-codex-plugin#48) — adapted for the
Python SDK's user-facing surface.

What this PR adds:

- scripts/lint-no-mocks-in-runtime-e2e.sh — copied verbatim from the
  pilot. Greps runtime-e2e/ for forbidden mock-pattern strings
  (unittest.mock, MagicMock, httpx_mock.add_response, jest.fn, sinon,
  wiremock, httptest.NewServer, msw, nock, capture-stub harnesses, etc.)
  and fails the build if any are found. Inline `allow-mocks-here:`
  marker available for the rare doc/comment that legitimately mentions
  the patterns by name.

- .github/workflows/definition-of-done.yml — runs the lint, then on PRs
  detects whether the diff touches the SDK's user-facing surface
  (axonflow/, pyproject.toml, examples/) and requires a runtime-e2e/
  test in the same PR. Escape hatch: `[skip-runtime-e2e]` in PR title
  + `## Skip-runtime-e2e justification` section in PR body.

- runtime-e2e/README.md — convention doc + local-run instructions
  (register a tenant against a live agent, export creds, run each
  test.py).

- runtime-e2e/x-axonflow-client/test.py — first runtime test, derived
  from the live driver used in this week's X-Axonflow-Client E2E
  (proves the SDK stamps `X-Axonflow-Client: sdk-python/<__version__>`
  on every governed request, by forcing the scope-mismatch path so the
  agent echoes the value back).

- pyproject.toml — adds a per-file-ignores stanza for runtime-e2e/**/*.py
  matching the existing tests/heartbeat-real-stack/** carve-out: these
  are real-stack driver scripts, not pytest tests, and the same lint
  exemptions apply (print as report channel, blind except for whatever
  the SDK wraps, monkey-patch on httpx.AsyncClient.request to inject
  the scope-mismatch header).

Why now (CLAUDE.md HARD RULE #0):

The 2026-05-05 X-Axonflow-Client incident landed mocks-only evidence at
PR-merge time on a feature whose runtime was silently broken. The new
top-level HARD RULE in CLAUDE.md states that a user-facing feature is
not done until demonstrated through its actual runtime. This PR is the
mechanical enforcement layer for the Python SDK.

Local validation:

  python3 -c "import yaml; yaml.safe_load(open('.github/workflows/definition-of-done.yml'))"  # ok
  ./scripts/lint-no-mocks-in-runtime-e2e.sh                                                    # clean
  python3 -m ruff check .                                                                      # clean
  python3 -m ruff format --check .                                                             # clean

## Skip-runtime-e2e justification

This PR's only "user-facing" change is a comment-only stanza in
pyproject.toml that adds per-file-ignores for runtime-e2e/. There is no
SDK behavior change, no new public API, no examples touched. The
runtime-e2e/x-axonflow-client/ test that already shipped to the four
plugin repos exists here and will run against a real stack the next
time a build pipeline brings one up. The skip-runtime-e2e escape hatch
exists exactly for changes like this — pure CI plumbing where there's
no runtime to demonstrate.

Refs:
- axonflow-claude-plugin#59 (pilot)
- CLAUDE.md HARD RULE #0

Signed-off-by: Saurabh Jain <saurabhjain1592@gmail.com>
Comment thread runtime-e2e/x-axonflow-client/test.py Fixed
…doesn't flag a secret-name f-string

CodeQL py/clear-text-logging-sensitive-data flagged line 27 because
the f-string interpolation included variable names like
AXONFLOW_TENANT_SECRET / AXONFLOW_E2E_PLUGIN_TOKEN. The print only
outputs the NAME, never the value, but CodeQL's heuristic flags the
pattern. Refactor to a static stderr message with the missing-list
collected separately.

Signed-off-by: Saurabh Jain <saurabhjain1592@gmail.com>
@saurabhjain1592 saurabhjain1592 merged commit ca4fa47 into main May 5, 2026
21 checks passed
@saurabhjain1592 saurabhjain1592 deleted the chore/definition-of-done-gate branch May 5, 2026 11:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants