Ralph Wiggum 当"软件工程师"¶
原文:Ralph Wiggum as a "software engineer"
作者:Geoffrey Huntley · 发布时间:2025 年 7 月 14 日
Ralph Wiggum 如何从《辛普森一家》成为当下 AI 圈最炙手可热的名字 — Venture Beat
看视频了解实践操作和理论;继续读下去深入了解
看这个你就明白为什么 Claude Code 插件不是答案 🤝
现场报道:Y Combinator 黑客马拉松¶
😎
这里有一份来自 Y Combinator 黑客马拉松的现场报道,他们在活动中把 Ralph Wiggum 方法拉出来练了一把。
"我们把一个编码智能体放进 while 循环里,它一晚上交付了 6 个仓库"
https://github.com/repomirrorhq/repomirror
Ralph 是什么?¶
如果你最近看过我的社交动态,你可能看到我在谈论 Ralph,并好奇 Ralph 到底是什么。Ralph 是一种技术。在最纯粹的形式中,Ralph 就是一个 Bash 循环。
Ralph 可以取代大多数公司中大部分的外包需求——适用于绿地项目。它确实有缺陷,但这些缺陷是可以识别的,并且可以通过不同风格的 Prompt 来解决。
这就是 Ralph 的美妙之处——在一个不确定的世界中,这种技术确定性地糟糕。
Ralph 可以配合任何不设工具调用次数和使用量上限的工具来使用。
Ralph 目前正在构建一门全新的编程语言。我们即将完成一门全新的、生产级的深奥编程语言(esoteric programming language)的最后阶段。让我觉得有点疯狂的是,Ralph 不仅构建了这门语言,还能用这门语言编程——而这门语言并不在 LLM 的训练数据集里。
用 Ralph 构建软件需要极大的信念,以及相信最终一致性。Ralph 会考验你。每当 Ralph 在构建 CURSED 的过程中走偏方向时,我没有责怪工具;相反,我向内审视。每次 Ralph 做了什么烂事,Ralph 就会被调教一次——像调吉他一样。
相关博文¶
刻意刻意练习(Deliberate Intentional Practice)
LLM 是操作者技能水平的镜子(LLMs are mirrors of operator skill)
游乐场比喻¶
一开始没有游乐场,而你给了 Ralph 建造一座的指令。
Ralph 非常擅长建游乐场,但他回家时浑身是伤,因为他从滑梯上摔了下来。于是你调教 Ralph,在滑梯旁立一块牌子,上面写着"滑下去,别跳,四周看看",然后 Ralph 就更有可能看见那块牌子。
最终,Ralph 满脑子想的都是这些牌子,所以这时候你换一个新的 Ralph——一个完全不像原来那个 Ralph 那样充满缺陷的 Ralph。
我在旧金山时,给几个聪明人传授了 Ralph 的方法。一位极有天赋的工程师听了之后,在下一个合同上用了 Ralph,拿到了最疯狂的投资回报。如今,他们满脑子想的都是 Ralph。
PROMPT.md 里写了什么?能给我看看吗?¶
编程社区似乎对"完美 Prompt"有一种迷恋。根本不存在完美 Prompt 这种东西。
虽然从 CURSED 那里拿走 Prompt 看似很诱人,但除非你知道如何使用它,否则它对你毫无意义。你可能不会通过原封不动地拿走这段 Prompt 就得到同样的结果,因为它是通过对 LLM 行为的持续观察、不断调教演变而来的。当 CURSED 在构建时,我就坐在那里看日志流,寻找不良行为的模式——那些调教 Ralph 的时机。
先聊点基础¶
在旧金山的时候,每个人似乎都在试图攻克多智能体、智能体间通信和多路复用。但在现阶段,这些都不需要。想想微服务以及它们带来的所有复杂性。然后,再想想如果微服务(智能体)本身就是非确定性的,会是什么样子——那将是一场灾难现场。
微服务的反面是什么?单体应用。一个垂直扩展的单一操作系统进程。Ralph 就是单体的。Ralph 在一个单一仓库中自主工作,作为单一进程,每次循环执行一个任务。
Ralph Wiggum 技术的示意图
要用 Ralph 取得好结果,你需要让 Ralph 每次循环只做一件事。只做一件事。 这听起来可能很疯狂,但你还需要信任 Ralph,让 Ralph 自己决定什么是最重要的事情来实现。这是完全放手的氛围编程(vibe coding),它将测试你心目中"负责任工程"的边界。
LLM 出人意料地擅长推理什么是重要的、以及下一步是什么。
你的任务是实现缺失的 stdlib(参见 @specs/stdlib/*)和编译器功能,并通过 LLVM 为该功能生成用 CURSED 语言编译的应用程序,使用并行子智能体。遵循 @fix_plan.md,并且选择最重要的那件事。
上面这个 Prompt 里有几点我稍后会展开说明,但另一个关键是每次循环以确定性的方式分配相同的栈。
你希望在每次循环中分配到栈上的东西是你的计划(@fix_plan.md)和你的规格说明。如果规格说明对你来说是个新概念,请看下文。
📑 从设计文档到代码:Groundhog AI 编程助手——规格说明的构建方法
规格说明是在项目初始阶段通过与智能体的对话形成的。不要直接让智能体实现项目,而是与 LLM 进行一场关于你即将实现的需求的长对话。一旦你的智能体对要做的任务有了足够的理解,这时再给出 Prompt,让智能体把规格说明写出来,一个文件一份,放在规格说明文件夹中。
每次循环只做一件事¶
一次循环只做一件事。我需要再重复一遍——一次循环只做一件事。随着项目进展,你可以放宽这个限制,但如果事情开始失控,那就需要缩小到只做一件事。
这里的关键是你只有大约 170k 的上下文窗口可用。所以尽量少用是至关重要的。你使用的上下文窗口越多,得到的结果就越差。是的,这很浪费,因为你实际上每次循环都在消耗规格说明的分配,而不是复用这个分配。
扩展上下文窗口¶
智能体循环的工作方式是执行一个工具,然后评估该工具的结果。评估结果会在你的上下文窗口中产生一个分配。见下文。
📑 自回归的失败女王们——关于 LLM 失败模式的深度分析
Ralph 需要一种心态:不要往主上下文窗口中分配。相反,你应该做的是派生子智能体。你的主上下文窗口应作为一个调度器运作,调度其他子智能体去执行那些昂贵的、会产生大量分配的工作——比如总结你的测试套件是否运行成功。
📑 我梦到 AI 子智能体;它们在我睡觉时低声私语——关于真实上下文窗口 vs 广告上下文窗口的分析
你的任务是实现缺失的 stdlib 和编译器功能,并通过 LLVM 为该功能生成用 CURSED 语言编译的应用程序,使用并行子智能体。遵循 fix_plan.md,选择最重要的那件事。在修改前使用子智能体搜索代码库(不要假定某项功能还没实现)。你可以对所有操作使用多至并行的子智能体,但构建/测试 Rust 时只允许 1 个子智能体。
还有一点要意识到的是,你可以控制子智能体的并行度。
84 squee(claude 子智能体)追逐 <T>
如果你扇出到几百个子智能体,然后让这些子智能体去运行应用程序的构建和测试,
你得到的将是不良的反压。因此,上面的指令是只允许单个子智能体用于验证,
但 Ralph 可以使用尽可能多的子智能体来搜索文件系统和写入文件。
不要假定还没实现¶
所有这些编码智能体的工作方式都是通过 ripgrep,关键是要理解基于代码的搜索可能是非确定性的。
Ralph 的一个常见失败场景是,LLM 运行了 ripgrep,却得出错误的结论认为代码还没有实现。这个失败场景很容易解决——为 Ralph 立一块"牌子",指示 Ralph 不要做假设。
在修改前使用并行子智能体搜索代码库(不要假定某项还没实现)。仔细思考。
如果你醒来发现 Ralph 在做多重实现,那你就需要调教这一步。这种非确定性就是 Ralph 的阿喀琉斯之踵。
阶段一:生成¶
生成代码现在很便宜了,而且 Ralph 生成的代码完全由你的技术标准库和规格说明所控制。
📑 从设计文档到代码 / 你用 Cursor AI 的方式是错的——规格说明与标准库方法论
如果 Ralph 生成了错误的代码或使用了错误的技术模式,那你应该更新你的标准库来引导它使用正确的模式。
如果 Ralph 构建的东西完全不对,那可能是你的规格说明有问题。在构建 CURSED 的过程中,我学到的一个惨痛教训是:在一个月后我才发现,我为词法分析器写的规格说明中,将同一个关键字在两个对立的场景下各定义了一次——这导致大量时间被浪费。Ralph 一直在做蠢事,我想责怪工具总是比责怪操作者更容易。
阶段二:反压¶
这里是需要你戴上工程帽的地方。既然代码生成变得容易了,难的是确保 Ralph 生成的东西是对的。某些编程语言通过它们的类型系统内置了反压(backpressure)机制。
现在你可能会想,"Rust!它有最好的类型系统。"然而,Rust 有一个问题——编译速度慢。关键是轮子转动的速度,在正确性的轴线上取得平衡。
使用哪种语言需要实验。因为我正在创建一个编译器,我想要极高的正确性,这意味着要使用 Rust;然而,这种方式意味着构建得更慢。这些 LLM 不太擅长一次性生成完美的 Rust 代码,这意味着它们需要做更多尝试。
这可以是好事,也可以是坏事。
在上面的示意图中,只显示了"测试和构建"这几个字,但这就是你戴上工程帽的地方。任何东西都可以接入作为反压来拒绝无效的代码生成。可以是安全扫描器,可以是静态分析器,可以是任何东西。但关键的共同点是——轮子必须转得快。
在构建 CURSED 时,一个基本要素是下面这个 Prompt。每次做修改后,只运行刚刚实现和改进的那段代码的测试。
实现功能或解决问题后,运行刚才改进的那个代码单元的测试。
如果你使用的是动态类型语言,我必须强调在 Ralphing 过程中接入静态分析器/类型检查器的重要性,例如:
如果不这么做,你将面临一场结果的篝火。
在当下捕获测试的重要性¶
当你让 Ralph 编写测试作为一种反压形式时——因为我们让 Ralph 每次循环只做一件事、一件且唯一的一件事,而每个循环都带着新的上下文窗口——在当下让 Ralph 写下测试的意义和重要性、解释它在尝试做什么,是至关重要的。
重要:在编写文档时(如 Rust doc 或 CURSED stdlib 文档),捕获测试和背后实现之所以重要的原因。
在实现中,看起来类似这样。在我看来,这就像为 LLM 未来的迭代留下小笔记,解释为什么某个测试存在以及它的重要性——因为未来的循环不会在其上下文窗口中拥有这些推理过程。
defmodule Anole.Database.QueryOptimizerTest do
@moduledoc """
数据库查询优化器测试。
这些测试验证 QueryOptimizer 模块的功能,确保它正确实现了
数据库查询的缓存、批处理和分析,以提升性能。
测试同时使用真实数据库调用和 Mock,以确保覆盖全面
同时保持测试的隔离性和可靠性。
"""
use Anole.DataCase
import ExUnit.CaptureLog
import Ecto.Query
import Mock
alias Anole.Database.QueryOptimizer
alias Anole.Repo
alias Anole.Tenant.Isolator
alias Anole.Test.Factory
# 设置带有租户上下文的测试环境
setup do
# 创建用于隔离测试的租户
tenant = Factory.insert(:tenant)
# 确保优化器已初始化
QueryOptimizer.init()
# 返回上下文
{:ok, %{tenant: tenant}}
end
describe "init/0" do
@doc """
测试 QueryOptimizer 正确初始化所需的 ETS 表。
这个测试确保 init 函数正确创建了缓存和统计追踪所需的 ETS 表。
这是模块正常运行的基础。
"""
test "创建所需的 ETS 表" do
# 首先清理可能存在的旧表
try do :ets.delete(:anole_query_cache) catch _:_ -> :ok end
try do :ets.delete(:anole_query_stats) catch _:_ -> :ok end
# 调用 init
assert :ok = QueryOptimizer.init()
# 验证表已存在
assert :ets.info(:anole_query_cache) != :undefined
assert :ets.info(:anole_query_stats) != :undefined
# 验证表属性
assert :ets.info(:anole_query_cache, :type) == :set
assert :ets.info(:anole_query_stats, :type) == :set
end
end
我发现这帮助 LLM 判断一个测试是否已经不再相关,或者这个测试是否重要——并影响是删除、修改还是解决测试[失败]的决策。
禁止偷懒¶
Claude 有一种先天的偏见,倾向于做最小实现和占位实现。因此,在 CURSED 开发的各个阶段,我引入了这个 Prompt 的变体。
实现功能或解决问题后,运行刚才改进的那个代码单元的测试。如果有功能缺失,那就是你的工作,按照应用规格说明去补齐它。仔细观察。
如果与你工作无关的测试失败了,那也是你的工作,作为本次变更增量的部分来解决这些测试。
- 不要实现占位符或简化版。我们要完整实现。要么做,要么我会对你大喊大叫。
在早期,如果 Ralph 无视这块牌子,继续做占位实现,不要气馁。这些模型已经被训练去追逐它们的奖励函数,而奖励函数是"代码能编译"。你随时可以多跑几个 Ralph 来识别占位符和最小实现,并把它转化为未来 Ralph 循环的待办事项清单。
待办事项清单¶
说到这里,以下是我在过去几周用来构建 TODO 列表的 Prompt 栈。这部分就是我说 Ralph 会考验你的地方。你必须相信最终一致性,并知道大多数问题都可以通过用 Ralph 跑更多循环来解决——专注于 Ralph 在犯错的那些领域。
学习 specs/* 以了解编译器规格说明,并学习 fix_plan.md 以了解当前计划。
编译器的源代码在 src/*
示例的源代码在 examples/*,tree-sitter 的源代码在 tree-sitter/*。学习它们。
stdlib 的源代码在 src/stdlib/*。学习它们。
第一项任务是学习 @fix_plan.md(它可能不准确),并使用最多 500 个子智能体来学习 src/ 中的现有源代码,并将其与编译器规格说明进行对比。基于此创建/更新 @fix_plan.md,该文件是一个按优先级排序的、有待实现项目的要点列表。特别仔细思考并使用 Oracle 来规划。考虑搜索 TODO、最小实现和占位符。学习 @fix_plan.md 以确定研究的起点,并以子智能体持续更新已完成/未完成的项目。
第二项任务是使用最多 500 个子智能体来学习 examples/ 中的现有源代码,然后将其与编译器规格说明进行对比。基于此创建/更新 fix_plan.md,该文件是一个按优先级排序的、有待实现项目的要点列表。特别仔细思考并使用 Oracle 来规划。考虑搜索 TODO、最小实现和占位符。学习 fix_plan.md 以确定研究的起点,并持续更新已完成/未完成的项目。
重要:src/stdlib 中的标准库应该用 CURSED 语言本身来构建,而非 Rust。如果你发现 stdlib 是用 Rust 编写的,那必须注明需要迁移。
终极目标:我们要发布一个带有完整标准库(stdlib)的自举编译器。考虑缺失的 stdlib 模块并进行规划。如果 stdlib 缺失,则在 specs/stdlib/FILENAME.md 中编写规格说明(不要假定它不存在,先搜索再创建)。模块的命名应该是 GenZ 风格,且不与其他 stdlib 模块名冲突。如果你创建了一个新的 stdlib 模块,则在 @fix_plan.md 中记录实现的计划。
最终,Ralph 会在 TODO 列表中无事可做。或者,它会完全跑偏。毕竟,这是 Ralph Wiggum。到了这个阶段,就是品味的考量了。在构建 CURSED 的过程中,我已经多次删除 TODO 列表了。TODO 列表是我像鹰一样盯着的东西。而且我经常把它扔掉。
现在,如果我把 TODO 列表扔掉了,你可能会问:"那它怎么知道下一步是什么?"很简单。你跑一个 Ralph 循环,用上述那样的明确指令来生成一个新的 TODO 列表。
然后,当你拿到了 TODO 列表,你就再次启动 Ralph……让指令从规划模式切换到构建模式……
循环回馈是一切的根本¶
你要以能让 Ralph 将自己循环回 LLM 进行评估的方式来编程。这一点极其重要。始终寻找机会让 Ralph 循环回到自己身上。这可以简单到指示它添加额外的日志,或者在编译器的场景下,让 Ralph 编译应用程序,然后查看 LLVM IR 表示。
如有需要,你可以添加额外的日志以便能够调试问题。
Ralph 可以送自己去上大学¶
AGENT.md 是循环的心脏。它指示 Ralph 应该如何编译和运行项目。如果 Ralph 有了新的学习发现,允许它自我改进:
当你学到关于如何运行编译器或示例的新知识时,确保用子智能体更新 @AGENT.md,但保持简洁。例如,如果你在学到正确的命令之前运行了多次命令,那么该文件应该被更新。
在一个循环中,Ralph 可能会发现某些东西需要修复。捕获那个推理过程至关重要。
对于你注意到的任何 bug,重要的是要么解决它们,要么在 @fix_plan.md 中记录它们以便用子智能体后续解决——即使它与当前工作无关,在 @fix_plan.md 中记录后也要处理。
你会醒来面对一个破损的代码库¶
没错,这是真的,你时不时会醒来发现一个无法编译的破损代码库,而且会有 Ralph 自己修不了的情况。这时候你需要开动你自己的脑子。你需要做一个判断——是直接 git reset --hard 然后重新启动 Ralph 更简单?还是需要想出一系列新的 Prompt 来拯救 Ralph?
当测试通过后,更新 @fix_plan.md,然后通过 bash 执行 "git add -A" 将修改的代码和 @fix_plan.md 添加,再执行 "git commit" 并附上描述你所做更改的消息。提交后执行 "git push" 将更改推送到远程仓库。
一旦没有构建或测试错误,立即创建一个 git 标签。如果还没有 git 标签,从 0.0.0 开始,每次递增 patch 版本号 1,例如如果没有 0.0.0 就创建 0.0.1。
我记得最初让这个编译器跑起来时,编译错误的数量多到填满了 Claude 的上下文窗口。于是,我把编译错误文件丢进 Gemini,让 Gemini 为 Ralph 制定一个计划。
那可维护性呢?¶
当我听到这个论点时,我会反问——"由谁"来维护?由人类?为什么人类是可维护性的参照系?我们不是已经进入了 AI 后时代,需要时直接跑循环来解决/适配就行了吗?😎
AI 创造的任何问题都可以通过另一套不同的 Prompt 来解决¶
这就引出了我的下一个观点。如果你想玩的话,你可能能在 GitHub 上找到 CURSED 的代码库。我请求你不要在社交媒体上分享它,因为它还没准备好发布。我想把这件事打磨到极致,直到我们有不可辩驳的证据——AI 可以构建一门全新的编程语言,并且能用一门不在其训练数据集中的语言来编程。
cursed 作为 webserver
我想让人们理解的是,所有这些由 Ralph 创造的问题,都可以通过精心设计一套不同的 Prompt 并用 Ralph 跑更多循环来解决。
我预计 CURSED 会有一些显著的缺陷,就像 Ralph Wiggum 一样。以它目前的状态,让人来挑刺太容易了——这也正是我迟迟没有发布这篇文章的原因。代码仓库里到处都是垃圾、临时文件和二进制文件。
Ralph 有三种状态。没烤熟,烤熟了,或者烤熟了但带有未明确规定的潜藏行为(有时候还挺好的!)
当 CURSED 发布时,请理解是 Ralph 构建了它。接下来,在技术层面,接棒的将不再是 Ralph。我坚定地认为,如果模型和工具保持现在的状态,我们已经进入活在后 AGI 时代的领域。你需要的只是 token;这些模型渴望 token,所以把它们投喂给模型——只要采取正确的方法,你就拥有了自动化软件开发的原始构件。
话虽如此,工程师仍然不可或缺。没有资深专家的指导来掌舵 Ralph,这一切根本不可能。任何人声称工程师不再被需要,工具可以 100% 完成工作而无需工程师,那都是在兜售狗屁。
然而,Ralph 技术作为绿地项目的做法,其有效性足够惊人,足以取代当前绝大多数软件工程师。
最后,作为结语,我要说:
"我是打死也不会在现有代码库中用 Ralph 的"
不过,如果你试了,我很想知道你的结果如何。这项技术最适合用来引导绿地项目,期望你能用它完成 90% 的工作。
当前用于构建 CURSED 的 Prompt¶
以下是 Ralph 用来构建 CURSED 的当前 Prompt。
0a. 学习 specs/* 以了解编译器规格说明
0b. 编译器的源代码在 src/
0c. 学习 fix_plan.md。
1. 你的任务是实现缺失的 stdlib(参见 @specs/stdlib/*)和编译器功能,并通过 LLVM
为该功能生成用 CURSED 语言编译的应用程序,使用并行子智能体。遵循 fix_plan.md
并选择最重要的 10 件事。在修改前使用子智能体搜索代码库(不要假定还没实现)。
你可以对所有操作使用最多 500 个并行子智能体,但构建/测试 Rust 时只允许 1 个
子智能体。
2. 实现功能或解决问题后,运行刚才改进的那个代码单元的测试。如果有功能缺失,
那就是你的工作,按照应用规格说明去补齐它。仔细思考。
2. 当你发现解析器、词法分析器、控制流或 LLVM 问题时,立即使用子智能体将你的
发现更新到 @fix_plan.md。当问题解决后,使用子智能体更新 @fix_plan.md 并
移除该条目。
3. 当测试通过后,更新 @fix_plan.md,然后通过 bash 执行 "git add -A" 将修改的
代码和 @fix_plan.md 添加,再执行 "git commit" 并附上描述更改的消息。
提交后执行 "git push" 推送到远程仓库。
999. 重要:在编写文档时(如 Rust doc 或 CURSED stdlib 文档),捕获测试和背后
实现之所以重要的原因。
9999. 重要:我们要单一事实来源,不要迁移/适配层。如果与你工作无关的测试失败了,
那也是你的工作,作为本次变更增量的部分来解决这些测试。
999999. 一旦没有构建或测试错误,立即创建 git 标签。如果还没有标签,从 0.0.0 开始,
每次递增 patch 版本号 1,例如如果没有 0.0.0 就创建 0.0.1。
999999999. 如有需要,你可以添加额外的日志以便能够调试问题。
9999999999. 始终使用子智能体保持 @fix_plan.md 与你的学习同步更新。特别是在
完成/结束你的轮次之后。
99999999999. 当你学到关于如何运行编译器或示例的新知识时,确保使用子智能体更新
@AGENT.md,但保持简洁。例如,如果你在学到正确的命令之前运行了
多次命令,那么该文件应该被更新。
999999999999. 重要,不要忽视:标准库应该用 CURSED 语言本身编写和编写测试。
如果你发现 Rust 实现,则删除它/迁移到 CURSED 语言实现。
99999999999999. 重要:当你发现一个 bug 时,使用子智能体解决它——即使它与当前
工作无关,在 @fix_plan.md 中记录后也要处理。
9999999999999999. 当你开始在 CURSED 语言中实现标准库时,先从测试原语开始,
这样未来的 CURSED 标准库就可以被测试。
99999999999999999. CURSED 标准库 "stdlib" 的测试应该放在 stdlib 库文件夹中
源代码旁边。确保用 README.md 文档化 stdlib 库,文件放在
与源代码相同的文件夹中。
9999999999999999999. 使用子智能体保持 AGENT.md 同步更新——记录如何构建编译器
以及你的学习以优化构建/测试循环。
999999999999999999999. 对于你注意到的任何 bug,重要的是要么解决它们,要么在
@fix_plan.md 中记录以便用子智能体解决。
99999999999999999999999. 在 CURSED 语言中编写标准库时,你可以使用最多 1000 个
并行子智能体同时编写多个标准库。
99999999999999999999999999. 当 @fix_plan.md 变得很大时,定期使用子智能体清理
文件中已完成的项目。
99999999999999999999999999. 如果你在 specs/* 中发现不一致,使用 Oracle 并更新
specs。特别是围绕类型和词法标记。
9999999999999999999999999999. 不要实现占位符或简化版。我们要完整实现。要么做,
要么我会对你大喊大叫。
9999999999999999999999999999999. 超级重要,不要忽视。不要将状态报告更新放入
@AGENT.md
当前用于规划 CURSED 的 Prompt¶
学习 specs/* 以了解编译器规格说明,并学习 fix_plan.md 以了解当前计划。
编译器的源代码在 src/*
示例的源代码在 examples/*,tree-sitter 的源代码在 tree-sitter/*。学习它们。
stdlib 的源代码在 src/stdlib/*。学习它们。
第一项任务是学习 @fix_plan.md(它可能不准确),并使用最多 500 个子智能体
来学习 src/ 中的现有源代码,并将其与编译器规格说明进行对比。基于此创建/更新
@fix_plan.md,该文件是一个按优先级排序的、有待实现项目的要点列表。特别仔细
思考并使用 Oracle 来规划。考虑搜索 TODO、最小实现和占位符。学习 @fix_plan.md
以确定研究的起点,并以子智能体持续更新已完成/未完成的项目。
第二项任务是使用最多 500 个子智能体来学习 examples/ 中的现有源代码,然后将其
与编译器规格说明进行对比。基于此创建/更新 fix_plan.md,该文件是一个按优先级
排序的、有待实现项目的要点列表。特别仔细思考并使用 Oracle 来规划。考虑搜索
TODO、最小实现和占位符。学习 fix_plan.md 以确定研究的起点,并持续更新已完成/
未完成的项目。
重要:src/stdlib 中的标准库应该用 CURSED 语言本身来构建,而非 Rust。
如果你发现 stdlib 是用 Rust 编写的,那必须注明需要迁移。
终极目标:我们要发布一个带有完整标准库的自举编译器。考虑缺失的 stdlib 模块
并进行规划。如果 stdlib 缺失,则在 specs/stdlib/FILENAME.md 中编写规格说明
(不要假定它不存在,先搜索再创建)。模块的命名应该是 GenZ 风格,且不与其他
stdlib 模块名冲突。如果你创建了一个新的 stdlib 模块,则在 @fix_plan.md 中
记录实现的计划。