```Markdown 在 /src```
Markdown in /src

原始链接: https://htmx.org/essays/markdown-in-src/

在 Carson Gross 的文章中,他认为随着代理式编码(agentic coding)成为标准,Markdown 正在从单纯的文档转变为一种至关重要的源代码形式。目前,软件的“真实依据”(ground truth)往往在短暂的 LLM 对话中丢失。为了解决这一问题,Gross 提出开发者应将项目意图显式地记录并存储在位于 `/src` 目录下的 Markdown 文件中。 将这些文档移入源码树具有多重优势:它为人类开发者和 AI 代理提供了“局部性”(locality),创建了可版本控制、可对比的架构决策记录,并确立了一个比单纯的测试代码更具可读性和可操作性的真理源。 Gross 构想了一种工作流程,即 Markdown 作为高级规范,代码和测试皆由此衍生。他建议采用标准化的 `/src/md` 结构来存放技术概览、数据模型和功能规范。尽管这需要人为进行严谨的维护以管理复杂性,但 Gross 断言,随着编码自动化的成本降低,捕捉系统背后的“意图”将成为现代软件开发中最宝贵的资产。

这篇 Hacker News 帖子探讨了将 Markdown 文档直接放置在 `/src` 目录下的提议,旨在提高可访问性并更好地整合基于 LLM 的开发工作流。 讨论揭示了开发者在理念上的分歧: * **支持者:** 许多人认为,将文档与代码放在一起可以减少上下文切换,使人类和 AI 智能体都能更容易地参考需求、规范和提示词。一些人认为,这是一种让 LLM 在整个开发生命周期中都能获取上下文的“低技术含量”方法。 * **批评者:** 持怀疑态度的人认为,文档应保留在 `/docs` 中,以保持源代码与元数据的清晰分离。另一些人警告称不要“弄乱”源代码目录,甚至有人讽刺道,如果把 Markdown 存在 `/src` 里,那干脆把日志、构建产物和截图也存进去好了。 * **其他观点:** 一些参与者主张采用既定模式,如将测试用例或清晰的代码本身视为主要文档;另一些人则认为,相比于根目录下的 `/src` 方案,针对具体包的文档(例如 `packages/foo/docs`)是更具扩展性的解决方案。 总的来说,这篇帖子反映了关于如何更好地管理“AI 原生”代码库这一议题日益增长的争论。
相关文章

原文
Carson Gross
  • Markdown is becoming source code, not documentation
  • That Markdown should be checked in to /src, next to the code it produces
  • Code and tests should be derived from that Markdown, rather than from ephemeral prompts (or at least prompt sessions should eventually turn into persisted Markdown)

In order to supplement my income as a professor at Montana State University, I do consulting on the side. I enjoy consulting and the act of writing code & helping build systems, both for their own sake and also because it keeps my skills relevant and allows me to teach students about the latest ideas in software development.

Obviously the biggest thing to happen in development in the last few years is agentic coding: using LLMs to generate code in lieu of hand coding. I have written a few essays on this topic:

In this essay I want to discuss an idea that is becoming increasingly clear to me as I work in companies that are prioritizing agentic coding:

Markdown is now source code, not documentation.

This is not a novel or particularly clever idea, of course.

In Markdown is the new source code, Hartley Brody writes:

It is starting to feel as if the application logic of the software is being defined and edited as markdown, and the actual code that is generated by the agent is sort of becoming a low-level implementation detail.

Now, as the essays above show, I am ambivalent about AI-generated code. However, my consulting work shows that organizations are headed in this direction, often at terrific speed.

What I want to do in the remainder of this essay is think about the ramifications of Markdown becoming, more and more, the source of truth for software systems.

There is a line of thinking, captured in the quote above, that LLMs are akin to compilers, taking high-level specifications and turning them into low-level implementations. In this view, we don’t need to look at the code an LLM generates, just as we don’t look at the machine code a compiler generates.

As I mention in Code is Cheap(er), I do not totally agree with this analogy for a few reasons, but the one relevant to this essay is: compiler workflows retain their original source code while LLM workflows typically do not.

Today, LLM-generated code is often created via a string of prompts fed into an agent as a developer builds out a feature. In practice, this means that the generated code is the closest thing we have to “ground truth” for that feature. There may be documentation for the feature stored elsewhere (e.g. Linear, Slack threads, wikis, etc.) but, so far as the codebase is concerned, the generated code is the source of truth.

