All field notes

You shipped it in the app. You forgot the MCP tool and the CLI.

AI coding agents can make a change pass tests while missing the API, docs, observability or recovery path a real feature owes. Build a definition of done your repository can prove.

By BankSync8 min read
A semantic operation resolving into the obligations a feature owes, each checked by the repository

AI coding agents have changed the shape of a software task. A well-scoped prompt can now produce a route, a component, a migration and a passing unit test in minutes.

That does not mean the feature is complete.

The missing work is usually not hidden in the diff. It is around the diff: the API contract a developer needs, the MCP tool an agent expects, the permission boundary, the destructive-action preview, the dashboard, alert, runbook, release check and documentation. Code can be perfectly reasonable and still leave the product less complete than it was before.

This is the new bottleneck: writing code is getting cheaper; knowing that a change arrived whole is not.

At Flagbase, we call one answer to that problem Obligation Engineering: describe a feature with a small set of facts, derive what it owes from policy, then make CI prove that each obligation is real. It is designed for teams using AI coding agents, but it is equally useful when people write the code.

A semantic operation resolving into the obligations a feature owes, each checked by the repository
A feature contract can resolve into the complete set of things it owes.

Specs solve intent. They do not prove completeness.

Spec-driven development is a meaningful improvement over “ask the agent to build it.” A good spec gives an agent a goal, constraints and acceptance criteria. It also gives a reviewer something concrete to challenge.

But a spec alone still leaves one hard question unanswered:

Given what this operation is and who it is for, what else must exist before we call it done?

Teams often answer that question with a longer AGENTS.md, a PR checklist or a collection of tribal rules. That works until the next surface appears. A rule about API compatibility, a new CLI, a security incident, an observability standard or a support expectation gets appended to a prompt that every agent must read and remember.

The result is familiar:

  • An agent builds the endpoint but no public reference explains it.
  • A deletion flow ships without an audit trail or recovery path.
  • A team adds an MCP tool but no parity check says it exposes the same permission and safety rules as the web app.
  • An SLO exists in a document, but no dashboard, alert or runbook can prove it is being met.

None of those are code-generation failures. They are definition-of-done failures.

Make a feature contract small enough to review

The contract is not a detailed implementation plan. It is structured facts that tooling can read without running the product. Give an operation one semantic identity, then declare the facts that change its obligations.

``json { "operation": "records.record.delete", "audiences": ["customer", "developer", "automation"], "effects": ["delete"], "data": { "persisted": true, "personal": true }, "measurement": { "slo": true }, "risk": "critical" } ``

The important move is naming the meaning of the operation, not one transport. records.record.delete can be represented by a REST route, a CLI command, an MCP tool, a product screen or an internal workflow. Those are projections of the same operation—not separate features with subtly different rules.

That identity gives the repository a place to join every piece of evidence. A test can refer to it. A documentation page can declare it. An event can bind to it. A dashboard tile, alert, rollback plan and release smoke test can all be checked against it.

Derive obligations from facts—not a hand-maintained checklist

Once the facts are explicit, a policy can resolve them into work. The mapping is not universal; it is an engineering decision your team owns and reviews. The point is that the policy is executable and consistent.

How a policy can derive feature obligations

Contract factExample obligations it can derive
A developer audiencePublic API, generated client, MCP tool, CLI, references, rate limit and compatibility contract
A delete effectAudit trail, idempotency, recovery, destructive preview and explicit approval
Personal dataClassification, privacy and data-boundary checks
An SLOMetric, health dashboard, enabled alert and runbook
Critical riskKill switch, smoke test, rollback signal, tracing and reliability evidence

The exact mapping is yours to review; these examples show how semantic facts replace a generic checklist.

The policy should be opinionated in exactly the places your product needs it to be. A developer-facing operation may owe an API and MCP tool. A customer-only UI action may not. A destructive operation should have stronger recovery and approval requirements than a read. The contract makes those differences visible before the agent begins to code.

This is also where the approach stays practical. You do not have to model every part of the product at once. Start with one class of expensive-to-miss work: destructive actions, public API operations, regulated data, or capability documentation. Add rules only after you can explain why they are needed.

A check should find providers, not trust a declaration

A checkbox that says “docs: done” is still a claim. Obligation Engineering treats a requirement as satisfied only when the repository can discover a real provider for it.

For example, a route declares which semantic operation it serves. A tool declares the same operation beside its input schema and effect. A docs page lists the operations it covers in front matter. A dashboard binds to the emitted event or metric. CI reads those registries and source files, joins them by identity, and reports what is missing.

