# When the Repository Becomes the Project Interface

There is a strange thing about good architecture.Sometimes the best features are the ones you never had to build. You change the model. Then certain problems simply disappear. That is what started happening once tasks moved into the repository.

At first the benefits were obvious. Tasks could branch with the code. They could be reviewed in the same pull request. They could share history with the implementation. You could check out an old commit and see the project state that belonged to that version of the code.

Useful things.

But then other consequences started appearing. Some were small. Some were much bigger. The first one was almost boring.

## Offline mode disappears

Every task tracker eventually has to think about connectivity. What happens when the network is unavailable? What happens on a plane? What happens when the VPN stops working? What happens when the tracker service is down? What happens when authentication expires?

Traditional software solves these problems with features. Offline mode. Caches. Synchronization queues. Conflict handling. Retry logic. Local mirrors.

A repository-native system takes a different path. The tasks are files. They are already local. There is no special offline mode. You open the repository. The tasks are there. You edit them. You commit them. When the network returns, Git synchronizes the changes.

The task tracker does not need to know that the network ever disappeared. That is a useful kind of simplicity.

Not:

> We built excellent offline support.

But:

> Offline support stopped being a separate problem.

## The backend starts disappearing too

That led to another question.

If the filesystem stores the current state, and Git stores the history, what exactly is the backend doing?

A conventional tracker might have something like:

```text
UI
 |
API
 |
Application server
 |
Database
```

The server owns the project state. The client asks permission to see it. The client asks permission to modify it. The database decides what exists.

But with repository-native tasks, the shape is different.

```text
UI
 |
Files
 |
Git
```

The current state is in the working tree. The history is in Git. Synchronization is handled by Git. Authentication to the remote repository is already handled by Git. Branching is handled by Git. Conflict detection is handled by Git. A task application can still provide useful things.

A board. Search. Filters. Validation. Commands. Views. Automation.

But it no longer owns the project. It is a client of the project. That distinction matters.

## The tracker becomes replaceable

Suppose you have a project managed in a traditional SaaS tracker. Then the service disappears. What remains? Perhaps an export. Perhaps an API dump. Perhaps nothing.

Suppose instead that your preferred repository-native task application disappears. The repository remains. The task files remain. The workflow remains. The team configuration remains. Git remains.

You can open the tasks in a text editor. You can write another tool. You can use scripts. You can migrate later. The application can die without taking the project state with it. That feels healthy.

Tools should be replaceable. Projects should not be.

## One project, many interfaces

Once the files are the source of truth, something else becomes possible. There is no longer one official interface. A GUI can show a Kanban board. A CLI can list open tasks. An editor extension can show the task assigned to the current branch. A script can find everything marked `blocked`. A CI job can validate that task IDs are unique.

All of them work with the same underlying project state. There is no need for each interface to have its own database. No need for synchronization between them. No privileged application has to mediate every change.

This is a useful shift. The task tracker stops being an application. It becomes a protocol. The files are the protocol.

The tools are just views and editors.

## Then AI enters the picture

This is where the idea became much more interesting to me. AI coding tools are very good at working with repositories.

They can read files. They can search files. They can modify files. They can inspect diffs. They can run tests. They can follow references through a codebase. They already know how to operate in the world of the repository.

But ask them to work with project management state and suddenly things become harder.

Now they need another interface.

## AI and traditional trackers live in different worlds

Suppose I tell an AI coding agent:

> Implement TASK-042.

If TASK-042 lives in Jira, the agent first has to get there.

It may need:

*   a Jira integration;
    
*   authentication;
    
*   an API key;
    
*   a tool definition;
    
*   permission to call the tool;
    
*   network access;
    
*   knowledge of the right project;
    
*   knowledge of the right Jira instance.
    

Then it retrieves the ticket. Perhaps it has to retrieve comments separately. Perhaps attachments separately. Perhaps linked tasks separately. Then it returns to the repository.

Now there are two worlds. The project description lives in one. The implementation lives in another. The agent has to move context between them. That is not impossible. We have APIs. We have MCP servers. We have connectors. We have browser automation. But all of them exist because there is a boundary.

What happens if the boundary disappears?

## Files are already the native interface

Suppose instead that TASK-042 is:

```text
tasks/TASK-042.md
```

Now the instruction:

> Implement TASK-042.

is almost enough.

The agent can open the file. Read the requirement. Search for the relevant implementation. Inspect tests. Modify code. Run the tests. Update the task. Show the diff.

No task API is required. No separate authentication is required. No second service needs to be taught to the agent.

The agent is doing exactly what it already knows how to do. It is reading a repository. That is why files are such a useful interface. They are not glamorous. They are not new.

But almost every development tool already understands them.

## The lowest-friction API may be no API

We like APIs because they provide structure. That is valuable. But every API also creates a boundary. A client needs to know how to call it. It needs credentials. It needs schemas. It needs error handling. It needs versions. It needs network access.

When the information already exists in a file the tool can read, an API may not add much.

