You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
map_step_runner.py parse_requirements_index() imports PyYAML → validate_blueprint_contract silently reports 'malformed' Requirements Index without it installed #319
parse_requirements_index() in .map/scripts/map_step_runner.py (added for the Requirements Index / forward-completeness gate, present as of mapify_version 3.20.0) does a lazy import yaml (yaml.safe_load) to parse the mapify:requirements-index:v1 sentinel block from the spec. When PyYAML is not installed in the environment running python3 .map/scripts/map_step_runner.py, the function catches the ImportError and returns status='malformed' — even when the spec's Requirements Index is perfectly well-formed.
This regresses the explicit scope note in #245 ("The .map/scripts/map_step_runner.py runner is NOT affected — it reads config via a manual scalar parser ... no yaml import"). That was true for _read_map_config_scalars at the time, but parse_requirements_index is a newer function in the same file that DOES import yaml, reintroducing the same root cause (PyYAML not a declared runtime dependency) in a code path #245 said was safe.
Observed
Running /map-plan on a fresh env without PyYAML (python3 -c "import yaml" → ModuleNotFoundError: No module named 'yaml'):
$ python3 .map/scripts/map_step_runner.py validate_blueprint_contract
{
"valid": false,
"errors": [
"Forward-coverage: Requirements Index is malformed (see the mapify:requirements-index:v1 template in plan-reference.md.jinja)"
],
...
"forward_coverage": {"status": "malformed", "basis": "Requirements Index malformed; could not diff"}
}
The spec's Requirements Index block was hand-verified to exactly match the documented sentinel-pair + fenced-yaml contract (open <!-- mapify:requirements-index:v1 -->, fenced ```yaml block, close <!-- /mapify:requirements-index:v1 -->, valid `{requirements: [{id, kind}, ...]}` shape). After `pip3 install pyyaml` the same command reports `forward_coverage.status: "present_nonempty"` correctly — confirming the failure is purely the missing import, not a spec formatting issue. This makes the error message ("Requirements Index is malformed") actively misleading: it points the operator at the wrong file (the spec) when the actual defect is the local Python environment's missing dependency.
Expected
Either:
parse_requirements_index() distinguishes ImportError from a genuine YAML parse error / malformed structure, and surfaces a distinct, honest status/message (e.g. status='pyyaml_missing' with a message like "PyYAML not installed; cannot validate Requirements Index — run pip install pyyaml") instead of conflating it with malformed, OR
PyYAML is made a true runtime dependency of everything .map/scripts/*.py needs (not just the mapify CLI package's pyproject.toml, which doesn't even apply here since these are vendored per-repo scripts, not an installed package) — e.g. documented as a required local Python dependency in .map/scripts/README or checked with a clear preflight error at the top of map_step_runner.py.
Scope
.map/scripts/map_step_runner.py: parse_requirements_index() (~line 2761, import yaml at ~line 2828) and its caller path through validate_blueprint_contract's forward-coverage check.
Summary
parse_requirements_index()in.map/scripts/map_step_runner.py(added for the Requirements Index / forward-completeness gate, present as of mapify_version 3.20.0) does a lazyimport yaml(yaml.safe_load) to parse themapify:requirements-index:v1sentinel block from the spec. When PyYAML is not installed in the environment runningpython3 .map/scripts/map_step_runner.py, the function catches theImportErrorand returnsstatus='malformed'— even when the spec's Requirements Index is perfectly well-formed.This regresses the explicit scope note in #245 ("The
.map/scripts/map_step_runner.pyrunner is NOT affected — it reads config via a manual scalar parser ... noyamlimport"). That was true for_read_map_config_scalarsat the time, butparse_requirements_indexis a newer function in the same file that DOESimport yaml, reintroducing the same root cause (PyYAML not a declared runtime dependency) in a code path #245 said was safe.Observed
Running
/map-planon a fresh env without PyYAML (python3 -c "import yaml"→ModuleNotFoundError: No module named 'yaml'):The spec's Requirements Index block was hand-verified to exactly match the documented sentinel-pair + fenced-yaml contract (open
<!-- mapify:requirements-index:v1 -->, fenced ```yaml block, close<!-- /mapify:requirements-index:v1 -->, valid `{requirements: [{id, kind}, ...]}` shape). After `pip3 install pyyaml` the same command reports `forward_coverage.status: "present_nonempty"` correctly — confirming the failure is purely the missing import, not a spec formatting issue. This makes the error message ("Requirements Index is malformed") actively misleading: it points the operator at the wrong file (the spec) when the actual defect is the local Python environment's missing dependency.Expected
Either:
parse_requirements_index()distinguishesImportErrorfrom a genuine YAML parse error / malformed structure, and surfaces a distinct, honest status/message (e.g.status='pyyaml_missing'with a message like "PyYAML not installed; cannot validate Requirements Index — runpip install pyyaml") instead of conflating it withmalformed, OR.map/scripts/*.pyneeds (not just themapifyCLI package'spyproject.toml, which doesn't even apply here since these are vendored per-repo scripts, not an installed package) — e.g. documented as a required local Python dependency in.map/scripts/READMEor checked with a clear preflight error at the top ofmap_step_runner.py.Scope
.map/scripts/map_step_runner.py:parse_requirements_index()(~line 2761,import yamlat ~line 2828) and its caller path throughvalidate_blueprint_contract's forward-coverage check./map-plan's Step 5.6 (validate_blueprint_contract) in a Python environment without PyYAML — likely common, since PyYAML is not obviously a prerequisite for the.map/scripts/runner scripts (per PyYAML missing from runtime deps → mapify CLI silently ignores .map/config.yaml (uses defaults) #245's own scope note, which is now stale for this function).Environment
.claude/skills/map-plan/SKILL.mdMAP-MANAGED header, installed_at 2026-07-02T11:40:03Z)python3 --version: 3.12.8 (/usr/local/bin/python3)pip3 show pyyaml: not found (before workaround)map_step_runner.py, which is now inaccurate forparse_requirements_index)