Skip to content

feat: effect_contracts の最初の生産者を立て、契約の到達範囲を実測する - #46

Merged
01rabbit merged 1 commit into
mainfrom
claude/zealous-edison-k5vt5j
Sep 20, 2026
Merged

01rabbit merged 1 commit into
mainfrom
claude/zealous-edison-k5vt5j

Conversation

@01rabbit

Copy link
Copy Markdown
Owner

Fabric#15 は「Edge/Gadget/AZ-06 が実際の bounded effect を記述できる」という受け入れ基準を持ったまま closed になっています。誰も生産者を立てていません。本 PR はそれを実行し、結果を記録します。

runtime/effect_projection.py が、AZ-06 の既存の PresentedTerrainSnapshotV0 を Fabric の PresentedTerrainRef に射影します。追加も選択も承認もしません。射影は AZ-06 が既に確立した事実の描画であり、Edge の決定論アービタが唯一の決定・強制権限であることは変わりません。

埋めずに拒否する

Fabric のレコードは AZ-06 が常には持たない事実を要求します。もっとも重いのが expires_at で、Fabric は bounded を要求し、AZ-06 には宣言された期限が無いのが普通です。

ここで期限を捏造すれば、AZ-06 が時限を切っていない presentation について「切った」と消費者に報告するレコードができ、しかもそれは valid になります。

AZ-06 が持たない事実は既定値ではなく拒否である。

拒否 理由
開始時刻が無い Fabric に「開始しなかった presentation」の形が無い
期限が無い 上記
isolation assertion が無い Fabric は必須
isolation assertion が複数 Fabric は単数。黙って捨てれば証拠が narrow になったことが誰にも見えない
非適合な参照 下記

欠落を毎回申告する

射影は「Fabric スロットに届かないローカル項目」19件を毎回返します。黙って欠落する射影は、消費者が Fabric レコードを AZ-06 の観測の全体だと読み始める経路です。

特筆すべき3件:

項目 状況
trace_id この family は他のすべてのレコードを trace で相関させる(assert_effect_chain_consistent も)が、PresentedTerrainRef には trace スロットが無い
synthetic_identity_refs Fabric#15 自身の候補フィールド一覧が名指しているが、出荷モデルに無い
synthetic_credential_refs 同上

生産者が立てられない2件

EffectObservation と OutcomeObservationEnvelope は AZ-06 のレコードです(AZ-06 が materializer)。しかし両者は effect: 型の id を鍵にしており、シリーズのどこもそれを発行していません。 AZ-06 が受け取るのは EnvironmentActivationDecision で、effect id を含みません。

作れないのではなく、作る対象が無いのです。テストで事実として固定しました。

測定: 参照文法

現 pin (v0.9.0rc2) では、AZ-06 が実際に発行する階層参照は typed ref を要求するすべてのスロットに拒否されます。

surface:http:8080            -> None   (tests/test_presented_terrain_evidence.py)
deception:surface:http-8080  -> None   (tests/test_defensive_state_boundary.py)

これが Azazel-Fabric#48 を生んだ測定です。書き換えは採りません: surface:http:8080 を surface:http-8080 に書き換えたものは、存在しない surface への well-formed な参照になります。

このテストは pin が動くと赤くなります。 緩和後の Fabric を pin した時点で、参照を自然な形に戻せという信号になります(変異N10で実証済み)。

もう1件の測定: shadow 実行は連鎖できない

assert_effect_chain_consistent は terrain を effect_ref.decision_ref と比較しますが、これは producer_decision_ref 以外のすべてのクラスで None です。一方 terrain の activation_decision_ref は必須・非空です。よって planned_shadow な effect には決して連鎖できません — そして AZ-06 の既定モードがまさにそれです(TransitionExecutor は live_enabled でない限り shadow_simulated)。

エラー文は「terrain は別の decision で activate された」と言いますが、実際には effect が decision を名指していません。

検証