My opinion is that, in professional agentic coding environments, we need to accept that LLM-generated code that emerges from ephemeral prompting sessions is not ideal, and begin moving towards capturing and checking in Markdown alongside generated code in the source directory.

Markdown has many nice properties that make it similar to traditional source code:

  • It is plain text and therefore diffable, greppable and reviewable in pull requests
  • LLMs read and write it natively
  • Humans can read and edit it without tools

And, in fact, it is already acting as source, to an extent, in AGENTS.md, specs, plans, TASK.md and so forth. We just haven’t standardized capturing that source yet.

In Markdown is the new source code, Brody says he keeps his Markdown files in .scratch/research/ and .scratch/plan/ as he works. I have adopted the convention of creating a /tmp directory for similar ephemeral needs.

My proposal is that we promote some of these files to a new directory, alongside our existing source code: /src/md

The Markdown captured in this proposed directory would be lower level than traditional design documents:

  • It contains architectural decisions
  • It contains source-level decisions
  • It contains low-level data design decisions

It is much closer to a specification (although it is not one) than a design document as traditionally managed by a project manager or designer.

Locality

I am a fan of locality, and I think that moving Markdown into /src has strong locality advantages:

  • Code modules would now include the Markdown that explains the intent of the code
  • There is no spooky “specification at a distance”, where the logic of why is elsewhere in a wiki/Notion/Confluence/Jira
  • Markdown in /src can be consumed by both humans and agents
  • Agents no longer need to look elsewhere to get context on a given codebase

Other sources of truth for the behavior of the system can still exist. These sources would provide higher-level and/or “process-oriented” documentation: high-level design documents, issues that need a resolution workflow and so forth.

But the core, current and static intended behavior of the system would increasingly be captured directly in Markdown in the source directory.

I have seen many people online saying that tests are the new specification (or always were). I think there is some truth to that.

However, tests are not a good mechanism for human/agent interaction:

  • They involve a lot of ceremony, often obscuring what they are testing
  • They are typically lower level than most humans want to deal with, particularly when understanding a system
  • Higher-level explanations such as Mermaid diagrams don’t fit naturally into them

I think the following division of labor makes sense:

  • Markdown sits in /src and is the specification(ish)
  • Tests sit in /test (or wherever) and are based on that Markdown, providing automated confirmation of correctness

Again, the core idea here is that, rather than generating code and tests from prompts, a developer would work on Markdown in the /src directory, from which the code and tests would be derived.

The Markdown in /src/md sits between a formal specification for the system and high-level design documents.

As with source code, there is a Complexity Budget associated with this Markdown. It will require thoughtful management to keep these documents clean, well-factored and at the right level of abstraction.

Developers should be expected to interact with both the Markdown and the derived code, so synchronizing the two (when appropriate) will become an important skill.

For example, developers will often do subtractive, constraining work on generated code, and those changes may need to be moved back into the Markdown.

I believe that agents should not be used to generate much content in /src/md. This directory should be mainly human authored and curated.

This is necessarily the weakest part of this essay because this is a new idea and I haven’t used it extensively yet. It is me thinking out loud and inviting discussion.

With that said, here is a possible /src/md standard:

src/
  md/
    README.md          # index of all md, entry point for agents
    TODO.md            # a list of general TODOs open for this module
    OVERVIEW.md        # a technical overview of this module
    features/FEATURE_1.md       # a set of feature-specific documents
    data/DATAMODEL_1.md         # descriptions of data models in the module
    api/API_1.md                # descriptions of APIs the module provides
    infrastructure/INFRASTRUCTURE_1.md   # descriptions of infrastructure used by the module

Here the features, data, api and infrastructure directories are all optional; the idea is to divide along different axes to best capture a solid working description of the module’s behavior directly in the /src/md folder.

As code gets cheaper to generate, what remains valuable is the intent behind the code: what it does, why it does it, and what it must not do.

Today that intent is often lost in ephemeral prompting sessions, or scattered across wikis, tickets and Slack threads.

I think that, in the name of locality, we should consider capturing this intent in Markdown and checking it in to /src, alongside the code it produces, where both humans and agents can find it.

I don’t know exactly what the right structure for something like /src/md is yet, and I expect my thinking will change as I (and others) get more experience with it.

But I am fairly confident that Markdown is becoming source code, and that we should increasingly treat it like source code.

(Even though, no, LLMs are not compilers :)

</>

联系我们 contact @ memedata.com