Context Is Not Permission

How context, ownership, and authority became part of the workflow around an AI agent.

Design
AI
Systems Thinking
Engineering
Context Is Not Permission

I was building a solo vocabulary-learning product with an AI agent. For a while, the workflow worked because I was the integration layer. I knew which document was current, which decision was provisional, and which approved plan was not yet authorized for implementation.

Documentation, code, and product decisions already existed. The connections between them depended on my memory, and as the product grew, I could no longer keep track of them all. I needed the workflow to make those relationships explicit: which context was current, who owned it, what state it described, and what it authorized.

A workflow cannot depend on one person’s memory

The loop works only while one person still remembers what the record leaves out.
The loop works only while one person still remembers what the record leaves out.

I translated between design intent, documentation, and implementation. When AI proposed a change, I could usually spot the missing assumption because most of the product model still lived in my head.

The first crack appeared in a simple learner status. One vocabulary record was carrying identity, a specific meaning, participation, progression, scheduling, and evidence. The product could mark a whole word as "learned" even when the learner knew only one meaning. It also could not distinguish prior knowledge from learning verified after a delay. The domain model left those distinctions unresolved.

As changes began crossing the interface, learning logic, authentication, content, data, and analytics, "implement this correctly" needed explicit ownership and dependency boundaries to mean anything. I added those boundaries to the codebase so that knowing what could depend on what no longer rested entirely with me. The workflow needed the same treatment.

More context became a second problem

The information is present, but its role is not.
The information is present, but its role is not.

My first response to growing complexity was more documentation. docs/project-setup.md eventually reached 2,854 lines. It was meant to be the one place an agent could open and understand the whole project. The information was there, but it was hard to tell which parts were current, who owned them, and whether they described shipped behavior, historical reasoning, or a future plan.

I replaced it with a short index, focused setup contracts, and separate history.

The design-system document reached 1,842 lines after absorbing motion, PWA behavior, interaction rules, Practice patterns, and implementation guidance. It contained useful knowledge, but had become too broad for a human or an agent to review as a single contract.

I split it by ownership: foundations, motion and feedback, reusable components, product patterns, and separate implementation owners for runtime-specific behavior. Living contracts received line budgets, not because line 401 is dangerous, but because document growth can signal that one owner is absorbing facts that belong elsewhere.

I also made each document's lifecycle explicit:

  • Living contracts describe the current state.

  • Approved specs freeze instead of growing indefinitely.

  • History records earlier reasoning.

  • Status records preserve what a particular delivery slice actually shipped.

  • Approved-but-unimplemented architecture stays visibly separate from current behavior.

In one review, two reviewers gave opposite but reasonable advice about the same roadmap text. One wanted to preserve Completed as historical evidence; the other wanted to correct it as stale current documentation. The document had no declared lifecycle.

During a design-system cleanup, the sentence "motion should feel interruptible" nearly moved into the canonical motion contract. It sounded like a good principle, but the shipped interaction deliberately held a transition lock until the spatial movement finished. The code and the existing owning contracts agreed. The proposed sentence contradicted them.

Even a well-written document that is stored in the repository and reviewed by a model still has to agree with its owner, the runtime, and its lifecycle.

The first restructuring fixed the largest document monoliths. The root agent context still held too much policy detail. An earlier governance reset had cut AGENTS.md to 347 lines; later edits brought it to 350. I removed duplicated design context, turned project setup into a link-only index, gave documentation governance one owner, and reduced the root file to 91 lines.

I tested six representative tasks from fresh contexts. The agent reached the correct owner every time, with no missing or incorrect routes and no more than one hop from root. The root file now routed the agent to the owning documents.

This added owners, routing, links, and maintenance. Giving each fact one owner made that maintenance work visible.

Splitting the documents also meant deciding which system should hold them. Product reasoning, research, and decisions develop through discussion and rarely have one correct answer when they are written. Current behavior changes through code and can be verified at any commit. When both lived in the same store, a decision and a shipped behavior looked equally authoritative to an agent.

I separated them:

A disagreement between them needs to be named as drift. The agent should not resolve it by choosing whichever version is better written.

A correct document is not permission

More context did not answer what could change now.
More context did not answer what could change now.

The repository contains an approved target architecture for a future domain rebuild. It is current, canonical, and owned, and it can guide planning and decomposition. Changes to application code, the database schema, or migrations require a separately authorized slice.

A human may read that as "approved direction, not yet scheduled." For an agent reading a detailed specification, I needed to make the authorization boundary explicit.

I separated four layers:

  1. Product intent: what should change and why.

  2. Current executable truth: how the system works now.

  3. Approved target: where the system is meant to go.

  4. Implementation authority: what this delivery slice is allowed to change.

I turned this distinction into a decision-alignment preflight. Before substantial domain, data, target-architecture, or roadmap work, the agent has to compare the product decision source with the current repository, name conflicts, anchor the review to the relevant main commit, and identify the authorization state separately.

The first version was too strict. A conflict blocked even the documentation work needed to resolve it. To let the owners resolve a disagreement, I allowed a documentation-only resolution pull request based on a fresh main. Implementation remains blocked until the preflight is run again and the slice receives explicit authorization.

With those boundaries in place, the agent had more room to execute without treating an approved direction as permission.

A source of truth answers what should be treated as correct. A source of authority answers what action is allowed now. The agent needs both.

Authority made the allowed action explicit.
Authority made the allowed action explicit.

I developed this model in a solo project, where ownership is easier to change and authority ultimately sits with one person. My experience here is limited to my own way of working. In a team, the same distinction would need shared owners, explicit change rights, and language simple enough for people other than the author to use.

Also on this

The Process Became the Work: What happens after the boundaries are explicit: how verification, governance, and stopping conditions became another system to design.

Next Agent Workbench  opens in a new tab: A Next.js starter I built with shared agent rules for knowledge ownership and separating approved plans from permission to implement.