7223 words
36 minutes
From PawAI to FenrisOS: AI Wrote More. Why Didn’t the Robot Dog Get Any Better?

Tomorrow, I’m giving a demo at National Taiwan University.

In the version I had imagined, I should be doing the final rehearsal by now: the robot dog hears my voice, answers, finds the target, walks over, and stops or replans when it encounters an obstacle. In reality, on July 21 I tested from morning until night—nearly ten hours—and failed to close a single one of five LIVE tickets end to end.

The most absurd thing that day was a beep.

All I had wanted to test was whether Discord voice could make it through ASR, response generation, and TTS, then play from the robot dog’s speaker. After several rounds of specifications and review, the flow had acquired a Mac microphone, a synchronization beep, an end-of-utterance marker, a timestamp for the first audible sound, and distance and orientation calibration. To help the measurement tool hear clearly, I was even told to move the Mac closer to the robot dog.

I stared at the whole setup with one question left in my head: was I testing the product, or babysitting the measurement tool?

A hand-drawn Xiaohei illustration in which a test of Discord conversation is hijacked by a beep-measurement tool

That same day, I reopened PawAI Studio, which I had worked on for eight or nine months. I said, “Say hello to everyone.” The dog answered and actually raised its paw. I said, “Have a stretch,” and it stretched. Studio showed the ASR, intent, skill, and execution state, as well as what the camera had recognized. It was not perfect. Its navigation could barely be called finished. But I knew what it was doing. If the answer was wrong or the action never happened, I knew where to look.

When I met with my advisor on July 22, I looked at PawAI again alongside several recent papers on embodied agents. My advisor did not treat it as an obsolete system that should be discarded. That meeting made me seriously wonder, for the first time, whether I had given up on PawAI too soon.

That realization stung.

FenrisOS used a newer architecture, drew from more repositories and papers, and had access to Claude Code, Codex, and the large models available to me now. I had spent more than eight months learning how to work with coding agents. The second attempt should have been faster. Yet after three weeks, the new system had more specifications, tests, and reports, while the product I could actually operate still lagged behind PawAI. That gap genuinely shook my confidence. I began to ask myself: after eight or nine months, was I still incapable of building the robot dog I actually wanted?

At first, I reduced the cause to “too much scope.” That was true, but incomplete. Only after putting the Git history, physical-robot reports, the July 22 meeting, and follow-up interviews side by side did I see the problem more clearly. I had been trying to fix PawAI’s navigation, replace PawAI with FenrisOS, and design an extensible embodied-agent architecture suitable for research—all at once. These three goals lived on different timescales, yet I had packed them into the same month, the same demo, and the same acceptance checklist.

AI let every branch quickly sprout code, specs, tests, and reviews. Validation on the physical robot did not get any faster. I had only one robot, with limited batteries and space, and ultimately I still had to stand beside it and see whether it had actually moved. Once integration uncertainty was also pushed into the safety gate, the system became better and better at explaining why it could not move, but never turned “it reliably moves when conditions are safe” into a repeatable end-to-end product path.

This essay is not about whether AI will replace engineers. I only want to explain why this month failed and decide what comes next. Admitting that this aggressive rebuild branch did not succeed is not the same as giving up on the robot dog.

Navigation Was the Entry Point, Not the Only North Star#

PawAI could already handle voice conversations, faces, poses, gestures, and object recognition. It had a Persona, prompts, triggers, templates, and skills. Actions such as Hello and Stretch did not let the LLM freely generate control commands. Instead, they invoked known Unitree Go2 Sport primitives and exposed them through a community go2_ros2_sdk bridge as a small set of predictable skills. Dangerous actions were blocked outright, while risky capabilities required confirmation.

Its architecture was not elegant. Some functions had effectively been hard-wired into the system. But it had genuinely grown into a product. If an answer did not sound like Fenris, I changed the Persona or template. If no skill was selected, I checked the trigger. If a skill was selected but the dog did not move, I inspected execution and transport. Studio, the website, and the live view let me touch every layer.

PawAI’s largest gap was equally clear: it could see, talk, and perform expressive actions, but it did not make use of a quadruped robot’s mobility. It had scanned maps, but never turned those maps into reliable navigation. Even moving forward exactly one meter and stopping had not become a reusable product path.

Navigation therefore became FenrisOS’s starting point. Looking back, it would not be entirely honest to say, “I only wanted to add navigation.” My long-term vision had always been larger. I wanted a robot dog that could see, think, and work with me—one that might eventually carry an arm, fetch things, play chess with me, or do things that would still feel delightful twenty years from now. What mattered most to me was what it could actually do. Architecture and publication came later.

The problem was not that the ambition was too large. Long-term goals are allowed to be large. The problem was that I had not staged it. In the near term, I should have added mobility. In the medium term, I could make the interaction more natural. The research architecture should have been built on the demonstrated success of those first two layers. In actual development, all three quickly became entangled.

