PRISM Control Integration¶
This guide covers integrating Structured Changelog with PRISM Control for roadmap traceability — linking changelog entries to roadmap items (RMIs) and strategic initiatives.
Overview¶
PRISM Control is a roadmap management system that organizes work into:
- Initiatives — strategic goals spanning multiple projects (e.g.,
INIT-STREAMING-001) - Roadmap Items (RMIs) — discrete deliverables tracked per-repository (e.g.,
RMI-MYREPO-042)
Structured Changelog supports optional rmis, rmi, and initiative fields on changelog entries, enabling:
- Traceability from releases back to roadmap planning
- Automated initiative progress tracking across repositories
- Changelog-driven roadmap status updates
JSON Schema¶
Add rmis (preferred) and/or initiative to any changelog entry. Use the
plural rmis array because a curated entry often summarizes several commits
spanning multiple RMIs; the legacy singular rmi is retained for
back-compatibility and treated as a one-element rmis.
{
"releases": [
{
"version": "v1.2.0",
"date": "2026-07-26",
"added": [
{
"description": "Add streaming support via ConverseStream API",
"rmis": ["RMI-MYREPO-042", "RMI-MYREPO-044"],
"commit": "abc123"
},
{
"description": "Add bearer token authentication",
"rmis": ["RMI-MYREPO-043"]
},
{
"description": "Ad-hoc refactor with no roadmap item",
"initiative": "INIT-STREAMING-001"
}
]
}
]
}
All three fields are optional. Follow the convention: populate rmis;
set initiative only for entries that have no RMI (with an RMI present the
initiative is derivable downstream, so storing both invites drift).
Field Reference¶
| Field | Type | Description |
|---|---|---|
rmis |
string[] | Roadmap Item IDs (format: RMI-<REPOSLUG>-<NNN>); preferred |
rmi |
string | Legacy single Roadmap Item ID; treated as a one-element rmis |
initiative |
string | Initiative ID (format: INIT-<SLUG>-<NNN>); use only when no RMI applies |
schangelog validate warns (W006) on malformed IDs in rmis and (W007) when a
singular rmi disagrees with rmis.
Programmatic Usage¶
Building Entries¶
Use the builder methods for fluent entry construction:
import "github.com/grokify/structured-changelog/changelog"
entry := changelog.NewEntry("Add streaming support").
WithRMIs("RMI-MYREPO-042", "RMI-MYREPO-044").
WithCommit("abc123").
WithAuthor("@developer")
// Legacy singular form (still supported); prefer WithRMIs for new code:
legacy := changelog.NewEntry("Add auth").WithRMI("RMI-MYREPO-043")
Reading Entries¶
Access the fields directly from parsed changelogs:
cl, err := changelog.LoadFile("CHANGELOG.json")
if err != nil {
return err
}
for _, release := range cl.Releases {
for _, entry := range release.Added {
if entry.RMI != "" {
fmt.Printf("Feature %s implements %s\n", entry.Description, entry.RMI)
}
if entry.Initiative != "" {
fmt.Printf(" Part of initiative: %s\n", entry.Initiative)
}
}
}
Filtering by RMI or Initiative¶
Find all entries for a specific roadmap item:
func findEntriesByRMI(cl *changelog.Changelog, rmi string) []changelog.Entry {
var results []changelog.Entry
for _, release := range cl.Releases {
for _, entry := range release.AllEntries() {
if entry.RMI == rmi {
results = append(results, entry)
}
}
}
return results
}
Git Commit Integration¶
Following the convention in CLAUDE.md, commits implementing roadmap items carry a git trailer:
feat(api): add streaming support
Implements server-sent events for real-time updates.
Refs: RMI-MYREPO-042
The parse-commits command extracts these references automatically, carrying
the RMI IDs on each parsed commit's rmis:
When you build a changelog from those commits with schangelog init --from-tags,
each generated entry's rmis is pre-populated from the underlying commits'
Refs: trailers (deduplicated and sorted) — you curate rather than transcribe.
initiative is never auto-populated.
Use Cases¶
Roadmap Progress Tracking¶
Query changelogs across a portfolio to track initiative completion:
// Load multiple project changelogs
portfolio := []*changelog.Changelog{project1, project2, project3}
// Count completed RMIs per initiative
progress := make(map[string]int)
for _, cl := range portfolio {
for _, release := range cl.Releases {
for _, entry := range release.AllEntries() {
if entry.Initiative != "" {
progress[entry.Initiative]++
}
}
}
}
Release Notes Generation¶
Generate initiative-focused release notes:
// Group entries by initiative for quarterly reports
byInitiative := make(map[string][]changelog.Entry)
for _, entry := range release.AllEntries() {
if entry.Initiative != "" {
byInitiative[entry.Initiative] = append(
byInitiative[entry.Initiative], entry)
}
}
Audit Trail¶
The combination of rmi, initiative, and commit fields provides a complete audit trail:
- What was delivered (entry description)
- Why it was done (initiative context)
- Where it was planned (RMI reference)
- When it shipped (release date)
- How it was implemented (commit hash)
Best Practices¶
- Prefer
rmisoverrmi— The plural array expresses entries that summarize several commits across multiple RMIs; the singular remains for back-compat - Set
initiativeonly without an RMI — With an RMI present the initiative is derivable downstream, so storing both invites drift - Let trailers do the work — Carry
Refs: RMI-<SLUG>-<NNN>on commits;parse-commitsandinitpopulatermisfor you - Omit when not planned — Bug fixes and dependency updates typically don't need roadmap references
- Keep IDs stable — Don't change RMI/Initiative IDs after they're referenced in changelogs