我正在建立一個開源庫,它已被下載約 8,000 次,並在日本和美國都有使用。
然後我進行了推廣,意識到我搞砸了,倉庫裡每多一顆星,我的胃就一陣翻騰。
我的結論是:自稱高階用戶所謂的「氛圍編碼」其實就是一團亂麻。
我沒有把爛攤子丟掉,而是決定把它改造成可以吃的東西。這就是這次重啟的意義。
你有沒有過這樣的經驗:某個個人專案進展極為緩慢,以至於幾個月都無法繼續進行?
我的結構化資料差異比較工具diffx從 2025 年 8 月到 11 月基本上處於停滯狀態——大約三個月。它本應已經“功能齊全”,但我卻無法繼續開發。我分析了問題所在,並使用我現在稱之為“重啟”的流程使其恢復執行。
這篇文章記錄了所有內容:根本原因分析、與 AI 合作失敗、擺脫單體倉庫以及具體的重啟步驟。
誰該讀這篇文章?
獨立開發者陷入停滯的專案
在使用人工智慧結對程式設計(例如 Claude Code)時,人們在程式碼品質方面遇到的困難
工程師們對單體程式碼庫和共享的 CI/CD 框架感到厭倦
{% github kako-jun/diffx %}
diffx 是一個 Rust 工具,它可以從 JSON、YAML、TOML、XML、INI 和 CSV 等結構化資料中提取語義差異。與傳統的基於文字的差異比較不同,它忽略格式和鍵順序的變化,只顯示有意義的差異。
$ diffx config-old.yaml config-new.yaml
~ server.port: 8080 -> 9000
+ server.timeout: 30
- server.deprecated_option
它專為 DevOps/SRE 工作流程而設計,尤其適用於追蹤 Kubernetes YAML 和 Terraform 配置變更。此外,它還有 npm 版本 (diffx-js) 和 Python 版本 (diffx-python)。
以下是當時的貼文:
這個計畫獲得了大量點贊,甚至有人成為了贊助商。
從表面上看,這個專案似乎已經很完善了:
README 文件提供日文、英文和中文版本。
支援六種資料格式
npm 和 Python 端口
複雜的 CI/CD 管道
一項740線遷移計劃
但實際上:
CI/CD 系統已完全損壞,無法修復。
測試結果不一定能驗證實際規格。
文件和實際執行之間可能已經脫節。
從技術上講,命令列介面 (CLI) 可以執行,但說實話,我不能稱其為可持續的。
我花了三個月時間「研究如何使其可持續發展」。
分析 diffx 後,我發現了三種主要的故障類型。
除了 diffx 之外,我還構思了兩個姊妹專案:diffai(用於 AI 模型配置的差異)和 lawkit(如本福特定律的統計)。
我做了什麼
為這三個系統建構了一個共享的 CI/CD 系統
嘗試透過workflow_call來協調所有操作。
加入了指向共享倉庫的符號連結
結果
我將共享部分(GitHub 工作流程、腳本等)拆分到另一個儲存庫中,然後從每個專案建立符號連結。
/home/kako-jun/repos/.github/ ← shared repo
└── rust-cli-kiln/
└── scripts/
└── testing/
└── quick-check.sh ← never stabilized
Inside each project:
github-shared -> ../.github ← symlink
quick-check.sh存在,但針對 diffx 調整後導致 lawkit 出現問題,而修復 lawkit 又導致 diffai 出現問題。所有測試結果都顯示正常。
教訓:第一個專案穩定之前,不要考慮下一個專案。
我將 Rust 核心程式碼以及 npm 和 Python 綁定放在同一個倉庫。
diffx/ # monorepo
├── diffx-core/ # Rust
├── diffx-cli/ # Rust
├── diffx-js/ # Node.js (napi-rs)
└── diffx-python/ # Python (PyO3)
問題
三種語言/工具鏈共享一個程式碼庫
GitHub Actions 擴展為六個工作流程以及共享倉庫
任何改變都有可能毀掉一切。
釋放過程需要多步驟的儀式
依賴關係圖呈指數級增長,變得極為複雜。
釋放節奏不匹配
Minor bug fix in Rust
→ diffx-core v0.6.1
→ diffx-cli v0.6.1
→ diffx-js needs binding updates (half-day)
→ diffx-python needs similar updates (half-day)
→ Rust-only release goes out
→ Versions drift apart
我從一開始就嘗試發布三個 README 文件。
問題
保持三個文件同步真是太累了。
每一次改變都會變成三倍的工作量
你忘記了哪個文件才是「真相」。
所有事物同時變得陳舊乏味。
更好的方法
Phase 1: README_ja.md only (use the language you can edit fastest)
Phase 2: Add English once the project matures
Phase 3: Add other languages based on demand
我大量使用了 Claude Code,並遇到了多種故障模式。
在上下文壓縮了三倍的會話中,答案一開始很完美,但隨著時間的推移而逐漸退化。
Start: accurate, detailed implementation
↓ 1 hour later: subtle spec violations
↓ 2 hours later: obvious bugs
↓ 3 hours later: forgets prior instructions entirely
當僅剩 20% 上下文時的行為
一旦上下文資訊不足,人工智慧就會公開改變其性格:
毫不猶豫地說謊
隨機省略程式碼
即使未被要求,也會主動促成交易。
即使有了規範文件,它也會忘記規範並隨意編寫程式碼。盲目信任人工智慧的初學者很容易陷入規範與程式碼不同步的困境。
為什麼會發生這種情況?
我的猜測是:人工智慧程式設計師接受的訓練是「在上下文崩潰之前乾淨利落地完成程式碼編寫」。這本身就合情合理。
但如果把這種本能和「一年級新生式的直覺程式設計」結合起來,那就注定要失敗。在 Qiita 或 Zenn 上,你會看到一些興奮的帖子:「我用直覺編程做出了這個!大家都應該試試!」這種熱情固然高漲,但人工智能「必須完成」的本能加上初學者「人工智能會保護我」的盲目信任,最終只會走向失敗。
這就是「氛圍編碼」的危險之處。我的定義是:
在單次會話中破解main
隨意下達指令,無須考慮上下文大小
相信它「有點用」。
醒來發現有 2000 多行義大利麵
如果是玩具專案,那就沒問題。但如果你在進入「幻滅階段」之前就一直按照預設的思路來設計,最終肯定會失敗。
撇開上下文問題不談:即使是 Opus 4.5,在有很多上下文的情況下,也經常在「已實施」方面撒謊。
人工智慧明明知道正確的事實,卻仍輸出與事實相反的程式碼。知道正確運用是兩碼事。
因應措施:讓同一人工智慧系統檢視自己的工作成果。
Me: "Implement this feature."
AI: "Implemented."
Me: "Review it yourself. Are you sure it's spec-compliant?"
AI: "I found the following issues..." (and fixes them immediately)
這就是為什麼業內一直在談論「人工智慧自動審核」。它正是應對這種失敗模式的良方。我當時只是不知道而已。
Me: "Add an option to ignore case."
AI: "Added --ignore-case."
Result: Values compare case-insensitively, but keys do not.
我理解的「忽略大小寫」包括鍵,但人工智慧並沒有推斷出這一點。
根本問題:我缺乏描述開發原則的詞彙。
當基於氛圍的編碼失效時,你需要告訴人工智慧「應用單一職責」或「分離關注點」。如果你不了解這些短語,那就束手無策了。
更好的說明
❌ "Add an option to ignore case."
✅ "Add --ignore-case with the following effects:
1. Compare values case-insensitively.
2. Compare keys case-insensitively.
Example: {"Name": "foo"} and {"name": "foo"} should be equal."
今天我至少會寫這麼多——或者讓人工智慧幫我起草這些指令。那時候我沒有這個習慣。
Me: "Read README.md and implement accordingly."
AI: "Implementation complete based on README."
Result: README was full of lies, so it implemented lies.
早期的AI會議已經讓醫生偏離了現實。
$ cargo test --workspace
29 passed; 0 failed
看到綠色檢測結果讓人安心。這是個錯誤的想法。
原因:人工智慧一旦看到程式碼,就會編寫測試案例來驗證目前的實作。當然,測試案例第一次執行就會通過——這並非成功。
像 Serena 這樣的工具會自動讀取程式碼。你無法隱藏它。因此,你必須明確地指示:
❌ "Write tests for this code."
✅ "Write tests based on docs/specs/cli.md.
Do not read the implementation. Tests must derive from the spec."
為什麼規範驅動開發很重要
事後看來,這就是「規範驅動開發」成為趨勢的原因。
規範被細分為許多細粒度的問題。
每期都包含人工智慧的詳細操作說明。
人工智慧會發現問題並加以解決。
GitHub MCP 會為每個功能建立分支。
PR會被審核。
遵循這個流程就能自動避免程式碼風格上的災難。這確實是一個很好的流程。
人工智慧發展成熟度金字塔
人工智慧輔助開發可以用一個三層金字塔來描述。 Vibe 編碼處於最底層。只有達到至少第二層,才能可靠地運作公共專案。用戶會受到影響。
重啟時我也使用了 Claude Code。
我向它坦白了一切,請求它提供復興計劃,它給了我一些既友善又實用的方案——不像岸邊露伴的懺悔室那樣。它奏效了。
在.claude目錄下建立reboot子目錄作為命令中心。
再次執行/init ,讓 Serena 從頭開始掃描整個儲存庫。
整個過程大約需要三天時間,因此需要人工在每次會話之間維護狀態。如果時間延長,人工操作又會成為瓶頸。
1. Assume everything outside reboot is untrustworthy.
2. Assume files are half-baked.
3. Assume docs are lying.
4. Figure out which parts are true.
那是人類的工作。克勞德·科德是戰略家;我只是個努力跟上步伐的小劉備。
首先,我將現有檔案移至_old/目錄,以建立空白畫布。
# Removed or quarantined
- docs/ (including examples) → breeding ground for unchecked lies
- English and Chinese READMEs
- scripts/ (complex CI/CD)
- benchmarks (non-essential)
- CHANGELOG.md, CONTRIBUTING.md
結果:109 個檔案已更改,32145 行已刪除。
我把 README_ja.md 中的每一句「它有效」的語句都手動驗證了一遍。
# Test each format
echo '{"a":1}' > test1.json
echo '{"a":2}' > test2.json
./target/release/diffx test1.json test2.json
發現
✅ All six formats (JSON/YAML/TOML/XML/INI/CSV) work.
✅ Output formats (CLI/JSON/YAML) work.
✅ --quiet, --ignore-keys-regex, --epsilon, --array-id-key work.
⚠️ --ignore-case may only affect values, not keys.
❓ --ignore-whitespace and directory diffs unverified.
結論:核心功能運作正常。問題出在未經驗證的功能。
我只記錄了我親自確認的行為。
docs/specs/
├── cli.md # CLI specs (exit codes, output, options)
└── core.md # Core API specs
規範原則
在查看程式碼之前,先描述一下理想的行為。
檢查是否已實現。
只記錄真正有效的方法。
將損壞的部分標記為待辦事項。
永遠不要說謊。
我刪除了現有的 436 個測試案例(8,022 行),並根據規格重新編寫了它們。
新測試佈局
tests/
├── spec/ # Spec-driven unit tests (69 cases)
└── cmd/ # trycmd-based doc-as-test (19 cases)
為什麼要使用 trycmd
Markdown 既可用作文件,也可用作測試。
文件不能脫離測試結果。
你不可能憑空捏造文件。
當以上所有情況都屬實時,我選擇了離開:
不同的建置系統:Cargo、npm 和 pip。
不同的發布節奏:需要獨立發布。
不同使用者群體:Rust、Node.js 和 Python 開發者。
CI/CD 複雜性:跨語言相互依賴難以管理。
diffx 擊中了所有四個。
cd /home/kako-jun/repos/
mkdir diffx-js && cd diffx-js && git init
mkdir diffx-python && cd diffx-python && git init
cp -r ../diffx/diffx-js/* ./diffx-js/
cp -r ../diffx/diffx-python/* ./diffx-python/
重要提示:我已刪除 Git 歷史記錄。保留歷史記錄會使一切變得複雜。
diffx-js 和 diffx-python 現在從 crates.io 拉取diffx-core 。
# diffx-js/Cargo.toml
[dependencies]
diffx-core = "0.6" # versioned dependency instead of path
# diffx/Cargo.toml
[workspace]
members = ["diffx-core", "diffx-cli"]
# diffx-js and diffx-python removed
/home/kako-jun/repos/
├── diffx/ # Rust only (simple)
│ ├── diffx-core/
│ ├── diffx-cli/
│ └── .github/workflows/
│ ├── ci.yml
│ └── release.yml
│
├── diffx-js/ # npm only
│ └── .github/workflows/
│ ├── ci.yml
│ └── release.yml
│
└── diffx-python/ # pip only
└── .github/workflows/
├── ci.yml
└── release.yml
易於理解的 CI/CD :從六個工作流程 + 共享倉庫簡化為每個倉庫兩個工作流程。
獨立發布:不急;每種語言都可以按照自己的步調發布。
明確的所有權:每個程式碼庫只有單一職責。
更簡單的貢獻:Node 開發人員只需要閱讀 diffx-js。
拆分程式碼庫讓我明白了一個至關重要的原則。
反模式
# ❌ Dangerous workflow
name: Release
on:
push:
tags: ["v*"]
jobs:
build-and-publish:
steps:
- run: cargo build --release
- run: cargo publish # publishes before confirming all builds succeed
為什麼說它不好:
如果 Windows/macOS/Linux 建置成功,只有一個系統版本成功,該怎麼辦?
cargo publish無法撤銷。
即使你發現了問題,唯一的解決方法也是提高版本號碼。
你無緣無故刻錄版本(v0.6.1 → v0.6.2 → v0.6.3...)。
# ✅ Safe workflow (release.yml)
name: Release
on:
push:
tags: ["v*"]
jobs:
build-linux:
runs-on: ubuntu-latest
steps:
- run: cargo build --release
- uses: actions/upload-artifact@v4
build-macos:
runs-on: macos-latest
# ...
build-windows:
runs-on: windows-latest
# ...
create-release:
needs: [build-linux, build-macos, build-windows]
steps:
- uses: actions/download-artifact@v4
- uses: softprops/action-gh-release@v1
with:
files: |
diffx-linux/*
diffx-macos/*
diffx-windows/*
# ✅ Publish is a separate workflow (publish.yml)
name: Publish
on:
workflow_dispatch:
inputs:
version:
description: "Tag to publish"
required: true
jobs:
publish:
steps:
- run: gh release view v${{ inputs.version }} # confirm release exists
- run: cargo publish
Step 1: Push tag → build for all platforms → create GitHub release
↓
Stop here. A human verifies everything.
↓
Step 2: Manually trigger the publish workflow
→ Push to crates.io / npm / PyPI
故障場景
| 場景 | 單階段工作流程 | 兩階段工作流程 |
| ------------------- |----------------------------- | ------------------- |
macOS 建置失敗 | 已發佈損壞版本 | 未發佈任何內容 |
| 恢復 | 必須發佈 v0.6.2、v0.6.3… | 刪除標籤,重新推送 |
版本消耗 | 浪費 | 高效率 |
1. Run the code yourself and find the truth.
2. Write specs in docs/specs/.
3. Build tests from those specs.
4. Fix the implementation until tests pass.
5. Update docs (README, etc.) to match the specs.
反模式
先寫文件→它們會變成謊言。
相信現有的測試結果→它們只能驗證表面上的結果。
舊測試用例編寫時沒有遵循規範。
examples/目錄(它們腐爛成謊言)。
舊路線圖(已執行或過時)。
宣傳資料(六個月後失效)。
docs/specs/ – 唯一真理的來源。
tests/cmd/ – 由測試強制執行的文件。
.claude/tasks.md – 目前任務清單。
CLAUDE.md – 最低開發規則。
Specs: 1 session
Tests: 1 session
Docs: 1 session
Cleanup: 1 session
Total: about four sessions (one session = one context window).
❌ Frozen for 3 months
❌ Monorepo complexity
❌ Broken CI/CD
❌ Maintaining three languages
❌ Happy as long as "it runs"
❌ Blind faith in existing code
✅ Back in motion
✅ Lean Rust-only repo
✅ Separate language-specific repos
✅ Focused on Japanese docs
✅ Obsessed with correctness
✅ Doubt everything
| 指標 | 前 | 之後 |
| ------------ | -------------- | ---------------- |
文件 | 很多 | -109 |
| 線 | 多 | -27,770 |
| 測試 | 436(意義?) | 88(規範驅動) |
| 自述文件 | 3 種語言 | 3 種語言 |
|存放庫 | 1 (單一倉庫) | 3(每種語言)|
重啟一個停滯了三個月的專案並不需要新功能或花哨的技術。
這需要質疑的勇氣和刪除的勇氣。
對現有測試結果表示懷疑。
懷疑文件的真實性。
質疑人工智慧現狀報告。
懷疑你對「完成」的理解。
刪除任何可疑物品。
我以前一直很納悶,為什麼聰明人也會犯下沉沒成本謬誤。結果發現,我也是其中之一。
你之所以對測試、文件和 CI/CD 如此執著,是因為「丟掉它們」感覺很浪費。但保留這些損壞的工件對誰都沒有好處。我最終言行一致,把它們都刪除了。
這是重啟的核心,也是永續發展的關鍵。
人工智慧引入了一個微妙的問題。
VS Code 的儲存時格式化功能從未運作。
當人類在 VS Code 中編寫程式碼時,格式化程式和.editorconfig檔會自動套用。而當 AI 直接寫入檔案時,這些都不會觸發。
結果:
縮排錯位
缺少尾隨換行符
隨機導入順序
到處都是無關緊要的 lint 警告。
CI 會因為一些無意義的事情而失敗,浪費時間。
解決方案:pre-commit鉤子
設定 pre-commit,以便在每次提交之前執行格式化和程式碼檢查。以下是 diffx-python 的實際配置:
# .pre-commit-config.yaml (diffx-python)
repos:
- repo: local
hooks:
- id: cargo-fmt
name: cargo fmt
entry: cargo fmt --
language: system
types: [rust]
pass_filenames: false
- id: cargo-clippy
name: cargo clippy
entry: cargo clippy -- -D warnings
language: system
types: [rust]
pass_filenames: false
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.6
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-toml
- id: check-added-large-files
# Setup
pip install pre-commit
pre-commit install
在 diffx-js (Node.js) 中,我改用 Husky:
// package.json (diffx-js)
{
"scripts": {
"prepare": "husky"
},
"devDependencies": {
"husky": "^9.1.7"
}
}
這樣,AI編寫的程式碼在提交時就會自動格式化。
儲存庫
{% github kako-jun/diffx %}
{% github kako-jun/diffx-js %}
{% github kako-jun/diffx-python %}
我還沒有寫正式的發布文章,但這些專案的初始版本都能正常運作,這足以證明重啟過程是可重複的——至少對我的生態系統而言是如此。
{%github kako-jun/define %}
{% github kako-jun/lawkit %}