Financebotresearch desk研究台

Playbook › Playbook

A pattern-based privacy gate cannot find a disclosure phrased with a noun it lacks

static 2026-09-28

Claim

A portfolio-specific passage was removed from the public build.

Eleven distinct disclosure shapes were live on the public site at that moment:

A portfolio-specific passage was removed from the public build.

Every one of them names a holding. None of them uses a noun the gate was watching. Held: is not position. A lot is not a position. Avg: with a colon is not $X avg. The gate was not weakened or misconfigured — it was doing exactly what it was written to do.

Why this is structural, not a bug

A pattern gate encodes the shapes someone already thought of. The set of ways to say "I own 234 shares at $12" is open, and prose written by a different author, or by the same author on a different day, reaches for different nouns. The gate's coverage is bounded by imagination; the disclosure surface is not.

The failure is silent in the worst way: a gate that finds nothing prints the same message as a gate that had nothing to find.

The complement

Audit the output against the real values. Portfolio*.md holds the actual average costs and share counts; grep the built HTML for them. Phrasing cannot hide a number.

site.py gate knows the SHAPES, cannot know the VALUES -> during the build canary.py knows the VALUES, cannot know the SHAPES -> after the build

Neither is sufficient. The value audit is heuristic and noisy — an insider can buy at the price we did, and an EPS guide can equal an average cost — so it reports advisory hits a human reads. The shape gate is deterministic but blind to what it lacks a noun for. Run both.

Over-redaction is the symmetric failure

Two patterns written the same day had to be removed for eating legitimate content:

  • <verb> N shares matched "CEO Cristiano Amon sold 20,000 shares" — insider-transaction analysis, which is exactly what these reports exist to carry.
  • a bare average cost halted the build on pitfall-average-cost-derived-not-copied, the Playbook note whose entire subject is average cost as a method.
  • a <N>% weight rule matched "bear 25% weight, base 50% weight" — ordinary scenario weighting — and was redundant besides, since the line it was written for was already caught twice over.

So: every new pattern needs a positive case and a negative case. A rule that deletes the analysis is not safer than a rule that leaks; it is a different way to lose the work. And a redundant rule that produces false positives is worse than no rule, because it trains you to skim the output.

A halting gate leaves deployable wreckage

site.py halts mid-write. A failed build leaves a partial .site-html/ — 579 of 694 files on the day — that is structurally indistinguishable from a good one to wrangler, which happily uploads it. The partial site was deployed because only the tail of the build log was read. Check the exit code; tail is not a check. The durable fix is to build into a temp directory and swap on success, so a halt cannot leave something deployable. Not yet done.

Related

  • [[pitfall-stale-entry-zone-suppresses-a-name]] and [[pitfall-frontmatter-flattens-a-tranche-ladder-into-a-false-zone]] — the same shape of error one layer up: a mechanism that silently reports the wrong thing while looking correct.

History

  • 2026-09-28 — written after a canary audit found eleven live disclosures behind a gate that reported clean. Nine new patterns added to site.py with verbatim leaked strings as test cases, three over-broad rules removed on negative cases, and .mcp/canary.py added as the standing second layer, wired into /deploy as steps 2b and 3b.