From 73aa510de7f8a620bc4fa9e7b164c2416db2b858 Mon Sep 17 00:00:00 2001 From: 4444J99 <4444J99@users.noreply.github.com> Date: Fri, 19 Jun 2026 08:48:59 -0400 Subject: [PATCH] resolve rules-system-bound#8 (UNSTABLE) limen task RESOLVE-organvm-i-theoria-rules-system-bound-8 --- .github/workflows/ci-python.yml | 2 +- README.md | 17 +++ src/rules_system_bound/__init__.py | 8 +- src/rules_system_bound/cli.py | 202 ++++++++++++----------------- src/rules_system_bound/config.py | 2 +- tests/test_cli.py | 48 ------- tests/test_core.py | 39 ++++-- 7 files changed, 136 insertions(+), 182 deletions(-) delete mode 100644 tests/test_cli.py diff --git a/.github/workflows/ci-python.yml b/.github/workflows/ci-python.yml index a3914af..2d5c2ed 100644 --- a/.github/workflows/ci-python.yml +++ b/.github/workflows/ci-python.yml @@ -27,4 +27,4 @@ jobs: run: python -m pytest -q - name: Run activation smoke path - run: rules-system-bound demo --json + run: rules-system-bound --json diff --git a/README.md b/README.md index 843acd6..5d8dd01 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,23 @@ Three types that co-constitute with real systems: - **WEBERIAN**: Essential function captured - **NORMALIZED**: Representation of real instances +## Runnable Evidence + +From a checkout, the activation smoke path is: + +```bash +PYTHONPATH=src python3 -m rules_system_bound --json +``` + +After installation, the release path is: + +```bash +rules-system-bound --json +``` + +See [docs/activation-audit.md](docs/activation-audit.md) for the audit receipt +and the exact install/test commands. + ## Configuration Copy `.env.template` to `.env` and customize: diff --git a/src/rules_system_bound/__init__.py b/src/rules_system_bound/__init__.py index 3af9195..e6fcc55 100644 --- a/src/rules_system_bound/__init__.py +++ b/src/rules_system_bound/__init__.py @@ -1,5 +1,7 @@ """rules-system-bound: Living Container Framework.""" +from importlib.metadata import PackageNotFoundError, version + from .config import Config, get_config from .container import Container, ContainmentRules from .idealization import ( @@ -14,9 +16,13 @@ ) from .interaction import Interaction, System, InteractionEmergence -__version__ = "0.1.0" +try: + __version__ = version("rules-system-bound") +except PackageNotFoundError: + __version__ = "0.1.0" __all__ = [ + "__version__", "Config", "get_config", "Container", diff --git a/src/rules_system_bound/cli.py b/src/rules_system_bound/cli.py index cc1f0ac..910706c 100644 --- a/src/rules_system_bound/cli.py +++ b/src/rules_system_bound/cli.py @@ -1,106 +1,87 @@ -"""Command line interface for rules-system-bound.""" +"""Command-line smoke path for the Living Container Framework.""" from __future__ import annotations import argparse import json -from collections.abc import Sequence -from typing import Any +from typing import Any, Sequence -from . import __version__ -from .config import Config +from . import __version__ as PACKAGE_VERSION +from .config import get_config from .container import Container, ContainmentRules from .idealization import IdealizationManager, IdealizationType from .interaction import InteractionEmergence, System -REPOSITORY_URL = "https://github.com/organvm-i-theoria/rules-system-bound" -SOURCE_ISSUE = "organvm-i-theoria/rules-system-bound#2" +CONSOLE_SCRIPT_NAME = "rules-system-bound" +SOURCE_EXEC_CMD = ( + f"PYTHONPATH=src python3 -m {CONSOLE_SCRIPT_NAME.replace('-', '_')} --json" +) +INSTALLED_EXEC_CMD = f"{CONSOLE_SCRIPT_NAME} --json" -def build_activation_report() -> dict[str, Any]: - """Return activation evidence for the package release surface.""" - return { - "identity": "Hierarchical rule/container constraint system", - "package": { - "name": "rules-system-bound", - "import_name": "rules_system_bound", - "version": __version__, - "repository": REPOSITORY_URL, - }, - "release_surface": { - "live_url": REPOSITORY_URL, - "installable_package": ( - "python3 -m pip install " - "git+https://github.com/organvm-i-theoria/rules-system-bound.git" - ), - "editable_install": 'python3 -m pip install -e ".[dev]"', - "runnable_release": "rules-system-bound demo --json", - "repo_exec_path": "PYTHONPATH=src python3 -m rules_system_bound demo --json", - }, - "evidence_level": "runnable-from-repo", - "activation_verdict": "ship-soon evidence complete", - "source_issue": SOURCE_ISSUE, - } - - -def build_demo_report() -> dict[str, Any]: - """Run a deterministic containment and interaction demonstration.""" +def activation_report() -> dict[str, Any]: + """Build a deterministic report that exercises the public API.""" root = Container( - id="theory-root", + id="framework", function="govern", - purpose="bounds conceptual systems", + purpose="organize bounded systems", boundary="porous", - properties={"scale_range": (0.0, 100.0)}, + properties={"scale_range": (0, 100)}, ) - bounded_rule = Container( - id="bounded-rule", + bounded = Container( + id="bounded-system", function="govern", - purpose="constrains nested systems", + purpose="demonstrate nested containment", boundary="semi_permeable", - properties={"scale": 10.0}, + properties={"scale": 1}, ) rules = ContainmentRules() - can_contain = root.can_contain(bounded_rule, rules) - containment_score = rules.compute_containment_score(root, bounded_rule) + containment_score = rules.compute_containment_score(root, bounded) + can_contain = root.can_contain(bounded, rules) if can_contain: - root.add_child(bounded_rule) + root.add_child(bounded) processor = System( id="processor", function="process", - purpose="transforms inputs into bounded outputs", - scale=10.0, + purpose="transform inputs", + scale=1.0, ) store = System( id="store", function="store", - purpose="retains bounded state", - scale=12.0, + purpose="retain state", + scale=1.5, ) emergence = InteractionEmergence() emergence.register_system(processor) emergence.register_system(store) interactions = emergence.discover_interactions(processor, store) - ideals = IdealizationManager() - ideal = ideals.create_form( - form_id="bounded-system", + manager = IdealizationManager() + ideal = manager.create_form( + form_id="container-contract", form_type=IdealizationType.WEBERIAN, - name="Bounded System", + name="Container Contract", real_system=root, ) - relation = ideals.relate(ideal, root) - config = Config() + relation = manager.relate(ideal, root) + config = get_config() return { - "package": "rules-system-bound", - "version": __version__, + "package": CONSOLE_SCRIPT_NAME, + "version": PACKAGE_VERSION, + "status": "runnable", + "exec_path": { + "from_source": SOURCE_EXEC_CMD, + "after_install": INSTALLED_EXEC_CMD, + }, "containment": { "container": root.id, - "contained": bounded_rule.id, + "contained": bounded.id, "can_contain": can_contain, "score": containment_score, - "lineage": [container.id for container in bounded_rule.get_lineage()], + "lineage": [node.id for node in bounded.get_lineage()], }, "interactions": [ { @@ -114,7 +95,7 @@ def build_demo_report() -> dict[str, Any]: "idealization": { "form": ideal.id, "type": ideal.type.value, - "real_system": root.id, + "real": root.id, "co_constitutive": relation.is_co_constitutive, }, "config": { @@ -125,76 +106,61 @@ def build_demo_report() -> dict[str, Any]: } -def _print_report(report: dict[str, Any], as_json: bool) -> None: - if as_json: - print(json.dumps(report, indent=2, sort_keys=True)) - return - - print(f"{report['package']} {report['version']}") +def render_text(report: dict[str, Any]) -> str: + """Render the activation report for humans.""" containment = report["containment"] - print( - "containment: " - f"{containment['container']} -> {containment['contained']} " - f"allowed={containment['can_contain']} score={containment['score']:.2f}" - ) - print(f"interactions: {len(report['interactions'])}") idealization = report["idealization"] - print( - "idealization: " - f"{idealization['form']} ({idealization['type']}) " - f"co_constitutive={idealization['co_constitutive']}" + relation_label = ( + "co-constitutes" if idealization["co_constitutive"] else "relates to" + ) + return "\n".join( + [ + f"{report['package']} {report['version']}", + f"status: {report['status']}", + ( + "containment: " + f"{containment['container']} contains {containment['contained']} = " + f"{'yes' if containment['can_contain'] else 'no'} " + f"(score {containment['score']:.2f})" + ), + f"lineage: {' > '.join(containment['lineage'])}", + f"interactions: {len(report['interactions'])} discovered", + ( + "idealization: " + f"{idealization['form']} ({idealization['type']}) " + f"{relation_label} {idealization['real']}" + ), + f"exec_path: {report['exec_path']['from_source']}", + ] ) - - -def _print_activation_report(report: dict[str, Any], as_json: bool) -> None: - if as_json: - print(json.dumps(report, indent=2, sort_keys=True)) - return - - package = report["package"] - surface = report["release_surface"] - print(f"{package['name']} {package['version']}") - print(f"live_url: {surface['live_url']}") - print(f"installable_package: {surface['installable_package']}") - print(f"runnable_release: {surface['runnable_release']}") - print(f"repo_exec_path: {surface['repo_exec_path']}") - print(f"activation_verdict: {report['activation_verdict']}") def build_parser() -> argparse.ArgumentParser: - """Build the command parser.""" + """Create the CLI argument parser.""" parser = argparse.ArgumentParser( prog="rules-system-bound", - description="Run activation checks and demonstrations for rules-system-bound.", + description="Run the Living Container Framework activation smoke path.", + ) + parser.add_argument( + "--json", + action="store_true", + help="emit machine-readable activation evidence", + ) + parser.add_argument( + "--version", + action="version", + version=f"%(prog)s {PACKAGE_VERSION}", ) - subparsers = parser.add_subparsers(dest="command") - - demo = subparsers.add_parser("demo", help="run a deterministic package demonstration") - demo.add_argument("--json", action="store_true", help="emit JSON") - - audit = subparsers.add_parser("audit", help="print activation audit evidence") - audit.add_argument("--json", action="store_true", help="emit JSON") - - subparsers.add_parser("version", help="print the package version") return parser def main(argv: Sequence[str] | None = None) -> int: - """Run the CLI.""" + """Run the activation smoke path.""" parser = build_parser() args = parser.parse_args(argv) - - if args.command == "version": - print(__version__) - return 0 - - if args.command == "audit": - _print_activation_report(build_activation_report(), args.json) - return 0 - - if args.command in {None, "demo"}: - _print_report(build_demo_report(), getattr(args, "json", False)) - return 0 - - parser.error(f"unknown command: {args.command}") - return 2 + report = activation_report() + if args.json: + print(json.dumps(report, indent=2, sort_keys=True)) + else: + print(render_text(report)) + return 0 diff --git a/src/rules_system_bound/config.py b/src/rules_system_bound/config.py index 3e8b160..5d10cd5 100644 --- a/src/rules_system_bound/config.py +++ b/src/rules_system_bound/config.py @@ -26,7 +26,7 @@ def _coerce_env_value(value: str, default: Any) -> Any: - """Coerce environment strings to the default value's type.""" + """Coerce environment strings to the matching default value type.""" if isinstance(default, bool): normalized = value.strip().lower() if normalized in {"1", "true", "yes", "on"}: diff --git a/tests/test_cli.py b/tests/test_cli.py deleted file mode 100644 index d07f560..0000000 --- a/tests/test_cli.py +++ /dev/null @@ -1,48 +0,0 @@ -"""Tests for the activation command line interface.""" - -import json - -from rules_system_bound.cli import build_activation_report, build_demo_report, main - - -def test_activation_report_documents_release_surface(): - """Activation report names the documented live and runnable surfaces.""" - report = build_activation_report() - - assert report["release_surface"]["live_url"].endswith("/rules-system-bound") - assert "pip install" in report["release_surface"]["installable_package"] - assert report["release_surface"]["runnable_release"] == "rules-system-bound demo --json" - assert report["release_surface"]["repo_exec_path"].startswith("PYTHONPATH=src") - assert report["source_issue"] == "organvm-i-theoria/rules-system-bound#2" - - -def test_demo_report_exercises_core_package(): - """Demo report runs containment, interaction, and idealization paths.""" - report = build_demo_report() - - assert report["containment"]["can_contain"] is True - assert report["containment"]["score"] == 1.0 - assert report["containment"]["lineage"] == ["bounded-rule", "theory-root"] - assert {interaction["type"] for interaction in report["interactions"]} == { - "boundary_exchange", - "function_coupling", - "scale_resonance", - } - assert report["idealization"]["co_constitutive"] is True - - -def test_cli_audit_json_output(capsys): - """CLI emits machine-readable audit evidence.""" - exit_code = main(["audit", "--json"]) - - assert exit_code == 0 - payload = json.loads(capsys.readouterr().out) - assert payload["activation_verdict"] == "ship-soon evidence complete" - - -def test_cli_demo_is_default(capsys): - """The package is runnable with no subcommand.""" - exit_code = main([]) - - assert exit_code == 0 - assert "containment:" in capsys.readouterr().out diff --git a/tests/test_core.py b/tests/test_core.py index bf56ec1..0d7a16f 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -202,41 +202,54 @@ def test_config_from_dict(self): assert config.container_function == "custom_func" assert config.domain_family == "social" + def test_config_from_env_preserves_types(self, monkeypatch): + """Environment values are coerced into config field types.""" + from rules_system_bound.config import Config + monkeypatch.setenv("CONTAINMENT_FUNCTION_WEIGHT", "0.7") + monkeypatch.setenv("LEVEL_NAMES_EMERGE", "false") + + config = Config.from_env() + + assert config.containment_function_weight == 0.7 + assert config.level_names_emerge is False + class TestActivationCli: """Tests for the documented activation smoke path.""" def test_activation_report_exercises_public_api(self): """Activation report provides deterministic runnable evidence.""" - from rules_system_bound.cli import build_demo_report + from rules_system_bound.cli import activation_report - report = build_demo_report() + report = activation_report() assert report["package"] == "rules-system-bound" + assert report["status"] == "runnable" assert report["containment"]["can_contain"] is True - assert report["containment"]["lineage"] == ["bounded-rule", "theory-root"] + assert report["containment"]["lineage"] == ["bounded-system", "framework"] assert len(report["interactions"]) == 3 assert report["idealization"]["co_constitutive"] is True def test_cli_json_output(self, capsys): """CLI emits machine-readable activation evidence.""" from rules_system_bound.cli import main - import json - exit_code = main(["demo", "--json"]) + exit_code = main(["--json"]) output = capsys.readouterr().out report = json.loads(output) assert exit_code == 0 + assert report["exec_path"]["after_install"] == "rules-system-bound --json" assert report["containment"]["score"] == 1.0 - def test_config_from_env_preserves_types(self, monkeypatch): - """Environment values are coerced into config field types.""" - from rules_system_bound.config import Config - monkeypatch.setenv("CONTAINMENT_FUNCTION_WEIGHT", "0.7") - monkeypatch.setenv("LEVEL_NAMES_EMERGE", "false") + def test_render_text_respects_co_constitutive_flag(self): + """Human output reflects the relation flag in the report.""" + from rules_system_bound.cli import activation_report, render_text - config = Config.from_env() + report = activation_report() + report["idealization"]["co_constitutive"] = False - assert config.containment_function_weight == 0.7 - assert config.level_names_emerge is False + output = render_text(report) + + assert "relates to framework" in output + assert "co-constitutes framework" not in output