Preparing today's journal

Please wait a moment.

Back to stories

Beyond One Repository: How Each Group Came to Own Its Project

A three-day record of separating repositories, public sites, and AI workspaces by group while preserving human approval and operational boundaries.

Read like a book
Normal
An editorial illustration of a central workbench connecting several independent project models and public windows, with a blank approval card resting nearby

Topic

Haru Space Lab

Beyond One Repository: How Each Group Came to Own Its Project

A three-day record of separating repositories, public sites, and AI workspaces by group while preserving human approval and operational boundaries.

Summary

Summary

  1. We separated public sites from the private group app and operated them around static builds and Git-based approval history.
  2. We treated repository connection, AI execution, repository delivery, and public deployment as separate links and verified each stage.
  3. Instead of adding a process for every group, we used a shared scheduler and isolated project policies to protect both cost and recoverability.
12Page
An editorial illustration of a central workbench connecting several independent project models and public windows, with a blank approval card resting nearby

Summary

At a glance

  • We separated public sites from the private group app and operated them around static builds and Git-based approval history.
  • We treated repository connection, AI execution, repository delivery, and public deployment as separate links and verified each stage.
  • Instead of adding a process for every group, we used a shared scheduler and isolated project policies to protect both cost and recoverability.

This retrospective reconstructs July 29–31, 2026 from Git history, design documents, and operational incident records. It omits group identifiers, local paths, internal addresses, credentials, and private conversations that do not belong in a public story.

In the beginning, Haru Space was mostly a problem of operating one product and one repository well. Once groups began starting their own projects, building their own public sites, and assigning work to their own AI pets, the question changed.

Was it enough to add another menu to one application? Or did each group need a real separation of code and deployment, public scope and approval responsibility?

We chose the latter. But creating more repositories did not, by itself, create independent projects.

A group-owned project is independent not merely when its code lives elsewhere, but when the authority to read, change, and publish it remains separate all the way to the end.

We separated the public site from the private app first

Our first experiment was Haru Journal. Rather than adding a public page inside Haru Space, we made the group’s publishing site a separate repository and a separate deployment project.

That choice changed the data boundary before it changed the visual design.

  • The public site was a static experience that anyone could read without signing in.
  • Posts and images came only from reviewed files inside the publishing repository.
  • The public build did not directly read private chats, member or account data, or internal group documents.
  • Drafts were prepared on work branches. Publication required a human to merge the PR after checking all three languages, the content schema, rights, and public scope.
  • The public site held neither repository write credentials nor an administrator session.

We left out comments and real-time AI features for the same reason. The moment a site accepts input, it also inherits spam, reporting, privacy, model-cost, and retention responsibilities. We chose to stabilize a read-only public surface first and add interaction only after we were prepared to operate it responsibly.

A static site also fit our cost boundary. Visitors could receive it from a CDN without waking a server function and database on every view. We kept source images separate from the sizes actually delivered. Giving a group an independent project did not need to multiply idle cost by the number of groups.

A repository connection was only one part of being ready to work

The next problem was AI work. A “verified” label beside a GitHub or GitLab repository did not mean a pet could already read the code, edit it, and deliver the result back to that repository.

The real flow depended on four different connections.

  1. Haru Space confirms the relationship between the current group, its repository, and its base branch.
  2. The gateway knows the conversation and work project policies for that group.
  3. An installed runner prepares the approved repository inside a defined isolation boundary.
  4. A separate delivery runner writes only human-approved changes to a work branch.

If even one link was missing, the connection screen could be green while the actual job failed. At the same time, one bad group configuration could not be allowed to stop every existing group.

We therefore closed only the group whose connection was invalid or conflicting. We did not silently substitute another project for an ambiguous mapping. Conversation projects were read-only; work projects could edit only after approval. Repository write credentials did not go to the AI execution process and were used briefly only at the delivery stage.

The structure appeared to add more settings. Yet as the number of group projects grew, “choose a similar repository automatically” became the most dangerous convenience we could offer. A failed connection can be repaired. A successful operation against another group’s code is much harder to undo.

Manual registration did not last long

At first, an operator aligned the runner and gateway allowlists whenever a new project appeared. That worked for a handful of projects. In practice, however, the project name, conversation-versus-work distinction, repository location, base branch, and permissions for each execution identity all had to be repeated in several places.

If one value differed, the job failed before it even called a model. Environmental assumptions unrelated to repository content could also block preparation. When a runner was refreshed, an old instance could remain behind, making a restart in the UI different from a genuinely single running process.

Rather than make the manual guide longer, we moved toward approved automatic provisioning.

