blue/.blue/docs/spikes/2026-01-26T2100Z-rfc-stub-source-link-and-kebab-case-filename-bugs.wip.md
Eric Garcia 0fea499957 feat: lifecycle suffixes for all document states + resolve all clippy warnings
Every document filename now mirrors its lifecycle state with a status
suffix (e.g., .draft.md, .wip.md, .accepted.md). No more bare .md for
tracked document types. Also renamed all from_str methods to parse to
avoid FromStr trait confusion, introduced StagingDeploymentParams struct,
and fixed all 19 clippy warnings across the codebase.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 12:19:46 -05:00

3.6 KiB

Spike: Rfc Stub Source Link And Kebab Case Filename Bugs

Status In Progress
Date 2026-01-26
Time Box 30 minutes

Question

Why does blue_rfc_create not link the Source Spike field, and why are some spike/RFC filenames created with spaces instead of kebab-case?


Findings

Bug 1: Source Spike field rendered as plain text

Root cause: Rfc::to_markdown() in crates/blue-core/src/documents.rs:227-228

if let Some(ref spike) = self.source_spike {
    md.push_str(&format!("| **Source Spike** | {} |\n", spike));
}

The spike title is stored as a bare String and rendered directly into the markdown table. No link is constructed.

Contributing factor: handle_rfc_create in crates/blue-mcp/src/server.rs:2522-2523 stores the raw title without resolving the spike's file path:

if let Some(s) = source_spike {
    rfc.source_spike = Some(s.to_string());
}

The Rfc struct has no access to the spike's file path or the document store at render time. The same issue exists for source_prd at documents.rs:230-231.

Fix options:

  1. Resolve the spike file path at creation time (in handle_rfc_create) and store a markdown link string in source_spike — e.g. [Title](../spikes/2026-01-26-slug.md)
  2. Change source_spike from Option<String> to a struct carrying both title and path, then render the link in to_markdown()

Option 1 is simpler. The spike's file_path can be looked up from the store via find_document(DocType::Spike, title).

Bug 2: Filenames created without kebab-case

Root cause: handle_rfc_create in crates/blue-mcp/src/server.rs:2529

let filename = format!("rfcs/{:04}-{}.md", number, title);

The raw title is interpolated directly — no to_kebab_case() call. If the title contains spaces or mixed case, the filename will too. There is no to_kebab_case function anywhere in server.rs.

Spike handler is correct. crates/blue-mcp/src/handlers/spike.rs:34 does call to_kebab_case(title):

let filename = format!("spikes/{}-{}.md", date, to_kebab_case(title));

The existing space-named spike files (e.g. 2026-01-25-Background Agents and Dialogue Creation Not Triggering.md) were created either before commit 015c21d applied the kebab-case fix to the spike handler, or by a Claude agent writing files directly with the Write tool (bypassing the MCP handler entirely).

Systemic issue: to_kebab_case() is duplicated as a private function in 7 handler files (spike.rs, adr.rs, decision.rs, prd.rs, postmortem.rs, dialogue.rs, runbook.rs) but is missing from server.rs where handle_rfc_create lives. RFC creation is the only handler that still generates filenames inline in server.rs rather than in a dedicated handler module.

Summary

Bug Location Cause
Source Spike not linked documents.rs:227 Renders title as plain text, never constructs a link
RFC filenames not kebab-cased server.rs:2529 Uses raw title in filename, no to_kebab_case()
to_kebab_case fragility 7 private copies across handler files Not shared; server.rs has no copy at all

Recommendation

Recommends implementation. Both bugs are straightforward fixes:

  1. In handle_rfc_create: look up the spike's file_path from the store, store a markdown link in source_spike (same for source_prd)
  2. In handle_rfc_create: apply to_kebab_case() to the title when generating the filename
  3. Extract to_kebab_case into blue-core as a shared public utility to prevent future drift