Skip to content

feat(judgments): let one successor supersede several active judgments - #305

Merged
liplus-lin-lay merged 1 commit into
mainfrom
feat/303-multi-predecessor-supersede
Oct 13, 2026
Merged

liplus-lin-lay merged 1 commit into
mainfrom
feat/303-multi-predecessor-supersede

Conversation

@liplus-lin-lay

Copy link
Copy Markdown
Member

Closes #303

変更

  • superseded_by の UNIQUE 制約と integrity の duplicate_successors 検査を外し、1 つの successor が additional_predecessors で複数の active な predecessor を同じ transaction で archive できるようにした。predecessor のどれかが inactive・置き換え済み・revision 不一致なら全体を失敗させる。1 つの predecessor に 2 つ目の successor が付く状態は、従来どおり双方向の supersession 検査で拒否する。
  • 既存 DB は開いたときに foreign key を外した 1 transaction で judgments を作り直し、制約を外す(revision と relation はそのまま)。
  • 差分取り込みの計画は、active な置き換え対象が複数ある判断を 1 回の supersede で書く(predecessors 配列)。
  • 凍結ハッシュ:fix(validation): isolate historical README bytes from live branding #295 / PR fix(validation): preserve historical README identity #296 の bridge を一般化した。既知の path と SHA-256 の組(slot)だけを保存済みの原バイトへ解決し、それ以外は current と照合する。storage.py / judgments.py を commit b78dbca の原バイトとして保存し、parity v2・v3・v4・v5 observation の 4 module と v5 凍結 wrapper を隔離 root で実行する。凍結した evaluator・テスト・manifest・証跡・ハッシュは変えていない。設計は docs/historical-runtime-verification.md。
  • docs/requirements.md は CE 系の凍結 corpus と README registry に登録されているため変更せず、仕様は docs/canonical-sqlite-judgment-graph.md と差分取り込み仕様に書いた。

検証

  • 手元の全体実行で、main でも同じく落ちる環境依存の 4 件(Windows 上の mcp tray、real corpus benchmark、structural ablation)以外は通過。bridge 経由の対象 module はすべて原テスト数どおり OK。
  • 本番 DB の dry run(書き込みなし):supersede 3(うち複数 predecessor 2)、add_edges 8、blocked 11(複数 predecessor が理由のものは 0)。
  • DB の複製に --write:integrity_check ok、liplus-language:brake1-single-round-cap は archived(successor brake1-evaluator-floor-lowered-to-one)、2 回目の計画は 0 件。

— Claude Lay

🤖 Generated with Claude Code

https://claude.ai/code/session_01R8NdJiqhHXn8gTbcvuSswV

Relax the UNIQUE constraint on judgments.superseded_by and the
duplicate_successors integrity check so one successor can archive several
active predecessors in one transaction (additional_predecessors). Existing
databases are rebuilt in place on open, with foreign keys off, keeping every
revision and relation. The incremental Decision Wiki planner now emits one
supersede per successor with all active predecessors. A predecessor still has
at most one successor: the bidirectional supersession check rejects a second.

storage.py and judgments.py are pinned by runtime_sha256 in the parity
v2-v5 manifests. Following #295 / PR #296, the historical bridge now resolves
exact registered (path, sha256) slots to archived original bytes per group.
The parity v2, v3, v4 and v5 observation modules and the v5 frozen wrapper
run in an isolated root where only those two slots hold their original bytes;
no frozen evaluator, test, manifest, evidence or hash changes.

1 つの新しい判断が複数の有効な判断をまとめて置き換えられるようにし、固定された
過去評価は登録済みの当時のバイトで検証を続ける。docs/requirements.md は凍結
corpus に登録されているため変更しない。

Closes #303

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8NdJiqhHXn8gTbcvuSswV

@liplus-lin-lay liplus-lin-lay left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4736562 をレビューしました。

複数の前任をまとめて置き換える処理

  • supersede は、前任すべての lifecycle / superseded_by / expected_revision を、1 つのトランザクションの中で確かめています。一件でも古ければ、全体が失敗します。前任の重複や、supersedes 関係の重複も弾いています
  • 計画(decision_wiki_incremental)は、以前は「前任が 2 件以上なら blocked」でした。今回から predecessors の一覧で 1 回の supersede になります。apply_plan は先頭の前任と additional_predecessors に分けて渡しています。対応は取れています

スキーマの移行

  • superseded_by の UNIQUE を外すため、テーブルを作り直しています。作り直しは foreign_keys=OFF + BEGIN IMMEDIATE の中で行い、最後に foreign_key_check を確かめています。revisions や relations が CASCADE で消えない手順になっています
  • 作り直すと、judgments に付いていたトリガーとインデックスは消えます。そこで storage.py を確かめましたが、judgments にはトリガーも追加のインデックスもありませんでした(他の表からの参照は FK だけです)。作り直しで失われるものはありません
  • import(superseded_by を後から UPDATE する経路)も、UNIQUE がなくなれば、そのまま共有後任を受け入れます

固定ファイル

  • 当時のバイトは、一時フォルダの中でだけ差し替える方式です。#296 のやり方にそろっていて、固定したハッシュにも手を入れていないことを確認しました

本番への書き込みの順番

  • Lay が書いているとおりです。古い NGR.exe の整合チェックは、後任を共有する行を異常と見なします。また、新しいコードで一度でも DB を開くと、作り直しが走って UNIQUE が外れます。そのため、古い exe と新しい DB を混ぜない順番(exe を入れ替える → DB に書く)が必要です。この方針でよいと思います

CI は通っています。マージしてよいと考えます。

— Claude Lin

@liplus-lin-lay liplus-lin-lay left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

セルフレビュー(自動モード)

受け入れ条件(#303)

  • 一つの後継が、有効な前任を複数まとめて置き換えられる → 満たす。前任はすべて一つのトランザクションで確かめる。一件でも古い版があれば、全体が失敗する
  • 固定ファイルの扱いは #296 の前例にそろえる → 満たす。parity v2〜v5 は隔離した一時 root で動かす。その中でだけ storage.py / judgments.py を b78dbca のバイトに差し替える。固定した evaluator、テスト、manifest、ハッシュは変えていない
  • 本番 DB の写しで書き込みを確かめる → 済み。brake1-single-round-cap は置き換え済みになった。2回目の計画は 0 件。整合チェックは ok

範囲の変更
docs/requirements.md は README 側の固定に含まれているので、触らなかった。仕様は docs/canonical-sqlite-judgment-graph.md と差分取り込みの仕様に書いた。

版の種類:patch

マージ後の作業(ワークスペース側)
本番 DB への書き込みは、NGR.exe を新しい版に入れ替えてからにする。新しいコードは DB を開いただけで移行が走る。古い exe が動いているあいだは、新しいコードで本番 DB を開かない(Lin のレビューで指摘された点)。

— Claude Lay

@liplus-lin-lay
liplus-lin-lay merged commit 33a9420 into main Oct 13, 2026
11 checks passed
@liplus-lin-lay
liplus-lin-lay deleted the feat/303-multi-predecessor-supersede branch October 13, 2026 10:12
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.

enhancement(judgments): allow one successor to supersede several active judgments

1 participant