PR-004: Freeze Phantom Consumer Contract (contract-version 1.0.0)#1
Merged
Conversation
phantom run previously committed and pushed captures regardless of the
quality check ("warnings only, don't block"), so a blank/too-small/sensitive
frame could reach pushed git history with no gate. Orchestrator._publish now
blocks commit/push when any QualityReport has an error-severity issue, unless
--force (reuses the existing flag). Warning-severity issues stay advisory and
still publish. A blocked publish sets JobReport.blocked_by_quality and the CLI
exits non-zero. CI is unaffected (it runs with --skip-publish).
Adds 3 integration tests: block-on-failure (proving test), force-overrides,
warning-only-still-publishes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The reusable phantom-capture.yml uploaded docs/screenshots/ with if: always(), making captured frames downloadable (world-readable on public repos, ~90d retention) before any review and bypassing the pr gate. Now gated on success() AND a new upload-screenshots-artifact input (default false). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Snapshots/rollback are a manual CLI tool, not an automatic safety net: the orchestrator never auto-creates snapshots or rolls back, and rollback is forward-only (git checkout into a new commit) so it cannot remove an already-pushed frame. Corrects the SnapshotManager docstring, the 0.3.0 CHANGELOG entry, and the collaborator guide; adds Unreleased CHANGELOG notes for the publish gate and artifact gating. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The publish quality gate from the prior PR does not run in CI, which uses `phantom run --skip-publish` (the gate sits after the skip-publish early return). So a bad/sensitive frame produced in CI was still committed by the workflow's own git steps. New `--fail-on-quality-error` flag / JobOptions.fail_on_quality_error: when set, an error-severity quality failure marks the run blocked even in --skip-publish mode, so the CLI exits non-zero (CI then skips its success-gated commit steps). --force overrides; warnings never block; default behaviour (no flag) is unchanged for local inspection. Adds orchestrator + CLI exit-code tests (block / no-flag-no-block / force). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…verride phantom-capture.yml now runs `phantom run --skip-publish --fail-on-quality-error` so an error-severity capture fails the job. The commit/push steps are made explicitly `success()`-gated (direct + pr) so they skip on that failure — nothing bad is committed. New `force-publish` input (default false) passes --force to bypass the gate for intentionally low-signal frames. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CHANGELOG [Unreleased] Security entry for the CI commit-path quality gate and the force-publish/--fail-on-quality-error overrides; collaborator guide Step 5 explains the CI quality gate and the force-publish escape hatch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nners Add `phantom.contract` as the machine-checkable source of truth for the Phantom Consumer Contract (contract-version 1.0.0): CONTRACT_VERSION, PHANTOM_MODE detection, the app_env() guarantee, artifact/health defaults, and the network allowlist helpers. Expose phantom.__contract_version__. Guarantee PHANTOM_MODE=1 in every launched consumer app's environment across the web, docker-compose, tui, and desktop runners via contract.app_env(). Previously demo mode activated only if the invoking shell or the manifest's setup.run.env set the variable, so a direct `phantom run` never triggered a consumer's demo mode. A manifest's explicit run.env may still override it. Bump package to 0.4.0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011aan6YK1rLYEUEfX2XB6QS
77 tests mechanically verifying Phantom's side of every CONTRACT.md promise: mode detection and PHANTOM_MODE=1 injection at all four runners' spawn points (web/docker/tui/desktop, system tools mocked), schema parsing including unknown-key forward-compat, ready-check timeout declaration, artifact path safety, the network allowlist, and contract-version exposure. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011aan6YK1rLYEUEfX2XB6QS
…ersion 1.0.0) - CONTRACT.md: frozen boot/config/health/artifact/versioning contract plus non-goals, at contract-version 1.0.0. - docs/smoke-job-spec.md: specification for the reusable CI smoke job Step 3 will implement (inputs, steps, pass/fail, consumer requirements). - CHANGELOG: 0.4.0 release entry noting contract-version 1.0.0. - README: Consumer Contract section, PHANTOM_MODE env var, pinning discipline. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011aan6YK1rLYEUEfX2XB6QS
wbuscombe
enabled auto-merge
July 11, 2026 17:27
Python 3.12 no longer auto-creates an event loop for the main thread, so the codebase's `asyncio.get_event_loop().run_until_complete(...)` idiom crashes with "no current event loop" on a fresh interpreter — breaking real CLI commands (`phantom run/doctor/analyze/rollback`) and 56 tests under newer pytest-asyncio. This was latent because CI only runs on main/PRs. - cli.py: add `_run_async()` helper that ensures/reuses a current loop and route all 13 CLI call sites through it (preserves single-loop-per-invocation semantics so async clients bound to the loop stay valid). - tests: replace the deprecated idiom with `asyncio.run(...)` (version- independent) across the affected unit + integration suites. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011aan6YK1rLYEUEfX2XB6QS
…b drift CI's mypy flagged `# type: ignore` comments on croniter/playwright imports as unused because those optional deps ship type info in some resolved versions but not others, so the same ignore is "needed" locally and "unused" in CI. Disable warn_unused_ignores so the type gate is deterministic across environments; the ignores remain correct where the stubs are absent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011aan6YK1rLYEUEfX2XB6QS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Freezes the interface consumer apps and the CI smoke job depend on, so Phantom can iterate freely behind it (PR-004 Step 2). No app/CI integration here — that is Step 3.
CONTRACT.md— frozen boot / config / health / artifact / versioning contract + non-goals, atcontract-version: 1.0.0.phantom.contractmodule — machine-checkable source of truth; exposesphantom.__contract_version__.PHANTOM_MODE=1in every launched app's environment across all four runners (web / docker-compose / tui / desktop). Previously demo mode only activated if the shell or manifest set it, so a directphantom runnever triggered a consumer's demo mode.tests/contract/— 77 conformance tests verifying every contract promise.docs/smoke-job-spec.md— spec for the reusable smoke job Step 3 will implement.Test counts
ruff check/ruff format --check/mypy --strictall clean.Note on branch history
This branch was based on
fix/ci-commit-quality-gate(6 CI quality-gate commits that were ahead ofmainwith no open PR), so this PR also lands that ready work. The final 3 commits are PR-004.🤖 Generated with Claude Code
https://claude.ai/code/session_011aan6YK1rLYEUEfX2XB6QS