惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Commits to openclaw:main
Recent Commits to openclaw:main
GbyAI
GbyAI
Y
Y Combinator Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
aimingoo的专栏
aimingoo的专栏
H
Hackread – Cybersecurity News, Data Breaches, AI and More
云风的 BLOG
云风的 BLOG
博客园 - 【当耐特】
Hugging Face - Blog
Hugging Face - Blog
M
MIT News - Artificial intelligence
博客园_首页
B
Blog RSS Feed
Recorded Future
Recorded Future
N
Netflix TechBlog - Medium
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
罗磊的独立博客
Apple Machine Learning Research
Apple Machine Learning Research
D
DataBreaches.Net
IT之家
IT之家
The GitHub Blog
The GitHub Blog
P
Proofpoint News Feed
Microsoft Azure Blog
Microsoft Azure Blog
S
SegmentFault 最新的问题
宝玉的分享
宝玉的分享
T
The Blog of Author Tim Ferriss
B
Blog
The Cloudflare Blog
MyScale Blog
MyScale Blog
雷峰网
雷峰网
U
Unit 42
C
Check Point Blog
月光博客
月光博客
Blog — PlanetScale
Blog — PlanetScale
T
Tailwind CSS Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
大猫的无限游戏
大猫的无限游戏
D
Docker
Microsoft Security Blog
Microsoft Security Blog
WordPress大学
WordPress大学
L
LangChain Blog
F
Fortinet All Blogs
腾讯CDC
Martin Fowler
Martin Fowler
I
InfoQ
J
Java Code Geeks
博客园 - Franky
Engineering at Meta
Engineering at Meta
人人都是产品经理
人人都是产品经理
有赞技术团队
有赞技术团队
阮一峰的网络日志
阮一峰的网络日志

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Your Coding Agent Doesn't Need Better Prompts. It Needs a Contract.
Fabibi · 2026-05-03 · via DEV Community

How I structured a repo to make AI agent drift visible before it ships.


The most dangerous failure mode I've seen in agentic coding workflows is not broken code. Broken code is at least visible.

The dangerous failure is plausible code: code that passes tests, implements something close to the request, and quietly expands the product surface in a direction nobody approved.

No bug. No crash. Just drift.

After a few months of fighting this, I stopped trying to write better prompts. The issue wasn't that the agent needed another instruction. The issue was that the repo didn't make authority clear enough. When behavior is implicit, agents fill gaps. The fix is not to ask them to stop doing that. The fix is to remove the gaps.

By "contract," I don't mean a legal document or a heavyweight framework. I mean a written, testable description of observable behavior: commands, outputs, exit codes, schemas, determinism rules, and the boundaries of what implementation is allowed to change. It is not the full design. It is the part external consumers can observe and rely on.

Prompts tell the agent how to behave. Contracts tell the repo how to reject behavior it did not authorize.


What quiet drift actually looks like

I'm implementing a scan --json command. The spec says the output should have three keys:

{
  "anchors": [],
  "mappings": [],
  "findings": []
}

Enter fullscreen mode Exit fullscreen mode

I ask an agent to implement it. The agent implements it correctly, but also adds a meta key with runtime diagnostics, because it seemed useful for debugging. The agent's implicit reasoning is understandable: the spec doesn't forbid it, and it makes the output more informative.

The tests pass. All three expected keys are present and correct. No test checks for the absence of extra keys, because nobody thought to write that test. A permissive test like this would pass:

expect(result.anchors).toEqual([]);
expect(result.mappings).toEqual([]);
expect(result.findings).toEqual([]);

Enter fullscreen mode Exit fullscreen mode

Even if the actual output was:

{
  "anchors": [],
  "mappings": [],
  "findings": [],
  "meta": {
    "cwd": "/Users/me/project",
    "durationMs": 42
  }
}

Enter fullscreen mode Exit fullscreen mode

The diff looks clean. Code review approves it. The feature ships.

Three weeks later, a downstream consumer expecting the exact JSON schema starts rejecting responses because the schema has an unexpected field. Or worse: the meta key leaks internal path information somewhere it shouldn't.

The bug was not that the agent failed to implement the request. The bug was that the repo never made the boundary machine-checkable. A closed contract would have caught it:

expect(Object.keys(result)).toEqual([
  "anchors",
  "mappings",
  "findings"
]);

Enter fullscreen mode Exit fullscreen mode

Or with JSON Schema:

{
  "type": "object",
  "required": ["anchors", "mappings", "findings"],
  "properties": {
    "anchors": { "type": "array" },
    "mappings": { "type": "array" },
    "findings": { "type": "array" }
  },
  "additionalProperties": false
}

Enter fullscreen mode Exit fullscreen mode

With structure, docs/contract.md explicitly lists the output schema as closed: no extra keys allowed. docs/evals.md validates byte-for-byte against a golden. Before handoff, npm run check:goldens fails because the golden doesn't include meta. The drift is caught before it ships.

Permissive tests validate what they know to expect. A contract also rejects behavior nobody authorized.

