Background: This isn't “a project,” it's a character that wants to live
First, let's be clear about why there were these two refactors — otherwise the failure list below will look like pointless thrashing for no reason.
It all started with one idea: make an AI that can chat and remember people (similar to Neuro Sama). Not a customer-service-style Q&A machine, not a parrot, but a being with personality, memory, and emotions, one that can banter and chat with me and is willing to keep viewers company even after the stream ends. The reference points were AIVtubers from around the world — but I didn't want to copy their homework; I wanted to raise one myself.
So there were three names, one same obsession:
- dango-live (the initial blank sheet): A single-streamer application, starting with “an AI character that can chat” — persona, red lines, voice timbre, and memory hard-coded into the code. Simple, but any change meant editing code.
- miststar-live (the first serious framework build, 2026-08): Upgraded into a “platform.” Characters became systematized; one AI became a den of characters, and switching characters meant switching persona, voice timbre, and dedicated memory; viewer profiles and worldview meme libraries were shared at the platform level. This was the first serious framework build.
- shiogiri-paw / shiogiri-live (the second serious framework build, 2026-09): Split “daily life” and “performing on stage” into two systems — the soul side handled chatting, memory, and dropping by (like shooting the breeze in Discord), while the body side handled streaming, danmaku, and singing (like performing on stage); persona was injected before going live, events were reported during the stream, and memories settled after the stream ended. This was the second serious framework build.
The direction never changed from beginning to end: personality continuity, memory accumulation, long-term viewer relationships — remembering you like a person does. The obsession itself wasn't wrong; what was wrong was that the framework was built twice, and both times it fell on the same class of problems. Now let's get to the point.
Before writing this, let me admit one thing: after going through the failure records from both refactors, I found that most problems ultimately converge into the same principle — we kept patching “this one spot,” but rarely asked “why does it always break at this same class of spots.”
Background
- First time: miststar-live (2026-08), 35 modules / 92 tests / no git;
- Second time: shiogiri-paw / shiogiri-live (2026-09), 54 modules / 16,283 lines / all 657 tests green / 15 review cards package / hash self-verification.
The second time looked much more disciplined, right? But the result was: neither time had a single real stream. The longest “stream” the second time was 100 seconds, 9 real danmaku, and memory / memes / summaries all at 0 lines.
The three conclusions most worth remembering
1. What truly repeated wasn't the “mistake,” it was “configuration layering has no single authoritative rule.” First time: runtime values, real credentials, and the real room ID were written into the template config.json (put on the wrong side). Second time: the provider endpoint was erased from the template → fallback to the official endpoint → 401, and the AI didn't reply at all (put on no side). Same root cause, two opposite directions, failed both times. The second time only half-fixed it (the local path was migrated, the endpoint wasn't) — a half-fixed layering rule is as good as not fixed.
2. Both times, “all tests green + complete review package” was used as the definition of done, and neither time did it result in “can stream and feels up to standard.” First time 92; second time 657. Neither had a real stream. Tests green ≠ can stream.
3. The same structural disease (single thread + long tasks) was not solved at the architecture layer either time. First time: AI singing ran synchronously on the single thread → all song requests paused. Second time: worker single-threaded + inline sleep → danmaku ingestion blocked, proactive engine starved; voice timbre cold start's dozen-plus seconds was welded onto every utterance. The first time it was a “scheduling problem,” the second time an “architecture problem,” but essentially the same one. Swapping only modules without changing the concurrency model will fail a third time.
8 recurring patterns across both times
- Configuration layering has no single authoritative rule — ⭐ most worth remembering
- Misaligned definition of done: tests green ≠ can stream (both times lacked “behavioral criteria”)
- Single thread + long tasks (putting “waiting” on the critical path)
- “One link in the chain is broken, yet no test can catch it” — for example, speech was bound to the wrong model type, silent degradation passed through, and the character's voice timbre never took effect
- Documentation described intent, not actual measurements (first time 70 measured vs 92 actual; second time 181 vs 657)
- No distinction between verification environment and delivery environment (temporary paths and debug switches got mixed into deliverables)
- Configuration persistence / multi-step writes are not atomic (relying on the caller's diligence; missing a call means losing data)
- The “default off” discipline protected rollback but also froze capabilities (10 capabilities default off, all carded, all tested, and never run end to end)
Why did it repeat?
Three explanations at the mechanism level:
- The system covered “changing code” but not “running after delivery” — there was no acceptance test for “running for a while”;
- Every failure point was treated as “a problem in this spot” to fix — no one abstracted principles like “long tasks must not occupy the critical thread”;
- The medium for leaving behind knowledge was too fragile — the first time's decisions lived in a memo file, and the second time's conclusions were scattered across fifteen cards. What must be left behind the third time are “rules,” not “records.”
How to prevent it the third time?
Before starting each card, copy the recurrence-prevention checklist once: configuration ownership / delivery surface / end-to-end use case / degradation observability / long-task placement / atomicity / behavioral criteria / switches and actual measurements / numeric assertions (9 items); after completion, accept according to 8 items (including golden comparison and rollback actual testing).
A third path: no more patch-style fill-the-hole work; establish the rules first, then make the cut.
Two refactors, the same pitfall — a preliminary framework retrospective on miststar-live and shiogiri-paw
Two refactors, the same pitfall — a preliminary framework retrospective on miststar-live and shiogiri-paw