STEP 1571 (a) — No-Data Primitives
目的
STEP 1569 Ophyd 読解の Rei 即持ち帰り top 3 のうち (a) を実装:
NotConnectedError = NEITHER の型化: 全 benchtop probe と全 D-FUMT₈ verdict tool で 「未接続 / データ未取得」 を単一 verdict に統一 (STEP 1567 pattern を全 tool 適用)
初回 audit で 「ZERO を全 tool 統一」 案は却下 — ZERO は既存 tool で domain-specific 意味 (deterministic distribution / complete depletion) を持ち、衝突する。 chat-Claude の 「NEITHER 同型」 直言は hardware layer に限定した pattern であり、analytical layer は既存 NEITHER で正しい (Ophyd の layer 分離と対応)。
二層 distinction
| Layer | verdict | reason | 対象 tool | 意味 |
|---|---|---|---|---|
| Layer 1 | ZERO |
'no_data' |
sensor / probe tool | 全 input が unset (probe 未接続) = Ophyd NotConnectedError 同型 |
| Layer 2 | NEITHER |
'empty_input' 他 5 alias |
analytical tool | dataset 空 (計算不可 mathematical indeterminate) = D-FUMT₈ NEITHER 本義 |
alias 5 種: empty_input (canonical) / empty_distribution (shannon-entropy STEP 1499) / empty_series / empty_data / no_input。 auditor はこの alias 集合を Layer 2 conforming と認識。
実装
Shared primitive module — src/mcp/no-data-primitives.ts
API 表面:
// Layer 1
createSensorNoDataResult<T>(extra?: T): SensorNoDataResult & T
// → { verdict: 'ZERO', reason: 'no_data',
// trippedField: null, trippedValue: null, trippedThreshold: null, ...extra }
// Layer 2 (default reason 'empty_input'、 alias 指定可)
createEmptyInputResult<R, T>(reason?: R, extra?: T): EmptyInputResult<R> & T
// → { verdict: 'NEITHER', reason: R, ...extra }
// Helpers
isUnset(v): boolean // undefined | null | NaN
isAllUnset(...fields): boolean // Layer 1 判定 (全 field unset)
isEmptyArrayInput(a): boolean // Layer 2 判定 (array 空 or non-array)
// Type guards (dispatcher / auditor 用)
isSensorNoDataResult(r): boolean
isEmptyInputResult(r): boolean // canonical + 5 alias 全 recognize
isNoDataResult(r): boolean // 上記 2 種を統合判定
// Capability enum (drift audit)
type NoDataHandling = 'sensor-zero-no-data' | 'analytical-neither-empty'
| 'not-applicable' | 'unaudited'
Pilot retrofit
- Layer 1:
disk-health-verdict.ts(STEP 1567) —allUnset判定をisAllUnset(...)に、no-data return をcreateSensorNoDataResult({ resolvedInputs })に置換。 26/26 regression PASS - Layer 2:
shannon-entropy-verdict.ts(STEP 1499) — Guard 1 (empty frequencies) をisEmptyArrayInput(...)+createEmptyInputResult('empty_distribution', {...})に置換 (alias 保持で backward compat)。 35/35 regression PASS
Audit — 18 verdict tool 全 classify
scripts/audit-no-data-handling.ts が src/mcp/*-verdict.ts を全走査、 source grep で 4 classification に分類。 初回 run で 3 tool が unaudited flag → 全 scalar-input と確認して NOT_APPLICABLE 明示 exemption 登録で 0 drift 達成。
| Classification | 件数 | tool |
|---|---|---|
| Layer 1 | 1 | disk-health-verdict.ts |
| Layer 2 | 1 | shannon-entropy-verdict.ts |
| not-applicable | 16 | ab-test / conservation-law / d8-mapping / dual-process / evolution / flow-state / game-verdict-connector / graph / homeostasis / liar-paradox / lyapunov / nash-equilibrium / pareto-frontier / peace-axiom / pid-tuning / syntax / wa-ga (各 justification 付) |
| unaudited | 0 | — |
Usage: npm run audit:no-data (human report、exit code 0/1) / --json (machine-readable)。 未来の新 verdict tool が unaudited で fail する → 明示的な classification が要求される。
Test — 70/70 PASS
test/step1571-no-data-primitives-test.ts、 8 section:
- SensorNoDataResult (Layer 1 primitive)
- EmptyInputResult (Layer 2 primitive、 canonical + alias)
- isUnset / isAllUnset / isEmptyArrayInput helpers
- Type guards (isSensorNoDataResult / isEmptyInputResult / isNoDataResult)
- NoDataHandling capability enum shape
- disk-health-verdict retrofit regression (Layer 1 pilot)
- shannon-entropy-verdict retrofit regression (Layer 2 pilot)
- Audit script — all verdict tools classified (no drift)
結果: 70/70 PASS + 既存 test regression (step1567: 26/26 / step1499: 35/35) 全通過。
Ophyd 対応関係 (STEP 1569 との bridge)
| Ophyd 概念 | Rei 実装 (STEP 1571) |
|---|---|
NotConnectedError (未接続 1st-class 例外) | createSensorNoDataResult() = ZERO / no_data |
connect() cache | isAllUnset(...) による input probe check |
Signal 未接続 → Status set_exception | verdict 'ZERO' + trippedField null で dispatcher 一貫識別 |
| Ophyd layer 分離 (hardware vs analysis) | Layer 1 / Layer 2 の 二層 distinction (auditor が enforce) |
Honest scope
- Pilot 2 tool のみ retrofit 完了。 残 16 tool は
NOT_APPLICABLE明示 exemption で classify されているが、 新 tool 追加時は auditor が 「unaudited」 flag で forcing function として作用 - 「ZERO 統一」 は却下 = domain semantics 衝突予防。 chat-Claude の 「NEITHER 同型」 直言は hardware layer 限定 pattern と再解釈 (Ophyd 実装の layer 分離を尊重)
- Audit script は source-grep ベース (AST 解析でない)。 tool が exotic な構造 (e.g. helper function 内で verdict 構築) を持つ場合は false-negative 可能性あり、 その場合
NOT_APPLICABLEに明示追加で解決 - Msg dispatcher (STEP (b) 予定) と Protocol type (STEP (c) 予定) は本 primitive を消費する予定、 statik integration は各 STEP で実装