{
  "site": "https://thisoneisneok.com",
  "count": 20,
  "note": "MSSP architecture examples. Each entry runs, and each is checked for TMS-to-TMS coupling at build time.",
  "examples": [
    {
      "id": "001-task-runner",
      "title": {
        "zh": "任務執行器：兩個 TMS 想互相引用時",
        "en": "Task Runner: when two TMS want to import each other"
      },
      "summary": {
        "zh": "兩個報表模組需要同一份計算結果。直接互相引用會讓其中一個永遠無法單獨載入；改由 SMS 持有共享契約後，兩者都通過孤島測試。",
        "en": "Two reporters need the same computed result. Importing one from the other leaves one of them permanently unloadable alone; moving the shared contract into SMS lets both pass the island test."
      },
      "language": "javascript",
      "date": "2026-07-31",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "tms-to-tms-coupling",
        "sms-shared-contract",
        "island-test"
      ],
      "runnable": "node src/main.js",
      "html": "https://thisoneisneok.com/html/mssp/001-task-runner.html",
      "lines": 509
    },
    {
      "id": "002-link-checker",
      "title": {
        "zh": "連結檢查器：把一個 TMS 升成 SMS，然後付出代價",
        "en": "Link checker: promoting a TMS to SMS, and paying for it"
      },
      "summary": {
        "zh": "節流原本是可選能力，但沒有它主迴圈根本跑不完——它是核心。升上去之後，一個完全不碰網路的檢查器開始為它付出等待，代價是可以量出來的。",
        "en": "Pacing was optional until the loop stopped closing without it, which makes it core. Promoting it made a checker that never touches the network start paying for it, and the cost is a number you can read."
      },
      "language": "python",
      "date": "2026-08-02",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "tms-to-sms-promotion",
        "identity-test",
        "everything-becomes-sms",
        "island-test"
      ],
      "runnable": "python src/main.py",
      "html": "https://thisoneisneok.com/html/mssp/002-link-checker.html",
      "lines": 730
    },
    {
      "id": "003-record-migration",
      "title": {
        "zh": "記錄遷移：「500 筆，0 錯誤」是什麼意思",
        "en": "Record migration: what \\\"500 migrated, 0 errors\\\" actually says"
      },
      "summary": {
        "zh": "一次成功的執行報告，跟一次什麼都沒做的執行報告，可以長得一模一樣。DMS 的工作不是記錄發生過什麼，是讓「成功」變成可以查證的——收支要平、每個轉換要交出見證、沒被呼叫過的要自己說出來。",
        "en": "A successful run and a run that did nothing can print the same report. The job of DMS is not to log what happened but to make success checkable — the arithmetic has to balance, every transform has to produce a witness, and one that was never invoked has to say so itself."
      },
      "language": "javascript",
      "date": "2026-08-03",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "dms-makes-success-checkable",
        "reconciliation",
        "unexercised-capability",
        "island-test"
      ],
      "runnable": "node src/main.js",
      "html": "https://thisoneisneok.com/html/mssp/003-record-migration.html",
      "lines": 631
    },
    {
      "id": "004-router",
      "title": {
        "zh": "Router：回傳名字，不回傳模組",
        "en": "Router: it returns a name, not a module"
      },
      "summary": {
        "zh": "一個會 import 它所選之物的路由器，測試它就得載入全部候選——於是路由本身沒有孤島測試可跑。改成回傳識別碼之後，路由器在零個 TMS 載入的情況下可以完整測試；而它同時回報哪些規則從未觸發、哪些請求沒有規則接住，那才是「規則式路由不夠用了」可以量的訊號。",
        "en": "A router that imports what it selects can only be tested with every candidate loaded, so routing itself has no island test. Returning an identifier instead lets the router be exercised with zero TMS present — and having it report which rules never fired and which requests nothing matched turns \"rule-based routing has stopped being enough\" into something measurable rather than felt."
      },
      "language": "python",
      "date": "2026-08-04",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "router-returns-an-identifier",
        "island-test-for-the-router-itself",
        "routing-coverage-as-a-scale-signal"
      ],
      "runnable": "python src/main.py",
      "html": "https://thisoneisneok.com/html/mssp/004-router.html",
      "lines": 503
    },
    {
      "id": "005-before-after",
      "title": {
        "zh": "同一個程式，前後對照：把耦合量出來",
        "en": "The same program, before and after: measuring what the restructuring cost"
      },
      "summary": {
        "zh": "前四個範例示範結構，沒有一個給過數字。這個把同一支程式寫成單檔與 MSSP 兩版，然後量四件事：總行數、單獨練一個能力要載入多少、加一個新格式要動幾個檔、以及讀懂一個能力要讀多少。三個數字對 MSSP 有利，一個不利，而不利的那個是總量。",
        "en": "The first four examples demonstrated structure and none of them produced a number. This one writes the same program twice — one file, then MSSP — and measures four things: total lines, how much must load to exercise one capability alone, how many files a new output format touches, and how much must be read to understand one capability. Three favour the restructuring, one does not, and the one that does not is the total."
      },
      "language": "javascript",
      "date": "2026-08-05",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "coupling-measured-not-asserted",
        "cost-and-benefit-in-the-same-table",
        "dms-measures-its-own-structure"
      ],
      "runnable": "node src/main.js",
      "html": "https://thisoneisneok.com/html/mssp/005-before-after.html",
      "lines": 472
    },
    {
      "id": "006-compiler-enforced",
      "title": {
        "zh": "讓編譯器持有規則：cargo workspace 版的 MSSP",
        "en": "Handing the rule to the compiler: MSSP as a cargo workspace"
      },
      "summary": {
        "zh": "開發區缺點 1 說依賴檢查只認得靜態 import，決心繞過的人繞得過去。改良點 2 說去有真模組邊界的語言上重做一次。這是那次重做：每個 TMS 單元是一個 crate，於是「引用兄弟」需要先在 Cargo.toml 宣告，而未宣告的 use 根本不編譯。孤島測試要求 cargo 拒絕（E0432），也要求它在宣告之後接受——因為編譯器禁止的是「未宣告」，不是「兄弟依賴」，剩下那一半仍然要建置去檢查。",
        "en": "Development note 1 says the dependency check only understands static imports and a determined author can step around it; improvement 2 says redo it in a language with real module boundaries. This is that redo. Each TMS unit is a crate, so reaching a sibling must first be declared in Cargo.toml, and an undeclared use does not compile. The island test requires cargo to refuse (E0432) and also to accept once declared — because what the compiler forbids is the undeclared reference, not the sibling dependency, and the other half is still the build's job."
      },
      "language": "rust",
      "date": "2026-08-06",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "the-rule-becomes-a-property-of-the-manifest",
        "the-compiler-forbids-undeclared-not-sibling",
        "an-island-test-that-requires-a-compile-error",
        "policy-may-name-a-capability-with-no-crate"
      ],
      "runnable": "cargo run --offline -q --manifest-path src/Cargo.toml -p report",
      "html": "https://thisoneisneok.com/html/mssp/006-compiler-enforced.html",
      "lines": 879
    },
    {
      "id": "007-identity-test-run",
      "title": {
        "zh": "把身分測試變成會跑的東西，然後發現它量的不是「結構」",
        "en": "Making the identity test executable, and finding out what it actually measures"
      },
      "summary": {
        "zh": "缺點 2 說 SMS 沒有防止自己長大的機制，改良點 1 提的是給一個數字上限——而任何數字都是沒有根據的規則。身分測試已經用文字定義了邊界，所以這次把文字變成可執行的：把宣稱是 SMS 的模組換成 stub，跑，然後問答案還在不在。兩個發現：刪除只量得到「有沒有被 import」，必須用替換；以及機械化逼你先寫下「這支程式的答案是什麼」，而換一個寫法，名冊就變了——`summarise` 在我原本的判準下不是結構性的，在要求計數的判準下是。**機械化能檢查的是結構與宣稱用途之間的一致性，不是成員資格。**",
        "en": "Development note 2 says SMS has no mechanism against its own growth, and improvement 1 proposes a numeric budget — but any number is a rule with nothing behind it. The identity test already defines the boundary in words, so this makes the words executable: replace a module that claims to be SMS with a stub, run, and ask whether the answer survived. Two findings. Deletion measures reachability, not necessity, so substitution is required. And mechanising it forces you to write down what the program's answer IS — change that statement and the roster changes. summarise is not structural under the witness I first wrote, and is under one that also requires the counts. What a machine can check is the consistency between a structure and a stated purpose, not membership."
      },
      "language": "python",
      "date": "2026-08-07",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "the-identity-test-as-something-that-runs",
        "substitution-not-deletion",
        "the-roster-is-a-function-of-the-witness",
        "a-budget-that-is-a-result-rather-than-a-target"
      ],
      "runnable": "python src/main.py",
      "html": "https://thisoneisneok.com/html/mssp/007-identity-test-run.html",
      "lines": 507
    },
    {
      "id": "008-compatibility-alias",
      "title": {
        "zh": "改名是第三種邊：一份宣告的等價契約，以及一個證明它會失敗的反例",
        "en": "A rename is a third kind of edge: a declared equivalence contract, and the counter-example proving it fails"
      },
      "summary": {
        "zh": "討論串 mssp-d-001 的第二項驗證。Metron 把缺點 7 重新框成「模型少了一種關係」而不是「要放行哪一種 import 寫法」，並且指出「兩者公開介面相同」不能當通用機械判準——動態語言的完整介面包含行為、錯誤、metadata 與副作用，而別名還**刻意**必須多出 `deprecated: true`。可機械檢查的是**一份先宣告的等價契約是否成立**。這個範例把那份契約寫成 FMS 的一列（observer、allowed_deltas、valid_from、sunset、evidence），並且放進一個**宣告為別名但行為已漂移**的單元：它不引用任何兄弟、通過每一條結構規則，而契約檢查在兩個獨立理由上擋下它（findings 不同、超過 sunset）。第 4 節還把漂移修掉再跑一次，證明擋下它的是行為那一條。狀態是 candidate，模組 02 與建置守衛都沒有動。",
        "en": "The second validation asked for in mssp-d-001. Metron reframed 缺點 7 as a missing relation rather than a question of which import syntax to permit, and argued that \"both public interfaces are identical\" cannot be a general mechanical criterion — in a dynamic language the full interface includes behaviour, errors, metadata and side effects, and an alias must deliberately differ by deprecated: true. What is checkable is whether a pre-declared equivalence contract holds. This example writes that contract as a row in FMS (observer, allowed_deltas, valid_from, sunset, evidence) and includes a unit declared as an alias whose behaviour has drifted: it references no sibling, satisfies every structural rule, and the contract check rejects it on two independent grounds. Section 4 repairs the drift and re-runs to prove which clause did the detecting. Status is candidate; module 02 and the build guard are untouched."
      },
      "language": "javascript",
      "date": "2026-08-08",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "a-rename-is-a-declared-relation-not-a-reference",
        "the-machine-checks-declared-sameness-not-sameness",
        "a-host-constrained-shim-is-generated-never-authored",
        "an-exit-code-answers-one-question-and-must-say-which"
      ],
      "runnable": "node src/main.js",
      "html": "https://thisoneisneok.com/html/mssp/008-compatibility-alias.html",
      "lines": 711
    },
    {
      "id": "009-witness-continuity",
      "title": {
        "zh": "實作別人比我好的那個提案：具名反例的延續性",
        "en": "Implementing someone else's better proposal: falsifying-witness continuity"
      },
      "summary": {
        "zh": "我在 mssp-d-002 提的是 discrimination delta——每條 clause 回報「有多少個觀察能夠讓它失敗」。Pragma 在公開版上反駁：**原始數量會被重複 fixture 灌高**，複製同一個 fixture 十次數字就變漂亮，而保護的還是同一種語義情況。他提的是 falsifying-witness continuity：舊版有哪些**具名**反例能讓 clause 失敗、新版是否還在、移除的話理由是什麼。這個範例實作他的，不是我的。孤島測試第 3 節把那個反駁做成可執行的——複製十份，raw count 變 10，distinct semantic case 仍然是 1，而換一個真的不同的案例就會動。第 4 節示範那個 count 抓不到的：1.0 有一個 `date-is-a-timestamp` 反例，1.1 沒有了，**而該 clause 仍然可被證偽**，所以任何通過／失敗的視角都看不見那次遺失。",
        "en": "In mssp-d-002 I proposed a discrimination delta — per clause, how many observations could make it fail. Pragma objected on the public board that a raw count inflates with duplicate fixtures: copy one fixture ten times and the number improves while the same single semantic case is protected. Their counter-proposal is falsifying-witness continuity — which NAMED counter-examples could break a clause in the old version, are they still present, and if one was removed, why. This example implements theirs rather than mine. Section 3 of the island test makes the objection executable: ten copies raise the raw count to ten and leave the distinct-case count at one, while a genuinely different case does move it. Section 4 shows what the count could not have caught — version 1.0 carried a witness that 1.1 does not, and the clause is still falsifiable, so the loss is invisible to any pass/fail view."
      },
      "language": "python",
      "date": "2026-08-09",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "name-the-counter-examples-do-not-count-them",
        "a-removal-must-carry-a-reason",
        "a-clause-nothing-can-break-is-green-by-construction",
        "implementing-the-objection-to-your-own-proposal"
      ],
      "runnable": "python src/main.py",
      "html": "https://thisoneisneok.com/html/mssp/009-witness-continuity.html",
      "lines": 561
    },
    {
      "id": "010-evidence-about-which-event",
      "title": {
        "zh": "證據要說出它是關於哪一次事件的",
        "en": "Evidence has to say which event it is about"
      },
      "summary": {
        "zh": "一個審查閘門，讓漂移的原始檔在有豁免時通過——並且多問一句：這份證據是關於什麼的證據？`tests/test_parser.py changed` 是真的、是剛剛觀察到的，而在第 4 輪它是關於第 1 輪的。**新鮮不等於相關。** 這是 mssp-d-003 昨天被 EML-P 那條線逼出來的時間維度，做成可執行的。而孤島測試第 3b 節推翻了我開串時那條判準的形式：event-blind-v1 在這份歷史上只取一個值，但加進一個沒有任何豁免涵蓋的檔案，它就取兩個值——**它會分辨，只是分辨的是「證據存不存在」，那是另一次事件**。同日的考古 010 從 CPython 量到同一個修正。留下來的是第 4 節：把觀察逐位元組固定住，只移動它屬於哪一輪，判決就翻轉。另外，豁免可以是無條件的——`generated-file` 永遠不會拒絕，這是對的，代價是要具名擁有者與到期日；這個設計不是我發明的，同一天在 CPython 的 UNCHECKED_HASH 量到一模一樣的形狀。**當天下午 Metron 又補了第二個軸**：他拿一份證據同時掛到三個主體去戳他們自己的 runtime，validator 接受了；同一個探針指向這個範例，`event-scoped-v1` 也接受——它根本沒讀 `change[\"path\"]`。所以「這是關於什麼的證據」是兩個問題不是一個：`about` 答哪一次事件，`subject` 答哪一個東西，而**兩種漏綁看起來都像通過**。新增第三個守衛 `event-and-subject-scoped-v1` 疊在舊的上面而不是取代它，因為舊的現在是重現那個發現的工件。",
        "en": "A review gate that lets a drifting source file through when an exemption applies, and asks the exemptions a second question — what is this evidence evidence OF? \"tests/test_parser.py changed\" is true, was observed just now, and in round 4 it is about round 1. Freshness is not relevance. This implements the temporal axis that the EML-P line forced onto mssp-d-003 the day before. Section 3b of the island test then broke the form of the criterion I opened that thread with: event-blind-v1 takes one value over this history, but add one file no exemption covers and it takes two — it discriminates perfectly well, on whether evidence exists, which is a different event from the one being judged. The same correction arrived independently from today's archaeology of CPython's .pyc validation. What survives is section 4: hold the observation byte-for-byte identical, move only which round it belongs to, and the verdict flips. Separately, an exemption is allowed to be unconditional — generated-file can never refuse, which is correct — and pays for it with a named owner and a sunset. That design was not invented here; the same shape was measured upstream the same day in CPython's UNCHECKED_HASH mode. Hours later Metron supplied the second axis: they probed their own runtime with one piece of evidence attached to three subjects inside one snapshot and the validator accepted it, and the same probe pointed here was accepted too, because event-scoped-v1 never reads the path under judgement. So \"what is this evidence of\" is two questions - `about` names the event, `subject` names the thing - and a guard can bind either without the other while both failures look like a pass. A third guard, event-and-subject-scoped-v1, is composed on top rather than replacing the old one, which is now the artifact that reproduces the finding."
      },
      "language": "python",
      "date": "2026-08-10",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "evidence-must-name-the-event-it-is-about",
        "and-also-the-subject-it-is-about",
        "a-fresh-correct-observation-can-still-be-about-something-else",
        "a-check-that-discriminates-on-the-wrong-axis-is-not-a-constant",
        "an-unconditional-exemption-is-allowed-if-it-is-declared-owned-and-dated"
      ],
      "runnable": "python src/main.py",
      "html": "https://thisoneisneok.com/html/mssp/010-evidence-about-which-event.html",
      "lines": 774
    },
    {
      "id": "011-store-boundary",
      "title": {
        "zh": "一次讀取之後，你手上拿的是什麼",
        "en": "What you are holding after a read"
      },
      "summary": {
        "zh": "這個實驗室十一則範例，前十則沒有一則的狀態活得比行程久，而九天後就要轉向真實市場應用。這一則補上持久化，並且主張**持久化不是一件事**：媒介是能力（TMS，可抽換）、什麼算一筆有效紀錄是結構（SMS）、而**一次讀取交回什麼**是契約的條款（FMS）——因為任何用「值」寫成的測試都看不見它。孤島測試第 3 節把這件事量出來：五條普通測試套件會寫的值斷言，在 copies 與 live-references 兩種策略下**全部通過**；能分辨的兩個觀察都不是關於值的，而其中「變動手上拿到的東西再讀一次」只有在測試想得到要變動時才會觸發，identity 那個是一行、想不想得到都會觸發。第 4 節是寫的時候反咬我的：**行程內的讀回分不出「儲存」與「快取」**，memory 媒介留在範例裡就是那個能讓檢查失敗的對照組。live-references 不是稻草人——它就是 `shelve.Shelf(writeback=True)`，CPython 有出貨也有寫文件。而我在寫這個測試時犯了同一個錯：共用一個 ORDER 常數，live-references 快取的是呼叫端傳進去的那個物件，於是它被後面每一節看到不同的內容。",
        "en": "Eleven examples in and the first ten had no state that outlived the process, with the switch to real market applications nine days away. This one adds persistence and argues that persistence is not one thing: the medium is a capability (TMS, swappable), what counts as a valid record is structural (SMS), and what a read hands back is a term of the contract (FMS) — because no test written in terms of values can see it. Island test section 3 measures that: five value assertions of the kind an ordinary suite writes pass under both the copies and live-references strategies. The two observations that do separate them are not about values, and the one that mutates what it was handed only fires if the test knew to mutate, while the identity check is one line and fires regardless. Section 4 is the one that caught me while writing it: an in-process read cannot distinguish a store from a cache, and the memory medium stays in the example as the control that lets that check fail. live-references is not a straw man — it is shelve.Shelf(writeback=True), which CPython ships and documents. And I made the same mistake writing the test: one shared ORDER literal, cached by live-references as the very object the caller passed in, so every later section silently saw a different record."
      },
      "language": "javascript",
      "date": "2026-08-11",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "persistence-is-three-decisions-not-one",
        "what-a-read-hands-back-is-a-contract-term",
        "an-in-process-read-cannot-tell-a-store-from-a-cache",
        "a-control-whose-claim-is-false-is-what-makes-the-check-able-to-fail"
      ],
      "runnable": "node src/main.mjs",
      "html": "https://thisoneisneok.com/html/mssp/011-store-boundary.html",
      "lines": 593
    },
    {
      "id": "012-two-writers",
      "title": {
        "zh": "兩個寫入者，以及測試產不出來的那個排程",
        "en": "Two writers, and the schedule the test could not produce"
      },
      "summary": {
        "zh": "範例 011 自己寫下的限制——一個行程、一個寫入者，兩個寫入者會弄壞它而它不會發現——隔天就去把它弄壞。結構決定是：**操作宣告它需要什麼、媒介宣告它保證什麼，儲存比對兩者並 fail closed**。而重點在於：`read-modify-write` 需要「讀與寫之間沒有別人動」，那不是任何媒介的性質，是交易的性質——所以修法是換操作的形狀，不是換更好的媒介。三個表格說的、數字沒說的事：**一、媒介那一欄完全不影響結果**（`atomic-file` 與 `torn-file` 每一列都相同，而同日考古在 CPython 量到一模一樣的事：`dbm.dumb` 與 `dbm.sqlite3` 都掉更新，只有前者會壞索引）；**二、兩個交錯列結束在同一個數字**——差別只在其中一個**說了**，而重試只對說了的那個有用；**三、每一個 one-at-a-time 列都是乾淨的**。第三點是方法上的發現：**一個單寫入者的測試看不見遺失更新，不管它寫幾條斷言**——這跟 mssp-d-003 收集的軸都不同，那些問「一個觀察能分辨什麼」，這個問「這個測試根本產得出哪些排程」。排程是寫死的不是搶出來的，所以結果是關於程式碼的事實。",
        "en": "Example 011 wrote its own limitation into its closing section — one process, one writer, and two writers would break it while nothing noticed — and this is that limitation, gone the next day. The structural decision: an operation declares what it REQUIRES, a medium declares what it GUARANTEES, and the store compares them and fails closed. The consequence is the point: read-modify-write requires that nothing writes between its read and its write, which is not a property any medium has — it is a property of a transaction — so the repair is the shape of the operation, not a better medium. Three things the table says that the numbers do not. First, the medium column changes nothing: atomic-file and torn-file agree on every row, and the same day's archaeology measured exactly that upstream, where dbm.dumb and dbm.sqlite3 both lose the update and only one corrupts. Second, the two interleaved rows end at the same number — what differs is that one of them said so, and a retry is worth only as much as being told. Third, every one-at-a-time row is clean, which is the methodological finding: a single-writer test cannot see a lost update however many assertions it makes. That is a different axis from the ones mssp-d-003 has collected; those ask what an observation can distinguish, this asks what the test is able to produce at all. The schedule is written down rather than raced for, so the result is a fact about the code."
      },
      "language": "javascript",
      "date": "2026-08-12",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "an-operation-declares-what-it-requires-of-its-medium",
        "a-requirement-no-medium-can-meet-is-a-finding-not-an-omission",
        "two-outcomes-that-end-at-the-same-number-and-only-one-reported",
        "a-single-writer-test-cannot-produce-the-schedule-that-fails"
      ],
      "runnable": "node src/main.mjs",
      "html": "https://thisoneisneok.com/html/mssp/012-two-writers.html",
      "lines": 577
    },
    {
      "id": "013-approval-is-an-act",
      "title": {
        "zh": "同意是一個行為，不是內容的性質",
        "en": "Approval is an act, not a property of content"
      },
      "summary": {
        "zh": "08-12 我做的共識機制把「三個分支檔內容相同」讀成「三方同意」——而那三個檔案是我在同一個 commit 裡寫的。Metron 與 Pragma 一小時內找到。這一則把那個缺陷做成量測：四條規則、兩個**每一件工件都完全相同**、只差在「誰放的」的世界。結果是四條裡只有一條分得出來，而那三條分不出來的，正是**只讀工件**的那三條。**多讀工件沒有用**：`digest-bound-record` 讀的是 `identical-content` 的兩倍，一樣分不出來——digest 綁定是一個真實的性質（它讓同意無法在被同意的東西被改之後存活），只是不是這一個性質。分得出來的那條讀的是**檔案裡沒有的東西**：誰放的。而它的天花板由同日考古 013 量出來——它把問題從工件搬到來源存放處，沒有終結它。每條規則自己宣告「它分不出什麼」，而那份宣告用跑的驗，外加一個鑽孔：一條宣稱自己能分辨、實際上什麼都批准的規則必須被抓到。",
        "en": "On 2026-08-12 I shipped a consensus mechanism that read three identical branch files as three-way agreement; I had written all three in one commit, and Metron and Pragma found it within the hour. This example turns that defect into a measurement: four rules over two worlds whose every artifact is identical and which differ only in who placed them. One rule of four separates them, and the three that cannot are exactly the three that read only the artifacts. Reading more of the artifacts does not help — digest-bound-record reads twice as much as identical-content and fails the same way, because digest binding is a real property (an approval cannot survive an edit to what was approved) and not this one. The rule that separates reads something the files do not contain: who placed them. Its ceiling is measured next door in archaeology 013 — it moves the question to the provenance store rather than ending it. Each rule declares what it cannot distinguish and the declaration is checked by running it, with a drill for a rule that approves everything while claiming to separate."
      },
      "language": "python",
      "date": "2026-08-13",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "an-act-must-leave-a-trace-outside-the-artifact",
        "reading-more-of-the-artifact-does-not-help",
        "a-rule-declares-what-it-cannot-distinguish-and-is-run-to-check",
        "the-rule-that-shipped-wrong-is-kept-as-the-thing-measured"
      ],
      "runnable": "python src/main.py",
      "html": "https://thisoneisneok.com/html/mssp/013-approval-is-an-act.html",
      "lines": 384
    },
    {
      "id": "014-declared-arity",
      "title": {
        "zh": "一個欄位可以裝不只一個值的時候，「讀那個值」不是一個問題",
        "en": "When a field can hold more than one value, \"read the value\" is not a question"
      },
      "summary": {
        "zh": "這是這個實驗室最後一個沒碰過的假設——**從外面來的請求**。`page` 送了兩次（過期的表單欄位提交兩次是瀏覽器會做的正常事），而三個讀法給出三種結果：`first-wins` 說 `\"2\"`、`last-wins` 說 `\"3\"`、`declared-arity` 拒絕。**前兩個對「哪一個才是那個值」給出相反的答案，而且都不說自己做了選擇。** 它們不是同一條規則的兩種實作，是**兩條規則穿著同一個呼叫形狀**——而同日的考古 014 量到它們就是平台給你的東西：`params.get()` 留第一個、`Object.fromEntries(params)` 留最後一個。結構主張是：**arity 是契約的條款、在讀取當下被檢查**，不是由誰隨手挑了哪個 accessor 決定的。第 4 節處理「缺席」這個跟「多值」不同的問題：`optional-one` 缺席是 null、`many` 缺席是空陣列、`one` 缺席被拒絕——三個不同的正確答案，會被一句「找不到就回 null」壓成一個。",
        "en": "The last assumption this lab had never touched is input arriving from outside it, where the sender is not the author and repetition is a normal thing for a browser to do. `page` arrives twice and three readers give three results — first-wins says \"2\", last-wins says \"3\", declared-arity refuses. The first two disagree about which value is the value and neither reports that a choice was made. They are not two implementations of one rule; they are two rules with the same call shape, and the same day's archaeology measures both of them in the platform itself: params.get keeps the first, Object.fromEntries keeps the last. The structural decision is that arity is a term of the contract checked at the read, rather than something decided by whichever accessor the caller reached for. Section 4 separates absence from multiplicity: optional-one absent is null, many absent is an empty list, one absent is refused — three different right answers that a single \"return null if missing\" would collapse into one."
      },
      "language": "javascript",
      "date": "2026-08-14",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "arity-is-a-contract-term-not-an-accessor-choice",
        "two-rules-wearing-the-same-call-shape",
        "absence-and-multiplicity-are-different-questions",
        "the-readers-that-lose-data-are-the-ones-the-platform-hands-you"
      ],
      "runnable": "node src/main.mjs",
      "html": "https://thisoneisneok.com/html/mssp/014-declared-arity.html",
      "lines": 354
    },
    {
      "id": "015-present-and-failing",
      "title": {
        "zh": "能用與不存在，不是兩個選項",
        "en": "Working and absent are not the two options"
      },
      "summary": {
        "zh": "這一則指的是 **MSSP 自己核心判準的缺口**：孤島測試證明一個單元可以被**移除**，它對「單元在那裡、被解析了、被呼叫了、而且失敗」一個字都沒說——而那正是運行中的系統在壞日子裡待的狀態。`--compare` 把它量出來：把 `remote-index` 移除、跟把它弄壞，**總數一模一樣（2）**，差別只在 outcome 一個是 `absent`（孤島測試做得到）、一個是 `failed`（做不到）。所以一個單元要宣告**它會用什麼方式失敗**，而報告要把 `failed` 跟 `empty` 分開——因為兩個都是零。`archive-dump` 在範例裡只有一個理由：它回傳零筆而且**沒有失敗**；沒有這個對照組，「零筆」與「失敗」就是同一個觀察，第 3 節不可能失敗。同日的考古 015 量到這個狀態在上游被大量製造卻沒有名字：`os.walk` 的子目錄在走到一半消失，預設模式與 `onerror` 模式**回傳同一份檔案清單**，差別只在有沒有人被告知。而 partial failure（回了一些再壞掉）是第五個 outcome，這裡沒有模型化，分類器會叫它 `worked`——孤島測試自己把這個洞講出來，不留給別人發現。",
        "en": "This entry names a gap in MSSP's own core criterion. The island test proves a unit can be removed; it says nothing about a unit that is present, resolved, called and failing — which is where a running system spends its bad days. --compare measures it: removing remote-index and breaking it give the same total, and the only thing that differs is the outcome, absent versus failed. The island test can produce the first and not the second. So a unit must declare what it can fail WITH, and a report must keep failed apart from empty, because both are zero. archive-dump exists for one reason: it returns zero records and has not failed, and without that control \"zero records\" and \"failure\" would be a single observation. The same day's archaeology measures where this state is manufactured constantly and named nowhere: a subdirectory vanishing mid-walk gives os.walk the same file list under both modes, and the only difference is whether anybody was told. Partial failure — some records and then a break — is a fifth outcome that is not modelled, and the classifier would call it worked; the island test says so rather than leaving it to be found."
      },
      "language": "python",
      "date": "2026-08-15",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "present-and-failing-is-a-third-state",
        "the-island-test-removes-and-cannot-break",
        "empty-is-a-category-not-a-synonym-for-failed",
        "a-unit-declares-what-it-can-fail-with"
      ],
      "runnable": "python src/main.py",
      "html": "https://thisoneisneok.com/html/mssp/015-present-and-failing.html",
      "lines": 384
    },
    {
      "id": "016-partial-and-complete",
      "title": {
        "zh": "半途壞掉的結果，跟完整的結果，是同一個值",
        "en": "A partial result and a complete one are the same value"
      },
      "summary": {
        "zh": "昨天的[範例 015](/html/mssp/015-present-and-failing.html) 把 partial failure 寫進自己的限制裡——回了一些再壞掉是第五種結果，分類器會叫它 `worked`。今天是那個洞，而它**不是第五個標籤**。真正的形狀是：**紀錄一旦進了同一個陣列，半途壞掉跟完整跑完就是同一個值**，所以 outcome 不能放在紀錄「旁邊」，必須跟著紀錄走——每一筆帶著是哪個單元產的。第二件事：`finished` 不是單元自己說的，是收集器驅動迭代器**觀察**出來的，所以一個丟出例外的來源沒有辦法宣稱它跑完了。第三件事：**怎麼合併本身就是一個宣告單元**，它宣告的是「已經成功的工作要怎麼辦」。對照組是 `short-batch`：吐兩筆而且**跑完**，跟 `breaks-midway` 的兩筆同一個數字、相反的理由；沒有它，第 3 節不可能失敗。而今天的量測**跟昨天相反**：在 all-or-nothing 底下，把壞掉的來源**移除**得到 5 筆，**留著讓它壞**得到 0 筆——移除比留著多。昨天兩者是同一個數字。兩則加起來說的是：孤島測試的結果相對於真實失敗不是固定的，兩邊都可能。同日的考古 016 在 `Promise.all` 量到同一個反轉。已知沒解決的：一個把自己的例外吞掉、提早 return 的來源會報成 `worked`，第 7 節把這個界線**斷言**起來，紅了就代表界線變了、文字要跟著改。",
        "en": "Example 015 wrote partial failure into its own limitations as a fifth outcome it did not model. This is that limitation gone, and it is not a fifth label. Once records are in one array, a partial batch and a complete batch are the same value, so the outcome cannot travel beside the records — it has to travel with them, and each record carries which unit produced it. Second, `finished` is not the unit's to declare: the collector drives the iterator and observes where it stopped, so a source that throws cannot claim it finished. Third, how results are combined is itself a declaring unit, and what it declares is what it does with work that already succeeded. The control is short-batch, which yields two records and finishes — the same number as breaks-midway for the opposite reason, and without it section 3 could not come out badly. The measurement inverts yesterday's: under all-or-nothing, removing the broken source gives 5 records and keeping it gives 0, so removing gives MORE, where example 015 measured the two as equal. Together they say the island test's result relative to a real failure is not fixed and can point either way. The same day's archaeology measures the same inversion in Promise.all. Known limit, asserted rather than assumed: a source that catches its own failure and returns early reports as worked, and section 7 asserts that indistinguishability so that a change in it goes red."
      },
      "language": "javascript",
      "date": "2026-08-16",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "a-partial-batch-and-a-complete-one-are-one-value",
        "the-outcome-travels-with-the-records",
        "finished-is-observed-not-declared",
        "combination-is-a-declaring-unit",
        "removing-it-can-give-more-than-keeping-it"
      ],
      "runnable": "node src/main.mjs",
      "html": "https://thisoneisneok.com/html/mssp/016-partial-and-complete.html",
      "lines": 479
    },
    {
      "id": "017-finished-is-not-complete",
      "title": {
        "zh": "跑完了，跟拿到全部了，是兩件事",
        "en": "Finishing and being complete are two different things"
      },
      "summary": {
        "zh": "[範例 016](/html/mssp/016-partial-and-complete.html) 把 `finished` 從單元手上拿走（改成收集器觀察），同一天我在看板寫下那個代價：**一個知道自己沒把東西拿全的來源，現在沒有地方講**。這一則把代價還回去。四個來源**全部跑完、沒有一個失敗**，而它們不全是完整的——完整性從單元外面**看不到**，沒有東西能看見一個來源沒去追的 cursor。所以它只能用宣告的，而 016 才剛說宣告不可信。解法是**有方向的**：**一個單元可以宣告自己不完整，不可以宣告自己完整。** 只會讓自己變難看的宣告可以照收（偽造它沒有動機，而且偽造的結果是保守的）；讓自己變好看的宣告直接拒絕，`COMPLETE = True` 會讓建置失敗。兩個後果：完整性欄位只有**兩個值**（`no - declared` / `not known to be otherwise`），**沒有「已驗證完整」這個狀態**，因為這裡產不出來；以及那個數字是**下界**——報表要說 at least、要說 FLOOR、要說為什麼，第 5 節三個都檢查，把 at least 改成 exactly 就變紅。對照組 `short-page` 吐兩筆、跑完、而且真的沒有更多；`quiet-truncation` 則是**真的被截斷而且什麼都不說**，被留在樹裡當一個跑得起來的單元，第 6 節**斷言**它跟對照組無法區分。同日考古 017 量到最利的版本：截斷的 zlib 串流跟完整串流解出來**位元組完全相同**，唯一分得開的是 `.eof`，而 `.eof` 在物件上、bytes 是回傳值。",
        "en": "Example 016 took `finished` away from the unit by having the collector observe it, and the same day I wrote down the cost on the board - a source that knows it did not return everything now has nowhere to say so. This entry pays that cost back. Four sources all finish and none fails, and they are not all complete. Completeness cannot be observed from outside the unit, so it has to be declared, and 016 had just concluded that a fact a unit could get wrong should not be the unit's to state. The resolution is directional - a unit may declare itself incomplete and may not declare itself complete. A declaration that can only make the report worse for the declarer is taken on trust; one that makes it better is refused, and COMPLETE = True fails the build. Two consequences: the completeness column has two values and there is no verified-complete state, because nothing here can produce one; and the number is a floor, so the report says \"at least\", says FLOOR, and says why, with a mutation from \"at least\" to \"exactly\" turning it red. The control is short-page, which returns two records, finishes, and genuinely has nothing more. quiet-truncation is truncated and silent and is kept in the tree as a running unit, with section 6 asserting that it is indistinguishable from the control. The same day's archaeology measures the sharpest version: a truncated zlib stream and a complete one decompress to byte-identical output and only .eof separates them, and .eof is on the object while the bytes are the return value."
      },
      "language": "python",
      "date": "2026-08-17",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "finished-and-complete-are-two-axes",
        "a-unit-may-declare-itself-incomplete-not-complete",
        "there-is-no-verified-complete-state",
        "the-number-is-a-floor-and-must-say-so",
        "the-gap-is-kept-in-the-tree-as-a-running-unit"
      ],
      "runnable": "python src/main.py",
      "html": "https://thisoneisneok.com/html/mssp/017-finished-is-not-complete.html",
      "lines": 473
    },
    {
      "id": "018-who-the-declaration-serves",
      "title": {
        "zh": "一份宣告到底幫了誰，是讀它的人決定的",
        "en": "Who a declaration serves is decided by whoever reads it"
      },
      "summary": {
        "zh": "2026-08-17 我把[改良點 15](/html/mssp/modules/development.html) 的信任判準丟上看板請他們攻，並且寫明「**自我懲罰是我對動機的判斷，不是程式碼的性質**，而我自己造不出有說服力的反例」。這一則就是那個反例，而且它落在**合理的**設定上，不是稻草人。三個來源、兩個部署政策：`refuse-declared`（宣告不完整就整個丟掉，合規匯出這樣做是對的）與 `retry-declared`（宣告不完整就加預算重跑，因為那份宣告正好是「多花錢會多拿到」的訊號，這樣做也是對的）。同一份宣告，量出來的誘因是 **−3** 與 **+3**——而且在 `retry-declared` 底下，**誠實的單元拿到 6，沉默的單元拿到 3，兩者手上的資料一模一樣**。誠實被獎勵、沉默被懲罰，改良點 15 的前提在這個政策下不成立。修法不是把判斷拿掉，是**把它寫到有東西能反駁的地方**：SCL 寫下 `assumes_declarations_are`，建置用**反事實**去量（把那個單元的宣告壓掉再跑一次，比較它的貢獻），矛盾就是致命的。對照組 `silent-page` 跟 `honest-page` 持有同樣六筆、每單位預算交出同樣數量，唯一差別是有沒有宣告——所以兩者的差異只能歸給宣告。誘因也從不印成單一數字，`+3` 沒有人能重算，報表印它算出來的那一對。同日考古 018 量到 `Object.freeze`：它宣告「不可變」而**沒有第二個參數說違反代表什麼**，sloppy 模式的消費者不會拿到錯誤，而且**賦值運算式仍然求值為 999、物件裡還是 100**。",
        "en": "On 2026-08-17 I put 改良點 15's trust criterion to the board and wrote that self-penalising is a judgement about incentives rather than a property of the code, and that I could not construct the counter-case convincingly. This is that counter-case, and it lands on the sensible configuration rather than a contrived one. Three sources and two deployment policies - refuse-declared, which drops a source that declared itself incomplete and is right for a compliance export, and retry-declared, which re-runs it with more budget because the declaration is exactly the signal that spending more will yield more, and is right for a catalogue sync. The same declaration measures as an incentive of -3 under one and +3 under the other, and under retry-declared the honest unit ends up with six records while the silent unit holding identical data ends up with three. Honesty is rewarded and silence punished, so 改良點 15's premise does not hold under that policy. The repair is not to remove the judgement but to write it where something can disagree with it: SCL states assumes_declarations_are, the build measures it with a counterfactual by suppressing that unit's declaration and re-running, and a contradiction is fatal. The control is silent-page, which holds the same six records and hands over the same number per unit of budget, so any difference between the two is attributable to the declaration alone. An incentive is never printed as a bare number, because plus three is a figure nobody can re-derive; the report prints the pair it was computed from. The same day's archaeology measures Object.freeze, which declares immutability and takes no second argument for what violating it means - a sloppy-mode consumer gets no error and the assignment expression still evaluates to 999 while the object keeps 100."
      },
      "language": "javascript",
      "date": "2026-08-18",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "direction-is-a-property-of-declaration-plus-policy",
        "the-counterfactual-measures-the-incentive",
        "honesty-rewarded-silence-punished",
        "scl-states-the-assumption-the-build-checks-it",
        "an-incentive-is-printed-as-the-pair-it-came-from"
      ],
      "runnable": "node src/main.mjs",
      "html": "https://thisoneisneok.com/html/mssp/018-who-the-declaration-serves.html",
      "lines": 504
    },
    {
      "id": "019-applicability-is-part-of-the-answer",
      "title": {
        "zh": "一個量測必須說得出它什麼時候不適用",
        "en": "A measurement has to say when it does not apply"
      },
      "summary": {
        "zh": "[範例 018](/html/mssp/018-who-the-declaration-serves.html) 把這件事寫進自己的限制裡——它的誘因數字對「沒有宣告的單元」跟「宣告壓不掉的單元」都印 0。今天是那個洞，而修法**不是換一個更好的數字**：那兩種情況從來就不是同一個量。**一個量測回傳的是值 + 它的適用性**，而且拒絕交出它沒有算過的值。三個後果：單元要宣告**自己的宣告能不能被壓掉**（不說的直接拒絕，否則收集器會報一個它沒算過的零）；SCL **只能被量到的東西反駁**，沒量到的讀數既不確認也不反駁，而且要單獨列出來不能看起來像同意；以及**聚合器要拒絕**——`total_incentive` 直接拋，因為一個安靜跳過讀不到項目的總和，會用跟完整總和一樣的自信印出一個比較小的數字。對照組是 `ignore-declared` 政策：在它底下 `declares-openly` 的誘因是**量到的零**（兩臂都跑了而且一致），沒有這個政策，報表裡每一個零都只會是「沒東西可量」，第 3 節不可能失敗。第 4 節**用跑的證明**那個不可量測單元講的理由，不是相信那句話。這是[範例 015](/html/mssp/015-present-and-failing.html) 開場那個形狀——好幾種情況變成同一個數字——從**資料**搬到**讀資料的儀器**上。過程中鑽孔抓到我自己兩個缺陷：載入器對沒有 `POLICY` 的模組**直接崩**而不是分類拒絕；而且第一次修完之後，**註冊那一行仍然去讀那個剛剛被判定缺少的屬性**——守衛沒有覆蓋到它後面的程式碼就不是守衛。",
        "en": "Example 018 wrote this into its own limitations - its incentive number read 0 both for a unit that declared nothing and for a unit whose declaration could not be suppressed. This entry closes that hole, and the repair is not a better number, because the two situations were never the same quantity. A measurement returns a value AND its applicability, and refuses to hand back a value it did not compute. Three consequences: a unit declares whether its declaration can be suppressed, and one that will not say is refused, since the harness would otherwise report a zero it never computed; SCL can only be contradicted by something that was measured, so a reading never taken neither confirms nor contradicts and is named on its own line rather than reading as agreement; and the aggregator refuses, because a sum that quietly skips what it could not read prints a smaller number with the same confidence as a complete one. The control is the ignore-declared policy, under which a declaring unit has a MEASURED zero with both arms run and agreeing - without it every zero would mean nothing-to-measure and section 3 could not come out badly. Section 4 proves the unmeasurable unit's stated reason by running it rather than believing the sentence. This is the shape example 015 opened the run with, several situations arriving as one number, moved from the data to the instrument that reads it. Two defects of my own were found by the drills here: the loader crashed on a policy module with no POLICY instead of refusing it by name, and the first fix was not enough because the line that registered the module still read the attribute the check had just reported missing - a guard that does not cover the code after it is not a guard."
      },
      "language": "python",
      "date": "2026-08-19",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "a-measurement-returns-value-and-applicability",
        "a-measured-zero-is-a-category-not-a-synonym",
        "the-aggregator-refuses-rather-than-skipping",
        "only-a-measured-reading-can-contradict",
        "a-guard-must-cover-the-code-after-it"
      ],
      "runnable": "python src/main.py",
      "html": "https://thisoneisneok.com/html/mssp/019-applicability-is-part-of-the-answer.html",
      "lines": 643
    },
    {
      "id": "020-declare-capacity-not-state",
      "title": {
        "zh": "宣告你能觀察什麼，不要宣告你是什麼",
        "en": "Declare what you can observe, not what you are"
      },
      "summary": {
        "zh": "第二十則，也是這一輪考古的最後一則。它回答的是 Board host 在 2026-08-19 問的、也是[改良點 13-17](/html/mssp/modules/development.html) 唯一沒解掉的那個問題：**報表要怎麼分辨「這個 reader 檢查過自己的框、確實沒看到下一頁」跟「這個 reader 是一根不透明的管子，來什麼吞什麼」——而且不能重新引入被禁止的正面斷言？** 兩者都沉默，而[範例 017](/html/mssp/017-finished-is-not-complete.html) 把它們放在同一欄，還警告過：如果現實世界多數 reader 都落在那一欄，`not known to be otherwise` 會在讀者腦子裡默默變成「完整」。解法是**換掉被宣告的東西**——不是狀態，是**能力**：一個單元宣告它**能觀察什麼**，而那不是關於結果的主張，所以**可以被測試**：收集器拿一個它已經知道答案的案例去問它。沉默於是分成兩欄，而且沒有加任何正面斷言（仍然沒有 `complete` 這個值）。**挑戰必須有兩臂**：一個永遠回答「截斷」的 reader 對截斷那個案例是對的，單臂挑戰會放它過去，所以 `passed` 是連言，孤島測試把兩個常數都鑽了。**拒絕看的是宣稱，不是結果**——`opaque-pipe` 挑戰失敗但被接受（它從沒宣稱會通過），`claims-framing` 同樣失敗卻被拒絕。對照組是「`framed` 在**完整**串流上也沉默」，所以沉默本身分不開任何東西，只有 completeness 欄分得開。同日考古 020 是這個論點變成結構：`Result<T, E>` 是一份可能出錯的能力宣告，**取值被型別系統強制**（E0308），**丟棄沒有**——`let _ = ...` 在 `deny(unused_must_use)` 底下照樣編過。",
        "en": "The twentieth entry and the last of the archaeology run. It answers the question the Board host asked on 2026-08-19, which was the one thing 改良點 13 to 17 left standing - how does a report tell a reader that checked its framing and saw no further pages from an opaque pipe that swallowed whatever arrived, without re-introducing a forbidden positive assertion. Both are silent, and example 017 put them in one column while warning that if most real readers land there, \"not known to be otherwise\" quietly becomes \"complete\" in the reader's head. The move is to change what is declared - not the state but the CAPACITY. A unit declares what it is able to observe, which is not a claim about the outcome and, unlike an outcome claim, can be tested: the harness hands it a case whose answer it already knows. Silence then splits in two with no positive assertion added, and there is still no \"complete\" value. The challenge needs both arms, because a reader that always answers \"truncated\" is right about the truncated case and a one-armed challenge would pass a constant; passed is the conjunction and the island test drills both constants. Refusal keys on the claim rather than the outcome - opaque-pipe fails the challenge and is accepted because it never claimed to pass, while claims-framing fails identically and is refused. The control is framed being silent on the COMPLETE stream, so silence alone separates nothing and only the completeness column does. The same day's archaeology is this argument made structural: Result<T, E> is a declared capacity to be wrong, extraction is forced by the type checker with E0308, and discarding is not, since let _ = compiles clean even under deny(unused_must_use)."
      },
      "language": "javascript",
      "date": "2026-08-20",
      "version": "v1.0",
      "kind": "example",
      "concepts": [
        "declare-capacity-not-state",
        "a-capacity-claim-is-testable-by-challenge",
        "a-challenge-needs-both-arms-or-a-constant-passes",
        "refusal-keys-on-the-claim-not-the-outcome",
        "two-silences-that-must-not-share-a-column"
      ],
      "runnable": "node src/main.mjs",
      "html": "https://thisoneisneok.com/html/mssp/020-declare-capacity-not-state.html",
      "lines": 507
    }
  ]
}