The difference is not just "more tests." It's a repo where tests are derived from an explicit behavioral contract, so the constraint is machine-checkable before the agent has a chance to be helpful in the wrong direction. This does not make drift impossible. It makes drift visible: either the contract changes explicitly, or the evals fail.


The three principles

The workflow I built in AnchorMap runs on three principles, stated at the top of AGENTS.md:

This repo is document-driven. The working mode is contract-first, eval-driven, scope-closed.

Contract-first means observable behavior is defined before implementation begins. docs/contract.md specifies commands, preconditions, outputs, exit codes, JSON schema, canonical key order, mutation guarantees, and determinism rules. If you want to add or change a behavior, you change the contract first. If an agent implements something that isn't in the contract, the workflow treats it as drift, not initiative.

Eval-driven means the contract is verified before implementation is considered done. docs/evals.md defines fixtures, goldens, and release gates derived directly from docs/contract.md. Successful JSON output is compared byte-for-byte. Failure cases require exact exit codes. Determinism is tested. Golden diffs are never accepted as noise. Any divergence is either classified as a defect or requires an explicit contract change first.

Scope-closed means agents cannot invent behavior. Not because they're trying to help. Not by inference. Not because something "seems right." Any observable behavior without traceability to contract.md and evals.md gets refused. This sounds restrictive. It is. That's the point.


Copy this pattern: the minimal four-file bootstrap

You don't need the full AnchorMap workflow to get most of the benefit. This is the smallest version that works: the four files I wish someone had handed me at the start.

AGENTS.md: entry map only, not authority:

# Agent Instructions

This repo is document-driven.
Working mode: contract-first, eval-driven, scope-closed.

## This file is an entry map. docs/ wins on conflict.

## Work intake

- Product implementation → identify a task in docs/tasks.md first.
- No task ID, no implementation.

## Authority

- docs/contract.md: observable behavior
- docs/evals.md: verification gates
- docs/tasks.md: execution plan and current task state

## Never

- Modify docs/contract.md without explicit instruction.
- Add observable behavior without traceability to docs/contract.md.
- Auto-pick a task or auto-commit unless explicitly asked.
- Fix a failing test before classifying the failure.

Enter fullscreen mode Exit fullscreen mode

docs/contract.md: observable behavior only, no implementation details:

# Contract

## Commands

### scan

- Exit 0 on success.
- stdout: JSON object with exactly these keys: anchors, mappings, findings.
- No extra keys. Closed schema.
- Exit 1 on error, stdout empty, stderr single-line diagnostic.

## Determinism

- Identical input → identical output, byte-for-byte.
- No timestamps, PIDs, random IDs, or environment-derived values in output.

Enter fullscreen mode Exit fullscreen mode

docs/evals.md: how the contract is verified:

# Evals

## Principles

- Contract-first: oracles test observable outputs only.
- Closed objects: goldens validate absence of extra keys.
- No golden drift: any difference is a defect or an explicit contract change.

## Fixtures

- fx01_scan_clean: empty repo, expect exit 0,
  golden: {"anchors":[],"mappings":[],"findings":[]}
- fx02_scan_error: missing config, expect exit 1, stdout empty

## Release gates

- Gate A: all fixtures pass
- Gate B: goldens match byte-for-byte

Enter fullscreen mode Exit fullscreen mode

docs/tasks.md: execution plan with a live cursor:

# Tasks

## Execution State

- Current active task: None
- Last completed task: None
- Blocked tasks: None
- Open deviations: None

## M1: Core scan command

### T1.1: Implement scan exit codes and JSON schema

Contract refs: contract.md §Commands/scan
Eval refs: evals.md fx01, fx02, Gate A, Gate B
Done when: fx01 and fx02 pass, goldens match, no extra keys in output.

Enter fullscreen mode Exit fullscreen mode

With these four files in place, an agent reading AGENTS.md knows immediately: find an explicit task first, read the contract before coding, don't add behavior that isn't in the contract, classify failures before fixing them. That's most of the anti-drift value with a fraction of the setup.

Documentation only helps agents when it is authoritative, scoped, and executable through evals. Otherwise it's just more context for the agent to reinterpret.


The document hierarchy

Which documents are authoritative for what? In most repos, this is implicit. That is exactly why agents drift. In AnchorMap, authority is explicit and domain-scoped. Each document owns a specific class of questions:

  • docs/contract.md: observable runtime behavior. If code contradicts it, the code is wrong.
  • docs/evals.md: verification gates. If a release gate doesn't pass, the release isn't ready.
  • docs/brief.md: product scope. It arbitrates what v1.0 is trying to prove.
  • docs/design.md: compatible implementation design. It can change as long as the contract stays satisfied.
  • docs/operating-model.md: production method, deviation taxonomy, review protocol, and done criteria.
  • docs/tasks.md: execution plan and current task state.
  • docs/adr/: locked technical decisions.

