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
Schema, code, docs, and test fixtures disagree on the field names used in plan.edges[] entries. Schema and docs use {"from", "to", "type"}; code and fixtures use {"source", "target", "type"}. Latent correctness bug that will fire the moment the #436 migrator runs against real-world speckit data or the #435 aggregator builds cross-scope dep maps from schema-compliant input.
Filed per the #437 post-walkthrough sanity sweep (2026-04-20). v0.20.0 GA blocker (#8 of 8).
Evidence (four-way disagreement)
Schema requires from / to / type
From vbrief/schemas/vbrief-core.schema.json:132-144:
speckit Phase 4 collides with plan.vbrief.json definition (no scope vBRIEFs emitted) #436 Opt 1 migrator depends on reading existing speckit edges[]. Real-world speckit users (per the migrator's design) have speckit-shaped plan.vbrief.json files. If those files follow the speckit.md example convention (from/to), the migrator code must read from/to. If the migrator reuses _build_edge_map's source/target pattern, it silently produces an empty dep map for every IP-N edge, losing all dependency information.
Silent failure, not loud.edge.get("source", "") returns empty string for {"from": ..., "to": ...} inputs. No error, no warning. Edge data effectively disappears. Topo sort degenerates to filename-only order.
Schema is published.vbrief/vbrief.md:306-308 points at ./schemas/vbrief-core.schema.json as the canonical source. Users who read the schema and write {"from", "to"} will get broken behavior from tools that expect {"source", "target"}.
Proposed fix
Three-part alignment:
1. Make roadmap_render.py (and the #435 aggregator implementation) bilingual
Going forward, new vBRIEFs emit {"from", "to", "type"} (matches schema + speckit doc). Old vBRIEFs with source/target continue to work via the bilingual reader for at least one release cycle.
3. Update test fixtures to match schema
tests/cli/test_roadmap_render.py:107-111 (and any similar fixtures) switch to {"from", "to"}. Add one legacy fixture asserting source/target still reads correctly (backward-compat regression guard).
4. Migrator (part of #436) reads from/to as primary with source/target fallback
Uses the same bilingual pattern so real-world speckit data is read correctly regardless of which convention was used historically.
v0.20.0 GA blocker. Must land before PR #403 can merge. Small scope, low risk, high correctness value -- the bilingual reader pattern protects against future data-shape drift.
Summary
Schema, code, docs, and test fixtures disagree on the field names used in
plan.edges[]entries. Schema and docs use{"from", "to", "type"}; code and fixtures use{"source", "target", "type"}. Latent correctness bug that will fire the moment the #436 migrator runs against real-world speckit data or the #435 aggregator builds cross-scope dep maps from schema-compliant input.Filed per the #437 post-walkthrough sanity sweep (2026-04-20). v0.20.0 GA blocker (#8 of 8).
Evidence (four-way disagreement)
Schema requires
from/to/typeFrom
vbrief/schemas/vbrief-core.schema.json:132-144:Speckit doc example matches schema
From
strategies/speckit.md:176-180:Code reads
source/target(disagrees with schema)From
scripts/roadmap_render.py:80-99:Test fixture matches code (disagrees with schema and docs)
From
tests/cli/test_roadmap_render.py:107-111:Why this is a v0.20.0 GA blocker
speckit Phase 4 collides with plan.vbrief.json definition (no scope vBRIEFs emitted) #436 Opt 1 migrator depends on reading existing speckit
edges[]. Real-world speckit users (per the migrator's design) have speckit-shapedplan.vbrief.jsonfiles. If those files follow the speckit.md example convention (from/to), the migrator code must readfrom/to. If the migrator reuses_build_edge_map'ssource/targetpattern, it silently produces an empty dep map for every IP-N edge, losing all dependency information.spec rendering does not aggregate scope vBRIEFs from lifecycle folders (v0.20 model) #435 aggregator cross-scope topo-sort depends on reading
edges[]consistently. Same silent-empty-map failure mode if a scope vBRIEF stores edges under one convention and the reader expects the other.Silent failure, not loud.
edge.get("source", "")returns empty string for{"from": ..., "to": ...}inputs. No error, no warning. Edge data effectively disappears. Topo sort degenerates to filename-only order.Schema is published.
vbrief/vbrief.md:306-308points at./schemas/vbrief-core.schema.jsonas the canonical source. Users who read the schema and write{"from", "to"}will get broken behavior from tools that expect{"source", "target"}.Proposed fix
Three-part alignment:
1. Make
roadmap_render.py(and the #435 aggregator implementation) bilingualUpdate
_build_edge_mapto read both conventions:2. Canonical convention: schema wins
Going forward, new vBRIEFs emit
{"from", "to", "type"}(matches schema + speckit doc). Old vBRIEFs withsource/targetcontinue to work via the bilingual reader for at least one release cycle.3. Update test fixtures to match schema
tests/cli/test_roadmap_render.py:107-111(and any similar fixtures) switch to{"from", "to"}. Add one legacy fixture assertingsource/targetstill reads correctly (backward-compat regression guard).4. Migrator (part of #436) reads
from/toas primary withsource/targetfallbackUses the same bilingual pattern so real-world speckit data is read correctly regardless of which convention was used historically.
Test coverage
test_edge_map_from_to_keys-- asserts canonical{"from", "to"}input produces correct dep map.test_edge_map_source_target_keys-- asserts legacy{"source", "target"}input produces correct dep map (backward-compat).test_edge_map_mixed_keys_within_single_plan-- edge case: mix of both in sameedges[]array should all resolve.Acceptance criteria
scripts/roadmap_render.py_build_edge_mapreads both{from, to}and{source, target}; prefersfrom/towhen both present.scripts/spec_render.py(spec rendering does not aggregate scope vBRIEFs from lifecycle folders (v0.20 model) #435 aggregator's cross-scope topo sort) uses the same bilingual read pattern.scripts/migrate_vbrief.pyspeckit-plan translator reads both conventions for input edges.tests/cli/test_roadmap_render.pyprimary fixture switches to{from, to}; legacy{source, target}fixture added for backward-compat regression.strategies/speckit.mdPhase 4 doc continues to use{from, to}(already does -- no change).vbrief/vbrief.md(if it documents edges anywhere) uses{from, to}consistently.Estimated effort
~1 hour. Small code change (bilingual reader in 2-3 places), fixture update, doc grep, tests.
Related
GA status
v0.20.0 GA blocker. Must land before PR #403 can merge. Small scope, low risk, high correctness value -- the bilingual reader pattern protects against future data-shape drift.