CedarCopilot wants to merge 0 commits into docs/cedar-authoring-skill-fixes from feat/debug-test-run
Not deployed
Libra has no production signal for this change yet because it has not deployed. Libra checks hourly for 3 days after each deploy.
Stacked on #2717 (docs/cedar-authoring-skill-fixes) , this is the code half of a gap that doc identifies: the only existing "run it now" path (agent.runNow, the frontend's Run Now button) always sends for real today, with no suppression option, so there was no safe way to test-run a newly authored or edited subagent from a live chat session before this.
test-run to the debug MCP tool, wrapping the SAME execution core agent.runNow already uses (runSingleSubagent for an isolated cron-triggered subagent, runPlaybookSectionExecution for the before_meeting bundle on one conversation).deliverForReal defaults to false: every run is wrapped in withSuppressedDelivery and returns the full captured trace (notify calls + tool calls) without sending anything for real.deliverForReal: true sends for real. On an org-level agent this requires org admin/owner , checked via authorize() (a new subagent_execution:org: 'ORG_ADMIN' row in DEFAULT_POLICY), not a direct role read. A user-level agent only ever touches the caller's own destinations, so no extra check applies there.cedar-configuration/building-an-agent.md and playbook-authoring/SKILL.md to point a live chat session at test-run; cedar-cli/subagent-runner remain the correct path for an internal engineering session with shell access (cedar-cli isn't reachable from a live chat session at all).debugTool.ts past 1,000 lines. Extracted the actual dispatch/scoping logic into services/playbook/test-run-subagent.ts, mirroring the split trpc/routes/admin-subagent.ts already uses ("the risky routing is delegated to the pure, unit-tested subagent-dispatch module; these procedures are the I/O shell around it"). debugTool.ts's case is now a thin shell; the service has its own direct unit tests.user.organizationRole directly and called isOrgAdminRole. pnpm deps:check caught this immediately , role-predicates-stay-inside-the-auth-authority forbids importing that predicate outside its one carved-out caller. Fixed by adding the new DEFAULT_POLICY row and calling authorize() instead, per that module's own contract ("Call authorize() instead, at the point the EFFECTIVE TARGET resolves"). The existing DEFAULT_POLICY-driven exhaustive test suite in authorize.test.ts picked up the new row automatically , no hand-written test needed for it.Also fixed 3 non-null assertions (!) from the first draft , one was masking a real gap (RunSingleSubagentResult isn't a discriminated union, so ok: true doesn't type-guarantee agentId; replaced with a real runtime check), the other two were TS closure-widening false positives fixed by binding to a const before the closure rather than asserting past them.
Known gap, disclosed rather than hidden: test coverage is cron-path only (the 4 scenarios asked for: default-suppressed, user-level real-send, org-level refused-for-non-admin, org-level allowed-for-admin). The before_meeting branch has no dedicated test yet , mocking db.query.crmConversations.findFirst cleanly is a bit more setup than the table-routed fake this suite already has, and didn't fit the time box for this pass.
pnpm --filter @zero/server run types , cleanpnpm deps:check , clean (was failing before the authorize() fix)pnpm --filter @zero/server exec vitest run src/mastra/tools/debug/__tests__/debugTool.test.ts src/services/playbook/__tests__/test-run-subagent.test.ts src/services/auth/__tests__/authorize.test.ts src/services/auth/__tests__/role-reads-confined-to-authority.test.ts , 387/387 passš¤ Generated with Claude Code
https:/
Libra has not measured any production surfaces for this change yet.