A coding agent usually already has primitives like:

```text
read file
search repository
edit file
list directory
show diff
```

Those primitives are enough to understand a Markdown task.

This does not mean higher-level tools are useless.

A dedicated command like:

```text
task.get TASK-042
```

may be convenient.

A tool that changes task status safely may be useful. A board API may be useful for large projects. But these become optimizations. They are no longer the only way to reach the data.

The repository remains the common denominator.

## “Implement TASK-042”

Consider a simple workflow.

The developer says:

> Implement TASK-042.

The agent reads:

```md
---
id: TASK-042
status: todo
assignee: coding-agent
---

# Retry failed uploads

Temporary network failures should be retried using exponential backoff.

## Acceptance criteria

- Temporary failures are retried.
- Permanent failures fail immediately.
- Behaviour is covered by tests.
```

The agent searches the repository.

It finds:

```text
src/uploader.cpp
src/network_error.cpp
tests/uploader_tests.cpp
```

It studies the implementation.

It changes the code. It adds tests. It runs them.

Then it updates the task:

```yaml
status: review
```

and perhaps adds:

```md
## Implementation notes

Implemented exponential backoff in `Uploader`.

The server currently does not distinguish all permanent failures.
See TASK-057.
```

Then it creates:

```text
tasks/TASK-057.md
```

The result is one project change.

Not:

```text
AI changes code
then reports something in chat
then human updates Jira
then human creates another ticket
```

but:

```text
code
tests
task update
new task
```

all in the same working tree.

This is much closer to how humans already work when they are disciplined about maintaining project state.

## The agent can discover work while doing work

This may be one of the more important consequences. Software work rarely follows the task exactly. You begin implementing something. You discover another bug. You discover that a requirement is wrong. You discover that the architecture cannot support part of the request. You find technical debt. You notice missing documentation. You realize that another task must happen first.

An AI agent can discover the same things.

Today, it often reports them back as prose.

> I also noticed that error classification should probably be improved.

Then somebody has to convert that observation into project state. Or nobody does. The observation disappears into the conversation.

If tasks live in the repository, the agent can create durable project state directly.

It can create:

```text
TASK-057 Improve server error classification
```

and reference it from the current work.

The discovery survives the chat. That is a big deal.

## Chat is a bad project database

AI tools produce a lot of useful information in conversation. They explain assumptions. They identify bugs. They suggest follow-up work. They notice architectural problems. Then the conversation ends. Perhaps the developer remembers. Perhaps not.

A chat transcript is a poor place for project state. It is chronological. It is noisy. It contains abandoned ideas. It contains questions. It contains speculation. It is difficult to query reliably. And it usually lives outside the repository.

The useful result of AI work should migrate into durable project artifacts. Code becomes code. Tests become tests. Documentation becomes documentation.

And discovered work should become tasks. The repository becomes the memory. The conversation is only the process that produced it.

## Code review can create work too

The same applies to review. Imagine an AI reviewer examining a change. It notices three things.

One is a bug that must be fixed before merge. One is a cleanup that can wait. One is a missing test for an unrelated edge case. The first belongs in the current review. The others may deserve tasks. Today, the agent might leave comments. Comments are useful. But review comments are attached to one pull request. After the pull request is merged, they become historical discussion. Follow-up work can easily disappear there.

With repository-native tasks, the reviewer can propose:

```text
tasks/TASK-071.md
tasks/TASK-072.md
```

Those files appear in the diff. The developer can reject them. Edit them. Accept them. Merge them. Now follow-up discoveries become project state.

This creates an interesting loop:

```text
task
  ↓
implementation
  ↓
review
  ↓
new tasks
  ↓
future implementation
```

The repository carries the loop.

## Humans and agents begin using the same language

This matters more than giving an AI access to Jira. With a tracker integration, the human and the agent can access the same data. That is useful. But they may still operate through different interfaces.

The human sees a board. The AI sees JSON returned by an API. The human writes comments. The agent calls tools. There is translation everywhere. A repository-native model gives them a simpler common language.

Both understand:

```text
TASK-042.md
```

Both can read:

```md
# Retry failed uploads
```

Both understand a Git diff. Both understand a branch. Both can refer to the same paths. Both can change the same artifacts. The GUI may still make things easier for the human.

Higher-level tools may still make things easier for the AI. But underneath, they share the same model.

That is important.

## AI does not need its own shadow project

There is a temptation when building AI development systems to create special infrastructure for agents.

Agent tasks. Agent memory. Agent plans. Agent state. Agent queues.

Some of that is necessary. An agent may need temporary state that humans do not care about. But there is a danger. You can accidentally create two projects.

The human project:

```text
Jira
GitHub
docs
repository
```

and the AI project:

```text
agent memory
agent plan
agent task graph
agent context
```

Then you need synchronization between them.

Again.

The whole problem returns at another layer.

A better approach, where possible, is to let permanent project state remain permanent project state. The agent can have temporary reasoning. Temporary plans. Scratch files. Execution state.

