CedarCopilot wants to merge 2 commits into staging from fix/aop-clone-noop-source
Libra ran this behavior against the change and confirmed the check detects when it breaks.
Changed code: create-aop.test.ts.
Libra ran this behavior against the change and confirmed the check detects when it breaks.
Changed code: create-aop.ts.
Live on prod, watching, 2 days left
Libra has verdicts on 0 of 3 tracked behaviors on prod; 3 are still being checked. Libra checks hourly for 3 days after each deploy.
cloneAop() required the clone source to have a real playbook document tree, but every genuine no-op AOP (Spam, Recruiting, Vendor notification, ...) is seeded with isNoOp: true and deliberately zero documents , there was no valid source to clone a new pure-classification bucket (e.g. a "Personal" category) from at all.cloneAop() also hardcoded isNoOp: false on both DB inserts regardless of the source, so even a successful clone of a no-op AOP would silently stop being a no-op.create-aop attempts (Recruiting → "no playbook document tree to clone", then Suppliers and Deals → playbook validation errors from cloning a live automation playbook) all failed.cloneAopDocuments now returns an empty result instead of throwing when the source has zero documents and is itself a no-op AOP. A non-no-op source with zero documents is still treated as corrupted state and rejected (existing behavior preserved, now covered by its own test).cloneAop now inherits isNoOp from the source AOP instead of hardcoding false (mirrors how scope already defaults from the source).aop-write tool's cloneFromAopId description so the agent clones from an existing no-op AOP for a pure classification category, instead of trying to clone and strip down a live playbook (which is what led it down the failing Suppliers/Deals path in the real transcript).create-aop.test.ts: replaced the test asserting the old (buggy) throw-on-no-op-source behavior with one asserting the new success path, and added a companion test proving the corrupted-state guard still holds for a non-no-op source with no documents.pnpm --filter @zero/server run types , cleanpnpm --filter @zero/server exec vitest run src/services/aop/__tests__/create-aop.test.ts , 19/19 passingcloneAop()/reassignConversationAop() functions directly against prod (via a one-off script, since this fix isn't deployed yet) to create the real "Personal" AOP for the customer who hit this and reassign their conversation to it , confirmed isNoOp: true on the new AOP row and aopName: "Personal" on the reassigned conversation.The PR appears safe to merge; the intended no-op cloning path is narrowly gated and the existing corrupted-state rejection remains intact.
This PR enables cloning a genuine no-op AOP whose deliberately empty document tree previously caused cloning to fail.
isNoOp on both newly created AOP rows.Revie
Libra has not measured any production surfaces for this change yet.