markharness

0023: Give Requirement two ownership modes, native and external

Status

Accepted (decided 2026-09-11, implemented 2026-09-12; see checklist-v2-core.md). It keeps the native Requirement defined by 0017 §1/§3 (many-to-many Feature↔Requirement, with the Feature side owning the relation) and adds a mode in which an external spec document owns the content.

Background

The 2026-09-11 rethink of markharness-v2-design.md settled on StrictDoc (.sdoc, Git-managed) as the source of truth for requirements, with markharness keeping only a fixed reference (source_locator / source_revision). Making that the only shape of requirement.yml, however, creates three problems.

  1. markharness becomes unusable without StrictDoc. None of the four North Star questions (impact, missed updates, past verification scope, release impact) presupposes an external spec document.
  2. The fixed reference does nothing during the MVP. Ingesting and parsing .sdoc is M3 (future) in that design; M0–M2 never read the external requirement itself. Requiring source_locator before anything reads it leaves teams pinning blob OIDs of files nobody parses.
  3. The current implementation and current usage are native. knowledge/requirements/<id>/requirement.yml is a native entity with label, description, axis, and a UID (src/knowledge.rs), and it is used without StrictDoc today — including in this repository.

Decision

1. Add source to requirement.yml

source: native | external, defaulting to native when absent.

2. Native mode

markharness owns label (required) and description (optional). source_locator / source_revision are not allowed. A spec-side change is detected from the base/head diff of requirement.yml itself — per-Requirement granularity, no external tool involved.

3. External mode

source_locator (a .sdoc path inside the same Git repository as markharness) and source_revision (a pinned Git blob OID) are required. label / description are not allowed (no duplication of external content — P1 in markharness-v2-design.md). Detect spec-side changes by comparing the .sdoc blobs referenced by source_locator at base and head. Compute a mismatch between the pin and the head blob separately as stale pin. Repinning neither cancels a source change nor confirms alignment (§6.1 of that design). The 2026-09-11 review correction replaces the previous pin-versus-head change-detection rule with this rule.

4. Mixing is rejected

A requirement.yml that carries fields from both modes, or that is incomplete for either, is rejected by validate.

5. axis is kept in both modes

axis is markharness’s own classification, not a copy of external content, so it stays even in external mode.

Consequences

Options considered and rejected