Skip to content

v0.6.18 — v0.6.17 の attestation を是正し、core と CLI を分離

Choose a tag to compare

@Driedsandwich Driedsandwich released this 15 Aug 02:58
· 58 commits to main since this release

v0.6.18 — v0.6.17 の attestation に誤りがありました。core と CLI を分離しました

⚠ 先に読むところ

1. v0.6.17 の attestation は、配った索引とは別のものを指していました

公開した直後に、自分で添付を検算して見つけました。

attestation が名乗る値   e9c72e2412fa6e21…  ← **repo 側**の索引(releaseTag: null)
配布した索引の実測       a014768129b56e18…  ← 受け手が計算する値
違う欄                   releaseTag / releaseCommit(配布時に書き込む)

3 つの digest のうち 2 つは一致していました。test_counts.json
validation-results.json は配布時にそのまま写すので同じ値になります。
索引だけが写しではありません——releaseTagreleaseCommit を配布時に書き込むためです。

**「ほとんど合ってしまう」のが危ないところでした。**ずれるのは
受け手が最初に引く 1 つだけです。

公開済みの v0.6.17 の asset は上書きしません。
docs/ERRATA.md §23 に記録し、
この版で直しました(測る先を配布物の側へ)。この欠陥を捕まえる検査も入れています。

v0.6.17 での影響は attestation.releaseIndexSha256 の 1 欄だけです。
SHA256SUMS は配布物から作っているので正しく、索引の検算はそちらで行えます。

2. core と CLI を分離しました。toolVersionschemaVersion も上げていません

外部監査 P2(v0.6.15 / v0.6.16 / v0.6.17 で 3 回続けて指摘)にようやく着手しました。

新設   defaultIo()(cwd / argv / stdout / stderr / exit + filesystem 5 種)
差替   process.* と console.log の呼び出しを io 経由へ
残す   入口の判定 2 か所(この道具が起動されたのかを見るもの)

上げていない根拠を実測で示します。

出力           分離前に固定した **9 経路すべてが byte 一致**(基準は現在 10 経路。
               10 本目は分離のあとに足した SOURCE_ARCHIVE_MISSING の経路)
出しうる code   **82 種類のまま**(増減 0)
schemaVersion  2 のまま・配布 schema も不変
出力に出るか    reachability は出力に 0 件(対照: stableReasonCode は 1 件)

**受け手の分岐は変わりません。**上げたくなったら、それは分離ではありません。

分離が「何も変えていない」ことは、分離の前に取った基準で確かめています
test/fixtures/cli-output-baseline.v1.jsonnpm run check:cli-output)。
基準は repo に入っているので、受け手も同じものを回せます。

3. SOURCE_ARCHIVE_MISSING を実経路として踏みました

v0.6.17 で race-defensive(到達しうるが決定的には踏めない)と宣言した code です。
踏めました。「決定的には踏めない」は踏む試験を書いていなかっただけでした。

loadFromDir      existsSync(abs)  … 通る
                 lstatSync(abs)   … ディレクトリでない → loadFromArchive へ
loadFromArchive  existsSync(abs)  … **ここで消えていればこの code**

同じ path に対する 2 回目の existsSync だけ false にすれば踏めます。
node:fs を差し替えて注入します——道具は 1 バイトも変えません
globalThis.fetch の差し替えと同じ形)。

catalog  race-defensive → **cli-route**
         82 種類 = corpus 45 / cli-route 34 / defensive-invariant 3
両方向照合  この run で出た 79 種類・到達しないと宣言した 3 種類(実測と一致)

race-defensive は語彙表に残しました(未使用であることを試験で明示)。

4. io へ filesystem を足しましたが、この経路には効いていません

実測(2026-08-15):

同じ注入(node:fs の差し替え)を当てる
  io に fs が無い版  → SOURCE_ARCHIVE_MISSING
  io に fs を足した版 → SOURCE_ARCHIVE_MISSING

node:fs の差し替えは ESM の named import にも効くので、
io を経由してもしなくても同じように踏めます。
この経路を踏むために io へ fs を足す必要はありませんでした。

残した理由は先の話です——main(args, io) を抽出したあとは、
global を差し替えずに fs を注入できるようになります。
いまは「そのための土台」であって、いま効いているわけではありません。
効いていないものを効いていると書かないでおきます。


まだやっていないこと

  • **実測が 1 件も来ていません。**ジャック内部の接点位置は全部仮定のままで、
    導通測定も音響測定もしていません(verifiedPhysicalfalse)。
  • **main(args, io) の抽出そのものは、まだです。**この版でやったのは
    接点を 1 か所に集めたところまでで、done() はまだ io.exit を叩きます。
    戻り値だけで完結する形にするのは次です。
  • BusyBox を oracle に足すこと。開発機にも CI にもありません。
  • annotated tag への署名。
  • 検算ツールの強化は試験した範囲までです。すべての細工に耐えることは示していません。

数えたもの

v0.6.17 v0.6.18
単体テスト 1352 1364(skip 0 / 失敗 0)
検算ツール toolVersion 20 変わらず 20
CLI 結果契約 schemaVersion 2 変わらず 2
止め方の名前(catalog) 82 種類 変わらず 82
うち到達しないと宣言 3 + race-defensive 1 3race-defensive は未使用)
出力の基準(経路) (無し) 10 経路(うち 9 件は分離前に固定)
検証対象(validate:profiles 14 14
schema 25 25
記録された入力 32 32
区間 / event TRS 23/32・TRRS 30/36 変わらず

変わっていないもの

  • **モデルの数値。**接点位置も走査結果も同じです。
  • verifiedPhysicalfalse。実測記録は依然 0 件です。
  • toolVersion 20 / CLI 結果契約 schemaVersion 2。
  • 止め方の名前の一覧(82 種類)・archivePolicy・status・終了コードの意味。