跳到正文
DEV Community· Graham Trott·· 3 小時前AI 評分54

「圍欄區塊原則」:每個程式碼區塊都應配有意圖説明

The Fenced Block Principle

AI 導讀

Graham Trott提出「圍欄區塊原則」,主張每個程式碼區塊都要配上一段説明其目的的意圖文字,並把兩者作為可審查的配對項目。文章建議以 linter 和 CI 檢查配對是否缺漏或過時,並並排檢視意圖與程式碼;意圖審查用來發現目標理解偏差,仍需測試、驗證及針對性閲讀程式碼來找出實作缺陷。

正文

The problem: code that reads well but means something else

If you vibe code — or supervise a coding agent that produces most of your diffs — you will have met the signature failure of AI-generated code. It compiles. It's idiomatic. The tests pass. And it implements a subtly different behaviour than the one you asked for, because the prompt was inexact or the model's reading of your codebase drifted.

Reviewers have a name for this: a correct answer to a slightly different question. It is the hardest class of defect to catch by reading code, because there is nothing wrong with the code. The wrongness lives one layer up, in the gap between what you intended and what the agent inferred.

The industry's current answer is spec-driven development (SDD): write the specification first, generate code against it, verify against it. That works, but it puts the spec upstream of the code as a contract, and once implementation begins, the two artefacts live separate lives. The spec becomes stale precisely when you need it most — at review time.

There is an older idea, and an older discipline, that suggests a different placement.

Knuth had the format; AI removes the burden

In 1984, Donald Knuth proposed literate programming: instead of writing code with comments, you write a narrative document in which code appears as blocks embedded in prose explaining the intent. The code is extracted from the document ("tangling"); the document itself is the primary artefact.

Literate programming never went mainstream, and the reason is well understood: the parallel maintenance burden. Keeping prose and code synchronised by hand was exhausting, so most who tried it abandoned it despite conceding its benefits. Knuth's WEB system required manual tangling and weaving — constant friction.

That burden is exactly what coding agents remove. An LLM can regenerate the prose when the code changes, regenerate the code when the prose changes, and maintain both in lockstep without fatigue. The literate programming model — agents writing prose explaining intent for each executable block — is credible for precisely this reason. What killed the paradigm in 1990 is the thing agents are best at.

So the raw material exists: a 40-year-old format whose only fatal flaw has just been fixed. What's missing is the application of that format to mainstream, agent-generated Python and JavaScript — and, crucially, a recognised convention for using it.

The fenced block principle

The principle is simple to state:

Every block of code must be fenced with a corresponding statement of intent — either embedded in the same file or directly linked to one — and the pairing is a first-class, reviewable artifact.

Call it spec-anchored code at block granularity. The ingredients:

  1. Co-location or hard linkage. Intent lives with the code, not in a separate upstream document that decays. In practice, for mainstream languages, this means a convention like: every function, class, module or logical section is preceded by (or linked to) a fenced intent block — a short, plain-language statement of what this is supposed to do and why, written to be read by a human reviewer, not as an API docstring.
  2. Machine-enforceable pairing. A linter or CI check verifies that no code block exists without a matching intent block, and that stale pairings are flagged. The document is not decoration; its absence is a build failure.
  3. Parallel generation. The agent writes code and intent together, as parallel renderings of the same design. Critically — and this inverts the usual spec-driven relationship — clarifying the intent costs nothing. When a reviewer asks "did you mean this?", the agent revises the intent wording without touching the code. The intent becomes the cheap, conversational layer; the code becomes the expensive, verified layer.
  4. A side-by-side viewer. The review surface is not a diff of code. It is a two-pane view: intent on the left, code on the right, block by block. The reviewer's first question at every block is "does this code match this intent?" — and only then, "is this code correct?"

This last point is where the review economics change. Reviewing AI code by reading lines is expensive and demoralising at the volumes agents produce, which is why a third of PRs now ship with zero review. Reviewing intent is cheap: a wrong objective, a missing edge case, a misunderstood requirement — all of the "vibe" failures — are visible in a paragraph, long before they require line-by-line study of the implementation. The reviewer allocates line-reading only where the intent looks risky, and hands the rest to tests and verification.

