Kkemeng1v1.6.2 SW.3.3 dev 域活体接线探针交付(ar 批令 2026-09-28「即启」同日兑现, 主线域件 kernel/插件仓增量零触发): examples/m2_subscribe_probe.rs 三 K 件 pub API 只读消费——kernel v1.4.4 Registry::mount+watch_status 原语(K-4 零增量定谳面, emit_status 与 Loader::mount_rows 同通路)+xwtui v0.3.8 plugin_watch 通道/attach/run_disposer(件③ 最小增量载荷 {entryId,phase,at} R4 结构体级)+xwmgmt v0.1.5 audit_cmd::append_plugin_event(件② M-e 六字段域写点); [dev-dependencies] 承载=产品 bin 依赖图零增量(lock 仅 +6 行 dev-deps 边, 零新包零新源, DUAL=1×6 复证); m2-spec §3 判据全咬合(S33a-d, evidence/M2_walkthrough_20260928_043928.log): 增量流 4 条逐字留痕(Loading→Active)+断线 run_disposer 零增量(即时性降级非失真)+重连增量恢复+全量对齐块 4 行全 Active(Loader 唯一权威, App::align_plugin_state 同构载荷)+M-e 联立在线装载留痕随审计时间线(4 条 load 事件 revision 单调 0..3, SW.4.1 后半 (b) 承继面实证); 拓扑发现申报 ar 候裁: 产品 TUI 运行链无活体 kernel::Registry(App::new 吞 runtime dev_app.rs:257+BootConfig 两字段无钩子位 boot.rs:33-36)——产品装配点 attach=kernel-host 源增量=新 tag(K-chain 件④ 形态)非本批零触发面; harness S33 段集成(探针沙箱隔离+timeout 短路); SW.3.3 勾选, CLI --watch 不做(1c 定谳⑥候下版)
1c690946创建于 9月28日历史提交
//! v1.6.2 SW.3.3 dev 域活体接线探针(ar 批令 2026-09-28「SW.3.3 产品面消费接线批令: 即启」)。
//!
//! 主线域件——kernel/插件仓增量零触发,三 K 件 pub API 只读消费:
//! - 件① kernel v1.4.4@7c3dcac:`Registry::mount`+`watch_status` 订阅原语(K-4 零增量定谳面,
//!   与 Loader::mount_rows 同一 emit_status 通路)
//! - 件③ xwtui v0.3.8@8720ad2:`plugin_watch::{plugin_status_channel, attach, run_disposer}`
//!   + `PluginStateEvent` 最小增量载荷 {entryId, phase, at}(R4 零第二份生命周期真相)
//! - 件② xwmgmt v0.1.5@2279510e:`audit_cmd::append_plugin_event`(M-e 六字段域写点,
//!   SW.4.1 后半 (b) 承继面——在线装载留痕随审计时间线)
//!
//! 判据(m2-consumer-spec §3): 启停期增量事件逐条留痕 + 断线重连全量对齐输出。
//! 拓扑注记(随批申报 ar): 产品 TUI 运行链现无活体 kernel::Registry(App::new 吞 runtime、
//! BootConfig 仅 version/worker_threads 两字段无钩子位; dev_app.rs:257 装配点 attach 须
//! kernel-host 源增量=新 tag)——本探针证订阅链活体+载荷纪律+审计联立, 产品装配点接线挂
//! K-chain 候裁。
//!
//! 用法:
//!   cargo build --release --example m2_subscribe_probe
//!   ./target/release/examples/m2_subscribe_probe [sandbox_dir]
//!   (审计落盘进 sandbox_dir/.xwcode/operation_audit.jsonl, 缺省=系统临时目录)
use std::sync::Arc;

use kernel::{MountSpec, Registry};
use xw_mgmt::audit_cmd::append_plugin_event;
use xwproviders::operation_audit;
use xwtui::plugin_watch::{self, PluginStateEvent};

fn drain(rx: &mut plugin_watch::PluginStatusRx) -> Vec<PluginStateEvent> {
    let mut out = Vec::new();
    while let Ok(ev) = rx.try_recv() {
        out.push(ev);
    }
    out
}

fn fail(msg: &str) -> ! {
    eprintln!("[probe] FAIL: {msg}");
    std::process::exit(1);
}

