Releases: yama-learns/Spark2Groundwork
Release list
v1.4.4 — 升級前驗證可復原收據,policy/ 退役
v1.4.4 — 有一支程式從 v1.4.1 起就在替你簽名
A program had been signing your name since v1.4.1
🔴
v1.4.3從未發布。 它在發布前的覆核中被找到五項缺陷,三項紅級。
⇒ 你不會在任何地方看到 v1.4.3,⛔ 那不是遺漏。
Upgrading now verifies a recoverable pre-image, and policy/ retires
這一版由一次外部稽核開始:有人用 v1.4.2 升級他的專案,然後把出問題的地方寫成報告。
This release started with an outside audit: someone upgraded a real project to v1.4.2 and wrote up what broke.
🔴 這一版最重要的一件事
v1.4.1 與 v1.4.2 有一個缺陷:按下升級之後,reviewed 標籤會被移到升級前的提交,
畫面上還會印「人工檢查點:我看過了」——⛔ 而你並沒有按下那個按鈕。
🔴 後果⛔ 不是標籤變了,是你的「還沒看過」被清空:
如果升級當下有 AI 做完、而你還沒審閱的工作,那些變更會從「查看變更」裡消失。
v1.4.4 已經修好。⛔ 但已經被移動過的標籤,程式修好也不會自己還原——
⇒ 請照「升級前必讀」的第 ④ 項檢查一次。
🔴 升級前必讀:四件要你動手的事
Before you upgrade: four things only you can do
① 你填的構想搬家了 / Your filled-in idea has moved
如果你曾經把構想填進 prompts/TEMPLATE_decompose.txt,它現在住在專案根目錄,改名叫
第一個想法.md(英文版 FIRST_IDEA.md),與 PROJECT.md 同層。
🔴 prompts/ 是升級時整包替換的資料夾——⛔ 你填的東西不該住在那裡。
升級工具現在會擋下來並列出檔名,⛔ 而不是換掉它。 照它說的搬,再重跑一次。
If you had filled in
prompts/TEMPLATE_decompose.txt, it now belongs at the project root as
FIRST_IDEA.md, besidePROJECT.md.prompts/is replaced wholesale on upgrade — your text
should never have lived there. The upgrader now stops and names the file instead of replacing it.
② policy/ 退役了 / policy/ has retired
它的四份文件(SOURCES.md、MODEL_IDENTITY.md、HANDOFF.md、EXTERNAL_TOOLS.md)
已經搬進 governance/。
⛔ 升級工具⛔ 不會刪掉你專案裡的 policy/——框架不刪使用者的檔案。
check、diff 與每一次成功的 apply 之後把它列出來:
⚠️ 這幾個資料夾已經退役,⛔ 而升級工具⛔ 不會刪掉你的東西:
⛔ `policy/`(於 v1.4.4 併入 `governance/`)——內容已經在 `governance/` 了;
確認之後這個資料夾可以自己刪掉
🔴 為什麼要講這件事:一個沒有人告訴你的孤兒資料夾,與一份過期的框架文件完全一樣——
它看起來還是框架的一部分,而⛔ 再也不會有任何東西更新它。
③ 框架第一次修訂了一條既有規則 / A shipped rule was revised for the first time
R-34 補了一句:「權威敘述的效力範圍,本身也是需要被查的東西。」
升級完 governance/ 之後跑:
python3 scripts/harness/tool_sync_my_rules.py
它會印出逐行差異,+ 開頭的就是新增的句子。
🔴 把那幾行逐字貼進 my/MY_RULES.md 裡 R-34 的正文,然後再跑一次確認。
⛔ ⛔ 沒有工具會替你做這一步,這是刻意的。
MY_RULES.md——那會刪掉你的 P-xx 與覆寫紀錄。
標了 [本專案覆寫] 的條目工具一律不碰,並且會逐條印出來。
R-34gained a clause. After replacinggovernance/, run the rule-sync tool: it prints a
line-by-line difference, and the+lines are the new sentences. Paste them verbatim into
R-34's body inmy/MY_RULES.md, then run it again to confirm. ⛔ No tool does this for you,
and that is deliberate — a tool that overwrote your rules file was found, in this version's own
review, to still write when its safety check had failed.
④ 🔴 檢查你的 reviewed 基準 / Check your reviewed baseline
⛔ 這一項⛔ 不是「跑一行指令就知道」——SETUP.md §9 有完整的三步,請照那裡做。
這裡只講為什麼它需要三步:
git log --oneline -1 reviewed
🔴 ⛔ 「訊息開頭是不是 snapshot …」⛔ 不能當判準。
auto: 提交上——
⛔ 而那也正是「你在 AI 做完之後按了一次記錄快照」的樣子。⇒ 兩者長得一模一樣。
⇒ 第二步是查 git-checkpoint.log 裡 mode=human 的時間,與你自己的記憶對照。
⇒ 第三步:兩步都判不出來時,⛔ 不猜、⛔ 不重設——退回一個你確定看過的提交重看一次。
reviewed,⛔ 而它正是被懷疑的東西。
⛔ ⛔ 不建議放著不管——一個指向你沒看過的地方的「我看過了」,比沒有標籤更糟:
沒有標籤時「查看變更」會拿 HEAD 當基準並明說,
SETUP.md§9 walks three steps. ⛔ The commit message alone is not a criterion: on a clean
working tree — the common case — the old upgrader moved the tag onto an existingauto:
commit, which is also what a legitimate human review looks like. Step 2 reads the
mode=humantimestamps ingit-checkpoint.logagainst what you remember; step 3, when
neither can tell, is ⛔ do not guess and do not reset — drop back to a commit you are certain
about and read forward. ⛔ Not with the review-changes button: its baseline is the very tag
under suspicion.
這一版做的事 / What this release does
🔴 升級會在整包替換前證明既有內容可依 Git 語意取回
整包替換仍然是整包替換——⛔ 沒有改成逐檔合併。
⛔ 而且不建立檢查點、不動任何東西。
[FAIL] 「scripts」內有新版來源沒有的檔案,⛔ 尚未建立檢查點,也沒有替換任何東西。
這些檔案可能屬於專案;請先逐一搬到整包替換範圍外,再重跑:
⛔ scripts/my_tool.py
🔴 它⛔ 不猜所有權。 你自己寫的工具請搬到 my/tools/——那裡升級永遠不會碰。
新增第十支感測器:這幾包是不是同一版
觸發個案: 有一個專案的 policy/ 停在 v1.3.0,而 governance/、profiles/、docs/
已經是 v1.4.2。九支感測器全綠、自測全過。
🔴 ⛔ 沒有任何一支在看「這幾包是不是同一版」——那個狀態是靜默的,靠一次外部稽核才被發現。
⛔ 它不宣稱的事: 版本標記只回答「這個資料夾自稱哪一版」。
同一個專案還有另一半:prompts/_VERSION 寫 v1.4.2,而裡面的內容仍是 v1.3.0。
⇒ 這支抓得到「自稱不一致」,⛔ 抓不到「自稱一致而內容不同」——那件事要跑 upgrade.py diff。
修掉一個會冤枉你的假警報
根目錄的 *.command 這類樣式,掃描目錄被算成了專案的「父目錄」。
🔴 於是隔壁專案的一個檔案,就能讓你這個健康的專案被判成「查不了」。
_upgrade/(升級說明叫你建的那個資料夾)
裡的檔案會重現同一個假警報。
⇒ 兩處都修了,並補了三組成對樣本:父目錄一例、_upgrade/ 一例,
加上一個「真的覆蓋崩潰仍然必須報」的正例。
🔴 第三例不能省——只加排除很容易把真正的警報一起關掉。
中文版的 讀我 改叫 說明書
「讀我」是 README 的直譯,⛔ 不是中文說法。 英文版的 READ_ME 也統一成 README。
🔴 規則同步工具⛔ 不會覆蓋你的檔案
v1.4.3 曾經有一個 --adopt 會替你把漂移的規則換成公版原句。⛔ 那一版沒有發布,
而那個功能已經被整個退回。
現在這一支只做兩件事:把缺少的規則附加進去、把不同的地方逐行印出來。
⛔ 它永遠不會覆蓋 MY_RULES.md 裡任何一個既有的字。
🔴 升級之後想把手動改動找回來:使用持久收據
升級在覆蓋之前一定會先建立還原點。⛔ 而 v1.4.4 之前,完成訊息叫你用「查看變更」把改動找回來
——那是假的: 那個按鈕以 reviewed 為基準,⛔ 而工具建立的還原點刻意不移動 reviewed。
🔴 ⇒ 你的 pre-image 確實還在,卻落在那個按鈕的視野之外。
第一版修正只印出提交編號,⛔ 仍有缺口: ignored、assume-unchanged 或
skip-worktree 可能讓 checkpoint commit 與即將被覆蓋的工作檔不同。
Windows 實測曾出現「checkpoint exit 0、提交內沒有手改檔、apply 仍覆蓋」;手改內容隨即消失。
現在 apply 會在替換前逐檔核對: 每個即將被同路徑覆蓋的既有非暫存檔都必須受 Git
追蹤,且依 Git 自己的 attributes/EOL 語意與 checkpoint tree 完全相符;任一項不成立就
列出路徑、exit 2、零替換。
驗證後會建立專案本地持久收據:Git 私有 ref 同時固定 checkpoint 與權威 manifest,可讀 JSON
鏡像放在 Git 自己的目錄。它能在同一個 Git 倉庫內抵抗一般垃圾回收,⛔ 但一般 git clone
或只備份工作檔案不會自動帶走這些私有 ref;它不是跨倉庫備份。
在同語言、同版本且完整的 v1.4.4 套件中,使用者不需要輸入 raw Git 指令:
列出收據: python3 scripts/harness/upgrade.py receipts
查看單檔差異: python3 scripts/harness/upgrade.py receipt-diff <收據> <檔案路徑>
還原一個檔案: python3 scripts/harness/upgrade.py restore <收據> <檔案路徑>
restore 一次只還原一個目前存在的一般檔案,動手前會先建立反向收據,只改 working tree,
且⛔ 不移動 reviewed。apply 與 restore 都先找執行中升級器同目錄、具有相符 tool API
標記的 checkpoint.py,再考慮專案內版本;兩者都不相符時零寫入,並要求重新下載完整同版套件。
讀不回或驗不過收據時,程式不會開始覆蓋或還原。
🔴 中文/英文套件不能再互相覆蓋
v1.4.2 沒有 edition 檢查;中文專案若誤放英文下載包,apply governance 會 exit 0 並把治理文件
整包換成英文。v1.4.4 先用既有三個語言專屬啟動器辨認來源與專案:Windows 可只有 .bat、
macOS 可只有 .command,也可兩套都有。兩邊必須都能唯一辨認且語言相同;跨語言、混合或缺漏
都在檢查點、收據與替換之前拒絕。
🔴
.bat/.command 不參與判定,⛔ 而專案若自己建了一個與它們同名的檔案
(例如自己寫的 snapshot.bat),會被算成另一個語言版本,整次升級被擋下。
🔴 ⇒ 發布前的覆核抓到這件事,所以訊息已經改掉:它現在會逐一列出兩側實際看到的啟動器與所屬版本,
⇒ 你一眼就看得到是哪一個檔案。⇒ 規定動作:把它改名(或搬進 my/),再跑一次。
⚠️ 判定只讀下列十二個框架啟動器檔名,⛔ 不看是誰放的。實際看到的是:
升級來源:查看變更.bat[中]、檢查更新.bat[中]、記錄快照.bat[中]……
目前專案:查看變更.bat[中]、檢查更新.bat[中]、記錄快照.bat[中]、snapshot.bat[英]
The gate reads only these six framework launcher names and ⛔ not who put them there, so a
project file that happens to carry one — your ownsnapshot.bat, say — counts as the other
edition and blocks the whole upgrade. Pre-release review caught this, so the refusal now
lists the launchers found on each side with their edition: rename the offending file (or move
it undermy/) and run again. A missing launcher from your own edition is likewise refused,
with zero writes.
🔴 同一道閘門帶來另一項行為變更:_upgrade/ 裡⛔ 不能再只放一個資料夾。
v1.4.2 以前,只把 governance/ 丟進 _upgrade/ 就能升級那一包;
v1.4.4 要在來源端也看到完整的語言啟動器,⇒ 只放單一套件會被判成不完整並 exit 1(零寫入)。
⇒ 請解壓完整套件。
One more behaviour change from the same gate:
_upgrade/can no longer hold a single package.
Dropping justgovernance/in there worked before v1.4.2; v1.4.4 needs the source side to show
a complete launcher set, so a single-package source is now rejected as incomplete with exit 1
and no writes. Unpack the complete package.
🔴 語料庫的雜湊會在「換一台機器」時整片變紅——⛔ 而內容沒有被動過
如果你曾在 Windows 上跑過 tool_pdf_to_md.py,這一項與你有關。
提取工具寫檔時沒有固定行尾,⇒ Windows 上檔案以 CRLF 落地,
而 _manifest.json 記的就是 CRLF 的雜湊。⛔ 而框架的 .gitattributes 會把倉庫內正規化成 LF。
🔴 ⇒ 下一次乾淨簽出(clone 到第二台機器、git checkout、或照 SETUP.md §9 復原)
工作區變成 LF,每一個提取物的雜湊都對不上 → CORPUS_MD_MODIFIED 整片 FAIL。
v1.4.4 已修(newline="\n")。⇒ 規定動作:重跑一次提取工具,
manifest 與檔案會一起變成 LF,⇒ 自洽。
If you have ever run
tool_pdf_to_md.pyon Windows, this affects you. The extractor did not
fix its line ending, so files landed as CRLF while.gitattributesnormalises the repository
copy to LF. On the next clean checkout every recorded hash mismatches and the corpus goes red
with nothing actually changed. Fixed in v1.4.4; run the extractor once more so the
manifest and the files agree again.
感測器現在會說出它比對了幾份
主張台帳感測器一直在逐檔重算語料庫的雜湊,⛔ 而它從來沒有說過。
🔴 兩位不同的稽核者、隔了七天,各自得到「找不到哪一支感測器在做這件事」的結論——⛔ 而它一直都在。
⇒ 統計欄現在印「逐檔比對雜湊:N 份」;語料庫是空的時候印 0,⛔ 不是省略。
事故登記簿新增三個失效家族
⑨ 批次編輯成功了、⛔ 而它做的不是你要的事(🔴 讀 diff 抓不到它);
⑩ 為一個環境調好的常數,原封不動搬到另一個(🔴 兩邊逐字相同,⇒「一致」正是它的偽裝);
⑪ 兩個寫入者共用一個編號空間,而各自看來都配號成功(碰撞只在合併後出現)。
另加「索引當權威」的兩個新變體。[框架自身]——它們發生在維護這套框架的過程中。
其他
-
tool_sync_my_rules.py以前會忽略--root,可能寫到你沒有指名的那個專案,而且退出碼 0。 -
tool_my_index.py --help以前會覆寫你的索引。 兩支現在都先驗參數再動檔案。 -
可替換清單的數字從說明文字裡全部拿掉了。 那個數字已經漂過三次(九 → 16 → 15)。
🔴 清單才是權威;一個複述它的數字只是第二份拷貝,而它會過期。 -
🔴 框架自己的原始碼引用了一條不存在的規則。
anchor_norm.py兩處寫R-43,
⛔ 而RULES.md只到R-35;那兩句其實都是R-27。⛔ 沒有任何一支感測器在查規則 ID 引用
(一支查檔案存不存在、一支查章節解不解析得出來),⇒ 它在每一次全綠中存活。
⚠️ 英文版⛔ 從來沒有這兩處引用。⇒ 補上感測器留給 v1.5.0 的保證地圖。 -
CITATION.cff曾經連續三個版本停在1.1.0,因為它不在_VERSION機制裡、也沒有感測器看它。
已對齊為 1.4.4,並在維護側加了一道發版閘門。 -
人工檢查點以前會在標籤建不起來時謊報成功。 專案裡只要先有一個
reviewed/<某某>標籤,
Git 就再也放不下reviewed,⛔ 而程式照樣印「基準已移到最新的檢查點」並回 0。
🔴 **現在它檢查退出碼、把標籤讀回來與...
[1.4.2] — 2026-08-28
[1.4.2] — 2026-08-28
🔴 The change / 這一版做的事
One defect, found by releasing v1.4.1: the file index was sorted by platform, not by name.
🔴 索引的排序取決於作業系統,⛔ 而不是檔名。
Fixed / 修正
- 🔴
tool_my_index.pysortedPathobjects.⚠️ WindowsPathcomparison casefolds
first;PosixPathdoes not — soPROJECT.mdsorts beforecorpus/on Linux and after it
on Windows.
⛔ The index shipped with v1.4.1 was generated on Linux, sosensor_my_index.pyreported
MY_INDEX_STALEon the first run on a Windows machine.
⚠️ What it reported was ⛔ not "the index is stale" but "your operating system is not the
one that generated it" — and it had already forced a manual workaround mid-release.
🔴 A criterion that fires on a correct state teaches people to ignore it (R-19).
The sort key is now the relative posix string. ⛔ Never thePathobject.
Self-tests / 自測
78 → 79.
case-insensitive filesystem (Windows, macOS). ⛔ On Linux the old and new code agree, so it
cannot fire there — it is kept because the release procedure runs the self-test on Windows.
⛔ This release does not claim / 本版不宣稱
- ⛔ That every generated artefact is now reproducible across platforms.
⚠️ Only this one
was examined. The general shape — "sorted() on a type whose ordering is platform-dependent" —
⛔ has not been swept for.
[1.4.1] — 2026-08-27
[1.4.1] — 2026-08-27
🔴 The change / 這一版做的事
Six defects where a document and the code disagreed, or where one of them was inert.
🔴 The most consequential: an upgrade deleted the rules a project had accumulated,
while PROFILE_solo.md was actively telling users to accumulate them.
🔴 升級會刪掉專案自己累積的規則,而說明書正在鼓勵使用者去累積。
Added / 新增
- 🔴
my/— everything in it belongs to the project and is ⛔ never touched by an upgrade:
MY_RULES.md(project rulesP-xx, with the framework's rules copied verbatim into §1),
MY_INCIDENTS.md(moved fromincidents/, now also holds the project's own failure
families專-①), andtools/for scripts the project writes itself.
⚠️ tools/exists because a self-written script placed inscripts/is deleted by the
next upgrade — observed in a live downstream project. - 🔴
scripts/harness/sensor_my_rules.py— checks thatmy/MY_RULES.mdcovers every
framework rule (RULE_MISSING_IN_MY/RULE_TEXT_DRIFT/OVERRIDE_WITHOUT_REASON). scripts/harness/tool_sync_my_rules.py— copies newly added framework rules in verbatim.- 🔴
governance_config.jsonnow ships at the project root with the permission settings.
⚠️ It is on the upgrade tool's never-replace list — the settings finally live somewhere
an upgrade cannot erase. governance/CLAIM_LEDGER_SPEC.md,governance/CONJECTURE_LEDGER_SPEC.md— the ledger
specifications, moved out ofledgers/.handoffs/now ships.⚠️ It never did, while the whole handoff ritual pointed at it.- Constitution §6.4 — "a file may have exactly one owner", with the criterion for
deciding which of the three treatments a document gets. - 🔴
my/MY_INDEX.md— an index of everything in the project that is yours, generated by
scripts/harness/tool_my_index.pyand watched bysensor_my_index.py; the descriptions
live inmy/MY_INDEX_notes.jsonand are AI-maintained.
⚠️ Why: a project that adopted v1.3.0 stopped maintaining its own file index — its
file_index.mdholds not one research-related entry. 🔴file_index.mdbegan as a
predecessor project's table for research documents; the contents became the framework's own
and the name did not change, so the framework displaced a mechanism that already existed.
⛔ The criterion is "everything the framework does not own", never a list of what to
include — a list of what to include is a whitelist (R-21).
Fixed / 修正
- 🔴 An upgrade deleted a project's accumulated rules (
governance/is replaced
wholesale).⚠️ Verified by experiment, ⛔ not by reading the code. - 🔴
t0_docswas folded intodeniedin code, so no configuration could turn T0
protection off — while the config comment said the opposite. T0 is now listed in the
denydefault instead. ✅ "Cleardenyand you have full authorisation" is true for the
first time. - 🔴 The permission check was skipped entirely when
write_scopeswas empty — and
PROFILE_solo.mdtells solo projects to leave it empty. Sodenyhad never been in
effect in a solo project. Now a solo project gets a WARN listing the files. - 🔴 An unrecognised key in
governance_config.jsonwas silently absorbed. Now a FAIL
that names the closest valid key. - 🔴 Framework updates to the ledger specifications could never reach an existing project
(ledgers/is on the never-replace list). The specs moved togovernance/. - Two dangling citations to
PROFILE_multi_agent.md§4.3, a section that no longer
exists, plus "four attack points" where there are five.⚠️ The sensor had been reporting
this every round and nobody read the output. attribution_globs/artifact_globspointed atoutputs/andreports/, two
directories that never existed.⚠️ They are ⛔ not being created — where research output
lands is defined in v1.5.0.MODEL_IDENTITY.md§3.4 now states the resulting gap.
Documentation / 說明
- 🔴 Both figures redrawn for v1.4.1, in both editions:
my/replacesincidents/,
the ledger specs appear on the framework side,handoffs/andgovernance_config.json
are shown as shipped, and an arrow now shows what an upgrade does to your rules. - 🔴 The figures are now produced by a generator, ⛔ no longer hand-edited SVG.
⚠️ Every box width is computed from its own text, so the generator fails loudly instead of
producing an overflowing box — the v1.3.0 defect where one pill width was copied
verbatim between editions and the English line was 306px wide cannot recur by construction.
⛔ The generator is a maintainer tool and does not ship (decision 42). - All three READMEs: the file list is now split into "yours" and "the framework's",
with the reason (§6.4) stated where the reader meets it.
getBBox(): 0 overflows and 0 overlaps across all four figures.
🔴 That measurement found two defects the eye did not: a 2px text collision present only in
the Chinese edition, and a blind spot in the measurement itself — a band's left column could
run into the boxes beside it without being flagged, because the band rectangle was too wide to
count as "the containing box". The criterion moved into the generator.
Self-tests / 自測
57 → 78 paired samples. Both editions pass. Sensors 7 → 9.
Fixed after the principal ran it on their own machine / 主持人實跑後修正
- 🔴
sensor_scope_and_t0.pycrashed withAttributeErrorwhengitreturned exit 0
withstdoutset toNone.⚠️ The code path had been there since v1.0.0 and had never
once run, because the old code skipped the whole block whenwrite_scopeswas empty and
PROFILE_solo.mdtells solo projects to leave it empty. Makingdenyeffective did not
cause the crash; it revealed it. 🔴 Cause, established by a diagnostic run on that machine (⛔ not guessed):
withtext=Trueand noencoding, Python decodes the child's output with the locale
encoding —cp950on Traditional-Chinese Windows — and git prints paths in UTF-8.
The decode fails insidesubprocess's reader thread, that thread dies, the exception
never propagates, andcommunicate()returnsNone. ⛔ The standard library turned an
error into a silent empty value. - 🔴 The same fix already existed in two files in the same folder and had never been carried
to the third:checkpoint.pyandreview_changes.pyboth state
encoding="utf-8", errors="replace".⚠️ _common._force_utf8()fixes what the harness
prints, ⛔ not what it reads — a true fix whose scope did not cover the other channel
(R-34). Its docstring now says what it does not cover. - New static self-test: any
subprocess.runin the harness that decodes without naming
anencodingis a FAIL, named asfile:line. - 🔴
docs/and the six launcher buttons were never on the upgrade tool's replaceable list,
so the seven figure-layout fixes shipped in v1.3.0 reach no existing project. They are on
the list now.⚠️ This was caught bytool_my_index.pyon its first run, because they
appeared in the list of "things the framework does not own".
⛔.gitignoreand.gitattributesare deliberately left off — mixed ownership, per §6.4. - 🔴 A project sitting in a subdirectory of a repository no longer refuses to report.
The report is narrowed to that subtree, with paths outside it dropped.⚠️ The framework's
own repository has that shape, and so does any project dropped into an existing notes repo —
the old behaviour was a light that is always on (R-19).
⛔ This release does not claim / 本版不宣稱
- ⛔ The permission model is not rebuilt.
⚠️ Seven separate mechanisms still express
permission;⚠️ this release fixes the ones that were false or inert. The single table is
v1.6.0. - ⛔ Research-side document management does not exist yet.
⚠️ research/is v1.5.0;
the main text still has nothing watching its author field. - ⛔
sensor_my_rules.pydoes not judge the quality of aP-xx, nor whether an
override's reason is sound — only that the line has text.
[1.4.0] — 2026-08-26
🔴 ⛔ 1.4.0 was never released on its own: it carries no git tag.
It was prepared, then folded into 1.4.1 and pushed as one release.
⚠️ This note exists because a changelog entry with no tag behind it is
"the document says it shipped" with nothing under it.🔴 ⛔ 1.4.0 沒有單獨發布,也沒有 tag。 它備妥之後併入 1.4.1 一起推。
🔴 The change / 這一版做的事
Three start-up prompts for the multi-agent setup, a prior-art template that actually
works out of the box, and scratch/ finally explained.
多角色情境現在有三份可以直接貼的開工指令。
Added / 新增
- 🔴
prompts/START_governance_AI.md,START_research_AI.md,START_audit_AI.md
(START_治理AI.md/START_研究AI.md/START_審計AI.mdin the Chinese edition).
⚠️ PROFILE_multi_agent.mdtold you to set up three roles and to "put this in the
governance role's standing instructions" — ⛔ while no such document existed anywhere.
Each file is self-contained: model declaration, write scope, the tools that already exist,
verification tags, the academic bottom lines, decision rights, what to do when an
instruction conflicts with a rule, the closing packet, and how that particular role helps
the framework grow.
⚠️ A solo setup does not need these —INITIALIZE_PROMPT.mdstill covers it. - A title-accuracy clause in
_COMMON_BLOCKS.mdblock A.⚠️ Found because an assembled
prior-art prompt still failed the deep-research check — the clause was simply not in the
parts bin.
Changed / 變更
- 🔴
TEMPLATE_prior_art.txtnow ships assembled. It used to be 24 lines, six of them
<<<paste block X>>>, ⛔ ...
1.3.0 — 2026-08-26
[1.3.0] — 2026-08-26
🔴 The change / 這一版的主要變更
Short-form section citations are now checked. sensor_governance_text.py resolved only the
long `<file>.md` §N form, while the framework itself writes "constitution §N" in 68 places
(Chinese) and 58 (English) — and its scan never reached scripts/**/*.py at all.
Three dangling citations had been living there, found by hand at v1.2.0 release time.
短式章節引用現在查得到了。
Added / 新增
- 🔴
corpus/andcorpus_md/now ship with the framework, each with a short note inside
saying what belongs there.corpus/also contains a blankBIBLIOGRAPHY.docx—
export your references from Zotero or EndNote into it, and from then on every citation in
the project follows that file, ⛔ not what the AI says.
⚠️ Why: a model will get DOIs, page numbers and years wrong, and a wrong one reads
exactly like a right one. A bibliography you maintain yourself is something to check against. CORPUS_EMPTY(WARN) — the extraction folder exists but holds nothing yet.
⛔ Not the same as "could not check" (see Fixed).- Config key
section_ref_aliases—{anchor word: target file}. ⛔ Not hard-coded:
R-21forbids a whitelist as the definition of scan scope, and a downstream project's short
name for its constitution will not be this one's. Absent key → the check simply does not run
for that project, ⛔ and the statistic says so. ALIAS_TARGET_MISSING(INCOMPLETE) — an anchor is configured but its target file is not in
the tree. ⛔ Not a silent skip (R-33).- A "section citations checked" statistic. ⛔ Silence is not a pass.
- Four paired fixtures, ⛔ two of them the "must not false-alarm" half:
secref_alias_bad/secref_alias_ok/secref_py(the citation lives in a.pyheader) /
secref_fence. Self-tests 50 → 54.
Changed / 變更
- The section-citation check now runs over
code_globs + launcher_globs + governance_globs—
the same scope assensor_reference_integrity.⚠️ That sensor exists because.pyheaders
were never scanned; ⛔ it fixed file references and not section references.
The same hole was half-fixed, and the half that was fixed made it look closed.
Fixed / 修正
- Three dangling constitution citations — already fixed in the v1.2.0 release commit;
this version is what stops the next one. - 🔴 A heading inside a fenced block was counted as a heading. The first run after the scope
widened reportedHANDOFF.mdas having two## 3.sections; one was a line inside the fenced
template.⚠️ The defect was already in the long-form check and had simply never been
reached. ⛔ Fixed by stripping fenced blocks, not by an exemption list (R-20/R-21).
Stated cost: a real heading inside a fenced block becomes invisible. ⛔ Nobody writes that. - 🔴 "Which folders does an upgrade touch" is now a measured fact, not a sentence in a guide.
⚠️ The behaviour was already right — the tool recognises five framework folders and four
framework files and refuses every other target, so a folder a user invented was never a
candidate. ⛔ The documentation was what read backwards: it described protection as a
list of protected items, and a list reads as "only these are safe".
Rewritten everywhere to state the guarantee the other way round, and
upgrade_case()in the self-test now proves it: a folder the tool has never heard of is
refused and left byte-identical, even when the upgrade source contains one by the same
name. ⛔ The "your data" list is documented as what it is — a better error message, not
the defence. Self-tests 56 → 57. - Constitution §6.2 gained a clause on folders the user creates, saying plainly that
⛔ no registration is required, and naming the two mechanical reasons they are safe. profiles/PROFILE_external_tools.mdcorrected: it saidexternal/was "not on the
protected list", which⚠️ was true and read as a warning about something that was never at
risk.- 🔴 A brand-new project reported INCOMPLETE on its very first run. Shipping an empty
corpus_md/tripped a check that knew only two states — no directory and directory
without a manifest. It had no third state for "a directory with nothing in it yet".
⚠️ With nothing to protect, there is no "could not protect it" — and ⛔ a first run
that cries wolf is what teaches people to ignore the output.
⛔ Fixed structurally, not with an exemption: the criterion now keys on whether
extractions exist. Self-tests 54 → 56. - 🔴 The figures overflowed and collided — in both editions. The divider pill in
fig1_architecture.svgcarriedwidth="260", identical in both files: the Chinese
sentence fits, the English one is 306px wide, so the dashed line ran straight through the
text.⚠️ The same shape as the sentence-length constant inSENSOR_CHANGELOGpre-history
#2 — a constant tuned for Chinese, ported unchanged — ⛔ this time in SVG coordinates.
Seven overflows and collisions were found and fixed across the four figures.
⚠️ Found by rendering each SVG and reading every element'sgetBBox(), ⛔ not by eye:
the Chinese constitution box was 1.5px inside its padding — invisible to a reader,
and still wrong. - Drifting counts removed from the figures (
7 sensors,8 failure families,
policy/ × 4,profiles/ × 4,three templates).⚠️ All five were correct at the time.
🔴 The README deliberately carries no counts (R-16) while the figures did — and a figure
is read as authority more often than the README is.R-01–R-35is kept: that is an id
range, ⛔ not a count. Exit codes and "three buttons" are kept: design constants.
Changed: the three guides / 三份說明文件
🔴 README.md at the root, and README.md + SETUP.md in both editions, were rewritten for
readers with no programming background.
- ⛔
git cloneis gone. Getting started is now: Download ZIP → unzip → copy the folder
for your language → rename it to your project.⚠️ Anyone who prefersgit clonealready
knows how, and did not need the instruction. - A new section on pointing your AI at the folder, with the actual steps for
Claude (Cowork), Gemini (Antigravity) and ChatGPT (Projects).
⚠️ Stated plainly: a ChatGPT project has a file limit and cannot see your folder —
profiles/PROFILE_chat_only.mdis written for that case. - The root README is now written in English throughout (the two opening lines stay in
Chinese), because both editions are linked at the top.⚠️ Two languages interleaved in one
document made it harder to read in either. - Plainer wording, and notes written for the AI rather than the reader were removed.
These are documents for people. - 🔴 A section on the framework growing with you, in all three READMEs:
there is no perfect framework — only one that gets better as you use it.
You say "log that" when something goes wrong; the AI finds the repeating pattern;
⛔ you decide whether it becomes a rule. After a while your copy stops looking like anyone
else's, and that is the point. profiles/rewritten, all four, in both editions. Each now says how the framework keeps
improving in that particular setup —⚠️ including the chat-only one, where the growth
goes into the text you paste at the start of every conversation.
Arguments are self-contained rather than pointing at rule numbers, and the file lists match
the v1.3.0 layout (corpus/,corpus_md/,incidents/).- ChatGPT is now documented as Work mode in the desktop app, which links a live local
folder and is the equivalent of the other two.⚠️ Web ChatGPT is described separately,
since it holds uploaded copies with a file limit.
Claude Code and Codex are named as working too — ⛔ without steps, because they have
not been tested here, and with the warning that a coding agent will not pause for the
snapshot habit on your behalf.
⚠️ Upgrade notes / 升級注意
- A project that was green on v1.2.0 can go WARN on v1.3.0. That is the point.
Setsection_ref_aliasesto your own short name, or leave it unset and the check does not run. - ⛔ No rule IDs changed.
R-01–R-35are unchanged.
⛔ What this release does not claim / 這一版不宣稱什麼
- ⛔ It does not claim every citation form is now checked. One anchor is configured.
R-35: that is the result of taking stock —⚠️ and nobody has taken stock of whether a
third form exists. - ⛔ It does not claim a citation points at the right content — only that the section exists
and is unique. - ⛔ Nothing compares the two editions. Still true, and still done by hand.
- ⛔ Nothing checks the figures. No sensor reads
.svg. The layout defects above were
reported by a human and measured with a throwaway script that is ⛔ deliberately not
shipped — a known and accepted gap, not an overlooked one.
1.2.0 — 2026-08-26
[1.2.0] — 2026-08-26
🔴 The headline changes / 這一版最重要的三件事
- One file to fill in. Everything a user must author now lives in
PROJECT.mdat the root;
every other governance document is AI-maintained. 使用者只需要填一個檔案。 - Buttons, on both platforms.
snapshot/review changes/check updateship as
.batand.command; the logic behind them lived in 8 near-duplicate files
(four batch scripts of 203–246 lines, plus four shell scripts) and now lives in 2 Python
files per edition — the six launchers are 40–43-line shells. macOS is supported for the
first time. 兩個平台都有按鈕。 - Folder-level upgrades. Framework folders can be replaced wholesale from GitHub while
PROJECT.md, ledgers, corpus, handoffs andincidents/are never touched.
框架可以整包升級,你的資料不會被碰。
Theme: the two editions are now actually equivalent, and the harness now fails loudly
instead of quietly passing.
主題:兩個版本這次真的對等了;檢查工具不再「靜靜地通過」,而是會出聲。
⚠️ Why this release exists / 這個版本為什麼存在
v1.0.0 shipped two editions described as "independent and equivalent". They were not.
The English edition was missing one sensor outright and three checks inside another; the two
prompt sensors were two different programs; thresholds differed between editions with the
divergence registered nowhere. A weaker sensor reads as a cleaner document — which is the
failure this release is mostly about.
v1.0.0 宣稱兩個版本「各自獨立且對等」。它們並不對等。
英文版整支少了一個感測器,另一支少了三項檢查;兩版的 prompt 感測器根本是兩支不同的程式;
門檻不一樣而且沒有登記在任何地方。一支較弱的感測器,會被讀成一份較乾淨的文件——
這一版修的主要就是這件事。
Added / 新增
sensor_reference_integrity.py— whether a referenced file actually exists, including
.py/.shfile headers, which had never been scanned.
被引用的檔案存不存在(含從未被掃過的.py/.sh檔頭)。sensor_clause_sync.py— whether a clause list copied into a prompt still matches its
home. Exists becauseR-24(prompts must be self-contained) and constitution §3.2 (one home
per rule) exclude each other, and the product of that exclusion is silent drift.
被抄到 prompt 裡的條款清單是否仍與定義處相同。tool_extract_compare.py— strict / loose / gap columns, so "normalisation does not cover
this" and "the extraction is poor" stop looking the same.R-33⛔ "nothing to do" must not be the default branch after a failed operation.R-34capability boundaries are read off the tool list, ⛔ not asserted from memory.R-35"none" must be the result of taking stock, ⛔ never an omission. Raised to a rule
because the same sentence appeared verbatim in four places across two documents, each
with a complete context of its own — one higher-order principle instanced in four settings.
All four sites now cite it. ⛔ Not reworded to dodge the sensor.
「無」必須是盤點的結果——同一句話原本逐字散在四處,現在四處都引用R-35。- Constitution §4.1.1 — an exit-code disposition table (0 / 1 / 2).
Audit_Protocol.md§6 — cross-family is not independence (with verified source anchors).Claim_Ledger.md§1.1 rule 5 — ⛔ an anchor must not span a page break.Conjecture_Ledger.md§0.2 — an optional "why I could not fill this" field, so a
deliberate blank stops looking like a forgotten one.- A new failure family: "text about a defect, and the defect itself, are indistinguishable to
string matching" — with two forms running in opposite directions and taking opposite
dispositions: mentioning it commits it (reword into description, add no exemption), and
mentioning it is mistaken for committing it (quotation detection, ⛔ not an exemption list).
Tagged[framework's own], a new provenance tag: it happened while maintaining this
framework, not to somebody else. - Two cross-cutting axes named above the family table. Axis one: two states carrying very
different information look identical on screen (four families sit on it). Axis two: one fact
has two copies and only one gets updated. ⛔ The families on an axis are deliberately not
merged — a family covering five families recognises no shape at all. - Constitution §6.2 defines the operational directories (
scratch/,archive/,
_to_delete/). They appeared in.gitignore, inexcluded_dirs, in the constitution and in
the audit protocol — four places using them, none defining them, the same shape "output
area" was in before §6.1. Nothing inscratch/may be cited: it is not version-controlled,
so a citation into it reads exactly like a well-founded one and resolves to nothing. HANDOFF.md§3.3: section 4 must carry the raw output ofgit diff --stat. It is the one
part of a handoff packet that can become a mechanical fact at zero cost. What it blocks is
not lying but under-reporting — a file list written from memory comes up short, and the
missing entries look exactly like files that were never touched.- A root
CHANGELOG.md— this file.
Changed / 變更
-
Failure families are now cited by name, never by number, across every document and
source comment. The number is the table's ordinal; the name is the identifier. -
The "fixed one layer, missed another" family gained two forms — the second copy living on
a carrier that evaporates (a conversation, screen output, memory), and a number written into
prose. The "index as authority" family gained a third variant: treating "this looks like a
known family" as "this is that family" — 🔴 a failure the family table itself induces. -
Predicted failure families moved to their own
P1–P6namespace. They used to share one
run of circled numbers with families that had actually occurred, so the next number for a new
occurred family was ⑭ — and if a predicted family were ever removed or promoted, its number
would fall free and be reused, silently retargeting every citation that used it.
預測家族改用獨立的P1~P6命名空間——兩套命名空間結構性地不可能相撞。 -
R-10no longer cites an incident-log case. A downstream project's incident log is its
own; inserting a case ahead of the cited one shifts the numbering while the citation still
resolves. A citation that silently retargets is worse than one that dangles, because it
stays green. The rule now carries the mechanism and the reason; the log carries the
verbatim evidence. -
Both editions brought into equivalence. The English edition gained
sensor_model_attribution.py(absent entirely), three checks inside
sensor_conjecture_ledger.py, and English text for three changelog sections that had been
left in Chinese. -
sensor_model_attribution.pyrewritten. Hard-coded filenames 25 → 0; dangling
references 9 → 0. The old whitelist existed only to suppress alarms a wrong scan scope
had created. -
sensor_prompt_self_contained.pysplit into two layers — self-containment always;
the deep-research clause table only under--profile deep-research. Previously all three
templates the framework ships came out FAIL, andprompts/README.mdhad written the
excuse for it. -
tool_pdf_to_md.py— PyMuPDF primary with a pypdf fallback, and the backend is
recorded. Degrading is fine; degrading silently is not. -
ai_checkpoint.sh— role + model + topic mandatory, UTC timestamps, sweeps every stale
git lock, falls back tomvwhere deletion is denied, and checksgit add's exit status. -
framework_config.py—load()now takes the scanned root, so--rootno longer reads
another project's configuration in silence. -
Self-tests: 12 → 50, over 43 paired fixtures.
-
Both T0 documents rewritten and trimmed, and one contradiction between them removed.
The six academic bottom lines now have one home,AGENTS.md§3;RULES.md§A carries
R-01–R-04as four one-line pointers naming the item each maps to.
⛔ The four rows are deliberately not collapsed into the rangeR-01–R-04: the mapping
is not contiguous (R-03→ item 5,R-04→ item 6), and a range would state something true
while losing which rule is which. Items 3 and 4 carry noR-xx— that is the result of
taking stock, ⛔ not an omission, and has been so since v1.0.0.
Fixed / 修正
- 🔴 INCOMPLETE could be swallowed by a later FAIL. Exit codes
[2, 1]aggregated to1,
so "a sensor never managed to check" disappeared behind a fixable failure.
一支感測器根本沒查成,會被後面一支 FAIL 蓋掉。 - 🔴 "Must not false-alarm" tests were checking nothing. WARN-level findings do not change
the exit code, so any number of WARN-level false alarms printed ✅.
「不得誤報」那一半的測試,對任意多筆 WARN 級誤報一律印 ✅。 - 🔴 A glob that matches nothing is not automatically fine. When the directory holds files
of that extension and the glob still sees none, that is coverage collapse → INCOMPLETE. - 🔴
sensor_self_certification.pyreturned PASS on a real audit report containing six
phrases its own protocol bans. sensor_governance_text.py— a character-count threshold is systematically weaker for
Chinese; the sentence splitter knew only。and newlines, so the English edition was
comparing whole lines only.tool_pdf_to_md.pycreated an empty output directory before checking whether there were
any PDFs — flipping a clean harness from 0 to 2, invisibly, because git does not track
empty directories.- Numerous dangling file and section references across both editions, including ones the
framework itself promised and did not ship. - 🔴
policy/MODEL_IDENTITY.md: the English edition was a 62-line abridgement of a 201-line
document. Missing: the platform-mechanism comparison, every rule §3.1–§3.7, and the
mechanical-defence table — including the two sectionssensor_model_attribution.pynames as
its own rule source.⚠️ Both editions' sensors ran green throughout: nothing in the...
v1.0.0 — first public release
First public release. Two independent, equivalent editions (English / 繁體中文).
What it does: makes three questions answerable at any point in a research project —
which page a sentence rests on, what would refute an idea, and what the AI just changed.
What it does not do: it does not guarantee your research is correct. It guarantees
that when it is wrong, the error leaves a trace.
- 5 sensors, 12 paired seeded-defect self-tests, cross-platform Python runners
- 32 permanent-ID working rules; 7 failure families
- 4 usage profiles: solo / multi-agent / chat-only / external tools
Distilled from two research projects in actual use.
Every sensor and hard rule carries the case that triggered it.