But once something becomes relevant to the project, it moves into the same artifacts humans use.

A discovered bug becomes a task. A design decision becomes documentation. An implementation becomes code. A requirement change updates the task.

That keeps the project from splitting into human reality and AI reality.

## One source of truth

The ideal shape starts looking simple.

Not:

```text
Human tracker
      |
      | integration
      v
AI task system
      |
      | integration
      v
Repository
```

but:

```text
             repository
             /        \
            /          \
        humans        agents
```

The repository contains the durable project state. Humans interact with it through whatever interfaces suit them. Agents interact with it through whatever tools suit them. But neither side owns a parallel truth. That reduces synchronization problems.

It also makes AI behaviour easier to inspect. If an agent changes the project plan, that is a diff. If it creates a task, that is a file. If it closes a task, that is a change in version control. If it changes a requirement, that can be reviewed.

Nothing needs to disappear into a hidden orchestration database.

## AI work becomes reviewable in the same way as human work

This may be the most valuable property.

Imagine an agent does this:

```text
M src/uploader.cpp
M tests/uploader_tests.cpp
M tasks/TASK-042.md
A tasks/TASK-057.md
```

A developer can inspect all of it.

The code. The tests. The change in task status. The implementation notes. The new follow-up task.

Maybe the agent was wrong.

Fine.

Reject the task.

Edit it.

Revert it.

The mechanism is ordinary version control.

This is much safer than letting an agent silently update an external tracker through an API where the changes are easy to overlook.

The common repository gives the agent power. Git gives the human visibility. Those two properties fit together well.

## This is not about letting AI do everything

There is an obvious failure mode here.

If an AI can edit tasks, why not let it rewrite the project plan whenever it wants? That would be a bad idea. Access should still have rules. An agent might be allowed to propose tasks but not commit them. It might be allowed to update implementation notes but not change acceptance criteria. It might move a task to `review` but not to `done`.

Another agent may only review. A human may remain responsible for merging project-state changes. The repository model does not remove governance. It makes governance visible. A proposed task can exist as a diff. A status change can exist on a branch. A human can review it before it becomes part of the main project state. That fits naturally with Git.

## Branches become safe places for agent work

This is another consequence of combining tasks and code. Give an agent a branch.

Let it implement TASK-042.

It can change:

```text
code
tests
documentation
task state
follow-up tasks
```

without changing the main project.

The branch becomes the agent's proposal. Then a human reviews the whole proposal. That is a much cleaner model than giving the agent permission to modify production project state in several independent systems.

Its changes are isolated. They are inspectable. They can be merged. They can be rejected. They can be partially accepted. We already know how to work this way. It is called version control.

## There is still value in specialized tools

None of this means everything should be done with `cat`, `grep`, and Git commands. A repository with ten thousand tasks may need indexing. A company may need cross-repository planning. Managers may want dashboards. Developers may want a board.

Agents may benefit from semantic tools such as:

```text
task.list
task.assign
task.move
task.create
```

That is fine. The distinction is where the authority lives. A specialized tool can sit on top of the repository. It can optimize access. It can validate rules. It can present better interfaces. It can provide automation. But the project should not become inaccessible without it. The abstraction can be richer than files.

The source of truth can still be files.

## The project begins to describe itself

Put all of these pieces together.

A repository may contain:

```text
src/
tests/
docs/

project/
    tasks/
        TASK-041.md
        TASK-042.md
        TASK-057.md

    statuses.json
    team.json
```

A developer clones it. They can understand what the software is. They can see what work exists. They can see the workflow. They can see who or what can own tasks. An AI agent receives the same repository. It can understand the same things. No separate onboarding API is necessary just to discover the project. The repository explains itself.

That is a powerful property.

## Maybe project management is part of the developer interface

This is where the original question starts to look different.

We began with:

> Why do tasks live outside the project?

That sounded like a storage question. It turned into a version-control question. Then a workflow question. Then an architecture question. Now it looks like an interface question.

What is the interface to a software project? For a long time, the answer was mostly source code. Then repositories gained documentation. CI configuration. Infrastructure definitions. Development environments. Architecture decisions. Instructions for coding agents.

Perhaps tasks belong there too. Not because every organization should abandon Jira. Not because Markdown is better than databases. But because the repository may be becoming something larger than source control.

It may be becoming the common interface through which humans, automation, and AI understand and change a project.

## And that changes the role of the task tracker

In this model, the tracker is not the place where work lives. The project is where work lives. The tracker is one view. A useful view. Sometimes an essential one.

But still a view.

A board can display tasks. A CLI can manipulate them. An IDE can show them. An AI can reason about them. All of those interfaces can come and go. The project state remains.

That is the part of this experiment I find most interesting. I started by asking what would happen if an issue were just another file. The answer was not only that issues would become easier to version.

The bigger answer was that the boundary between code, project management, and AI collaboration would start to disappear.

And perhaps that boundary was more artificial than we thought.