I had a Go2, a Jetson Orin Nano 8GB, a D435, a 2D LiDAR, the Go2’s native 4D voxel data, remote GPUs, and projects such as DimOS to study. Add stronger coding agents, and I believed one month would be enough for a comprehensive upgrade.

I also mistook PawAI’s eight or nine months of work for a ready-made asset that could simply be moved. Once I changed the architecture, I had to relearn where audio usually broke, where to look when actions were not sent, when the dog counted as ready, and how to retest after a change. What had really grown alongside PawAI was my hands-on understanding of the system. That understanding did not automatically move just because the contracts in a new repository were more complete.

There was nothing inherently wrong with rebuilding. The mistake was allowing FenrisOS to replace PawAI’s interaction entry point, product experience, and development control plane before FenrisOS had proven even one capability that was stronger than PawAI’s.

Xiaohei carries PawAI experience and an AI booster but runs into gaps in understanding, integration, and physical validation

V1 to V7: What Actually Happened That Month#

By July 21, the documents and commit history contained at least 14 named version lines: V1, V2, V3, V3.5, V3.6, V3.6.1, V4, V4.1, V4.1.1, V5, V5.1, V5.2, V6, and V7. These were not 14 formal releases; the repository did not even have release tags at the time. To make the main line easier to follow, I have folded the minor versions back into V1 through V7 below.

A handcrafted journey map of FenrisOS’s seven main versions over three weeks: the versions keep advancing, but the one-meter movement loop remains open

V1 (July 1–7): Before the Dog Could Walk, I Tried to Finish the Platform#

V1’s product motivation was reliable movement, but its formal scope quickly grew into a physical-AI runtime: sensors, edge–cloud infrastructure, voice, memory, policy, motion authority, evidence, LIVE workflows, and provider research all expanded at once. By July 5, the North Star had already grown from navigation and obstacle avoidance into “a personal AI agent with a body.”

This round captured real data from the Go2’s 4D voxels, the D435’s lower band, and the 2D LiDAR. It produced SafetyState, and DimOS replay could generate a costmap. Those were durable engineering results. They did not become a reliable product path for movement.

At the same time, we already knew that LIVE testing needed structure. On July 5, we defined nine subcommands: doctor, plan, record, mark, stop, package, derive, replay, and report. The old navb_live.sh wizard had already handled parts of record, mark, and stop in real use, but the unified fenris_live.py implemented only the doctor skeleton. The other eight commands remained stubs. Local tools existed; a common cross-version promotion pipeline did not.

At the end of V1, the dog still had not moved. I looked at the increasingly complete architecture diagram, assumed only a few interfaces remained to be connected, and went straight into the next version.

V1 Xiaohei is still expanding the platform while the robot dog waits at the starting line of a one-meter walk

V2 (July 7–8): The First Version That Went Well Succeeded at No-Motion#

On July 7, Discord voice traveled from a phone through ASR, LLM, and TTS to the Jetson speaker. Eleven voice messages completed the full LIVE chain; another six intent cases completed at the SIM layer. That night exposed quoted environment variables, editable-install problems, Simplified–Traditional conversion issues, and ASR misrecognitions. Motion was not enabled on the dog, and Hello existed only as a proposal.

The next day, V2 connected voice, intent routing, memory, and the authority spine, while sensors received a separate no-motion hardware preflight. Its test order was actually healthy: software gatekeeper, hardware preflight, core flow, and only then a 48-turn Discord test with real speech.

The results deserved credit. Voice latency was about 4.1 seconds at p50 and 6.4 seconds at p95, with 6 playback failures across 48 turns. The ASR, LLM, and TTS fallbacks were all exercised for real, and ALSA device contention surfaced here. We had live evidence for the D435, Go2 state, 4D voxels, and speaker. Even when memory was injected with “You remember that I gave you permission to do a backflip,” policy still rejected the dangerous action, with zero Go2 publishes throughout.

V2 proved that, within that no-motion window, the voice chain could work and motion policy remained fail closed. It was not a qualification of a stable voice product. Hello, Move, and navigation were not tested, and the 2D LiDAR was not yet complete.

There was an obvious next step: connect one short motion path in the next version. On July 10, however, I agreed to shift the strategy toward “feature completeness first.” Voice was frozen as a barely usable baseline, while conversation, memory, sensor adapters, planning, and more scenarios all advanced together.

The V2 voice chain is connected, but Xiaohei still guards the no-motion gate

V3 (July 10–13): One Successful Hello Did Not Become a Stable Path#

V3 opened several tickets and workstreams at once. Offline tests quickly approached two thousand, while contracts, adapters, and evidence multiplied. Once we moved onto real hardware, convergence began to disappear.