fn main() {
    let cwd =
        std::env::args().nth(1).map(std::path::PathBuf::from).unwrap_or_else(std::env::temp_dir);

    let reg = Arc::new(Registry::new());
    let rt = tokio::runtime::Builder::new_current_thread()
        .enable_all()
        .build()
        .expect("tokio current_thread rt");

    // ── S33a 增量流活体: watch_status 订阅→mount→{entryId,phase,at} 逐条 ─────────
    println!("## S33a 增量流(订阅→mount→最小增量逐条; emit_status 与 Loader::mount_rows 同通路)");
    let (tx1, mut rx1) = plugin_watch::plugin_status_channel();
    let d1 = plugin_watch::attach(&reg, tx1);
    let (uid1, uid2) = rt.block_on(async {
        let u1 = reg
            .clone()
            .mount(MountSpec { plugin_name: "probe-p1".into(), ..Default::default() })
            .await
            .expect("mount probe-p1");
        let u2 = reg
            .clone()
            .mount(MountSpec { plugin_name: "probe-p2".into(), ..Default::default() })
            .await
            .expect("mount probe-p2");
        (u1, u2)
    });
    let evs_a = drain(&mut rx1);
    if evs_a.is_empty() {
        fail("S33a: 订阅在位但 mount 零增量——watch→通道链断裂");
    }
    for ev in &evs_a {
        println!(
            "  Δ [{}] {}  载荷={{entryId: {}, phase: {}, at: {}}}",
            ev.at,
            ev.message(),
            ev.entry_id,
            ev.phase,
            ev.at
        );
    }
    for name in ["probe-p1", "probe-p2"] {
        if !evs_a.iter().any(|e| e.entry_id == name && e.phase == "Active") {
            fail(&format!("S33a: {name} 未达 Active 终相(NoopPlugin apply 应即时激活)"));
        }
    }
    println!(
        "  判读: {} 条增量逐条留痕, p1/p2 终相 Active ✓(载荷三字段结构体级, from/error/drain_timeout 不携带=R4)",
        evs_a.len()
    );

    // ── S33b 断线实证: run_disposer → 后续 mount 零增量(即时性降级非失真)─────────
    println!("## S33b 断线(run_disposer→后续 mount 零增量; R4 即时性降级非失真)");
    plugin_watch::run_disposer(d1);
    let uid3 = rt.block_on(async {
        reg.clone()
            .mount(MountSpec { plugin_name: "probe-p3".into(), ..Default::default() })
            .await
            .expect("mount probe-p3")
    });
    let evs_b = drain(&mut rx1);
    if !evs_b.is_empty() {
        fail(&format!("S33b: dispose 后仍收到 {} 条增量——断线语义失守", evs_b.len()));
    }
    println!("  判读: dispose 后 mount probe-p3(uid={uid3})增量=0 条 ✓(断线=即时性降级, 状态真相无损)");

    // ── S33c 重连+全量对齐: re-attach→增量恢复+权威快照对齐块(Loader 唯一权威)──
    println!(
        "## S33c 重连全量对齐(re-attach→增量恢复→全量对齐块, App::align_plugin_state 同构载荷)"
    );
    let (tx2, mut rx2) = plugin_watch::plugin_status_channel();
    let d2 = plugin_watch::attach(&reg, tx2);
    let uid4 = rt.block_on(async {
        reg.clone()
            .mount(MountSpec { plugin_name: "probe-p4".into(), ..Default::default() })
            .await
            .expect("mount probe-p4")
    });
    let evs_c = drain(&mut rx2);
    if evs_c.is_empty() {
        fail("S33c: re-attach 后增量未恢复——重连链断裂");
    }
    println!(
        "  重连后增量 {} 条恢复 ✓({})",
        evs_c.len(),
        evs_c.iter().map(|e| e.message()).collect::<Vec<_>>().join("; ")
    );
    // 全量对齐块: 权威快照=registry 现态直读(phase_of 逐 uid), 载荷形=App::align_plugin_state
    // 入参同构(App 面 Event Pane 渲染=km t5/drain 红侧已测, 本探针证载荷流+行格式)。
    let mounted: [(&str, u64); 4] =
        [("probe-p1", uid1), ("probe-p2", uid2), ("probe-p3", uid3), ("probe-p4", uid4)];
    let rows: Vec<PluginStateEvent> = mounted
        .iter()
        .map(|(name, uid)| PluginStateEvent {
            entry_id: (*name).into(),
            phase: reg
                .phase_of(*uid)
                .map(|p| format!("{p:?}"))
                .unwrap_or_else(|| "<无 fiber>".into()),
            at: plugin_watch_iso_now(),
        })
        .collect();
    println!("  plugin state 全量对齐({} 行, Loader 唯一权威)", rows.len());
    for r in &rows {
        println!("    [{}] {}", r.at, r.message());
    }
    if rows.iter().any(|r| r.phase != "Active") {
        fail("S33c: 全量对齐快照存在非 Active 行——phase_of 与 mount 终相不一致");
    }
    println!("  判读: 对齐块 4 行全 Active ✓(不覆盖不静默, 权威重同步语义)");
    plugin_watch::run_disposer(d2);

    // ── S33d M-e 联立审计留痕: 在线装载事件→审计时间线(SW.4.1 后半 (b) 承继面)──
    println!("## S33d M-e 联立(在线装载留痕随审计时间线; 六字段域, source=tui 运行态面)");
    for (i, (name, uid)) in mounted.iter().enumerate() {
        append_plugin_event(
            &cwd,
            "load",
            name,
            i as u64,
            "tui",
            serde_json::json!({ "phase": "Active", "fiber_uid": uid }),
        );
    }
    let path = operation_audit::default_path(&cwd);
    let events = operation_audit::read_events(&path)
        .unwrap_or_else(|e| fail(&format!("S33d: 审计回读失败: {e}")));
    let plugin_domain = events
        .iter()
        .filter(|e| e.payload.get("domain").and_then(|d| d.as_str()) == Some("plugin"))
        .count();
    if plugin_domain != mounted.len() {
        fail(&format!(
            "S33d: 审计 plugin 域 {} 条 ≠ 装载 {} 条——在线留痕缺口",
            plugin_domain,
            mounted.len()
        ));
    }
    println!(
        "  判读: {} 条 load 事件落审计时间线(domain=plugin 六字段域, revision 单调 0..{})✓",
        plugin_domain,
        mounted.len() - 1
    );
    println!("  时间线回读(operation_audit::print_timeline):");
    operation_audit::print_timeline(&path, None);

    println!("[probe] S33a-d 全绿——SW.3.3 订阅链活体+载荷纪律+断线/重连/对齐+M-e 联立实证");
}

// ISO 8601 时刻戳对齐面——载荷 at 字段由 plugin_watch handler 收包时刻生成(km std-only
// Hinnant civil 实现未导出 pub fn), 本探针对齐行用标准库秒级 UTC 形(观测元数据, 非状态机
// 字段; 与载荷 at 语义同级不同源, 不入对齐纪律判据)。
fn plugin_watch_iso_now() -> String {
    let d = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default();
    format!("{}s UTC", d.as_secs())
}