Libra CodeHub

CedarCopilot/cedar-mail

Branch: staging

drafter: port per-account gates, restore the review path, and make the ref the only route

merged#2648CedarCopilot

CedarCopilot wants to merge 3 commits into staging from feat/drafter-system-agent

Live on prod, no production signal yetTimeline and evidence
  1. Opened
    Sep 1, 2026, 9:26 PM
  2. Sep 1, 2026, 10:18 PM
  3. Merged
    Sep 2, 2026, 4:47 PM
  4. Live on prod
    Sep 2, 2026, 4:47 PM
  5. Observed 3 days
    Sep 2, 2026, 4:47 PM
  6. Pipelines steady after this deploy
    Sep 2, 2026, 4:47 PM
  7. Unobserved

    Live on prod, no production signal yet

    Sep 5, 2026, 4:45 PM

Behaviors Libra is checking

Automation runs can invoke the automation-only review-conversation tool again, restoring the conversation-review path instead of substituting spawn-subagent.Brokenlow confidence

Verification reached its 130s outer budget before the verifier returned. Libra is keeping this intent verifying until the next check.

prod, checked Sep 5, 2026, 4:43 PM
The drafting health check alerts when a day has at least ten real drafts but none are attributed to a drafter.md agent execution.Degradedlow confidence

Verification reached its 120s wall-clock budget before a tied verdict. Libra is keeping this intent verifying until the next check.

prod, checked Sep 5, 2026, 4:45 PM
A reviewed gate-prose file can be applied to one drafter ref so the playbook uses the account's ported drafting rules instead of the seeded default.Inconclusivehigh confidence

No positive production telemetry was found for the intended ref --apply --gate-prose-file operation or verify-drafter-migration since deployment: 0 matching OTEL spans, 0 spans from commit fea8aabaf6543572e3b07cfb7de386209a52fde9, and 0 CloudWatch matches for.

prod, checked Sep 4, 2026, 11:44 PM
Drafter document, ref, and Stage 4 operations can be narrowed to a specific playbook/AOP without widening an account-scoped operation to every playbook.Inconclusivehigh confidence

No verifiable production telemetry was found for the changed CLI surfaces since 2026-09-02T23:47:55Z. OTEL returned 0 spans matching drafter, stage4, backfill, or related routes in CedarCopilot/cedar-mail production, so success/error counts, latency, and distinct-user volume.

prod, checked Sep 5, 2026, 12:45 AM
Gate application rejects a missing, empty, or bare-valued gate-prose file argument instead of treating operator mistakes as valid prose.Inconclusivehigh confidence

No production telemetry tied to backfill-drafter or --gate-prose-file was found since 2026-09-02T23:47:55Z: 0 matching CloudWatch log events and 0 matching production OTEL spans. Therefore there are no observed executions, success signals, validation errors, latency, volume, or.

prod, checked Sep 5, 2026, 1:45 AM
Drafter ref activation reads each playbook's cross-cutting drafting policy and applies the seeded gate only to no-policy accounts, refusing rules and suppressed accounts without account-specific prose.Inconclusivehigh confidence

No production telemetry tied to the intended surface was found since 2026-09-02T23:47:55Z (~58h): CloudWatch returned 0 executions containing '[backfill-drafter ref]', and OTEL returned 0 matching spans/routes/attributes/events for drafter or backfill-drafter. The alternate 74.

prod, checked Sep 5, 2026, 2:44 AM

Libra has verdicts on 0 of 17 tracked behaviors on prod; 17 are still being checked. Libra has 2 low-confidence degraded or broken verdicts it is still confirming. Libra checks hourly for 3 days after each deploy.

Three commits, shipped together because the last one only becomes safe once the first two are true.

The fleet migration in commit 1 already ran against production on 2026-09-01. Commits 2 and 3 are the code that makes it whole.

1. 5406a058d , port each account's own drafting rules into its gate

The ref step no longer appends a seeded default. It reads each account's <cross-cutting> and refuses unless that account's ported prose is supplied.

The first fleet pass showed why: it wanted to write "do not draft" onto 5 of 8 accounts that draft constantly, hardest on the highest-volume ones , zach@ would have been silenced at 193 drafts/30d, jihoon@ at 174. Three defects behind that, each regression-tested against the real prose that exposed it:

  • Positives were scanned far more narrowly than prohibitions, so an account forbidding drafting in SOME case read as forbidding it in ALL cases.
  • A NEVER DRAFT section was treated as evidence drafting is off. Nearly every account forbids drafting somewhere.
  • NEVER[ _-]?DRAFT had no leading \b, so it matched inside "whenever drafting" , turning seven LABEL RULES lines into seven prohibitions.

DRAFTER_GATE_PROSE also no longer permits inbound reply drafting. Of 73 inbound-email-notifier documents, 66 only notify, 4 opt in, 2 forbid it , so permitting it by default contradicted every account the default reaches.

