iceboundrock / iceboundrock/AutoForge
The `yaml` extra's PyYAML branch is exercised by no environment
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 0
- Forks
- 0
- Avg merge
- 8h 56m
- Merged PRs (30d)
- 40
Description
Follow-up from PR #38 (issue #31), listed there as out of scope.
pyproject.toml declares an optional extra:
[project.optional-dependencies]
# Full YAML config support (without it, the built-in subset parser is used).
yaml = ["pyyaml>=6"]
and config.py branches on whether it is installed:
def _load_yaml(path: Path) -> dict:
text = path.read_text(encoding="utf-8")
try:
import yaml # type: ignore
data = yaml.safe_load(text)
return data if isinstance(data, dict) else {}
except ImportError:
return _minimal_yaml_parse(text)
No environment exercises the PyYAML branch. The dev dependency group is
["pytest>=8", "ruff>=0.4", "mypy>=1.10"], the local .venv does not have
PyYAML, and the CI matrix added in #38 installs uv sync --locked --group dev
— so import yaml raises in all three, and _minimal_yaml_parse is what
actually runs everywhere. The one test that touches this,
tests/test_config.py::test_example_yaml_loads_without_pyyaml, pins the
absent case deliberately (monkeypatch.setitem(sys.modules, "yaml", None)).
Why it matters
The extra is a documented, supported configuration path, and it is the branch
an operator gets the moment they pip install autoforge[yaml]. Today that
operator runs a code path with zero test coverage, on a config file that
decides routing, loop bounds and safety gates — including safety.allow_merge.
The two parsers are also not guaranteed to agree. _minimal_yaml_parse handles
a documented subset (2-space nested maps, - lists, inline scalars) and
raises ConfigurationError beyond it, while PyYAML accepts far more. A config
that parses one way locally and another way under the extra is a silent
divergence that nothing currently detects. The interesting risk is not the
input the subset parser rejects — it is input both accept and interpret
differently (yes/no/on/off as booleans, 1.0 vs "1.0", sexagesimal
and octal-looking scalars, empty values, duplicate keys).
Proposed
- Make the branch reachable in tests regardless of the ambient environment —
e.g. a fixture that skips when PyYAML is genuinely unavailable, plus one
that installs/imports it, so_load_yamlis covered in both directions
rather than only in the ImportError direction. - Add a differential test over the repository's own example config and a
handful of the ambiguous scalars above: both parsers must produce the same
resultingConfig, or the subset parser must refuse outright. Silent
disagreement is the failure mode worth catching. - Decide where PyYAML gets installed. Either add an extras entry to the dev
group / a CI job that installs.[yaml], or — if the extra is not actually
wanted — remove it and the branch, and document that the subset parser is
the only YAML path. Keeping an untested optional branch is the one outcome
worth avoiding.
Not a bug report
Nothing is known to be broken. yaml.YAMLError on malformed input is already
caught by the caller's except Exception and re-raised as ConfigurationError
with the file path, which was verified while writing this. This is a coverage
and consistency gap, not a defect.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with _load_yaml in config.py, the YAML dependency declaration in pyproject.toml, and tests/test_config.py::test_example_yaml_loads_without_pyyaml. Review the existing CI setup and test the PyYAML and fallback paths against the repository example and ambiguous scalars. Done means both branches are exercised, parser divergence is detected or rejected, and the dependency or removal decision is reflected in configuration and documentation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- ci-cd, testing
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100