Haru Space Lab
Where should the gate stand when a free-form conversation becomes code?
An eight-day span connecting project coordination to real code work through editable briefs, shared actions, stage-aware rejection and rework, and durable audit boundaries.

Summary
At a glance
- We kept coordination conversations read-only and passed only a human-edited, human-confirmed execution brief into the existing code-work approval flow.
- Questions and answers were stored once in a dedicated ledger, while the work room received only the approved brief and a reference to its source.
- We unified the conditions for viewing, approving, rejecting, and reworking jobs across chat and coordination, while preserving the history of rejected work.
This retrospective was reconstructed from Haru Space design documents, Git history, and operational issues dated August 17–24, 2026. It does not disclose actual project conversations or rejection reasons, group, room, or job identifiers, internal addresses, or authentication information.
Projects begin in conversation before they become code.
Only after people have discussed what to build, who it is for, what lies outside the current scope, and what outcome will count as complete does the work become clear. Haru Space’s work room was strong at execution and approval, but its stage cards appeared too early for this kind of extended coordination.
Yet we could not connect every exchange in ordinary chat directly to a code job. A person might only be exploring an idea while the AI interprets the conversation as an instruction to change files.
We created a separate project coordination screen. Most of our time went not into improving the summary itself, but into deciding where the boundary should stand at the moment that summary became real code.
Free-form conversation needed to remain free. At the moment it became code, a person needed to confirm the target, the wording, the authority, and the responsibility once again.
Coordination began read-only
In project coordination, a group administrator could choose a workspace and an AI pet, then continue discussing the goal, the current code, risks, and completion criteria. The AI could read and explain the connected repository, but it could not modify files, commit, push, or deploy.
This was not merely a UI notice. We separated it as an execution contract. Coordination used a read-only profile and its own context. Actual write work began through the existing editing profile in a separate isolated workspace. A low-authority context did not gradually acquire write permission simply because the conversation had become long.
Access was also determined by membership in the current group, not by a platform-wide role. Even a platform administrator could not enter private coordination unless that person was actually an administrator of the group. Workspaces and pets were limited to those belonging to the current group and accessible to the user.
Knowing a great deal about a project and having the authority to change it were two different things.
We added a pause before creating a brief
Once coordination had progressed far enough, the AI could prepare an executable work brief. The first version of the button called the model immediately. An accidental click still consumed tokens and waiting time, and the user could not easily tell whether the action would also begin modifying files.
We added a confirmation step before generating the brief. It explained that the action would organize the conversation but would not change code. We also limited the length and number of items in the brief and stopped attaching a large duplicate of work-room messages that already existed in the dedicated conversation context.
We did not freeze the AI-written brief as a read-only result. The administrator could edit the text directly. Instead of requiring the final text to match the AI version character for character, the server checked that the source was a successful coordination brief from this group, that it had not already been sent to another job, and that the final wording was non-empty and described an executable goal.
The person was not merely an approver. The person was the editor of the actual work request.
A “do not execute” sentence reached the real execution step
The most revealing failure in the brief flow came from a meta-instruction in the prompt.
While asking the AI to prepare a brief, we told it not to modify files or deploy anything yet. The instruction was meant to prevent action only during the drafting stage. One brief, however, copied that sentence into the exclusions of the final work request. The brief was then passed into a real editing job.
Codex followed the instruction precisely. It inspected the code and checked the build, but changed no files. The runner treated the job as failed because a task that required changes had completed without any changes.
We could not dismiss this as the AI simply misunderstanding us. The system had mixed instructions from two different stages into one document.
We revised the brief-generation prompts in all three languages so that drafting-stage prohibitions would not be carried into the final brief. The more important safeguard was server-side validation. If a brief contained a prohibition on code or file changes that conflicted with a real editing job, the handoff stopped and asked the user to revise the brief.
Writing a good prompt and validating an execution contract could not substitute for one another.
We did not copy every question and answer into the work room
The first version of project coordination assembled AI responses in temporary screen state and projected some results into the ordinary work room. After leaving and returning, the user’s question disappeared while the answer remained in the work room. The flow of the conversation broke, and read-only coordination jobs were mixed into the same list as real development jobs.
Copying the entire conversation into both the work room and the work request would make the data and model context grow without bound. Saving nothing, on the other hand, would erase the basis of the agreement.
We created a separate coordination conversation ledger.
- Each question and AI answer is stored once in the coordination ledger.
- The original conversation is not copied into the ordinary work room.
- Only the final brief approved by a person becomes the execution snapshot for a real job.
- The work room shows the approved brief and a reference back to the source coordination.
- Older conversations are fetched page by page only when the user asks for them.
- The model receives only a bounded set of recent messages and moves to a fresh context after a set number of turns.
Keeping a record did not have to mean keeping every duplicate copy. We kept the original in one place and used the smallest human-confirmed snapshot for execution.
The same job showed different buttons on different screens
Once a real job had been created, another inconsistency appeared. In the work chat, users could view the job, approve or reject edits and dependencies, request commit and push, and decide on a pull request. The brief card on the coordination screen showed only a status line.
The actions available for the same job appeared to depend on where the user was looking. More seriously, each screen had implemented its own button conditions. That allowed a commit-and-push request to appear for a failed job, or caused the job-view action itself to disappear after a pull request was rejected.
We consolidated the behavior into a shared job policy and action component.
View job was neither a new feature nor a continue button. It opened the existing workbench dialog for the same job. As long as the job was valid, its details, changed files, and audit history remained visible whether it was running, successful, failed, rejected, or in any pull-request state.
Execution buttons, by contrast, followed only the current stage.
- Only the decision currently awaiting action—editing, dependencies, repository delivery, or pull request—appears.
- The initial commit-and-push request appears only after a real edit has succeeded and both changed files and a result fingerprint exist.
- No repository-delivery action is offered for failed, cancelled, rejected, analysis-only, or successful-but-unchanged jobs.
- A pull-request decision is revalidated against the approval room recorded by the server, not simply the room currently on screen.
We separated the right to inspect details from the authority to execute a new change.
Rejection had four different starting points
“Rework using the rejection reason” was not one operation. The safe starting point depended on what had been rejected.
Rejected before code execution
There is no change to preserve, so a new isolated job starts from the current authoritative repository. There is no reason to inherit the old workspace.
Dependency approval rejected
Safe changes and work context may already exist from before the approval point. A separate follow-up job continues from that isolated workspace only when the server and bridge can verify the original job.
Repository delivery rejected
The files have been changed and verified, but a person has decided not to apply them to the repository. The verified isolated changes become the starting point, while the new job goes through every approval step again.
Pull-request merge rejected
A reviewable result already exists on a remote source branch. A new isolated job starts from that branch and keeps the original protected branch as the final target. It does not quietly modify the rejected pull request or rewrite the earlier decision as a success.
A technical failure in the delivery runner was also different from a human rejection. If the change fingerprint had already been approved and only the execution failed, we retried the same delivery instead of creating a child rework job. When a verified commit already existed, recovery resumed from the push step rather than creating another commit unnecessarily.
Every one of these cases could look like “try again” in the UI, but their audit history and source of truth were completely different.
A rejection reason was both input for the next job and protected data
Every rejection required a concise reason. Empty values, excessively long input, and control characters were rejected by both the client and the server. The reason was used only in the job details and the follow-up prompt that needed it; it was not copied repeatedly into general audit details and logs.
The original job’s status, decision maker, time, and reason did not change. A follow-up had its own identifier, change fingerprint, and approval history. Keeping the earlier rejection intact made it possible to explain why the work had been attempted again.
A user could also put sensitive information into a rejection reason. We applied the existing central masking, but the presence of a filter was not an excuse to store the original in many places. Reducing the number of places that needed it was the first defense.
One long security table pushed the chat out of view
Project coordination often contains long pieces of text such as code, URLs, and security audit tables. In one conversation, an ASCII table made of uninterrupted characters expanded the message’s minimum width. The page hid horizontal overflow, so the text on the right was clipped and the whole chat appeared to have been pushed sideways.
Adding wrapping rules to the body alone was not enough. Every grid and flex layer, from the outer screen to the chat panel, scroll area, conversation row, and bubble, needed to allow its child to shrink. User bubbles could size to their content but not exceed a bounded part of the chat column, while only code and tables scrolled horizontally inside the message.
This layout issue also touched the product boundary. If an important rejection reason or audit result is clipped off-screen, the user cannot make a sound approval decision. A readable interface was part of the approval system.
A checklist for turning conversation into code
If we built this flow again, these are the questions we would ask first.
1. Does the conversation runner remain read-only all the way through?
A long discussion does not grant write authority. A real job begins under a new contract.
2. Can a person edit the AI brief directly?
Rather than only approving or rejecting AI output, a person takes responsibility for editing the final work request.
3. Are the brief’s origin and executability validated separately?
Verify that it came from the correct coordination message, then block wording that contradicts the actual editing goal at the server boundary.
4. Are the original conversation and execution snapshot stored without duplication?
Keep the coordination ledger once, then leave only the smallest approved brief and a reference in the job.
5. Do all screens use the same job policy?
Share the conditions for viewing a job and taking its current-stage actions. Screen-specific convenience must not take precedence over server authority.
6. Does each rejection stage restart from the correct source?
Before changes, start from the current repository; after changes, use a verified workspace; after a pull request, use the source branch. Recover technical failures within the same delivery.
7. Are past decisions preserved?
Create a new history for follow-up work. Carry the rejection reason only where it is needed, and never overwrite the original job as successful.
A place to speak freely and execute carefully
We did not create project coordination so that AI could start coding faster. We created it so that unresolved thoughts could be explored safely for as long as necessary, then enter the existing work system only after they had become sufficiently clear.
Over those eight days, the brief button gained a confirmation step, AI drafts became editable, and the coordination ledger separated from the work room. Job details remained accessible after failures and rejections, while repository delivery appeared only for successful jobs with real changes. Rework began from the source appropriate to the rejected stage and created a new history.
Every change was guided by the same idea.
Good AI collaboration is not the ability to turn conversation into action immediately. It is the ability to let a person choose the precise moment when free-form speech becomes a responsible change.
Leaving a reaction may store a random identifier in this browser to prevent duplicates.