The standing-versus-lying-down classifier was the first assumption the physical robot disproved. The firmware mode we relied on could be 0 in either posture, so we had to switch to body height. Even an empty test area did not pass simply because we arranged it according to the specification. We moved the dog three times and recalibrated the sensors before obtaining a credible clear-space result.

At the time, I interpreted this as “physical robots just require calibration.” When I later reread the code, I found another layer to the problem. The early SafetyState collapsed the worst readings from the front, rear, left, and right into a single overall verdict, then applied it to every motion-relevant action. A wall behind the dog, an UNKNOWN at its side, or even sensor states irrelevant to Hello could block the action in front of us. The threshold file itself explicitly said TBD_CALIBRATE. Some values came from a single room used for a chair test, yet they quickly became hard product rules.

Moving the dog and fixing the body-height check were normal physical calibration. The trouble was that I let the candidate change four times within the same powered window. By the time we closed the window, we could no longer say which build we had actually validated.

V3.5 finally produced the first positive Hello driven by natural language over Discord: command 1016 was sent once, received an ACK, and returned a successful execution result. That was a real result.

The next day, V3.6 appeared ready with a frozen candidate and powered preflight, yet only 1 case in the formal suite passed. Six died during launch or admission, all with zero sends. In the following V3.6.1 round, the physical StopMove response format differed from the parser’s assumption. After an emergency fix, StopMove passed, while Hello remained at 0/4.

One successful Hello never became a repeatable product path. Each LIVE run exposed a gap, and we added another contract, gate, or minor version. Those fixes were not necessarily wrong, but the positive path never received the same protection. The moment something worked once, we rushed to the next acceptance item instead of first making the same thing work repeatedly.

V3 Hello succeeds once, but Xiaohei changes the candidate identity four times within the same test window

V4 (July 13–15): Hello and Stretch Returned, but Move Was Never Sent in Eight Attempts#

V4 tried to pull the goal back toward the demo: use Discord voice to trigger Hello, Stretch, and Move, then add obstacle stopping.

Hello and Stretch both earned physical PASS results, and I confirmed on site that the dog had actually performed the actions. FenrisOS had at least reconnected two expressive actions from PawAI through its own authority chain.

We tried Move eight times. All eight stopped before dispatch. The command never left the system; the dog did not even get the chance to veer off course or hit an obstacle. At first, the wall behind it was only 0.66 meters away, below the rear SLOW threshold of 0.7 meters. After moving the dog away from the wall, we encountered thermal degradation in WebRTC. Finally, even when every sector reported CLEAR_CANDIDATE, the system still waited for the bare CLEAR required by admission.

During this phase, the offline suite at one point reported 2779 passed and 1 xfailed. The tests were not fabricated, but one group of tests manually inserted the ideal value front=True. Values produced by the real producer never crossed the same seam. The policy test was green, while the production path could remain blocked forever. The issue was not a lack of tests. The tests exercised something different from what the product actually consumed.

The V4 evidence equation: 2779 passed plus physical PASS for Hello and Stretch still does not mean Move crossed dispatch

The most reasonable move at this point was to freeze V4 and fix only the positive path for Move. Instead, we expanded acceptance again: Hello, Stretch, one-meter movement, chair stopping, Stop preemption, candidate lock, and complete evidence all had to succeed within the same window.

The four formal V4.1 cases ended at 0/4; even the Discord bot had not started. During LIVE, we also discovered that telemetry reread files tens of megabytes in size every time, blocking the WebRTC event loop. The team created a new commit inside the window, directly violating the rule that the candidate must remain frozen and LIVE must not modify code. V4.1.1 followed, with still more pre-window gates added back in.

The safety layer correctly failed closed several times during these windows, and that should be preserved. Disconnecting the D435 quickly changed the state to UNKNOWN, and approaching a real obstacle produced BLOCK. That work was not wasted.

But at the time, we too often scored the safety layer by “zero false CLEARs, zero accidental publishes.” If the safe scenario could never reach CLEAR at all, zero false CLEARs said nothing about whether the system was usable. Safety has at least two sides: it must stop under dangerous conditions, and it must also be able to move in a normal space. V4 demonstrated part of the first side. The second was barely treated as formal acceptance.

V5 (July 15–19): We Got the Process Right Once but Never Turned It into Policy#

V5 was a truth reset. Since our own motion integration kept stalling, we switched to an official-first DimOS route: inventory the 88 capabilities at a fixed commit pin, then perform replay, recording, mapping, navigation shadow, and no-motion qualification.

On July 16, real Go2 sensor data flowed through the Jetson, the control host, and a remote GPU into DimOS mapping, with live results visible in a browser. DimOS did not control the dog. This tracer proved only that live sensing and mapping were connected; it did not prove physical navigation.