571 passed, 8 skipped   (546 → 571)
変異 結果
期限を捏造して拒否しない CAUGHT
非適合参照を書き換えて通す CAUGHT (3)
isolation assertion を黙って1件に切る CAUGHT
stale が observed_fact を名乗る CAUGHT (2)
presentation id を無検査で prefix する CAUGHT
lifecycle 参照が state を無視する CAUGHT
欠落一覧から trace_id を外す CAUGHT (2)
欠落一覧を空で返す CAUGHT
Fabric が trace_id スロットを獲得 CAUGHT
pin が緩和後の文法へ動く CAUGHT (2) — 想定どおり赤くなる

最後の2件はインストール済み Fabric を書き換えて実行しました。

🤖 Generated with Claude Code

https://claude.ai/code/session_01SsboPSj6GyJju6mTXwHHjq


Generated by Claude Code

Fabric#15 は「Edge/Gadget/AZ-06 が**実際の** bounded effect を記述できる」と
いう受け入れ基準を持ったまま closed になっていた。誰も生産者を立てていない。
本変更はそれを実行し、結果を記録する。

runtime/effect_projection.py が、AZ-06 の既存の PresentedTerrainSnapshotV0 を
Fabric の PresentedTerrainRef に射影する。追加も選択も承認もしない。射影は
AZ-06 が既に確立した事実の描画であり、Edge の決定論アービタが唯一の決定・強制
権限であることは変わらない。

## 埋めずに拒否する

Fabric のレコードは AZ-06 が常には持たない事実を要求する。もっとも重いのが
expires_at で、Fabric は bounded を要求し、AZ-06 には宣言された期限が無いのが
普通である。ここで期限を捏造すれば、AZ-06 が時限を切っていない presentation
について「切った」と消費者に報告するレコードができ、しかもそれは valid になる。

  AZ-06 が持たない事実は既定値ではなく拒否である。

拒否は4種類: 開始時刻が無い / 期限が無い / isolation assertion が無い /
Fabric の単数スロットに収まらない複数の isolation assertion(黙って捨てれば
証拠が narrow になったことが誰にも見えない)。

## 欠落を毎回申告する

射影は「Fabric スロットに届かないローカル項目」19件を毎回返す。黙って欠落する
射影は、消費者が Fabric レコードを AZ-06 の観測の全体だと読み始める経路である。

特筆3件:
- trace_id — この family は他のすべてのレコードを trace で相関させるが、
  PresentedTerrainRef には trace スロットが無い
- synthetic_identity_refs / synthetic_credential_refs — Fabric#15 自身の
  候補フィールド一覧が名指しているが、出荷されたモデルには無い

## 生産者が立てられない2件

EffectObservation と OutcomeObservationEnvelope は AZ-06 のレコードである
(AZ-06 が materializer)。しかし両者は effect: 型の id を鍵にしており、
**シリーズのどこもそれを発行していない。** AZ-06 が受け取るのは
EnvironmentActivationDecision で、effect id を含まない。作れないのではなく、
作る対象が無い。テストで事実として固定した。

## 測定: 参照文法

現 pin では、AZ-06 が実際に発行する階層参照(surface:http:8080 など)は
typed ref を要求するすべてのスロットに拒否される。これが
Azazel-Fabric#48 を生んだ測定である。書き換えは採らない:
surface:http:8080 を surface:http-8080 に書き換えたものは、存在しない surface
への well-formed な参照になる。

このテストは **pin が動くと赤くなる**。緩和後の Fabric を pin した時点で、
参照を自然な形に戻せという信号になる。

## 検証

571 passed, 8 skipped (546 → 571)

