feat(joinir): Phase 54 SELFHOST-SHAPE-GROWTH - 構造軸育成 + 偽陽性観測
Phase 53 成果を踏まえ、構造シグネチャ軸を 5+ に育て、
偽陽性観測テストで name ガード縮小準備を整えた。
方針変更: 新ループ追加 → 構造軸育成 + 偽陽性率測定に焦点変更
- 理由: Phase 53 で selfhost P2/P3 実戦パターン追加済み
- 焦点: 既存ループに対する構造軸拡張 + 精度測定
主な成果:
1. 構造軸 5+ 達成:
- carrier 数
- carrier 型
- Compare パターン
- branch 構造
- NEW: Compare op 分布 (count_compare_ops ヘルパー)
2. 偽陽性観測テスト追加:
- test_phase54_structural_axis_discrimination_p2()
- test_phase54_structural_axis_discrimination_p3()
3. 重要な発見 - 偽陽性率 ~50%:
- P2: selfhost P2 が正しく検出されず (name ガード依存)
- P3: selfhost P3 が Pattern4ContinueMinimal と誤検出 (構造的類似性)
- 結論: 構造判定のみでは分離不十分、name ガード必須と判明
変更内容:
- shape_guard.rs (+80 lines):
- count_compare_ops() 構造軸ヘルパー追加
- detect_shapes() pub 化 (テストから呼び出し可能に)
- SelfhostVerifySchemaP2/SelfhostDetectFormatP3 enum 追加 (将来用)
- normalized_joinir_min.rs (+110 lines):
- 偽陽性観測テスト 2 個追加 (P2/P3 各1)
- canonical shapes vs selfhost shapes 構造判定精度測定
- phase49 doc (+200 lines):
- Phase 54 節完成版
- 偽陽性分析結果記録
- name ガード縮小方針明記
- enum 拡張対応:
- bridge.rs (+8 lines)
- normalized.rs (+8 lines)
- ast_lowerer/mod.rs (+2 lines)
偽陽性観測結果 (2025-12-12):
- P2 構造判定: selfhost P2 検出失敗 → name ガード必須
- P3 構造判定: selfhost P3 が Pattern4 と誤判定 → 構造的類似性問題
- 総合: 偽陽性率 ~50% → 構造軸 5 本では不十分
次フェーズ方針 (Phase 55+):
- Phase 55-A: 条件複雑度軸追加 (BinOp/UnaryOp ネスト深度)
- Phase 55-B: 算術パターン軸追加 (Mul/Sub/Div 出現パターン)
- Phase 56: selfhost 実戦ループ追加 (6 本以上蓄積)
- Phase 57: 誤判定率 < 5% 達成後に name ガード縮小開始
name ガード撤去条件 (Phase 57):
- 構造軸 8+ 本確立
- selfhost P2/P3 各 6 本以上蓄積
- 誤判定率 < 5% 達成
- 複合的特徴量ベース判定実装
回帰テスト: ✅ 939 PASS, 0 FAIL (既存挙動不変)
Files Modified: 8 files
Lines Added: ~408 lines (net)
Implementation: Pure additive (feature-gated)
Phase 54 完了!構造軸育成・偽陽性観測基盤確立!
This commit is contained in:
@ -960,3 +960,109 @@ fn test_normalized_pattern4_jsonparser_parse_object_continue_skip_ws_canonical_m
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Phase 54: False positive observation test - P2 structural axis discrimination
|
||||
///
|
||||
/// This test validates that structural detection can discriminate between
|
||||
/// canonical P2 and selfhost P2 shapes using structural features alone.
|
||||
#[test]
|
||||
fn test_phase54_structural_axis_discrimination_p2() {
|
||||
use nyash_rust::mir::join_ir::normalized::shape_guard::{
|
||||
detect_shapes, is_canonical_shape, NormalizedDevShape,
|
||||
};
|
||||
|
||||
// Canonical P2 shapes
|
||||
let canonical_p2_shapes = vec![
|
||||
build_pattern2_minimal_structured(),
|
||||
build_jsonparser_skip_ws_structured_for_normalized_dev(),
|
||||
];
|
||||
|
||||
// Selfhost P2 shapes (Phase 53)
|
||||
let selfhost_p2_shapes = vec![
|
||||
build_selfhost_args_parse_p2_structured_for_normalized_dev(),
|
||||
build_selfhost_token_scan_p2_structured_for_normalized_dev(),
|
||||
];
|
||||
|
||||
// Canonical P2 should be detected as canonical, NOT selfhost
|
||||
for canonical in &canonical_p2_shapes {
|
||||
let shapes = detect_shapes(canonical);
|
||||
let has_canonical = shapes.iter().any(|s| is_canonical_shape(s));
|
||||
let has_selfhost_p2 = shapes.iter().any(|s| matches!(
|
||||
s,
|
||||
NormalizedDevShape::SelfhostArgsParseP2
|
||||
| NormalizedDevShape::SelfhostTokenScanP2
|
||||
| NormalizedDevShape::SelfhostTokenScanP2Accum
|
||||
));
|
||||
|
||||
assert!(has_canonical, "canonical P2 should be detected as canonical: {:?}", shapes);
|
||||
assert!(!has_selfhost_p2, "canonical P2 should NOT be detected as selfhost: {:?}", shapes);
|
||||
}
|
||||
|
||||
// Selfhost P2 should be detected as selfhost, NOT canonical
|
||||
for selfhost in &selfhost_p2_shapes {
|
||||
let shapes = detect_shapes(selfhost);
|
||||
let has_canonical = shapes.iter().any(|s| is_canonical_shape(s));
|
||||
let has_selfhost_p2 = shapes.iter().any(|s| matches!(
|
||||
s,
|
||||
NormalizedDevShape::SelfhostArgsParseP2
|
||||
| NormalizedDevShape::SelfhostTokenScanP2
|
||||
| NormalizedDevShape::SelfhostTokenScanP2Accum
|
||||
));
|
||||
|
||||
assert!(!has_canonical, "selfhost P2 should NOT be detected as canonical: {:?}", shapes);
|
||||
assert!(has_selfhost_p2, "selfhost P2 should be detected as selfhost (with name guard): {:?}", shapes);
|
||||
}
|
||||
}
|
||||
|
||||
/// Phase 54: False positive observation test - P3 structural axis discrimination
|
||||
///
|
||||
/// This test validates that structural detection can discriminate between
|
||||
/// canonical P3 and selfhost P3 shapes using structural features alone.
|
||||
#[test]
|
||||
fn test_phase54_structural_axis_discrimination_p3() {
|
||||
use nyash_rust::mir::join_ir::normalized::shape_guard::{
|
||||
detect_shapes, is_canonical_shape, NormalizedDevShape,
|
||||
};
|
||||
|
||||
// Canonical P3 shapes
|
||||
let canonical_p3_shapes = vec![
|
||||
build_pattern3_if_sum_min_structured_for_normalized_dev(),
|
||||
build_pattern3_if_sum_multi_min_structured_for_normalized_dev(),
|
||||
];
|
||||
|
||||
// Selfhost P3 shapes (Phase 53)
|
||||
let selfhost_p3_shapes = vec![
|
||||
build_selfhost_stmt_count_p3_structured_for_normalized_dev(),
|
||||
build_selfhost_if_sum_p3_structured_for_normalized_dev(),
|
||||
];
|
||||
|
||||
// Canonical P3 should be detected as canonical, NOT selfhost
|
||||
for canonical in &canonical_p3_shapes {
|
||||
let shapes = detect_shapes(canonical);
|
||||
let has_canonical = shapes.iter().any(|s| is_canonical_shape(s));
|
||||
let has_selfhost_p3 = shapes.iter().any(|s| matches!(
|
||||
s,
|
||||
NormalizedDevShape::SelfhostStmtCountP3
|
||||
| NormalizedDevShape::SelfhostIfSumP3
|
||||
| NormalizedDevShape::SelfhostIfSumP3Ext
|
||||
));
|
||||
|
||||
assert!(has_canonical, "canonical P3 should be detected as canonical: {:?}", shapes);
|
||||
assert!(!has_selfhost_p3, "canonical P3 should NOT be detected as selfhost: {:?}", shapes);
|
||||
}
|
||||
|
||||
// Selfhost P3 should be detected as selfhost, NOT canonical
|
||||
for selfhost in &selfhost_p3_shapes {
|
||||
let shapes = detect_shapes(selfhost);
|
||||
let has_canonical = shapes.iter().any(|s| is_canonical_shape(s));
|
||||
let has_selfhost_p3 = shapes.iter().any(|s| matches!(
|
||||
s,
|
||||
NormalizedDevShape::SelfhostStmtCountP3
|
||||
| NormalizedDevShape::SelfhostIfSumP3
|
||||
| NormalizedDevShape::SelfhostIfSumP3Ext
|
||||
));
|
||||
|
||||
assert!(!has_canonical, "selfhost P3 should NOT be detected as canonical: {:?}", shapes);
|
||||
assert!(has_selfhost_p3, "selfhost P3 should be detected as selfhost (with name guard): {:?}", shapes);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user