Extend tools/decisions with a roadmap subcommand to validate and manage docs/development-plan.jsonl (RM-028)
Context
RM-028, tracked as a deferred roadmap item since decision 0009, named this gap explicitly: docs/development-plan.jsonl has been hand-edited since it was introduced, with no equivalent validation or ID-assignment tooling to the one docs/decisions.jsonl already has (tools/decisions/). This session made the gap concrete, not just theoretical: RM-033 (Breakout's own roadmap entry) was hand-edited twice via ad hoc Python one-liners to update its status/resolution/decision_refs -- exactly the kind of unchecked, error-prone hand-edit tools/decisions/ was built to prevent for decisions.jsonl in the first place (decision 0009's own original motivation). With Breakout's roadmap now fully closed out and no other active work item queued, this was picked as the next concrete piece of work.
Options considered
Decision
Added decisions/roadmap_id.gleam (an RM-NNN opaque id type, 3-digit, mirroring decisions/id.gleam's own shape and guarantees), decisions/roadmap_schema.gleam (Status/RoadmapItem/Draft/Patch types plus decoders/encoders matching docs/development-plan.md's schema exactly, including a status vocabulary decoder for planned/in_progress/completed/deferred/superseded), and decisions/roadmap_log.gleam (read/next_id/append mirroring decisions/log.gleam's own contracts, plus a new update(path, id, patch) -> Result(Nil, LogError) capability decisions.jsonl's own append-only log structurally never needs, and validate_decision_refs for the decisions.jsonl cross-check). Renamed the CLI's bare-positional decision-append invocation to an explicit `decision` subcommand, and added `roadmap new`/`roadmap update` subcommands with matching draft/patch-file conventions. Every decision_refs entry supplied to either roadmap subcommand is validated against a real read of decisions.jsonl before anything is written. Dogfooded immediately: used `roadmap update` (not another hand-edit) to update RM-028's own status.
Verification
gleam test in tools/decisions passes -- 104 tests (up from 61 before this change: 12 new roadmap_id tests, 15 new roadmap_schema tests, 16 new roadmap_log tests, plus the pre-existing 61 all still passing unchanged). gleam build in tools/decisions is warning-free. Manually verified the CLI end-to-end against scratch copies of the real decisions.jsonl/development-plan.jsonl (not the real files) before touching anything real: roadmap update succeeded and wrote exactly the patched fields, leaving id/phase/phase_title/title/description untouched; roadmap update correctly rejected an unknown decision_refs id (DecisionRefNotFound) and an unknown item id (UnknownId), in both cases leaving the file byte-for-byte unchanged; roadmap new correctly appended a new item at the next free RM-NNN; the renamed `decision` subcommand still appends to decisions.jsonl correctly, and an unrecognized command prints the multi-line usage message. The main glemy repo's own gleam build/gleam test/deno task check-warnings all remain green and unaffected (tools/decisions is a wholly separate Gleam package, not part of the main package's build graph).
Consequences
docs/development-plan.jsonl status changes (the actual, recurring need this session hand-rolled twice) now go through the same validated, canonicalizing write path decisions.jsonl already had -- a malformed status value, a typo'd decision_refs id, or an accidental edit to a field that should stay fixed (phase/phase_title/title/description) is now a command failure instead of a silent, checked-in mistake. RM-028 itself is the first roadmap item ever updated via this tool rather than by hand. docs/decisions.md and docs/development-plan.md were both updated to document the new/changed invocation syntax. A third project record needing this same append-or-append-and-patch shape would extend this tool's module set the same way, not start a new one from scratch.
References
- tools/decisions/src/decisions.gleam
- tools/decisions/src/decisions/roadmap_id.gleam
- tools/decisions/src/decisions/roadmap_schema.gleam
- tools/decisions/src/decisions/roadmap_log.gleam
- tools/decisions/test/decisions/roadmap_id_test.gleam
- tools/decisions/test/decisions/roadmap_schema_test.gleam
- tools/decisions/test/decisions/roadmap_log_test.gleam
- docs/decisions.md
- docs/development-plan.md
- ARCHITECTURE.md
- docs/development-plan.jsonl