Ordering for the eleven follow-ups from the review of #114. They are not independent: several pairs have a hard dependency where doing them the other way round means the second one cannot be verified. This issue is the single place that order lives; the individual issues carry the work.
Five lanes can run at the same time. The rest cannot, and the reason is usually a shared file rather than a shared idea.
Wave 0 - prerequisite
Upstream, on its own schedule: OO-LD/oold-schema#137 merges, oold-schema releases rc.3, rc.3 is vendored here. That chain gates two items below.
Wave 1 - genuinely parallel, no shared files
#128 before #119. No fixture currently makes Resolver fetch anything over HTTP, so the retrieval layer #119 replaces has no test covering it and the swap would be unverifiable.
#125 item 5 and #128 touch the same question from opposite sides: a fixture that resolves a remote @context cannot run under a default of --offline. Whichever lands second has to account for the other.
#123 and #128 both edit docs/maintaining-meta-schemas.md - #123 replaces the hand-run vendoring procedure, #128 renames the remote_context/ fixture it mentions. Different sections, so it should auto-merge, but whichever lands second should re-read the file rather than assume.
#127 is the widest diff in the set: compliance.py (4 sites), instance_checks.py (2), schema_checks.py, roundtrip.py, predicates.py, pipeline.py, pattern_lint.py, generate.py. It is parallel with Wave 1 only because none of those modules appear in the other four lanes. It collides with everything from Wave 2 onwards - #120 and #118 (predicates.py), #124 (schema_checks.py), #126 (pipeline.py) - so it has to be merged before Wave 2 opens, not merely started.
#127 before #120. predicates.py:112 returns DROPPED both when pyld raises and when a term is genuinely unmapped. #120 turns the unmapped case into a warning; done first, it silently downgrades processor failures with it.
Wave 2 - the context and resolver cluster, strictly sequential
In that order, and not concurrently. #120 moves the context.* verdicts; #118's and #119's acceptance criterion is that verdicts do not move, so both need #120's verdicts to be the settled baseline. #118 and #119 also share the parity gate, so running them together makes a moved verdict unattributable.
#120 is additionally blocked on the upstream chain in Wave 0, for the OOLD-SCH-2d05 citation. The split itself can be built before rc.3 lands.
Wave 3 - the front-end surface
#122 and #125 item 2 both edit mcp_server.py, so they want to be adjacent or combined. #125 items 2 and 4 both edit check_registry.py. Item 4 is blocked on rc.3 being vendored, which #123 automates.
Wave 4 - cleanup, once the rewrites have landed
Renames DEFAULT_MAX_DEPTH in both resolve.py and context_resolution.py and removes dead code in modules #118 and #119 rewrite, so it has to follow them or it is written twice.
Wave 5 - last, on its own
Touches report.py, the five parse sites in resolve.py, the CLI renderer and all nine MCP result models. It conflicts with anything else in flight, so it goes when nothing else is open.
One hazard git will not catch
The parity gate is global state. OOLD_SCHEMA_DIR=... uv run pytest -m parity compares verdicts across the whole corpus, so two branches can each be green in isolation and still both move a verdict, with the conflict surfacing only after the second merge and attributable to neither. That is the real reason Wave 2 is sequential rather than merely inconvenient.
What this is not
Not a schedule, and not a claim that all eleven are worth doing. Waves 1 and 5 in particular contain work that may be closed as "recorded and declined" after a prototype - #119 says so explicitly. The order matters; the completeness does not.
Ordering for the eleven follow-ups from the review of #114. They are not independent: several pairs have a hard dependency where doing them the other way round means the second one cannot be verified. This issue is the single place that order lives; the individual issues carry the work.
Five lanes can run at the same time. The rest cannot, and the reason is usually a shared file rather than a shared idea.
Wave 0 - prerequisite
mainafterwards, not from the review branch.Upstream, on its own schedule: OO-LD/oold-schema#137 merges, oold-schema releases rc.3, rc.3 is vendored here. That chain gates two items below.
Wave 1 - genuinely parallel, no shared files
Replace hand-written format checkers with jsonschema[format-nongpl] #121 -
jsonschema[format-nongpl]for the format checkers.formats.py,test_formats.py,pyproject.toml,uv.lock.Add an "oold meta vendor" command instead of a documented bash procedure #123 -
oold meta vendorcommand. New CLI command plusdocs/maintaining-meta-schemas.md.No fixture exercises a truly remote (HTTP) @context #128 - a fixture that exercises a truly remote
@context.tests/test_validation/conftest.pyplus a new fixture.Follow-ups from the validation subsystem review #125 items 1, 3 and 5 - parity
continue-on-error(main.yml), the corrupt rules schema (meta_store.py), and the--offlinedefault (Makefile, docs). Three separate files, none shared with the above.Narrow the broad except Exception handling in the validation subsystem #127 - narrow the broad
except Exceptionhandling. Nine validation modules, none of them touched by the four lanes above.#128 before #119. No fixture currently makes
Resolverfetch anything over HTTP, so the retrieval layer #119 replaces has no test covering it and the swap would be unverifiable.#125 item 5 and #128 touch the same question from opposite sides: a fixture that resolves a remote
@contextcannot run under a default of--offline. Whichever lands second has to account for the other.#123 and #128 both edit
docs/maintaining-meta-schemas.md- #123 replaces the hand-run vendoring procedure, #128 renames theremote_context/fixture it mentions. Different sections, so it should auto-merge, but whichever lands second should re-read the file rather than assume.#127 is the widest diff in the set:
compliance.py(4 sites),instance_checks.py(2),schema_checks.py,roundtrip.py,predicates.py,pipeline.py,pattern_lint.py,generate.py. It is parallel with Wave 1 only because none of those modules appear in the other four lanes. It collides with everything from Wave 2 onwards - #120 and #118 (predicates.py), #124 (schema_checks.py), #126 (pipeline.py) - so it has to be merged before Wave 2 opens, not merely started.#127 before #120.
predicates.py:112returnsDROPPEDboth when pyld raises and when a term is genuinely unmapped. #120 turns the unmapped case into a warning; done first, it silently downgrades processor failures with it.Wave 2 - the context and resolver cluster, strictly sequential
context.predicatesciting a rule about prefixes for a coverage findingreferencingforresolve.py's URI and retrieval layerIn that order, and not concurrently. #120 moves the
context.*verdicts; #118's and #119's acceptance criterion is that verdicts do not move, so both need #120's verdicts to be the settled baseline. #118 and #119 also share the parity gate, so running them together makes a moved verdict unattributable.#120 is additionally blocked on the upstream chain in Wave 0, for the
OOLD-SCH-2d05citation. The split itself can be built before rc.3 lands.Wave 3 - the front-end surface
select_rules/select_checks/check_summaryextraction_MUST_LEVELSderived from the level vocabulary#122 and #125 item 2 both edit
mcp_server.py, so they want to be adjacent or combined. #125 items 2 and 4 both editcheck_registry.py. Item 4 is blocked on rc.3 being vendored, which #123 automates.Wave 4 - cleanup, once the rewrites have landed
Renames
DEFAULT_MAX_DEPTHin bothresolve.pyandcontext_resolution.pyand removes dead code in modules #118 and #119 rewrite, so it has to follow them or it is written twice.Wave 5 - last, on its own
Touches
report.py, the five parse sites inresolve.py, the CLI renderer and all nine MCP result models. It conflicts with anything else in flight, so it goes when nothing else is open.One hazard git will not catch
The parity gate is global state.
OOLD_SCHEMA_DIR=... uv run pytest -m paritycompares verdicts across the whole corpus, so two branches can each be green in isolation and still both move a verdict, with the conflict surfacing only after the second merge and attributable to neither. That is the real reason Wave 2 is sequential rather than merely inconvenient.What this is not
Not a schedule, and not a claim that all eleven are worth doing. Waves 1 and 5 in particular contain work that may be closed as "recorded and declined" after a prototype - #119 says so explicitly. The order matters; the completeness does not.