---
schema_version: 1
id: RAC-KV3G1RJ3CJ3R
type: roadmap
---
# RAC v0.14.0 — Edge-Legality Enforcement

## Status

Planned

## Context

ADR-049 names deterministic, CI-enforced cross-artifact validation as RAC's core
product, and `rac-cross-artifact-enforcement` scopes the rules. This milestone
opens the v0.14.x enforcement series with the first rule beyond referential
integrity: edge-legality.

Today a `## Related <Type>` (or `## Supersedes`) section on an artifact whose type
does not declare that relationship is parsed away to nothing — it renders as
prose, passes validation, and produces zero edges with no warning. That silent
failure was recorded in `rac-traceability-self-relationships` REQ-003 and is
`rac-cross-artifact-enforcement` REQ-004. This milestone surfaces it as a
validation issue (`relationship-edge-unsupported`) so authors learn the link did
nothing instead of believing it resolved.

Status-consistency (REQ-003 of the enforcement requirement) needs the resolved
target's type and status at validation time and ships next, in v0.14.1; this
milestone does not add that plumbing because edge-legality does not need it — the
check is entirely a property of the source artifact and its own schema.

## Outcomes

- A relationship section the source type's schema does not support is reported as
  a validation issue instead of being silently dropped, and fails the
  `rac relationships --validate` exit code.
- The new finding is deterministic, carried in both human and JSON output, and
  gated in CI through the existing dogfood relationship check.
- Referential integrity and all existing relationship issue codes are unchanged;
  the corpus stays green (it has no unsupported sections).

## Initiatives

### Initiative 1 — Edge-legality / no-silent-drop

Detect relationship sections present (with at least one reference) in an
artifact's Markdown whose name its type's `spec.optional` does not include, and
emit a new issue, `relationship-edge-unsupported`, naming the source and the
offending section. Recognise only the canonical `## Related <Type>` / `supersedes`
section names the parser already knows, so prose headings that merely resemble a
relationship section do not trip it.

### Initiative 2 — Output and coverage

Render the new finding under its own "Unsupported Relationships" group in human
output and as a `{source_path, relationship, code}` object in JSON. Add
negative/boundary tests (a legal edge, an unsupported `## Related <Type>`, a
non-decision declaring `## Supersedes`, the CLI exit code, the JSON shape).

## Constraints

- Deterministic (ADR-002): same corpus state, identical findings and ordering
  (artifacts in sorted-path order, sections in canonical `RELATIONSHIP_SECTIONS`
  order).
- Additive (ADR-007): existing relationship issue codes
  (`relationship-target-not-found`, `relationship-target-ambiguous`,
  `relationship-self-reference`, `duplicate-artifact-identifier`) are unchanged;
  the new code is added, not substituted. `supersedes` semantics are untouched.
- Structural references stay the mechanism (ADR-016); this adds a graph-legality
  check over the same parsed sections.

## Non-Goals

- Status-consistency (the superseded-target rule) — that is v0.14.1, with the
  target-metadata threading it needs.
- Generalising lifecycle status beyond decisions.
- Richer typed edge labels beyond the target-type vocabulary (ADR-016 reserves).
- Auto-repairing or rewriting offending sections.

## Implementation Contract

The following decisions are pinned for v0.14.0.

### Behaviour

- A relationship section present on an artifact but absent from that artifact
  type's `spec.optional` raises one `relationship-edge-unsupported` issue per
  offending section, carrying the source path and the snake_case section name; it
  is not counted as a checked reference (it produces no edge).
- Referential-integrity issue codes and their output are unchanged.

### Interface

- `rac relationships <dir> --validate` reports the new issue under an
  "Unsupported Relationships" group and exits `1` when it occurs; `0` when the
  corpus is clean. Human and JSON outputs both carry it.

## Success Measures

- `rac relationships rac/ --validate` exits `0` on the corpus and `1` on a fixture
  whose artifact declares a relationship section its type does not support.
- The count of silently-dropped relationship sections is observable (each is now
  either a real edge or a surfaced finding).
- No existing relationship-validation output changes except by the additive new
  issue.

## Risks

- Edge-legality could over-fire on intentional prose headings. Mitigated by
  matching only canonical section names already recognised by the parser.
- A consumer might assume only the four legacy issue codes. Mitigated: the code is
  additive and documented; existing codes and their `to_dict` shapes are unchanged.

## Assumptions

- `spec.optional` remains the source of truth for which relationship sections a
  type may declare (`src/rac/core/artifacts.py`).
- `validate_relationships` / `validation_from_corpus` remain the validation entry
  points feeding `rac relationships --validate`, `rac review`, and `rac watchkeeper`.

## Related Decisions

- adr-049
- adr-016
- adr-007

## Related Requirements

- rac-cross-artifact-enforcement
- rac-traceability-self-relationships

## Related Roadmaps

- v0.13.6-okf-bundle-export
