Skip to content

v0.6.17 — v0.6.16 は NOT_READY。CLI 結果の契約を v2 へ

Choose a tag to compare

@Driedsandwich Driedsandwich released this 15 Aug 01:41
· 67 commits to main since this release

v0.6.17 — v0.6.16 は NOT_READY です。CLI 結果の契約を v2 へ上げます

⚠ 先に読むところ

1. v0.6.16 は、版を据え置いたまま公開契約を広げていました

v0.6.16 の道具の出力は、1 つも v0.6.15 の schema を通りません。

同じ schemaId / schemaVersion: 1 を名乗りながら、言語が 3 か所広がっていました。
repo 自身の判定器で実測(2026-08-15・両 tag の実物):

diffSchemaObjects(v0.6.15 の v1, v0.6.16 の v1) = **BUMP**
  WIDEN  /properties/stableReasonCode/enum
           + CLI_ARGUMENTS_MISSING, SOURCE_FETCH_TIMEOUT
  WIDEN  /properties/archivePolicy/properties/coverage/properties/reasonCodeFamilies/items/enum   + usage
  WIDEN  /properties/archivePolicy/properties/reasonCodeFamilies/items/enum                        + usage
対照  同じ schema どうしなら HOLD(何にでも BUMP と言う判定器ではない)

外部監査の指摘より影響が広いことが分かりました。
監査は「新しい 2 つの code を返す結果が不適合」としていましたが、
usage 族は archivePolicy に載るのですべての出力に出ます。ajv で実測:

v0.6.15 の v1 schema に当てる
  引数不足の出力(CLI_ARGUMENTS_MISSING)  → 不適合(3 か所)
  **`OK` の正常な出力**                     → **不適合(2 か所)**

公開済みの asset は上書きしません。
docs/ERRATA.md §17 で
NOT_READY へ再分類しました。

受け手への影響は限定されます。 profile の数値・区間・event は変わりません。
使えないのは「v0.6.16 の出力を、後の版の schema で検証すること」だけです。
v0.6.16 が出した保存済みの結果は、v0.6.16 と一緒に配った v1 schema で検証してください。
v1 のファイルは変更していません。

2. schemaVersion が 2 に、toolVersion が 20 になります

                     v0.6.16                                    v0.6.17
schemaId       …source-verifier-cli-result.v1        →  …source-verifier-cli-result.v2
schemaVersion  1                                     →  2
toolVersion    19                                    →  20
配布ファイル名  source-verifier-cli-result.v1.schema.json → …v2.schema.json

ファイル名で引いている lock は、schema 検査へ到達する前に「ファイルが無い」で止まります。
対応は同梱の contract-migration.v1.jsonrenamedAssets)にあります。

止め方の名前の一覧・archivePolicy・status・終了コードの意味は変わっていません。
v1 → v2 で変わるのは、名乗る版だけです。

3. なぜ検査が通したか——母集団が 11 版のあいだ止まっていました

test/schemaVersioningPolicy.test.ts
  const LATEST_TAG = 'v0.5.1'          ← ここが母集団を決めていた

source-verifier-cli-result は v0.6.11 の新設なので、一度も母集団に入っていません。
コメントには「上げた回はここを新しい tag へ進める」と書いてありましたが、進みませんでした。

対照(2026-08-15): BUMP が実在する状態で v0.6.16 の検査を回すと **57/57 全緑**

「比較した本数 === 母集団の本数」という空振り検査は付いていました。
数えていたのは古いほうの一覧です。

v0.6.17 では、直前 release を package.json の版数から毎回その場で決め、
母集団を現行の schema 全部git add していないものも含む)にしました。
この反例を違反として捕まえる回帰試験も入れています。


証拠の由来を、契約が要求するようにしました

v0.6.16 は testCountsSha256 / testCountsGeneratedFromCommit / testCountsGeneratedAt
**書いてはいましたが、schema が要求していませんでした。**変異対照:

                                  v2(旧)   v3(新)
基準(無変更)                       適合       適合
3 欄をそれぞれ消す                    適合     **不適合**
SHA を 63 桁 / commit を短縮 / 日付を壊す  適合  **不適合**
未知項目を足す                       適合     **不適合**

監査は「狭める変更なので HOLD_RECORD」と想定していましたが、判定器の実測は BUMP でした。
testEvidenceoneOf の中にあり、判定器は枝の言語について単調でないことを理由に
判定不能を返します。判定器を緩めず、validation-results を v3 へ上げました。

2 つの証拠を結び直しました

release:stage は、test_counts.json の鮮度と READY別々に見ていました。
片方だけ作り直した状態は、どちらの検査も単体では通ります。

