Appearance
ADR-0006: Accept yaml@^2.8 as First Runtime Dependency (Amendment to ADR-0002)
- Status: Accepted
- Date: 2026-04-15
- Supersedes: None
- Amends: ADR-0002
Context and Problem Statement
Phase 4 introduces .nubos-pilot/roadmap.yaml as the canonical source-of-truth for roadmap data. The schema contains nested sequences, mixed scalar types, and per-phase plans sub-objects that go well beyond what a hand-rolled regex parser can handle. lib/frontmatter.cjs (the hand-rolled parser) already hits its design ceiling on Task-Frontmatter multiline sequences; extending it further to parse the full roadmap YAML would reimplement a real YAML 1.2 parser in-repo, which is strictly worse than vendoring a 50KB tested library.
ADR-0002 §"Escape hatch for future exceptions" explicitly foresees this: "if a concrete future feature genuinely requires a runtime dep that builtins cannot satisfy, the exception is introduced by a new ADR […] that either supersedes ADR-0002 wholesale or amends it narrowly with a name-scoped exemption." This ADR is the first exercise of that escape hatch.
Scope
- This amendment permits EXACTLY ONE additional runtime dependency:
yaml@^2.8. package.json.dependenciesis limited to{"yaml": "^2.8.0"}; no other key permitted.- No further runtime deps may be added without a new ADR amendment that either supersedes ADR-0002 again, or amends it with a second narrowly-scoped exemption.
devDependenciesremain unconstrained by this amendment.
Decision Drivers
- Concrete need:
roadmap.yamlships nested sequences (milestones → phases → plans) that the hand-rolled regex parser cannot express. - Pre-sanctioned by CLAUDE.md: the project's tech-stack document explicitly identifies
yaml@^2.8as the acceptable escape-hatch dependency. - Install-footprint minimal:
yaml@^2.8has zero transitive dependencies and ships ~50KB of JS. - Type safety:
YAML.parseyields typed scalars (number, string, boolean, null, arrays of same). - Round-trip support: supports CST-preserving
YAML.parseDocumentfor future phases that need to edit YAML while preserving comments.
Considered Options
- Option A: Keep regex parser, extend it to handle nested sequences. Reject: every step lands in a hand-rolled YAML 1.2 implementation.
- Option B: Write a minimal purpose-built YAML subset parser. Reject: effort exceeds the install-surface cost of vendoring
yaml@^2.8. - Option C: Accept
yaml@^2.8as the first and only additional runtime dependency. Chosen. - Option D: Move the roadmap source-of-truth back to Markdown. Reject: Phase-4 decisions lock
roadmap.yamlas source-of-truth specifically because Markdown cannot express the structured plan-object data.
Decision Outcome
Chosen: Option C, accept yaml@^2.8 as the first runtime dependency, because the concrete need is documented in Phase-4 decisions, CLAUDE.md pre-sanctions this specific dep, and the narrow name-scoped amendment preserves ADR-0002's forcing function against "just add a dep" drift.
Audit rule: Any PR that adds a key to package.json.dependencies beyond yaml MUST be blocked unless it ships with a new ADR amendment that supersedes this one or adds a second narrowly-scoped exemption.
Consequences
- Good:
roadmap.yamlparsing now covers nested sequences and YAML 1.2's full scalar type system. - Good: future phases that need structured YAML can reuse
yaml@^2.8without another amendment. - Good: the install-footprint remains effectively flat;
yaml@^2.8has zero transitive dependencies. - Bad:
npx nubos-pilotnow performs one actual download at install time on a fresh machine. The "zero-deps ≈ zero failure modes" property is slightly weakened, but only by the thinnest possible amount. - Bad: the escape-hatch is no longer purely theoretical; future PR authors have a concrete precedent to cite. Mitigated by the Scope clause pinning this to EXACTLY ONE dep.
- Neutral: workflow patterns remain unchanged.
More Information
- Amended ADR: ADR-0002.
- CLAUDE.md: §"Supporting Libraries" → row "yaml
^2.8.0" pre-sanctions this dependency. - Upstream:
yamlnpm package. Maintained by Eemeli Aro, version 2.x is YAML 1.2 compliant, zero transitive deps.
This ADR does not describe CI enforcement. The dep-growth block (PR blocker on any new dependencies key beyond yaml) is deferred to a later deploy/CI phase, identical to ADR-0002's deferral.
