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

119 lines
3.7 KiB
Markdown

# 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`:
```rust
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()`:
```rust
// 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:
```sql
-- 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"