The first proper test of SkyeEngine Code was not building SkyeEngine Code. It was trying to understand why the first connection to an Ashes of the Unbound server could capture a different sky from the second.
By then the issue record was 2,821 lines and about 339 KB. It contained rendering states, captured evidence, rejected explanations, experiment gates and enough history for a new session to spend most of its context merely arriving at the problem.
One large agent was not the answer. The investigation needed several smaller surfaces which could disagree without losing the thread.
Assigning different roles
I split the work between investigators, coders, an auditor and a test runner.
The investigators interpreted evidence and proposed the next discriminating test. The coder implemented a cleared change, not whichever theory sounded most convincing in chat. The auditor checked one gate at a time. The test runner executed the accepted recipe and recorded what actually happened.
That separation prevented a familiar failure: the same session proposes an explanation, writes the patch and then reviews its own assumptions while carrying all of the confidence from the first step.
The investigator pair also used different model families. They caught different kinds of drift. One would tighten a causal claim while the other noticed that a test protocol had stopped matching the established control. Agreement became useful only after the two paths had remained independent long enough to challenge each other.
Keeping the issue record in the vault
Chat was for coordination. The Obsidian vault was the durable record.
The current issue state, accepted gates, forbidden claims and evidence references lived in notes which the next session could read without inheriting an entire chat transcript. Important interpretation was drafted in-channel, reviewed, then written into the vault. One agent made the durable edit and another verified it.
That distinction mattered because the lighting result was not a fix. The run showed that changing SkyAtmosphere admission state changed the captured cubemap, including a control which became worse. It established a causal relationship inside that run. It did not establish the root cause of the first-connection difference, and it did not justify shipping the diagnostic switch.
The workflow made it harder to accidentally promote “this changes the symptom” into “this is the production solution.” That was the point.
Routing direct requests
By 17 May, the app could launch and supervise agent sessions instead of merely watching an external bus. A role had a saved prompt, model configuration, working directory and channel. Direct pings could wake the relevant agent. Recent context arrived with the request, so agents did not have to poll the channel and decide whether every new message deserved an answer.
This felt materially different from several uncoordinated terminal windows. The coder could stay narrow. The auditor did not need to follow every speculative branch. An investigator could hand over a durable artifact instead of asking me to paste a long draft elsewhere.
It was also the first time the app began showing me its real shape. It was not a general group chat with unusually patient participants. It was a work coordinator whose visible conversation happened to be the easiest part to build first.
Adding independent review
The run also produced a useful embarrassment.
An investigator re-described an established cvar test protocol incorrectly. The second investigator mirrored the wording. The coder prepared a run which matched it. The auditor cleared it. Four roles touched the instruction and none compared it with the durable protocol it was supposed to reproduce. I caught the mismatch from domain knowledge before it cost another evidence session.
Role separation did not magically create correctness. It made the path legible enough to see where correctness had been assumed.
The process change was simple: when a handoff depends on an established procedure, cite the exact durable anchor instead of paraphrasing it from memory. The reviewer can then check fidelity to the source, not merely whether the new description is internally consistent.
The limits of automatic convergence
Agent-to-agent messages used explicit request, response and handoff markers. Ordinary mentions were context only. A channel fuse stopped more than one round trip without a human message, which prevented two agents from thanking each other forever.
It also stopped a perfectly healthy investigator exchange: draft, review, refinement, commit. I had to post small relay messages to re-arm the channel even though every turn was adding information.
Other seams showed too. A review-relevant message could be elided from delivered context and require a manual fetch. Tool availability arrived piecemeal. The boundary between answering in the shared channel and answering in the agent’s local session was not always obvious.
None of those failures invalidated the workflow. They told me that role, thread, expected responder and delivery state could not remain prompt conventions wrapped around a flat message table.
What the dogfood run proved
The game investigation stayed honest, the durable ticket remained usable, and different agents could join without restarting the reasoning from zero. That was enough to keep.
The pressure log from the run became the design input for V3. The next version would own the database, record routing decisions, make threads and artifacts real objects, and remember enough state to recover when an agent disappeared halfway through a turn.
That rewrite is the next part: Tracking Agent Work Outside the Chat Window.