Context is infrastructure
A document that no agent loads is not context. A document that loads with no date is a liability. Both must be handled by the system, not by good intentions.
Agentic SDLC · context on disk · plan unmeasured
When agents do every stage of the lifecycle, the repository stops being the place where code lives and becomes the place where the work lives. Context, conventions, decisions, and checks must all sit on disk, in scope, and with a date. Anything not on disk is invisible to the agent. Anything without a date will be wrong eventually, and will still read with authority.
Seven stages One manifest Four detectors Three tiers
Illustrative manifest · from the plan, not a real repository
Put every durable fact on disk, index it, and serve it with a status.
One curator role. Four detectors in CI. Six weeks of habit change.
No context file is served without a date. Dead paths fail the build.
A document that no agent loads is not context. A document that loads with no date is a liability. Both must be handled by the system, not by good intentions.
A missing file makes the agent ask. A stale file makes the agent confident. The second is worse, so absence must be loud and staleness must be visible.
If a fact can be computed from the repository, compute it at load time. A file tree, a route list, and a schema can never go stale if nobody stores them.
The whole lifecycle
Discovery, design, build, verification, deploy, release, and operation all run with a model in the loop. The human does not leave the lifecycle. The human moves to the decisions and the checks, and the agent takes the production between them.
The table below is the load bearing one. For each stage, it names what the agent produces, what a person owns, and what has to exist on disk before the stage can start.
| Stage | Agent produces | Human owns | On disk | Gate |
|---|---|---|---|---|
| Discover | Clustered requests, prior art, a draft problem statement | What is worth doing | specs/NNNN.md | G1 intent |
| Design | Options, trade-offs, and a draft decision record | The choice, and the reason | docs/adr/NNNN.md | G1 intent |
| Build | The change, a trace to the spec, and migration notes | The declared scope | Code and .agents/exemplars/ | G2 conformance |
| Verify | Candidate checks, coverage runs, failure analysis | The oracle, written outside the agent | acceptance/NNNN.ts | G3 acceptance |
| Deploy | Build, deploy, rollback steps, and a flag set to off | The deployment, and the rollback | Flag registry, runbooks/ | G4 deploy |
| Release | Notes, cohort size, and a risk summary | Whether a user sees the feature | Flag state, generated notes | G5 release |
| Operate | Triage, correlation, first diagnosis | The response and the trade-off | runbooks/, incident record | Post incident review |
| What changed | Why it breaks the old process |
|---|---|
| Review costs more than writing | Review time rose 91 percent while change size rose 154 percent |
| Planning loses to action | A model starts producing in seconds, so the plan feels like a detour |
| Generation is no longer scarce | Every engineer has a licence, so the constraint moves to review and coordination |
| Records multiply | Jira, the wiki, and the changelog are all hand maintained and all disagree |
| Context does not travel | Every session starts blind, so every session rebuilds a private model of the system |
The other four cost time every week. Missing context costs correctness, because each agent rebuilds the architecture from whatever it happens to read first. Two agents on the same task with different context will produce two defensible and incompatible answers.
Assignment
Assume every engineer has a licence and can generate code. Access is not the constraint. The constraint is that ten parallel changes need one shared scope, one review standard, and one record. If everyone owns a feature end to end, ten people generate and the review queue absorbs all of it.
Run the item as three stages instead. The whole team plans, one writer generates, the team reviews, and the writer role rotates daily. Several items can generate at once when their scopes do not overlap. A stage is a unit of work with a fixed handover, so an agent can pick up a stage without owning the feature.
| Stage | Who | Can run in parallel | Hands over |
|---|---|---|---|
| Plan | Anyone, in one weekly session | Yes, in parallel | Spec, checks, and declared scope |
| Generate | Writer, rotates daily | Yes, by declared scope | Change, trace, and test notes |
| Review | Two reviewers plus one agent | Yes, across items | Pass, or a named defect |
| Integrate | Integrator, rotates weekly | No, one merge order | Trunk |
Generation is cheap and review is not. A queue above fifteen means the team is planning work it cannot review. A queue below three means the next item is not ready when a writer frees up. Three to eight planned items keeps planning and generation fed without building a review backlog.
The on disk layer
Multiple agents need the same explanation of the system. If that explanation lives in a chat, a person's head, or a ticket comment, each agent rebuilds it. The versions then disagree. Put it on disk, in one location per fact, with a structure the loader can act on.
Four rules decide what is allowed in. One canonical home per fact. Scope declared in the file. A date and an owner on every entry. Nothing derivable is stored.
AGENTS.md # entry point, under 150 lines, points to the index
.agents/
index.json # the manifest: scope, tier, owner, date, status
context/
invariants.md # rules that must never break
domain.md # the vocabulary and the business rules
tooling.md # commands, versions, local setup
exemplars/ # one canonical file per pattern
skills/ # procedures, loaded only when named
generated/ # written by CI, never edited by hand
tree.json # the module map
routes.json # the HTTP surface
schema.sql # the current schema
docs/
architecture.md # one page, current
adr/ # decisions that must not reopen
specs/
0042-export-limits.md # the work item itself
acceptance/
0042-export-limits.ts # written outside the agent
| Layer | What belongs here | Never here | Written by |
|---|---|---|---|
| Entry point | Commands, the map, the bans, and where to look | Architecture essays | Context curator |
| Invariants | Rules a change must not break | Preferences and style opinions | Tech lead |
| Domain | Vocabulary and business rules | Code walkthroughs | Domain owner |
| Exemplars | One real file per pattern | Descriptions of a pattern | Tech lead |
| Skills | Repeatable procedures with a trigger | Anything always loaded | Whoever runs it twice |
| Generated | Facts computed from the repository | Anything a person typed | CI only |
If a fact can be computed from the repository, compute it at load time. A file tree, a route list, a schema, and a dependency graph can never go stale if nobody stores them. Every stored fact is a future inconsistency.
Two copies of the same rule will disagree within a quarter, and the agent will read the wrong one. If a second document needs the fact, it carries a pointer, not a copy. Duplication is the cheapest bug to introduce and the hardest to find.
Secrets, tokens, customer data, and anything that changes hourly. A file in the repository will be read by an agent with tools, quoted in a transcript, and possibly committed to a branch. Volatile status belongs in the tracker, and the tracker is a projection of the spec, not the reverse.
Discovery
A large context window makes it tempting to load everything. That spends the token budget on files the agent does not need and buries the file it does. The fix is a manifest that maps a task to the documents whose scope covers the paths in that task.
Every document declares the paths it applies to. The loader selects by scope, sorts by tier, and attaches a status header. The agent never guesses which file matters.
{
"id": "invariants",
"path": ".agents/context/invariants.md",
"scope": ["packages/core/**", "apps/web/**"],
"tier": "canonical",
"owner": "tech-lead",
"verified_at": "2026-10-21",
"verified_commit": "a1b2c3d",
"expires": "2027-01-21",
"status": "suspect",
"detectors": ["paths", "claims", "drift"],
"checks": ["scripts/check-invariants.ts"]
}
| Tier | Meaning | The agent may | The agent may not |
|---|---|---|---|
| Canonical | Verified against the current commit and passing its checks | Act on it without re-reading the code | Edit it silently |
| Working | Human written, verified recently, checks not run | Use it, and cite the date | Treat it as proof |
| Unverified | Stale, suspect, or never checked | Read it for orientation only | Use it to justify a decision |
If no document covers a path, the loader writes "no context for this path" into the prompt and names the path. An agent that knows it is uninformed will read the code and ask. An agent that receives silence will assume there was nothing to know, and invent the rest.
Decay
Missing context produces a question. Stale context produces confidence. The agent reads an obsolete rule, applies it precisely, and reports success. The failure is not that the document is old. It is that nothing marks it as old.
So the design has two halves. Detect the decay in CI, and tell the agent at read time, in the prompt, on every load. A dashboard nobody reads is not a control.
| Detector | What it checks | Cost to run | Result |
|---|---|---|---|
| Paths | Every path, command, and symbol named in the document still resolves | Seconds | Stale |
| Drift | No file inside the scope changed since the verified commit | Seconds | Suspect |
| Claims | Each stated invariant has a script, and the script passes | Minutes | Stale |
| Expiry | The review by date has not passed | None | Stale |
[context] .agents/context/invariants.md
status: suspect
verified: 2026-10-21 at a1b2c3d
drift: 3 files changed in scope since that commit
rule: check the code before you rely on this claim
rule: do not edit this file. Report it as a finding.
[context] apps/billing/**
status: none
rule: no document covers this path. Read the code and say so.
public void DoWork()
{
// ...
}
| Status | How it is produced | What the agent must do |
|---|---|---|
| Verified | All four detectors pass | Act on it, and cite the date |
| Suspect | A watched path changed after the verified commit | Check the code before relying on a claim |
| Stale | A check failed, or the expiry date passed | Do not use it for a decision. Report it |
| Quarantined | Stale for longer than the grace period | Never served. Treat the path as uncovered |
A deleted document loses the knowledge and the history. A quarantined document keeps both and stops being served. The loader reads the manifest, so moving the status to quarantined is the whole mechanism. No file moves and no agent needs retraining.
If confirming a document takes ten minutes of hunting, nobody will do it and the whole system rots. One command re-runs the detectors, stamps the date and the commit, and writes the new status. Five minutes is the target, and the tool decides the rest.
Stage one
Planning loses to action because action gives feedback in a minute and planning gives feedback in a week. You cannot argue someone out of that. You can make planning shorter, make it social, and give it a visible payoff.
The payoff is structural. An unplanned item cannot enter the ready queue, so nobody writes it. Planning is how an item competes for review attention, because a planned item is small enough to review in one sitting.
| Rule | Why it works | Failure it prevents |
|---|---|---|
| Fifteen minutes per item | A longer plan means the item is too large | Specs that become a second project |
| Plan together, once a week | Boring alone, tolerable in a room | A solo chore that gets deferred |
| Produce two things only | One sentence of intent, and the checks | Documents nobody reads |
| Show the ready queue | Planning visibly moves an item closer to a writer | The feeling that planning changes nothing |
| No spec, no writer | A writer only takes an item with a declared scope | Generation on a half formed request |
# 0042 · Export limits
Intent: an export stops at 500 rows unless the caller asks for more.
Checks:
- Default export returns 500 rows and sets truncated: true.
- limit=100 returns 100 rows.
- A limit above 5000 returns 422 and no file.
Scope: apps/web/exports, packages/core/export, one migration.
Out: pagination, queue changes.
Context: .agents/context/domain.md, .agents/exemplars/route.ts
# That is the whole document. If it does not fit, split the item.
A model asked to draft the spec will produce a confident version of the request you actually made, including the parts you were unsure about. You then review your own ambiguity with more confidence than before. The intent must come from a person.
Stage three
A reviewer does not get faster with practice. The change gets smaller, the questions get specific, and the reading gets shallower on purpose. Three tiers, one hard size cap, and one fixed window in the day.
The agent reviewer runs first and clears the mechanical noise. A human still signs, because a model that reviews its own family of output shares the blind spot that produced it.
| Tier | Size | Reviewers | Agent role | Target |
|---|---|---|---|---|
| T1 · small | Up to 200 lines | 1 person | Comments first, human confirms | Same day |
| T2 · normal | Up to 600 lines | 2 people | Filters noise, human decides | Next day |
| T3 · risky | Over 600, or any schema, auth, or money change | 2 people plus a demo | Runs a risk checklist | Two days |
A change above 600 lines is split before review starts, not after it stalls. This one rule does more for review latency than any tool. It also forces the plan to be real, because a change that cannot be split was not planned as one unit.
| Review question | Who answers it | Time |
|---|---|---|
| Does the change match the spec and the scope? | First reviewer | 5 minutes |
| Does it follow an existing exemplar? | First reviewer | 5 minutes |
| Is there an acceptance check that the author did not write? | Second reviewer | 5 minutes |
| Did the change read a document marked suspect? | Second reviewer | 2 minutes |
| Is there a rollback path? | Second reviewer | 5 minutes |
Thirty minutes, same time every day, the whole team. A change is reviewed in the window or it waits for the next one. Review stops being a favour that interrupts an afternoon, and latency becomes predictable enough to measure.
Deploy and release
Ten teams can work on ten features if they share one trunk. Each feature merges behind a flag that starts off, so every team deploys on every merge. The code is in production while the feature stays dark. A developer owns that deploy. Product owns the flag turn-on.
This split removes the release train. Work lands when it is ready, and users see it when product decides the risk is acceptable.
| Step | State | Owner | Gate |
|---|---|---|---|
| Create | The flag exists and defaults to off | Developer | The spec names the flag and the off behaviour |
| Merge | The code is on trunk and the flag is off | Reviewer pair | Tests cover the on path and the off path |
| Deploy | The build runs in production and the flag is off | Developer | The deploy is green and reversible |
| Validate | Real traffic runs the code and no user sees a change | Developer and QA | Errors and latency stay flat |
| Release | The flag is on for one cohort, then wider | Product | A product decision, with a recorded reason |
| Retire | The flag and the dead branch are deleted | Developer | Within 30 days of full rollout |
The developer deploys on every merge, watches the dark feature, and can roll the deploy back without asking. Deployment is a technical event with a technical owner, and it runs on every merge.
Product chooses the cohort, the date, and the message. The release is a business event, so it does not ride on a deploy and it never happens by accident. The decision and the reason go in the flag registry.
| Rule | Reason |
|---|---|
| Default off on merge | Trunk stays deployable and each feature stays reversible |
| One flag per behaviour | A flag that gates two features cannot be released with confidence |
| Test the off path | It is the production path for every user until the release |
| Deploy on every merge | Small frequent deploys are easier to observe and easier to reverse |
| Release on a product cadence | Users see changes in a chosen order, not by accident |
| Kill switch on the flag | One action disables the feature without a deploy |
| No flag past 90 days | Long lived flags become a second codebase with no owner |
| Concern | Owner | Shared rule |
|---|---|---|
| Feature scope | Each team | One spec, one flag, and one named release owner |
| Merge order | Integrator | Dependency order, declared in the spec |
| Deployment | Each team | Every merge deploys behind its own flag |
| Release | Product | Cohort and date recorded in the flag registry |
| Flag debt | Platform | A weekly report and a 90 day limit |
The off path reaches production on the day of the merge. It needs the same review, the same tests, and the same rollback as an enabled feature. A team that treats the flag as a place to park unfinished work builds a second codebase in the dark.
Measurement
Two queues and one library decide the pace. Report queue depth, work in progress, review latency, and how much of the context is actually trustworthy. Output per engineer rises either way, so it cannot tell you whether the system works.
Every metric needs a source that a script can read. A metric from a survey is a story, not a control.
| Metric | Definition | Target | Source |
|---|---|---|---|
| Queue depth | Planned items waiting for a writer | 3 to 8 | Ready queue |
| Work in progress | Items in generation at the same time | 2 to 4 per team | Tracker |
| Review latency | Ready for review to first human comment | Under one day | Tracker |
| Context trust | Share of served documents marked verified | Above 80 percent | Manifest |
| Suspect age | Days a suspect document waits for a re-read | Under seven | Manifest |
| Uncovered paths | Billing or auth paths with no document in scope | 0 | Loader log |
| Rework rate | Changes that passed review and failed acceptance | Under 10 percent | Tracker |
| Flag age | Open flags older than the 90 day limit | 0 | Flag registry |
When the trust number falls, rework rises two to four weeks later. The context rots before the code does. Watch the trust number weekly and treat a fall as an early warning, not a documentation chore.
Risk register
Each risk has an early signal. The signal matters more than the mitigation. A team that cannot see the risk coming will not apply the response in time.
Four of the eight come from the substrate itself. A library of documents creates its own decay, and the decay is quiet.
| Risk | Early signal | Response | Severity |
|---|---|---|---|
| The context rots faster than it is read | Suspect age passes seven days | One curator. A weekly re-verify slot, not a backlog. | High |
| The agent trusts a stale rule | A change cites a document that failed its check | The loader blocks stale docs. The review asks the question. | High |
| The library grows without limit | The entry point passes 150 lines | Delete a document for every document added. | High |
| Duplication returns | The same rule appears in two files | A link check fails when a phrase repeats. | Medium |
| The generated folder gets edited | CI overwrites a manual change | Mark the folder read only. Regenerate on every build. | Medium |
| Writes outrun review | The review queue grows for two weeks | Cap work in progress. Do not add a reviewer until the cap holds. | High |
| Handoffs add a day each | Items sit between stages, not inside them | All handoffs run inside the same daily window. | High |
| A flag is never retired | Flag age passes 90 days | A scheduled job names the owner and fails the build. | High |
It cannot make the context correct. The detectors prove that a document still describes the paths it names. They cannot prove that the rule inside it is a good rule. Only a person can decide that, which is why every document carries an owner and not just a date.
Rollout
A stage split without a substrate gives ten people a faster way to work from ten private models of the system. Build the index first, even in a rough form, then change how work moves.
Each week has one exit condition. A week that fails its condition repeats. It does not advance.
List every document the team uses. Mark the owner and the last time anyone verified it held.
One manifest with scope, tier, owner, and date. Five documents is enough to start.
Paths first, because it is cheap and catches the most. Drift and expiry next. Claims last.
One visible list. An item enters it only with a spec, checks, and a declared scope.
The writer role changes hands every morning. The reviewer pair changes with it. Cap changes at 600 lines. Merge behind a flag and deploy on every merge.
Generate Jira from the specs. Freeze manual edits. Publish context trust and review latency weekly.
Review latency rises while the queue stays full, or the trust number falls while coverage rises. Both mean the team is producing more than it can verify. Cap work in progress before you add a reviewer.
Readiness
This page is a design, not a result. No team has run it end to end. The score reflects that gap, not the quality of the argument, and the checks below are the route from design to evidence.
A plan that scores itself highly with no field data is a sales page. This one does not.
Every problem here is measured in a published source. The manifest, the four detectors, the trust tiers, and the six week order are proposals with no team behind them yet. Treat the first six weeks as the test.
If the agent cannot read it, it does not exist. Put every durable fact on disk, index it by scope, and stamp it with a date. Let the loader tell the agent how much to trust it.