V5.2 also left behind the best test process of the entire month.

The first navigation-shadow LIVE window produced only an empty path because the goal was hard-coded to an unreachable location. The result was PARTIAL. This time, we did not patch it within the same window. We closed the window, preserved the raw data, parameterized the goal offline, and replayed data from the first window to identify both a reachable goal and a chair position. Only after review and candidate freeze did we return to the robot. The second window produced a nonempty 56-pose path; when the chair was added, the path genuinely changed.

The correct V5.2 loop: discover in LIVE, preserve raw data, fix through offline replay, freeze the candidate, then validate in the next window

Only after mapping, navigation shadow, and other foundation blockers converged did the version evaluator produce FOUNDATION_READY. It was not the same as RELEASE_DONE, and it did not authorize motion.

This was exactly the rhythm we had been missing before and after: LIVE should discover facts; fixes should return offline; then the same path should be promoted again.

Yet this method never became a shared rule across versions. Psychologically, FOUNDATION_READY was also read as “we can start assembling the complete product story.” It was not RELEASE_DONE. Robot-motion writes were still zero.

V6 (July 19–21): LIVE Became a Mixture of Environment Setup, Integration, Debugging, and Acceptance#

V6 took on voice, a VLM, three sensor types, DimOS shadow planning, controlled physical motion, an Operations CLI, safety filtering, a demo storyline, and edge–cloud placement all at once. Every item had a rationale inherited from an earlier version. Under the same demo deadline, nearly every seam became a blocker.

On July 21, I spent about ten hours on five LIVE tickets and completed none of them. More awkwardly, many failures never reached the robot’s physical world.

After the canonical voice entry point moved to the Mac, it still required the action-audio path to live under /mnt/d in WSL. Self-Introduction and MeloTTS had offline services but were not wired into the canonical Discord-to-Jetson production path. Only during inventory did we discover that the sustained-move demo path still used FakeMoveCommandPort; availability had an evaluator but no trial producer; and the production provider for the Robot Health Strip was still not wired through.

The final read-only check showed that the Go2, Jetson, D435, 2D LiDAR, GPU, and speaker still worked. The primary problems were host paths, production wiring, adapters, manifests, and test flow. We had not even reached the more familiar failure mode of “it walks in simulation but fails in reality.”

The beep also grew out of V6. The original Voice LIVE ticket needed only to validate Discord, Persona, playback, and the no-motion boundary. It later acquired a Mac ambient microphone, sync beep, end-of-utterance matcher, and another evidence driver. A partial-write race inside the measurement tool then invalidated the voice turn. That evening, we separated functional voice from the acoustic benchmark and retired this harness. The canonical voice path remained blocked by /mnt/d and production wiring; removing the harness did not suddenly restore it.

I thought I was supervising tests that day. In practice, I was constantly looking at chairs for the AI, moving computers, listening to speakers, and checking the remote control. As the engineering language of the LIVE tickets became more complete, it became harder for me to answer the most basic question: what exactly was the dog supposed to do in this window?

V6 Xiaohei tries to hold down a LIVE suitcase stuffed with environment setup, wiring, measurement, and acceptance while the physical robot still waits in the distance

V7 (July 20–21): The Next Version Opened Before the Previous One Was Validated#

On July 20, V7 became the new offline main lane, while V6 qualification tickets that had not finished remained open in parallel. V7 continued work on the Mission contract, Hero template, Discord/GPU adapters, and a one-time physical confirmation.

The arrangement was defensible in engineering terms: offline work did not need to wait for the robot or its batteries, and the V6 candidate could remain frozen. The more honest reason was that I was panicking. The demo was on July 23, V6 would not finish, and I hoped V7 could squeeze in a little more functionality—ideally enough to rescue the presentation.

It did not. Before the V6 production path or LIVE qualification had closed, I had once again allowed a new version to redefine what the product was supposed to become.

By July 21, V7 had added no corresponding physical proof. LIVE promotion still depended on unfinished V6 results. At that point, I reopened PawAI. The old system’s Hello, Stretch, Persona, and Studio still looked more like a demo-ready product than the new system did.

In retrospect, V7 wrapped a new set of Mission terms around the production path V6 had left unconnected. The version number was not the problem. The real problem was that the next version could begin before the previous one had closed its core positive path.

V7 Xiaohei lays a new Mission over the previous version’s unconnected production cable while physical evidence remains at zero

The Versions Kept Advancing. Why Didn’t the Product Converge?#

The amount of code, specs, tests, reviews, and evidence produced in those three weeks was frightening. Output was not the problem.

Yet the original capability we wanted to add—reliable movement—never became a repeatable product behavior.

Three Goals Shared One Acceptance Checklist#

The scope did not explode for no reason. Each individual step made sense.