AGENTS.md is explicitly demoted. It's the entry map, not the authority. That sounds counterintuitive. Many agentic repos treat the instruction file as the highest authority. I don't. Durable product rules live in docs/. If AGENTS.md conflicts with anything in docs/, docs/ wins, and the file says so.

The mistake is treating AGENTS.md as the constitution. I treat it as a signpost.

A repo that relies on a single instruction file gives an agent enough room to drift if it skims that file and stops there. In this setup, an agent that reads AGENTS.md only learns where to go next.


The loop

For a product task, the loop has six moves.

1. Identify an explicit task. The agent can propose work, but it cannot start product implementation without a task ID in docs/tasks.md. This shuts down the "let me just do something useful while I'm here" pattern.

2. Read within bounds, not as little as possible. The agent reads the sections explicitly linked to the task, not the entire documentation tree. The goal is not to starve the agent of context. It is to prevent unrelated context from becoming accidental authority. Broader reading is allowed when a concrete failure demands it, or when the diff touches a critical surface like the parser, renderer, contract, or eval machinery.

3. Declare before patching. Before touching a file, the agent states the target task, binding references, smallest useful check, expected handoff checks, expected patch boundary, and explicit out-of-scope items. An agent that can't declare a clean patch boundary isn't ready to edit. This is the most effective anti-drift guardrail in the workflow. A real declaration looks like this:

Task: T7.5: Assemble exact scan JSON output

Binding refs:
- contract.md §13.2 Exact success schema
- contract.md §§13.3–13.7 scan JSON sections and canonical serialization
- evals.md §6.1 Mandatory JSON goldens
- evals.md fx01, fx02, fx09, fx10
- evals.md Gate B

Patch boundary:
- scan result projection
- JSON output assembly
- renderer integration for scan success
- focused scan JSON tests or goldens required by the task

Smallest check:
- run fx10_scan_closed_objects before broadening beyond schema assembly

Handoff checks:
- run B-scan success fixtures
- run JSON golden checks for the touched fixtures

Out of scope:
- human scan output
- semantic JSON comparison
- new JSON keys outside the contract
- diagnostics metadata
- changing scan semantics

Enter fullscreen mode Exit fullscreen mode

That declaration changes the interaction. The agent is no longer free-floating in the repo. It has a task, sources of authority, a bounded patch surface, and known refusal conditions.

4. Implement only the traced surface. Not the adjacent improvement it noticed. Not the cleanup that seems obvious. Not the extra diagnostic that might be useful. If something outside scope needs to change, it needs its own task.

5. Classify failures before fixing them. When something breaks, the instinct is to fix it immediately. The workflow requires naming the failure class first: contract violation, spec ambiguity, design gap, eval defect, product question, tooling problem, out-of-scope discovery. The label determines the correct action. Fixing before classifying is how you accidentally weaken a fixture, paper over a spec ambiguity, or turn an out-of-scope discovery into a silent product change.

6. Submit a bounded diff to fresh review. The review context is separate from the implementation context. Same-session review gives the model the intent, tradeoffs, and partial reasoning that produced the patch. That is exactly the context that makes it easier to rationalize the change instead of challenging it. The invariant isn't a specific tool. It's separation: review must inspect the diff from a clean context and issue a decision before rework begins.


What gets stricter when the workflow scales

The four-file bootstrap is enough to start. AnchorMap goes further because the workflow also handles repeated implementation cycles, fixture diagnosis, task-plan maintenance, and bounded automation. Three constraints become important at that point.

Review starts from a clean context. In AnchorMap, that means native Codex review on the bounded diff, or a fresh interactive session where review is the first step. In another stack, the mechanism can differ. The rule is the same: the session that produced the patch doesn't approve the patch.

Workflow tools don't count as review. AnchorMap has local skills for implementation, fixture diagnosis, task updates, and task validation. They make specific paths repeatable and they can help produce work. They can't approve their own output.

Autopilot is opt-in and bounded. Automation can run the loop, but it can't blur the boundaries. Each implementation and review still runs in a task-scoped context. The coordinator retains task-level state, not an ever-growing transcript of implementation reasoning. Automation doesn't relax the contract. It makes the boundaries more important.


When this is overkill

This is not how I would structure a weekend prototype or a throwaway script. For exploratory work, agents need room: to try things, follow weak signals, make useful jumps before the shape of the product is known.

The workflow starts paying for itself when the repo has observable behavior that other people or tools depend on: CLI output, public APIs, migration scripts, generated files, config formats, release gates, anything where "almost correct" can become a compatibility problem. The more stable the surface, the more expensive quiet drift becomes.

For product behavior that people depend on, agents need clear authority. A repo that tells an agent which document governs each class of decision, how failures must be classified, and what "done" means will produce more consistent, traceable, reviewable output. A repo that leaves those questions implicit invites drift.

For agent-written code, the workflow is not process overhead. It is part of the product.


AnchorMap is a CLI tool for anchor-based dependency mapping in TypeScript repositories. The full workflow documentation lives in the public repo under docs/. A follow-up article will cover the fresh review protocol and bounded autopilot in detail.