基準(無変更)              通す
test_counts だけ更新        **止める**
validation だけ更新         **止める**
SHA / commit / 日付 を偽装   **止める**
testEvidence ごと消す       **止める**

関門を切り出してから測っています。release:stage を丸ごと回すと
手前の鮮度検査が先に落ちて全件が同じ exit 1 になり
「この関門が効いた」の証拠になりません(実際に一度そう測って読み違えました)。

最終関門を通ったことが、配布物から読めるようになりました

release-stage-attestation.v1.json を足しました。
validation-results.releaseReadinessStatus: READYrelease:evidence 時点の判定で、
最終関門を通った証拠ではありません。

**索引には入れません。**索引はこれより前に作られ、これは索引を読んでから作るので、
入れると 1 回の実行で収束しません。SHA256SUMS がこの記録の sha256 を持ちます。

**この記録も自己申告です。**作った側が作った側を検査した結果でしかなく、
受け手の独立検証を置き換えません。

終了コード 3 に、機械で読める目印を付けました

stderr の 1 行目: TRS_JACK_VERIFIER_INTERNAL_CONTRACT_FAILURE

**説明文は版ごとに書き換わります。**文言でなくこの 1 語で分岐してください。
通常の CLI 結果 schema へ INTERNAL_ERROR は足していません
——壊れた道具が schema 適合の検証結果を捏造するほうが危ないためです。

到達性の語彙を作りました

SOURCE_ARCHIVE_MISSINGdefensive-invariant(論理的に起こりえない)から
race-defensive(確認と使用の間で消されれば到達する)へ移しました。外部監査の指摘どおりです。

あわせて、両方向の照合が reachability !== 'defensive-invariant' という
文字列の否定で群を分けていたのを、語彙表から引く形にしました。
否定で分けていると、新しい種類を足した瞬間に黙ってどちらかへ入ります。


まだやっていないこと

  • **実測が 1 件も来ていません。**ジャック内部の接点位置は全部仮定のままで、
    導通測定も音響測定もしていません(verifiedPhysicalfalse)。
  • **core と CLI の分離をしていません。**v0.6.16 の notes で「次の版で着手します」と
    書きましたが、**この版でも着手していません。**外部監査も
    「先に契約の versioning を閉じ、その次の独立版で着手するのが妥当」としています。
    **この版は P0 の是正です。**次の版の最初に着手します。
  • BusyBox を oracle に足すこと。開発機にも CI にもありません。
  • annotated tag への署名。
  • 検算ツールの強化は試験した範囲までです。すべての細工に耐えることは示していません。
  • SOURCE_ARCHIVE_MISSING を実経路として踏んでいません。
    race-defensive は「確認と使用の間で消されれば到達する」という分類であって、
    実際に踏んだ記録ではありません。踏むには filesystem を差し替える必要があり、
    それは core / CLI 分離のあとになります。
  • 由来の検査(release:evidence)の範囲は、artifacts/docs/ を含みません。
    含めると、証拠を書く工程が自分の書き込みで「古くなった」と判定して収束しません。
    最終判定は release:stage が実際に測り直して行います。

再生成の途中で、新しい門が自分を止めました

**第3段の順序を間違えました。**第1段・第2段で artifact を作り直したあと、
manifest と索引がまだ追随していない状態で件数を数えたので、
突合の試験が 26 件落ちました。

記録された値   failed 26 / exitCode 1 / allPassed false
門の反応       releaseReadiness NOT_READY・release:stage が拒否

生成は止めず、配布を止める設計どおりです——件数の照合が落ちている間は
件数を更新できない、という循環を避けるためにこの形にしてあります。
正しい順序(release:evidencetest:countrelease:evidence)で回し直しました。

数えたもの

v0.6.16 v0.6.17
検算ツール toolVersion 19 20
出力契約 …cli-result.v1 / schemaVersion 1 …cli-result.v2 / 2
止め方の名前(catalog) 82 種類 変わらず 82
うち到達しないと宣言 4(defensive-invariant 3 + race-defensive 1
schema 23 25(cli-result.v2 と validation-results.v3 を新設)
検証結果の契約 validation-results.v2 validation-results.v3
version 検査の母集団 v0.5.1 の 21 本 現行の 25 本

変わっていないもの

  • **モデルの数値。**接点位置も走査結果も同じです。
    葉ノードで比較して実測しています(感度 artifact: 由来まわりの差 10 件・モデル数値の差 0 件
    対照として 1 つの値を 0.001 動かすと「モデル数値の差 1 件」が出ます)。
  • verifiedPhysicalfalse。実測記録は依然 0 件です。
  • 止め方の名前の一覧・archivePolicy・status・終了コードの意味。
  • 過去 release の asset。