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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
- name: Check ORRO wrapper install
run: python3 scripts/check_orro_wrapper_install.py --json
- name: Check ORRO wrapper distribution
run: python3 scripts/check_orro_wrapper_distribution.py --json
run: python3 scripts/check_orro_wrapper_distribution.py --json --allow-network
- name: Compile scripts
run: python3 -m py_compile scripts/check_no_bidi_controls.py scripts/check_orro_repo_contract.py scripts/check_orro_language_boundaries.py scripts/check_orro_assurance_contract_fixtures.py scripts/check_orro_release_manifest.py scripts/check_compatibility_matrix.py scripts/check_orro_packaging_decision.py scripts/check_orro_fallback_policy.py scripts/check_orro_command_migration.py scripts/check_orro_command_migration_dry_run.py scripts/check_orro_wrapper.py scripts/check_orro_wrapper_install.py scripts/check_orro_wrapper_distribution.py scripts/orro_e2e_smoke.py scripts/update_orro_engine_lock.py scripts/bootstrap_orro.py src/orro_wrapper/__init__.py src/orro_wrapper/__main__.py src/orro_wrapper/cli.py
- name: Bidi control scanner self-test
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,13 @@ temporary virtual environment, and verifies that `orro` and `orro-wrapper` are
exposed:

```bash
python3 scripts/check_orro_wrapper_distribution.py --json
python3 scripts/check_orro_wrapper_distribution.py --json --allow-network
```

The distribution smoke checks that the wheel contains no Depone or witnessd
packages and no proofrun/proofcheck runtime implementation files.
The explicit network flag authorizes pip build isolation to provision the
declared `setuptools>=61` build requirement in a clean build environment.

The distribution smoke is local test metadata, not proof, not verifier truth,
not package publish, not approval, and not assurance.
Expand Down
5 changes: 3 additions & 2 deletions docs/bootstrap.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,13 @@ Published ORRO package remains future work.
The wrapper distribution smoke is separate from bootstrap:

```bash
python3 scripts/check_orro_wrapper_distribution.py --json
python3 scripts/check_orro_wrapper_distribution.py --json --allow-network
```

It builds and installs a local wheel to verify packaging boundaries. It does not
prepare engine checkouts, does not verify evidence, does not publish a package,
and does not shadow the witnessd-hosted `orro` command.
and does not shadow the witnessd-hosted `orro` command. The explicit network
flag authorizes only the isolated wrapper build-dependency bootstrap.

## Self-Test

Expand Down
2 changes: 1 addition & 1 deletion docs/engine-lock-update-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ checkout or open an intentional engine-lock update PR.
3. Run `python3 scripts/check_orro_repo_contract.py`.
4. Run `python3 scripts/check_orro_release_manifest.py`.
5. Run `python3 scripts/update_orro_engine_lock.py --self-test`.
6. Run `python3 scripts/check_orro_wrapper_distribution.py --json`.
6. Run `python3 scripts/check_orro_wrapper_distribution.py --json --allow-network`.
7. Run `python3 scripts/orro_e2e_smoke.py --engine-lock engine-lock/orro-e2e-engine-lock.json --require-lock-match --allow-network`.
8. Confirm boundary text.
9. Open a PR with engine commits and test results.
Expand Down
4 changes: 3 additions & 1 deletion docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ remains future work, and future wrapper work must contain no engine code.
The local wrapper package can be checked without publishing anything:

```bash
python3 scripts/check_orro_wrapper_distribution.py --json
python3 scripts/check_orro_wrapper_distribution.py --json --allow-network
```

This builds and installs a local wheel and verifies `orro` plus `orro-wrapper`.
The flag authorizes pip build isolation to provision the declared wrapper build
dependency; it does not authorize engine checkout or package publication.
4 changes: 3 additions & 1 deletion docs/thin-wrapper.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,14 @@ not package publish, not approval, and not assurance.
The wrapper distribution smoke builds and installs a local wheel:

```bash
python3 scripts/check_orro_wrapper_distribution.py --json
python3 scripts/check_orro_wrapper_distribution.py --json --allow-network
```

It verifies that the wheel contains wrapper modules only, exposes `orro` and
`orro-wrapper`, and contains no Depone, witnessd, proofrun, proofcheck,
scheduler, observer, fan-in, team-ledger, or verifier implementation files.
The explicit network flag authorizes only pip build isolation for the wrapper's
declared build dependency.

The distribution smoke is local test metadata, not proof, not verifier truth,
not package publish, not approval, and not assurance.
8 changes: 6 additions & 2 deletions docs/wrapper-distribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ truth, not package publish, not approval, and not assurance.
## Command

```bash
python3 scripts/check_orro_wrapper_distribution.py --json
python3 scripts/check_orro_wrapper_distribution.py --json --allow-network
```