A group administrator requests a connection for a verified repository. An authorized administrator then confirms the boundary between group and repository. Only after that approval does the runner prepare the repository and synchronize its policy. If the repository or base branch changes, the old approval is not reused. A preparation failure does not roll back existing group or space data; it remains in a state that can be retried.

Automation increased, but the automatic approval boundary did not. Preparing a connection automatically and automatically merging or deploying a change made through that connection were still different decisions.

One demonstration could not prove success across repositories

To verify multiple repositories, we did not stop after one representative project worked. We checked, in sequence, whether read access, isolated editing, commit and push, PR creation, and deployment integration followed the same boundaries across different repositories.

The important result was not the content of the changes. It was the isolation of failure.

  • Does one group’s connection error leave other groups working?
  • Can a conversation be promoted into a writable job without approval?
  • Do the work runner and delivery runner keep their credentials separate?
  • Are direct and forced pushes to the base branch blocked?
  • Does a person still review the final scope before PR merge and public deployment?

Even the operational record avoided tokens, internal addresses, and local paths. Recovery should require only the project and stage that succeeded or failed, plus the policy version and change fingerprint that were checked.

We did not create a process for every scheduled group job

As group projects multiplied, recurring requests emerged naturally: “prepare this post every week” or “run this check at a set time.” The simplest implementation would have assigned a separate Cron and AI process to every group.

That design did not fit the resources of a small proof of concept. Persistent processes, configuration, logs, and failure points would all grow with the group count. Instead, one shared scheduler claimed only a bounded number of due tasks and processed them serially.

We also separated schedules into two kinds.

  • Simple reminders, calendar summaries, and weather updates do not call AI.
  • Only actual code or content work creates a structured work request.

Automatic approval for scheduled work could accept the request and start the initial edit, but no further. Commit and push, PR creation, merge, production deployment, database changes, and permission changes still crossed their existing human approval gates. A recurring schedule was not permission to publish every result automatically.

Each run received its own history so retries would not duplicate messages and jobs. After a long interruption, the scheduler did not flood rooms with every missed occurrence. It preserved the failure record and moved a recurring schedule to its next time.

One long job exposed the limit of scheduling

In production, one scheduled request combined research, image work, three-language writing, verification, and publication preparation. It exceeded the execution limit. The scheduler and automatic approval had worked correctly; only the downstream AI job failed.

At first, increasing the limit seemed like the answer. A bounded increase was useful in some cases. But extending execution time indefinitely also extended the time a single work slot could block everything waiting behind it.

The more important fix was to divide work by deliverable. Rather than asking one run to finish research, drafting, language review, images, and build verification, we could preserve intermediate results in the repository and let the next job continue from a verified artifact.

We did not deliver a timed-out partial result because it looked “almost finished.” Even if a Korean draft and images remained, the result was not publishable until all three language reviews and final verification were complete.

Group sovereignty became visible as the project count grew

What we built over those three days was not one multiple-repository feature. It was a standard for how groups, repositories, AI projects, workspaces, delivery, and public sites should relate to one another.

If I started again, I would keep this order.

1. Separate the public surface from the private source first

Let a public site read only approved public files or projections. Do not place visitor read access and editorial authority in the same runtime.

2. Show connection readiness as a set of stages

Do not compress SCM connection, runner readiness, repository delivery, and deployment integration into one green indicator. Show which layer failed and what recovery action comes next.

3. Do not confuse automatic preparation with automatic decisions

Automate repetitive configuration while preserving human approval for code editing, repository delivery, merge, and publication.

4. Do not add persistent resources for every group

Use a shared scheduler, conditional synchronization, and verification caches. A new group’s idle cost should not equal a new server.

5. Do not overwrite failure history with success

Keep partial artifacts, failed schedules, and rejected decisions as recovery evidence. Continue with a new history.

Building several baselines inside one platform

By the end of July 31, Haru Space was no longer an application that managed only its own repository. It was becoming a small platform where a group could own a separate project and public site, assign bounded work to its own pet, and deliver the result through its own approval flow.

Becoming a platform did not mean controlling everything from the center.

The center provides connection contracts, least privilege, auditability, and cost boundaries. Each group keeps its own repository, public scope, and final decisions. A failed connection closes within that group, and even successful automation does not open the final gate in place of a person.

The day we moved beyond one repository, what we gained was not simply more projects. We gained a way for different projects to move without crossing one another’s boundaries.

Continue reading

Previous story · Next story

Previous storyFrom Talking Pet to Approved Development Collaborator — Four Gates Built by FailureNext story Opening the Production Domain Began Behind the Screen