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
40 changes: 40 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,46 @@ jobs:
grep -q 'Counterproof · Regression Witness' /tmp/REGRESSION_WITNESS.md
grep -Fq 'Base code + PR tests: **FAIL**' /tmp/REGRESSION_WITNESS.md

- name: Run packaged zero-config local check
run: |
set -euo pipefail
rm -rf /tmp/counterproof-check-fixture
mkdir -p /tmp/counterproof-check-fixture
cd /tmp/counterproof-check-fixture

git init -b main
git config user.email "counterproof@example.test"
git config user.name "Counterproof CI"

printf 'VALUE = 1\n' > app.py
git add app.py
git commit -m "base"

git checkout -b feature/fix
mkdir -p tests
printf 'VALUE = 2\n' > app.py
cat > tests/test_regression.py <<'PY'
from app import VALUE

def test_regression():
assert VALUE == 2
PY
git add app.py tests/test_regression.py
git commit -m "fix plus regression test"

/tmp/counterproof-clean/bin/pip install pytest
/tmp/counterproof-clean/bin/counterproof check \
--repo /tmp/counterproof-check-fixture \
--test-command "/tmp/counterproof-clean/bin/python -m pytest -q {tests}" \
--strict \
> /tmp/LOCAL_CHECK.txt

grep -q 'Regression WITNESSED' /tmp/LOCAL_CHECK.txt
grep -q 'Strict gate PASS' /tmp/LOCAL_CHECK.txt
grep -q 'Base main' /tmp/LOCAL_CHECK.txt
grep -q 'Product oracle UNVERIFIED' /tmp/LOCAL_CHECK.txt
grep -q 'Proof integrity CLEAN' /tmp/LOCAL_CHECK.txt

- name: Run packaged Proof Integrity Guard
run: |
set -euo pipefail
Expand Down
9 changes: 8 additions & 1 deletion site/data/capabilities.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@
"evidence": "counterproof init detects common test runners and writes a pull-request workflow using the root CounterProof Action without overwriting existing config by default.",
"limitation": "Runner detection is conservative; project-specific dependency setup may still need review, and strict mode refuses suite-only evidence."
},
{
"id": "local-check",
"name": "One-command local branch proof check",
"status": "tested",
"evidence": "counterproof check resolves a base branch, detects or accepts a test runner, executes Regression Witness plus Proof Integrity, and is exercised from both unit tests and a clean installed wheel.",
"limitation": "Automatic base detection currently prefers origin/HEAD, main/master conventions, or an explicit --base; unusual repository topologies may need an override."
},
{
"id": "regression-witness",
"name": "Regression Witness for agent pull requests",
Expand Down Expand Up @@ -220,7 +227,7 @@
}
],
"summary": {
"tested": 22,
"tested": 23,
"partial": 4,
"demo": 1,
"planned": 4
Expand Down
7 changes: 7 additions & 0 deletions skill_factory/evolution/capabilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@
"evidence": "counterproof init detects common test runners and writes a pull-request workflow using the root CounterProof Action without overwriting existing config by default.",
"limitation": "Runner detection is conservative; project-specific dependency setup may still need review, and strict mode refuses suite-only evidence.",
},
{
"id": "local-check",
"name": "One-command local branch proof check",
"status": "tested",
"evidence": "counterproof check resolves a base branch, detects or accepts a test runner, executes Regression Witness plus Proof Integrity, and is exercised from both unit tests and a clean installed wheel.",
"limitation": "Automatic base detection currently prefers origin/HEAD, main/master conventions, or an explicit --base; unusual repository topologies may need an override.",
},
{
"id": "regression-witness",
"name": "Regression Witness for agent pull requests",
Expand Down
61 changes: 61 additions & 0 deletions skill_factory/evolution/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
render_integrity_markdown,
write_integrity_json,
)
from .local_check import local_check_json, render_local_check, run_local_check
from .models import (
CandidateMutation,
Evidence,
Expand Down Expand Up @@ -737,6 +738,66 @@ def doctor(json_output: bool) -> None:
raise click.ClickException("Counterproof self-test failed")


@cli.command("check")
@click.option(
"--repo",
"repo_dir",
default=".",
show_default=True,
type=click.Path(file_okay=False),
)
@click.option(
"--base",
"base_ref",
default=None,
help="Override automatic base-branch detection.",
)
@click.option(
"--test-command",
default=None,
help="Override runner detection. Use {tests} for precise replay.",
)
@click.option("--timeout", "timeout_seconds", default=300.0, show_default=True, type=float)
@click.option(
"--result-protocol",
type=click.Choice(["exit-code", "json-v1"]),
default="exit-code",
show_default=True,
)
@click.option("--json-output", is_flag=True, help="Emit machine-readable JSON.")
@click.option(
"--strict",
is_flag=True,
help="Exit non-zero unless exact witness evidence exists and integrity is clean.",
)
def check_cmd(
repo_dir: str,
base_ref: str | None,
test_command: str | None,
timeout_seconds: float,
result_protocol: str,
json_output: bool,
strict: bool,
) -> None:
"""Run a zero-config local proof check for the current branch."""
try:
result = run_local_check(
Path(repo_dir),
base_ref=base_ref,
test_command=test_command,
timeout_seconds=timeout_seconds,
result_protocol=result_protocol,
)
except (RuntimeError, ValueError) as exc:
raise click.ClickException(str(exc)) from exc

click.echo(local_check_json(result) if json_output else render_local_check(result))
if strict and not result.strict_pass:
raise click.ClickException(
f"CounterProof strict check failed: status={result.status}"
)


@cli.command("integrity")
@click.option(
"--base",
Expand Down
Loading
Loading