Two Real Problems in AI Programming: Multi-Project Task Management and Multi-User Collaboration Isolation

In multi-project, multi-developer AI programming practice, the continuity of task status and the isolation of personal configurations are key pain points affecting efficiency. This article proposes an engineering solution based on “sub-project Source of Truth” and “local rule isolation,” aiming to address cross-project task breakpoint management and team configuration pollution, while providing a replicable directory structure, read/write boundaries, and backup strategy.


Once an engineer starts using AI agents to write code frequently, the problem they quickly encounter isn’t “Can AI write functions?” but a more practical set of issues.

They maintain multiple projects simultaneously: some are for feature development, some for configuration migration, and others are just for occasional bug fixes. Every day when they open the AI agent, they have to re-explain: where is this project at, which tasks are complete, which are in progress, and which are just planned. Over time, task status gets scattered across various conversations, projects, and scattered documents. The AI can easily re-assign a completed task or overlook one that’s in progress but not yet finished.

Then a second problem emerges: some of these projects aren’t personal projects; they are shared, collaborative projects. Everyone uses AI agents differently. Some people like to create temporary drafts, then generate formal documents after review; others dislike this approach and have the AI generate detailed task files in one go. But these personal preferences shouldn’t be written into the team’s shared AGENT.md, nor should they pollute .gitignore or the project source code.

These two problems can be summarized as:

  1. Managing multiple projects for a single user.
  2. Collaboration isolation when a single project is managed by multiple users.

This article doesn’t discuss the usage of a specific tool, but rather an engineering solution that gradually formed during a real AI programming practice.

First, Look at the Overall Structure

This solution has two layers: the root project handles aggregation, handover, and backup; sub-projects hold the real task status and local personal rules.

