v0.13.3 — Audience prompts: anti-bleed + BIZ translation table
v0.13.3 — Audience prompts: anti-bleed + BIZ translation table
Why
v0.13.2 made biz the default (verified the same day with a clean side-by-side: zero code blocks, plain-Chinese structure, "對業務的實際意義" section). Two follow-ups from the same dogfood round needed addressing:
-
PM tier was still leaking code blocks. A 4-line Ruby
def/loop snippet appeared in the PM-tier reply to "admin 權限的核心邏輯", even though the PM prompt's own rule said "No code blocks unless quoting an exact API name or table column." Root cause: prior turns in the channel were tech-tier replies with full Ruby blocks, and the LLM was tone-matching the conversation history rather than strictly following the system prompt. Without an explicit anti-bleed rule, tier semantics silently degrade whenever the channel mixes audiences. -
BIZ translation cheat-sheet was thin — 3 inline examples (
AdFormat→ 廣告版型,scope→ 篩選條件,AASM→ 狀態機). For Rails-stack workspaces the bot will seeDevise/Doorkeeper/Rolify/CanCanCan/Sidekiq/migrationconstantly; without explicit translations the LLM either keeps the English term or invents inconsistent translations across turns.
Fixed
Anti-bleed guardrail (PM + BIZ)
Both prompts now lead with this first rule:
Your tier dictates style, not the conversation history. If prior turns in this thread used multi-line Ruby/Python/SQL blocks, do NOT tone-match — those replies were for a different reader. Stay in PM voice. (BIZ: "Re-frame everything you say in plain Chinese for this user.")
This counters the LLM's default of mirroring conversation tone when the audience tier silently changes mid-channel (e.g., a PM joins a thread that an engineer started).
PM tier: "inline backticks only" rule
The existing "No code blocks unless quoting an exact API name or table column" stays, but is reinforced with a concrete recipe:
Cite specific files / model names INLINE only.
app/services/foo.rb,PlacementRevenue,is_admin_permission?go in backticks as inline names — the PM forwards them. Do not paste multi-line code blocks. If you'd otherwise show a 3+ line snippet (Ruby def, SQL query, JSON), describe the structure in prose: "Ability 用 dynamic dispatch — Rolify 表裡的角色名稱被當 method 名稱呼叫" beats pasting the 4-line Ruby loop.
BIZ tier: 9-row translation table
Was 3 inline examples. Now a full table the bot is told to apply to every body sentence:
| Tech form (DON'T leave as-is) | Plain-Chinese form (USE this) |
|---|---|
Devise / Doorkeeper / OAuth / JWT |
登入機制 / 第三方授權登入 |
Rolify / role / roles table |
角色管理(誰能用哪些功能) |
CanCanCan / ability.rb / authorization |
權限規則 / 權限設定 |
scope / named scope / where clause |
資料篩選條件 |
AASM / state machine / state column |
流程狀態管理(例如:草稿 → 送審 → 上線) |
Sidekiq / scheduled job / cron / worker |
背景排程 / 定時任務 |
migration / schema change |
資料表結構變更 |
controller / endpoint / route / API |
後台處理動作 / 系統入口 |
AdFormat / placement / inventory (ad-tech) |
廣告版型 / 版位 / 媒體資源 |
BIZ tier: "對業務的實際意義" closing section
Matches the pattern the LLM organically produced in v0.13.2 verification — codified into the prompt so it lands consistently.
Tests
@pmk/cli 362 → 362 (unchanged). Shared package's "audience prompts have distinct bodies (cross-wire regression)" test still passes — the four prompts remain distinct after the edits. All 412 workspace tests still pass.
Operator note
Prompt-only change inside @pmk/shared. The gateway loads the new prompts on next start — no config migration needed:
git pull && npm run -w @pmk/cli build
kill -TERM $(cat ~/.pmk/gateway/gateway.pid) && pmk gateway startThe anti-bleed guardrail's effectiveness is measurable: if you observe a PM-tier or BIZ-tier reply that still includes a multi-line code block AFTER this upgrade, file an issue with the Slack thread URL — the prompt isn't strong enough yet and we need another iteration.
What's next
The ad-tech-specific row (AdFormat/placement/inventory) in the BIZ table is the only workspace-leaky entry — future iterations might split the BIZ prompt into biz-base + biz-domain-{adtech,fintech,ecommerce} layers if more workspaces adopt pmk. For now it's left as a single example so an ad-tech operator sees the pattern.