mirror of
https://github.com/razzant/ouroboros.git
synced 2026-10-03 04:07:04 +00:00
headless.py (1573 at tip) gives up its two ledger-assigned leaves again: ouroboros/headless_status.py (50, 11 symbols) and ouroboros/workspace_patch_capture.py (668, 19 symbols). All 30 spans are byte-identical between the reference leaves and git show HEAD bytes — the hardened transplant --check (mandatory byte gate, undeclared-top-level check,def681bd) is green on every symbol of both leaves. The facade (947) replays the oracle's exact edit script over tip bytes: its only divergence from the reference facade is genuine upstream residue drift (child_ref promotion machinery, import changes), verified hunk by hunk. Test splits per the ledger, upstream bytes as truth: - test_headless_cli.py 2824 -> 462 + five themed siblings + shared fixtures; 93 test functions preserved exactly (lossless set equality), one adapted span kept (the _PATCH_MAX_UNTRACKED_FILE_BYTES monkeypatch retargeted to the new leaf, ledger row 739's own adaptation); nine oracle spans carrying OTHER domains' v7 spellings reverse-mapped to upstream signatures keyed to git show HEAD (registry._run_shell_safety_check string form, tools.core _repo_read, queue.init 3-arg, queue.QUEUE_SNAPSHOT_PATH). - test_workspace_executor.py 1995 -> 541 + three siblings + shared builder; two reference spans byte-falsified by upstream drift (06339bb7readiness truth,a849c9a6probe uncertainty) re-emitted from tip bytes and recorded in docs/v7next/LEDGER_CORRECTIONS.md. - test_agent_task_pipeline.py 1658 -> 1515: only the five ledger-assigned _store_task_result rows carved into tests/test_store_task_result.py; the other siblings belong to their own lanes. Thirteen post-cutoff upstream tests have no ledger rows; placed by the split's theme rule (task_api x4, task_artifacts x1, docker x6, services x2), disclosed in LEDGER_CORRECTIONS for F5 row-minting. Pins and mirrors: test_headless_extraction.py transplanted with the tool_module_inventory clause reduced under an oracle-SHA note (that leaf belongs to the tools lane); conftest serial table gains the executor family; the process-custody Popen allowlist row moves headless.py -> workspace_patch_capture.py with the oracle's justification. All 14 non-split D17 runtime modules re-proven zero-v7-delta (task_results.py included: upstream-hot drift stands, no ledger split assigned). size-ratchet manifest regenerated with the official tool (three test giants leave GIANT_PATHS, no new band entries); --check green. ruff F clean. 135/105/244/113 tests green in 4-var isolation; HEAD held after every run. (cherry picked from commit 8dac8303006085bfdb636bacbfc402d6905fae7c)
123 lines
5 KiB
Python
123 lines
5 KiB
Python
"""Structural contracts for the semantic-no-op headless extraction."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import ast
|
|
import pathlib
|
|
|
|
from ouroboros import headless, headless_status, workspace_patch_capture
|
|
|
|
|
|
REPO = pathlib.Path(__file__).parents[1]
|
|
|
|
_LEAVES = (headless_status, workspace_patch_capture)
|
|
|
|
_MOVED_OWNERS = {
|
|
"ARTIFACT_STATUS_FAILED": headless_status,
|
|
"ARTIFACT_STATUS_FINALIZING": headless_status,
|
|
"ARTIFACT_STATUS_MISSING": headless_status,
|
|
"ARTIFACT_STATUS_PENDING": headless_status,
|
|
"ARTIFACT_STATUS_READY": headless_status,
|
|
"ARTIFACT_STATUS_READY_NO_CHANGES": headless_status,
|
|
"ARTIFACT_STATUS_READY_WITH_CHANGES": headless_status,
|
|
"ARTIFACT_TERMINAL_STATUSES": headless_status,
|
|
"_ARTIFACT_LIFECYCLE_FIELDS": headless_status,
|
|
"_FINAL_STATUSES": headless_status,
|
|
"_LOCAL_READONLY_SUBAGENT_MODE": headless_status,
|
|
"SCRATCH_MANIFEST_NAME": workspace_patch_capture,
|
|
"_GIT_UNBORN_HEAD": workspace_patch_capture,
|
|
"_acting_constraint_from_task": workspace_patch_capture,
|
|
"_append_git_output": workspace_patch_capture,
|
|
"_empty_patch_manifest": workspace_patch_capture,
|
|
"_git_bytes": workspace_patch_capture,
|
|
"_git_empty_tree_oid": workspace_patch_capture,
|
|
"_git_path_list": workspace_patch_capture,
|
|
"_git_stdout": workspace_patch_capture,
|
|
"_head_reflog_exists": workspace_patch_capture,
|
|
"_looks_like_git_oid": workspace_patch_capture,
|
|
"_preflight_head_from_task": workspace_patch_capture,
|
|
"_preflight_head_present": workspace_patch_capture,
|
|
"_untracked_blob_exclude_reason": workspace_patch_capture,
|
|
"_workspace_patch_base": workspace_patch_capture,
|
|
"_write_patch_separator": workspace_patch_capture,
|
|
"build_workspace_patch": workspace_patch_capture,
|
|
"untracked_capture_veto_reason": workspace_patch_capture,
|
|
"write_workspace_patch_artifacts": workspace_patch_capture,
|
|
}
|
|
|
|
|
|
def test_headless_leaves_are_non_catalog_owners_without_headless_backedges():
|
|
for module in (headless, *_LEAVES):
|
|
source_path = pathlib.Path(module.__file__)
|
|
tree = ast.parse(source_path.read_text(encoding="utf-8"))
|
|
assert not any(
|
|
isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
|
|
and node.name == "get_tools"
|
|
for node in tree.body
|
|
)
|
|
for module in _LEAVES:
|
|
tree = ast.parse(pathlib.Path(module.__file__).read_text(encoding="utf-8"))
|
|
assert not any(
|
|
isinstance(node, ast.ImportFrom) and node.module == "ouroboros.headless"
|
|
for node in ast.walk(tree)
|
|
)
|
|
assert not any(
|
|
isinstance(node, ast.Import)
|
|
and any(alias.name == "ouroboros.headless" for alias in node.names)
|
|
for node in ast.walk(tree)
|
|
)
|
|
|
|
# v7next transplant note: the reference test (ouroboros_v7_wip @ 9f691656)
|
|
# additionally proves the three modules stay out of the frozen tool-module
|
|
# inventory via ouroboros.tool_module_inventory; that leaf belongs to the
|
|
# tools domain and is not on this integration branch yet — the clause
|
|
# returns with its lane. The static guarantee it rested on is kept above:
|
|
# none of the three modules defines get_tools, so no catalog can adopt them.
|
|
|
|
|
|
def test_headless_public_export_list_is_unchanged():
|
|
"""``__all__`` is the module's declared contract; the extraction moved owners,
|
|
never the surface, so every published name still resolves on ``headless``."""
|
|
assert headless.__all__ == [
|
|
"ARTIFACT_STATUS_FAILED",
|
|
"ARTIFACT_STATUS_FINALIZING",
|
|
"ARTIFACT_STATUS_PENDING",
|
|
"ARTIFACT_STATUS_READY",
|
|
"build_memory_export",
|
|
"build_workspace_patch",
|
|
"copy_child_task_result",
|
|
"finalize_task_artifacts",
|
|
"task_is_readonly_subagent",
|
|
"prepare_task_drive",
|
|
"prune_headless_task_drives",
|
|
"prune_task_drives",
|
|
"task_artifacts_dir",
|
|
"task_state_dir",
|
|
"write_workspace_patch_artifacts",
|
|
"write_workspace_preflight_artifact",
|
|
]
|
|
for name in headless.__all__:
|
|
assert hasattr(headless, name), name
|
|
|
|
|
|
def test_headless_facade_reexports_every_moved_identity():
|
|
"""``headless`` keeps the exact objects, so the supervisor, the gateway,
|
|
outcomes, task_status, artifacts and the delegation owners see no identity
|
|
change."""
|
|
for name, owner in _MOVED_OWNERS.items():
|
|
assert hasattr(headless, name), name
|
|
assert getattr(headless, name) is getattr(owner, name), name
|
|
owned = {name for module in _LEAVES for name in vars(module)}
|
|
assert set(_MOVED_OWNERS) <= owned
|
|
|
|
|
|
def test_headless_extraction_size_bounds_have_meaningful_headroom():
|
|
counts = {
|
|
module.__name__: len(
|
|
pathlib.Path(module.__file__).read_text(encoding="utf-8").splitlines()
|
|
)
|
|
for module in (headless, *_LEAVES)
|
|
}
|
|
assert counts["ouroboros.headless"] <= 1000
|
|
assert all(count <= 1000 for count in counts.values())
|
|
assert 400 <= counts["ouroboros.workspace_patch_capture"] <= 1000
|