---
name: feedback_workflow_fanout_reliability
description: Workflow fan-out parallelism thật nhưng return kém (empty-return); S73 chốt nguyên-nhân = SCHEMA-FORCE (R1 ép-schema 1/4 lane vs R2 free-text 2/3) → review/verify fan-out dùng free-text/hmw KHÔNG ép-schema; verify-heavy vẫn em-main self-gate; mode-ON lệch mandate phải surface-before-deviate
metadata: 
  node_type: memory
  type: feedback
  originSessionId: b036d4a2-cde7-4ef1-91d8-c93e7092ded9
---

**S65 (2026-06-16) chạy Workflow fan-out THẬT lần đầu** (`pe-hoso-link-rename-pro`: BE ∥ FE → review barrier) sau khi anh hỏi "sao không workflow fan-out ra?" (HMW-mode ON, H6.1 governed-ultracode).

**Kết quả thật (data, không lý thuyết):**
- ✅ **Parallelism hoạt động:** BE (`src/Backend`) ∥ FE (`fe-user`+`fe-admin`) file-disjoint chạy đồng thời, cả 2 đẻ việc ĐÚNG trên disk (migration HoSoLink + mục E + rename).
- ⚠️ **2/3 agent (FE-implementer + reviewer-stage) return RỖNG** (`""`, die-empty #53) — việc LANDED trên disk nhưng mất return-message → em main recover-from-disk + self-gate (và chính lúc tự gác mới **bắt được badge "DỰ TRÙ PRO" sót rename**).
- ❌ **reviewer-STAGE bên trong workflow cũng chết-rỗng** → verify-heavy task em main VẪN phải tự gác, workflow KHÔNG đỡ được khâu review.

**Why:** harness này vốn có vấn đề agent-return-rỗng (#53); gói nhiều agent vào 1 workflow = nhân xác suất dính. Và Workflow `hmw.js` chạy SCRIPT tất-định — KHÔNG chèn `AskUserQuestion` giữa chừng được.

**How to apply:**
- **Workflow fan-out hợp khi:** task đã-chốt no-decision · nhiều việc ĐỘC LẬP song song · KHÔNG cần verify sâu từng output (research / sweep / generate-N-variants / migrate-N-sites).
- **Spawn lẻ (hoặc em-main solo) hợp khi:** vừa-làm-vừa-hỏi (workflow không pause hỏi anh được) · **verify-heavy prod task** (reviewer-stage không tin được → tự gác = tương đương, lại đỡ phải recover).
- Workflow KHÔNG miễn cho em main việc self-gate prod-bound change. **Chọn công cụ theo bản chất task, KHÔNG mặc định một kiểu.**
- Containment: parallel WRITE agent chỉ an toàn khi **file-disjoint** (no-worktree rule SE — Windows/Dropbox MAX_PATH); BE+FE đụng file khác nhau = OK song song.

**S73 (2026-06-18) refinement — SCHEMA-FORCE là nguyên nhân, free-text đỡ hơn rõ rệt:**
- 2 review-workflow CÙNG task (Mig 54 PE review): **R1 custom-inline `agent({schema})` ép StructuredOutput** → CHỈ **1/4 lane** trả (3/4 fail "completed without calling StructuredOutput"). **R2 free-text (KHÔNG schema)** → **2/3 lane PASS** — cùng harness, cùng commit, cùng reviewer agentType.
- **Kết luận:** return-rỗng phần lớn do **schema-forcing** (agent làm xong việc nhưng không gọi tool StructuredOutput) — KHÔNG phải agent lười. Free-text return đáng tin hơn NHIỀU cho review/verify.
- **How to apply (cập nhật):** review/verify fan-out → **free-text return** (Agent-tool spawn HOẶC Workflow `agent()` KHÔNG schema) · HOẶC **hmw RUN-TRACE** (sub ghi file, không phụ thuộc StructuredOutput). **TRÁNH** `agent({schema})` cho review nhiều lane. Schema-force chỉ hợp khi cần parse-máy + chấp nhận rớt lane.
- **Governance lesson (S73):** mode-ON + task substantive = mandate **tự chạy Workflow**; em đã spawn-lẻ + em-main BE solo + chỉ khai khi anh hỏi → **phải BÁO TRƯỚC khi đi khác mandate** (surface-before-deviate), không tự ý. Phối đúng: Workflow lo fan-out (recon/FE-mirror/test/review free-text) + em-main giữ phần lõi tight-coupling + luôn báo đường đi.

**S108 (2026-07-10) refinement — schema-NHỎ giờ đáng tin + 2 bẫy Workflow-tool param:**
- **Schema-forced 4/4 CLEAN** (fable-real-runbook draft `wf_2f85b3f6-3dc`, 4 worker Opus, schema 3-field `{sectionMarkdown, findings, memoryDelta}`): NGƯỢC data S73 (1/4). Khác biệt = schema NHỎ + prompt có RETURN-format tường minh (mitigation adap-request S103 `narrow-schema`). Free-text judge với "DÒNG-1 = VERDICT-header" cũng 2/2 clean. → Cả 2 kiểu đều dùng được NẾU: schema ≤3-4 field phẳng HOẶC free-text + header-dòng-1 bắt buộc; S73 lesson thu hẹp còn "TRÁNH schema SÂU/PHỨC TẠP cho review nhiều lane".
- **2 bẫy Workflow-tool (KHÔNG phải hmw.js):** (1) `args` có thể đến script dạng **JSON-STRING** → script PHẢI parse-guard `typeof args === 'string' ? JSON.parse(args) : args` (fail lộ ngay `args.taskList.map undefined`, resume 0-mất); (2) `tier:'opus'` là convention CỦA hmw.js — Workflow generic script phải dùng **`model:'opus'`** trong agent() opts, không thì worker inherit lead (suýt 4×Fable khi ý định là đám Opus).

**S115 (2026-07-13) refinement — ensemble BREADTH ≠ deep-pass DEPTH + sub-file saves the garble-lane:**
- **Deep-pass catches the consensus-blind-spot:** a 5-lane `/fable-clone reviewer` ensemble converged confidently on a fix, but ALL 5 shared one blind-spot — a contiguity-inversion bug in the proposed pseudocode (skip-on-contiguous-prefix = silent inversion). The 1 independent `/fable-real reviewer` deep-pass caught it (M2). **Ensemble = breadth (cover N angles); deep-pass = depth (catch what the consensus SHARES).** Complementary, not redundant: fable-clone to SURVEY, fable-real to STRESS the synthesis. Same shape as the code-review harness breadth-then-depth.
- **Schema-NHỎ + RUN-TRACE = garble-safe (confirms S108):** 5-lane ensemble, 6-field flat schema → 4/5 clean return, 1 garble (lane-4 = heaviest analysis / Part B). Recovered 100% from `sub-reviewer-4.md` (lanes told: Write full detail to sub-file + return lean). **WRITE-lane garble ≠ lost work** — the per-agent sub-file IS the #53 backstop; `parallel()` (not sequential `await`) so 1→null didn't kill the run.

Link: [[feedback_agent_kill_recovery]] (recovery-from-disk + self-gate) · [[feedback_implementer_truncation_mitigation]] (#53 truncation) · [[feedback_agent_return_garble_recover]] (recover-ladder khi return hỏng).
