Skip to content

feat: hyp-001 blocked_by フィールド — 昇格停止装置の構造的固定 - #17

Open
codowave wants to merge 2 commits into
mainfrom
claude/hyp-001-blocked-by-field
Open

feat: hyp-001 blocked_by フィールド — 昇格停止装置の構造的固定#17
codowave wants to merge 2 commits into
mainfrom
claude/hyp-001-blocked-by-field

Conversation

@codowave

Copy link
Copy Markdown
Owner

変更内容

問題

「固定文」(hyp-001 remains candidate until Yanase translation of DLW 55/56 is directly verified)をメッセージに残すだけでは、セッションを跨ぐと風化する。次のセッションの AI が文脈を持たない状態で hyp-001 を進行させるリスクがある。

解決策

固定文を 機械可読な frontmatter フィールド に移動し、mechanism_mapping の出力に反映させる。

research/hypotheses/hyp-001.md

blocked_by:
  - id: DLW-55-56-yanase-verification
    description: "柳瀬訳 DLW 55/56 の直接照合が未完了"
    blocks: promotion_to_verified
    condition: "verified:true かつ confirmed_reference に昇格するまで"
    note: "Web経由の原文取得全滅(403)。書架での実物確認のみ有効。"

research_os/tasks/mechanism_mapping.py

run()blocked_by を読み込み、promotion_to_verified をブロックする blocker が存在する場合、promotion_decision に以下を付与:

promotion_decision:
  from: candidate
  to: candidate
  ...
  blocked_by:
    - DLW-55-56-yanase-verification
  block_note: 柳瀬訳 DLW 55/56 の直接照合が未完了

昇格解除条件

hyp-001.mdblocked_by リストから該当エントリを削除するか、blocks フィールドを除去することで解除される。ロックの解除も宣言的に行う。


背景

削除ではなく降格、メッセージではなくデータ構造——観測系の汚染履歴を保存し、進行を構造的に止める設計。

https://claude.ai/code/session_017WKYFbVsWhWZA3M8Jc1eKs


Generated by Claude Code

- hyp-001.md frontmatter に blocked_by: [{id: DLW-55-56-yanase-verification, ...}] を追加
  - blocks: promotion_to_verified(candidate→verified の昇格をブロック)
  - condition: 柳瀬訳 DLW 55/56 の直接照合が完了するまで
- mechanism_mapping.py: blocked_by を読み込み、promotion_decision に
  blocked_by / block_note フィールドを付与
  - verified への昇格が検討される状況でも、blockerが残っていれば警告を出力

セッション跨ぎで固定文が風化するリスクへの対処:
固定文をノートに残すだけでなく、frontmatter の機械可読フィールドに移動し、
promotion_decision の出力に反映させる構造にした。

https://claude.ai/code/session_017WKYFbVsWhWZA3M8Jc1eKs

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a blocking mechanism to prevent hypotheses from being promoted to a verified status if they have unresolved blockers. Specifically, it adds a blocked_by field to hyp-001.md and implements the blocking logic in mechanism_mapping.py. Feedback on the changes highlights a potential TypeError crash if the blocked_by field is empty (parsed as None) in the YAML file, and suggests defensive coding practices to safely handle the parsed data structure.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread research_os/tasks/mechanism_mapping.py Outdated
Comment on lines +361 to +373
blocked_by = hypothesis.get("blocked_by", [])
promotion_blockers = [
b for b in blocked_by
if b.get("blocks") == "promotion_to_verified"
]
if promotion_blockers and promotion.get("to") not in (
PromotionTarget.STAY_EXPLORATION.value,
PromotionTarget.REJECT.value,
):
promotion["blocked_by"] = [b["id"] for b in promotion_blockers]
promotion["block_note"] = "; ".join(
b.get("description", b["id"]) for b in promotion_blockers
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

YAMLのパースにおいて、blocked_by: のようにキーのみが定義されて値が空(null)の場合、hypothesis.get("blocked_by", [])None を返します。この場合、後続のリスト内包表記で TypeError: 'NoneType' object is not iterable が発生してクラッシュする危険性があります。

また、blocked_by の各要素が辞書型(dict)であることを保証し、かつ "id" キーが存在しない場合の KeyError を防ぐために、安全なゲッター(.get())を使用し、型チェックを行う防衛的コーディングを推奨します。

    blocked_by = hypothesis.get("blocked_by") or []
    if not isinstance(blocked_by, list):
        blocked_by = []
    promotion_blockers = [
        b for b in blocked_by
        if isinstance(b, dict) and b.get("blocks") == "promotion_to_verified"
    ]
    if promotion_blockers and promotion.get("to") not in (
        PromotionTarget.STAY_EXPLORATION.value,
        PromotionTarget.REJECT.value,
    ):
        promotion["blocked_by"] = [b.get("id") for b in promotion_blockers if b.get("id")]
        promotion["block_note"] = "; ".join(
            b.get("description") or b.get("id") or "unknown" for b in promotion_blockers
        )

YAML で `blocked_by:` のみ定義されると None に parse される。
`hypothesis.get("blocked_by", [])` は None を返すため
後続のリスト内包表記で TypeError が発生する。

- `hypothesis.get("blocked_by") or []` で None を空リストに変換
- `isinstance(blocked_by, list)` チェックを追加
- `isinstance(b, dict)` チェックで非辞書要素を除外
- `b["id"]` を `b.get("id")` に置換して KeyError を防止
- `block_note` の fallback を "unknown" に統一

https://claude.ai/code/session_017WKYFbVsWhWZA3M8Jc1eKs
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