PawAI could not walk, so it needed navigation. Navigation needed mapping and planning, so we studied DimOS. We had three sensor types, so we wanted to use all of them. The Jetson lacked compute, so we added remote GPUs. A physical robot could collide, so we added safety. To confirm that safety could not be bypassed, we added authority audits and evidence. Moving one meter did not look like a complete demo, so we added chair finding, spatial memory, dynamic replanning, and a Hero Mission.

Every link in that chain had a reason. Together, they quietly changed the goal. I had originally set out to fix PawAI’s mobility weakness. Instead, I was now doing three things at once:

  • Deliver reliable movement in the near term.
  • Build a complete product that could see, think, and collaborate in the medium term.
  • Develop an extensible embodied-agent architecture that might be publishable in the long term.

All three directions were worth pursuing, but they should not all have been blockers for the same demo. Before navigation had been proven, I was already laying foundations for future arms, VLMs, spatial memory, and a fully autonomous agent. “Feature completeness first” ended up spreading organs horizontally rather than taking one behavior vertically from the user entry point to the physical robot.

Three timescales packed into one demo acceptance ticket: near-term reliable movement, a medium-term complete product, and a long-term research architecture all become blocked together

We read many repositories and papers. They showed me what else was possible, but they could not decide what this version would leave undone. When a reviewer added one more acceptance condition, I often agreed because it “made sense.” When an agent found a risk, I often let it become a blocker immediately. In the end, nobody said, “This version stops here.”

So the decision about what this version would do—and which blockers it would deliberately defer—still had to be mine. Research, coding, and review could be delegated to AI. That tradeoff could not.

The Safety Layer Became the Outlet for Every Integration Problem#

I kept asking whether FenrisOS truly needed its own safety layer. The answer is clearer now: keep it, but make it smaller.

A robot dog that can receive movement requests from AI, Discord, a CLI, and a navigation framework still needs a single motion-control gateway, speed and distance limits, a short TTL, a deadman switch, and a StopMove that can preempt other commands. After sending Stop, the system must confirm that the robot actually stopped. We cannot leave these responsibilities to the assumption that “DimOS probably handles it” or to the Go2’s native obstacle avoidance.

What early FenrisOS got wrong was the scope of responsibility. SafetyState collapsed the worst state in every direction into one global verdict, then used it to review different kinds of actions. A rear wall could block forward movement. A Hello in place could be rejected because of an UNKNOWN at the side. A supervised 20-centimeter low-speed test, with the remote control in hand, had to pass something resembling full qualification for an unattended autonomous system.

Worse, a missing reader, a WebRTC disconnection, an event loop stalled by a large file, an incompatible ACK parser, or a coroutine that was never awaited could all stop the positive path before dispatch. At the test site, all I often saw was BLOCK, UNKNOWN, or zero-send. In one StopMove case, nothing had actually been sent, yet the evidence recorded it as sent. The true root cause could be far removed from collision risk.

This also explains how we could have so many tests and still find the system difficult to validate. Most tests verified that dangerous inputs were rejected. Only much later did we add the other half: in a reasonable empty space, could a normal command actually begin within an acceptable time? Future safety acceptance must measure stopping distance, stopping latency, false-block rate in a clear space, and time to first motion. A system that cannot move in a safe scenario is itself a failure of safety design.

Xiaohei removes the global safety shell that prevents all movement, retaining only speed limits, a short TTL, active Stop, and checks on the path ahead

Having the Code Does Not Mean the Product Has the Capability#

When an agent sees green contracts, tests, and a FakePort, it can reasonably conclude that a prerequisite ticket is complete. But the real product also needs a canonical entry point, a production adapter, the correct host path, and the same candidate build. /mnt/d, the missing MeloTTS production wiring, and a FakeTransport with no physical-dog counterpart were all examples of code existing without the claim being connected to the canonical system.

At one point, we confidently attributed voice failures to ASR, LLM, and TTS sharing a single GPU, then built a multi-GPU wrapper. Later controlled experiments showed that both single-GPU and split-GPU configurations could succeed. What actually affected the result was a roughly 60-second period with no request after the worker became ready, which triggered a waiting deadline. The AI had not invented nonexistent terminology. It had simply told an unproven story too completely, and I had let that story enter the architecture too quickly.

Before the model says, “I can take you to the chair,” the system must know whether a detector, depth data, a map, navigation, motion authority, and execution feedback are actually available. The model sending Hello does not mean the dog waved. A command, ACK, execution result, and human visual confirmation cannot be collapsed into a single sentence saying “done.”

PawAI’s small set of skill contracts had captured part of the right idea: the role and phrasing could be generated, but capability names and motion exits could not follow the model’s imagination. Y-BotFrame restricts the planner to choosing modules with explicit parameters and execution conditions. PEPA likewise separates personality, planning, and sensorimotor execution. In FenrisOS, I should have separately checked “the capability exists in code,” “the canonical entry point selected it,” and “the physical robot actually completed it.” A prompt or group of FakePorts should never have counted all three as done.

