From 88a0604fb7d21e5b3d965bd425bb31d1b34cd0e6 Mon Sep 17 00:00:00 2001 From: Mopati Ramaologa <102808043+Mopati123@users.noreply.github.com> Date: Tue, 1 Sep 2026 16:36:41 +0200 Subject: [PATCH 01/10] feat(developer-os): add admission-only end-to-end rehearsal v4 --- repo_intelligence/kernel_harness.py | 35 ++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/repo_intelligence/kernel_harness.py b/repo_intelligence/kernel_harness.py index 53e286f..60a3a8f 100644 --- a/repo_intelligence/kernel_harness.py +++ b/repo_intelligence/kernel_harness.py @@ -1,13 +1,14 @@ -"""Cross-repository Governed Developer OS harness v3. +"""Cross-repository Governed Developer OS harness v4. -This harness invokes the certified kernel-side Agentic Runner as a separate -process. It pins the kernel repository to an exact commit before invocation. -Default mode is admission-only; external effects require explicit execute=True. +The harness invokes the certified kernel-side Agentic Runner as a separate +process, pins the kernel checkout to an exact commit, and defaults to +admission-only execution. """ from __future__ import annotations import hashlib import json +import os import subprocess import tempfile from pathlib import Path @@ -56,11 +57,20 @@ def verify_kernel_checkout( return root +def _resolve_python(root:Path,python_executable:str|None)->str: + if python_executable: + return python_executable + candidate=root/".venv"/"bin"/"python" + if candidate.is_file(): + return str(candidate) + return "python" + + def invoke_kernel_binding( binding:dict, *, kernel_root:str|Path, - python_executable:str="python", + python_executable:str|None=None, execute:bool=False, trace_dir:str|Path|None=None, timeout_seconds:int=60, @@ -79,8 +89,9 @@ def invoke_kernel_binding( encoding="utf-8", ) + python_cmd=_resolve_python(root,python_executable) cmd=[ - python_executable, + python_cmd, "-m", "hpl.runtime.agentic_runner", str(binding_path), @@ -92,9 +103,11 @@ def invoke_kernel_binding( if execute: cmd.append("--execute") - env=None - # The caller owns environment configuration for OpenHands/HPL. We avoid - # injecting credentials or service endpoints here. + env=os.environ.copy() + src=str((root/"src").resolve()) + current=env.get("PYTHONPATH","") + env["PYTHONPATH"]=src if not current else src+os.pathsep+current + result=subprocess.run( cmd, cwd=root, @@ -106,14 +119,14 @@ def invoke_kernel_binding( ) if not result_path.is_file(): raise KernelHarnessError( - f"kernel runner produced no result (exit={result.returncode})" + f"kernel runner produced no result (exit={result.returncode}): {result.stderr.strip()}" ) payload=json.loads(result_path.read_text(encoding="utf-8")) if not isinstance(payload,dict): raise KernelHarnessError("kernel runner result must be an object") core={ - "schema_version":"1.0", + "schema_version":"1.1", "authority_semantics":"kernel_runner_separate_process", "execution_requested":bool(execute), "binding_sha256":binding["binding_sha256"], From 39c03a68516c9288cc568277bde2aa17368393ba Mon Sep 17 00:00:00 2001 From: Mopati Ramaologa <102808043+Mopati123@users.noreply.github.com> Date: Tue, 1 Sep 2026 16:36:46 +0200 Subject: [PATCH 02/10] feat(developer-os): add admission-only end-to-end rehearsal v4 --- repo_intelligence/rehearsal.py | 72 ++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 repo_intelligence/rehearsal.py diff --git a/repo_intelligence/rehearsal.py b/repo_intelligence/rehearsal.py new file mode 100644 index 0000000..9b776c2 --- /dev/null +++ b/repo_intelligence/rehearsal.py @@ -0,0 +1,72 @@ +"""Admission-only end-to-end Developer OS rehearsal v4.""" +from __future__ import annotations + +import hashlib +import json +from pathlib import Path + +from .developer_os import build_developer_plan +from .graph import build_repository_graph +from .hpl_binding import build_repo_read_binding +from .impact import analyze_change_impact +from .kernel_harness import invoke_kernel_binding + + +def _canon(v:object)->str: + return json.dumps(v,sort_keys=True,separators=(",",":"),ensure_ascii=False) + + +def _sha(v:object)->str: + return "sha256:"+hashlib.sha256(_canon(v).encode("utf-8")).hexdigest() + + +def rehearse_admission( + *, + target_root:str|Path, + changed_paths:list[str], + change_request:str, + inspect_path:str, + conversation_id:str, + kernel_root:str|Path, + impact_depth:int=3, +)->dict: + graph=build_repository_graph(target_root) + impact=analyze_change_impact(graph,changed_paths,max_depth=impact_depth) + plan=build_developer_plan(graph,impact,change_request) + binding=build_repo_read_binding( + plan, + conversation_id=conversation_id, + path=inspect_path, + ) + harness=invoke_kernel_binding( + binding, + kernel_root=kernel_root, + execute=False, + ) + + admission=harness.get("kernel_result",{}).get("admission",{}) + admitted=isinstance(admission,dict) and admission.get("status")=="admitted" + runtime=harness.get("kernel_result",{}).get("runtime") + if runtime is not None: + raise RuntimeError("admission-only rehearsal unexpectedly produced runtime execution") + + core={ + "schema_version":"1.0", + "mode":"admission_only", + "execution_requested":False, + "graph_sha256":graph["graph_sha256"], + "impact_sha256":impact["impact_sha256"], + "developer_plan_sha256":plan["plan_sha256"], + "binding_sha256":binding["binding_sha256"], + "kernel_harness_receipt_sha256":harness["harness_receipt_sha256"], + "kernel_head":harness["kernel_head"], + "admitted":admitted, + "execution_token_present":bool( + isinstance(admission,dict) + and isinstance(admission.get("plan"),dict) + and isinstance(admission["plan"].get("execution_token"),dict) + ), + "runtime_executed":False, + } + core["rehearsal_sha256"]=_sha(core) + return core From 00c90a2f7d83e1a245e4fe7e65e63b5c5eafad91 Mon Sep 17 00:00:00 2001 From: Mopati Ramaologa <102808043+Mopati123@users.noreply.github.com> Date: Tue, 1 Sep 2026 16:36:50 +0200 Subject: [PATCH 03/10] feat(developer-os): add admission-only end-to-end rehearsal v4 --- tests/test_kernel_harness.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/test_kernel_harness.py b/tests/test_kernel_harness.py index ab6b587..7989f6a 100644 --- a/tests/test_kernel_harness.py +++ b/tests/test_kernel_harness.py @@ -1,6 +1,7 @@ from pathlib import Path from unittest import mock import json +import os from repo_intelligence.kernel_harness import ( CERTIFIED_KERNEL_RUNNER_HEAD, @@ -22,10 +23,14 @@ def _binding(): } -def test_verify_kernel_checkout_requires_exact_head(tmp_path:Path): +def _tree(tmp_path:Path): (tmp_path/".git").mkdir() (tmp_path/"src"/"hpl"/"runtime").mkdir(parents=True) (tmp_path/"src"/"hpl"/"runtime"/"agentic_runner.py").write_text("x=1\n",encoding="utf-8") + + +def test_verify_kernel_checkout_requires_exact_head(tmp_path:Path): + _tree(tmp_path) ok=mock.Mock(returncode=0,stdout=CERTIFIED_KERNEL_RUNNER_HEAD+"\n") with mock.patch("repo_intelligence.kernel_harness.subprocess.run",return_value=ok): assert verify_kernel_checkout(tmp_path)==tmp_path.resolve() @@ -45,14 +50,11 @@ def test_verify_kernel_checkout_refuses_wrong_head(tmp_path:Path): raise AssertionError("expected KernelHarnessError") -def test_harness_defaults_to_admission_only(tmp_path:Path): - (tmp_path/".git").mkdir() - (tmp_path/"src"/"hpl"/"runtime").mkdir(parents=True) - (tmp_path/"src"/"hpl"/"runtime"/"agentic_runner.py").write_text("x=1\n",encoding="utf-8") - +def test_harness_defaults_to_admission_only_and_sets_kernel_pythonpath(tmp_path:Path): + _tree(tmp_path) calls=[] def fake_run(cmd,**kwargs): - calls.append(cmd) + calls.append((cmd,kwargs)) if cmd[:3]==["git","rev-parse","HEAD"]: return mock.Mock(returncode=0,stdout=CERTIFIED_KERNEL_RUNNER_HEAD+"\n",stderr="") out=Path(cmd[cmd.index("--out")+1]) @@ -62,17 +64,15 @@ def fake_run(cmd,**kwargs): with mock.patch("repo_intelligence.kernel_harness.subprocess.run",side_effect=fake_run): receipt=invoke_kernel_binding(_binding(),kernel_root=tmp_path) - runner_cmd=calls[1] + runner_cmd,kwargs=calls[1] assert "--execute" not in runner_cmd assert receipt["execution_requested"] is False assert receipt["kernel_result"]["runtime"] is None + assert kwargs["env"]["PYTHONPATH"].split(os.pathsep)[0]==str((tmp_path/"src").resolve()) def test_harness_execute_is_explicit(tmp_path:Path): - (tmp_path/".git").mkdir() - (tmp_path/"src"/"hpl"/"runtime").mkdir(parents=True) - (tmp_path/"src"/"hpl"/"runtime"/"agentic_runner.py").write_text("x=1\n",encoding="utf-8") - + _tree(tmp_path) calls=[] def fake_run(cmd,**kwargs): calls.append(cmd) From 0be7c79d3f528910e5b1021cec3b7528017bbcda Mon Sep 17 00:00:00 2001 From: Mopati Ramaologa <102808043+Mopati123@users.noreply.github.com> Date: Tue, 1 Sep 2026 16:36:55 +0200 Subject: [PATCH 04/10] feat(developer-os): add admission-only end-to-end rehearsal v4 --- tests/test_admission_rehearsal.py | 60 +++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 tests/test_admission_rehearsal.py diff --git a/tests/test_admission_rehearsal.py b/tests/test_admission_rehearsal.py new file mode 100644 index 0000000..eaaea8b --- /dev/null +++ b/tests/test_admission_rehearsal.py @@ -0,0 +1,60 @@ +from pathlib import Path +from unittest import mock + +from repo_intelligence.rehearsal import rehearse_admission + + +def test_admission_rehearsal_composes_full_chain_without_runtime(tmp_path:Path): + target=tmp_path/"target" + target.mkdir() + (target/"README.md").write_text("# target\n",encoding="utf-8") + + fake={ + "schema_version":"1.1", + "execution_requested":False, + "binding_sha256":"sha256:"+"a"*64, + "kernel_head":"a5d2d913e41fd9a80212825921d0919fd8320b3b", + "kernel_result":{ + "admission":{ + "status":"admitted", + "plan":{"execution_token":{"token_id":"sha256:test"}}, + }, + "runtime":None, + }, + "harness_receipt_sha256":"sha256:"+"b"*64, + } + with mock.patch("repo_intelligence.rehearsal.invoke_kernel_binding",return_value=fake) as invoke: + receipt=rehearse_admission( + target_root=target, + changed_paths=["README.md"], + change_request="Inspect README impact", + inspect_path="README.md", + conversation_id="123e4567-e89b-12d3-a456-426614174000", + kernel_root=tmp_path/"kernel", + ) + + assert invoke.call_args.kwargs["execute"] is False + assert receipt["admitted"] is True + assert receipt["execution_token_present"] is True + assert receipt["runtime_executed"] is False + assert receipt["rehearsal_sha256"].startswith("sha256:") + + +def test_rehearsal_refuses_inspect_path_outside_scope(tmp_path:Path): + target=tmp_path/"target" + target.mkdir() + (target/"README.md").write_text("# target\n",encoding="utf-8") + (target/"OTHER.md").write_text("# other\n",encoding="utf-8") + try: + rehearse_admission( + target_root=target, + changed_paths=["README.md"], + change_request="Inspect README impact", + inspect_path="OTHER.md", + conversation_id="123e4567-e89b-12d3-a456-426614174000", + kernel_root=tmp_path/"kernel", + ) + except ValueError: + pass + else: + raise AssertionError("expected ValueError") From bf30b154e1da099d2415d120552afaaa5fcb0018 Mon Sep 17 00:00:00 2001 From: Mopati Ramaologa <102808043+Mopati123@users.noreply.github.com> Date: Tue, 1 Sep 2026 16:37:00 +0200 Subject: [PATCH 05/10] feat(developer-os): add admission-only end-to-end rehearsal v4 --- ...NED_DEVELOPER_OS_ADMISSION_REHEARSAL_V4.md | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 docs/GOVERNED_DEVELOPER_OS_ADMISSION_REHEARSAL_V4.md diff --git a/docs/GOVERNED_DEVELOPER_OS_ADMISSION_REHEARSAL_V4.md b/docs/GOVERNED_DEVELOPER_OS_ADMISSION_REHEARSAL_V4.md new file mode 100644 index 0000000..3056708 --- /dev/null +++ b/docs/GOVERNED_DEVELOPER_OS_ADMISSION_REHEARSAL_V4.md @@ -0,0 +1,31 @@ +# Governed Developer OS admission rehearsal v4 + +Phase N v4 adds a single admission-only rehearsal that composes the entire +non-mutating control path: + +```text +target repository + -> repository graph + -> change impact + -> Developer OS plan + -> bounded repo.read binding + -> pinned kernel harness + -> HPL AgenticAdmissionPolicy + -> scheduler admission + -> ExecutionPlan + ExecutionToken + -> STOP +``` + +The rehearsal requires `execute=False` and refuses any unexpected runtime +result. Its output records deterministic hashes for the repository graph, impact, +developer plan, binding, kernel harness receipt, and rehearsal itself. + +The kernel harness v4 also prepends the pinned kernel's `src/` directory to +`PYTHONPATH` and prefers `/.venv/bin/python` when present. This makes +the local cross-repository invocation executable without assuming the kernel is +installed into the Developer OS Python environment. + +CI tests the composed contract with the kernel subprocess mocked. A real local +rehearsal against the exact certified kernel checkout is a separate operational +proof and still performs no OpenHands network effect because the runner remains +admission-only. From 51de84e64cf18df587cf773ae690caa30acc1820 Mon Sep 17 00:00:00 2001 From: Mopati Ramaologa <102808043+Mopati123@users.noreply.github.com> Date: Tue, 1 Sep 2026 16:37:06 +0200 Subject: [PATCH 06/10] feat(developer-os): add admission-only end-to-end rehearsal v4 --- repo_intelligence/cli.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/repo_intelligence/cli.py b/repo_intelligence/cli.py index 70d69a9..93103a8 100644 --- a/repo_intelligence/cli.py +++ b/repo_intelligence/cli.py @@ -9,6 +9,7 @@ from .developer_os import build_developer_plan from .hpl_binding import build_repo_read_binding, build_test_execute_binding from .kernel_harness import invoke_kernel_binding +from .rehearsal import rehearse_admission def _write(path:str,data:dict)->None: @@ -62,6 +63,16 @@ def main()->None: k.add_argument("--trace-dir") k.add_argument("--out",default="kernel-harness-receipt.json") + r=sub.add_parser("rehearse-admission") + r.add_argument("target_root") + r.add_argument("changed",nargs="+") + r.add_argument("--change-request",required=True) + r.add_argument("--inspect-path",required=True) + r.add_argument("--conversation-id",required=True) + r.add_argument("--kernel-root",required=True) + r.add_argument("--depth",type=int,default=3) + r.add_argument("--out",default="developer-os-admission-rehearsal.json") + a=p.parse_args() if a.cmd=="graph": @@ -87,7 +98,7 @@ def main()->None: elif a.cmd=="hpl-test-binding": plan=json.loads(Path(a.developer_plan).read_text(encoding="utf-8")) data=build_test_execute_binding(plan,workspace=a.workspace,test_path=a.test_path) - else: + elif a.cmd=="kernel-run": binding=json.loads(Path(a.binding).read_text(encoding="utf-8")) data=invoke_kernel_binding( binding, @@ -95,6 +106,16 @@ def main()->None: execute=a.execute, trace_dir=a.trace_dir, ) + else: + data=rehearse_admission( + target_root=a.target_root, + changed_paths=a.changed, + change_request=a.change_request, + inspect_path=a.inspect_path, + conversation_id=a.conversation_id, + kernel_root=a.kernel_root, + impact_depth=a.depth, + ) _write(a.out,data) From a5e456d58dc72ef4abd9c5c080a6251aa041c195 Mon Sep 17 00:00:00 2001 From: Mopati Ramaologa <102808043+Mopati123@users.noreply.github.com> Date: Tue, 1 Sep 2026 16:37:11 +0200 Subject: [PATCH 07/10] feat(developer-os): add admission-only end-to-end rehearsal v4 --- repo_intelligence/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/repo_intelligence/__init__.py b/repo_intelligence/__init__.py index d6dfba5..ab7b42c 100644 --- a/repo_intelligence/__init__.py +++ b/repo_intelligence/__init__.py @@ -7,6 +7,7 @@ from .developer_os import build_developer_plan, reconcile_developer_run from .hpl_binding import build_repo_patch_binding, build_repo_read_binding, build_test_execute_binding from .kernel_harness import invoke_kernel_binding, verify_kernel_checkout +from .rehearsal import rehearse_admission __all__=[ "build_repository_graph", @@ -19,6 +20,7 @@ "build_repo_patch_binding", "invoke_kernel_binding", "verify_kernel_checkout", + "rehearse_admission", "load_architecture_contract", "validate_architecture_contract", ] From 72c25f2214e76f0bffaf55c658fd81250f395b3e Mon Sep 17 00:00:00 2001 From: Mopati Ramaologa <102808043+Mopati123@users.noreply.github.com> Date: Tue, 1 Sep 2026 16:37:20 +0200 Subject: [PATCH 08/10] feat(developer-os): add admission-only end-to-end rehearsal v4 --- .github/workflows/repository-intelligence.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/repository-intelligence.yml b/.github/workflows/repository-intelligence.yml index 96eb865..b413217 100644 --- a/.github/workflows/repository-intelligence.yml +++ b/.github/workflows/repository-intelligence.yml @@ -2,7 +2,7 @@ name: Repository Intelligence CI on: pull_request: push: - branches: ["feat/repository-intelligence-v1", "feat/repository-intelligence-v2", "feat/repository-intelligence-v3", "feat/governed-developer-os-v1", "feat/governed-developer-os-v2", "feat/governed-developer-os-v3"] + branches: ["feat/repository-intelligence-v1", "feat/repository-intelligence-v2", "feat/repository-intelligence-v3", "feat/governed-developer-os-v1", "feat/governed-developer-os-v2", "feat/governed-developer-os-v3", "feat/governed-developer-os-v4"] permissions: contents: read jobs: From 64833452df6c0dcae78614cd45b347cb2e68e29e Mon Sep 17 00:00:00 2001 From: Mopati Ramaologa <102808043+Mopati123@users.noreply.github.com> Date: Tue, 1 Sep 2026 16:37:57 +0200 Subject: [PATCH 09/10] docs(developer-os): document admission-only rehearsal v4 --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index ea1ae9e..c86dcb1 100644 --- a/README.md +++ b/README.md @@ -75,3 +75,18 @@ repo-intel kernel-run hpl-read-binding.json \ The harness pins the kernel checkout to the certified Developer OS Agentic Runner head and defaults to admission-only. External effects require explicit `--execute`, after which HPL admission still remains mandatory. + + +## Admission-only end-to-end rehearsal v4 + +```bash +repo-intel rehearse-admission /path/to/target-repo README.md \ + --change-request "Inspect README impact" \ + --inspect-path README.md \ + --conversation-id 123e4567-e89b-12d3-a456-426614174000 \ + --kernel-root /path/to/apex-hpl-governed-kernel \ + --out developer-os-admission-rehearsal.json +``` + +This composes repository intelligence through HPL scheduler admission and then +stops. It cannot execute an OpenHands effect. From 94584263636a49163e94469eefe3c75a0f731508 Mon Sep 17 00:00:00 2001 From: Mopati Ramaologa <102808043+Mopati123@users.noreply.github.com> Date: Tue, 1 Sep 2026 16:38:00 +0200 Subject: [PATCH 10/10] docs(developer-os): document admission-only rehearsal v4 --- docs/GOVERNED_DEVELOPER_OS_ADMISSION_REHEARSAL_V4.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/GOVERNED_DEVELOPER_OS_ADMISSION_REHEARSAL_V4.md b/docs/GOVERNED_DEVELOPER_OS_ADMISSION_REHEARSAL_V4.md index 3056708..463d6b2 100644 --- a/docs/GOVERNED_DEVELOPER_OS_ADMISSION_REHEARSAL_V4.md +++ b/docs/GOVERNED_DEVELOPER_OS_ADMISSION_REHEARSAL_V4.md @@ -16,9 +16,10 @@ target repository -> STOP ``` -The rehearsal requires `execute=False` and refuses any unexpected runtime -result. Its output records deterministic hashes for the repository graph, impact, -developer plan, binding, kernel harness receipt, and rehearsal itself. +The rehearsal always invokes the kernel harness with `execute=False` and +refuses any unexpected runtime result. Its output records deterministic hashes +for the repository graph, impact, developer plan, binding, kernel harness +receipt, and rehearsal receipt. The kernel harness v4 also prepends the pinned kernel's `src/` directory to `PYTHONPATH` and prefers `/.venv/bin/python` when present. This makes