New: --aop-id (three users have two AOPs needing different gates), and --replace-gate for an account wired by the very run that appended a default over its own rules. stage4-plan.ts has no write path at all , no --apply, no writePlaybookXml import.

2. 537d2f2d4 , restore review-conversation to the automation agent

review-conversation has not been callable since 2026-08-24, and the review path went dark with it:

dayreview-conversationspawn-subagent
08-244019
08-258661
08-2600
09-010534

4d8fb3437 moved the daily agenda into an automation-only skill for a good reason , its prose ends in a notify-user call and was being spliced into every tasks load. But reviewConversationTool moved with it, and getAllSkillTools() iterates skills only. The agent kept reading "call review-conversation, never spawn-subagent" and substituted the tool it could actually reach.

reviewConversationTool is the only caller of triggerType: 'conversation_review', so routeDrafter, runDrafterRef and the review-path tool strip have executed zero times since 08-26. The substitute is worse than a missing tool: a spawn-subagent child runs on createOrchestratorAgent, which hardwires save-draft and carries no drafter document , 428 such runs made 458 draft calls across 48 users in 7 days.

Tools and instructions are separate concerns, so they get separate gates. getAutomationSkillTools() = chat catalog + automation-only skills' tools. The skill stays unadvertised to chat.

3. 7fcb859b2 , Stage 5: the ref is the only route

run-post-event-executor leaves orchestratorTools; drafting goes through run-subagent(@subagents/drafter). The seed gets the ref back, last in <trigger type="any">.

Gate, measured rather than assumed: of 60 playbooks that can actually draft , excluding no-op AOPs and users whose agent_settings.agentExecutionEnabled is false , 59 carry a drafter ref. The one that does not has had no <trigger> element since 2026-06-18 and dispatches nothing.

I got that denominator wrong twice before landing on it: getActiveUsers() gave 59 playbooks and missed 28 live ones; every live playbook gave 27 missing refs and would have blocked this outright. Neither is right , a playbook whose owner has execution off cannot lose drafting to this change.

Production state as of this PR

  • 57/59 migrated playbooks compile, carry the ref, and hold their intended gate
  • 185 drafts on 09-01, 124 through the drafter , against zero on every pr
Show production surfaces and changed-file mapping

Production surfaces

Libra has not measured any production surfaces for this change yet.

Changed files → surfaces

  • .claude/skills/account-setup-from-transcript/SKILL.mdno production surface mapped
  • apps/server/scripts/backfill-drafter.tsno production surface mapped
  • apps/server/scripts/drafting-health.tsno production surface mapped
  • apps/server/scripts/lib/backfill-cli-utils.tsno production surface mapped
  • apps/server/scripts/stage4-plan.tsno production surface mapped
  • apps/server/scripts/verify-drafter-migration.tsno production surface mapped
  • apps/server/src/mastra/agents/on-event-orchestrator-agent.tsno production surface mapped
  • apps/server/src/mastra/skills/__tests__/automation-skill-tools.test.tsno production surface mapped
  • apps/server/src/mastra/skills/index.tsno production surface mapped
  • apps/server/src/services/aop/__tests__/automations-service.test.tsno production surface mapped
  • apps/server/src/services/aop/automations.tsno production surface mapped
  • apps/server/src/services/playbook/__tests__/drafter-seed.test.tsno production surface mapped
  • apps/server/src/services/playbook/agent-defaults/drafter.tsno production surface mapped
  • apps/server/src/services/playbook/agent-defaults/index.tsno production surface mapped
  • apps/server/src/services/playbook/backfill/__tests__/drafter-migration.test.tsno production surface mapped
  • apps/server/src/services/playbook/backfill/__tests__/drafting-policy.test.tsno production surface mapped
  • apps/server/src/services/playbook/backfill/__tests__/gate-prose-proposal.test.tsno production surface mapped
  • apps/server/src/services/playbook/backfill/__tests__/label-rules-cleanup.test.tsno production surface mapped
  • apps/server/src/services/playbook/backfill/__tests__/stage4-plan.test.tsno production surface mapped
  • apps/server/src/services/playbook/backfill/cross-cutting-sections.tsno production surface mapped
  • apps/server/src/services/playbook/backfill/cross-cutting.tsno production surface mapped
  • apps/server/src/services/playbook/backfill/drafter-migration.tsno production surface mapped
  • apps/server/src/services/playbook/backfill/drafting-policy.tsno production surface mapped
  • apps/server/src/services/playbook/backfill/gate-prose-proposal.tsno production surface mapped
  • apps/server/src/services/playbook/backfill/label-rules-cleanup.tsno production surface mapped
  • apps/server/src/services/playbook/backfill/stage4-plan.tsno production surface mapped
  • apps/server/src/services/playbook/seed-playbook.tsno production surface mapped
  • docs/design/drafter-system-agent.mdno production surface mapped