blue/.blue/docs/spikes/2026-01-26T1941Z-rfc-id-collision-root-cause.wip.md
Eric Garcia 02901dfec7 chore: batch commit - ADRs, RFCs, dialogues, spikes, and code updates
ADRs:
- Update 0008-honor, 0009-courage, 0013-overflow, 0015-plausibility
- Add 0017-hosted-coding-assistant-architecture

RFCs:
- 0032: per-repo AWS profile configuration (draft)
- 0033: round-scoped dialogue files (impl + plan)
- 0034: comprehensive config architecture (accepted)
- 0036: expert output discipline (impl)
- 0037: single source protocol authority (draft)
- 0038: SDLC workflow discipline (draft)
- 0039: ADR architecture greenfield clarifications (impl)
- 0040: divorce financial analysis (draft)
- 0042: alignment dialogue defensive publication (draft)

Spikes:
- Read tool token limit on assembled dialogues
- RFC ID collision root cause
- Expert agent output too long
- Judge writes expert outputs
- Blue MCP server on superviber infrastructure
- Playwright MCP multiple window isolation

Dialogues: 16 alignment dialogue records

Code:
- blue-core: forge module enhancements
- blue-mcp: env handlers and server updates
- alignment-expert agent improvements
- alignment-play skill refinements
- install.sh script

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 16:28:31 -05:00

3.7 KiB

Spike: Rfc Id Collision Root Cause

Status In Progress
Date 2026-01-26
Time Box 1 hour

Question

Why is there an RFC ID collision in blue.db when working on multiple RFCs simultaneously? What is the root cause and how do we prevent it?


Findings

Evidence

Two blue.db files exist:

  • /Users/ericg/letemcook/blue/blue.db — empty (0 bytes), stale artifact at repo root
  • /Users/ericg/letemcook/blue/.blue/blue.db — actual database (299KB)

11 RFC numbers have duplicate database entries:

number | count
-------|------
1      | 3
2      | 3
14     | 2
15     | 2
17     | 2
20     | 2
27     | 2
28     | 2
30     | 2
31     | 2
33     | 2

RFC 0033 collision details:

id  | number | title                           | status      | file_path                                          | created_at
----|--------|--------------------------------|-------------|----------------------------------------------------|-----------
24  | 33     | round-scoped-dialogue-files    | implemented | rfcs/0033-round-scoped-dialogue-files.impl.md     | 18:58:43
137 | 33     | Comprehensive Config Arch      | draft       | rfcs/0033-comprehensive-config-architecture.draft.md | 19:35:04

File timestamps:

14:33 — 0033-comprehensive-config-architecture.draft.md (created via Write tool)
14:39 — 0033-round-scoped-dialogue-files.plan.md
14:40 — 0033-round-scoped-dialogue-files.impl.md

Root Cause Analysis

Primary cause: reconcile() doesn't check for number collisions

In store.rs:2031-2034, the reconcile function finds existing documents by matching on file_path:

let existing = self.list_documents(dt)
    .into_iter()
    .find(|d| d.file_path.as_ref() == Some(&relative_path));

This means:

  1. Two files with the same number but different filenames are both considered "unindexed"
  2. Both get registered via register_from_file() without collision detection
  3. Database ends up with multiple entries for the same RFC number

Secondary cause: Write tool bypasses Blue's numbering system

When I created 0033-comprehensive-config-architecture.draft.md using Claude's Write tool instead of blue_rfc_create, it bypassed:

  1. Blue's next_number_with_fs() function that scans filesystem for max number
  2. Blue's database registration

Then when blue_sync ran (or when the file was otherwise registered), it created a duplicate entry.

Tertiary cause: Concurrent sessions

Two Claude sessions working simultaneously may have:

  1. Cached state that doesn't reflect filesystem changes from the other session
  2. Race conditions where next_number_with_fs() returns the same number to both

Remediation Options

  1. Fix reconcile() — Add collision detection before register_from_file():

    // Check if number already exists for this doc_type
    let number_exists = self.list_documents(dt)
        .into_iter()
        .any(|d| d.number == parsed.number);
    
    if number_exists {
        // Log warning about collision, don't create duplicate
        result.collisions.push(relative_path);
        continue;
    }
    
  2. Fix the immediate collision — Delete duplicate database entries:

    -- Keep the older entry, delete the newer one
    DELETE FROM documents WHERE id = 137;  -- comprehensive-config (newer)
    

    Then rename the file to use the next available number.

  3. Process improvement — Always use blue_rfc_create for new RFCs, never Write tool directly.

Recommendation

Outcome: recommends-implementation

  1. Create RFC to add collision detection to reconcile() function
  2. Manually fix current collisions by renaming files and cleaning database
  3. Add CLAUDE.md guidance: "Always use blue_rfc_create for new RFCs"