The checker builds a local wheel in a temporary workspace, installs that wheel
into a temporary virtual environment, and verifies the installed `orro` and
`orro-wrapper` console scripts.
`orro-wrapper` console scripts. It creates a separate build environment, removes
any preinstalled `setuptools`, confirms the build backend is absent, and then
uses pip build isolation to provision the declared `setuptools>=61` requirement.
`--allow-network` explicitly authorizes that build-dependency bootstrap; it does
not authorize engine checkout mutation or package publication.

## Boundary

Expand Down
49 changes: 44 additions & 5 deletions scripts/check_orro_wrapper_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,27 +182,56 @@ def check_boundary_payload(label: str, payload: dict[str, Any]) -> None:
fail("ERR_ORRO_WRAPPER_DISTRIBUTION_BOUNDARY_INVALID", f"{label}.boundary.{key} must be false")


def build_wheel(source_dir: Path, dist_dir: Path) -> Path:
run_command([sys.executable, "-m", "pip", "wheel", "--no-deps", "--no-build-isolation", "-w", str(dist_dir), str(source_dir)])
def prepare_build_venv(venv_dir: Path) -> Path:
create_venv(venv_dir)
bin_dir = scripts_dir(venv_dir)
python = bin_dir / ("python.exe" if os.name == "nt" else "python")
run_command([str(python), "-m", "pip", "uninstall", "--yes", "setuptools"])
probe = run_command(
[
str(python),
"-c",
"import importlib.util; print(importlib.util.find_spec('setuptools') is not None)",
]
)
if probe.stdout.strip() != "False":
fail(
"ERR_ORRO_WRAPPER_DISTRIBUTION_BUILD_ENV_INVALID",
"wrapper build venv must not contain setuptools before the isolated build",
{"stdout": probe.stdout, "stderr": probe.stderr},
)
return python


def build_wheel(source_dir: Path, dist_dir: Path, python: Path) -> Path:
run_command([str(python), "-m", "pip", "wheel", "--no-deps", "-w", str(dist_dir), str(source_dir)])
wheels = sorted(dist_dir.glob("orro_product_wrapper-*.whl"))
if len(wheels) != 1:
fail("ERR_ORRO_WRAPPER_DISTRIBUTION_WHEEL_NOT_FOUND", "expected exactly one ORRO wrapper wheel", {"wheels": [str(path) for path in wheels]})
return wheels[0]


def distribution_check(workspace: Path | None) -> dict[str, Any]:
def distribution_check(workspace: Path | None, *, allow_network: bool) -> dict[str, Any]:
owns_workspace = workspace is None
workdir = Path(tempfile.mkdtemp(prefix="orro-wrapper-dist-")) if workspace is None else workspace
if workdir.exists() and any(workdir.iterdir()):
fail("ERR_ORRO_WRAPPER_DISTRIBUTION_WORKSPACE_NOT_EMPTY", "workspace must be empty for distribution check", {"workspace": str(workdir)})
workdir.mkdir(parents=True, exist_ok=True)
source_dir = workdir / "source"
dist_dir = workdir / "dist"
build_venv_dir = workdir / "build-venv"
venv_dir = workdir / "venv"
try:
copy_source(source_dir)
dist_dir.mkdir()
wheel_path = build_wheel(source_dir, dist_dir)
build_python = prepare_build_venv(build_venv_dir)
if not allow_network:
fail(
"ERR_ORRO_WRAPPER_DISTRIBUTION_NETWORK_NOT_ALLOWED",
"isolated wrapper build dependency bootstrap requires --allow-network",
{"build_backend": "setuptools.build_meta", "build_requirement": "setuptools>=61"},
)
wheel_path = build_wheel(source_dir, dist_dir, build_python)
package_contents = inspect_wheel(wheel_path)
entry_points = inspect_entry_points(wheel_path)