What would need to exist for Python and JavaScript

None of this requires a new language. It requires conventions and tooling, and the tooling itself would, naturally, be built by AI. Sketching the minimum viable stack:

  • A pairing convention. The simplest credible form is structured comments or fenced blocks in the source file itself — for Python, an # intent: block above each definition; for JS/TS, a /** intent */ block distinct from JSDoc's @description API documentation. Intent is why and what-for; API docs are how to call. Conflating them is how intent documentation degrades into boilerplate.
  • An extractor/linter. A small tool (a tree-sitter pass, trivially agent-written) that parses a repo, builds the block-level intent/code index, and fails CI on unpaired code, orphaned intent, or pairings not updated when their code changed. Think ruff for intent.
  • Agent instructions. A clause for AGENTS.md obliging the agent to write and maintain the pairing — generate intent with code, update both on change, and ask the human to clarify intent wording rather than silently choosing an interpretation. This is where the clarification asymmetry pays: the conversation the agent should be having with you is about intent, not about implementation.
  • The viewer. A review UI (web or IDE panel) that renders the index side-by-side, highlights stale or divergent pairs, and lets the reviewer accept/reject at the level of "this code matches this intent" rather than line comments. Diff review then becomes the second pass, targeted where intent review found risk.
  • A drift signal. Because pairings are machine-checked, drift becomes measurable: the proportion of blocks whose intent was clarified or rewritten after generation is a direct, quantitative proxy for how much vibing happened in a codebase — a metric no current tooling gives you.

Existing systems prove the pieces work. AllSpeak, a coding system built along these lines, enforces the principle through its AGENTS.md and ships an editor/visualiser with the side-by-side view — demonstrating the format's feasibility, in the same way Knuth's WEB demonstrated literate programming's. Safety-critical engineering has enforced exactly this kind of linkage for decades: IEC 62304 and DO-178C both require traceable connections between requirements, design, code and tests. The fenced block principle is that discipline, made cheap enough for everyday vibe coding.

Objections, honestly

"The intent can be vibes too." Yes — if the agent writes both layers, a confabulated intent can sit beside confabulated code. Worse, the pair will be internally consistent, and a side-by-side view of two agreeing fictions is more dangerous than no viewer at all, because the agreement feels like verification and the reviewer never asks for a rewrite. The mitigation is the clarification loop: the intent layer only earns trust if the human has ratified it — which is far cheaper than ratifying code — and the viewer must visually distinguish agent-authored intent from intent the human has confirmed. Once that distinction exists, unratified blocks become a targeting mechanism: review starts where the intent is still a guess, not a promise.

"It catches the wrong objective, not the subtle bug." Correct. Intent review catches "correct answer to a slightly different question." It does not catch "slightly broken implementation of the right answer." For that you still need tests, verification, and targeted code reading. The claim is not that intent review replaces these — it's that it gives them a target and a budget. You read lines where the intent looked risky, and you let executable verification cover the rest.

"Block-level documentation is tedious." It was. When humans had to maintain it, it was tedious enough to kill literate programming. The entire bet of the principle is that agents change the maintenance cost curve — and a current revival of interest in literate programming suggests that bet is now worth taking.

The ask

None of the pieces above are hard to build any more; an agent could produce a working extractor, linter and viewer prototype in a long weekend. What's missing is the convention — agreement that intent, at block granularity, is a first-class artifact that mainstream AI tooling should carry alongside code.

If you build coding tools, the interesting open surface right now is not a better code generator. It's a better review target: tooling that lets a vibe coder see what the agent thought it was doing, block by block, before deciding whether to care how it did it.

The code is the deliverable — and it is usually a truthful implementation of the stated intent. That is exactly why the intent should be read first: when the code faithfully renders the wrong intent, it will compile, pass, and ship. Most of the bugs that matter live in the prose.

Photo by Imagine Buddy on Unsplash

來源:DEV Community · dev.to