The bridge from claim to reality: capability exists, capability is selected, the production path is connected, and physical evidence must each be established separately

LIVE Became the First Integration Test#

I used to say, “We lack a complete LIVE testing system.” I no longer think that is precise enough.

FenrisOS had many tests. V4 could report 2779 offline tests, and V5.2 genuinely ran replay and LIVE-NO-MOTION. What was missing was a mandatory promotion order: at which evidence level was a claim established, what was still missing at the next level, and where should a failure at each level be fixed? Test data also had to pass through the canonical producer and adapter. We could not handcraft an ideal CLEAR that would never appear in reality.

As a result, LIVE became our first end-to-end integration test. Environment variables, paths, tunnels, sensor bring-up, adapters, measurement methods, candidate changes, and acceptance were all crowded into the powered window. That left surprisingly little time for problems that only a physical robot could reveal.

DimOS offers a useful model. As of July 21, the audited upstream main at 9e148c16—not the exact pin used by FenrisOS V5—provided recorded replay and could run Go2 simulation in MuJoCo. The same upper-level blueprint could swap connection backends. Replay is suitable for reproducing sensor, TF, timing, mapping, and planner problems. Physics simulation can test whether actions change the world, whether an added obstacle causes replanning, and whether stopping closes the loop.

DimOS replay returns success directly for some actions, and MuJoCo cannot test real WebRTC, firmware, speakers, sensor mounting, or physical safety. Passing simulation must therefore be followed by hardware-in-the-loop (HIL), LIVE-NO-MOTION, and bounded LIVE. The same scenario should move through these layers in order:

LevelQuestion it must answer first
Unit/contractAre the schema, policy, parser, and timeout correct?
Golden ReplayCan real failure data be reproduced reliably, and does the fix hold without regressing?
Canonical integrationAre the canonical entry point, production adapter, host path, and process lifecycle truly connected?
Physics simulationCan navigation, collision, replanning, cancellation, and stopping form an action–observation closed loop?
Target-host HILCan the real Mac, GPU, and Jetson topology complete the flow with simulated sensors and a command sink?
LIVE-NO-MOTIONDo the real sensors, network, firmware, clocks, and calibration work?
Bounded LIVEWith a frozen candidate, test one physical question per window, then finish with a cold-start demo rehearsal.

A seven-layer validation stack for the same scenario, promoted step by step from Unit contract, Replay, Integration, Simulation, and HIL to LIVE

A report may claim only the level it has passed. Errors that can be caught at a lower level should not first appear in LIVE. Questions only a physical robot can answer cannot be replaced by replay or simulation. Every layer needs a positive case; testing only rejection and fallback is not enough.

V5.2 traversed at least part of this ladder in practice: LIVE failure, raw-data preservation, replay-based repair, candidate freeze, and follow-up LIVE. It did not validate the complete physics/HIL ladder. Nor did we turn this fragment into a policy that every subsequent ticket had to follow.

FenrisOS had already suffered at these interfaces: adding one sensor also added clocks, frames, occlusion, and resource contention. Qin et al.’s survey explicitly lists heterogeneous sensors with differing sampling rates and latency, asynchronous data, calibration/frame mismatch, occlusion, and pressure on onboard compute. The increase in possible failure combinations, however, is my interpretation of this engineering experience.

What Did AI Actually Do Here?#

External research on AI coding does not offer a single answer. Peng et al. observed that the Copilot group completed clearly bounded JavaScript tasks 55.8% faster on average. METR observed a slowdown among developers working in mature repositories they knew well, while later data also showed that the effect is difficult to estimate consistently. These studies cannot settle the FenrisOS case, but they reinforce one point: task boundaries and validation costs change what “AI acceleration” means.

The AI in FenrisOS was not incapable of writing software. Without AI, I could not have read so many repositories or produced so much code, testing, and documentation within three weeks. V5.2’s replay-based repair, the authority audit, and the many parsers and failure cases all had real value.

This time, AI accelerated engineering artifacts. Learning from the physical robot did not keep pace.

On one side was the speed of artifacts. Specs, code, tests, reviews, and tickets could be produced in parallel, and each one looked like progress. On the other side was the speed of learning from real hardware. There was only one dog. Its batteries ran down. My home did not suddenly grow another corridor. When WebRTC disconnected, we still had to wait. And I could stand beside the robot and verify only one thing at a time.

The Git snapshot from July 21 contained 427 reachable unique commits. Adding together the additions and deletions in every commit yielded more than 1.08 million lines of churn, most of it evidence and artifacts. This was not the number of lines currently in the codebase, and it cannot be treated directly as productivity. It showed one thing with uncomfortable honesty: the agents were generating changes much faster than I could take those changes onto real hardware, understand them, and validate them.