Expand Down Expand Up @@ -239,6 +268,7 @@ def distribution_check(workspace: Path | None) -> dict[str, Any]:
"wheel_entry_points": entry_points,
"package_contents": package_contents,
"checks": [
{"name": "build_venv_has_no_setuptools_before_build", "status": "pass"},
{"name": "wheel_build", "status": "pass"},
{"name": "wheel_contains_no_engine_packages", "status": "pass"},
{"name": "wheel_entry_points_include_orro", "status": "pass"},
Expand Down Expand Up @@ -303,14 +333,23 @@ def parse_args(argv: list[str]) -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Build and smoke-test the local ORRO wrapper wheel.")
parser.add_argument("--workspace", "--workdir", dest="workspace", help="Empty workspace for build/install artifacts. Defaults to a temporary directory.")
parser.add_argument("--json", action="store_true", help="Emit JSON. JSON is the default output.")
parser.add_argument(
"--allow-network",
action="store_true",
help="Allow pip build isolation to bootstrap the wrapper's declared build dependency.",
)
parser.add_argument("--self-test", action="store_true", help="Run offline self-test without building a wheel.")
return parser.parse_args(argv)


def main(argv: list[str] | None = None) -> int:
args = parse_args(sys.argv[1:] if argv is None else argv)
try:
result = self_test() if args.self_test else distribution_check(Path(args.workspace) if args.workspace else None)
result = (
self_test()
if args.self_test
else distribution_check(Path(args.workspace) if args.workspace else None, allow_network=args.allow_network)
)
print(json.dumps(result, indent=2, sort_keys=True))
return 0
except DistributionCheckError as exc:
Expand Down
69 changes: 69 additions & 0 deletions scripts/orro_e2e_smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
SCHEMA_VERSION = "0.1"
COMMIT_RE = re.compile(r"^[0-9a-f]{40}$")
LOCK_BOUNDARY_FALSE_KEYS = ("approves_merge", "raises_assurance", "executes_commands", "verifies_evidence")
ROLE_LANE_PLACEHOLDER_PROMPT_PREFIX = "Execute ORRO role "


class OrroE2EError(RuntimeError):
Expand Down Expand Up @@ -112,6 +113,25 @@ def _self_test() -> int:
lambda: _engine_lock_status(mismatch, True, witnessd_repo, depone_repo),
checks,
)
role_lane_plan = {
"lanes": [
{
"lane_id": "runner",
"may_execute": True,
"prompt": "Execute ORRO role runner for goal: update README safely",
},
{
"lane_id": "reviewer",
"may_execute": False,
"prompt": "Review the README without changing it",
},
]
}
materialized = _materialize_executable_role_lane_prompts(role_lane_plan, "update README safely")
assert materialized == 1
assert role_lane_plan["lanes"][0]["prompt"] == "update README safely"
assert role_lane_plan["lanes"][1]["prompt"] == "Review the README without changing it"
checks.append({"name": "executable_role_lane_prompt_materialization", "status": "pass"})
result = _json_result("pass", checks)
assert result["kind"] == "orro-e2e-smoke-result"
assert result["boundary"]["contains_engine_logic"] is False
Expand Down Expand Up @@ -309,6 +329,26 @@ def _run_raw(args: list[str], *, cwd: Path) -> subprocess.CompletedProcess[str]:
return completed


def _materialize_executable_role_lane_prompts(role_lane_plan: dict[str, Any], task: str) -> int:
lanes = role_lane_plan.get("lanes")
if not isinstance(lanes, list):
raise OrroE2EError(
"ERR_ORRO_E2E_ROLE_LANE_PLAN_INVALID",
"role-lane plan lanes must be a list",
)
materialized = 0
for lane in lanes:
if not isinstance(lane, dict):
raise OrroE2EError(
"ERR_ORRO_E2E_ROLE_LANE_PLAN_INVALID",
"role-lane plan lanes must contain objects",
)
if lane.get("may_execute") is True:
lane["prompt"] = task
materialized += 1
return materialized


class SmokeRunner:
def __init__(
self,
Expand Down Expand Up @@ -532,6 +572,35 @@ def _full_flow(self) -> None:
self._assert(workflow_plan.is_file(), "flowplan_writes_workflow_plan", "workflow plan missing")
self._assert(role_lane_plan.is_file(), "flowplan_writes_role_lane_plan", "role-lane plan missing")

try:
role_lane_payload = json.loads(role_lane_plan.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError) as exc:
raise OrroE2EError(
"ERR_ORRO_E2E_ROLE_LANE_PLAN_INVALID",
"could not load generated role-lane plan",
{"path": str(role_lane_plan), "error": str(exc)},
) from exc
if not isinstance(role_lane_payload, dict):
raise OrroE2EError(
"ERR_ORRO_E2E_ROLE_LANE_PLAN_INVALID",
"generated role-lane plan must be a JSON object",
{"path": str(role_lane_plan)},
)
materialized_lanes = _materialize_executable_role_lane_prompts(role_lane_payload, goal)
role_lane_plan.write_text(json.dumps(role_lane_payload, indent=2, sort_keys=True) + "\n", encoding="utf-8")
executable_lanes = [lane for lane in role_lane_payload["lanes"] if lane.get("may_execute") is True]
self._assert(
materialized_lanes > 0
and all(
lane.get("prompt") == goal
and not str(lane.get("prompt", "")).startswith(ROLE_LANE_PLACEHOLDER_PROMPT_PREFIX)
for lane in executable_lanes
),
"flowplan_materializes_explicit_role_lane_prompts",
"every executable role lane must carry the declared E2E task before proofrun",
materialized_lanes=materialized_lanes,
)

proofrun_args = [
"proofrun",
goal,
Expand Down
Loading