Skip to content
Draft
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/repository-intelligence.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
32 changes: 32 additions & 0 deletions docs/GOVERNED_DEVELOPER_OS_ADMISSION_REHEARSAL_V4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 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 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 `<kernel>/.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.
2 changes: 2 additions & 0 deletions repo_intelligence/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -19,6 +20,7 @@
"build_repo_patch_binding",
"invoke_kernel_binding",
"verify_kernel_checkout",
"rehearse_admission",
"load_architecture_contract",
"validate_architecture_contract",
]
23 changes: 22 additions & 1 deletion repo_intelligence/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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":
Expand All @@ -87,14 +98,24 @@ 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,
kernel_root=a.kernel_root,
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)

Expand Down
35 changes: 24 additions & 11 deletions repo_intelligence/kernel_harness.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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),
Expand All @@ -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,
Expand All @@ -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"],
Expand Down
72 changes: 72 additions & 0 deletions repo_intelligence/rehearsal.py
Original file line number Diff line number Diff line change
@@ -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
60 changes: 60 additions & 0 deletions tests/test_admission_rehearsal.py
Original file line number Diff line number Diff line change
@@ -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")
Loading
Loading