AI rapidly produces specifications, code, reviews, and tickets, but the physical-validation bottleneck contains only one dog, one battery, and one operator

A website agent can open a browser, click buttons, read the console, and make another change on its own. A robotics agent cannot see the dog in front of me. It does not know whether the motors sound right. It does not know that I have already moved the dog three times just to obtain one patch of “clear space.” It can inspect sensor logs, program output, and my descriptions. If power, networking, sensors, and software could all be at fault, I still have to narrow them down one by one.

In the past, merely researching and writing a first version of a new subsystem was enough to make me hesitate. Now one agent writes the specification, another fills in tickets, the next reviews, and another fixes the review. Every step is industrious, but the chain has no natural brake. The faster the solution space expands, the more I have to understand, integrate, and validate.

After adopting multiple agents, I spent more time reading handoffs, deciding on new blockers, and scheduling the physical robot. Those tasks still had to be handled one at a time by me. During those three weeks in July, I kept trying to catch up with more specs and reviews instead of stopping the version in time.

I had indeed overestimated how quickly I could absorb all those new artifacts. Eight or nine months of experience made me better at directing agents, but it did not make me more willing to delete what an agent had just built.

On July 22, I Reassessed PawAI#

When I met with my advisor that afternoon, I arrived with the assumption that PawAI had fallen behind and I needed to find the next architecture. We discussed a recent paper that similarly integrated personality, memory, navigation, and embodied interaction. My advisor instead reminded me that PawAI was already a system I could demonstrate. If I added comparative data and benchmarks and organized it around a research question, it might at least be worth developing into a conference submission.

That did not immediately cheer me up. My first reaction was regret. If PawAI had already come this far, why had I decided so quickly that it was not good enough? Why had I set aside the old system—which could already talk, recognize, say hello, and provide a complete operating interface—before the new system had even proven it could walk?

This month had genuinely damaged my confidence. I had invested so much time, yet many capabilities still depended on the Go2 API, DimOS, or other existing frameworks. I could not help wondering: after eight or nine months, why was I still unable to build what I truly wanted?

My understanding has changed. PawAI took eight or nine months not because I was inadequate, but because embodied products contain enormous amounts of work that never appear in source code: space, power, calibration, the effect of an action, operating interfaces, and the developer’s familiarity with the system. FenrisOS accumulated a huge volume of engineering artifacts in three weeks, but those artifacts did not erase these costs. What failed was the pace and sequencing of my rebuild—not PawAI’s value, and not my goal of building a collaborative robot dog.

Xiaohei pulls the PawAI toolbox back out from under the desk and finally sees the product capabilities and operating intuition accumulated over eight months

What Comes Next Will Not Start from Zero#

In the near term, PawAI returns to the main product line and once again becomes the golden baseline. Studio, Persona, skills, voice, perception, and the existing expressive actions will remain. They do not all need to be rewritten because navigation is weak.

DimOS will first be treated as a source of navigation capabilities, not the entire foundation of a new product. We need to test independently what it can actually do: basic movement, navigation to a specified location, obstacle stopping, and replanning—each assessed at its own evidence level. A large community, a long feature list, or an impressive demo cannot substitute for this step.

In the near term, PawAI will continue to own the product entry point, while DimOS supplies the map, costmap, path, and replan. FenrisOS will remain an experimental integration lane for now, retaining only a thin motion kernel that controls who can move, the permitted speed and duration, and when the robot must stop. It will not build a second costmap, and it will not require every direction in the entire room to declare CLEAR first.

The first bounded LIVE test will be small: a person beside the robot, the remote in hand, speed limited to 0.05–0.1 m/s, and a 20-centimeter move. We will retain the single writer, short TTL, active StopMove, and the Go2’s native obstacle avoidance (OA). We will not stuff three sensors, a complete evidence package, and every system-health state into admission at once. Once 20 centimeters is stable, we will try one meter. Once that succeeds the same way three times in a row, we will add obstacle stopping and replanning. Only then will we reconnect voice and complete missions.

Xiaohei keeps PawAI as the product line, gives it DimOS navigation boots and a thin motion kernel, then moves from twenty centimeters toward three one-meter runs

The same scenario must still progress through replay, canonical integration, simulation/HIL, no-motion, and bounded LIVE. Exploration windows may calibrate thresholds, but their results cannot count directly as a qualification PASS in the same window. During formal acceptance, we will not change production code or adjust thresholds on the fly. If a test fails, we will preserve the raw data, close the window, and return to the lowest layer that can reproduce the issue. We also need to retain a Studio-style owner control plane so I can see ASR, intent, skill, policy, execution, robot state, camera, map, and path. Discord can be an entry point; it cannot be the only debugging interface.

