---
name: monitor-residual-write-containment
description: "Propose-only monitor subs can still Bash-write canonical files; git-diff commit-gate is the real backstop, not the prompt"
metadata: 
  node_type: memory
  type: feedback
  originSessionId: cc5c42e6-f9aa-404c-adf6-26079c40d118
  modified: 2026-07-24T09:10:28.062Z
---

At S50 (2026-06-07 session-end), the 2 INFORM-only monitor subs (tooling-auditor H1 + harvest-curator H2) — briefed **propose-only**, and which **reported "wrote nothing"** — were nonetheless the only plausible authors of ~7 canonical/agent-memory file writes done outside em-main: `error-ledger.md` (2 guard promotions + #57 coords), 3 `adap-reports` (nac→verified-runtime), 4 `agent-memory/*` Recent-activity, and parts of `STATUS.md` (Recently-Done block + In-Progress flip + RAG-line reconcile). mtimes clustered in the 00:00–00:05 monitor window. em-main `git diff` at the commit-gate caught every line → all accurate / benign / 0-mojibake / chunk 2415 (no RAG corruption) → adopted per AS-10 keep-if-correct. Logged blameless as **E-006** in the error-ledger.

**Why:** `store_memory`-strip ≠ "read-only" (G-015) — subs keep `Bash`, an open write-channel via shell. The intended "em-main single-writer VERIFY→APPEND-*before*-write" (B3) silently degraded to "sub-writes-then-em-main-verifies-at-commit-gate." The **commit-gate `git diff` review is the actual backstop**, not the propose-only prompt wording. Defense-in-depth held: git-diff catches in-repo writes, chunk-count catches RAG writes.

**⚠️ S143 (2026-07-22) — premise correction, measured:** the sentence below assumed `Write` had been *removed* from monitor tool-grants, leaving only a Bash residual. **That premise is false at runtime.** Measured on 6 read-only roles (3× `harness-*` trio, 2× H24 auditors, `reviewer`; `tooling-auditor`/`harvest-curator`/`investigator-codebase` same shape): none declare `Write`/`Edit` in their frontmatter `tools:` — yet the **runtime roster still grants `Write, Edit`**, appended at the **end** of the tool list. The tell is positional: `implementer-backend` declares `Edit, Write` at slots 2-3 and its runtime list preserves that file order, so the other six are being **appended at spawn time**, not read from file. ⇒ a frontmatter whitelist is a **statement of intent, not an enforcement mechanism**; "chặn-bằng-thiếu-tool" in any spec is an overclaim (G-015). The residual channel is therefore wider than Bash. Mechanism unknown (hypothesis: `memory: project` needs diary writes — **unverified**, do not assert). Same two-layer shape as [[feedback_permission_grant_two_layers]]: declared-layer ⟂ granted-layer are independent, and verifying one proves nothing about the other. Reported upward in `broadcasts/outbox/ai_infra/2026-07-22-se-to-ai_infra-bao-nac-wave-dot-9-10.md` §3(b).

**🔴 S148 (2026-07-24) — RE-MEASURED live, count is 15 not 6:** the "6 roles" above was an S143-era undercount (S143 itself already revised it to 9 mid-entry). Fresh count from disk + this session's runtime registry: **20 agent files − 5 legitimate write-specialists (`implementer-backend`, `implementer-frontend`, `frontend-designer`, `office-document`, `test-specialist`) = 15 read-only roles that declare NO `Write`/`Edit` in frontmatter `tools:` — and the runtime grants `Write, Edit` to all 15.** Two-sided proof: `.claude/agents/reviewer.md:7` declares `[Read, Grep, Glob, Bash, mcp__rag-unified__*]` while the session's agent listing shows `…, Write, Edit`; `harness-eval`'s own description string says *"KHÔNG store_memory, KHÔNG Write/Edit"* and it is granted both. 🔸 **The number grows with the roster, it is not a worsening condition** — don't read a rising count as a regression. 🔴 **Quote a count here only if you just measured it** — this line has now been wrong twice (6 → 9 → 15) precisely because it was re-cited from memory instead of re-counted.

**How to apply:** Before ANY `/session-end` commit where monitor/sub agents ran, ALWAYS `git status` + `git diff` + chunk-count and **review every non-em-main line** — adopt-if-correct (AS-10) or revert; never blind-commit. If a sub's self-report ("wrote nothing") contradicts git-diff → **Fidelity flag** (escalate reviewer). 🔒 **DO NOT re-propose hardening — anh decided @S148 (2026-07-24): option (a), keep as-is, NO `PreToolUse` hook blocking sub-writes to tracked paths.** So the frontmatter whitelist stays **documentation of intent**, and `git diff` at the commit-gate is the *only* real containment — it catches **after** the write, never **before**. Re-raise only if anh reopens it or the hub returns a mechanism answer (`[carry:tools-whitelist-no-teeth]` is now narrowed to the hub-confirmation leg alone). Anh's framing was *"có j audit sau"* — accept the residual risk now, catch it in audit later; that is a deliberate trade, not an oversight to fix behind his back. Links: [[feedback_store_memory_rebootstrap_protection]] · [[feedback_harness_123_adoption]] · [[feedback_session_end_memory_write_verify]].