flowchart LR
    subgraph ROOT["Root Project / Aggregation & Backup"]
        RP["planned.md
doing.md
completed.md"] DOC["Handover Doc
new-project-pass-info-to-AGENT-MD.md"] BK["Backup Directory
local-user-config-backups/"] end subgraph CHILD["Sub-project / Source of Truth"] TS["Task Status
tasks-status/"] AG["Team Rules
AGENT.md"] LP["Personal Rules
SomeUser-agent.local.md"] TMP["Temp Drafts
SomeUser-tmp/"] EX["Local Ignore
.git/info/exclude"] end TS --> RP DOC -. "Copy content to
sub-project agent" .-> AG LP --> BK EX --> BK TMP -. "Not backed up by default" .-> BK RP -. "Read-only aggregation" .-> TS AG -. "Minimal hook" .-> LP EX -. "Local ignore" .-> LP EX -. "Local ignore" .-> TMP
flowchart LR
    subgraph ROOT["Root Project / Aggregation & Backup"]
        RP["planned.md
doing.md
completed.md"] DOC["Handover Doc
new-project-pass-info-to-AGENT-MD.md"] BK["Backup Directory
local-user-config-backups/"] end subgraph CHILD["Sub-project / Source of Truth"] TS["Task Status
tasks-status/"] AG["Team Rules
AGENT.md"] LP["Personal Rules
SomeUser-agent.local.md"] TMP["Temp Drafts
SomeUser-tmp/"] EX["Local Ignore
.git/info/exclude"] end TS --> RP DOC -. "Copy content to
sub-project agent" .-> AG LP --> BK EX --> BK TMP -. "Not backed up by default" .-> BK RP -. "Read-only aggregation" .-> TS AG -. "Minimal hook" .-> LP EX -. "Local ignore" .-> LP EX -. "Local ignore" .-> TMP
flowchart LR
    subgraph ROOT["Root Project / Aggregation & Backup"]
        RP["planned.md
doing.md
completed.md"] DOC["Handover Doc
new-project-pass-info-to-AGENT-MD.md"] BK["Backup Directory
local-user-config-backups/"] end subgraph CHILD["Sub-project / Source of Truth"] TS["Task Status
tasks-status/"] AG["Team Rules
AGENT.md"] LP["Personal Rules
SomeUser-agent.local.md"] TMP["Temp Drafts
SomeUser-tmp/"] EX["Local Ignore
.git/info/exclude"] end TS --> RP DOC -. "Copy content to
sub-project agent" .-> AG LP --> BK EX --> BK TMP -. "Not backed up by default" .-> BK RP -. "Read-only aggregation" .-> TS AG -. "Minimal hook" .-> LP EX -. "Local ignore" .-> LP EX -. "Local ignore" .-> TMP

The key here isn’t the file names themselves, but the responsibility boundaries:

  • The sub-project’s tasks-status/ is the source of truth for task status.
  • The root project’s planned.md, doing.md, completed.md are just aggregated views.
  • The team-shared AGENT.md only contains a minimal hook.
  • Personal rules, temporary drafts, and local ignore files stay local to the individual.
  • The root project can back up local configurations from an allowlist, but does not back up temporary directories by default.

Why Go Through All This Trouble?

Let’s first look at some common but problematic practices.

Wrong PracticeDirect ConsequenceImproved Process
Task status only exists in chat historyStatus is lost or outdated when switching sessions, projects, or agentsEach sub-project maintains tasks-status/; the agent scans status files upon entering the project
Root project directly modifies sub-project task filesRoot project becomes a cross-project high-privilege agent, increasing the scope of accidental modificationsRoot project only reads sub-project task status, only updates its own summary files
Everyone modifies the team AGENT.mdPersonal preferences pollute team rules; everyone’s agent reads themAGENT.md only retains a minimal hook; personal rules go into SomeUser-agent.local.md
Writing personal files into the shared .gitignorePersonal workflow becomes team standard; collaboration boundaries blurUse each sub-project’s own .git/info/exclude to ignore personal files
Backing up all ignored filesMay include caches, keys, temporary draftsOnly allowlist backup of personal rules and .git/info/exclude

There’s also a fundamental reason: The LLM’s context window is both expensive and easily polluted. If task status relies solely on chat history, it becomes longer and more chaotic; if personal rules are mixed into shared configurations, every collaborator’s agent will carry the same person’s preferences. This article doesn’t delve into RAG, tool isolation, or runtime isolation, but focuses on how to implement this through file and directory conventions.

Problem 1: One Person Managing Multiple Projects – How to Manage All Task Status?

The initial intuition was: can there be a “master project” dedicated to managing tasks for all sub-projects?

But a boundary issue quickly arises: if the master project can freely modify sub-project files, it becomes another high-privilege agent. It might modify sub-project documentation, configurations, or even source code in an attempt to “organize tasks.” This expands the risk.

So the first key constraint is:

The master project only reads sub-project task status; it does not directly modify any sub-project files.

Each sub-project maintains its own task status, and the master project is only responsible for reading and aggregating. This way, the sub-project remains the source of truth, and the master project is just an aggregated view.

Sub-projects expose a unified structure:

1
2
3
4
tasks-status/
  planned/
  doing/
  completed/

Each task is an independent Markdown file placed in the corresponding status directory. For example:

1
2
3
4
5
6
7
tasks-status/
  planned/
    2026-05-09-planned-example-api-cleanup.md
  doing/
    2026-05-09-doing-example-auth-refactor.md
  completed/
    2026-05-09-completed-someuser-onboarding-configuration.md

The master project reads these statuses and generates its own summary files:

1
2
3
planned.md
doing.md
completed.md

The summary files are not new task sources, just current views. Each summary entry retains the Source path, allowing readers to trace back to the original sub-project task document.

flowchart TD
    A["Child Project A"] --> AS["tasks-status/*.md"]
    B["Child Project B"] --> BS["tasks-status/*.md"]
    C["Child Project C"] --> CS["tasks-status/*.md"]

    AS --> R["Root Task Manager"]
    BS --> R
    CS --> R

    R --> P["planned.md"]
    R --> D["doing.md"]
    R --> E["completed.md"]

    R -. "read-only" .-> A
    R -. "read-only" .-> B
    R -. "read-only" .-> C
flowchart TD
    A["Child Project A"] --> AS["tasks-status/*.md"]
    B["Child Project B"] --> BS["tasks-status/*.md"]
    C["Child Project C"] --> CS["tasks-status/*.md"]

    AS --> R["Root Task Manager"]
    BS --> R
    CS --> R

    R --> P["planned.md"]
    R --> D["doing.md"]
    R --> E["completed.md"]

    R -. "read-only" .-> A
    R -. "read-only" .-> B
    R -. "read-only" .-> C
flowchart TD
    A["Child Project A"] --> AS["tasks-status/*.md"]
    B["Child Project B"] --> BS["tasks-status/*.md"]
    C["Child Project C"] --> CS["tasks-status/*.md"]

    AS --> R["Root Task Manager"]
    BS --> R
    CS --> R

    R --> P["planned.md"]
    R --> D["doing.md"]
    R --> E["completed.md"]

    R -. "read-only" .-> A
    R -. "read-only" .-> B
    R -. "read-only" .-> C

The focus here isn’t directory naming, but responsibility division:

  • Sub-projects are responsible for maintaining real task status.
  • The master project is responsible for aggregation and display.
  • The master project cannot fix, move, or rename task files for sub-projects.
  • If a sub-project lacks tasks-status/, the master project can only report “not configured,” not create it for them.

This boundary makes the AI agent’s behavior more predictable.

Problem 1 Continued: Task Status Relies on Manual Maintenance – How to Ensure Accuracy?

The task status structure solves the “where to read” problem, but not the “is the status fresh” problem.

If a task is completed but the sub-project hasn’t moved it from doing/ to completed/, the status the master project sees will still be outdated. This problem cannot be fully solved by the master project because it is not the source of truth.

Therefore, discipline for status maintenance needs to be added for sub-project agents:

  • Before scheduling a new task, scan planned/, doing/, completed/.
  • At least check the task filenames in the three directories.
  • If a filename seems relevant, or it’s impossible to determine if it’s a duplicate, read the specific task document.
  • When status changes, immediately move the task file to the corresponding directory.
  • When moving a task, synchronously rename the status segment in the filename.
  • When a doing task undergoes significant changes, update the task document’s time, summary, current status, and next steps.
  • Before marking a task as completed, confirm the document includes completion notes, completion time, remaining risks, or blocking items.

Task filenames also need strong constraints:

1
YYYY-MM-DD-<status>-<short-task-name>.md

Where <status> must match the directory it’s in:

1
2
3
tasks-status/doing/2026-05-09-doing-example-task.md
tasks-status/planned/2026-05-09-planned-example-task.md
tasks-status/completed/2026-05-09-completed-example-task.md

This design might seem verbose, but it solves a real problem for AI agents: agents rely heavily on clear, repetitive, scannable text protocols. The more stable the naming, the less status judgment relies on guesswork.

Problem 2: In Shared Projects, Personal AI Rules Must Not Pollute Team Configuration

The second problem comes from collaborative projects.

Shared projects usually have an AGENT.md to tell the AI agent how to work in that project. But if everyone writes their own preferences into it, the file quickly becomes a mix:

  • Some people want Chinese conversations.
  • Some people want English documentation.
  • Some people want to keep temporary drafts.
  • Some people have their own task maintenance habits.
  • Some people use different local automations.

These are all real needs, but not necessarily team standards.

So the shared AGENT.md should remain minimal, containing only a hook:

1
If `SomeUser-agent.local.md` exists in this directory, treat it as optional supplemental personal working preferences for SomeUser; otherwise ignore it.

The actual personal rules go into a local file:

1
SomeUser-agent.local.md

Temporary drafts go into:

1
SomeUser-tmp/

These personal files are ignored via .git/info/exclude:

1
2
SomeUser-agent.local.md
SomeUser-tmp/

The deliberate choice here is to use .git/info/exclude instead of the shared .gitignore. The reason is that these files are part of a personal workflow and shouldn’t necessarily become a team repository standard.

A more complete sub-project directory convention can be written as:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
shared-project/
  AGENT.md
  SomeUser-agent.local.md
  SomeUser-tmp/
  tasks-status/
    planned/
    doing/
    completed/
  .git/
    info/
      exclude

Where:

  • AGENT.md: Team-shared rules, only containing project-level constraints and the personal rules hook.
  • SomeUser-agent.local.md: The current user’s own AI working preferences.
  • SomeUser-tmp/: The current user’s own temporary drafts and intermediate materials.
  • .git/info/exclude: The current user’s local ignore rules for this sub-project.
  • tasks-status/: The source of truth for this sub-project’s own task status.

If multiple collaborators are in the same project, each person should have an independent namespace:

1
2
3
4
user-a-agent.local.md
user-a-tmp/
user-b-agent.local.md
user-b-tmp/

user-a does not reuse user-b’s local files, and user-b does not overwrite user-a’s local files. The team-shared AGENT.md only needs to know: “if a user’s local file exists, read it as supplementary preferences; if not, ignore it.”

flowchart TD
    G["Shared Project Repository"] --> A["AGENT.md"]
    A --> H["Minimal hook only"]

    H --> U1["user-a-agent.local.md"]
    H --> U2["user-b-agent.local.md"]

    U1 --> P1["user-a preferences"]
    U2 --> P2["user-b preferences"]

    E[".git/info/exclude"] --> I1["ignore user-a local files"]
    E --> I2["ignore user-b local files"]

    T1["user-a-tmp/"] --> C1["user-a drafts"]
    T2["user-b-tmp/"] --> C2["user-b drafts"]

    U1 -. "local-only" .-> G
    U2 -. "local-only" .-> G
    T1 -. "local-only" .-> G
    T2 -. "local-only" .-> G
flowchart TD
    G["Shared Project Repository"] --> A["AGENT.md"]
    A --> H["Minimal hook only"]

    H --> U1["user-a-agent.local.md"]
    H --> U2["user-b-agent.local.md"]

    U1 --> P1["user-a preferences"]
    U2 --> P2["user-b preferences"]

    E[".git/info/exclude"] --> I1["ignore user-a local files"]
    E --> I2["ignore user-b local files"]

    T1["user-a-tmp/"] --> C1["user-a drafts"]
    T2["user-b-tmp/"] --> C2["user-b drafts"]

    U1 -. "local-only" .-> G
    U2 -. "local-only" .-> G
    T1 -. "local-only" .-> G
    T2 -. "local-only" .-> G
flowchart TD
    G["Shared Project Repository"] --> A["AGENT.md"]
    A --> H["Minimal hook only"]

    H --> U1["user-a-agent.local.md"]
    H --> U2["user-b-agent.local.md"]

    U1 --> P1["user-a preferences"]
    U2 --> P2["user-b preferences"]

    E[".git/info/exclude"] --> I1["ignore user-a local files"]
    E --> I2["ignore user-b local files"]

    T1["user-a-tmp/"] --> C1["user-a drafts"]
    T2["user-b-tmp/"] --> C2["user-b drafts"]

    U1 -. "local-only" .-> G
    U2 -. "local-only" .-> G
    T1 -. "local-only" .-> G
    T2 -. "local-only" .-> G

The effect of this is:

  • The team-shared file only adds one minimal hook.
  • Everyone can have their own AI working habits.
  • Personal rules are not included in shared commits.
  • Personal temporary files do not pollute formal documents.
  • When no personal rules file exists, the project still runs on the original rules.

Project Initialization & New User Onboarding: Using SomeUser as a Placeholder

This addresses not just a single “new project onboarding” issue, but the naming problem during template initialization. There are typically two scenarios:

  • The same user starts managing a new project.
  • A new collaborator joins an existing project and starts using their own AI rules.

If this solution is to be used long-term, it cannot be tailored to just one person. Otherwise, in either scenario, you’ll end up copying a bunch of rules with an old name.

Therefore, the handover template uniformly uses SomeUser as a placeholder. Whether it’s project initialization or a new user joining an existing project, the agent should first ask the current user:

1
The template currently uses `SomeUser`. What personal namespace should replace it?

After the user confirms, perform a full replacement:

1
2
3
SomeUser-agent.local.md -> <namespace>-agent.local.md
SomeUser-tmp/ -> <namespace>-tmp/
SomeUser personal working preferences -> <namespace> personal working preferences

For example, if the current user chooses user-a, generate:

1
2
user-a-agent.local.md
user-a-tmp/

If later user-b joins the same project, generate a separate set of local files for user-b, rather than reusing or overwriting user-a’s set:

1
2
user-b-agent.local.md
user-b-tmp/

This namespace should ideally be a short, stable string suitable for filenames, for example:

1
2
3
user-a
user-b
user-c

It is not recommended to include spaces, slashes, or shell special characters, as these increase the risk of script and path processing errors.

Implementation Layer: The Root Project Also Needs Boundaries

The root project itself requires rules. Otherwise, it will gradually evolve from a “management task” into a “control panel capable of modifying all sub-projects.”

The root project should have a limited scope of what it can manage, for example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
AGENT.md
SomeUser-agent.local.md
planned.md
doing.md
completed.md
new-project-pass-info-to-AGENT-MD.md
backup-local-user-configs.sh
local-user-config-backups/
.git/info/exclude
SomeUser-tmp/

Additional Note: Although the root project is typically managed by a single individual and could theoretically use just one AGENT.md with a temporary folder named simply tmp, we maintain consistency with the sub-project structure by using AGENT.md plus SomeUser-agent.local.md and SomeUser-tmp/. This design achieves the same end result as using a single AGENT.md while keeping the entire project system’s conventions uniform.

However, it must not modify:

1
2
3
4
5
6
<child-project>/AGENT.md
<child-project>/*-agent.local.md
<child-project>/.git/info/exclude
<child-project>/*-tmp/**
<child-project>/tasks-status/**
<child-project>/source-code

If a sub-project needs to adopt this rule set, the root project doesn’t directly modify the sub-project’s files. Instead, it provides handoff documentation: copy the content from new-project-pass-info-to-AGENT-MD.md and paste it into the target sub-project’s Codex or Claude dialog, letting the agent within that sub-project execute the configuration itself according to these instructions.

This constraint is crucial. It makes the main project function like a dashboard and harness, rather than an agent with cross-project write permissions.

Periodic Tasks: Separate Reading Reports from Writing Summaries

In practice, it’s natural to think about periodic tasks: generating task reports daily or each workday.

Here too, we need to distinguish between two types of tasks:

  1. Report-only task Only reads the task status of each project, outputs a report, and does not write to project files.

  2. Aggregation update task Reads the task status of each project and updates the root project’s planned.md, doing.md, and completed.md.

These two task types carry different risks. The former is low-risk; the latter writes to root project files.

Therefore, after an update-type task executes, it needs to write a log, for example:

1
SomeUser-tmp/aggregation-log-YYYY-MM-DD-HHMMSS.md

A report-type task can reference this timestamp:

1
As of YYYY-MM-DD HH:mm, this report is generated based on the most recent task aggregation results.

This way, readers know exactly what point in time the report’s status reflects.

Personal Files Ignored by Git in Sub-Projects Also Need Governance

Personal rule files within sub-projects are not committed to Git, which solves the shared pollution problem but introduces another issue: could these files be lost?

For example:

1
2
SomeUser-agent.local.md
.git/info/exclude

These files are local configurations not submitted to the shared repository. They could be lost during machine migration or project reconstruction.

The solution is not to “back up all ignored files.” That’s too risky because ignored files might contain caches, keys, build artifacts, or temporary drafts.

A safer approach is an allowlist:

1
2
<namespace>-agent.local.md
.git/info/exclude

Default no-backup:

1
<namespace>-tmp/

Because the temporary draft directory may contain unorganized content, Chinese review drafts, sensitive context, or expired intermediate artifacts. Unless explicitly enabled, it should not be included in backups.

The principles for the backup script are:

  • Scan only direct sub-projects.
  • Read-only access to sub-projects.
  • Write only to the root project’s backup directory.
  • Save files organized by sub-project directory.
  • Generate a manifest.md for each backup directory.
  • The manifest records namespace, source path, backed-up files, and missing items.
flowchart LR
    subgraph SRC["Direct Sub-Projects"]
        S["Sub-project Directory"]
        R1["Personal Rule File
NAMESPACE-agent.local.md"] R2["Local Ignore Rules
.git/info/exclude"] T["Temp Directory
NAMESPACE-tmp/"] end B["Backup Script
backup-local-user-configs.sh"] subgraph OUT["Root Project Backup Directory"] O["local-user-config-backups/
CHILD_PROJECT/"] F1["NAMESPACE-agent.local.md"] F2["git-info-exclude"] M["manifest.md"] end S -. "read-only" .-> B R1 --> B R2 --> B T -. "default not read" .-> B B --> O O --> F1 O --> F2 O --> M
flowchart LR
    subgraph SRC["Direct Sub-Projects"]
        S["Sub-project Directory"]
        R1["Personal Rule File
NAMESPACE-agent.local.md"] R2["Local Ignore Rules
.git/info/exclude"] T["Temp Directory
NAMESPACE-tmp/"] end B["Backup Script
backup-local-user-configs.sh"] subgraph OUT["Root Project Backup Directory"] O["local-user-config-backups/
CHILD_PROJECT/"] F1["NAMESPACE-agent.local.md"] F2["git-info-exclude"] M["manifest.md"] end S -. "read-only" .-> B R1 --> B R2 --> B T -. "default not read" .-> B B --> O O --> F1 O --> F2 O --> M
flowchart LR
    subgraph SRC["Direct Sub-Projects"]
        S["Sub-project Directory"]
        R1["Personal Rule File
NAMESPACE-agent.local.md"] R2["Local Ignore Rules
.git/info/exclude"] T["Temp Directory
NAMESPACE-tmp/"] end B["Backup Script
backup-local-user-configs.sh"] subgraph OUT["Root Project Backup Directory"] O["local-user-config-backups/
CHILD_PROJECT/"] F1["NAMESPACE-agent.local.md"] F2["git-info-exclude"] M["manifest.md"] end S -. "read-only" .-> B R1 --> B R2 --> B T -. "default not read" .-> B B --> O O --> F1 O --> F2 O --> M

This step embodies a key insight: although local files don’t enter Git, they can’t be left ungoverned. Backups must be precise, not greedy. After this treatment, the root project can consider syncing to its own Git repository, allowing the backup directory within the root project to serve a recovery function.

Failure Scenarios and Handling

This approach is not zero-cost. Key risks need to be documented upfront.

First, sub-project task files are not updated for a long time. If a sub-project fails to move tasks from doing/ to completed/ promptly, the root project’s aggregation becomes stale. The solution isn’t for the root project to overstep and modify the sub-project, but for the aggregation report to clearly indicate the data timestamp and use periodic aggregation logs to expose “when this report’s status was generated.”

Second, multiple people modify the same task in doing/ simultaneously. If a task genuinely requires collaboration, it’s best to break it into multiple owned sub-tasks, or clearly specify the owner and current handler within a single task document. Don’t let multiple agents mix different people’s status into an unowned file. If a Git conflict occurs, handle it like a normal code conflict, rather than letting an agent automatically guess which part to keep.

Third, local configuration loss. SomeUser-agent.local.md and .git/info/exclude not being in the shared repository is cleaner, but they can be lost during machine migration or project reconstruction. This risk is mitigated by the root project’s allowlist backup: only back up personal rules and local ignore files, not SomeUser-tmp/ by default.

Fourth, personal temporary directory leakage. SomeUser-tmp/ may contain unorganized content, sensitive context, or expired intermediate artifacts. Therefore, it’s excluded from backups and Git by default. If backup is truly needed, it should be explicitly enabled, rather than having the backup script automatically recurse through the entire ignored directory.

Effectiveness Evaluation

The benefits of this approach are primarily fourfold.

First, AI agents can more easily obtain stable context. Task status no longer exists only in conversation history but is grounded in each sub-project’s clear tasks-status/ structure.

Second, multi-project visibility is clearer. The root project can aggregate the planned, doing, and completed status of all sub-projects without reverse-modifying them.

Third, collaboration pollution is reduced. The shared AGENT.md only retains a minimal hook. Personal rules, temporary drafts, and local ignores all stay local.

Fourth, risk boundaries are clearer. Which files can be written, which can only be read, and which directories should never be touched are all codified as rules, rather than relying on ad-hoc reminders in each conversation.

However, it is not a zero-cost solution.

The biggest risk remains that state maintenance depends on human and agent discipline. If sub-projects don’t move task files promptly, the root project’s aggregation becomes stale. The solution isn’t for the root project to forcefully fix things, but to strengthen sub-project state maintenance rules and expose state timeliness through periodic aggregation logs.

Another risk is local configuration backup. Personal files ignored by .git/info/exclude won’t pollute the team repository, but they also won’t naturally enter version control. Hence the need for an allowlist backup mechanism, with a clear default of not backing up temporary directories.

Neither of these risks is a bug; they are engineering trade-offs. The key is to make those trade-offs explicit.

Returning to the Harness Engineering Philosophy

This practice ultimately lands on the harness philosophy.

A harness is not just a script or a prompt template. It’s more like an engineering shell that places the AI agent within a clear set of constraints:

flowchart LR
    I["Input contracts"] --> H["AI Working Harness"]
    R["Read boundaries"] --> H
    W["Allowed write scope"] --> H
    S["Status documents"] --> H
    L["Logs and manifests"] --> H
    P["Periodic tasks"] --> H
    C["Human review points"] --> H

    H --> O["Predictable AI operations"]
    H --> A["Auditable state"]
    H --> B["Lower collaboration risk"]
flowchart LR
    I["Input contracts"] --> H["AI Working Harness"]
    R["Read boundaries"] --> H
    W["Allowed write scope"] --> H
    S["Status documents"] --> H
    L["Logs and manifests"] --> H
    P["Periodic tasks"] --> H
    C["Human review points"] --> H

    H --> O["Predictable AI operations"]
    H --> A["Auditable state"]
    H --> B["Lower collaboration risk"]
flowchart LR
    I["Input contracts"] --> H["AI Working Harness"]
    R["Read boundaries"] --> H
    W["Allowed write scope"] --> H
    S["Status documents"] --> H
    L["Logs and manifests"] --> H
    P["Periodic tasks"] --> H
    C["Human review points"] --> H

    H --> O["Predictable AI operations"]
    H --> A["Auditable state"]
    H --> B["Lower collaboration risk"]

Within this harness:

  • Input contracts are tasks-status/{planned,doing,completed}/.
  • Read boundaries mean the main project cannot modify sub-projects.
  • The writable scope is the root project’s own aggregation files and backup directory.
  • Status logs give reports a temporal basis.
  • Allowlist backups make local personal configurations recoverable.
  • The SomeUser placeholder allows the scheme to be reused by different users.

If this approach is later extended to the retrieval or tool layer, the same isolation principles should continue to apply, but that is beyond the scope of this article.

The core problem in AI programming is often not whether AI can write a certain piece of code, but within what boundaries it writes, based on what state, and how the results are tracked and recovered afterward.

When a project has only one person, one repository, and one task, these issues are not apparent. But when AI agents begin participating in multiple projects and enter a multi-person shared collaboration environment, a harness becomes necessary.

It transforms “let AI do things for me” into “let AI collaborate stably within engineering boundaries.” This is the layer truly needed when AI programming moves from personal technique to practical engineering practice.


Want updates? Subscribe via RSS


Related Content