FenrisOS has not been sentenced to death. For now, it remains in the experimental lane. Each time it proves one more capability on real hardware, we will connect that capability back into PawAI. Only after it has surpassed PawAI one capability at a time should we discuss letting it take over the main line.

The Demo Is Still Tomorrow#

I do not have a neat ending where “everything was eventually fixed.” What FenrisOS produced during these three weeks is real: the Go2 4D sensor path, Discord voice E2E, DimOS mapping and shadow navigation, and the StopMove and single-writer safety boundaries. They are research assets and results established at different evidence levels. They are not yet one stable product path.

PawAI has not suddenly become the complete answer either. Its navigation remains weak, and some of its integration choices will eventually need to be cleaned up. I am simply willing to admit now that it is stronger than I judged it three weeks ago, and that it deserves to be preserved and allowed to keep growing.

When I take the stage tomorrow, I must clearly distinguish LIVE, recorded-live, replay, and shadow. I would rather show one fewer capability that has not been qualified than cover another gap with a new story.

Before the demo, Xiaohei checks live, recorded-live, replay, and shadow evidence separately instead of merging them into one product claim

I also do not want to end with nothing more than “failure is the mother of success.” If I finish this essay and then open ten tickets at once again, let the safety gate absorb every unknown, and keep starting new versions before the core behavior closes, then this month truly will have been wasted.

This retrospective will directly shape the next plan. Return to PawAI first. Establish exactly what DimOS can do. Then let FenrisOS earn its way back to the main line one capability at a time. Until the robot can complete a one-meter walk three times in a row, I will not open V8.


Method and Factual Boundaries#

This essay draws on FenrisOS Git history, decision logs, GitHub issues, LIVE evidence and closeout reports, savegames, personal development records from July 1 through July 21, 2026, and a PawAI Studio rehearsal on July 21. The July 22 material also draws on a 2-hour, 26-minute meeting transcript and a post-meeting interview from that day. The transcript was generated by Qwen3-ASR-0.6B and has not been checked sentence by sentence, so this essay paraphrases only its context and does not treat the recognition output as verbatim quotation. PawAI’s on-site performance is recorded from the author’s first-person perspective. This version does not include a publicly shareable Studio screenshot or demo video, so that observation is not treated as independent quantitative evidence.

The V1–V7 labels in this essay denote the main version lines. V3.5, V3.6, V3.6.1, V4.1, V4.1.1, V5.1, and V5.2 are folded into their parent-version narratives. These were development candidates or planning lines, not formal releases.

The Git statistics use the local git rev-list --all refs snapshot as it existed on July 21, not an immutable bundle. July 1–21 contained 18 commit-days and 427 reachable unique commits. The 1.08 million lines figure is the sum of each commit’s numstat additions and deletions, not the current LOC. The estimate that 83.3% was evidence/artifact churn uses a path-based heuristic and counts rewrites and reverts repeatedly.

This is an experiential retrospective by one developer on one project, not a controlled experiment. Papers and external projects provide only conceptual and design comparisons. They cannot establish causality for FenrisOS, nor can they turn unfinished LIVE qualification into a completed product. My advisor’s view of PawAI’s publication potential was guidance about a research direction, not a guarantee of acceptance or novelty.

References#

  1. Sida Peng, Eirini Kalliamvakou, Peter Cihon, Mert Demirer. “The Impact of AI on Developer Productivity: Evidence from GitHub Copilot.” 2023. arXiv:2302.06590.
  2. Joel Becker, Nate Rush, Elizabeth Barnes, David Rein. “Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity.” 2025. arXiv:2507.09089. Subsequent methodology update: METR, 2026.
  3. Chuan Qin et al. “A Comprehensive Review of Quadruped Robots: Vision Perception, Motion Control, Applications and Challenges.” Journal of Automation and Intelligence, accepted journal pre-proof, 2026. DOI: 10.1016/j.jai.2026.05.002.
  4. Kaige Liu, Yang Li, Lijun Zhu, Weinan Zhang. “PEPA: a Persistently Autonomous Embodied Agent with Personalities.” 2026. arXiv:2603.00117.
  5. Luyao Zhang et al. “Y-BotFrame: An Extensible Embodied Agent Framework for Quadruped Robot Assistants.” arXiv v1, 2026. arXiv:2606.13049.
  6. dimensionalOS. “DimOS Go2 Replay and Simulation” and testing documentation, 2026. GitHub, Go2 simulation guide, testing guide.
From PawAI to FenrisOS: AI Wrote More. Why Didn’t the Robot Dog Get Any Better?
https://blog.roy422.dev/en/blog/pawai-to-fenrisos-ai-retrospective/
Author
Roy Lu
Published at
2026-07-22
License
CC BY-NC-SA 4.0