diff --git a/src/platforms/feishu/mod.rs b/src/platforms/feishu/mod.rs index d3b2a20..8589a04 100644 --- a/src/platforms/feishu/mod.rs +++ b/src/platforms/feishu/mod.rs @@ -306,18 +306,21 @@ fn escape_feishu_markdown(text: &str) -> String { /// Builds a schema-2.0 interactive card: `config.update_multi:true`, a /// markdown body element (fixed `element_id:"main_text"`, escaped text), and -/// — when present — one `"action"` element per button row, per -/// `docs/feishu-adapter-plan.md` §2c outbound decision 2. The exact button -/// element wrapper (`tag:"action"` with a nested `"actions"` array) is this -/// adapter's own choice: the plan pins ONLY the `behaviors`/`value.cb` -/// shape, not the surrounding container, so this is the one place protocol -/// shape was inferred rather than verified — flagged in the task report. +/// — when present — one `column_set` element per button row (one column per +/// button), per `docs/feishu-adapter-plan.md` §2c outbound decision 2. The +/// plan pins ONLY the `behaviors`/`value.cb` shape, not the surrounding +/// container — the container is this adapter's choice, verified live. /// -/// Schema 2.0 nests `elements` under `body` — a TOP-LEVEL `elements` key is -/// the v1 location and the real API rejects it with -/// `200621 parse card json err: unknown property "elements" at path []` -/// (caught live in the 2026-07-15 real-device e2e; the wiremock tests can't -/// see this because they don't validate Feishu's card schema). +/// Both container choices here were dictated by the REAL API in the +/// 2026-07-15 real-device e2e (the wiremock tests can't see this because +/// they don't validate Feishu's card schema): +/// - `elements` must nest under `body` — the v1 top-level location is +/// rejected with `200621 parse card json err: unknown property +/// "elements" at path []`. +/// - the v1 `tag:"action"` row container is GONE in schema 2.0 — rejected +/// with `200861 cards of schema V2 no longer support this capability: +/// unsupported tag action`. Button rows are laid out with `column_set` +/// (a "weighted" column per button) instead. fn build_card(text: &str, buttons: Option<&[Vec