Agentic SDLC · context on disk · plan unmeasured

The repository is the system.
If the agent cannot read it, it does not exist.

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

context manifest 3 of 5 verified
one index, scoped docs
served with a date and a status
invariants.md
verified
domain.md
suspect
routes.json
generated
auth-runbook.md
stale
adr-0011.md
verified
exemplars/
verified
detectors4 checks
quarantined1 doc
loader reads the manifest not the folder

Illustrative manifest · from the plan, not a real repository

Decision

Put every durable fact on disk, index it, and serve it with a status.

Cost

One curator role. Four detectors in CI. Six weeks of habit change.

Gate

No context file is served without a date. Dead paths fail the build.

7
stages with an agent
4
staleness detectors
3
trust tiers
1
manifest to read
150
lines in the entry point

At a glance

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.

Stale beats missing

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.

Derive, do not write

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

Every stage now has an agent in it.

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.

StageAgent producesHuman ownsOn diskGate
DiscoverClustered requests, prior art, a draft problem statementWhat is worth doingspecs/NNNN.mdG1 intent
DesignOptions, trade-offs, and a draft decision recordThe choice, and the reasondocs/adr/NNNN.mdG1 intent
BuildThe change, a trace to the spec, and migration notesThe declared scopeCode and .agents/exemplars/G2 conformance
VerifyCandidate checks, coverage runs, failure analysisThe oracle, written outside the agentacceptance/NNNN.tsG3 acceptance
DeployBuild, deploy, rollback steps, and a flag set to offThe deployment, and the rollbackFlag registry, runbooks/G4 deploy
ReleaseNotes, cohort size, and a risk summaryWhether a user sees the featureFlag state, generated notesG5 release
OperateTriage, correlation, first diagnosisThe response and the trade-offrunbooks/, incident recordPost incident review
What changedWhy it breaks the old process
Review costs more than writingReview time rose 91 percent while change size rose 154 percent
Planning loses to actionA model starts producing in seconds, so the plan feels like a detour
Generation is no longer scarceEvery engineer has a licence, so the constraint moves to review and coordination
Records multiplyJira, the wiki, and the changelog are all hand maintained and all disagree
Context does not travelEvery session starts blind, so every session rebuilds a private model of the system

The fifth row is the one that compounds

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

Assign work to stages, not to people.

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.