| 変異 | 結果 |
|---|---|
| 期限を捏造して拒否しない | CAUGHT |
| 非適合参照を書き換えて通す | CAUGHT (3) |
| isolation assertion を黙って1件に切る | CAUGHT |
| stale が observed_fact を名乗る | CAUGHT (2) |
| presentation id を無検査で prefix する | CAUGHT |
| lifecycle 参照が state を無視する | CAUGHT |
| 欠落一覧から trace_id を外す | CAUGHT (2) |
| 欠落一覧を空で返す | CAUGHT |
| Fabric が trace_id スロットを獲得 | CAUGHT |
| pin が緩和後の文法へ動く | CAUGHT (2) — 想定どおり赤くなる |

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SsboPSj6GyJju6mTXwHHjq
@01rabbit
01rabbit marked this pull request as ready for review September 20, 2026 10:12
@01rabbit
01rabbit merged commit f9f48e3 into main Sep 20, 2026
10 checks passed
@01rabbit
01rabbit deleted the claude/zealous-edison-k5vt5j branch September 20, 2026 10:12
01rabbit pushed a commit to 01rabbit/Azazel-Edge that referenced this pull request Sep 20, 2026
Fabric#15 の effect_contracts は effect: 型 id を鍵にする。シリーズ全体を
実測したところ、**どのリポジトリもそれを発行していなかった。** そのため
EffectObservation と OutcomeObservationEnvelope は、どの製品が採用しても
生産者が存在しえなかった。materializer である Azazel-Deception は、
観測する対象を持てなかった(Azazel-Deception#46)。

連鎖の先頭はここに属する。DefensiveEffectRef は
authority_class = producer_decision_ref を持ち、Edge の決定論アービタが
シリーズ唯一の決定権限である。決定していない製品はそのクラスを名乗れない。

py/azazel_edge/outcome/effect_export.py が、アービタが既に作った
ActionExecutionReceipt を横断参照として描画する。決定も選択も強制もしない。
決定論経路はこのモジュールを import しない(テストで固定)。

## 埋めずに拒否する3件

**lease の無いアクション。** Fabric は expires_at を要求し、Edge の receipt
では省略可能である。期限を捏造すれば、Edge が時限を切っていない effect に
ついて「切った」と報告するレコードができる。

**ROUTE_CHANGE。** EffectClass に対応する値が無い。この enum は意図的に
小さく、「2製品が同じ effect について話せるように名付ける」ものであって
製品が作れる effect を網羅しない。近い値に寄せれば別の effect を記述する。

**UNKNOWN。** Fabric が未知を observe_only に落とすのは**消費者**が
fail-safe になるためである。生産者が同じことをすれば、識別できなかった
mechanism について observe_only を**主張**することになる。

## scope は不透明なハンドルとして渡す

Fabric はここに opaque typed ref を要求し、理由も述べている — provider
コマンドであってはならず、受信側が作用すべきアドレスであってもならない。
Edge の scope は match フィールドの map なので、その digest を publish する。
map は Edge ローカルに留まり、渡るのは Edge が解決でき受信側が作用できない
ハンドルである。

## effect id は execution を同定し、mechanism を同定しない

observed mechanism が後で訂正されたとき id が動けば、それまでに行われた
観測がすべて孤立する。id の入力は decision / action / execution の3つだけで
あることを直接固定した。

## 既存テストの誤検知を1件直した

test_nothing_on_the_deterministic_path_imports_this_export_surface は
ファイル本文の部分一致で shared_export の importer を探していた。本モジュール
が docstring で shared_export を引用した時点で誤検知した。**コメントで壊れる
境界検査は、コメントを消すことで回避される。** import を構文解析する形に
直した。

## 既存の失敗12件について

main 上でも同じ12件が失敗する。**本 PR は1件も増やしていない**(main と
branch の FAILED 集合が完全一致することを実測)。原因は bhusa_status.py が
gh(GitHub CLI)を subprocess で呼び、未インストール環境で FileNotFoundError
が伝播すること。--skip-github フラグは存在するが既定経路が劣化しない。
本 PR の範囲外なので触っていない。

## 検証

tests/test_outcome_effect_export.py 18 passed
tests 全体: 12 failed, 808 passed(12 は上記の既存失敗)

| 変異 | 結果 |
|---|---|
| lease 不在時に期限を捏造 | CAUGHT |
| ROUTE_CHANGE を近い class に割り当てる | CAUGHT |
| UNKNOWN を observe_only に落とす | CAUGHT (3) |
| scope をそのまま載せる | CAUGHT |
| effect_id が mechanism を含む | **最初は生存** → 入力3件を直接固定して捕捉 |
| 2つの mechanism が同じ class を名乗る | CAUGHT |
| authority_class を下げる | CAUGHT |

Refs 01rabbit/Azazel-Deception#46, 01rabbit/Azazel-Fabric#49

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SsboPSj6GyJju6mTXwHHjq
01rabbit added a commit to 01rabbit/Azazel-Edge that referenced this pull request Sep 20, 2026
Fabric#15 の effect_contracts は effect: 型 id を鍵にする。シリーズ全体を
実測したところ、**どのリポジトリもそれを発行していなかった。** そのため
EffectObservation と OutcomeObservationEnvelope は、どの製品が採用しても
生産者が存在しえなかった。materializer である Azazel-Deception は、
観測する対象を持てなかった(Azazel-Deception#46)。

連鎖の先頭はここに属する。DefensiveEffectRef は
authority_class = producer_decision_ref を持ち、Edge の決定論アービタが
シリーズ唯一の決定権限である。決定していない製品はそのクラスを名乗れない。

py/azazel_edge/outcome/effect_export.py が、アービタが既に作った
ActionExecutionReceipt を横断参照として描画する。決定も選択も強制もしない。
決定論経路はこのモジュールを import しない(テストで固定)。

## 埋めずに拒否する3件

**lease の無いアクション。** Fabric は expires_at を要求し、Edge の receipt
では省略可能である。期限を捏造すれば、Edge が時限を切っていない effect に
ついて「切った」と報告するレコードができる。

**ROUTE_CHANGE。** EffectClass に対応する値が無い。この enum は意図的に
小さく、「2製品が同じ effect について話せるように名付ける」ものであって
製品が作れる effect を網羅しない。近い値に寄せれば別の effect を記述する。

**UNKNOWN。** Fabric が未知を observe_only に落とすのは**消費者**が
fail-safe になるためである。生産者が同じことをすれば、識別できなかった
mechanism について observe_only を**主張**することになる。

## scope は不透明なハンドルとして渡す

Fabric はここに opaque typed ref を要求し、理由も述べている — provider
コマンドであってはならず、受信側が作用すべきアドレスであってもならない。
Edge の scope は match フィールドの map なので、その digest を publish する。
map は Edge ローカルに留まり、渡るのは Edge が解決でき受信側が作用できない
ハンドルである。

## effect id は execution を同定し、mechanism を同定しない

observed mechanism が後で訂正されたとき id が動けば、それまでに行われた
観測がすべて孤立する。id の入力は decision / action / execution の3つだけで
あることを直接固定した。

## 既存テストの誤検知を1件直した

test_nothing_on_the_deterministic_path_imports_this_export_surface は
ファイル本文の部分一致で shared_export の importer を探していた。本モジュール
が docstring で shared_export を引用した時点で誤検知した。**コメントで壊れる
境界検査は、コメントを消すことで回避される。** import を構文解析する形に
直した。

## 既存の失敗12件について

main 上でも同じ12件が失敗する。**本 PR は1件も増やしていない**(main と
branch の FAILED 集合が完全一致することを実測)。原因は bhusa_status.py が
gh(GitHub CLI)を subprocess で呼び、未インストール環境で FileNotFoundError
が伝播すること。--skip-github フラグは存在するが既定経路が劣化しない。
本 PR の範囲外なので触っていない。

## 検証

tests/test_outcome_effect_export.py 18 passed
tests 全体: 12 failed, 808 passed(12 は上記の既存失敗)

| 変異 | 結果 |
|---|---|
| lease 不在時に期限を捏造 | CAUGHT |
| ROUTE_CHANGE を近い class に割り当てる | CAUGHT |
| UNKNOWN を observe_only に落とす | CAUGHT (3) |
| scope をそのまま載せる | CAUGHT |
| effect_id が mechanism を含む | **最初は生存** → 入力3件を直接固定して捕捉 |
| 2つの mechanism が同じ class を名乗る | CAUGHT |
| authority_class を下げる | CAUGHT |

Refs 01rabbit/Azazel-Deception#46, 01rabbit/Azazel-Fabric#49


Claude-Session: https://claude.ai/code/session_01SsboPSj6GyJju6mTXwHHjq

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants