Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c52900e
T020, U-1: the governed host for the governed suites that drive the g…
brettheap Oct 6, 2026
0736158
T021, U-2: the gate console's schemas, each read where its owner keep…
brettheap Oct 6, 2026
c40af91
T022, U-3: the runbook placed from the composed tree, git-ignored, no…
brettheap Oct 6, 2026
ecf0ba9
T021: a host schema the console cannot apply refuses as GateRefused (…
brettheap Oct 6, 2026
8d02a1b
Merge T021's fix (Copilot r4194497045) into T022
brettheap Oct 6, 2026
7a149b7
T022: the placement script's guards held in CI, tests/test_composed_p…
brettheap Oct 6, 2026
d6f4a81
T029, U-9: the composed run, permanent: composed.yml and its openxFac…
brettheap Oct 6, 2026
541852d
T029: judge a pull request's own edits as the landing they would be (…
brettheap Oct 6, 2026
570efda
Merge T022's placement tests (7a149b70, #41) into T029
brettheap Oct 6, 2026
82d9592
T029: an edited pull request body is judged again (Copilot r4195546545)
brettheap Oct 6, 2026
c27c91d
T073: the composed declarations, ARC-Q2 (a): each declared entry runs…
brettheap Oct 6, 2026
b4993d1
T029: 12.5's oracle call takes --chains, as Brett ruled (#656 6016648…
brettheap Oct 6, 2026
2565dac
T073: the rail's and the contracts' open_until, as the holder ruled (…
brettheap Oct 6, 2026
bf8f5b7
Merge T029's newer head (b4993d1f, #44) into T073
brettheap Oct 6, 2026
b09c138
Merge origin/main (c6d15b27, T020 landed as #39) into T073
brettheap Oct 6, 2026
26fe63e
T073: commit the rail block's restore cases, tests/test_declared_rail…
brettheap Oct 6, 2026
860ad06
Merge origin/main (e2340bb6) into T073
brettheap Oct 6, 2026
cebf345
T073: the contracts farm leaves out only openDox-spec's opendox-snaps…
brettheap Oct 6, 2026
8179615
Merge origin/main (9720925e) into T073
brettheap Oct 8, 2026
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
442 changes: 442 additions & 0 deletions .github/workflows/composed.yml

Large diffs are not rendered by default.

33 changes: 33 additions & 0 deletions tests/composed_host_pin.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# THE COMPOSED RUN'S HOST: the one openxFactory commit the composed workflow
# checks out (plan 038 task T029, U-9, in openxFactory
# `specs/038-opendox-document-tool-self-maintenance/`; decision N-7a, ruled
# with the plan on openxFactory#656 comment 6013547504).
#
# WHAT READS IT. `.github/workflows/composed.yml`, and nothing else. It checks
# openxFactory out at `commit`, initializes that checkout's `openDox`,
# `openXdox` and `openXwallet` submodules recursively, and runs 12.5's
# governed suites with that checkout's `scripts/` on `PYTHONPATH` (R1Q23 (a)'s
# form; F12.1 runs composed, CF-5). The workflow refuses the file, naming the
# rule, unless all of these hold:
# * `schema_version` is the integer 1, and `kind` is `composed-host-pin`;
# * `commit` is a full 40-character lowercase commit id;
# * no other key is present, and no key is given twice.
# The repository is openxFactory, always: the workflow names it, and this file
# names only the commit.
#
# WHEN IT MOVES. Never on its own: each advance is an openXdox-code pull
# request of its own, so the composed run always tests the host that
# openxFactory's `main` carries (plan 038 plan.md, "The composed workflow's
# openxFactory pin"). It advances after T030, T064 and T075 land in
# openxFactory, and T073 re-runs after each advance.
#
# ITS FIRST VALUE. openxFactory `main`'s head when T029 authored this file,
# read with `git ls-remote` at 2026-10-06T11:56:20Z: `92010d3e`, "Land
# add-factory-mcp-conformance on main as Speckit feature 037, with repairs
# and validator fixes (#1243)".
#
# A CREATED file: no row in openxFactory's `docs/opendox-carve-manifest.yaml`
# (RULED OQ-C).
schema_version: 1
kind: composed-host-pin
commit: 92010d3e67f2c556687e1c3583ed3ca1867f4b8b
113 changes: 110 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1027,15 +1027,21 @@ def _the_hosts_seams_for_the_seam_suites(request):
# * `<farm>/examples/ideation-dashboard/`: a link to each YAML example the
# three owners keep under `examples/ideation-dashboard/`, at the same
# relative path, less openDox's own `opendox-snapshot-*` examples, whose
# kind the family's validator does not serve. Two owners naming one path
# is refused, never resolved.
# kind the family's validator does not serve. Only openDox-spec's are left
# out: an example of that prefix from openxFactory or openXdox-spec is
# linked like any other (T073; Copilot r4201411760 on openXdox-code#46,
# the holder's r4201421102). Two owners naming one path is refused, never
# resolved.
# It is OUTSIDE the checkout, in a temporary directory removed at exit: the
# validator refuses a `contracts/` that links out of its tree (`:157-163`). A
# temporary root inside the checkout (a TMPDIR, or `under`, beneath it) is
# refused before anything is created.
# The reach is read with `sys.path` saved and put back, and it must be the
# composed tree's own.
CONTRACT_EXAMPLE_LEFT_OUT = "opendox-snapshot-"
#: The one owner whose examples of that prefix are left out: openDox-spec,
#: as `carved_reach.MOUNTS` names it.
CONTRACT_EXAMPLE_LEFT_OUT_OWNER = "opendox_spec"


def build_contracts_farm(reach, farm: Path) -> Path:
Expand All @@ -1054,11 +1060,13 @@ def build_contracts_farm(reach, farm: Path) -> Path:
examples = farm / "examples" / "ideation-dashboard"
examples.mkdir(parents=True)
linked: dict[Path, Path] = {}
left_out_from = reach.MOUNTS[CONTRACT_EXAMPLE_LEFT_OUT_OWNER]
for owner in (reach.REPO_ROOT, reach.MOUNTS["opendox_spec"],
reach.MOUNTS["openxdox_spec"]):
base = owner / "examples" / "ideation-dashboard"
for path in sorted(base.rglob("*.yaml")):
if path.name.startswith(CONTRACT_EXAMPLE_LEFT_OUT):
if (owner == left_out_from
and path.name.startswith(CONTRACT_EXAMPLE_LEFT_OUT)):
continue
relative = path.relative_to(base)
if relative in linked:
Expand Down Expand Up @@ -1119,3 +1127,102 @@ def runs_a_local_install(suite: str) -> bool:
fixture stands in."""
return suite == _LAUNCH_SUITE or (
suite in LOCAL_INSTALL_SUITES and openxfactory_host() is not None)


# ---------------------------------------------------------------------------
# THE HOST'S STATUS-EXEMPTION RAIL FOR THE DECLARED RAIL SUITES (plan 038
# T073; ARC-Q2 (a), openxFactory#656 comment 6003918488; R1Q24 (a), comment
# 5850003126).
#
# R1Q24 (a) declared the files that need openxFactory's status-exemption rail,
# which only openxFactory's host registers at openDox's status-exemption seam
# (`opendox.doxbench_packet.register_status_exemption`). In a lone checkout
# nothing registers it, so their cases refuse with
# `StatusExemptionNotRegistered`, which is the declaration's evidence for their
# reason. ARC-Q2 (a) makes them declared integration tests, which the composed
# workflow runs. So, as U-1 registers the governed host above, for the length
# of each test of a file `tests/declared_exclusion.yaml` names under the reason
# `status-exemption-rail`, this registers THE HOST'S RAIL where the run is
# composed, and puts the seam back afterwards. Where the run is not composed it
# registers nothing, and the lone checkout's evidence is unchanged.
#
# THE RAIL IS THE ONE openxFactory'S HOST REGISTERS: the
# `register_status_exemption` row of `opendox_host.seams()`, the table the
# host's process start registers from. It is read off that table rather than
# named here, so a later host pin is followed.
#
# THE LIST IS THE DECLARATION'S, as the root `conftest.py` has already held it
# to its rules: a file gets the rail, or stops getting it, only with its entry.
#
# THE SEAM IS PUT BACK. A rail held before the test is dropped for it. After
# it, a host's rail is registered again, and openDox's own default, an entry
# point's, is not, since the next entry point registers it again, as
# `a_hosts_plane` treats the default profile.
# ---------------------------------------------------------------------------

STATUS_EXEMPTION_RAIL_REASON = "status-exemption-rail"


@functools.cache
def status_exemption_rail_suites() -> frozenset[str]:
"""The test modules the declaration names under the rail's reason."""
import yaml

declaration = yaml.safe_load(
(HERE / "declared_exclusion.yaml").read_text(encoding="utf-8"))
return frozenset(Path(entry["path"]).name
for entry in declaration["entries"]
if STATUS_EXEMPTION_RAIL_REASON in entry["reasons"])


@functools.cache
def openxfactory_status_exemption_rail():
"""openxFactory's status-exemption rail where the run is composed, and
None where it is not: what its host registers at openDox's seam, read off
the host's own seam table."""
host_module = openxfactory_host()
if host_module is None:
return None
saved = list(sys.path)
try:
rails = [what for _, call, what in host_module.seams()
if call == "register_status_exemption"]
finally:
sys.path[:] = saved
_refuse_an_openxdox_from_elsewhere()
if len(rails) != 1:
raise RuntimeError(
f"openxFactory's host seam table names {len(rails)} "
"status-exemption rails, so the rail it registers is not one "
"this harness can register for it")
return rails[0]


@contextlib.contextmanager
def a_hosts_rail(rail):
"""Register `rail` at openDox's status-exemption seam for the length of
the block, then put the seam back as it was, less openDox's default."""
from opendox import doxbench_packet as _packet

previous = getattr(_packet, "_status_exemption_rail", None)
a_hosts = previous is not None and not getattr(
_packet, "_status_exemption_is_default", False)
_packet.unregister_status_exemption()
try:
yield _packet.register_status_exemption(rail)
finally:
_packet.unregister_status_exemption()
if a_hosts:
_packet.register_status_exemption(previous)
Comment thread
brettheap marked this conversation as resolved.


@_pytest.fixture(autouse=True)
def _the_hosts_rail_for_the_declared_rail_suites(request):
rail = (openxfactory_status_exemption_rail()
if request.node.path.name in status_exemption_rail_suites()
else None)
if rail is None:
yield
return
with a_hosts_rail(rail):
yield
29 changes: 26 additions & 3 deletions tests/declared_exclusion.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,23 @@
# emptied list is `count: 0` with no reasons and no entries. The root
# conftest loads it, excludes nothing, and prints that nothing is left out.
#
# EVERY ENTRY IS ALSO A DECLARED INTEGRATION TEST (plan 038 task T073, in
# openxFactory `specs/038-opendox-document-tool-self-maintenance/`; ARC-Q2
# (a), openxFactory#656 comment 6003918488; #1144's F9.1 as batch Q amends
# it). What a lone checkout cannot run runs in this repository's own CI,
# composed with openxFactory: `.github/workflows/composed.yml` runs every
# file below at the ONE openxFactory commit `tests/composed_host_pin.yaml`
# names, in R1Q23 (a)'s form. 12.5's governed suites among them run in its
# governed step, and every other entry runs in its declared step, each file
# alone. So no file here is dropped from both suites. The count is `count`,
# and each entry keeps its reason. This file names that commit by naming the
# pin file, and writes no commit id of its own, so the pin advances (after
# T030, T064 and T075) with no edit here. Read with the paragraph above: in a
# lone checkout each entry stays an open extraction until its reason is
# cleared, and composed it is a declared integration test, by which
# declaration requirement 9 closes for openXdox-code (batch Q). Each reason's
# `open_until` names that composed home, so every lone run prints it.
#
# WHO READS IT.
# * The repository-root `conftest.py`. It derives `collect_ignore` from
# `entries`, so a run that loads it collects the whole suite less these
Expand All @@ -27,6 +44,12 @@
# list cannot hide a failure of any other kind. A file that stops failing
# for its reason turns that test red, and it leaves the list in the pull
# request that clears the reason.
# * `.github/workflows/composed.yml`. Its declared step runs every entry
# that is not one of 12.5's governed suites, composed and each alone, and
# refuses an entry that neither of its two steps runs.
# * `tests/conftest.py`. Where the run is composed, it registers the rail
# openxFactory's host registers for each entry naming
# `status-exemption-rail`, and only for those.
#
# THE RULES.
# * `schema_version` is the integer 1, and `count` is an integer equal to the
Expand Down Expand Up @@ -65,15 +88,15 @@ reasons:
- id: doc_health
reason: "reaches openxFactory's doc_health, which openxFactory packages nowhere and no lone checkout supplies"
ruled: "R1Q6 (d), openxFactory#656 comment 5817152735"
open_until: "the doc_health direction arc (plan 034 T008)"
open_until: "the doc_health direction arc (plan 034 T008); run composed, as a declared integration test, by .github/workflows/composed.yml at the openxFactory commit tests/composed_host_pin.yaml names (ARC-Q2 (a), openxFactory#656 comment 6003918488)"
- id: status-exemption-rail
reason: "needs openxFactory's status-exemption rail, which only openxFactory registers at openDox's status-exemption seam"
ruled: "R1Q24 (a), openxFactory#656 comment 5850003126"
open_until: "the doc_health direction arc (plan 034 T008)"
open_until: "never in a lone checkout: a declared integration test, run composed by .github/workflows/composed.yml at the openxFactory commit tests/composed_host_pin.yaml names (ARC-Q2 (a), openxFactory#656 comment 6003918488)"
- id: openxfactory-contracts
reason: "reads openxFactory's contracts (the contract family's validator, schemas and examples, or its contracts/manifest.yaml) where openxFactory's tree keeps them, which is outside this checkout"
ruled: "R1Q24 (a), openxFactory#656 comment 5850003126"
open_until: "the doc_health direction arc (plan 034 T008)"
open_until: "never in a lone checkout: a declared integration test, run composed by .github/workflows/composed.yml at the openxFactory commit tests/composed_host_pin.yaml names (ARC-Q2 (a), openxFactory#656 comment 6003918488)"

entries:
- {path: tests/test_authoring_agent.py, reasons: [doc_health]}
Expand Down
100 changes: 100 additions & 0 deletions tests/test_declared_rail_registration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
"""The rail registration `tests/conftest.py` makes for the declared rail
suites, held to its word (plan 038 task T073; ARC-Q2 (a), openxFactory#656
comment 6003918488; Copilot r4197793290 on openXdox-code#45).
Comment thread
brettheap marked this conversation as resolved.

Where the run is composed, each test of a file `tests/declared_exclusion.yaml`
names under `status-exemption-rail` runs with the rail openxFactory's host
registers, through `conftest.a_hosts_rail`. Those runs prove the rail is
registered. These cases prove what a composed run cannot see: that the seam is
put back afterwards, so no test after a rail suite meets a rail it did not
register, and no host's rail is lost to one. They use stand-in rails, so they
run in a lone checkout too, inside the required check.

Each case leaves openDox's seam exactly as it found it: `_the_seam_as_found`
records the seam's three globals through `monkeypatch`, which writes them back
at teardown, whatever the case did.
"""

from __future__ import annotations

import pytest
import yaml

from conftest import HERE, a_hosts_rail, status_exemption_rail_suites
from opendox import doxbench_packet


class _Rail:
"""A stand-in rail: the two names a rail must carry, each its own."""

def __init__(self, name: str):
self.name = name

def lifecycle_status(text):
return None

def is_compression_exempt(text):
return False

self.lifecycle_status = lifecycle_status
self.is_compression_exempt = is_compression_exempt


def _answering() -> object:
"""The rail openDox's seam answers with now, read through the name it
hands over (`doxbench_packet.is_compression_exempt`), or None when no
rail is registered."""
if not doxbench_packet.status_exemption_registered():
return None
return doxbench_packet.is_compression_exempt


@pytest.fixture(autouse=True)
def _the_seam_as_found(monkeypatch):
for name in ("_status_exemption_rail", "_status_exemption_is_default",
"_status_exemption_default_read"):
monkeypatch.setattr(doxbench_packet, name, getattr(doxbench_packet, name))
doxbench_packet.unregister_status_exemption()


def test_a_hosts_earlier_rail_is_dropped_for_the_block_and_put_back_after():
earlier, rail = _Rail("earlier"), _Rail("the host's")
doxbench_packet.register_status_exemption(earlier)
with a_hosts_rail(rail):
assert _answering() is rail.is_compression_exempt
assert _answering() is earlier.is_compression_exempt


def test_no_rail_is_left_behind_where_none_was_registered():
rail = _Rail("the host's")
with a_hosts_rail(rail):
assert _answering() is rail.is_compression_exempt
assert _answering() is None


def test_opendoxs_own_default_is_not_put_back():
"""As `a_hosts_plane` treats the default profile: the next entry point
registers the default again, as it does in any process."""
default, rail = _Rail("openDox's default"), _Rail("the host's")
doxbench_packet.register_default_status_exemption(default)
with a_hosts_rail(rail):
assert _answering() is rail.is_compression_exempt
assert _answering() is None


def test_the_seam_is_put_back_when_the_block_fails():
earlier, rail = _Rail("earlier"), _Rail("the host's")
doxbench_packet.register_status_exemption(earlier)
with pytest.raises(RuntimeError, match="the case failed"):

Check warning on line 88 in tests/test_declared_rail_registration.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this exception test to have only one invocation possibly throwing an exception.

See more on https://sonarcloud.io/project/issues?id=opensoft_openXdox-code&issues=AaESCmxz_l81UYI2pFVJ&open=AaESCmxz_l81UYI2pFVJ&pullRequest=45
with a_hosts_rail(rail):
raise RuntimeError("the case failed")
assert _answering() is earlier.is_compression_exempt


def test_the_rail_suites_are_the_declarations_rail_entries():
declaration = yaml.safe_load(
(HERE / "declared_exclusion.yaml").read_text(encoding="utf-8"))
named = {entry["path"].rsplit("/", 1)[-1] for entry in declaration["entries"]
if "status-exemption-rail" in entry["reasons"]}
assert named, "the declaration names no rail file"
assert status_exemption_rail_suites() == frozenset(named)
22 changes: 22 additions & 0 deletions tests/test_host_plane.py
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,28 @@ def test_the_farm_links_the_familys_schemas_and_examples(tmp_path) -> None:
}


def test_the_farm_leaves_out_only_opendox_specs_snapshot_examples(tmp_path) -> None:
"""The `opendox-snapshot-` prefix is left out for openDox-spec's own
examples only (T073; Copilot r4201411760 on #46, the holder's
r4201421102). An example of the same prefix from openxFactory or from
openXdox-spec is linked like any other."""
root = tmp_path / "openxFactory"
_a_tree(root, {
"examples/ideation-dashboard/opendox-snapshot-a.example.yaml": "",
"openXdox/spec/examples/ideation-dashboard/negative/opendox-snapshot-b.negative.yaml": "",
"openDox/spec/examples/ideation-dashboard/opendox-snapshot-c.example.yaml": "",
"openDox/spec/examples/ideation-dashboard/negative/opendox-snapshot-d.negative.yaml": "",
})
farm = tmp_path / "farm"
tests_conftest.build_contracts_farm(_a_reach(root, {}), farm)
assert _links(farm / "examples" / "ideation-dashboard") == {
"opendox-snapshot-a.example.yaml":
root / "examples/ideation-dashboard/opendox-snapshot-a.example.yaml",
"negative/opendox-snapshot-b.negative.yaml":
root / "openXdox/spec/examples/ideation-dashboard/negative/opendox-snapshot-b.negative.yaml",
}


def test_the_farm_refuses_an_example_two_owners_keep(tmp_path) -> None:
root = tmp_path / "openxFactory"
_a_tree(root, {
Expand Down
Loading