Mermaid · flowchart LR · plan, generate, review
flowchart LR P["plan
whole team
15 min per item"] --> H1{"handoff 1
spec and checks"} H1 --> G["generate
one writer per item
parallel by scope"] G --> H2{"handoff 2
size and trace"} H2 --> V["review
two people
plus one agent"] V --> H3{"handoff 3
acceptance on trunk"} H3 --> T["trunk"] class P manual class H1,H2,H3 control class G device class V manual class T ok
Each handoff is a check with one owner. A failed handoff returns to the same stage, not to the person who started the item.
Text version of this diagram
  1. The whole team plans an item in about fifteen minutes.
  2. Handoff 1 checks that the spec exists and the acceptance checks are testable.
  3. A writer generates the change for one item. Several items run at once when their scopes do not overlap.
  4. Handoff 2 checks that the change fits the size cap and traces to the spec.
  5. Two people and one agent review the change.
  6. Handoff 3 runs acceptance on the merged trunk.
  7. The integrator merges in dependency order.
StageWhoCan run in parallelHands over
PlanAnyone, in one weekly sessionYes, in parallelSpec, checks, and declared scope
GenerateWriter, rotates dailyYes, by declared scopeChange, trace, and test notes
ReviewTwo reviewers plus one agentYes, across itemsPass, or a named defect
IntegrateIntegrator, rotates weeklyNo, one merge orderTrunk

Keep the queue at three to eight

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

What the agents read, and where it lives.

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.

The context layout
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
LayerWhat belongs hereNever hereWritten by
Entry pointCommands, the map, the bans, and where to lookArchitecture essaysContext curator
InvariantsRules a change must not breakPreferences and style opinionsTech lead
DomainVocabulary and business rulesCode walkthroughsDomain owner
ExemplarsOne real file per patternDescriptions of a patternTech lead
SkillsRepeatable procedures with a triggerAnything always loadedWhoever runs it twice
GeneratedFacts computed from the repositoryAnything a person typedCI only

Derive, do not write

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.

One canonical home per fact

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.

What must never be on disk

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

The agent asks the index, not the folder.

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.

Mermaid · flowchart LR · scope based loading
flowchart LR T["task
with paths"] --> L["loader
reads index.json"] L --> M{"scope
match?"} M -->|yes| D["document
plus status header"] M -->|no| N["explicit gap
no context for this path"] D --> P["agent prompt"] N --> P P --> W["agent works"] class T data class L device class M control class D ok class N blocked class P manual class W device
Scope decides what loads. A path with no matching document produces a visible gap, not a silent empty string.
Text version of this diagram
  1. A task arrives with the paths it is allowed to touch.
  2. The loader reads the manifest instead of scanning the folder.
  3. Each document in the manifest declares a scope of path patterns.
  4. A matching document loads with a status header and a date.
  5. A path with no matching document produces an explicit gap in the prompt.
  6. The agent works from the loaded set and knows what it was not given.
.agents/index.json · one entry
{
  "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"]
}
TierMeaningThe agent mayThe agent may not
CanonicalVerified against the current commit and passing its checksAct on it without re-reading the codeEdit it silently
WorkingHuman written, verified recently, checks not runUse it, and cite the dateTreat it as proof
UnverifiedStale, suspect, or never checkedRead it for orientation onlyUse it to justify a decision

Absence must be loud

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

A stale document is worse than a missing one.

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.

Mermaid · stateDiagram-v2 · the life of one document
stateDiagram-v2 [*] --> Verified Verified --> Suspect: a watched path changed Suspect --> Verified: a human re-reads, 5 minutes Suspect --> Stale: a check fails Verified --> Stale: the expiry date passes Stale --> Verified: the check passes again Stale --> Quarantined: the loader stops serving it Quarantined --> Verified: rewritten from the code
Four events move a document. The cheap move is always to re-verify, so the system makes re-verification a five minute task with one command.
Text version of this diagram
  1. A new document starts as verified.
  2. A file inside its scope changes, so it becomes suspect.
  3. A person re-reads it and confirms it, which takes about five minutes.
  4. Or a check fails and it becomes stale.
  5. A verified document becomes stale when its expiry date passes.
  6. A stale document returns to verified when its check passes again.
  7. A stale document that nobody fixes is quarantined and no longer served.
  8. A quarantined document is rewritten from the code and returns to verified.
DetectorWhat it checksCost to runResult
PathsEvery path, command, and symbol named in the document still resolvesSecondsStale
DriftNo file inside the scope changed since the verified commitSecondsSuspect
ClaimsEach stated invariant has a script, and the script passesMinutesStale
ExpiryThe review by date has not passedNoneStale
The header the agent actually sees
StatusHow it is producedWhat the agent must do
VerifiedAll four detectors passAct on it, and cite the date
SuspectA watched path changed after the verified commitCheck the code before relying on a claim
StaleA check failed, or the expiry date passedDo not use it for a decision. Report it
QuarantinedStale for longer than the grace periodNever served. Treat the path as uncovered

Quarantine, do not delete

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.

Re-verification must be one command

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

Give planning a visible payoff.

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.

RuleWhy it worksFailure it prevents
Fifteen minutes per itemA longer plan means the item is too largeSpecs that become a second project
Plan together, once a weekBoring alone, tolerable in a roomA solo chore that gets deferred
Produce two things onlyOne sentence of intent, and the checksDocuments nobody reads
Show the ready queuePlanning visibly moves an item closer to a writerThe feeling that planning changes nothing
No spec, no writerA writer only takes an item with a declared scopeGeneration on a half formed request
specs/0042-export-limits.md · the whole plan
# 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.

Do not let the agent write the plan first

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

Review time falls when the unit falls.

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.

TierSizeReviewersAgent roleTarget
T1 · smallUp to 200 lines1 personComments first, human confirmsSame day
T2 · normalUp to 600 lines2 peopleFilters noise, human decidesNext day
T3 · riskyOver 600, or any schema, auth, or money change2 people plus a demoRuns a risk checklistTwo days

The 600 line cap is the whole fix

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 questionWho answers itTime
Does the change match the spec and the scope?First reviewer5 minutes
Does it follow an existing exemplar?First reviewer5 minutes
Is there an acceptance check that the author did not write?Second reviewer5 minutes
Did the change read a document marked suspect?Second reviewer2 minutes
Is there a rollback path?Second reviewer5 minutes

Review is a calendar event

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

Deployment is not 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.

Mermaid · flowchart LR · deploy is not release
flowchart LR M["merge to trunk
flag off"] --> B["build
every gate"] B --> D["deploy
developer owns"] D --> S["dark in production
flag off"] S --> O["observe
errors and metrics"] O --> G{"product
turn on?"} G -->|yes| R["release
one cohort, then wider"] G -->|no| K["leave off
or delete the code"] R --> F["retire the flag
within 30 days"] class M data class B,D device class S ok class O manual class G control class R ok class K blocked class F data
The deploy ends at a dark feature. The release starts at a product decision. Two different owners, two different dates, and one record that names both.
Text version of this diagram
  1. A team merges to trunk with its flag off.
  2. The build runs every gate and produces a deployable artefact.
  3. The developer deploys the artefact to production.
  4. The feature runs dark, because the flag is off for every user.
  5. The team observes errors and latency with the code live.
  6. Product decides whether to turn the flag on.
  7. If product turns it on, the feature is released to one cohort and then wider.
  8. If product does not, the code stays off or is deleted.
  9. The flag is retired within 30 days of full rollout.
StepStateOwnerGate
CreateThe flag exists and defaults to offDeveloperThe spec names the flag and the off behaviour
MergeThe code is on trunk and the flag is offReviewer pairTests cover the on path and the off path
DeployThe build runs in production and the flag is offDeveloperThe deploy is green and reversible
ValidateReal traffic runs the code and no user sees a changeDeveloper and QAErrors and latency stay flat
ReleaseThe flag is on for one cohort, then widerProductA product decision, with a recorded reason
RetireThe flag and the dead branch are deletedDeveloperWithin 30 days of full rollout

The developer owns the deploy

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 owns the release

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.

RuleReason
Default off on mergeTrunk stays deployable and each feature stays reversible
One flag per behaviourA flag that gates two features cannot be released with confidence
Test the off pathIt is the production path for every user until the release
Deploy on every mergeSmall frequent deploys are easier to observe and easier to reverse
Release on a product cadenceUsers see changes in a chosen order, not by accident
Kill switch on the flagOne action disables the feature without a deploy
No flag past 90 daysLong lived flags become a second codebase with no owner
ConcernOwnerShared rule
Feature scopeEach teamOne spec, one flag, and one named release owner
Merge orderIntegratorDependency order, declared in the spec
DeploymentEach teamEvery merge deploys behind its own flag
ReleaseProductCohort and date recorded in the flag registry
Flag debtPlatformA weekly report and a 90 day limit

A flag hides a feature. It does not hide the code.

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

Measure the context, not just the output.

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.

MetricDefinitionTargetSource
Queue depthPlanned items waiting for a writer3 to 8Ready queue
Work in progressItems in generation at the same time2 to 4 per teamTracker
Review latencyReady for review to first human commentUnder one dayTracker
Context trustShare of served documents marked verifiedAbove 80 percentManifest
Suspect ageDays a suspect document waits for a re-readUnder sevenManifest
Uncovered pathsBilling or auth paths with no document in scope0Loader log
Rework rateChanges that passed review and failed acceptanceUnder 10 percentTracker
Flag ageOpen flags older than the 90 day limit0Flag registry

Context trust is the leading indicator

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

The plan fails in eight ways.

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.

RiskEarly signalResponseSeverity
The context rots faster than it is readSuspect age passes seven daysOne curator. A weekly re-verify slot, not a backlog.High
The agent trusts a stale ruleA change cites a document that failed its checkThe loader blocks stale docs. The review asks the question.High
The library grows without limitThe entry point passes 150 linesDelete a document for every document added.High
Duplication returnsThe same rule appears in two filesA link check fails when a phrase repeats.Medium
The generated folder gets editedCI overwrites a manual changeMark the folder read only. Regenerate on every build.Medium
Writes outrun reviewThe review queue grows for two weeksCap work in progress. Do not add a reviewer until the cap holds.High
Handoffs add a day eachItems sit between stages, not inside themAll handoffs run inside the same daily window.High
A flag is never retiredFlag age passes 90 daysA scheduled job names the owner and fails the build.High

What this plan cannot do

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

Six weeks. The substrate comes before the stages.

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.

Inventory what exists

List every document the team uses. Mark the owner and the last time anyone verified it held.

Write the index

One manifest with scope, tier, owner, and date. Five documents is enough to start.

Turn on the detectors

Paths first, because it is cheap and catches the most. Drift and expiry next. Claims last.

Add the ready queue

One visible list. An item enters it only with a spec, checks, and a declared scope.

Rotate the writer

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.

Close the records

Generate Jira from the specs. Freeze manual edits. Publish context trust and review latency weekly.

The only reason to stop

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

The system holds when eight checks pass.

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.

"The mechanism is sound. The adoption is untested."

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.

review cost context decay manifest design release split no field data no trust baseline
  • Index. Every served document has a scope, a tier, an owner, and a date.
  • Detectors. Path checks fail the build on a dead reference.
  • Signals. The loader injects a status header, and a gap is stated explicitly.
  • Quarantine. A stale document stops being served after the grace period.
  • Derivation. The tree, routes, and schema are generated and never edited.
  • Stages. The writer role and the reviewer pair rotate daily, and no change above 600 lines is reviewed.
  • Flags. Every feature merges behind a default off flag. The developer deploys and product releases.
  • Evidence. Context trust above 80 percent and review latency under one day for two weeks.

The one sentence to keep

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.