```text $ capability:check records --stage merge records.record.delete api-reference satisfied records.record.delete mcp-tool missing no provider registered records.record.delete recovery satisfied records.record.delete alert-slo missing no enabled alert binds this operation

repair: register the MCP tool; bind an enabled alert to records.record.delete exit 1 ```

That output is more useful than “the agent says the work is finished.” It tells a person or agent what is incomplete, why it is incomplete and where to make the smallest repair.

The proof should live on the commit, not in a file that says a check once passed. Repository facts can be checked deterministically in CI. Facts about a live system—such as a deployed smoke test, incoming telemetry or an applied alert—need receipts from an authorised workflow and should expire. A green build cannot prove production health forever.

Make “not applicable” an owned decision

The dangerous state in an agentic workflow is silence. Was the CLI intentionally excluded? Did nobody build it? Was a dashboard unnecessary, or merely forgotten?

Treating every absence as “not applicable” makes this impossible to answer. A better rule is simple: an omitted obligation must have a reason, an owner, an approval and a review date. When the date arrives, the decision is reconsidered instead of becoming a permanent exception.

This gives legacy systems a sane path too. When a new policy finds gaps in old features, record them precisely and make the baseline ratchet down. Debt can shrink as each capability is brought up to the new standard; it cannot quietly grow because a broad allowlist was added.

A small first implementation

  1. Describe one semantic operation

    Start with a real operation such as a public endpoint, destructive action or regulated-data flow. Record its audience, effects, data, measurement and risk.

  2. Resolve the work before coding

    Let policy produce the obligation set, so the developer or agent can see the complete work list before implementation begins.

  3. Register real providers

    Implement and register the route, tool, UI, documentation, tests and operational evidence that apply. A comment or a manual checkbox does not count as a provider.

  4. Gate the commit

    Run fast local checks, then a capability check and affected-graph check in CI. Make the output name the missing obligation and smallest repair.

  5. Own exceptions and legacy debt

    Give every deliberate omission a reason, owner, approval and review date. Allow the baseline to shrink, never silently grow.

Keep the agent instructions short by moving repeated rules into checks

Agents still need instructions. They should explain where to start, how to retrieve context, how to run the relevant commands and which safety boundaries need human approval.

They should not be the only place that says “remember the docs,” “remember the MCP tool,” “remember the dashboard,” “remember the destructive preview” and “remember not to use production credentials.” Repeated, testable rules belong in a check. That makes the agent prompt smaller, reduces policy drift across coding harnesses and gives humans the same feedback loop as agents.

This gives an AI coding agent a bounded work list rather than an ever-growing memory test. It also gives reviewers a way to ask better questions: not “did we remember every surface?” but “does this contract derive the correct obligations, and does the commit satisfy them?”

What stays human

Automation can determine whether a required provider exists. It cannot decide whether the feature is worth building, whether the policy is proportionate, whether a risk is acceptable or whether a destructive action should be approved.

Those choices stay with people. So do product direction, policy changes, privilege boundaries and an explicit decision to defer work. The agent can implement within those constraints; it should never define or waive them for itself.

That is the useful boundary for agentic engineering. Give agents fast, deterministic ways to discover what is required and prove what they changed. Keep judgement, authority and exceptions visible and human-owned.

Start with the feature most likely to hurt when it is incomplete

Do not begin by trying to formalise your entire company. Choose one real capability where “the tests passed” has previously been insufficient:

  • A public API endpoint that needs documentation and compatibility guarantees
  • A delete or export action that needs recovery, audit and approval rules
  • A workflow that needs traces, metrics, an alert and a runbook
  • A developer-facing integration where a REST API, MCP tool and CLI must stay in parity

Define the smallest contract, derive a handful of obligations and make one required check fail when something is absent. The first win is not a perfect policy engine. It is replacing “we hope someone remembered” with a result the repository can show.

If you build financial-data integrations, the same discipline applies at the boundary: a webhook receiver is not complete because it accepts a payload. It also needs idempotency, credential handling, observability and a safe replay path. Our guide to connecting bank data to Postgres or a webhook walks through that delivery pattern.

Frequently asked questions

Read the full framework

This article is the practical case for a stronger definition of done. The complete method—including the policy resolver, surface parity, receipts, budgets, command design and CI gates—is documented in Obligation Engineering: specs as code for AI agents.

A semantic operation resolving into the obligations a feature owes, each checked by the repository
A feature contract can resolve into the complete set of things it owes.

Related field notes